From c7d7f10bdff703e4a3c0414e8a33d4e45c91eb35 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 4 Jul 2020 11:12:55 +0200 Subject: go.mod: vendor golangci-lint --- vendor/github.com/BurntSushi/toml/.gitignore | 5 + vendor/github.com/BurntSushi/toml/.travis.yml | 15 + vendor/github.com/BurntSushi/toml/COMPATIBLE | 3 + vendor/github.com/BurntSushi/toml/COPYING | 21 + vendor/github.com/BurntSushi/toml/Makefile | 19 + vendor/github.com/BurntSushi/toml/README.md | 218 + vendor/github.com/BurntSushi/toml/decode.go | 509 + vendor/github.com/BurntSushi/toml/decode_meta.go | 121 + vendor/github.com/BurntSushi/toml/doc.go | 27 + vendor/github.com/BurntSushi/toml/encode.go | 568 + .../github.com/BurntSushi/toml/encoding_types.go | 19 + .../BurntSushi/toml/encoding_types_1.1.go | 18 + vendor/github.com/BurntSushi/toml/lex.go | 953 + vendor/github.com/BurntSushi/toml/parse.go | 592 + vendor/github.com/BurntSushi/toml/session.vim | 1 + vendor/github.com/BurntSushi/toml/type_check.go | 91 + vendor/github.com/BurntSushi/toml/type_fields.go | 242 + vendor/github.com/Djarvur/go-err113/.gitignore | 15 + vendor/github.com/Djarvur/go-err113/.golangci.yml | 150 + vendor/github.com/Djarvur/go-err113/.travis.yml | 24 + vendor/github.com/Djarvur/go-err113/LICENSE | 21 + vendor/github.com/Djarvur/go-err113/README.adoc | 73 + vendor/github.com/Djarvur/go-err113/comparison.go | 103 + vendor/github.com/Djarvur/go-err113/definition.go | 74 + vendor/github.com/Djarvur/go-err113/err113.go | 90 + vendor/github.com/Djarvur/go-err113/go.mod | 5 + vendor/github.com/Djarvur/go-err113/go.sum | 20 + vendor/github.com/OpenPeeDeeP/depguard/.gitignore | 14 + vendor/github.com/OpenPeeDeeP/depguard/LICENSE | 674 + vendor/github.com/OpenPeeDeeP/depguard/README.md | 77 + vendor/github.com/OpenPeeDeeP/depguard/depguard.go | 241 + vendor/github.com/OpenPeeDeeP/depguard/go.mod | 9 + vendor/github.com/OpenPeeDeeP/depguard/go.sum | 6 + vendor/github.com/bombsimon/wsl/v3/.gitignore | 70 + vendor/github.com/bombsimon/wsl/v3/.travis.yml | 25 + vendor/github.com/bombsimon/wsl/v3/LICENSE | 21 + vendor/github.com/bombsimon/wsl/v3/README.md | 125 + vendor/github.com/bombsimon/wsl/v3/go.mod | 12 + vendor/github.com/bombsimon/wsl/v3/go.sum | 25 + vendor/github.com/bombsimon/wsl/v3/wsl.go | 1122 + vendor/github.com/davecgh/go-spew/LICENSE | 15 + vendor/github.com/davecgh/go-spew/spew/bypass.go | 145 + .../github.com/davecgh/go-spew/spew/bypasssafe.go | 38 + vendor/github.com/davecgh/go-spew/spew/common.go | 341 + vendor/github.com/davecgh/go-spew/spew/config.go | 306 + vendor/github.com/davecgh/go-spew/spew/doc.go | 211 + vendor/github.com/davecgh/go-spew/spew/dump.go | 509 + vendor/github.com/davecgh/go-spew/spew/format.go | 419 + vendor/github.com/davecgh/go-spew/spew/spew.go | 148 + vendor/github.com/fatih/color/.travis.yml | 5 + vendor/github.com/fatih/color/Gopkg.lock | 27 + vendor/github.com/fatih/color/Gopkg.toml | 30 + vendor/github.com/fatih/color/LICENSE.md | 20 + vendor/github.com/fatih/color/README.md | 179 + vendor/github.com/fatih/color/color.go | 603 + vendor/github.com/fatih/color/doc.go | 133 + vendor/github.com/fsnotify/fsnotify/.editorconfig | 5 + vendor/github.com/fsnotify/fsnotify/.gitignore | 6 + vendor/github.com/fsnotify/fsnotify/.travis.yml | 30 + vendor/github.com/fsnotify/fsnotify/AUTHORS | 52 + vendor/github.com/fsnotify/fsnotify/CHANGELOG.md | 317 + .../github.com/fsnotify/fsnotify/CONTRIBUTING.md | 77 + vendor/github.com/fsnotify/fsnotify/LICENSE | 28 + vendor/github.com/fsnotify/fsnotify/README.md | 79 + vendor/github.com/fsnotify/fsnotify/fen.go | 37 + vendor/github.com/fsnotify/fsnotify/fsnotify.go | 66 + vendor/github.com/fsnotify/fsnotify/inotify.go | 337 + .../github.com/fsnotify/fsnotify/inotify_poller.go | 187 + vendor/github.com/fsnotify/fsnotify/kqueue.go | 521 + .../github.com/fsnotify/fsnotify/open_mode_bsd.go | 11 + .../fsnotify/fsnotify/open_mode_darwin.go | 12 + vendor/github.com/fsnotify/fsnotify/windows.go | 561 + vendor/github.com/go-critic/go-critic/LICENSE | 22 + .../go-critic/checkers/appendAssign_checker.go | 102 + .../go-critic/checkers/appendCombine_checker.go | 102 + .../go-critic/checkers/argOrder_checker.go | 98 + .../go-critic/checkers/assignOp_checker.go | 102 + .../go-critic/checkers/badCall_checker.go | 63 + .../go-critic/checkers/badCond_checker.go | 147 + .../go-critic/checkers/boolExprSimplify_checker.go | 344 + .../go-critic/checkers/builtinShadow_checker.go | 36 + .../go-critic/checkers/captLocal_checker.go | 49 + .../go-critic/checkers/caseOrder_checker.go | 88 + .../go-critic/go-critic/checkers/checkers.go | 10 + .../go-critic/checkers/codegenComment_checker.go | 61 + .../checkers/commentFormatting_checker.go | 77 + .../go-critic/checkers/commentedOutCode_checker.go | 157 + .../checkers/commentedOutImport_checker.go | 76 + .../go-critic/checkers/defaultCaseOrder_checker.go | 65 + .../checkers/deprecatedComment_checker.go | 149 + .../go-critic/checkers/docStub_checker.go | 95 + .../go-critic/go-critic/checkers/dupArg_checker.go | 133 + .../go-critic/checkers/dupBranchBody_checker.go | 58 + .../go-critic/checkers/dupCase_checker.go | 57 + .../go-critic/checkers/dupImports_checker.go | 63 + .../go-critic/checkers/dupSubExpr_checker.go | 102 + .../go-critic/go-critic/checkers/elseif_checker.go | 71 + .../go-critic/checkers/emptyFallthrough_checker.go | 70 + .../go-critic/checkers/emptyStringTest_checker.go | 58 + .../go-critic/checkers/equalFold_checker.go | 87 + .../go-critic/checkers/evalOrder_checker.go | 87 + .../go-critic/checkers/exitAfterDefer_checker.go | 78 + .../go-critic/checkers/flagDeref_checker.go | 65 + .../go-critic/checkers/flagName_checker.go | 68 + .../go-critic/checkers/hexLiteral_checker.go | 60 + .../go-critic/checkers/hugeParam_checker.go | 63 + .../go-critic/checkers/ifElseChain_checker.go | 99 + .../go-critic/checkers/importShadow_checker.go | 47 + .../go-critic/checkers/indexAlloc_checker.go | 50 + .../go-critic/checkers/initClause_checker.go | 56 + .../checkers/internal/lintutil/astfind.go | 27 + .../checkers/internal/lintutil/astflow.go | 86 + .../go-critic/checkers/internal/lintutil/astset.go | 44 + .../checkers/internal/lintutil/zero_value.go | 94 + .../go-critic/go-critic/checkers/mapKey_checker.go | 124 + .../go-critic/checkers/methodExprCall_checker.go | 57 + .../go-critic/checkers/nestingReduce_checker.go | 73 + .../go-critic/checkers/newDeref_checker.go | 45 + .../go-critic/checkers/nilValReturn_checker.go | 64 + .../go-critic/checkers/octalLiteral_checker.go | 82 + .../go-critic/go-critic/checkers/offBy1_checker.go | 66 + .../go-critic/checkers/paramTypeCombine_checker.go | 86 + .../go-critic/checkers/ptrToRefParam_checker.go | 70 + .../go-critic/checkers/rangeExprCopy_checker.go | 80 + .../go-critic/checkers/rangeValCopy_checker.go | 75 + .../go-critic/checkers/regexpMust_checker.go | 47 + .../go-critic/checkers/regexpPattern_checker.go | 68 + .../go-critic/checkers/singleCaseSwitch_checker.go | 61 + .../go-critic/checkers/sloppyLen_checker.go | 72 + .../go-critic/checkers/sloppyReassign_checker.go | 80 + .../go-critic/checkers/stringXbytes_checker.go | 47 + .../go-critic/checkers/switchTrue_checker.go | 49 + .../go-critic/checkers/truncateCmp_checker.go | 117 + .../go-critic/checkers/typeAssertChain_checker.go | 132 + .../go-critic/checkers/typeSwitchVar_checker.go | 88 + .../go-critic/checkers/typeUnparen_checker.go | 86 + .../go-critic/checkers/underef_checker.go | 127 + .../go-critic/checkers/unlabelStmt_checker.go | 170 + .../go-critic/checkers/unlambda_checker.go | 79 + .../go-critic/checkers/unnamedResult_checker.go | 103 + .../go-critic/checkers/unnecessaryBlock_checker.go | 69 + .../go-critic/checkers/unslice_checker.go | 59 + .../go-critic/go-critic/checkers/utils.go | 309 + .../go-critic/checkers/valSwap_checker.go | 64 + .../go-critic/checkers/weakCond_checker.go | 77 + .../go-critic/checkers/whyNoLint_checker.go | 52 + .../go-critic/checkers/wrapperFunc_checker.go | 224 + .../go-critic/checkers/yodaStyleExpr_checker.go | 66 + vendor/github.com/go-lintpack/lintpack/.travis.yml | 7 + vendor/github.com/go-lintpack/lintpack/LICENSE | 24 + vendor/github.com/go-lintpack/lintpack/Makefile | 14 + vendor/github.com/go-lintpack/lintpack/README.md | 32 + .../go-lintpack/lintpack/astwalk/comment_walker.go | 41 + .../lintpack/astwalk/doc_comment_walker.go | 48 + .../go-lintpack/lintpack/astwalk/expr_walker.go | 29 + .../lintpack/astwalk/func_decl_walker.go | 21 + .../lintpack/astwalk/local_comment_walker.go | 32 + .../lintpack/astwalk/local_def_visitor.go | 51 + .../lintpack/astwalk/local_def_walker.go | 118 + .../lintpack/astwalk/local_expr_walker.go | 27 + .../lintpack/astwalk/stmt_list_walker.go | 31 + .../go-lintpack/lintpack/astwalk/stmt_walker.go | 27 + .../lintpack/astwalk/type_expr_walker.go | 114 + .../go-lintpack/lintpack/astwalk/visitor.go | 80 + .../go-lintpack/lintpack/astwalk/walk_handler.go | 34 + .../go-lintpack/lintpack/astwalk/walker.go | 57 + .../github.com/go-lintpack/lintpack/checkers_db.go | 135 + vendor/github.com/go-lintpack/lintpack/context.go | 35 + vendor/github.com/go-lintpack/lintpack/doc.go | 5 + vendor/github.com/go-lintpack/lintpack/go.mod | 11 + vendor/github.com/go-lintpack/lintpack/go.sum | 14 + vendor/github.com/go-lintpack/lintpack/lintpack.go | 248 + vendor/github.com/go-toolsmith/astcast/.travis.yml | 9 + vendor/github.com/go-toolsmith/astcast/LICENSE | 21 + vendor/github.com/go-toolsmith/astcast/README.md | 86 + vendor/github.com/go-toolsmith/astcast/astcast.go | 590 + vendor/github.com/go-toolsmith/astcast/go.mod | 6 + vendor/github.com/go-toolsmith/astcast/go.sum | 4 + vendor/github.com/go-toolsmith/astcopy/.travis.yml | 9 + vendor/github.com/go-toolsmith/astcopy/LICENSE | 21 + vendor/github.com/go-toolsmith/astcopy/README.md | 41 + vendor/github.com/go-toolsmith/astcopy/astcopy.go | 955 + vendor/github.com/go-toolsmith/astcopy/go.mod | 6 + vendor/github.com/go-toolsmith/astcopy/go.sum | 4 + vendor/github.com/go-toolsmith/astequal/.gitignore | 5 + .../github.com/go-toolsmith/astequal/.travis.yml | 9 + vendor/github.com/go-toolsmith/astequal/LICENSE | 21 + vendor/github.com/go-toolsmith/astequal/README.md | 67 + .../github.com/go-toolsmith/astequal/astequal.go | 734 + vendor/github.com/go-toolsmith/astequal/go.mod | 1 + vendor/github.com/go-toolsmith/astfmt/.travis.yml | 9 + vendor/github.com/go-toolsmith/astfmt/LICENSE | 21 + vendor/github.com/go-toolsmith/astfmt/README.md | 39 + vendor/github.com/go-toolsmith/astfmt/astfmt.go | 111 + vendor/github.com/go-toolsmith/astfmt/go.mod | 6 + vendor/github.com/go-toolsmith/astfmt/go.sum | 4 + vendor/github.com/go-toolsmith/astp/.gitignore | 4 + vendor/github.com/go-toolsmith/astp/.travis.yml | 9 + vendor/github.com/go-toolsmith/astp/LICENSE | 21 + vendor/github.com/go-toolsmith/astp/README.md | 39 + vendor/github.com/go-toolsmith/astp/decl.go | 39 + vendor/github.com/go-toolsmith/astp/expr.go | 141 + vendor/github.com/go-toolsmith/astp/go.mod | 6 + vendor/github.com/go-toolsmith/astp/go.sum | 4 + vendor/github.com/go-toolsmith/astp/stmt.go | 135 + .../github.com/go-toolsmith/strparse/.travis.yml | 9 + vendor/github.com/go-toolsmith/strparse/LICENSE | 21 + vendor/github.com/go-toolsmith/strparse/README.md | 34 + vendor/github.com/go-toolsmith/strparse/go.mod | 1 + .../github.com/go-toolsmith/strparse/strparse.go | 59 + vendor/github.com/go-toolsmith/typep/.travis.yml | 9 + vendor/github.com/go-toolsmith/typep/LICENSE | 21 + vendor/github.com/go-toolsmith/typep/README.md | 37 + vendor/github.com/go-toolsmith/typep/doc.go | 2 + vendor/github.com/go-toolsmith/typep/go.mod | 1 + vendor/github.com/go-toolsmith/typep/predicates.go | 36 + vendor/github.com/go-toolsmith/typep/safeExpr.go | 62 + .../go-toolsmith/typep/simplePredicates.go | 359 + vendor/github.com/gobwas/glob/.gitignore | 8 + vendor/github.com/gobwas/glob/.travis.yml | 9 + vendor/github.com/gobwas/glob/LICENSE | 21 + vendor/github.com/gobwas/glob/bench.sh | 26 + vendor/github.com/gobwas/glob/compiler/compiler.go | 525 + vendor/github.com/gobwas/glob/glob.go | 80 + vendor/github.com/gobwas/glob/match/any.go | 45 + vendor/github.com/gobwas/glob/match/any_of.go | 82 + vendor/github.com/gobwas/glob/match/btree.go | 146 + vendor/github.com/gobwas/glob/match/contains.go | 58 + vendor/github.com/gobwas/glob/match/every_of.go | 99 + vendor/github.com/gobwas/glob/match/list.go | 49 + vendor/github.com/gobwas/glob/match/match.go | 81 + vendor/github.com/gobwas/glob/match/max.go | 49 + vendor/github.com/gobwas/glob/match/min.go | 57 + vendor/github.com/gobwas/glob/match/nothing.go | 27 + vendor/github.com/gobwas/glob/match/prefix.go | 50 + vendor/github.com/gobwas/glob/match/prefix_any.go | 55 + .../github.com/gobwas/glob/match/prefix_suffix.go | 62 + vendor/github.com/gobwas/glob/match/range.go | 48 + vendor/github.com/gobwas/glob/match/row.go | 77 + vendor/github.com/gobwas/glob/match/segments.go | 91 + vendor/github.com/gobwas/glob/match/single.go | 43 + vendor/github.com/gobwas/glob/match/suffix.go | 35 + vendor/github.com/gobwas/glob/match/suffix_any.go | 43 + vendor/github.com/gobwas/glob/match/super.go | 33 + vendor/github.com/gobwas/glob/match/text.go | 45 + vendor/github.com/gobwas/glob/readme.md | 148 + vendor/github.com/gobwas/glob/syntax/ast/ast.go | 122 + vendor/github.com/gobwas/glob/syntax/ast/parser.go | 157 + .../github.com/gobwas/glob/syntax/lexer/lexer.go | 273 + .../github.com/gobwas/glob/syntax/lexer/token.go | 88 + vendor/github.com/gobwas/glob/syntax/syntax.go | 14 + vendor/github.com/gobwas/glob/util/runes/runes.go | 154 + .../github.com/gobwas/glob/util/strings/strings.go | 39 + vendor/github.com/gofrs/flock/.gitignore | 24 + vendor/github.com/gofrs/flock/.travis.yml | 10 + vendor/github.com/gofrs/flock/LICENSE | 27 + vendor/github.com/gofrs/flock/README.md | 41 + vendor/github.com/gofrs/flock/appveyor.yml | 25 + vendor/github.com/gofrs/flock/flock.go | 127 + vendor/github.com/gofrs/flock/flock_unix.go | 195 + vendor/github.com/gofrs/flock/flock_winapi.go | 76 + vendor/github.com/gofrs/flock/flock_windows.go | 140 + vendor/github.com/gogo/protobuf/AUTHORS | 15 + vendor/github.com/gogo/protobuf/CONTRIBUTORS | 23 + vendor/github.com/gogo/protobuf/LICENSE | 35 + vendor/github.com/gogo/protobuf/proto/Makefile | 43 + vendor/github.com/gogo/protobuf/proto/clone.go | 258 + .../github.com/gogo/protobuf/proto/custom_gogo.go | 39 + vendor/github.com/gogo/protobuf/proto/decode.go | 427 + .../github.com/gogo/protobuf/proto/deprecated.go | 63 + vendor/github.com/gogo/protobuf/proto/discard.go | 350 + vendor/github.com/gogo/protobuf/proto/duration.go | 100 + .../gogo/protobuf/proto/duration_gogo.go | 49 + vendor/github.com/gogo/protobuf/proto/encode.go | 203 + .../github.com/gogo/protobuf/proto/encode_gogo.go | 33 + vendor/github.com/gogo/protobuf/proto/equal.go | 300 + .../github.com/gogo/protobuf/proto/extensions.go | 604 + .../gogo/protobuf/proto/extensions_gogo.go | 368 + vendor/github.com/gogo/protobuf/proto/lib.go | 967 + vendor/github.com/gogo/protobuf/proto/lib_gogo.go | 50 + .../github.com/gogo/protobuf/proto/message_set.go | 181 + .../gogo/protobuf/proto/pointer_reflect.go | 357 + .../gogo/protobuf/proto/pointer_reflect_gogo.go | 59 + .../gogo/protobuf/proto/pointer_unsafe.go | 308 + .../gogo/protobuf/proto/pointer_unsafe_gogo.go | 56 + .../github.com/gogo/protobuf/proto/properties.go | 599 + .../gogo/protobuf/proto/properties_gogo.go | 36 + vendor/github.com/gogo/protobuf/proto/skip_gogo.go | 119 + .../gogo/protobuf/proto/table_marshal.go | 3006 ++ .../gogo/protobuf/proto/table_marshal_gogo.go | 388 + .../github.com/gogo/protobuf/proto/table_merge.go | 657 + .../gogo/protobuf/proto/table_unmarshal.go | 2245 ++ .../gogo/protobuf/proto/table_unmarshal_gogo.go | 385 + vendor/github.com/gogo/protobuf/proto/text.go | 928 + vendor/github.com/gogo/protobuf/proto/text_gogo.go | 57 + .../github.com/gogo/protobuf/proto/text_parser.go | 1018 + vendor/github.com/gogo/protobuf/proto/timestamp.go | 113 + .../gogo/protobuf/proto/timestamp_gogo.go | 49 + vendor/github.com/gogo/protobuf/proto/wrappers.go | 1888 ++ .../gogo/protobuf/proto/wrappers_gogo.go | 113 + vendor/github.com/golangci/check/LICENSE | 674 + .../golangci/check/cmd/structcheck/structcheck.go | 193 + .../golangci/check/cmd/varcheck/varcheck.go | 163 + vendor/github.com/golangci/dupl/.travis.yml | 5 + vendor/github.com/golangci/dupl/LICENSE | 21 + vendor/github.com/golangci/dupl/README.md | 63 + vendor/github.com/golangci/dupl/job/buildtree.go | 22 + vendor/github.com/golangci/dupl/job/parse.go | 36 + vendor/github.com/golangci/dupl/main.go | 148 + vendor/github.com/golangci/dupl/printer/html.go | 120 + .../github.com/golangci/dupl/printer/plumbing.go | 50 + vendor/github.com/golangci/dupl/printer/printer.go | 11 + vendor/github.com/golangci/dupl/printer/text.go | 100 + vendor/github.com/golangci/dupl/suffixtree/dupl.go | 98 + .../golangci/dupl/suffixtree/suffixtree.go | 216 + .../golangci/dupl/syntax/golang/golang.go | 392 + vendor/github.com/golangci/dupl/syntax/syntax.go | 175 + vendor/github.com/golangci/errcheck/LICENSE | 22 + .../golangci/errcheck/golangci/golangci.go | 85 + .../errcheck/internal/errcheck/errcheck.go | 538 + vendor/github.com/golangci/go-misc/LICENSE | 27 + .../github.com/golangci/go-misc/deadcode/README.md | 18 + .../golangci/go-misc/deadcode/deadcode.go | 135 + vendor/github.com/golangci/goconst/LICENSE | 21 + vendor/github.com/golangci/goconst/README.md | 49 + vendor/github.com/golangci/goconst/parser.go | 188 + vendor/github.com/golangci/goconst/visitor.go | 143 + vendor/github.com/golangci/gocyclo/CONTRIBUTORS | 7 + vendor/github.com/golangci/gocyclo/LICENSE | 27 + .../golangci/gocyclo/pkg/gocyclo/gocyclo.go | 82 + vendor/github.com/golangci/gofmt/gofmt/LICENSE | 27 + vendor/github.com/golangci/gofmt/gofmt/doc.go | 104 + vendor/github.com/golangci/gofmt/gofmt/gofmt.go | 327 + vendor/github.com/golangci/gofmt/gofmt/golangci.go | 46 + vendor/github.com/golangci/gofmt/gofmt/internal.go | 176 + vendor/github.com/golangci/gofmt/gofmt/rewrite.go | 303 + vendor/github.com/golangci/gofmt/gofmt/simplify.go | 165 + vendor/github.com/golangci/gofmt/goimports/LICENSE | 27 + .../golangci/gofmt/goimports/goimports.go | 358 + .../golangci/gofmt/goimports/golangci.go | 33 + vendor/github.com/golangci/golangci-lint/LICENSE | 674 + .../golangci-lint/cmd/golangci-lint/main.go | 25 + .../golangci-lint/cmd/golangci-lint/mod_version.go | 19 + .../golangci/golangci-lint/internal/cache/cache.go | 544 + .../golangci-lint/internal/cache/default.go | 87 + .../golangci/golangci-lint/internal/cache/hash.go | 186 + .../golangci-lint/internal/errorutil/errors.go | 23 + .../golangci-lint/internal/pkgcache/pkgcache.go | 229 + .../golangci-lint/internal/renameio/renameio.go | 93 + .../golangci-lint/internal/robustio/robustio.go | 53 + .../internal/robustio/robustio_darwin.go | 29 + .../internal/robustio/robustio_flaky.go | 93 + .../internal/robustio/robustio_other.go | 28 + .../internal/robustio/robustio_windows.go | 33 + .../golangci/golangci-lint/pkg/commands/cache.go | 84 + .../golangci-lint/pkg/commands/completion.go | 53 + .../golangci/golangci-lint/pkg/commands/config.go | 66 + .../golangci-lint/pkg/commands/executor.go | 245 + .../golangci/golangci-lint/pkg/commands/help.go | 84 + .../golangci/golangci-lint/pkg/commands/linters.go | 51 + .../golangci/golangci-lint/pkg/commands/root.go | 165 + .../golangci/golangci-lint/pkg/commands/run.go | 534 + .../golangci/golangci-lint/pkg/commands/version.go | 17 + .../golangci/golangci-lint/pkg/config/config.go | 491 + .../golangci-lint/pkg/config/config_gocritic.go | 367 + .../golangci/golangci-lint/pkg/config/reader.go | 204 + .../golangci-lint/pkg/exitcodes/exitcodes.go | 34 + .../golangci-lint/pkg/fsutils/filecache.go | 67 + .../golangci/golangci-lint/pkg/fsutils/fsutils.go | 100 + .../golangci-lint/pkg/fsutils/linecache.go | 70 + .../golangci-lint/pkg/golinters/asciicheck.go | 19 + .../golangci-lint/pkg/golinters/bodyclose.go | 21 + .../golangci-lint/pkg/golinters/deadcode.go | 52 + .../golangci-lint/pkg/golinters/depguard.go | 112 + .../golangci-lint/pkg/golinters/dogsled.go | 97 + .../golangci/golangci-lint/pkg/golinters/dupl.go | 83 + .../golangci-lint/pkg/golinters/errcheck.go | 217 + .../golangci/golangci-lint/pkg/golinters/funlen.go | 64 + .../pkg/golinters/goanalysis/adapters.go | 36 + .../pkg/golinters/goanalysis/issue.go | 31 + .../pkg/golinters/goanalysis/linter.go | 519 + .../pkg/golinters/goanalysis/load/guard.go | 30 + .../pkg/golinters/goanalysis/metalinter.go | 99 + .../pkg/golinters/goanalysis/runner.go | 1363 + .../pkg/golinters/gochecknoglobals.go | 100 + .../golangci-lint/pkg/golinters/gochecknoinits.go | 74 + .../golangci-lint/pkg/golinters/gocognit.go | 69 + .../golangci-lint/pkg/golinters/goconst.go | 81 + .../golangci-lint/pkg/golinters/gocritic.go | 162 + .../golangci-lint/pkg/golinters/gocyclo.go | 69 + .../golangci/golangci-lint/pkg/golinters/godot.go | 63 + .../golangci/golangci-lint/pkg/golinters/godox.go | 63 + .../golangci-lint/pkg/golinters/goerr113.go | 19 + .../golangci/golangci-lint/pkg/golinters/gofmt.go | 72 + .../golangci-lint/pkg/golinters/gofmt_common.go | 269 + .../golangci-lint/pkg/golinters/goimports.go | 73 + .../golangci/golangci-lint/pkg/golinters/golint.go | 78 + .../golangci/golangci-lint/pkg/golinters/gomnd.go | 27 + .../golangci-lint/pkg/golinters/gomodguard.go | 88 + .../pkg/golinters/goprintffuncname.go | 17 + .../golangci/golangci-lint/pkg/golinters/gosec.go | 97 + .../golangci-lint/pkg/golinters/gosimple.go | 19 + .../golangci/golangci-lint/pkg/golinters/govet.go | 165 + .../golangci-lint/pkg/golinters/ineffassign.go | 61 + .../golangci-lint/pkg/golinters/interfacer.go | 67 + .../golangci/golangci-lint/pkg/golinters/lll.go | 124 + .../golangci-lint/pkg/golinters/maligned.go | 58 + .../golangci-lint/pkg/golinters/megacheck.go | 30 + .../golangci-lint/pkg/golinters/misspell.go | 132 + .../golangci-lint/pkg/golinters/nakedret.go | 123 + .../golangci/golangci-lint/pkg/golinters/nestif.go | 65 + .../golangci-lint/pkg/golinters/nolintlint.go | 92 + .../pkg/golinters/nolintlint/README.md | 31 + .../pkg/golinters/nolintlint/nolintlint.go | 239 + .../golangci-lint/pkg/golinters/prealloc.go | 57 + .../golangci-lint/pkg/golinters/rowerrcheck.go | 23 + .../golangci-lint/pkg/golinters/scopelint.go | 178 + .../golangci-lint/pkg/golinters/staticcheck.go | 19 + .../golangci-lint/pkg/golinters/structcheck.go | 55 + .../golangci-lint/pkg/golinters/stylecheck.go | 19 + .../golangci-lint/pkg/golinters/testpackage.go | 23 + .../golangci-lint/pkg/golinters/typecheck.go | 26 + .../golangci-lint/pkg/golinters/unconvert.go | 53 + .../golangci-lint/pkg/golinters/unparam.go | 77 + .../golangci/golangci-lint/pkg/golinters/unused.go | 65 + .../golangci/golangci-lint/pkg/golinters/util.go | 24 + .../golangci-lint/pkg/golinters/varcheck.go | 55 + .../golangci-lint/pkg/golinters/whitespace.go | 85 + .../golangci/golangci-lint/pkg/golinters/wsl.go | 81 + .../golangci/golangci-lint/pkg/goutil/env.go | 61 + .../golangci-lint/pkg/lint/linter/config.go | 89 + .../golangci-lint/pkg/lint/linter/context.go | 49 + .../golangci-lint/pkg/lint/linter/linter.go | 13 + .../pkg/lint/lintersdb/enabled_set.go | 187 + .../golangci-lint/pkg/lint/lintersdb/manager.go | 374 + .../golangci-lint/pkg/lint/lintersdb/validator.go | 99 + .../golangci/golangci-lint/pkg/lint/load.go | 308 + .../golangci/golangci-lint/pkg/lint/runner.go | 256 + .../golangci/golangci-lint/pkg/logutils/log.go | 31 + .../golangci-lint/pkg/logutils/logutils.go | 49 + .../golangci/golangci-lint/pkg/logutils/mock.go | 47 + .../golangci/golangci-lint/pkg/logutils/out.go | 9 + .../golangci-lint/pkg/logutils/stderr_log.go | 121 + .../golangci/golangci-lint/pkg/packages/errors.go | 39 + .../golangci/golangci-lint/pkg/packages/skip.go | 25 + .../golangci/golangci-lint/pkg/packages/util.go | 71 + .../golangci-lint/pkg/printers/checkstyle.go | 80 + .../golangci-lint/pkg/printers/codeclimate.go | 62 + .../golangci/golangci-lint/pkg/printers/github.go | 39 + .../golangci/golangci-lint/pkg/printers/json.go | 41 + .../golangci-lint/pkg/printers/junitxml.go | 79 + .../golangci/golangci-lint/pkg/printers/printer.go | 11 + .../golangci/golangci-lint/pkg/printers/tab.go | 58 + .../golangci/golangci-lint/pkg/printers/text.go | 90 + .../golangci/golangci-lint/pkg/report/data.go | 26 + .../golangci/golangci-lint/pkg/report/log.go | 64 + .../golangci/golangci-lint/pkg/result/issue.go | 78 + .../pkg/result/processors/autogenerated_exclude.go | 152 + .../golangci-lint/pkg/result/processors/cgo.go | 58 + .../golangci-lint/pkg/result/processors/diff.go | 74 + .../golangci-lint/pkg/result/processors/exclude.go | 59 + .../pkg/result/processors/exclude_rules.go | 143 + .../pkg/result/processors/filename_unadjuster.go | 123 + .../golangci-lint/pkg/result/processors/fixer.go | 248 + .../pkg/result/processors/identifier_marker.go | 125 + .../pkg/result/processors/max_from_linter.go | 54 + .../result/processors/max_per_file_from_linter.go | 60 + .../pkg/result/processors/max_same_issues.go | 81 + .../golangci-lint/pkg/result/processors/nolint.go | 304 + .../pkg/result/processors/path_prettifier.go | 48 + .../pkg/result/processors/path_shortener.go | 40 + .../pkg/result/processors/processor.go | 11 + .../pkg/result/processors/skip_dirs.go | 143 + .../pkg/result/processors/skip_files.go | 52 + .../pkg/result/processors/source_code.go | 47 + .../pkg/result/processors/uniq_by_line.go | 58 + .../golangci-lint/pkg/result/processors/utils.go | 62 + .../golangci-lint/pkg/timeutils/stopwatch.go | 116 + vendor/github.com/golangci/ineffassign/.gitignore | 30 + vendor/github.com/golangci/ineffassign/LICENSE | 21 + vendor/github.com/golangci/ineffassign/README.md | 4 + vendor/github.com/golangci/ineffassign/bugs | 7 + .../github.com/golangci/ineffassign/ineffassign.go | 620 + vendor/github.com/golangci/ineffassign/list | 25 + vendor/github.com/golangci/ineffassign/liststd | 131 + vendor/github.com/golangci/lint-1/.travis.yml | 19 + vendor/github.com/golangci/lint-1/CONTRIBUTING.md | 15 + vendor/github.com/golangci/lint-1/LICENSE | 27 + vendor/github.com/golangci/lint-1/README.md | 88 + vendor/github.com/golangci/lint-1/go.mod | 3 + vendor/github.com/golangci/lint-1/go.sum | 6 + vendor/github.com/golangci/lint-1/lint.go | 1655 + vendor/github.com/golangci/maligned/LICENSE | 27 + vendor/github.com/golangci/maligned/README | 7 + vendor/github.com/golangci/maligned/maligned.go | 253 + vendor/github.com/golangci/misspell/.gitignore | 34 + vendor/github.com/golangci/misspell/.travis.yml | 20 + vendor/github.com/golangci/misspell/Dockerfile | 37 + vendor/github.com/golangci/misspell/Gopkg.lock | 24 + vendor/github.com/golangci/misspell/Gopkg.toml | 34 + vendor/github.com/golangci/misspell/LICENSE | 22 + vendor/github.com/golangci/misspell/Makefile | 74 + vendor/github.com/golangci/misspell/README.md | 424 + .../github.com/golangci/misspell/RELEASE-HOWTO.md | 38 + vendor/github.com/golangci/misspell/ascii.go | 62 + vendor/github.com/golangci/misspell/case.go | 59 + vendor/github.com/golangci/misspell/goreleaser.yml | 38 + .../golangci/misspell/install-misspell.sh | 362 + vendor/github.com/golangci/misspell/legal.go | 48 + vendor/github.com/golangci/misspell/mime.go | 210 + vendor/github.com/golangci/misspell/notwords.go | 85 + vendor/github.com/golangci/misspell/replace.go | 246 + .../github.com/golangci/misspell/stringreplacer.go | 336 + .../golangci/misspell/stringreplacer_test.gox | 421 + vendor/github.com/golangci/misspell/url.go | 17 + vendor/github.com/golangci/misspell/words.go | 31194 +++++++++++++++++++ vendor/github.com/golangci/prealloc/LICENSE | 21 + vendor/github.com/golangci/prealloc/README.md | 198 + vendor/github.com/golangci/prealloc/import.go | 310 + vendor/github.com/golangci/prealloc/prealloc.go | 403 + vendor/github.com/golangci/revgrep/.gitignore | 1 + vendor/github.com/golangci/revgrep/.travis.yml | 7 + vendor/github.com/golangci/revgrep/LICENSE | 201 + vendor/github.com/golangci/revgrep/README.md | 58 + vendor/github.com/golangci/revgrep/revgrep.go | 395 + vendor/github.com/golangci/unconvert/LICENSE | 27 + vendor/github.com/golangci/unconvert/README | 36 + vendor/github.com/golangci/unconvert/unconvert.go | 665 + .../gostaticanalysis/analysisutil/LICENSE | 21 + .../gostaticanalysis/analysisutil/README.md | 10 + .../gostaticanalysis/analysisutil/file.go | 18 + .../gostaticanalysis/analysisutil/go.mod | 5 + .../gostaticanalysis/analysisutil/go.sum | 6 + .../gostaticanalysis/analysisutil/pkg.go | 26 + .../gostaticanalysis/analysisutil/ssa.go | 31 + vendor/github.com/hashicorp/hcl/.gitignore | 9 + vendor/github.com/hashicorp/hcl/.travis.yml | 13 + vendor/github.com/hashicorp/hcl/LICENSE | 354 + vendor/github.com/hashicorp/hcl/Makefile | 18 + vendor/github.com/hashicorp/hcl/README.md | 125 + vendor/github.com/hashicorp/hcl/appveyor.yml | 19 + vendor/github.com/hashicorp/hcl/decoder.go | 729 + vendor/github.com/hashicorp/hcl/go.mod | 3 + vendor/github.com/hashicorp/hcl/go.sum | 2 + vendor/github.com/hashicorp/hcl/hcl.go | 11 + vendor/github.com/hashicorp/hcl/hcl/ast/ast.go | 219 + vendor/github.com/hashicorp/hcl/hcl/ast/walk.go | 52 + .../github.com/hashicorp/hcl/hcl/parser/error.go | 17 + .../github.com/hashicorp/hcl/hcl/parser/parser.go | 532 + .../github.com/hashicorp/hcl/hcl/printer/nodes.go | 789 + .../hashicorp/hcl/hcl/printer/printer.go | 66 + .../hashicorp/hcl/hcl/scanner/scanner.go | 652 + .../github.com/hashicorp/hcl/hcl/strconv/quote.go | 241 + .../github.com/hashicorp/hcl/hcl/token/position.go | 46 + vendor/github.com/hashicorp/hcl/hcl/token/token.go | 219 + .../hashicorp/hcl/json/parser/flatten.go | 117 + .../github.com/hashicorp/hcl/json/parser/parser.go | 313 + .../hashicorp/hcl/json/scanner/scanner.go | 451 + .../hashicorp/hcl/json/token/position.go | 46 + .../github.com/hashicorp/hcl/json/token/token.go | 118 + vendor/github.com/hashicorp/hcl/lex.go | 38 + vendor/github.com/hashicorp/hcl/parse.go | 39 + .../github.com/inconshreveable/mousetrap/LICENSE | 13 + .../github.com/inconshreveable/mousetrap/README.md | 23 + .../inconshreveable/mousetrap/trap_others.go | 15 + .../inconshreveable/mousetrap/trap_windows.go | 98 + .../inconshreveable/mousetrap/trap_windows_1.4.go | 46 + vendor/github.com/jingyugao/rowserrcheck/LICENSE | 21 + .../rowserrcheck/passes/rowserr/rowserr.go | 319 + .../go-printf-func-name/pkg/analyzer/analyzer.go | 74 + vendor/github.com/kisielk/gotool/.travis.yml | 23 + vendor/github.com/kisielk/gotool/LEGAL | 32 + vendor/github.com/kisielk/gotool/LICENSE | 20 + vendor/github.com/kisielk/gotool/README.md | 6 + vendor/github.com/kisielk/gotool/go.mod | 1 + vendor/github.com/kisielk/gotool/go13.go | 15 + vendor/github.com/kisielk/gotool/go14-15.go | 15 + vendor/github.com/kisielk/gotool/go16-18.go | 15 + .../kisielk/gotool/internal/load/path.go | 27 + .../github.com/kisielk/gotool/internal/load/pkg.go | 25 + .../kisielk/gotool/internal/load/search.go | 354 + vendor/github.com/kisielk/gotool/match.go | 56 + vendor/github.com/kisielk/gotool/match18.go | 317 + vendor/github.com/kisielk/gotool/tool.go | 48 + .../go-windows-terminal-sequences/LICENSE | 9 + .../go-windows-terminal-sequences/README.md | 40 + .../konsorten/go-windows-terminal-sequences/go.mod | 1 + .../go-windows-terminal-sequences/sequences.go | 36 + vendor/github.com/magiconair/properties/.gitignore | 6 + .../github.com/magiconair/properties/.travis.yml | 12 + .../github.com/magiconair/properties/CHANGELOG.md | 139 + vendor/github.com/magiconair/properties/LICENSE | 25 + vendor/github.com/magiconair/properties/README.md | 129 + vendor/github.com/magiconair/properties/decode.go | 289 + vendor/github.com/magiconair/properties/doc.go | 156 + vendor/github.com/magiconair/properties/go.mod | 1 + .../github.com/magiconair/properties/integrate.go | 34 + vendor/github.com/magiconair/properties/lex.go | 407 + vendor/github.com/magiconair/properties/load.go | 292 + vendor/github.com/magiconair/properties/parser.go | 95 + .../github.com/magiconair/properties/properties.go | 833 + .../github.com/magiconair/properties/rangecheck.go | 31 + vendor/github.com/maratori/testpackage/LICENSE | 21 + .../testpackage/pkg/testpackage/testpackage.go | 53 + vendor/github.com/matoous/godox/.gitignore | 19 + vendor/github.com/matoous/godox/.golangci.yml | 71 + vendor/github.com/matoous/godox/.revive.toml | 135 + vendor/github.com/matoous/godox/LICENSE | 21 + vendor/github.com/matoous/godox/README.md | 18 + vendor/github.com/matoous/godox/go.mod | 5 + vendor/github.com/matoous/godox/go.sum | 8 + vendor/github.com/matoous/godox/godox.go | 84 + vendor/github.com/mattn/go-colorable/.travis.yml | 9 + vendor/github.com/mattn/go-colorable/LICENSE | 21 + vendor/github.com/mattn/go-colorable/README.md | 48 + .../mattn/go-colorable/colorable_appengine.go | 29 + .../mattn/go-colorable/colorable_others.go | 30 + .../mattn/go-colorable/colorable_windows.go | 1005 + vendor/github.com/mattn/go-colorable/go.mod | 3 + vendor/github.com/mattn/go-colorable/go.sum | 4 + .../github.com/mattn/go-colorable/noncolorable.go | 55 + vendor/github.com/mattn/go-isatty/.travis.yml | 13 + vendor/github.com/mattn/go-isatty/LICENSE | 9 + vendor/github.com/mattn/go-isatty/README.md | 50 + vendor/github.com/mattn/go-isatty/doc.go | 2 + vendor/github.com/mattn/go-isatty/go.mod | 3 + vendor/github.com/mattn/go-isatty/go.sum | 2 + .../github.com/mattn/go-isatty/isatty_android.go | 23 + vendor/github.com/mattn/go-isatty/isatty_bsd.go | 24 + vendor/github.com/mattn/go-isatty/isatty_others.go | 15 + .../github.com/mattn/go-isatty/isatty_solaris.go | 22 + vendor/github.com/mattn/go-isatty/isatty_tcgets.go | 19 + .../github.com/mattn/go-isatty/isatty_windows.go | 94 + vendor/github.com/mitchellh/go-homedir/LICENSE | 21 + vendor/github.com/mitchellh/go-homedir/README.md | 14 + vendor/github.com/mitchellh/go-homedir/go.mod | 1 + vendor/github.com/mitchellh/go-homedir/homedir.go | 167 + .../github.com/mitchellh/mapstructure/.travis.yml | 8 + .../github.com/mitchellh/mapstructure/CHANGELOG.md | 21 + vendor/github.com/mitchellh/mapstructure/LICENSE | 21 + vendor/github.com/mitchellh/mapstructure/README.md | 46 + .../mitchellh/mapstructure/decode_hooks.go | 217 + vendor/github.com/mitchellh/mapstructure/error.go | 50 + vendor/github.com/mitchellh/mapstructure/go.mod | 1 + .../mitchellh/mapstructure/mapstructure.go | 1149 + vendor/github.com/nakabonne/nestif/.gitignore | 16 + vendor/github.com/nakabonne/nestif/LICENSE | 25 + vendor/github.com/nakabonne/nestif/README.md | 122 + vendor/github.com/nakabonne/nestif/go.mod | 8 + vendor/github.com/nakabonne/nestif/go.sum | 12 + vendor/github.com/nakabonne/nestif/nestif.go | 148 + vendor/github.com/nbutton23/zxcvbn-go/.gitignore | 2 + vendor/github.com/nbutton23/zxcvbn-go/Gopkg.lock | 27 + vendor/github.com/nbutton23/zxcvbn-go/Gopkg.toml | 26 + vendor/github.com/nbutton23/zxcvbn-go/LICENSE.txt | 20 + vendor/github.com/nbutton23/zxcvbn-go/Makefile | 15 + vendor/github.com/nbutton23/zxcvbn-go/README.md | 78 + .../nbutton23/zxcvbn-go/adjacency/adjcmartix.go | 108 + .../github.com/nbutton23/zxcvbn-go/data/bindata.go | 444 + .../zxcvbn-go/entropy/entropyCalculator.go | 216 + .../nbutton23/zxcvbn-go/frequency/frequency.go | 50 + .../github.com/nbutton23/zxcvbn-go/match/match.go | 44 + .../nbutton23/zxcvbn-go/matching/dateMatchers.go | 209 + .../zxcvbn-go/matching/dictionaryMatch.go | 57 + .../nbutton23/zxcvbn-go/matching/leet.go | 234 + .../nbutton23/zxcvbn-go/matching/matching.go | 82 + .../nbutton23/zxcvbn-go/matching/repeatMatch.go | 67 + .../nbutton23/zxcvbn-go/matching/sequenceMatch.go | 76 + .../nbutton23/zxcvbn-go/matching/spatialMatch.go | 88 + .../nbutton23/zxcvbn-go/scoring/scoring.go | 177 + .../nbutton23/zxcvbn-go/utils/math/mathutils.go | 40 + vendor/github.com/nbutton23/zxcvbn-go/zxcvbn.go | 22 + vendor/github.com/pelletier/go-toml/.gitignore | 2 + vendor/github.com/pelletier/go-toml/.travis.yml | 23 + vendor/github.com/pelletier/go-toml/LICENSE | 21 + vendor/github.com/pelletier/go-toml/README.md | 131 + vendor/github.com/pelletier/go-toml/benchmark.json | 164 + vendor/github.com/pelletier/go-toml/benchmark.sh | 32 + vendor/github.com/pelletier/go-toml/benchmark.toml | 244 + vendor/github.com/pelletier/go-toml/benchmark.yml | 121 + vendor/github.com/pelletier/go-toml/doc.go | 23 + .../github.com/pelletier/go-toml/example-crlf.toml | 29 + vendor/github.com/pelletier/go-toml/example.toml | 29 + vendor/github.com/pelletier/go-toml/fuzz.go | 31 + vendor/github.com/pelletier/go-toml/fuzz.sh | 15 + vendor/github.com/pelletier/go-toml/keysparsing.go | 85 + vendor/github.com/pelletier/go-toml/lexer.go | 750 + vendor/github.com/pelletier/go-toml/marshal.go | 609 + .../github.com/pelletier/go-toml/marshal_test.toml | 38 + vendor/github.com/pelletier/go-toml/parser.go | 430 + vendor/github.com/pelletier/go-toml/position.go | 29 + vendor/github.com/pelletier/go-toml/test.sh | 88 + vendor/github.com/pelletier/go-toml/token.go | 144 + vendor/github.com/pelletier/go-toml/toml.go | 367 + .../pelletier/go-toml/tomltree_create.go | 142 + .../github.com/pelletier/go-toml/tomltree_write.go | 333 + vendor/github.com/pkg/errors/.gitignore | 24 + vendor/github.com/pkg/errors/.travis.yml | 15 + vendor/github.com/pkg/errors/LICENSE | 23 + vendor/github.com/pkg/errors/README.md | 52 + vendor/github.com/pkg/errors/appveyor.yml | 32 + vendor/github.com/pkg/errors/errors.go | 282 + vendor/github.com/pkg/errors/stack.go | 147 + vendor/github.com/pmezard/go-difflib/LICENSE | 27 + .../pmezard/go-difflib/difflib/difflib.go | 772 + .../github.com/ryancurrah/gomodguard/.dockerignore | 1 + vendor/github.com/ryancurrah/gomodguard/.gitignore | 21 + .../ryancurrah/gomodguard/.gomodguard.yaml | 18 + .../ryancurrah/gomodguard/.goreleaser.yml | 31 + vendor/github.com/ryancurrah/gomodguard/Dockerfile | 17 + .../ryancurrah/gomodguard/Dockerfile.goreleaser | 10 + vendor/github.com/ryancurrah/gomodguard/LICENSE | 21 + vendor/github.com/ryancurrah/gomodguard/Makefile | 37 + vendor/github.com/ryancurrah/gomodguard/README.md | 114 + vendor/github.com/ryancurrah/gomodguard/VERSION | 1 + vendor/github.com/ryancurrah/gomodguard/go.mod | 11 + vendor/github.com/ryancurrah/gomodguard/go.sum | 24 + .../github.com/ryancurrah/gomodguard/gomodguard.go | 403 + vendor/github.com/securego/gosec/v2/.gitignore | 35 + .../github.com/securego/gosec/v2/.goreleaser.yml | 20 + vendor/github.com/securego/gosec/v2/Dockerfile | 14 + vendor/github.com/securego/gosec/v2/LICENSE.txt | 154 + vendor/github.com/securego/gosec/v2/Makefile | 71 + vendor/github.com/securego/gosec/v2/README.md | 326 + vendor/github.com/securego/gosec/v2/action.yml | 19 + vendor/github.com/securego/gosec/v2/analyzer.go | 378 + vendor/github.com/securego/gosec/v2/call_list.go | 109 + vendor/github.com/securego/gosec/v2/config.go | 125 + vendor/github.com/securego/gosec/v2/errors.go | 33 + vendor/github.com/securego/gosec/v2/go.mod | 19 + vendor/github.com/securego/gosec/v2/go.sum | 82 + vendor/github.com/securego/gosec/v2/helpers.go | 435 + .../github.com/securego/gosec/v2/import_tracker.go | 75 + vendor/github.com/securego/gosec/v2/install.sh | 372 + vendor/github.com/securego/gosec/v2/issue.go | 177 + vendor/github.com/securego/gosec/v2/renovate.json | 7 + vendor/github.com/securego/gosec/v2/resolve.go | 95 + vendor/github.com/securego/gosec/v2/rule.go | 59 + .../github.com/securego/gosec/v2/rules/archive.go | 60 + .../securego/gosec/v2/rules/bad_defer.go | 69 + vendor/github.com/securego/gosec/v2/rules/bind.go | 83 + .../securego/gosec/v2/rules/blacklist.go | 94 + .../securego/gosec/v2/rules/decompression-bomb.go | 109 + .../github.com/securego/gosec/v2/rules/errors.go | 119 + .../securego/gosec/v2/rules/fileperms.go | 111 + .../gosec/v2/rules/hardcoded_credentials.go | 173 + .../securego/gosec/v2/rules/implicit_aliasing.go | 116 + .../securego/gosec/v2/rules/integer_overflow.go | 89 + vendor/github.com/securego/gosec/v2/rules/pprof.go | 42 + vendor/github.com/securego/gosec/v2/rules/rand.go | 55 + .../github.com/securego/gosec/v2/rules/readfile.go | 106 + vendor/github.com/securego/gosec/v2/rules/rsa.go | 58 + .../github.com/securego/gosec/v2/rules/rulelist.go | 116 + vendor/github.com/securego/gosec/v2/rules/sql.go | 219 + vendor/github.com/securego/gosec/v2/rules/ssh.go | 38 + vendor/github.com/securego/gosec/v2/rules/ssrf.go | 66 + .../github.com/securego/gosec/v2/rules/subproc.go | 85 + .../securego/gosec/v2/rules/tempfiles.go | 58 + .../securego/gosec/v2/rules/templates.go | 61 + vendor/github.com/securego/gosec/v2/rules/tls.go | 130 + .../securego/gosec/v2/rules/tls_config.go | 88 + .../github.com/securego/gosec/v2/rules/unsafe.go | 53 + .../securego/gosec/v2/rules/weakcrypto.go | 58 + vendor/github.com/sirupsen/logrus/.gitignore | 2 + vendor/github.com/sirupsen/logrus/.travis.yml | 25 + vendor/github.com/sirupsen/logrus/CHANGELOG.md | 200 + vendor/github.com/sirupsen/logrus/LICENSE | 21 + vendor/github.com/sirupsen/logrus/README.md | 495 + vendor/github.com/sirupsen/logrus/alt_exit.go | 76 + vendor/github.com/sirupsen/logrus/appveyor.yml | 14 + vendor/github.com/sirupsen/logrus/doc.go | 26 + vendor/github.com/sirupsen/logrus/entry.go | 407 + vendor/github.com/sirupsen/logrus/exported.go | 225 + vendor/github.com/sirupsen/logrus/formatter.go | 78 + vendor/github.com/sirupsen/logrus/go.mod | 10 + vendor/github.com/sirupsen/logrus/go.sum | 16 + vendor/github.com/sirupsen/logrus/hooks.go | 34 + .../github.com/sirupsen/logrus/json_formatter.go | 121 + vendor/github.com/sirupsen/logrus/logger.go | 351 + vendor/github.com/sirupsen/logrus/logrus.go | 186 + .../sirupsen/logrus/terminal_check_appengine.go | 11 + .../sirupsen/logrus/terminal_check_bsd.go | 13 + .../sirupsen/logrus/terminal_check_no_terminal.go | 11 + .../sirupsen/logrus/terminal_check_notappengine.go | 17 + .../sirupsen/logrus/terminal_check_solaris.go | 11 + .../sirupsen/logrus/terminal_check_unix.go | 13 + .../sirupsen/logrus/terminal_check_windows.go | 34 + .../github.com/sirupsen/logrus/text_formatter.go | 295 + vendor/github.com/sirupsen/logrus/writer.go | 64 + vendor/github.com/sourcegraph/go-diff/LICENSE | 35 + vendor/github.com/sourcegraph/go-diff/diff/diff.go | 76 + .../github.com/sourcegraph/go-diff/diff/diff.pb.go | 1059 + .../github.com/sourcegraph/go-diff/diff/diff.proto | 81 + vendor/github.com/sourcegraph/go-diff/diff/doc.go | 2 + .../github.com/sourcegraph/go-diff/diff/parse.go | 625 + .../github.com/sourcegraph/go-diff/diff/print.go | 140 + .../sourcegraph/go-diff/diff/reader_util.go | 37 + vendor/github.com/spf13/afero/.travis.yml | 21 + vendor/github.com/spf13/afero/LICENSE.txt | 174 + vendor/github.com/spf13/afero/README.md | 452 + vendor/github.com/spf13/afero/afero.go | 108 + vendor/github.com/spf13/afero/appveyor.yml | 15 + vendor/github.com/spf13/afero/basepath.go | 180 + vendor/github.com/spf13/afero/cacheOnReadFs.go | 290 + vendor/github.com/spf13/afero/const_bsds.go | 22 + vendor/github.com/spf13/afero/const_win_unix.go | 25 + vendor/github.com/spf13/afero/copyOnWriteFs.go | 292 + vendor/github.com/spf13/afero/go.mod | 1 + vendor/github.com/spf13/afero/httpFs.go | 110 + vendor/github.com/spf13/afero/ioutil.go | 230 + vendor/github.com/spf13/afero/lstater.go | 27 + vendor/github.com/spf13/afero/match.go | 110 + vendor/github.com/spf13/afero/mem/dir.go | 37 + vendor/github.com/spf13/afero/mem/dirmap.go | 43 + vendor/github.com/spf13/afero/mem/file.go | 317 + vendor/github.com/spf13/afero/memmap.go | 365 + vendor/github.com/spf13/afero/os.go | 101 + vendor/github.com/spf13/afero/path.go | 106 + vendor/github.com/spf13/afero/readonlyfs.go | 80 + vendor/github.com/spf13/afero/regexpfs.go | 214 + vendor/github.com/spf13/afero/unionFile.go | 305 + vendor/github.com/spf13/afero/util.go | 330 + vendor/github.com/spf13/cast/.gitignore | 25 + vendor/github.com/spf13/cast/.travis.yml | 15 + vendor/github.com/spf13/cast/LICENSE | 21 + vendor/github.com/spf13/cast/Makefile | 38 + vendor/github.com/spf13/cast/README.md | 75 + vendor/github.com/spf13/cast/cast.go | 171 + vendor/github.com/spf13/cast/caste.go | 1249 + vendor/github.com/spf13/cast/go.mod | 7 + vendor/github.com/spf13/cast/go.sum | 6 + vendor/github.com/spf13/cobra/.gitignore | 38 + vendor/github.com/spf13/cobra/.mailmap | 3 + vendor/github.com/spf13/cobra/.travis.yml | 31 + vendor/github.com/spf13/cobra/LICENSE.txt | 174 + vendor/github.com/spf13/cobra/README.md | 741 + vendor/github.com/spf13/cobra/args.go | 101 + vendor/github.com/spf13/cobra/bash_completions.go | 547 + vendor/github.com/spf13/cobra/bash_completions.md | 256 + vendor/github.com/spf13/cobra/cobra.go | 207 + vendor/github.com/spf13/cobra/command.go | 1594 + vendor/github.com/spf13/cobra/command_notwin.go | 5 + vendor/github.com/spf13/cobra/command_win.go | 26 + vendor/github.com/spf13/cobra/go.mod | 13 + vendor/github.com/spf13/cobra/go.sum | 51 + .../spf13/cobra/powershell_completions.go | 100 + .../spf13/cobra/powershell_completions.md | 14 + vendor/github.com/spf13/cobra/shell_completions.go | 85 + vendor/github.com/spf13/cobra/zsh_completions.go | 336 + vendor/github.com/spf13/cobra/zsh_completions.md | 39 + .../github.com/spf13/jwalterweatherman/.gitignore | 22 + vendor/github.com/spf13/jwalterweatherman/LICENSE | 21 + .../github.com/spf13/jwalterweatherman/README.md | 148 + .../spf13/jwalterweatherman/default_notepad.go | 113 + vendor/github.com/spf13/jwalterweatherman/go.mod | 1 + .../spf13/jwalterweatherman/log_counter.go | 55 + .../github.com/spf13/jwalterweatherman/notepad.go | 194 + vendor/github.com/spf13/pflag/.gitignore | 2 + vendor/github.com/spf13/pflag/.travis.yml | 22 + vendor/github.com/spf13/pflag/LICENSE | 28 + vendor/github.com/spf13/pflag/README.md | 296 + vendor/github.com/spf13/pflag/bool.go | 94 + vendor/github.com/spf13/pflag/bool_slice.go | 185 + vendor/github.com/spf13/pflag/bytes.go | 209 + vendor/github.com/spf13/pflag/count.go | 96 + vendor/github.com/spf13/pflag/duration.go | 86 + vendor/github.com/spf13/pflag/duration_slice.go | 166 + vendor/github.com/spf13/pflag/flag.go | 1239 + vendor/github.com/spf13/pflag/float32.go | 88 + vendor/github.com/spf13/pflag/float32_slice.go | 174 + vendor/github.com/spf13/pflag/float64.go | 84 + vendor/github.com/spf13/pflag/float64_slice.go | 166 + vendor/github.com/spf13/pflag/go.mod | 3 + vendor/github.com/spf13/pflag/go.sum | 0 vendor/github.com/spf13/pflag/golangflag.go | 105 + vendor/github.com/spf13/pflag/int.go | 84 + vendor/github.com/spf13/pflag/int16.go | 88 + vendor/github.com/spf13/pflag/int32.go | 88 + vendor/github.com/spf13/pflag/int32_slice.go | 174 + vendor/github.com/spf13/pflag/int64.go | 84 + vendor/github.com/spf13/pflag/int64_slice.go | 166 + vendor/github.com/spf13/pflag/int8.go | 88 + vendor/github.com/spf13/pflag/int_slice.go | 158 + vendor/github.com/spf13/pflag/ip.go | 94 + vendor/github.com/spf13/pflag/ip_slice.go | 186 + vendor/github.com/spf13/pflag/ipmask.go | 122 + vendor/github.com/spf13/pflag/ipnet.go | 98 + vendor/github.com/spf13/pflag/string.go | 80 + vendor/github.com/spf13/pflag/string_array.go | 129 + vendor/github.com/spf13/pflag/string_slice.go | 163 + vendor/github.com/spf13/pflag/string_to_int.go | 149 + vendor/github.com/spf13/pflag/string_to_int64.go | 149 + vendor/github.com/spf13/pflag/string_to_string.go | 160 + vendor/github.com/spf13/pflag/uint.go | 88 + vendor/github.com/spf13/pflag/uint16.go | 88 + vendor/github.com/spf13/pflag/uint32.go | 88 + vendor/github.com/spf13/pflag/uint64.go | 88 + vendor/github.com/spf13/pflag/uint8.go | 88 + vendor/github.com/spf13/pflag/uint_slice.go | 168 + vendor/github.com/spf13/viper/.gitignore | 20 + vendor/github.com/spf13/viper/.golangci.yml | 24 + vendor/github.com/spf13/viper/.travis.yml | 32 + vendor/github.com/spf13/viper/LICENSE | 21 + vendor/github.com/spf13/viper/Makefile | 71 + vendor/github.com/spf13/viper/README.md | 761 + vendor/github.com/spf13/viper/flags.go | 57 + vendor/github.com/spf13/viper/go.mod | 48 + vendor/github.com/spf13/viper/go.sum | 192 + vendor/github.com/spf13/viper/util.go | 221 + vendor/github.com/spf13/viper/viper.go | 2011 ++ vendor/github.com/stretchr/objx/.codeclimate.yml | 13 + vendor/github.com/stretchr/objx/.gitignore | 11 + vendor/github.com/stretchr/objx/.travis.yml | 25 + vendor/github.com/stretchr/objx/Gopkg.lock | 30 + vendor/github.com/stretchr/objx/Gopkg.toml | 8 + vendor/github.com/stretchr/objx/LICENSE | 22 + vendor/github.com/stretchr/objx/README.md | 80 + vendor/github.com/stretchr/objx/Taskfile.yml | 32 + vendor/github.com/stretchr/objx/accessors.go | 148 + vendor/github.com/stretchr/objx/constants.go | 13 + vendor/github.com/stretchr/objx/conversions.go | 108 + vendor/github.com/stretchr/objx/doc.go | 66 + vendor/github.com/stretchr/objx/map.go | 190 + vendor/github.com/stretchr/objx/mutations.go | 77 + vendor/github.com/stretchr/objx/security.go | 12 + vendor/github.com/stretchr/objx/tests.go | 17 + .../stretchr/objx/type_specific_codegen.go | 2501 ++ vendor/github.com/stretchr/objx/value.go | 53 + vendor/github.com/stretchr/testify/LICENSE | 21 + .../stretchr/testify/assert/assertion_format.go | 622 + .../testify/assert/assertion_format.go.tmpl | 5 + .../stretchr/testify/assert/assertion_forward.go | 1232 + .../testify/assert/assertion_forward.go.tmpl | 5 + .../stretchr/testify/assert/assertion_order.go | 309 + .../stretchr/testify/assert/assertions.go | 1626 + vendor/github.com/stretchr/testify/assert/doc.go | 45 + .../github.com/stretchr/testify/assert/errors.go | 10 + .../stretchr/testify/assert/forward_assertions.go | 16 + .../stretchr/testify/assert/http_assertions.go | 143 + vendor/github.com/stretchr/testify/mock/doc.go | 44 + vendor/github.com/stretchr/testify/mock/mock.go | 917 + vendor/github.com/subosito/gotenv/.env | 1 + vendor/github.com/subosito/gotenv/.env.invalid | 1 + vendor/github.com/subosito/gotenv/.gitignore | 3 + vendor/github.com/subosito/gotenv/.travis.yml | 10 + vendor/github.com/subosito/gotenv/CHANGELOG.md | 47 + vendor/github.com/subosito/gotenv/LICENSE | 21 + vendor/github.com/subosito/gotenv/README.md | 131 + vendor/github.com/subosito/gotenv/appveyor.yml | 9 + vendor/github.com/subosito/gotenv/gotenv.go | 265 + vendor/github.com/tdakkota/asciicheck/.gitignore | 33 + vendor/github.com/tdakkota/asciicheck/LICENSE | 21 + vendor/github.com/tdakkota/asciicheck/README.md | 44 + vendor/github.com/tdakkota/asciicheck/ascii.go | 18 + .../github.com/tdakkota/asciicheck/asciicheck.go | 49 + vendor/github.com/tdakkota/asciicheck/go.mod | 5 + vendor/github.com/tetafro/godot/.gitignore | 2 + vendor/github.com/tetafro/godot/.goreleaser.yml | 12 + vendor/github.com/tetafro/godot/LICENSE | 21 + vendor/github.com/tetafro/godot/Makefile | 11 + vendor/github.com/tetafro/godot/README.md | 54 + vendor/github.com/tetafro/godot/go.mod | 3 + vendor/github.com/tetafro/godot/godot.go | 151 + vendor/github.com/timakin/bodyclose/LICENSE | 21 + .../bodyclose/passes/bodyclose/bodyclose.go | 354 + .../github.com/tommy-muehle/go-mnd/.editorconfig | 12 + vendor/github.com/tommy-muehle/go-mnd/.gitignore | 2 + .../github.com/tommy-muehle/go-mnd/.goreleaser.yml | 30 + vendor/github.com/tommy-muehle/go-mnd/.travis.yml | 12 + vendor/github.com/tommy-muehle/go-mnd/LICENSE | 21 + vendor/github.com/tommy-muehle/go-mnd/README.md | 111 + vendor/github.com/tommy-muehle/go-mnd/analyzer.go | 91 + .../tommy-muehle/go-mnd/checks/argument.go | 107 + .../tommy-muehle/go-mnd/checks/assign.go | 66 + .../github.com/tommy-muehle/go-mnd/checks/case.go | 68 + .../tommy-muehle/go-mnd/checks/checks.go | 3 + .../tommy-muehle/go-mnd/checks/condition.go | 55 + .../tommy-muehle/go-mnd/checks/operation.go | 73 + .../tommy-muehle/go-mnd/checks/return.go | 50 + .../tommy-muehle/go-mnd/config/config.go | 84 + vendor/github.com/tommy-muehle/go-mnd/go.mod | 11 + vendor/github.com/tommy-muehle/go-mnd/go.sum | 18 + vendor/github.com/ultraware/funlen/LICENSE | 7 + vendor/github.com/ultraware/funlen/README.md | 69 + vendor/github.com/ultraware/funlen/main.go | 98 + vendor/github.com/ultraware/whitespace/LICENSE | 7 + vendor/github.com/ultraware/whitespace/README.md | 7 + vendor/github.com/ultraware/whitespace/main.go | 158 + vendor/github.com/uudashr/gocognit/LICENSE | 21 + vendor/github.com/uudashr/gocognit/README.md | 185 + vendor/github.com/uudashr/gocognit/go.mod | 3 + vendor/github.com/uudashr/gocognit/go.sum | 0 vendor/github.com/uudashr/gocognit/gocognit.go | 313 + 993 files changed, 165823 insertions(+) create mode 100644 vendor/github.com/BurntSushi/toml/.gitignore create mode 100644 vendor/github.com/BurntSushi/toml/.travis.yml create mode 100644 vendor/github.com/BurntSushi/toml/COMPATIBLE create mode 100644 vendor/github.com/BurntSushi/toml/COPYING create mode 100644 vendor/github.com/BurntSushi/toml/Makefile create mode 100644 vendor/github.com/BurntSushi/toml/README.md create mode 100644 vendor/github.com/BurntSushi/toml/decode.go create mode 100644 vendor/github.com/BurntSushi/toml/decode_meta.go create mode 100644 vendor/github.com/BurntSushi/toml/doc.go create mode 100644 vendor/github.com/BurntSushi/toml/encode.go create mode 100644 vendor/github.com/BurntSushi/toml/encoding_types.go create mode 100644 vendor/github.com/BurntSushi/toml/encoding_types_1.1.go create mode 100644 vendor/github.com/BurntSushi/toml/lex.go create mode 100644 vendor/github.com/BurntSushi/toml/parse.go create mode 100644 vendor/github.com/BurntSushi/toml/session.vim create mode 100644 vendor/github.com/BurntSushi/toml/type_check.go create mode 100644 vendor/github.com/BurntSushi/toml/type_fields.go create mode 100644 vendor/github.com/Djarvur/go-err113/.gitignore create mode 100644 vendor/github.com/Djarvur/go-err113/.golangci.yml create mode 100644 vendor/github.com/Djarvur/go-err113/.travis.yml create mode 100644 vendor/github.com/Djarvur/go-err113/LICENSE create mode 100644 vendor/github.com/Djarvur/go-err113/README.adoc create mode 100644 vendor/github.com/Djarvur/go-err113/comparison.go create mode 100644 vendor/github.com/Djarvur/go-err113/definition.go create mode 100644 vendor/github.com/Djarvur/go-err113/err113.go create mode 100644 vendor/github.com/Djarvur/go-err113/go.mod create mode 100644 vendor/github.com/Djarvur/go-err113/go.sum create mode 100644 vendor/github.com/OpenPeeDeeP/depguard/.gitignore create mode 100644 vendor/github.com/OpenPeeDeeP/depguard/LICENSE create mode 100644 vendor/github.com/OpenPeeDeeP/depguard/README.md create mode 100644 vendor/github.com/OpenPeeDeeP/depguard/depguard.go create mode 100644 vendor/github.com/OpenPeeDeeP/depguard/go.mod create mode 100644 vendor/github.com/OpenPeeDeeP/depguard/go.sum create mode 100644 vendor/github.com/bombsimon/wsl/v3/.gitignore create mode 100644 vendor/github.com/bombsimon/wsl/v3/.travis.yml create mode 100644 vendor/github.com/bombsimon/wsl/v3/LICENSE create mode 100644 vendor/github.com/bombsimon/wsl/v3/README.md create mode 100644 vendor/github.com/bombsimon/wsl/v3/go.mod create mode 100644 vendor/github.com/bombsimon/wsl/v3/go.sum create mode 100644 vendor/github.com/bombsimon/wsl/v3/wsl.go create mode 100644 vendor/github.com/davecgh/go-spew/LICENSE create mode 100644 vendor/github.com/davecgh/go-spew/spew/bypass.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/bypasssafe.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/common.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/config.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/doc.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/dump.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/format.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/spew.go create mode 100644 vendor/github.com/fatih/color/.travis.yml create mode 100644 vendor/github.com/fatih/color/Gopkg.lock create mode 100644 vendor/github.com/fatih/color/Gopkg.toml create mode 100644 vendor/github.com/fatih/color/LICENSE.md create mode 100644 vendor/github.com/fatih/color/README.md create mode 100644 vendor/github.com/fatih/color/color.go create mode 100644 vendor/github.com/fatih/color/doc.go create mode 100644 vendor/github.com/fsnotify/fsnotify/.editorconfig create mode 100644 vendor/github.com/fsnotify/fsnotify/.gitignore create mode 100644 vendor/github.com/fsnotify/fsnotify/.travis.yml create mode 100644 vendor/github.com/fsnotify/fsnotify/AUTHORS create mode 100644 vendor/github.com/fsnotify/fsnotify/CHANGELOG.md create mode 100644 vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md create mode 100644 vendor/github.com/fsnotify/fsnotify/LICENSE create mode 100644 vendor/github.com/fsnotify/fsnotify/README.md create mode 100644 vendor/github.com/fsnotify/fsnotify/fen.go create mode 100644 vendor/github.com/fsnotify/fsnotify/fsnotify.go create mode 100644 vendor/github.com/fsnotify/fsnotify/inotify.go create mode 100644 vendor/github.com/fsnotify/fsnotify/inotify_poller.go create mode 100644 vendor/github.com/fsnotify/fsnotify/kqueue.go create mode 100644 vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go create mode 100644 vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go create mode 100644 vendor/github.com/fsnotify/fsnotify/windows.go create mode 100644 vendor/github.com/go-critic/go-critic/LICENSE create mode 100644 vendor/github.com/go-critic/go-critic/checkers/appendAssign_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/argOrder_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/assignOp_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/badCall_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/boolExprSimplify_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/builtinShadow_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/captLocal_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/caseOrder_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/checkers.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/codegenComment_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/commentedOutCode_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/commentedOutImport_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/defaultCaseOrder_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/docStub_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/dupArg_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/dupBranchBody_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/dupImports_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/dupSubExpr_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/emptyFallthrough_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/emptyStringTest_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/equalFold_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/evalOrder_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/flagDeref_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/flagName_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/hexLiteral_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/hugeParam_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/ifElseChain_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/importShadow_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/indexAlloc_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/initClause_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astfind.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astflow.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astset.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/zero_value.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/mapKey_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/methodExprCall_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/nestingReduce_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/newDeref_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/nilValReturn_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/offBy1_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/paramTypeCombine_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/ptrToRefParam_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/rangeExprCopy_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/rangeValCopy_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/regexpMust_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/regexpPattern_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/singleCaseSwitch_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/sloppyLen_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/sloppyReassign_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/stringXbytes_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/switchTrue_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/truncateCmp_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/typeAssertChain_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/typeSwitchVar_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/underef_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/unlabelStmt_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/unlambda_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/unnamedResult_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/unslice_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/utils.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/valSwap_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/weakCond_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/whyNoLint_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/wrapperFunc_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/yodaStyleExpr_checker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/.travis.yml create mode 100644 vendor/github.com/go-lintpack/lintpack/LICENSE create mode 100644 vendor/github.com/go-lintpack/lintpack/Makefile create mode 100644 vendor/github.com/go-lintpack/lintpack/README.md create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/comment_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/doc_comment_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/expr_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/func_decl_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/local_comment_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/local_def_visitor.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/local_def_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/local_expr_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/stmt_list_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/stmt_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/type_expr_walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/visitor.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/walk_handler.go create mode 100644 vendor/github.com/go-lintpack/lintpack/astwalk/walker.go create mode 100644 vendor/github.com/go-lintpack/lintpack/checkers_db.go create mode 100644 vendor/github.com/go-lintpack/lintpack/context.go create mode 100644 vendor/github.com/go-lintpack/lintpack/doc.go create mode 100644 vendor/github.com/go-lintpack/lintpack/go.mod create mode 100644 vendor/github.com/go-lintpack/lintpack/go.sum create mode 100644 vendor/github.com/go-lintpack/lintpack/lintpack.go create mode 100644 vendor/github.com/go-toolsmith/astcast/.travis.yml create mode 100644 vendor/github.com/go-toolsmith/astcast/LICENSE create mode 100644 vendor/github.com/go-toolsmith/astcast/README.md create mode 100644 vendor/github.com/go-toolsmith/astcast/astcast.go create mode 100644 vendor/github.com/go-toolsmith/astcast/go.mod create mode 100644 vendor/github.com/go-toolsmith/astcast/go.sum create mode 100644 vendor/github.com/go-toolsmith/astcopy/.travis.yml create mode 100644 vendor/github.com/go-toolsmith/astcopy/LICENSE create mode 100644 vendor/github.com/go-toolsmith/astcopy/README.md create mode 100644 vendor/github.com/go-toolsmith/astcopy/astcopy.go create mode 100644 vendor/github.com/go-toolsmith/astcopy/go.mod create mode 100644 vendor/github.com/go-toolsmith/astcopy/go.sum create mode 100644 vendor/github.com/go-toolsmith/astequal/.gitignore create mode 100644 vendor/github.com/go-toolsmith/astequal/.travis.yml create mode 100644 vendor/github.com/go-toolsmith/astequal/LICENSE create mode 100644 vendor/github.com/go-toolsmith/astequal/README.md create mode 100644 vendor/github.com/go-toolsmith/astequal/astequal.go create mode 100644 vendor/github.com/go-toolsmith/astequal/go.mod create mode 100644 vendor/github.com/go-toolsmith/astfmt/.travis.yml create mode 100644 vendor/github.com/go-toolsmith/astfmt/LICENSE create mode 100644 vendor/github.com/go-toolsmith/astfmt/README.md create mode 100644 vendor/github.com/go-toolsmith/astfmt/astfmt.go create mode 100644 vendor/github.com/go-toolsmith/astfmt/go.mod create mode 100644 vendor/github.com/go-toolsmith/astfmt/go.sum create mode 100644 vendor/github.com/go-toolsmith/astp/.gitignore create mode 100644 vendor/github.com/go-toolsmith/astp/.travis.yml create mode 100644 vendor/github.com/go-toolsmith/astp/LICENSE create mode 100644 vendor/github.com/go-toolsmith/astp/README.md create mode 100644 vendor/github.com/go-toolsmith/astp/decl.go create mode 100644 vendor/github.com/go-toolsmith/astp/expr.go create mode 100644 vendor/github.com/go-toolsmith/astp/go.mod create mode 100644 vendor/github.com/go-toolsmith/astp/go.sum create mode 100644 vendor/github.com/go-toolsmith/astp/stmt.go create mode 100644 vendor/github.com/go-toolsmith/strparse/.travis.yml create mode 100644 vendor/github.com/go-toolsmith/strparse/LICENSE create mode 100644 vendor/github.com/go-toolsmith/strparse/README.md create mode 100644 vendor/github.com/go-toolsmith/strparse/go.mod create mode 100644 vendor/github.com/go-toolsmith/strparse/strparse.go create mode 100644 vendor/github.com/go-toolsmith/typep/.travis.yml create mode 100644 vendor/github.com/go-toolsmith/typep/LICENSE create mode 100644 vendor/github.com/go-toolsmith/typep/README.md create mode 100644 vendor/github.com/go-toolsmith/typep/doc.go create mode 100644 vendor/github.com/go-toolsmith/typep/go.mod create mode 100644 vendor/github.com/go-toolsmith/typep/predicates.go create mode 100644 vendor/github.com/go-toolsmith/typep/safeExpr.go create mode 100644 vendor/github.com/go-toolsmith/typep/simplePredicates.go create mode 100644 vendor/github.com/gobwas/glob/.gitignore create mode 100644 vendor/github.com/gobwas/glob/.travis.yml create mode 100644 vendor/github.com/gobwas/glob/LICENSE create mode 100644 vendor/github.com/gobwas/glob/bench.sh create mode 100644 vendor/github.com/gobwas/glob/compiler/compiler.go create mode 100644 vendor/github.com/gobwas/glob/glob.go create mode 100644 vendor/github.com/gobwas/glob/match/any.go create mode 100644 vendor/github.com/gobwas/glob/match/any_of.go create mode 100644 vendor/github.com/gobwas/glob/match/btree.go create mode 100644 vendor/github.com/gobwas/glob/match/contains.go create mode 100644 vendor/github.com/gobwas/glob/match/every_of.go create mode 100644 vendor/github.com/gobwas/glob/match/list.go create mode 100644 vendor/github.com/gobwas/glob/match/match.go create mode 100644 vendor/github.com/gobwas/glob/match/max.go create mode 100644 vendor/github.com/gobwas/glob/match/min.go create mode 100644 vendor/github.com/gobwas/glob/match/nothing.go create mode 100644 vendor/github.com/gobwas/glob/match/prefix.go create mode 100644 vendor/github.com/gobwas/glob/match/prefix_any.go create mode 100644 vendor/github.com/gobwas/glob/match/prefix_suffix.go create mode 100644 vendor/github.com/gobwas/glob/match/range.go create mode 100644 vendor/github.com/gobwas/glob/match/row.go create mode 100644 vendor/github.com/gobwas/glob/match/segments.go create mode 100644 vendor/github.com/gobwas/glob/match/single.go create mode 100644 vendor/github.com/gobwas/glob/match/suffix.go create mode 100644 vendor/github.com/gobwas/glob/match/suffix_any.go create mode 100644 vendor/github.com/gobwas/glob/match/super.go create mode 100644 vendor/github.com/gobwas/glob/match/text.go create mode 100644 vendor/github.com/gobwas/glob/readme.md create mode 100644 vendor/github.com/gobwas/glob/syntax/ast/ast.go create mode 100644 vendor/github.com/gobwas/glob/syntax/ast/parser.go create mode 100644 vendor/github.com/gobwas/glob/syntax/lexer/lexer.go create mode 100644 vendor/github.com/gobwas/glob/syntax/lexer/token.go create mode 100644 vendor/github.com/gobwas/glob/syntax/syntax.go create mode 100644 vendor/github.com/gobwas/glob/util/runes/runes.go create mode 100644 vendor/github.com/gobwas/glob/util/strings/strings.go create mode 100644 vendor/github.com/gofrs/flock/.gitignore create mode 100644 vendor/github.com/gofrs/flock/.travis.yml create mode 100644 vendor/github.com/gofrs/flock/LICENSE create mode 100644 vendor/github.com/gofrs/flock/README.md create mode 100644 vendor/github.com/gofrs/flock/appveyor.yml create mode 100644 vendor/github.com/gofrs/flock/flock.go create mode 100644 vendor/github.com/gofrs/flock/flock_unix.go create mode 100644 vendor/github.com/gofrs/flock/flock_winapi.go create mode 100644 vendor/github.com/gofrs/flock/flock_windows.go create mode 100644 vendor/github.com/gogo/protobuf/AUTHORS create mode 100644 vendor/github.com/gogo/protobuf/CONTRIBUTORS create mode 100644 vendor/github.com/gogo/protobuf/LICENSE create mode 100644 vendor/github.com/gogo/protobuf/proto/Makefile create mode 100644 vendor/github.com/gogo/protobuf/proto/clone.go create mode 100644 vendor/github.com/gogo/protobuf/proto/custom_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/decode.go create mode 100644 vendor/github.com/gogo/protobuf/proto/deprecated.go create mode 100644 vendor/github.com/gogo/protobuf/proto/discard.go create mode 100644 vendor/github.com/gogo/protobuf/proto/duration.go create mode 100644 vendor/github.com/gogo/protobuf/proto/duration_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/encode.go create mode 100644 vendor/github.com/gogo/protobuf/proto/encode_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/equal.go create mode 100644 vendor/github.com/gogo/protobuf/proto/extensions.go create mode 100644 vendor/github.com/gogo/protobuf/proto/extensions_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/lib.go create mode 100644 vendor/github.com/gogo/protobuf/proto/lib_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/message_set.go create mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_reflect.go create mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_reflect_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_unsafe.go create mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/properties.go create mode 100644 vendor/github.com/gogo/protobuf/proto/properties_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/skip_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/table_marshal.go create mode 100644 vendor/github.com/gogo/protobuf/proto/table_marshal_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/table_merge.go create mode 100644 vendor/github.com/gogo/protobuf/proto/table_unmarshal.go create mode 100644 vendor/github.com/gogo/protobuf/proto/table_unmarshal_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/text.go create mode 100644 vendor/github.com/gogo/protobuf/proto/text_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/text_parser.go create mode 100644 vendor/github.com/gogo/protobuf/proto/timestamp.go create mode 100644 vendor/github.com/gogo/protobuf/proto/timestamp_gogo.go create mode 100644 vendor/github.com/gogo/protobuf/proto/wrappers.go create mode 100644 vendor/github.com/gogo/protobuf/proto/wrappers_gogo.go create mode 100644 vendor/github.com/golangci/check/LICENSE create mode 100644 vendor/github.com/golangci/check/cmd/structcheck/structcheck.go create mode 100644 vendor/github.com/golangci/check/cmd/varcheck/varcheck.go create mode 100644 vendor/github.com/golangci/dupl/.travis.yml create mode 100644 vendor/github.com/golangci/dupl/LICENSE create mode 100644 vendor/github.com/golangci/dupl/README.md create mode 100644 vendor/github.com/golangci/dupl/job/buildtree.go create mode 100644 vendor/github.com/golangci/dupl/job/parse.go create mode 100644 vendor/github.com/golangci/dupl/main.go create mode 100644 vendor/github.com/golangci/dupl/printer/html.go create mode 100644 vendor/github.com/golangci/dupl/printer/plumbing.go create mode 100644 vendor/github.com/golangci/dupl/printer/printer.go create mode 100644 vendor/github.com/golangci/dupl/printer/text.go create mode 100644 vendor/github.com/golangci/dupl/suffixtree/dupl.go create mode 100644 vendor/github.com/golangci/dupl/suffixtree/suffixtree.go create mode 100644 vendor/github.com/golangci/dupl/syntax/golang/golang.go create mode 100644 vendor/github.com/golangci/dupl/syntax/syntax.go create mode 100644 vendor/github.com/golangci/errcheck/LICENSE create mode 100644 vendor/github.com/golangci/errcheck/golangci/golangci.go create mode 100644 vendor/github.com/golangci/errcheck/internal/errcheck/errcheck.go create mode 100644 vendor/github.com/golangci/go-misc/LICENSE create mode 100644 vendor/github.com/golangci/go-misc/deadcode/README.md create mode 100644 vendor/github.com/golangci/go-misc/deadcode/deadcode.go create mode 100644 vendor/github.com/golangci/goconst/LICENSE create mode 100644 vendor/github.com/golangci/goconst/README.md create mode 100644 vendor/github.com/golangci/goconst/parser.go create mode 100644 vendor/github.com/golangci/goconst/visitor.go create mode 100644 vendor/github.com/golangci/gocyclo/CONTRIBUTORS create mode 100644 vendor/github.com/golangci/gocyclo/LICENSE create mode 100644 vendor/github.com/golangci/gocyclo/pkg/gocyclo/gocyclo.go create mode 100644 vendor/github.com/golangci/gofmt/gofmt/LICENSE create mode 100644 vendor/github.com/golangci/gofmt/gofmt/doc.go create mode 100644 vendor/github.com/golangci/gofmt/gofmt/gofmt.go create mode 100644 vendor/github.com/golangci/gofmt/gofmt/golangci.go create mode 100644 vendor/github.com/golangci/gofmt/gofmt/internal.go create mode 100644 vendor/github.com/golangci/gofmt/gofmt/rewrite.go create mode 100644 vendor/github.com/golangci/gofmt/gofmt/simplify.go create mode 100644 vendor/github.com/golangci/gofmt/goimports/LICENSE create mode 100644 vendor/github.com/golangci/gofmt/goimports/goimports.go create mode 100644 vendor/github.com/golangci/gofmt/goimports/golangci.go create mode 100644 vendor/github.com/golangci/golangci-lint/LICENSE create mode 100644 vendor/github.com/golangci/golangci-lint/cmd/golangci-lint/main.go create mode 100644 vendor/github.com/golangci/golangci-lint/cmd/golangci-lint/mod_version.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/cache/cache.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/cache/default.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/cache/hash.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/errorutil/errors.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/pkgcache/pkgcache.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/renameio/renameio.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/robustio/robustio.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_darwin.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_flaky.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_other.go create mode 100644 vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_windows.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/commands/cache.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/commands/completion.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/commands/config.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/commands/executor.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/commands/help.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/commands/linters.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/commands/root.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/commands/run.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/commands/version.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/config/config.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/config/config_gocritic.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/config/reader.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/exitcodes/exitcodes.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/fsutils/filecache.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/fsutils/fsutils.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/fsutils/linecache.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/asciicheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/bodyclose.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/deadcode.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/depguard.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/dogsled.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/dupl.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/errcheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/funlen.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/adapters.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/issue.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/linter.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load/guard.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/metalinter.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gochecknoglobals.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gochecknoinits.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gocognit.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goconst.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gocritic.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gocyclo.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/godot.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/godox.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goerr113.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gofmt.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gofmt_common.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goimports.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/golint.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gomnd.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gomodguard.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/goprintffuncname.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gosec.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/gosimple.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/govet.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/ineffassign.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/interfacer.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/lll.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/maligned.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/megacheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/misspell.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/nakedret.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/nestif.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint/README.md create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint/nolintlint.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/prealloc.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/rowerrcheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/scopelint.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/staticcheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/structcheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/stylecheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/testpackage.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/typecheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/unconvert.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/unparam.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/unused.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/util.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/varcheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/whitespace.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/wsl.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/goutil/env.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/lint/linter/config.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/lint/linter/context.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/lint/linter/linter.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/enabled_set.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/manager.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/validator.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/lint/load.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/lint/runner.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/logutils/log.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/logutils/logutils.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/logutils/mock.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/logutils/out.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/logutils/stderr_log.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/packages/errors.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/packages/skip.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/packages/util.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/printers/checkstyle.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/printers/codeclimate.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/printers/github.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/printers/json.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/printers/junitxml.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/printers/printer.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/printers/tab.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/printers/text.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/report/data.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/report/log.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/issue.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/autogenerated_exclude.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/cgo.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/diff.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/exclude.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/exclude_rules.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/filename_unadjuster.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/fixer.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/identifier_marker.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_from_linter.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_per_file_from_linter.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_same_issues.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/nolint.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/path_prettifier.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/path_shortener.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/processor.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/skip_dirs.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/skip_files.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/source_code.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/uniq_by_line.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/result/processors/utils.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go create mode 100644 vendor/github.com/golangci/ineffassign/.gitignore create mode 100644 vendor/github.com/golangci/ineffassign/LICENSE create mode 100644 vendor/github.com/golangci/ineffassign/README.md create mode 100644 vendor/github.com/golangci/ineffassign/bugs create mode 100644 vendor/github.com/golangci/ineffassign/ineffassign.go create mode 100644 vendor/github.com/golangci/ineffassign/list create mode 100644 vendor/github.com/golangci/ineffassign/liststd create mode 100644 vendor/github.com/golangci/lint-1/.travis.yml create mode 100644 vendor/github.com/golangci/lint-1/CONTRIBUTING.md create mode 100644 vendor/github.com/golangci/lint-1/LICENSE create mode 100644 vendor/github.com/golangci/lint-1/README.md create mode 100644 vendor/github.com/golangci/lint-1/go.mod create mode 100644 vendor/github.com/golangci/lint-1/go.sum create mode 100644 vendor/github.com/golangci/lint-1/lint.go create mode 100644 vendor/github.com/golangci/maligned/LICENSE create mode 100644 vendor/github.com/golangci/maligned/README create mode 100644 vendor/github.com/golangci/maligned/maligned.go create mode 100644 vendor/github.com/golangci/misspell/.gitignore create mode 100644 vendor/github.com/golangci/misspell/.travis.yml create mode 100644 vendor/github.com/golangci/misspell/Dockerfile create mode 100644 vendor/github.com/golangci/misspell/Gopkg.lock create mode 100644 vendor/github.com/golangci/misspell/Gopkg.toml create mode 100644 vendor/github.com/golangci/misspell/LICENSE create mode 100644 vendor/github.com/golangci/misspell/Makefile create mode 100644 vendor/github.com/golangci/misspell/README.md create mode 100644 vendor/github.com/golangci/misspell/RELEASE-HOWTO.md create mode 100644 vendor/github.com/golangci/misspell/ascii.go create mode 100644 vendor/github.com/golangci/misspell/case.go create mode 100644 vendor/github.com/golangci/misspell/goreleaser.yml create mode 100644 vendor/github.com/golangci/misspell/install-misspell.sh create mode 100644 vendor/github.com/golangci/misspell/legal.go create mode 100644 vendor/github.com/golangci/misspell/mime.go create mode 100644 vendor/github.com/golangci/misspell/notwords.go create mode 100644 vendor/github.com/golangci/misspell/replace.go create mode 100644 vendor/github.com/golangci/misspell/stringreplacer.go create mode 100644 vendor/github.com/golangci/misspell/stringreplacer_test.gox create mode 100644 vendor/github.com/golangci/misspell/url.go create mode 100644 vendor/github.com/golangci/misspell/words.go create mode 100644 vendor/github.com/golangci/prealloc/LICENSE create mode 100644 vendor/github.com/golangci/prealloc/README.md create mode 100644 vendor/github.com/golangci/prealloc/import.go create mode 100644 vendor/github.com/golangci/prealloc/prealloc.go create mode 100644 vendor/github.com/golangci/revgrep/.gitignore create mode 100644 vendor/github.com/golangci/revgrep/.travis.yml create mode 100644 vendor/github.com/golangci/revgrep/LICENSE create mode 100644 vendor/github.com/golangci/revgrep/README.md create mode 100644 vendor/github.com/golangci/revgrep/revgrep.go create mode 100644 vendor/github.com/golangci/unconvert/LICENSE create mode 100644 vendor/github.com/golangci/unconvert/README create mode 100644 vendor/github.com/golangci/unconvert/unconvert.go create mode 100644 vendor/github.com/gostaticanalysis/analysisutil/LICENSE create mode 100644 vendor/github.com/gostaticanalysis/analysisutil/README.md create mode 100644 vendor/github.com/gostaticanalysis/analysisutil/file.go create mode 100644 vendor/github.com/gostaticanalysis/analysisutil/go.mod create mode 100644 vendor/github.com/gostaticanalysis/analysisutil/go.sum create mode 100644 vendor/github.com/gostaticanalysis/analysisutil/pkg.go create mode 100644 vendor/github.com/gostaticanalysis/analysisutil/ssa.go create mode 100644 vendor/github.com/hashicorp/hcl/.gitignore create mode 100644 vendor/github.com/hashicorp/hcl/.travis.yml create mode 100644 vendor/github.com/hashicorp/hcl/LICENSE create mode 100644 vendor/github.com/hashicorp/hcl/Makefile create mode 100644 vendor/github.com/hashicorp/hcl/README.md create mode 100644 vendor/github.com/hashicorp/hcl/appveyor.yml create mode 100644 vendor/github.com/hashicorp/hcl/decoder.go create mode 100644 vendor/github.com/hashicorp/hcl/go.mod create mode 100644 vendor/github.com/hashicorp/hcl/go.sum create mode 100644 vendor/github.com/hashicorp/hcl/hcl.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/ast/ast.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/ast/walk.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/parser/error.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/parser/parser.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/printer/printer.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/token/position.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/token/token.go create mode 100644 vendor/github.com/hashicorp/hcl/json/parser/flatten.go create mode 100644 vendor/github.com/hashicorp/hcl/json/parser/parser.go create mode 100644 vendor/github.com/hashicorp/hcl/json/scanner/scanner.go create mode 100644 vendor/github.com/hashicorp/hcl/json/token/position.go create mode 100644 vendor/github.com/hashicorp/hcl/json/token/token.go create mode 100644 vendor/github.com/hashicorp/hcl/lex.go create mode 100644 vendor/github.com/hashicorp/hcl/parse.go create mode 100644 vendor/github.com/inconshreveable/mousetrap/LICENSE create mode 100644 vendor/github.com/inconshreveable/mousetrap/README.md create mode 100644 vendor/github.com/inconshreveable/mousetrap/trap_others.go create mode 100644 vendor/github.com/inconshreveable/mousetrap/trap_windows.go create mode 100644 vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go create mode 100644 vendor/github.com/jingyugao/rowserrcheck/LICENSE create mode 100644 vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go create mode 100644 vendor/github.com/jirfag/go-printf-func-name/pkg/analyzer/analyzer.go create mode 100644 vendor/github.com/kisielk/gotool/.travis.yml create mode 100644 vendor/github.com/kisielk/gotool/LEGAL create mode 100644 vendor/github.com/kisielk/gotool/LICENSE create mode 100644 vendor/github.com/kisielk/gotool/README.md create mode 100644 vendor/github.com/kisielk/gotool/go.mod create mode 100644 vendor/github.com/kisielk/gotool/go13.go create mode 100644 vendor/github.com/kisielk/gotool/go14-15.go create mode 100644 vendor/github.com/kisielk/gotool/go16-18.go create mode 100644 vendor/github.com/kisielk/gotool/internal/load/path.go create mode 100644 vendor/github.com/kisielk/gotool/internal/load/pkg.go create mode 100644 vendor/github.com/kisielk/gotool/internal/load/search.go create mode 100644 vendor/github.com/kisielk/gotool/match.go create mode 100644 vendor/github.com/kisielk/gotool/match18.go create mode 100644 vendor/github.com/kisielk/gotool/tool.go create mode 100644 vendor/github.com/konsorten/go-windows-terminal-sequences/LICENSE create mode 100644 vendor/github.com/konsorten/go-windows-terminal-sequences/README.md create mode 100644 vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod create mode 100644 vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go create mode 100644 vendor/github.com/magiconair/properties/.gitignore create mode 100644 vendor/github.com/magiconair/properties/.travis.yml create mode 100644 vendor/github.com/magiconair/properties/CHANGELOG.md create mode 100644 vendor/github.com/magiconair/properties/LICENSE create mode 100644 vendor/github.com/magiconair/properties/README.md create mode 100644 vendor/github.com/magiconair/properties/decode.go create mode 100644 vendor/github.com/magiconair/properties/doc.go create mode 100644 vendor/github.com/magiconair/properties/go.mod create mode 100644 vendor/github.com/magiconair/properties/integrate.go create mode 100644 vendor/github.com/magiconair/properties/lex.go create mode 100644 vendor/github.com/magiconair/properties/load.go create mode 100644 vendor/github.com/magiconair/properties/parser.go create mode 100644 vendor/github.com/magiconair/properties/properties.go create mode 100644 vendor/github.com/magiconair/properties/rangecheck.go create mode 100644 vendor/github.com/maratori/testpackage/LICENSE create mode 100644 vendor/github.com/maratori/testpackage/pkg/testpackage/testpackage.go create mode 100644 vendor/github.com/matoous/godox/.gitignore create mode 100644 vendor/github.com/matoous/godox/.golangci.yml create mode 100644 vendor/github.com/matoous/godox/.revive.toml create mode 100644 vendor/github.com/matoous/godox/LICENSE create mode 100644 vendor/github.com/matoous/godox/README.md create mode 100644 vendor/github.com/matoous/godox/go.mod create mode 100644 vendor/github.com/matoous/godox/go.sum create mode 100644 vendor/github.com/matoous/godox/godox.go create mode 100644 vendor/github.com/mattn/go-colorable/.travis.yml create mode 100644 vendor/github.com/mattn/go-colorable/LICENSE create mode 100644 vendor/github.com/mattn/go-colorable/README.md create mode 100644 vendor/github.com/mattn/go-colorable/colorable_appengine.go create mode 100644 vendor/github.com/mattn/go-colorable/colorable_others.go create mode 100644 vendor/github.com/mattn/go-colorable/colorable_windows.go create mode 100644 vendor/github.com/mattn/go-colorable/go.mod create mode 100644 vendor/github.com/mattn/go-colorable/go.sum create mode 100644 vendor/github.com/mattn/go-colorable/noncolorable.go create mode 100644 vendor/github.com/mattn/go-isatty/.travis.yml create mode 100644 vendor/github.com/mattn/go-isatty/LICENSE create mode 100644 vendor/github.com/mattn/go-isatty/README.md create mode 100644 vendor/github.com/mattn/go-isatty/doc.go create mode 100644 vendor/github.com/mattn/go-isatty/go.mod create mode 100644 vendor/github.com/mattn/go-isatty/go.sum create mode 100644 vendor/github.com/mattn/go-isatty/isatty_android.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_bsd.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_others.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_solaris.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_tcgets.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_windows.go create mode 100644 vendor/github.com/mitchellh/go-homedir/LICENSE create mode 100644 vendor/github.com/mitchellh/go-homedir/README.md create mode 100644 vendor/github.com/mitchellh/go-homedir/go.mod create mode 100644 vendor/github.com/mitchellh/go-homedir/homedir.go create mode 100644 vendor/github.com/mitchellh/mapstructure/.travis.yml create mode 100644 vendor/github.com/mitchellh/mapstructure/CHANGELOG.md create mode 100644 vendor/github.com/mitchellh/mapstructure/LICENSE create mode 100644 vendor/github.com/mitchellh/mapstructure/README.md create mode 100644 vendor/github.com/mitchellh/mapstructure/decode_hooks.go create mode 100644 vendor/github.com/mitchellh/mapstructure/error.go create mode 100644 vendor/github.com/mitchellh/mapstructure/go.mod create mode 100644 vendor/github.com/mitchellh/mapstructure/mapstructure.go create mode 100644 vendor/github.com/nakabonne/nestif/.gitignore create mode 100644 vendor/github.com/nakabonne/nestif/LICENSE create mode 100644 vendor/github.com/nakabonne/nestif/README.md create mode 100644 vendor/github.com/nakabonne/nestif/go.mod create mode 100644 vendor/github.com/nakabonne/nestif/go.sum create mode 100644 vendor/github.com/nakabonne/nestif/nestif.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/.gitignore create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/Gopkg.lock create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/Gopkg.toml create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/LICENSE.txt create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/Makefile create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/README.md create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/adjacency/adjcmartix.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/data/bindata.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/entropy/entropyCalculator.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/frequency/frequency.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/match/match.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/matching/dateMatchers.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/matching/dictionaryMatch.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/matching/leet.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/matching/matching.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/matching/repeatMatch.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/matching/sequenceMatch.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/matching/spatialMatch.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/scoring/scoring.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/utils/math/mathutils.go create mode 100644 vendor/github.com/nbutton23/zxcvbn-go/zxcvbn.go create mode 100644 vendor/github.com/pelletier/go-toml/.gitignore create mode 100644 vendor/github.com/pelletier/go-toml/.travis.yml create mode 100644 vendor/github.com/pelletier/go-toml/LICENSE create mode 100644 vendor/github.com/pelletier/go-toml/README.md create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.json create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.sh create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.toml create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.yml create mode 100644 vendor/github.com/pelletier/go-toml/doc.go create mode 100644 vendor/github.com/pelletier/go-toml/example-crlf.toml create mode 100644 vendor/github.com/pelletier/go-toml/example.toml create mode 100644 vendor/github.com/pelletier/go-toml/fuzz.go create mode 100644 vendor/github.com/pelletier/go-toml/fuzz.sh create mode 100644 vendor/github.com/pelletier/go-toml/keysparsing.go create mode 100644 vendor/github.com/pelletier/go-toml/lexer.go create mode 100644 vendor/github.com/pelletier/go-toml/marshal.go create mode 100644 vendor/github.com/pelletier/go-toml/marshal_test.toml create mode 100644 vendor/github.com/pelletier/go-toml/parser.go create mode 100644 vendor/github.com/pelletier/go-toml/position.go create mode 100644 vendor/github.com/pelletier/go-toml/test.sh create mode 100644 vendor/github.com/pelletier/go-toml/token.go create mode 100644 vendor/github.com/pelletier/go-toml/toml.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_create.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_write.go create mode 100644 vendor/github.com/pkg/errors/.gitignore create mode 100644 vendor/github.com/pkg/errors/.travis.yml create mode 100644 vendor/github.com/pkg/errors/LICENSE create mode 100644 vendor/github.com/pkg/errors/README.md create mode 100644 vendor/github.com/pkg/errors/appveyor.yml create mode 100644 vendor/github.com/pkg/errors/errors.go create mode 100644 vendor/github.com/pkg/errors/stack.go create mode 100644 vendor/github.com/pmezard/go-difflib/LICENSE create mode 100644 vendor/github.com/pmezard/go-difflib/difflib/difflib.go create mode 100644 vendor/github.com/ryancurrah/gomodguard/.dockerignore create mode 100644 vendor/github.com/ryancurrah/gomodguard/.gitignore create mode 100644 vendor/github.com/ryancurrah/gomodguard/.gomodguard.yaml create mode 100644 vendor/github.com/ryancurrah/gomodguard/.goreleaser.yml create mode 100644 vendor/github.com/ryancurrah/gomodguard/Dockerfile create mode 100644 vendor/github.com/ryancurrah/gomodguard/Dockerfile.goreleaser create mode 100644 vendor/github.com/ryancurrah/gomodguard/LICENSE create mode 100644 vendor/github.com/ryancurrah/gomodguard/Makefile create mode 100644 vendor/github.com/ryancurrah/gomodguard/README.md create mode 100644 vendor/github.com/ryancurrah/gomodguard/VERSION create mode 100644 vendor/github.com/ryancurrah/gomodguard/go.mod create mode 100644 vendor/github.com/ryancurrah/gomodguard/go.sum create mode 100644 vendor/github.com/ryancurrah/gomodguard/gomodguard.go create mode 100644 vendor/github.com/securego/gosec/v2/.gitignore create mode 100644 vendor/github.com/securego/gosec/v2/.goreleaser.yml create mode 100644 vendor/github.com/securego/gosec/v2/Dockerfile create mode 100644 vendor/github.com/securego/gosec/v2/LICENSE.txt create mode 100644 vendor/github.com/securego/gosec/v2/Makefile create mode 100644 vendor/github.com/securego/gosec/v2/README.md create mode 100644 vendor/github.com/securego/gosec/v2/action.yml create mode 100644 vendor/github.com/securego/gosec/v2/analyzer.go create mode 100644 vendor/github.com/securego/gosec/v2/call_list.go create mode 100644 vendor/github.com/securego/gosec/v2/config.go create mode 100644 vendor/github.com/securego/gosec/v2/errors.go create mode 100644 vendor/github.com/securego/gosec/v2/go.mod create mode 100644 vendor/github.com/securego/gosec/v2/go.sum create mode 100644 vendor/github.com/securego/gosec/v2/helpers.go create mode 100644 vendor/github.com/securego/gosec/v2/import_tracker.go create mode 100644 vendor/github.com/securego/gosec/v2/install.sh create mode 100644 vendor/github.com/securego/gosec/v2/issue.go create mode 100644 vendor/github.com/securego/gosec/v2/renovate.json create mode 100644 vendor/github.com/securego/gosec/v2/resolve.go create mode 100644 vendor/github.com/securego/gosec/v2/rule.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/archive.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/bad_defer.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/bind.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/blacklist.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/decompression-bomb.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/errors.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/fileperms.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/implicit_aliasing.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/integer_overflow.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/pprof.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/rand.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/readfile.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/rsa.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/rulelist.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/sql.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/ssh.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/ssrf.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/subproc.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/tempfiles.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/templates.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/tls.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/tls_config.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/unsafe.go create mode 100644 vendor/github.com/securego/gosec/v2/rules/weakcrypto.go create mode 100644 vendor/github.com/sirupsen/logrus/.gitignore create mode 100644 vendor/github.com/sirupsen/logrus/.travis.yml create mode 100644 vendor/github.com/sirupsen/logrus/CHANGELOG.md create mode 100644 vendor/github.com/sirupsen/logrus/LICENSE create mode 100644 vendor/github.com/sirupsen/logrus/README.md create mode 100644 vendor/github.com/sirupsen/logrus/alt_exit.go create mode 100644 vendor/github.com/sirupsen/logrus/appveyor.yml create mode 100644 vendor/github.com/sirupsen/logrus/doc.go create mode 100644 vendor/github.com/sirupsen/logrus/entry.go create mode 100644 vendor/github.com/sirupsen/logrus/exported.go create mode 100644 vendor/github.com/sirupsen/logrus/formatter.go create mode 100644 vendor/github.com/sirupsen/logrus/go.mod create mode 100644 vendor/github.com/sirupsen/logrus/go.sum create mode 100644 vendor/github.com/sirupsen/logrus/hooks.go create mode 100644 vendor/github.com/sirupsen/logrus/json_formatter.go create mode 100644 vendor/github.com/sirupsen/logrus/logger.go create mode 100644 vendor/github.com/sirupsen/logrus/logrus.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_appengine.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_bsd.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_solaris.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_unix.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_windows.go create mode 100644 vendor/github.com/sirupsen/logrus/text_formatter.go create mode 100644 vendor/github.com/sirupsen/logrus/writer.go create mode 100644 vendor/github.com/sourcegraph/go-diff/LICENSE create mode 100644 vendor/github.com/sourcegraph/go-diff/diff/diff.go create mode 100644 vendor/github.com/sourcegraph/go-diff/diff/diff.pb.go create mode 100644 vendor/github.com/sourcegraph/go-diff/diff/diff.proto create mode 100644 vendor/github.com/sourcegraph/go-diff/diff/doc.go create mode 100644 vendor/github.com/sourcegraph/go-diff/diff/parse.go create mode 100644 vendor/github.com/sourcegraph/go-diff/diff/print.go create mode 100644 vendor/github.com/sourcegraph/go-diff/diff/reader_util.go create mode 100644 vendor/github.com/spf13/afero/.travis.yml create mode 100644 vendor/github.com/spf13/afero/LICENSE.txt create mode 100644 vendor/github.com/spf13/afero/README.md create mode 100644 vendor/github.com/spf13/afero/afero.go create mode 100644 vendor/github.com/spf13/afero/appveyor.yml create mode 100644 vendor/github.com/spf13/afero/basepath.go create mode 100644 vendor/github.com/spf13/afero/cacheOnReadFs.go create mode 100644 vendor/github.com/spf13/afero/const_bsds.go create mode 100644 vendor/github.com/spf13/afero/const_win_unix.go create mode 100644 vendor/github.com/spf13/afero/copyOnWriteFs.go create mode 100644 vendor/github.com/spf13/afero/go.mod create mode 100644 vendor/github.com/spf13/afero/httpFs.go create mode 100644 vendor/github.com/spf13/afero/ioutil.go create mode 100644 vendor/github.com/spf13/afero/lstater.go create mode 100644 vendor/github.com/spf13/afero/match.go create mode 100644 vendor/github.com/spf13/afero/mem/dir.go create mode 100644 vendor/github.com/spf13/afero/mem/dirmap.go create mode 100644 vendor/github.com/spf13/afero/mem/file.go create mode 100644 vendor/github.com/spf13/afero/memmap.go create mode 100644 vendor/github.com/spf13/afero/os.go create mode 100644 vendor/github.com/spf13/afero/path.go create mode 100644 vendor/github.com/spf13/afero/readonlyfs.go create mode 100644 vendor/github.com/spf13/afero/regexpfs.go create mode 100644 vendor/github.com/spf13/afero/unionFile.go create mode 100644 vendor/github.com/spf13/afero/util.go create mode 100644 vendor/github.com/spf13/cast/.gitignore create mode 100644 vendor/github.com/spf13/cast/.travis.yml create mode 100644 vendor/github.com/spf13/cast/LICENSE create mode 100644 vendor/github.com/spf13/cast/Makefile create mode 100644 vendor/github.com/spf13/cast/README.md create mode 100644 vendor/github.com/spf13/cast/cast.go create mode 100644 vendor/github.com/spf13/cast/caste.go create mode 100644 vendor/github.com/spf13/cast/go.mod create mode 100644 vendor/github.com/spf13/cast/go.sum create mode 100644 vendor/github.com/spf13/cobra/.gitignore create mode 100644 vendor/github.com/spf13/cobra/.mailmap create mode 100644 vendor/github.com/spf13/cobra/.travis.yml create mode 100644 vendor/github.com/spf13/cobra/LICENSE.txt create mode 100644 vendor/github.com/spf13/cobra/README.md create mode 100644 vendor/github.com/spf13/cobra/args.go create mode 100644 vendor/github.com/spf13/cobra/bash_completions.go create mode 100644 vendor/github.com/spf13/cobra/bash_completions.md create mode 100644 vendor/github.com/spf13/cobra/cobra.go create mode 100644 vendor/github.com/spf13/cobra/command.go create mode 100644 vendor/github.com/spf13/cobra/command_notwin.go create mode 100644 vendor/github.com/spf13/cobra/command_win.go create mode 100644 vendor/github.com/spf13/cobra/go.mod create mode 100644 vendor/github.com/spf13/cobra/go.sum create mode 100644 vendor/github.com/spf13/cobra/powershell_completions.go create mode 100644 vendor/github.com/spf13/cobra/powershell_completions.md create mode 100644 vendor/github.com/spf13/cobra/shell_completions.go create mode 100644 vendor/github.com/spf13/cobra/zsh_completions.go create mode 100644 vendor/github.com/spf13/cobra/zsh_completions.md create mode 100644 vendor/github.com/spf13/jwalterweatherman/.gitignore create mode 100644 vendor/github.com/spf13/jwalterweatherman/LICENSE create mode 100644 vendor/github.com/spf13/jwalterweatherman/README.md create mode 100644 vendor/github.com/spf13/jwalterweatherman/default_notepad.go create mode 100644 vendor/github.com/spf13/jwalterweatherman/go.mod create mode 100644 vendor/github.com/spf13/jwalterweatherman/log_counter.go create mode 100644 vendor/github.com/spf13/jwalterweatherman/notepad.go create mode 100644 vendor/github.com/spf13/pflag/.gitignore create mode 100644 vendor/github.com/spf13/pflag/.travis.yml create mode 100644 vendor/github.com/spf13/pflag/LICENSE create mode 100644 vendor/github.com/spf13/pflag/README.md create mode 100644 vendor/github.com/spf13/pflag/bool.go create mode 100644 vendor/github.com/spf13/pflag/bool_slice.go create mode 100644 vendor/github.com/spf13/pflag/bytes.go create mode 100644 vendor/github.com/spf13/pflag/count.go create mode 100644 vendor/github.com/spf13/pflag/duration.go create mode 100644 vendor/github.com/spf13/pflag/duration_slice.go create mode 100644 vendor/github.com/spf13/pflag/flag.go create mode 100644 vendor/github.com/spf13/pflag/float32.go create mode 100644 vendor/github.com/spf13/pflag/float32_slice.go create mode 100644 vendor/github.com/spf13/pflag/float64.go create mode 100644 vendor/github.com/spf13/pflag/float64_slice.go create mode 100644 vendor/github.com/spf13/pflag/go.mod create mode 100644 vendor/github.com/spf13/pflag/go.sum create mode 100644 vendor/github.com/spf13/pflag/golangflag.go create mode 100644 vendor/github.com/spf13/pflag/int.go create mode 100644 vendor/github.com/spf13/pflag/int16.go create mode 100644 vendor/github.com/spf13/pflag/int32.go create mode 100644 vendor/github.com/spf13/pflag/int32_slice.go create mode 100644 vendor/github.com/spf13/pflag/int64.go create mode 100644 vendor/github.com/spf13/pflag/int64_slice.go create mode 100644 vendor/github.com/spf13/pflag/int8.go create mode 100644 vendor/github.com/spf13/pflag/int_slice.go create mode 100644 vendor/github.com/spf13/pflag/ip.go create mode 100644 vendor/github.com/spf13/pflag/ip_slice.go create mode 100644 vendor/github.com/spf13/pflag/ipmask.go create mode 100644 vendor/github.com/spf13/pflag/ipnet.go create mode 100644 vendor/github.com/spf13/pflag/string.go create mode 100644 vendor/github.com/spf13/pflag/string_array.go create mode 100644 vendor/github.com/spf13/pflag/string_slice.go create mode 100644 vendor/github.com/spf13/pflag/string_to_int.go create mode 100644 vendor/github.com/spf13/pflag/string_to_int64.go create mode 100644 vendor/github.com/spf13/pflag/string_to_string.go create mode 100644 vendor/github.com/spf13/pflag/uint.go create mode 100644 vendor/github.com/spf13/pflag/uint16.go create mode 100644 vendor/github.com/spf13/pflag/uint32.go create mode 100644 vendor/github.com/spf13/pflag/uint64.go create mode 100644 vendor/github.com/spf13/pflag/uint8.go create mode 100644 vendor/github.com/spf13/pflag/uint_slice.go create mode 100644 vendor/github.com/spf13/viper/.gitignore create mode 100644 vendor/github.com/spf13/viper/.golangci.yml create mode 100644 vendor/github.com/spf13/viper/.travis.yml create mode 100644 vendor/github.com/spf13/viper/LICENSE create mode 100644 vendor/github.com/spf13/viper/Makefile create mode 100644 vendor/github.com/spf13/viper/README.md create mode 100644 vendor/github.com/spf13/viper/flags.go create mode 100644 vendor/github.com/spf13/viper/go.mod create mode 100644 vendor/github.com/spf13/viper/go.sum create mode 100644 vendor/github.com/spf13/viper/util.go create mode 100644 vendor/github.com/spf13/viper/viper.go create mode 100644 vendor/github.com/stretchr/objx/.codeclimate.yml create mode 100644 vendor/github.com/stretchr/objx/.gitignore create mode 100644 vendor/github.com/stretchr/objx/.travis.yml create mode 100644 vendor/github.com/stretchr/objx/Gopkg.lock create mode 100644 vendor/github.com/stretchr/objx/Gopkg.toml create mode 100644 vendor/github.com/stretchr/objx/LICENSE create mode 100644 vendor/github.com/stretchr/objx/README.md create mode 100644 vendor/github.com/stretchr/objx/Taskfile.yml create mode 100644 vendor/github.com/stretchr/objx/accessors.go create mode 100644 vendor/github.com/stretchr/objx/constants.go create mode 100644 vendor/github.com/stretchr/objx/conversions.go create mode 100644 vendor/github.com/stretchr/objx/doc.go create mode 100644 vendor/github.com/stretchr/objx/map.go create mode 100644 vendor/github.com/stretchr/objx/mutations.go create mode 100644 vendor/github.com/stretchr/objx/security.go create mode 100644 vendor/github.com/stretchr/objx/tests.go create mode 100644 vendor/github.com/stretchr/objx/type_specific_codegen.go create mode 100644 vendor/github.com/stretchr/objx/value.go create mode 100644 vendor/github.com/stretchr/testify/LICENSE create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_format.go create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_forward.go create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_order.go create mode 100644 vendor/github.com/stretchr/testify/assert/assertions.go create mode 100644 vendor/github.com/stretchr/testify/assert/doc.go create mode 100644 vendor/github.com/stretchr/testify/assert/errors.go create mode 100644 vendor/github.com/stretchr/testify/assert/forward_assertions.go create mode 100644 vendor/github.com/stretchr/testify/assert/http_assertions.go create mode 100644 vendor/github.com/stretchr/testify/mock/doc.go create mode 100644 vendor/github.com/stretchr/testify/mock/mock.go create mode 100644 vendor/github.com/subosito/gotenv/.env create mode 100644 vendor/github.com/subosito/gotenv/.env.invalid create mode 100644 vendor/github.com/subosito/gotenv/.gitignore create mode 100644 vendor/github.com/subosito/gotenv/.travis.yml create mode 100644 vendor/github.com/subosito/gotenv/CHANGELOG.md create mode 100644 vendor/github.com/subosito/gotenv/LICENSE create mode 100644 vendor/github.com/subosito/gotenv/README.md create mode 100644 vendor/github.com/subosito/gotenv/appveyor.yml create mode 100644 vendor/github.com/subosito/gotenv/gotenv.go create mode 100644 vendor/github.com/tdakkota/asciicheck/.gitignore create mode 100644 vendor/github.com/tdakkota/asciicheck/LICENSE create mode 100644 vendor/github.com/tdakkota/asciicheck/README.md create mode 100644 vendor/github.com/tdakkota/asciicheck/ascii.go create mode 100644 vendor/github.com/tdakkota/asciicheck/asciicheck.go create mode 100644 vendor/github.com/tdakkota/asciicheck/go.mod create mode 100644 vendor/github.com/tetafro/godot/.gitignore create mode 100644 vendor/github.com/tetafro/godot/.goreleaser.yml create mode 100644 vendor/github.com/tetafro/godot/LICENSE create mode 100644 vendor/github.com/tetafro/godot/Makefile create mode 100644 vendor/github.com/tetafro/godot/README.md create mode 100644 vendor/github.com/tetafro/godot/go.mod create mode 100644 vendor/github.com/tetafro/godot/godot.go create mode 100644 vendor/github.com/timakin/bodyclose/LICENSE create mode 100644 vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/.editorconfig create mode 100644 vendor/github.com/tommy-muehle/go-mnd/.gitignore create mode 100644 vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml create mode 100644 vendor/github.com/tommy-muehle/go-mnd/.travis.yml create mode 100644 vendor/github.com/tommy-muehle/go-mnd/LICENSE create mode 100644 vendor/github.com/tommy-muehle/go-mnd/README.md create mode 100644 vendor/github.com/tommy-muehle/go-mnd/analyzer.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/checks/argument.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/checks/assign.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/checks/case.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/checks/checks.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/checks/condition.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/checks/operation.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/checks/return.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/config/config.go create mode 100644 vendor/github.com/tommy-muehle/go-mnd/go.mod create mode 100644 vendor/github.com/tommy-muehle/go-mnd/go.sum create mode 100644 vendor/github.com/ultraware/funlen/LICENSE create mode 100644 vendor/github.com/ultraware/funlen/README.md create mode 100644 vendor/github.com/ultraware/funlen/main.go create mode 100644 vendor/github.com/ultraware/whitespace/LICENSE create mode 100644 vendor/github.com/ultraware/whitespace/README.md create mode 100644 vendor/github.com/ultraware/whitespace/main.go create mode 100644 vendor/github.com/uudashr/gocognit/LICENSE create mode 100644 vendor/github.com/uudashr/gocognit/README.md create mode 100644 vendor/github.com/uudashr/gocognit/go.mod create mode 100644 vendor/github.com/uudashr/gocognit/go.sum create mode 100644 vendor/github.com/uudashr/gocognit/gocognit.go (limited to 'vendor/github.com') diff --git a/vendor/github.com/BurntSushi/toml/.gitignore b/vendor/github.com/BurntSushi/toml/.gitignore new file mode 100644 index 000000000..0cd380037 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/.gitignore @@ -0,0 +1,5 @@ +TAGS +tags +.*.swp +tomlcheck/tomlcheck +toml.test diff --git a/vendor/github.com/BurntSushi/toml/.travis.yml b/vendor/github.com/BurntSushi/toml/.travis.yml new file mode 100644 index 000000000..8b8afc4f0 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/.travis.yml @@ -0,0 +1,15 @@ +language: go +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - tip +install: + - go install ./... + - go get github.com/BurntSushi/toml-test +script: + - export PATH="$PATH:$HOME/gopath/bin" + - make test diff --git a/vendor/github.com/BurntSushi/toml/COMPATIBLE b/vendor/github.com/BurntSushi/toml/COMPATIBLE new file mode 100644 index 000000000..6efcfd0ce --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/COMPATIBLE @@ -0,0 +1,3 @@ +Compatible with TOML version +[v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md) + diff --git a/vendor/github.com/BurntSushi/toml/COPYING b/vendor/github.com/BurntSushi/toml/COPYING new file mode 100644 index 000000000..01b574320 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/COPYING @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 TOML authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/BurntSushi/toml/Makefile b/vendor/github.com/BurntSushi/toml/Makefile new file mode 100644 index 000000000..3600848d3 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/Makefile @@ -0,0 +1,19 @@ +install: + go install ./... + +test: install + go test -v + toml-test toml-test-decoder + toml-test -encoder toml-test-encoder + +fmt: + gofmt -w *.go */*.go + colcheck *.go */*.go + +tags: + find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS + +push: + git push origin master + git push github master + diff --git a/vendor/github.com/BurntSushi/toml/README.md b/vendor/github.com/BurntSushi/toml/README.md new file mode 100644 index 000000000..7c1b37ecc --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/README.md @@ -0,0 +1,218 @@ +## TOML parser and encoder for Go with reflection + +TOML stands for Tom's Obvious, Minimal Language. This Go package provides a +reflection interface similar to Go's standard library `json` and `xml` +packages. This package also supports the `encoding.TextUnmarshaler` and +`encoding.TextMarshaler` interfaces so that you can define custom data +representations. (There is an example of this below.) + +Spec: https://github.com/toml-lang/toml + +Compatible with TOML version +[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) + +Documentation: https://godoc.org/github.com/BurntSushi/toml + +Installation: + +```bash +go get github.com/BurntSushi/toml +``` + +Try the toml validator: + +```bash +go get github.com/BurntSushi/toml/cmd/tomlv +tomlv some-toml-file.toml +``` + +[![Build Status](https://travis-ci.org/BurntSushi/toml.svg?branch=master)](https://travis-ci.org/BurntSushi/toml) [![GoDoc](https://godoc.org/github.com/BurntSushi/toml?status.svg)](https://godoc.org/github.com/BurntSushi/toml) + +### Testing + +This package passes all tests in +[toml-test](https://github.com/BurntSushi/toml-test) for both the decoder +and the encoder. + +### Examples + +This package works similarly to how the Go standard library handles `XML` +and `JSON`. Namely, data is loaded into Go values via reflection. + +For the simplest example, consider some TOML file as just a list of keys +and values: + +```toml +Age = 25 +Cats = [ "Cauchy", "Plato" ] +Pi = 3.14 +Perfection = [ 6, 28, 496, 8128 ] +DOB = 1987-07-05T05:45:00Z +``` + +Which could be defined in Go as: + +```go +type Config struct { + Age int + Cats []string + Pi float64 + Perfection []int + DOB time.Time // requires `import time` +} +``` + +And then decoded with: + +```go +var conf Config +if _, err := toml.Decode(tomlData, &conf); err != nil { + // handle error +} +``` + +You can also use struct tags if your struct field name doesn't map to a TOML +key value directly: + +```toml +some_key_NAME = "wat" +``` + +```go +type TOML struct { + ObscureKey string `toml:"some_key_NAME"` +} +``` + +### Using the `encoding.TextUnmarshaler` interface + +Here's an example that automatically parses duration strings into +`time.Duration` values: + +```toml +[[song]] +name = "Thunder Road" +duration = "4m49s" + +[[song]] +name = "Stairway to Heaven" +duration = "8m03s" +``` + +Which can be decoded with: + +```go +type song struct { + Name string + Duration duration +} +type songs struct { + Song []song +} +var favorites songs +if _, err := toml.Decode(blob, &favorites); err != nil { + log.Fatal(err) +} + +for _, s := range favorites.Song { + fmt.Printf("%s (%s)\n", s.Name, s.Duration) +} +``` + +And you'll also need a `duration` type that satisfies the +`encoding.TextUnmarshaler` interface: + +```go +type duration struct { + time.Duration +} + +func (d *duration) UnmarshalText(text []byte) error { + var err error + d.Duration, err = time.ParseDuration(string(text)) + return err +} +``` + +### More complex usage + +Here's an example of how to load the example from the official spec page: + +```toml +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it + +# Line breaks are OK when inside arrays +hosts = [ + "alpha", + "omega" +] +``` + +And the corresponding Go types are: + +```go +type tomlConfig struct { + Title string + Owner ownerInfo + DB database `toml:"database"` + Servers map[string]server + Clients clients +} + +type ownerInfo struct { + Name string + Org string `toml:"organization"` + Bio string + DOB time.Time +} + +type database struct { + Server string + Ports []int + ConnMax int `toml:"connection_max"` + Enabled bool +} + +type server struct { + IP string + DC string +} + +type clients struct { + Data [][]interface{} + Hosts []string +} +``` + +Note that a case insensitive match will be tried if an exact match can't be +found. + +A working example of the above can be found in `_examples/example.{go,toml}`. diff --git a/vendor/github.com/BurntSushi/toml/decode.go b/vendor/github.com/BurntSushi/toml/decode.go new file mode 100644 index 000000000..b0fd51d5b --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/decode.go @@ -0,0 +1,509 @@ +package toml + +import ( + "fmt" + "io" + "io/ioutil" + "math" + "reflect" + "strings" + "time" +) + +func e(format string, args ...interface{}) error { + return fmt.Errorf("toml: "+format, args...) +} + +// Unmarshaler is the interface implemented by objects that can unmarshal a +// TOML description of themselves. +type Unmarshaler interface { + UnmarshalTOML(interface{}) error +} + +// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`. +func Unmarshal(p []byte, v interface{}) error { + _, err := Decode(string(p), v) + return err +} + +// Primitive is a TOML value that hasn't been decoded into a Go value. +// When using the various `Decode*` functions, the type `Primitive` may +// be given to any value, and its decoding will be delayed. +// +// A `Primitive` value can be decoded using the `PrimitiveDecode` function. +// +// The underlying representation of a `Primitive` value is subject to change. +// Do not rely on it. +// +// N.B. Primitive values are still parsed, so using them will only avoid +// the overhead of reflection. They can be useful when you don't know the +// exact type of TOML data until run time. +type Primitive struct { + undecoded interface{} + context Key +} + +// DEPRECATED! +// +// Use MetaData.PrimitiveDecode instead. +func PrimitiveDecode(primValue Primitive, v interface{}) error { + md := MetaData{decoded: make(map[string]bool)} + return md.unify(primValue.undecoded, rvalue(v)) +} + +// PrimitiveDecode is just like the other `Decode*` functions, except it +// decodes a TOML value that has already been parsed. Valid primitive values +// can *only* be obtained from values filled by the decoder functions, +// including this method. (i.e., `v` may contain more `Primitive` +// values.) +// +// Meta data for primitive values is included in the meta data returned by +// the `Decode*` functions with one exception: keys returned by the Undecoded +// method will only reflect keys that were decoded. Namely, any keys hidden +// behind a Primitive will be considered undecoded. Executing this method will +// update the undecoded keys in the meta data. (See the example.) +func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { + md.context = primValue.context + defer func() { md.context = nil }() + return md.unify(primValue.undecoded, rvalue(v)) +} + +// Decode will decode the contents of `data` in TOML format into a pointer +// `v`. +// +// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be +// used interchangeably.) +// +// TOML arrays of tables correspond to either a slice of structs or a slice +// of maps. +// +// TOML datetimes correspond to Go `time.Time` values. +// +// All other TOML types (float, string, int, bool and array) correspond +// to the obvious Go types. +// +// An exception to the above rules is if a type implements the +// encoding.TextUnmarshaler interface. In this case, any primitive TOML value +// (floats, strings, integers, booleans and datetimes) will be converted to +// a byte string and given to the value's UnmarshalText method. See the +// Unmarshaler example for a demonstration with time duration strings. +// +// Key mapping +// +// TOML keys can map to either keys in a Go map or field names in a Go +// struct. The special `toml` struct tag may be used to map TOML keys to +// struct fields that don't match the key name exactly. (See the example.) +// A case insensitive match to struct names will be tried if an exact match +// can't be found. +// +// The mapping between TOML values and Go values is loose. That is, there +// may exist TOML values that cannot be placed into your representation, and +// there may be parts of your representation that do not correspond to +// TOML values. This loose mapping can be made stricter by using the IsDefined +// and/or Undecoded methods on the MetaData returned. +// +// This decoder will not handle cyclic types. If a cyclic type is passed, +// `Decode` will not terminate. +func Decode(data string, v interface{}) (MetaData, error) { + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr { + return MetaData{}, e("Decode of non-pointer %s", reflect.TypeOf(v)) + } + if rv.IsNil() { + return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v)) + } + p, err := parse(data) + if err != nil { + return MetaData{}, err + } + md := MetaData{ + p.mapping, p.types, p.ordered, + make(map[string]bool, len(p.ordered)), nil, + } + return md, md.unify(p.mapping, indirect(rv)) +} + +// DecodeFile is just like Decode, except it will automatically read the +// contents of the file at `fpath` and decode it for you. +func DecodeFile(fpath string, v interface{}) (MetaData, error) { + bs, err := ioutil.ReadFile(fpath) + if err != nil { + return MetaData{}, err + } + return Decode(string(bs), v) +} + +// DecodeReader is just like Decode, except it will consume all bytes +// from the reader and decode it for you. +func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { + bs, err := ioutil.ReadAll(r) + if err != nil { + return MetaData{}, err + } + return Decode(string(bs), v) +} + +// unify performs a sort of type unification based on the structure of `rv`, +// which is the client representation. +// +// Any type mismatch produces an error. Finding a type that we don't know +// how to handle produces an unsupported type error. +func (md *MetaData) unify(data interface{}, rv reflect.Value) error { + + // Special case. Look for a `Primitive` value. + if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() { + // Save the undecoded data and the key context into the primitive + // value. + context := make(Key, len(md.context)) + copy(context, md.context) + rv.Set(reflect.ValueOf(Primitive{ + undecoded: data, + context: context, + })) + return nil + } + + // Special case. Unmarshaler Interface support. + if rv.CanAddr() { + if v, ok := rv.Addr().Interface().(Unmarshaler); ok { + return v.UnmarshalTOML(data) + } + } + + // Special case. Handle time.Time values specifically. + // TODO: Remove this code when we decide to drop support for Go 1.1. + // This isn't necessary in Go 1.2 because time.Time satisfies the encoding + // interfaces. + if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) { + return md.unifyDatetime(data, rv) + } + + // Special case. Look for a value satisfying the TextUnmarshaler interface. + if v, ok := rv.Interface().(TextUnmarshaler); ok { + return md.unifyText(data, v) + } + // BUG(burntsushi) + // The behavior here is incorrect whenever a Go type satisfies the + // encoding.TextUnmarshaler interface but also corresponds to a TOML + // hash or array. In particular, the unmarshaler should only be applied + // to primitive TOML values. But at this point, it will be applied to + // all kinds of values and produce an incorrect error whenever those values + // are hashes or arrays (including arrays of tables). + + k := rv.Kind() + + // laziness + if k >= reflect.Int && k <= reflect.Uint64 { + return md.unifyInt(data, rv) + } + switch k { + case reflect.Ptr: + elem := reflect.New(rv.Type().Elem()) + err := md.unify(data, reflect.Indirect(elem)) + if err != nil { + return err + } + rv.Set(elem) + return nil + case reflect.Struct: + return md.unifyStruct(data, rv) + case reflect.Map: + return md.unifyMap(data, rv) + case reflect.Array: + return md.unifyArray(data, rv) + case reflect.Slice: + return md.unifySlice(data, rv) + case reflect.String: + return md.unifyString(data, rv) + case reflect.Bool: + return md.unifyBool(data, rv) + case reflect.Interface: + // we only support empty interfaces. + if rv.NumMethod() > 0 { + return e("unsupported type %s", rv.Type()) + } + return md.unifyAnything(data, rv) + case reflect.Float32: + fallthrough + case reflect.Float64: + return md.unifyFloat64(data, rv) + } + return e("unsupported type %s", rv.Kind()) +} + +func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { + tmap, ok := mapping.(map[string]interface{}) + if !ok { + if mapping == nil { + return nil + } + return e("type mismatch for %s: expected table but found %T", + rv.Type().String(), mapping) + } + + for key, datum := range tmap { + var f *field + fields := cachedTypeFields(rv.Type()) + for i := range fields { + ff := &fields[i] + if ff.name == key { + f = ff + break + } + if f == nil && strings.EqualFold(ff.name, key) { + f = ff + } + } + if f != nil { + subv := rv + for _, i := range f.index { + subv = indirect(subv.Field(i)) + } + if isUnifiable(subv) { + md.decoded[md.context.add(key).String()] = true + md.context = append(md.context, key) + if err := md.unify(datum, subv); err != nil { + return err + } + md.context = md.context[0 : len(md.context)-1] + } else if f.name != "" { + // Bad user! No soup for you! + return e("cannot write unexported field %s.%s", + rv.Type().String(), f.name) + } + } + } + return nil +} + +func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { + tmap, ok := mapping.(map[string]interface{}) + if !ok { + if tmap == nil { + return nil + } + return badtype("map", mapping) + } + if rv.IsNil() { + rv.Set(reflect.MakeMap(rv.Type())) + } + for k, v := range tmap { + md.decoded[md.context.add(k).String()] = true + md.context = append(md.context, k) + + rvkey := indirect(reflect.New(rv.Type().Key())) + rvval := reflect.Indirect(reflect.New(rv.Type().Elem())) + if err := md.unify(v, rvval); err != nil { + return err + } + md.context = md.context[0 : len(md.context)-1] + + rvkey.SetString(k) + rv.SetMapIndex(rvkey, rvval) + } + return nil +} + +func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { + datav := reflect.ValueOf(data) + if datav.Kind() != reflect.Slice { + if !datav.IsValid() { + return nil + } + return badtype("slice", data) + } + sliceLen := datav.Len() + if sliceLen != rv.Len() { + return e("expected array length %d; got TOML array of length %d", + rv.Len(), sliceLen) + } + return md.unifySliceArray(datav, rv) +} + +func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error { + datav := reflect.ValueOf(data) + if datav.Kind() != reflect.Slice { + if !datav.IsValid() { + return nil + } + return badtype("slice", data) + } + n := datav.Len() + if rv.IsNil() || rv.Cap() < n { + rv.Set(reflect.MakeSlice(rv.Type(), n, n)) + } + rv.SetLen(n) + return md.unifySliceArray(datav, rv) +} + +func (md *MetaData) unifySliceArray(data, rv reflect.Value) error { + sliceLen := data.Len() + for i := 0; i < sliceLen; i++ { + v := data.Index(i).Interface() + sliceval := indirect(rv.Index(i)) + if err := md.unify(v, sliceval); err != nil { + return err + } + } + return nil +} + +func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error { + if _, ok := data.(time.Time); ok { + rv.Set(reflect.ValueOf(data)) + return nil + } + return badtype("time.Time", data) +} + +func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { + if s, ok := data.(string); ok { + rv.SetString(s) + return nil + } + return badtype("string", data) +} + +func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { + if num, ok := data.(float64); ok { + switch rv.Kind() { + case reflect.Float32: + fallthrough + case reflect.Float64: + rv.SetFloat(num) + default: + panic("bug") + } + return nil + } + return badtype("float", data) +} + +func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { + if num, ok := data.(int64); ok { + if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 { + switch rv.Kind() { + case reflect.Int, reflect.Int64: + // No bounds checking necessary. + case reflect.Int8: + if num < math.MinInt8 || num > math.MaxInt8 { + return e("value %d is out of range for int8", num) + } + case reflect.Int16: + if num < math.MinInt16 || num > math.MaxInt16 { + return e("value %d is out of range for int16", num) + } + case reflect.Int32: + if num < math.MinInt32 || num > math.MaxInt32 { + return e("value %d is out of range for int32", num) + } + } + rv.SetInt(num) + } else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 { + unum := uint64(num) + switch rv.Kind() { + case reflect.Uint, reflect.Uint64: + // No bounds checking necessary. + case reflect.Uint8: + if num < 0 || unum > math.MaxUint8 { + return e("value %d is out of range for uint8", num) + } + case reflect.Uint16: + if num < 0 || unum > math.MaxUint16 { + return e("value %d is out of range for uint16", num) + } + case reflect.Uint32: + if num < 0 || unum > math.MaxUint32 { + return e("value %d is out of range for uint32", num) + } + } + rv.SetUint(unum) + } else { + panic("unreachable") + } + return nil + } + return badtype("integer", data) +} + +func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { + if b, ok := data.(bool); ok { + rv.SetBool(b) + return nil + } + return badtype("boolean", data) +} + +func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error { + rv.Set(reflect.ValueOf(data)) + return nil +} + +func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error { + var s string + switch sdata := data.(type) { + case TextMarshaler: + text, err := sdata.MarshalText() + if err != nil { + return err + } + s = string(text) + case fmt.Stringer: + s = sdata.String() + case string: + s = sdata + case bool: + s = fmt.Sprintf("%v", sdata) + case int64: + s = fmt.Sprintf("%d", sdata) + case float64: + s = fmt.Sprintf("%f", sdata) + default: + return badtype("primitive (string-like)", data) + } + if err := v.UnmarshalText([]byte(s)); err != nil { + return err + } + return nil +} + +// rvalue returns a reflect.Value of `v`. All pointers are resolved. +func rvalue(v interface{}) reflect.Value { + return indirect(reflect.ValueOf(v)) +} + +// indirect returns the value pointed to by a pointer. +// Pointers are followed until the value is not a pointer. +// New values are allocated for each nil pointer. +// +// An exception to this rule is if the value satisfies an interface of +// interest to us (like encoding.TextUnmarshaler). +func indirect(v reflect.Value) reflect.Value { + if v.Kind() != reflect.Ptr { + if v.CanSet() { + pv := v.Addr() + if _, ok := pv.Interface().(TextUnmarshaler); ok { + return pv + } + } + return v + } + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + return indirect(reflect.Indirect(v)) +} + +func isUnifiable(rv reflect.Value) bool { + if rv.CanSet() { + return true + } + if _, ok := rv.Interface().(TextUnmarshaler); ok { + return true + } + return false +} + +func badtype(expected string, data interface{}) error { + return e("cannot load TOML value of type %T into a Go %s", data, expected) +} diff --git a/vendor/github.com/BurntSushi/toml/decode_meta.go b/vendor/github.com/BurntSushi/toml/decode_meta.go new file mode 100644 index 000000000..b9914a679 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/decode_meta.go @@ -0,0 +1,121 @@ +package toml + +import "strings" + +// MetaData allows access to meta information about TOML data that may not +// be inferrable via reflection. In particular, whether a key has been defined +// and the TOML type of a key. +type MetaData struct { + mapping map[string]interface{} + types map[string]tomlType + keys []Key + decoded map[string]bool + context Key // Used only during decoding. +} + +// IsDefined returns true if the key given exists in the TOML data. The key +// should be specified hierarchially. e.g., +// +// // access the TOML key 'a.b.c' +// IsDefined("a", "b", "c") +// +// IsDefined will return false if an empty key given. Keys are case sensitive. +func (md *MetaData) IsDefined(key ...string) bool { + if len(key) == 0 { + return false + } + + var hash map[string]interface{} + var ok bool + var hashOrVal interface{} = md.mapping + for _, k := range key { + if hash, ok = hashOrVal.(map[string]interface{}); !ok { + return false + } + if hashOrVal, ok = hash[k]; !ok { + return false + } + } + return true +} + +// Type returns a string representation of the type of the key specified. +// +// Type will return the empty string if given an empty key or a key that +// does not exist. Keys are case sensitive. +func (md *MetaData) Type(key ...string) string { + fullkey := strings.Join(key, ".") + if typ, ok := md.types[fullkey]; ok { + return typ.typeString() + } + return "" +} + +// Key is the type of any TOML key, including key groups. Use (MetaData).Keys +// to get values of this type. +type Key []string + +func (k Key) String() string { + return strings.Join(k, ".") +} + +func (k Key) maybeQuotedAll() string { + var ss []string + for i := range k { + ss = append(ss, k.maybeQuoted(i)) + } + return strings.Join(ss, ".") +} + +func (k Key) maybeQuoted(i int) string { + quote := false + for _, c := range k[i] { + if !isBareKeyChar(c) { + quote = true + break + } + } + if quote { + return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\"" + } + return k[i] +} + +func (k Key) add(piece string) Key { + newKey := make(Key, len(k)+1) + copy(newKey, k) + newKey[len(k)] = piece + return newKey +} + +// Keys returns a slice of every key in the TOML data, including key groups. +// Each key is itself a slice, where the first element is the top of the +// hierarchy and the last is the most specific. +// +// The list will have the same order as the keys appeared in the TOML data. +// +// All keys returned are non-empty. +func (md *MetaData) Keys() []Key { + return md.keys +} + +// Undecoded returns all keys that have not been decoded in the order in which +// they appear in the original TOML document. +// +// This includes keys that haven't been decoded because of a Primitive value. +// Once the Primitive value is decoded, the keys will be considered decoded. +// +// Also note that decoding into an empty interface will result in no decoding, +// and so no keys will be considered decoded. +// +// In this sense, the Undecoded keys correspond to keys in the TOML document +// that do not have a concrete type in your representation. +func (md *MetaData) Undecoded() []Key { + undecoded := make([]Key, 0, len(md.keys)) + for _, key := range md.keys { + if !md.decoded[key.String()] { + undecoded = append(undecoded, key) + } + } + return undecoded +} diff --git a/vendor/github.com/BurntSushi/toml/doc.go b/vendor/github.com/BurntSushi/toml/doc.go new file mode 100644 index 000000000..b371f396e --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/doc.go @@ -0,0 +1,27 @@ +/* +Package toml provides facilities for decoding and encoding TOML configuration +files via reflection. There is also support for delaying decoding with +the Primitive type, and querying the set of keys in a TOML document with the +MetaData type. + +The specification implemented: https://github.com/toml-lang/toml + +The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify +whether a file is a valid TOML document. It can also be used to print the +type of each key in a TOML document. + +Testing + +There are two important types of tests used for this package. The first is +contained inside '*_test.go' files and uses the standard Go unit testing +framework. These tests are primarily devoted to holistically testing the +decoder and encoder. + +The second type of testing is used to verify the implementation's adherence +to the TOML specification. These tests have been factored into their own +project: https://github.com/BurntSushi/toml-test + +The reason the tests are in a separate project is so that they can be used by +any implementation of TOML. Namely, it is language agnostic. +*/ +package toml diff --git a/vendor/github.com/BurntSushi/toml/encode.go b/vendor/github.com/BurntSushi/toml/encode.go new file mode 100644 index 000000000..d905c21a2 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/encode.go @@ -0,0 +1,568 @@ +package toml + +import ( + "bufio" + "errors" + "fmt" + "io" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +type tomlEncodeError struct{ error } + +var ( + errArrayMixedElementTypes = errors.New( + "toml: cannot encode array with mixed element types") + errArrayNilElement = errors.New( + "toml: cannot encode array with nil element") + errNonString = errors.New( + "toml: cannot encode a map with non-string key type") + errAnonNonStruct = errors.New( + "toml: cannot encode an anonymous field that is not a struct") + errArrayNoTable = errors.New( + "toml: TOML array element cannot contain a table") + errNoKey = errors.New( + "toml: top-level values must be Go maps or structs") + errAnything = errors.New("") // used in testing +) + +var quotedReplacer = strings.NewReplacer( + "\t", "\\t", + "\n", "\\n", + "\r", "\\r", + "\"", "\\\"", + "\\", "\\\\", +) + +// Encoder controls the encoding of Go values to a TOML document to some +// io.Writer. +// +// The indentation level can be controlled with the Indent field. +type Encoder struct { + // A single indentation level. By default it is two spaces. + Indent string + + // hasWritten is whether we have written any output to w yet. + hasWritten bool + w *bufio.Writer +} + +// NewEncoder returns a TOML encoder that encodes Go values to the io.Writer +// given. By default, a single indentation level is 2 spaces. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + w: bufio.NewWriter(w), + Indent: " ", + } +} + +// Encode writes a TOML representation of the Go value to the underlying +// io.Writer. If the value given cannot be encoded to a valid TOML document, +// then an error is returned. +// +// The mapping between Go values and TOML values should be precisely the same +// as for the Decode* functions. Similarly, the TextMarshaler interface is +// supported by encoding the resulting bytes as strings. (If you want to write +// arbitrary binary data then you will need to use something like base64 since +// TOML does not have any binary types.) +// +// When encoding TOML hashes (i.e., Go maps or structs), keys without any +// sub-hashes are encoded first. +// +// If a Go map is encoded, then its keys are sorted alphabetically for +// deterministic output. More control over this behavior may be provided if +// there is demand for it. +// +// Encoding Go values without a corresponding TOML representation---like map +// types with non-string keys---will cause an error to be returned. Similarly +// for mixed arrays/slices, arrays/slices with nil elements, embedded +// non-struct types and nested slices containing maps or structs. +// (e.g., [][]map[string]string is not allowed but []map[string]string is OK +// and so is []map[string][]string.) +func (enc *Encoder) Encode(v interface{}) error { + rv := eindirect(reflect.ValueOf(v)) + if err := enc.safeEncode(Key([]string{}), rv); err != nil { + return err + } + return enc.w.Flush() +} + +func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) { + defer func() { + if r := recover(); r != nil { + if terr, ok := r.(tomlEncodeError); ok { + err = terr.error + return + } + panic(r) + } + }() + enc.encode(key, rv) + return nil +} + +func (enc *Encoder) encode(key Key, rv reflect.Value) { + // Special case. Time needs to be in ISO8601 format. + // Special case. If we can marshal the type to text, then we used that. + // Basically, this prevents the encoder for handling these types as + // generic structs (or whatever the underlying type of a TextMarshaler is). + switch rv.Interface().(type) { + case time.Time, TextMarshaler: + enc.keyEqElement(key, rv) + return + } + + k := rv.Kind() + switch k { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, + reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, + reflect.Uint64, + reflect.Float32, reflect.Float64, reflect.String, reflect.Bool: + enc.keyEqElement(key, rv) + case reflect.Array, reflect.Slice: + if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) { + enc.eArrayOfTables(key, rv) + } else { + enc.keyEqElement(key, rv) + } + case reflect.Interface: + if rv.IsNil() { + return + } + enc.encode(key, rv.Elem()) + case reflect.Map: + if rv.IsNil() { + return + } + enc.eTable(key, rv) + case reflect.Ptr: + if rv.IsNil() { + return + } + enc.encode(key, rv.Elem()) + case reflect.Struct: + enc.eTable(key, rv) + default: + panic(e("unsupported type for key '%s': %s", key, k)) + } +} + +// eElement encodes any value that can be an array element (primitives and +// arrays). +func (enc *Encoder) eElement(rv reflect.Value) { + switch v := rv.Interface().(type) { + case time.Time: + // Special case time.Time as a primitive. Has to come before + // TextMarshaler below because time.Time implements + // encoding.TextMarshaler, but we need to always use UTC. + enc.wf(v.UTC().Format("2006-01-02T15:04:05Z")) + return + case TextMarshaler: + // Special case. Use text marshaler if it's available for this value. + if s, err := v.MarshalText(); err != nil { + encPanic(err) + } else { + enc.writeQuoted(string(s)) + } + return + } + switch rv.Kind() { + case reflect.Bool: + enc.wf(strconv.FormatBool(rv.Bool())) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, + reflect.Int64: + enc.wf(strconv.FormatInt(rv.Int(), 10)) + case reflect.Uint, reflect.Uint8, reflect.Uint16, + reflect.Uint32, reflect.Uint64: + enc.wf(strconv.FormatUint(rv.Uint(), 10)) + case reflect.Float32: + enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32))) + case reflect.Float64: + enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64))) + case reflect.Array, reflect.Slice: + enc.eArrayOrSliceElement(rv) + case reflect.Interface: + enc.eElement(rv.Elem()) + case reflect.String: + enc.writeQuoted(rv.String()) + default: + panic(e("unexpected primitive type: %s", rv.Kind())) + } +} + +// By the TOML spec, all floats must have a decimal with at least one +// number on either side. +func floatAddDecimal(fstr string) string { + if !strings.Contains(fstr, ".") { + return fstr + ".0" + } + return fstr +} + +func (enc *Encoder) writeQuoted(s string) { + enc.wf("\"%s\"", quotedReplacer.Replace(s)) +} + +func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) { + length := rv.Len() + enc.wf("[") + for i := 0; i < length; i++ { + elem := rv.Index(i) + enc.eElement(elem) + if i != length-1 { + enc.wf(", ") + } + } + enc.wf("]") +} + +func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) { + if len(key) == 0 { + encPanic(errNoKey) + } + for i := 0; i < rv.Len(); i++ { + trv := rv.Index(i) + if isNil(trv) { + continue + } + panicIfInvalidKey(key) + enc.newline() + enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll()) + enc.newline() + enc.eMapOrStruct(key, trv) + } +} + +func (enc *Encoder) eTable(key Key, rv reflect.Value) { + panicIfInvalidKey(key) + if len(key) == 1 { + // Output an extra newline between top-level tables. + // (The newline isn't written if nothing else has been written though.) + enc.newline() + } + if len(key) > 0 { + enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll()) + enc.newline() + } + enc.eMapOrStruct(key, rv) +} + +func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) { + switch rv := eindirect(rv); rv.Kind() { + case reflect.Map: + enc.eMap(key, rv) + case reflect.Struct: + enc.eStruct(key, rv) + default: + panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String()) + } +} + +func (enc *Encoder) eMap(key Key, rv reflect.Value) { + rt := rv.Type() + if rt.Key().Kind() != reflect.String { + encPanic(errNonString) + } + + // Sort keys so that we have deterministic output. And write keys directly + // underneath this key first, before writing sub-structs or sub-maps. + var mapKeysDirect, mapKeysSub []string + for _, mapKey := range rv.MapKeys() { + k := mapKey.String() + if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) { + mapKeysSub = append(mapKeysSub, k) + } else { + mapKeysDirect = append(mapKeysDirect, k) + } + } + + var writeMapKeys = func(mapKeys []string) { + sort.Strings(mapKeys) + for _, mapKey := range mapKeys { + mrv := rv.MapIndex(reflect.ValueOf(mapKey)) + if isNil(mrv) { + // Don't write anything for nil fields. + continue + } + enc.encode(key.add(mapKey), mrv) + } + } + writeMapKeys(mapKeysDirect) + writeMapKeys(mapKeysSub) +} + +func (enc *Encoder) eStruct(key Key, rv reflect.Value) { + // Write keys for fields directly under this key first, because if we write + // a field that creates a new table, then all keys under it will be in that + // table (not the one we're writing here). + rt := rv.Type() + var fieldsDirect, fieldsSub [][]int + var addFields func(rt reflect.Type, rv reflect.Value, start []int) + addFields = func(rt reflect.Type, rv reflect.Value, start []int) { + for i := 0; i < rt.NumField(); i++ { + f := rt.Field(i) + // skip unexported fields + if f.PkgPath != "" && !f.Anonymous { + continue + } + frv := rv.Field(i) + if f.Anonymous { + t := f.Type + switch t.Kind() { + case reflect.Struct: + // Treat anonymous struct fields with + // tag names as though they are not + // anonymous, like encoding/json does. + if getOptions(f.Tag).name == "" { + addFields(t, frv, f.Index) + continue + } + case reflect.Ptr: + if t.Elem().Kind() == reflect.Struct && + getOptions(f.Tag).name == "" { + if !frv.IsNil() { + addFields(t.Elem(), frv.Elem(), f.Index) + } + continue + } + // Fall through to the normal field encoding logic below + // for non-struct anonymous fields. + } + } + + if typeIsHash(tomlTypeOfGo(frv)) { + fieldsSub = append(fieldsSub, append(start, f.Index...)) + } else { + fieldsDirect = append(fieldsDirect, append(start, f.Index...)) + } + } + } + addFields(rt, rv, nil) + + var writeFields = func(fields [][]int) { + for _, fieldIndex := range fields { + sft := rt.FieldByIndex(fieldIndex) + sf := rv.FieldByIndex(fieldIndex) + if isNil(sf) { + // Don't write anything for nil fields. + continue + } + + opts := getOptions(sft.Tag) + if opts.skip { + continue + } + keyName := sft.Name + if opts.name != "" { + keyName = opts.name + } + if opts.omitempty && isEmpty(sf) { + continue + } + if opts.omitzero && isZero(sf) { + continue + } + + enc.encode(key.add(keyName), sf) + } + } + writeFields(fieldsDirect) + writeFields(fieldsSub) +} + +// tomlTypeName returns the TOML type name of the Go value's type. It is +// used to determine whether the types of array elements are mixed (which is +// forbidden). If the Go value is nil, then it is illegal for it to be an array +// element, and valueIsNil is returned as true. + +// Returns the TOML type of a Go value. The type may be `nil`, which means +// no concrete TOML type could be found. +func tomlTypeOfGo(rv reflect.Value) tomlType { + if isNil(rv) || !rv.IsValid() { + return nil + } + switch rv.Kind() { + case reflect.Bool: + return tomlBool + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, + reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, + reflect.Uint64: + return tomlInteger + case reflect.Float32, reflect.Float64: + return tomlFloat + case reflect.Array, reflect.Slice: + if typeEqual(tomlHash, tomlArrayType(rv)) { + return tomlArrayHash + } + return tomlArray + case reflect.Ptr, reflect.Interface: + return tomlTypeOfGo(rv.Elem()) + case reflect.String: + return tomlString + case reflect.Map: + return tomlHash + case reflect.Struct: + switch rv.Interface().(type) { + case time.Time: + return tomlDatetime + case TextMarshaler: + return tomlString + default: + return tomlHash + } + default: + panic("unexpected reflect.Kind: " + rv.Kind().String()) + } +} + +// tomlArrayType returns the element type of a TOML array. The type returned +// may be nil if it cannot be determined (e.g., a nil slice or a zero length +// slize). This function may also panic if it finds a type that cannot be +// expressed in TOML (such as nil elements, heterogeneous arrays or directly +// nested arrays of tables). +func tomlArrayType(rv reflect.Value) tomlType { + if isNil(rv) || !rv.IsValid() || rv.Len() == 0 { + return nil + } + firstType := tomlTypeOfGo(rv.Index(0)) + if firstType == nil { + encPanic(errArrayNilElement) + } + + rvlen := rv.Len() + for i := 1; i < rvlen; i++ { + elem := rv.Index(i) + switch elemType := tomlTypeOfGo(elem); { + case elemType == nil: + encPanic(errArrayNilElement) + case !typeEqual(firstType, elemType): + encPanic(errArrayMixedElementTypes) + } + } + // If we have a nested array, then we must make sure that the nested + // array contains ONLY primitives. + // This checks arbitrarily nested arrays. + if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) { + nest := tomlArrayType(eindirect(rv.Index(0))) + if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) { + encPanic(errArrayNoTable) + } + } + return firstType +} + +type tagOptions struct { + skip bool // "-" + name string + omitempty bool + omitzero bool +} + +func getOptions(tag reflect.StructTag) tagOptions { + t := tag.Get("toml") + if t == "-" { + return tagOptions{skip: true} + } + var opts tagOptions + parts := strings.Split(t, ",") + opts.name = parts[0] + for _, s := range parts[1:] { + switch s { + case "omitempty": + opts.omitempty = true + case "omitzero": + opts.omitzero = true + } + } + return opts +} + +func isZero(rv reflect.Value) bool { + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return rv.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return rv.Uint() == 0 + case reflect.Float32, reflect.Float64: + return rv.Float() == 0.0 + } + return false +} + +func isEmpty(rv reflect.Value) bool { + switch rv.Kind() { + case reflect.Array, reflect.Slice, reflect.Map, reflect.String: + return rv.Len() == 0 + case reflect.Bool: + return !rv.Bool() + } + return false +} + +func (enc *Encoder) newline() { + if enc.hasWritten { + enc.wf("\n") + } +} + +func (enc *Encoder) keyEqElement(key Key, val reflect.Value) { + if len(key) == 0 { + encPanic(errNoKey) + } + panicIfInvalidKey(key) + enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1)) + enc.eElement(val) + enc.newline() +} + +func (enc *Encoder) wf(format string, v ...interface{}) { + if _, err := fmt.Fprintf(enc.w, format, v...); err != nil { + encPanic(err) + } + enc.hasWritten = true +} + +func (enc *Encoder) indentStr(key Key) string { + return strings.Repeat(enc.Indent, len(key)-1) +} + +func encPanic(err error) { + panic(tomlEncodeError{err}) +} + +func eindirect(v reflect.Value) reflect.Value { + switch v.Kind() { + case reflect.Ptr, reflect.Interface: + return eindirect(v.Elem()) + default: + return v + } +} + +func isNil(rv reflect.Value) bool { + switch rv.Kind() { + case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return rv.IsNil() + default: + return false + } +} + +func panicIfInvalidKey(key Key) { + for _, k := range key { + if len(k) == 0 { + encPanic(e("Key '%s' is not a valid table name. Key names "+ + "cannot be empty.", key.maybeQuotedAll())) + } + } +} + +func isValidKeyName(s string) bool { + return len(s) != 0 +} diff --git a/vendor/github.com/BurntSushi/toml/encoding_types.go b/vendor/github.com/BurntSushi/toml/encoding_types.go new file mode 100644 index 000000000..d36e1dd60 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/encoding_types.go @@ -0,0 +1,19 @@ +// +build go1.2 + +package toml + +// In order to support Go 1.1, we define our own TextMarshaler and +// TextUnmarshaler types. For Go 1.2+, we just alias them with the +// standard library interfaces. + +import ( + "encoding" +) + +// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here +// so that Go 1.1 can be supported. +type TextMarshaler encoding.TextMarshaler + +// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined +// here so that Go 1.1 can be supported. +type TextUnmarshaler encoding.TextUnmarshaler diff --git a/vendor/github.com/BurntSushi/toml/encoding_types_1.1.go b/vendor/github.com/BurntSushi/toml/encoding_types_1.1.go new file mode 100644 index 000000000..e8d503d04 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/encoding_types_1.1.go @@ -0,0 +1,18 @@ +// +build !go1.2 + +package toml + +// These interfaces were introduced in Go 1.2, so we add them manually when +// compiling for Go 1.1. + +// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here +// so that Go 1.1 can be supported. +type TextMarshaler interface { + MarshalText() (text []byte, err error) +} + +// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined +// here so that Go 1.1 can be supported. +type TextUnmarshaler interface { + UnmarshalText(text []byte) error +} diff --git a/vendor/github.com/BurntSushi/toml/lex.go b/vendor/github.com/BurntSushi/toml/lex.go new file mode 100644 index 000000000..e0a742a88 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/lex.go @@ -0,0 +1,953 @@ +package toml + +import ( + "fmt" + "strings" + "unicode" + "unicode/utf8" +) + +type itemType int + +const ( + itemError itemType = iota + itemNIL // used in the parser to indicate no type + itemEOF + itemText + itemString + itemRawString + itemMultilineString + itemRawMultilineString + itemBool + itemInteger + itemFloat + itemDatetime + itemArray // the start of an array + itemArrayEnd + itemTableStart + itemTableEnd + itemArrayTableStart + itemArrayTableEnd + itemKeyStart + itemCommentStart + itemInlineTableStart + itemInlineTableEnd +) + +const ( + eof = 0 + comma = ',' + tableStart = '[' + tableEnd = ']' + arrayTableStart = '[' + arrayTableEnd = ']' + tableSep = '.' + keySep = '=' + arrayStart = '[' + arrayEnd = ']' + commentStart = '#' + stringStart = '"' + stringEnd = '"' + rawStringStart = '\'' + rawStringEnd = '\'' + inlineTableStart = '{' + inlineTableEnd = '}' +) + +type stateFn func(lx *lexer) stateFn + +type lexer struct { + input string + start int + pos int + line int + state stateFn + items chan item + + // Allow for backing up up to three runes. + // This is necessary because TOML contains 3-rune tokens (""" and '''). + prevWidths [3]int + nprev int // how many of prevWidths are in use + // If we emit an eof, we can still back up, but it is not OK to call + // next again. + atEOF bool + + // A stack of state functions used to maintain context. + // The idea is to reuse parts of the state machine in various places. + // For example, values can appear at the top level or within arbitrarily + // nested arrays. The last state on the stack is used after a value has + // been lexed. Similarly for comments. + stack []stateFn +} + +type item struct { + typ itemType + val string + line int +} + +func (lx *lexer) nextItem() item { + for { + select { + case item := <-lx.items: + return item + default: + lx.state = lx.state(lx) + } + } +} + +func lex(input string) *lexer { + lx := &lexer{ + input: input, + state: lexTop, + line: 1, + items: make(chan item, 10), + stack: make([]stateFn, 0, 10), + } + return lx +} + +func (lx *lexer) push(state stateFn) { + lx.stack = append(lx.stack, state) +} + +func (lx *lexer) pop() stateFn { + if len(lx.stack) == 0 { + return lx.errorf("BUG in lexer: no states to pop") + } + last := lx.stack[len(lx.stack)-1] + lx.stack = lx.stack[0 : len(lx.stack)-1] + return last +} + +func (lx *lexer) current() string { + return lx.input[lx.start:lx.pos] +} + +func (lx *lexer) emit(typ itemType) { + lx.items <- item{typ, lx.current(), lx.line} + lx.start = lx.pos +} + +func (lx *lexer) emitTrim(typ itemType) { + lx.items <- item{typ, strings.TrimSpace(lx.current()), lx.line} + lx.start = lx.pos +} + +func (lx *lexer) next() (r rune) { + if lx.atEOF { + panic("next called after EOF") + } + if lx.pos >= len(lx.input) { + lx.atEOF = true + return eof + } + + if lx.input[lx.pos] == '\n' { + lx.line++ + } + lx.prevWidths[2] = lx.prevWidths[1] + lx.prevWidths[1] = lx.prevWidths[0] + if lx.nprev < 3 { + lx.nprev++ + } + r, w := utf8.DecodeRuneInString(lx.input[lx.pos:]) + lx.prevWidths[0] = w + lx.pos += w + return r +} + +// ignore skips over the pending input before this point. +func (lx *lexer) ignore() { + lx.start = lx.pos +} + +// backup steps back one rune. Can be called only twice between calls to next. +func (lx *lexer) backup() { + if lx.atEOF { + lx.atEOF = false + return + } + if lx.nprev < 1 { + panic("backed up too far") + } + w := lx.prevWidths[0] + lx.prevWidths[0] = lx.prevWidths[1] + lx.prevWidths[1] = lx.prevWidths[2] + lx.nprev-- + lx.pos -= w + if lx.pos < len(lx.input) && lx.input[lx.pos] == '\n' { + lx.line-- + } +} + +// accept consumes the next rune if it's equal to `valid`. +func (lx *lexer) accept(valid rune) bool { + if lx.next() == valid { + return true + } + lx.backup() + return false +} + +// peek returns but does not consume the next rune in the input. +func (lx *lexer) peek() rune { + r := lx.next() + lx.backup() + return r +} + +// skip ignores all input that matches the given predicate. +func (lx *lexer) skip(pred func(rune) bool) { + for { + r := lx.next() + if pred(r) { + continue + } + lx.backup() + lx.ignore() + return + } +} + +// errorf stops all lexing by emitting an error and returning `nil`. +// Note that any value that is a character is escaped if it's a special +// character (newlines, tabs, etc.). +func (lx *lexer) errorf(format string, values ...interface{}) stateFn { + lx.items <- item{ + itemError, + fmt.Sprintf(format, values...), + lx.line, + } + return nil +} + +// lexTop consumes elements at the top level of TOML data. +func lexTop(lx *lexer) stateFn { + r := lx.next() + if isWhitespace(r) || isNL(r) { + return lexSkip(lx, lexTop) + } + switch r { + case commentStart: + lx.push(lexTop) + return lexCommentStart + case tableStart: + return lexTableStart + case eof: + if lx.pos > lx.start { + return lx.errorf("unexpected EOF") + } + lx.emit(itemEOF) + return nil + } + + // At this point, the only valid item can be a key, so we back up + // and let the key lexer do the rest. + lx.backup() + lx.push(lexTopEnd) + return lexKeyStart +} + +// lexTopEnd is entered whenever a top-level item has been consumed. (A value +// or a table.) It must see only whitespace, and will turn back to lexTop +// upon a newline. If it sees EOF, it will quit the lexer successfully. +func lexTopEnd(lx *lexer) stateFn { + r := lx.next() + switch { + case r == commentStart: + // a comment will read to a newline for us. + lx.push(lexTop) + return lexCommentStart + case isWhitespace(r): + return lexTopEnd + case isNL(r): + lx.ignore() + return lexTop + case r == eof: + lx.emit(itemEOF) + return nil + } + return lx.errorf("expected a top-level item to end with a newline, "+ + "comment, or EOF, but got %q instead", r) +} + +// lexTable lexes the beginning of a table. Namely, it makes sure that +// it starts with a character other than '.' and ']'. +// It assumes that '[' has already been consumed. +// It also handles the case that this is an item in an array of tables. +// e.g., '[[name]]'. +func lexTableStart(lx *lexer) stateFn { + if lx.peek() == arrayTableStart { + lx.next() + lx.emit(itemArrayTableStart) + lx.push(lexArrayTableEnd) + } else { + lx.emit(itemTableStart) + lx.push(lexTableEnd) + } + return lexTableNameStart +} + +func lexTableEnd(lx *lexer) stateFn { + lx.emit(itemTableEnd) + return lexTopEnd +} + +func lexArrayTableEnd(lx *lexer) stateFn { + if r := lx.next(); r != arrayTableEnd { + return lx.errorf("expected end of table array name delimiter %q, "+ + "but got %q instead", arrayTableEnd, r) + } + lx.emit(itemArrayTableEnd) + return lexTopEnd +} + +func lexTableNameStart(lx *lexer) stateFn { + lx.skip(isWhitespace) + switch r := lx.peek(); { + case r == tableEnd || r == eof: + return lx.errorf("unexpected end of table name " + + "(table names cannot be empty)") + case r == tableSep: + return lx.errorf("unexpected table separator " + + "(table names cannot be empty)") + case r == stringStart || r == rawStringStart: + lx.ignore() + lx.push(lexTableNameEnd) + return lexValue // reuse string lexing + default: + return lexBareTableName + } +} + +// lexBareTableName lexes the name of a table. It assumes that at least one +// valid character for the table has already been read. +func lexBareTableName(lx *lexer) stateFn { + r := lx.next() + if isBareKeyChar(r) { + return lexBareTableName + } + lx.backup() + lx.emit(itemText) + return lexTableNameEnd +} + +// lexTableNameEnd reads the end of a piece of a table name, optionally +// consuming whitespace. +func lexTableNameEnd(lx *lexer) stateFn { + lx.skip(isWhitespace) + switch r := lx.next(); { + case isWhitespace(r): + return lexTableNameEnd + case r == tableSep: + lx.ignore() + return lexTableNameStart + case r == tableEnd: + return lx.pop() + default: + return lx.errorf("expected '.' or ']' to end table name, "+ + "but got %q instead", r) + } +} + +// lexKeyStart consumes a key name up until the first non-whitespace character. +// lexKeyStart will ignore whitespace. +func lexKeyStart(lx *lexer) stateFn { + r := lx.peek() + switch { + case r == keySep: + return lx.errorf("unexpected key separator %q", keySep) + case isWhitespace(r) || isNL(r): + lx.next() + return lexSkip(lx, lexKeyStart) + case r == stringStart || r == rawStringStart: + lx.ignore() + lx.emit(itemKeyStart) + lx.push(lexKeyEnd) + return lexValue // reuse string lexing + default: + lx.ignore() + lx.emit(itemKeyStart) + return lexBareKey + } +} + +// lexBareKey consumes the text of a bare key. Assumes that the first character +// (which is not whitespace) has not yet been consumed. +func lexBareKey(lx *lexer) stateFn { + switch r := lx.next(); { + case isBareKeyChar(r): + return lexBareKey + case isWhitespace(r): + lx.backup() + lx.emit(itemText) + return lexKeyEnd + case r == keySep: + lx.backup() + lx.emit(itemText) + return lexKeyEnd + default: + return lx.errorf("bare keys cannot contain %q", r) + } +} + +// lexKeyEnd consumes the end of a key and trims whitespace (up to the key +// separator). +func lexKeyEnd(lx *lexer) stateFn { + switch r := lx.next(); { + case r == keySep: + return lexSkip(lx, lexValue) + case isWhitespace(r): + return lexSkip(lx, lexKeyEnd) + default: + return lx.errorf("expected key separator %q, but got %q instead", + keySep, r) + } +} + +// lexValue starts the consumption of a value anywhere a value is expected. +// lexValue will ignore whitespace. +// After a value is lexed, the last state on the next is popped and returned. +func lexValue(lx *lexer) stateFn { + // We allow whitespace to precede a value, but NOT newlines. + // In array syntax, the array states are responsible for ignoring newlines. + r := lx.next() + switch { + case isWhitespace(r): + return lexSkip(lx, lexValue) + case isDigit(r): + lx.backup() // avoid an extra state and use the same as above + return lexNumberOrDateStart + } + switch r { + case arrayStart: + lx.ignore() + lx.emit(itemArray) + return lexArrayValue + case inlineTableStart: + lx.ignore() + lx.emit(itemInlineTableStart) + return lexInlineTableValue + case stringStart: + if lx.accept(stringStart) { + if lx.accept(stringStart) { + lx.ignore() // Ignore """ + return lexMultilineString + } + lx.backup() + } + lx.ignore() // ignore the '"' + return lexString + case rawStringStart: + if lx.accept(rawStringStart) { + if lx.accept(rawStringStart) { + lx.ignore() // Ignore """ + return lexMultilineRawString + } + lx.backup() + } + lx.ignore() // ignore the "'" + return lexRawString + case '+', '-': + return lexNumberStart + case '.': // special error case, be kind to users + return lx.errorf("floats must start with a digit, not '.'") + } + if unicode.IsLetter(r) { + // Be permissive here; lexBool will give a nice error if the + // user wrote something like + // x = foo + // (i.e. not 'true' or 'false' but is something else word-like.) + lx.backup() + return lexBool + } + return lx.errorf("expected value but found %q instead", r) +} + +// lexArrayValue consumes one value in an array. It assumes that '[' or ',' +// have already been consumed. All whitespace and newlines are ignored. +func lexArrayValue(lx *lexer) stateFn { + r := lx.next() + switch { + case isWhitespace(r) || isNL(r): + return lexSkip(lx, lexArrayValue) + case r == commentStart: + lx.push(lexArrayValue) + return lexCommentStart + case r == comma: + return lx.errorf("unexpected comma") + case r == arrayEnd: + // NOTE(caleb): The spec isn't clear about whether you can have + // a trailing comma or not, so we'll allow it. + return lexArrayEnd + } + + lx.backup() + lx.push(lexArrayValueEnd) + return lexValue +} + +// lexArrayValueEnd consumes everything between the end of an array value and +// the next value (or the end of the array): it ignores whitespace and newlines +// and expects either a ',' or a ']'. +func lexArrayValueEnd(lx *lexer) stateFn { + r := lx.next() + switch { + case isWhitespace(r) || isNL(r): + return lexSkip(lx, lexArrayValueEnd) + case r == commentStart: + lx.push(lexArrayValueEnd) + return lexCommentStart + case r == comma: + lx.ignore() + return lexArrayValue // move on to the next value + case r == arrayEnd: + return lexArrayEnd + } + return lx.errorf( + "expected a comma or array terminator %q, but got %q instead", + arrayEnd, r, + ) +} + +// lexArrayEnd finishes the lexing of an array. +// It assumes that a ']' has just been consumed. +func lexArrayEnd(lx *lexer) stateFn { + lx.ignore() + lx.emit(itemArrayEnd) + return lx.pop() +} + +// lexInlineTableValue consumes one key/value pair in an inline table. +// It assumes that '{' or ',' have already been consumed. Whitespace is ignored. +func lexInlineTableValue(lx *lexer) stateFn { + r := lx.next() + switch { + case isWhitespace(r): + return lexSkip(lx, lexInlineTableValue) + case isNL(r): + return lx.errorf("newlines not allowed within inline tables") + case r == commentStart: + lx.push(lexInlineTableValue) + return lexCommentStart + case r == comma: + return lx.errorf("unexpected comma") + case r == inlineTableEnd: + return lexInlineTableEnd + } + lx.backup() + lx.push(lexInlineTableValueEnd) + return lexKeyStart +} + +// lexInlineTableValueEnd consumes everything between the end of an inline table +// key/value pair and the next pair (or the end of the table): +// it ignores whitespace and expects either a ',' or a '}'. +func lexInlineTableValueEnd(lx *lexer) stateFn { + r := lx.next() + switch { + case isWhitespace(r): + return lexSkip(lx, lexInlineTableValueEnd) + case isNL(r): + return lx.errorf("newlines not allowed within inline tables") + case r == commentStart: + lx.push(lexInlineTableValueEnd) + return lexCommentStart + case r == comma: + lx.ignore() + return lexInlineTableValue + case r == inlineTableEnd: + return lexInlineTableEnd + } + return lx.errorf("expected a comma or an inline table terminator %q, "+ + "but got %q instead", inlineTableEnd, r) +} + +// lexInlineTableEnd finishes the lexing of an inline table. +// It assumes that a '}' has just been consumed. +func lexInlineTableEnd(lx *lexer) stateFn { + lx.ignore() + lx.emit(itemInlineTableEnd) + return lx.pop() +} + +// lexString consumes the inner contents of a string. It assumes that the +// beginning '"' has already been consumed and ignored. +func lexString(lx *lexer) stateFn { + r := lx.next() + switch { + case r == eof: + return lx.errorf("unexpected EOF") + case isNL(r): + return lx.errorf("strings cannot contain newlines") + case r == '\\': + lx.push(lexString) + return lexStringEscape + case r == stringEnd: + lx.backup() + lx.emit(itemString) + lx.next() + lx.ignore() + return lx.pop() + } + return lexString +} + +// lexMultilineString consumes the inner contents of a string. It assumes that +// the beginning '"""' has already been consumed and ignored. +func lexMultilineString(lx *lexer) stateFn { + switch lx.next() { + case eof: + return lx.errorf("unexpected EOF") + case '\\': + return lexMultilineStringEscape + case stringEnd: + if lx.accept(stringEnd) { + if lx.accept(stringEnd) { + lx.backup() + lx.backup() + lx.backup() + lx.emit(itemMultilineString) + lx.next() + lx.next() + lx.next() + lx.ignore() + return lx.pop() + } + lx.backup() + } + } + return lexMultilineString +} + +// lexRawString consumes a raw string. Nothing can be escaped in such a string. +// It assumes that the beginning "'" has already been consumed and ignored. +func lexRawString(lx *lexer) stateFn { + r := lx.next() + switch { + case r == eof: + return lx.errorf("unexpected EOF") + case isNL(r): + return lx.errorf("strings cannot contain newlines") + case r == rawStringEnd: + lx.backup() + lx.emit(itemRawString) + lx.next() + lx.ignore() + return lx.pop() + } + return lexRawString +} + +// lexMultilineRawString consumes a raw string. Nothing can be escaped in such +// a string. It assumes that the beginning "'''" has already been consumed and +// ignored. +func lexMultilineRawString(lx *lexer) stateFn { + switch lx.next() { + case eof: + return lx.errorf("unexpected EOF") + case rawStringEnd: + if lx.accept(rawStringEnd) { + if lx.accept(rawStringEnd) { + lx.backup() + lx.backup() + lx.backup() + lx.emit(itemRawMultilineString) + lx.next() + lx.next() + lx.next() + lx.ignore() + return lx.pop() + } + lx.backup() + } + } + return lexMultilineRawString +} + +// lexMultilineStringEscape consumes an escaped character. It assumes that the +// preceding '\\' has already been consumed. +func lexMultilineStringEscape(lx *lexer) stateFn { + // Handle the special case first: + if isNL(lx.next()) { + return lexMultilineString + } + lx.backup() + lx.push(lexMultilineString) + return lexStringEscape(lx) +} + +func lexStringEscape(lx *lexer) stateFn { + r := lx.next() + switch r { + case 'b': + fallthrough + case 't': + fallthrough + case 'n': + fallthrough + case 'f': + fallthrough + case 'r': + fallthrough + case '"': + fallthrough + case '\\': + return lx.pop() + case 'u': + return lexShortUnicodeEscape + case 'U': + return lexLongUnicodeEscape + } + return lx.errorf("invalid escape character %q; only the following "+ + "escape characters are allowed: "+ + `\b, \t, \n, \f, \r, \", \\, \uXXXX, and \UXXXXXXXX`, r) +} + +func lexShortUnicodeEscape(lx *lexer) stateFn { + var r rune + for i := 0; i < 4; i++ { + r = lx.next() + if !isHexadecimal(r) { + return lx.errorf(`expected four hexadecimal digits after '\u', `+ + "but got %q instead", lx.current()) + } + } + return lx.pop() +} + +func lexLongUnicodeEscape(lx *lexer) stateFn { + var r rune + for i := 0; i < 8; i++ { + r = lx.next() + if !isHexadecimal(r) { + return lx.errorf(`expected eight hexadecimal digits after '\U', `+ + "but got %q instead", lx.current()) + } + } + return lx.pop() +} + +// lexNumberOrDateStart consumes either an integer, a float, or datetime. +func lexNumberOrDateStart(lx *lexer) stateFn { + r := lx.next() + if isDigit(r) { + return lexNumberOrDate + } + switch r { + case '_': + return lexNumber + case 'e', 'E': + return lexFloat + case '.': + return lx.errorf("floats must start with a digit, not '.'") + } + return lx.errorf("expected a digit but got %q", r) +} + +// lexNumberOrDate consumes either an integer, float or datetime. +func lexNumberOrDate(lx *lexer) stateFn { + r := lx.next() + if isDigit(r) { + return lexNumberOrDate + } + switch r { + case '-': + return lexDatetime + case '_': + return lexNumber + case '.', 'e', 'E': + return lexFloat + } + + lx.backup() + lx.emit(itemInteger) + return lx.pop() +} + +// lexDatetime consumes a Datetime, to a first approximation. +// The parser validates that it matches one of the accepted formats. +func lexDatetime(lx *lexer) stateFn { + r := lx.next() + if isDigit(r) { + return lexDatetime + } + switch r { + case '-', 'T', ':', '.', 'Z', '+': + return lexDatetime + } + + lx.backup() + lx.emit(itemDatetime) + return lx.pop() +} + +// lexNumberStart consumes either an integer or a float. It assumes that a sign +// has already been read, but that *no* digits have been consumed. +// lexNumberStart will move to the appropriate integer or float states. +func lexNumberStart(lx *lexer) stateFn { + // We MUST see a digit. Even floats have to start with a digit. + r := lx.next() + if !isDigit(r) { + if r == '.' { + return lx.errorf("floats must start with a digit, not '.'") + } + return lx.errorf("expected a digit but got %q", r) + } + return lexNumber +} + +// lexNumber consumes an integer or a float after seeing the first digit. +func lexNumber(lx *lexer) stateFn { + r := lx.next() + if isDigit(r) { + return lexNumber + } + switch r { + case '_': + return lexNumber + case '.', 'e', 'E': + return lexFloat + } + + lx.backup() + lx.emit(itemInteger) + return lx.pop() +} + +// lexFloat consumes the elements of a float. It allows any sequence of +// float-like characters, so floats emitted by the lexer are only a first +// approximation and must be validated by the parser. +func lexFloat(lx *lexer) stateFn { + r := lx.next() + if isDigit(r) { + return lexFloat + } + switch r { + case '_', '.', '-', '+', 'e', 'E': + return lexFloat + } + + lx.backup() + lx.emit(itemFloat) + return lx.pop() +} + +// lexBool consumes a bool string: 'true' or 'false. +func lexBool(lx *lexer) stateFn { + var rs []rune + for { + r := lx.next() + if !unicode.IsLetter(r) { + lx.backup() + break + } + rs = append(rs, r) + } + s := string(rs) + switch s { + case "true", "false": + lx.emit(itemBool) + return lx.pop() + } + return lx.errorf("expected value but found %q instead", s) +} + +// lexCommentStart begins the lexing of a comment. It will emit +// itemCommentStart and consume no characters, passing control to lexComment. +func lexCommentStart(lx *lexer) stateFn { + lx.ignore() + lx.emit(itemCommentStart) + return lexComment +} + +// lexComment lexes an entire comment. It assumes that '#' has been consumed. +// It will consume *up to* the first newline character, and pass control +// back to the last state on the stack. +func lexComment(lx *lexer) stateFn { + r := lx.peek() + if isNL(r) || r == eof { + lx.emit(itemText) + return lx.pop() + } + lx.next() + return lexComment +} + +// lexSkip ignores all slurped input and moves on to the next state. +func lexSkip(lx *lexer, nextState stateFn) stateFn { + return func(lx *lexer) stateFn { + lx.ignore() + return nextState + } +} + +// isWhitespace returns true if `r` is a whitespace character according +// to the spec. +func isWhitespace(r rune) bool { + return r == '\t' || r == ' ' +} + +func isNL(r rune) bool { + return r == '\n' || r == '\r' +} + +func isDigit(r rune) bool { + return r >= '0' && r <= '9' +} + +func isHexadecimal(r rune) bool { + return (r >= '0' && r <= '9') || + (r >= 'a' && r <= 'f') || + (r >= 'A' && r <= 'F') +} + +func isBareKeyChar(r rune) bool { + return (r >= 'A' && r <= 'Z') || + (r >= 'a' && r <= 'z') || + (r >= '0' && r <= '9') || + r == '_' || + r == '-' +} + +func (itype itemType) String() string { + switch itype { + case itemError: + return "Error" + case itemNIL: + return "NIL" + case itemEOF: + return "EOF" + case itemText: + return "Text" + case itemString, itemRawString, itemMultilineString, itemRawMultilineString: + return "String" + case itemBool: + return "Bool" + case itemInteger: + return "Integer" + case itemFloat: + return "Float" + case itemDatetime: + return "DateTime" + case itemTableStart: + return "TableStart" + case itemTableEnd: + return "TableEnd" + case itemKeyStart: + return "KeyStart" + case itemArray: + return "Array" + case itemArrayEnd: + return "ArrayEnd" + case itemCommentStart: + return "CommentStart" + } + panic(fmt.Sprintf("BUG: Unknown type '%d'.", int(itype))) +} + +func (item item) String() string { + return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val) +} diff --git a/vendor/github.com/BurntSushi/toml/parse.go b/vendor/github.com/BurntSushi/toml/parse.go new file mode 100644 index 000000000..50869ef92 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/parse.go @@ -0,0 +1,592 @@ +package toml + +import ( + "fmt" + "strconv" + "strings" + "time" + "unicode" + "unicode/utf8" +) + +type parser struct { + mapping map[string]interface{} + types map[string]tomlType + lx *lexer + + // A list of keys in the order that they appear in the TOML data. + ordered []Key + + // the full key for the current hash in scope + context Key + + // the base key name for everything except hashes + currentKey string + + // rough approximation of line number + approxLine int + + // A map of 'key.group.names' to whether they were created implicitly. + implicits map[string]bool +} + +type parseError string + +func (pe parseError) Error() string { + return string(pe) +} + +func parse(data string) (p *parser, err error) { + defer func() { + if r := recover(); r != nil { + var ok bool + if err, ok = r.(parseError); ok { + return + } + panic(r) + } + }() + + p = &parser{ + mapping: make(map[string]interface{}), + types: make(map[string]tomlType), + lx: lex(data), + ordered: make([]Key, 0), + implicits: make(map[string]bool), + } + for { + item := p.next() + if item.typ == itemEOF { + break + } + p.topLevel(item) + } + + return p, nil +} + +func (p *parser) panicf(format string, v ...interface{}) { + msg := fmt.Sprintf("Near line %d (last key parsed '%s'): %s", + p.approxLine, p.current(), fmt.Sprintf(format, v...)) + panic(parseError(msg)) +} + +func (p *parser) next() item { + it := p.lx.nextItem() + if it.typ == itemError { + p.panicf("%s", it.val) + } + return it +} + +func (p *parser) bug(format string, v ...interface{}) { + panic(fmt.Sprintf("BUG: "+format+"\n\n", v...)) +} + +func (p *parser) expect(typ itemType) item { + it := p.next() + p.assertEqual(typ, it.typ) + return it +} + +func (p *parser) assertEqual(expected, got itemType) { + if expected != got { + p.bug("Expected '%s' but got '%s'.", expected, got) + } +} + +func (p *parser) topLevel(item item) { + switch item.typ { + case itemCommentStart: + p.approxLine = item.line + p.expect(itemText) + case itemTableStart: + kg := p.next() + p.approxLine = kg.line + + var key Key + for ; kg.typ != itemTableEnd && kg.typ != itemEOF; kg = p.next() { + key = append(key, p.keyString(kg)) + } + p.assertEqual(itemTableEnd, kg.typ) + + p.establishContext(key, false) + p.setType("", tomlHash) + p.ordered = append(p.ordered, key) + case itemArrayTableStart: + kg := p.next() + p.approxLine = kg.line + + var key Key + for ; kg.typ != itemArrayTableEnd && kg.typ != itemEOF; kg = p.next() { + key = append(key, p.keyString(kg)) + } + p.assertEqual(itemArrayTableEnd, kg.typ) + + p.establishContext(key, true) + p.setType("", tomlArrayHash) + p.ordered = append(p.ordered, key) + case itemKeyStart: + kname := p.next() + p.approxLine = kname.line + p.currentKey = p.keyString(kname) + + val, typ := p.value(p.next()) + p.setValue(p.currentKey, val) + p.setType(p.currentKey, typ) + p.ordered = append(p.ordered, p.context.add(p.currentKey)) + p.currentKey = "" + default: + p.bug("Unexpected type at top level: %s", item.typ) + } +} + +// Gets a string for a key (or part of a key in a table name). +func (p *parser) keyString(it item) string { + switch it.typ { + case itemText: + return it.val + case itemString, itemMultilineString, + itemRawString, itemRawMultilineString: + s, _ := p.value(it) + return s.(string) + default: + p.bug("Unexpected key type: %s", it.typ) + panic("unreachable") + } +} + +// value translates an expected value from the lexer into a Go value wrapped +// as an empty interface. +func (p *parser) value(it item) (interface{}, tomlType) { + switch it.typ { + case itemString: + return p.replaceEscapes(it.val), p.typeOfPrimitive(it) + case itemMultilineString: + trimmed := stripFirstNewline(stripEscapedWhitespace(it.val)) + return p.replaceEscapes(trimmed), p.typeOfPrimitive(it) + case itemRawString: + return it.val, p.typeOfPrimitive(it) + case itemRawMultilineString: + return stripFirstNewline(it.val), p.typeOfPrimitive(it) + case itemBool: + switch it.val { + case "true": + return true, p.typeOfPrimitive(it) + case "false": + return false, p.typeOfPrimitive(it) + } + p.bug("Expected boolean value, but got '%s'.", it.val) + case itemInteger: + if !numUnderscoresOK(it.val) { + p.panicf("Invalid integer %q: underscores must be surrounded by digits", + it.val) + } + val := strings.Replace(it.val, "_", "", -1) + num, err := strconv.ParseInt(val, 10, 64) + if err != nil { + // Distinguish integer values. Normally, it'd be a bug if the lexer + // provides an invalid integer, but it's possible that the number is + // out of range of valid values (which the lexer cannot determine). + // So mark the former as a bug but the latter as a legitimate user + // error. + if e, ok := err.(*strconv.NumError); ok && + e.Err == strconv.ErrRange { + + p.panicf("Integer '%s' is out of the range of 64-bit "+ + "signed integers.", it.val) + } else { + p.bug("Expected integer value, but got '%s'.", it.val) + } + } + return num, p.typeOfPrimitive(it) + case itemFloat: + parts := strings.FieldsFunc(it.val, func(r rune) bool { + switch r { + case '.', 'e', 'E': + return true + } + return false + }) + for _, part := range parts { + if !numUnderscoresOK(part) { + p.panicf("Invalid float %q: underscores must be "+ + "surrounded by digits", it.val) + } + } + if !numPeriodsOK(it.val) { + // As a special case, numbers like '123.' or '1.e2', + // which are valid as far as Go/strconv are concerned, + // must be rejected because TOML says that a fractional + // part consists of '.' followed by 1+ digits. + p.panicf("Invalid float %q: '.' must be followed "+ + "by one or more digits", it.val) + } + val := strings.Replace(it.val, "_", "", -1) + num, err := strconv.ParseFloat(val, 64) + if err != nil { + if e, ok := err.(*strconv.NumError); ok && + e.Err == strconv.ErrRange { + + p.panicf("Float '%s' is out of the range of 64-bit "+ + "IEEE-754 floating-point numbers.", it.val) + } else { + p.panicf("Invalid float value: %q", it.val) + } + } + return num, p.typeOfPrimitive(it) + case itemDatetime: + var t time.Time + var ok bool + var err error + for _, format := range []string{ + "2006-01-02T15:04:05Z07:00", + "2006-01-02T15:04:05", + "2006-01-02", + } { + t, err = time.ParseInLocation(format, it.val, time.Local) + if err == nil { + ok = true + break + } + } + if !ok { + p.panicf("Invalid TOML Datetime: %q.", it.val) + } + return t, p.typeOfPrimitive(it) + case itemArray: + array := make([]interface{}, 0) + types := make([]tomlType, 0) + + for it = p.next(); it.typ != itemArrayEnd; it = p.next() { + if it.typ == itemCommentStart { + p.expect(itemText) + continue + } + + val, typ := p.value(it) + array = append(array, val) + types = append(types, typ) + } + return array, p.typeOfArray(types) + case itemInlineTableStart: + var ( + hash = make(map[string]interface{}) + outerContext = p.context + outerKey = p.currentKey + ) + + p.context = append(p.context, p.currentKey) + p.currentKey = "" + for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() { + if it.typ != itemKeyStart { + p.bug("Expected key start but instead found %q, around line %d", + it.val, p.approxLine) + } + if it.typ == itemCommentStart { + p.expect(itemText) + continue + } + + // retrieve key + k := p.next() + p.approxLine = k.line + kname := p.keyString(k) + + // retrieve value + p.currentKey = kname + val, typ := p.value(p.next()) + // make sure we keep metadata up to date + p.setType(kname, typ) + p.ordered = append(p.ordered, p.context.add(p.currentKey)) + hash[kname] = val + } + p.context = outerContext + p.currentKey = outerKey + return hash, tomlHash + } + p.bug("Unexpected value type: %s", it.typ) + panic("unreachable") +} + +// numUnderscoresOK checks whether each underscore in s is surrounded by +// characters that are not underscores. +func numUnderscoresOK(s string) bool { + accept := false + for _, r := range s { + if r == '_' { + if !accept { + return false + } + accept = false + continue + } + accept = true + } + return accept +} + +// numPeriodsOK checks whether every period in s is followed by a digit. +func numPeriodsOK(s string) bool { + period := false + for _, r := range s { + if period && !isDigit(r) { + return false + } + period = r == '.' + } + return !period +} + +// establishContext sets the current context of the parser, +// where the context is either a hash or an array of hashes. Which one is +// set depends on the value of the `array` parameter. +// +// Establishing the context also makes sure that the key isn't a duplicate, and +// will create implicit hashes automatically. +func (p *parser) establishContext(key Key, array bool) { + var ok bool + + // Always start at the top level and drill down for our context. + hashContext := p.mapping + keyContext := make(Key, 0) + + // We only need implicit hashes for key[0:-1] + for _, k := range key[0 : len(key)-1] { + _, ok = hashContext[k] + keyContext = append(keyContext, k) + + // No key? Make an implicit hash and move on. + if !ok { + p.addImplicit(keyContext) + hashContext[k] = make(map[string]interface{}) + } + + // If the hash context is actually an array of tables, then set + // the hash context to the last element in that array. + // + // Otherwise, it better be a table, since this MUST be a key group (by + // virtue of it not being the last element in a key). + switch t := hashContext[k].(type) { + case []map[string]interface{}: + hashContext = t[len(t)-1] + case map[string]interface{}: + hashContext = t + default: + p.panicf("Key '%s' was already created as a hash.", keyContext) + } + } + + p.context = keyContext + if array { + // If this is the first element for this array, then allocate a new + // list of tables for it. + k := key[len(key)-1] + if _, ok := hashContext[k]; !ok { + hashContext[k] = make([]map[string]interface{}, 0, 5) + } + + // Add a new table. But make sure the key hasn't already been used + // for something else. + if hash, ok := hashContext[k].([]map[string]interface{}); ok { + hashContext[k] = append(hash, make(map[string]interface{})) + } else { + p.panicf("Key '%s' was already created and cannot be used as "+ + "an array.", keyContext) + } + } else { + p.setValue(key[len(key)-1], make(map[string]interface{})) + } + p.context = append(p.context, key[len(key)-1]) +} + +// setValue sets the given key to the given value in the current context. +// It will make sure that the key hasn't already been defined, account for +// implicit key groups. +func (p *parser) setValue(key string, value interface{}) { + var tmpHash interface{} + var ok bool + + hash := p.mapping + keyContext := make(Key, 0) + for _, k := range p.context { + keyContext = append(keyContext, k) + if tmpHash, ok = hash[k]; !ok { + p.bug("Context for key '%s' has not been established.", keyContext) + } + switch t := tmpHash.(type) { + case []map[string]interface{}: + // The context is a table of hashes. Pick the most recent table + // defined as the current hash. + hash = t[len(t)-1] + case map[string]interface{}: + hash = t + default: + p.bug("Expected hash to have type 'map[string]interface{}', but "+ + "it has '%T' instead.", tmpHash) + } + } + keyContext = append(keyContext, key) + + if _, ok := hash[key]; ok { + // Typically, if the given key has already been set, then we have + // to raise an error since duplicate keys are disallowed. However, + // it's possible that a key was previously defined implicitly. In this + // case, it is allowed to be redefined concretely. (See the + // `tests/valid/implicit-and-explicit-after.toml` test in `toml-test`.) + // + // But we have to make sure to stop marking it as an implicit. (So that + // another redefinition provokes an error.) + // + // Note that since it has already been defined (as a hash), we don't + // want to overwrite it. So our business is done. + if p.isImplicit(keyContext) { + p.removeImplicit(keyContext) + return + } + + // Otherwise, we have a concrete key trying to override a previous + // key, which is *always* wrong. + p.panicf("Key '%s' has already been defined.", keyContext) + } + hash[key] = value +} + +// setType sets the type of a particular value at a given key. +// It should be called immediately AFTER setValue. +// +// Note that if `key` is empty, then the type given will be applied to the +// current context (which is either a table or an array of tables). +func (p *parser) setType(key string, typ tomlType) { + keyContext := make(Key, 0, len(p.context)+1) + for _, k := range p.context { + keyContext = append(keyContext, k) + } + if len(key) > 0 { // allow type setting for hashes + keyContext = append(keyContext, key) + } + p.types[keyContext.String()] = typ +} + +// addImplicit sets the given Key as having been created implicitly. +func (p *parser) addImplicit(key Key) { + p.implicits[key.String()] = true +} + +// removeImplicit stops tagging the given key as having been implicitly +// created. +func (p *parser) removeImplicit(key Key) { + p.implicits[key.String()] = false +} + +// isImplicit returns true if the key group pointed to by the key was created +// implicitly. +func (p *parser) isImplicit(key Key) bool { + return p.implicits[key.String()] +} + +// current returns the full key name of the current context. +func (p *parser) current() string { + if len(p.currentKey) == 0 { + return p.context.String() + } + if len(p.context) == 0 { + return p.currentKey + } + return fmt.Sprintf("%s.%s", p.context, p.currentKey) +} + +func stripFirstNewline(s string) string { + if len(s) == 0 || s[0] != '\n' { + return s + } + return s[1:] +} + +func stripEscapedWhitespace(s string) string { + esc := strings.Split(s, "\\\n") + if len(esc) > 1 { + for i := 1; i < len(esc); i++ { + esc[i] = strings.TrimLeftFunc(esc[i], unicode.IsSpace) + } + } + return strings.Join(esc, "") +} + +func (p *parser) replaceEscapes(str string) string { + var replaced []rune + s := []byte(str) + r := 0 + for r < len(s) { + if s[r] != '\\' { + c, size := utf8.DecodeRune(s[r:]) + r += size + replaced = append(replaced, c) + continue + } + r += 1 + if r >= len(s) { + p.bug("Escape sequence at end of string.") + return "" + } + switch s[r] { + default: + p.bug("Expected valid escape code after \\, but got %q.", s[r]) + return "" + case 'b': + replaced = append(replaced, rune(0x0008)) + r += 1 + case 't': + replaced = append(replaced, rune(0x0009)) + r += 1 + case 'n': + replaced = append(replaced, rune(0x000A)) + r += 1 + case 'f': + replaced = append(replaced, rune(0x000C)) + r += 1 + case 'r': + replaced = append(replaced, rune(0x000D)) + r += 1 + case '"': + replaced = append(replaced, rune(0x0022)) + r += 1 + case '\\': + replaced = append(replaced, rune(0x005C)) + r += 1 + case 'u': + // At this point, we know we have a Unicode escape of the form + // `uXXXX` at [r, r+5). (Because the lexer guarantees this + // for us.) + escaped := p.asciiEscapeToUnicode(s[r+1 : r+5]) + replaced = append(replaced, escaped) + r += 5 + case 'U': + // At this point, we know we have a Unicode escape of the form + // `uXXXX` at [r, r+9). (Because the lexer guarantees this + // for us.) + escaped := p.asciiEscapeToUnicode(s[r+1 : r+9]) + replaced = append(replaced, escaped) + r += 9 + } + } + return string(replaced) +} + +func (p *parser) asciiEscapeToUnicode(bs []byte) rune { + s := string(bs) + hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32) + if err != nil { + p.bug("Could not parse '%s' as a hexadecimal number, but the "+ + "lexer claims it's OK: %s", s, err) + } + if !utf8.ValidRune(rune(hex)) { + p.panicf("Escaped character '\\u%s' is not valid UTF-8.", s) + } + return rune(hex) +} + +func isStringType(ty itemType) bool { + return ty == itemString || ty == itemMultilineString || + ty == itemRawString || ty == itemRawMultilineString +} diff --git a/vendor/github.com/BurntSushi/toml/session.vim b/vendor/github.com/BurntSushi/toml/session.vim new file mode 100644 index 000000000..562164be0 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/session.vim @@ -0,0 +1 @@ +au BufWritePost *.go silent!make tags > /dev/null 2>&1 diff --git a/vendor/github.com/BurntSushi/toml/type_check.go b/vendor/github.com/BurntSushi/toml/type_check.go new file mode 100644 index 000000000..c73f8afc1 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/type_check.go @@ -0,0 +1,91 @@ +package toml + +// tomlType represents any Go type that corresponds to a TOML type. +// While the first draft of the TOML spec has a simplistic type system that +// probably doesn't need this level of sophistication, we seem to be militating +// toward adding real composite types. +type tomlType interface { + typeString() string +} + +// typeEqual accepts any two types and returns true if they are equal. +func typeEqual(t1, t2 tomlType) bool { + if t1 == nil || t2 == nil { + return false + } + return t1.typeString() == t2.typeString() +} + +func typeIsHash(t tomlType) bool { + return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash) +} + +type tomlBaseType string + +func (btype tomlBaseType) typeString() string { + return string(btype) +} + +func (btype tomlBaseType) String() string { + return btype.typeString() +} + +var ( + tomlInteger tomlBaseType = "Integer" + tomlFloat tomlBaseType = "Float" + tomlDatetime tomlBaseType = "Datetime" + tomlString tomlBaseType = "String" + tomlBool tomlBaseType = "Bool" + tomlArray tomlBaseType = "Array" + tomlHash tomlBaseType = "Hash" + tomlArrayHash tomlBaseType = "ArrayHash" +) + +// typeOfPrimitive returns a tomlType of any primitive value in TOML. +// Primitive values are: Integer, Float, Datetime, String and Bool. +// +// Passing a lexer item other than the following will cause a BUG message +// to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime. +func (p *parser) typeOfPrimitive(lexItem item) tomlType { + switch lexItem.typ { + case itemInteger: + return tomlInteger + case itemFloat: + return tomlFloat + case itemDatetime: + return tomlDatetime + case itemString: + return tomlString + case itemMultilineString: + return tomlString + case itemRawString: + return tomlString + case itemRawMultilineString: + return tomlString + case itemBool: + return tomlBool + } + p.bug("Cannot infer primitive type of lex item '%s'.", lexItem) + panic("unreachable") +} + +// typeOfArray returns a tomlType for an array given a list of types of its +// values. +// +// In the current spec, if an array is homogeneous, then its type is always +// "Array". If the array is not homogeneous, an error is generated. +func (p *parser) typeOfArray(types []tomlType) tomlType { + // Empty arrays are cool. + if len(types) == 0 { + return tomlArray + } + + theType := types[0] + for _, t := range types[1:] { + if !typeEqual(theType, t) { + p.panicf("Array contains values of type '%s' and '%s', but "+ + "arrays must be homogeneous.", theType, t) + } + } + return tomlArray +} diff --git a/vendor/github.com/BurntSushi/toml/type_fields.go b/vendor/github.com/BurntSushi/toml/type_fields.go new file mode 100644 index 000000000..608997c22 --- /dev/null +++ b/vendor/github.com/BurntSushi/toml/type_fields.go @@ -0,0 +1,242 @@ +package toml + +// Struct field handling is adapted from code in encoding/json: +// +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the Go distribution. + +import ( + "reflect" + "sort" + "sync" +) + +// A field represents a single field found in a struct. +type field struct { + name string // the name of the field (`toml` tag included) + tag bool // whether field has a `toml` tag + index []int // represents the depth of an anonymous field + typ reflect.Type // the type of the field +} + +// byName sorts field by name, breaking ties with depth, +// then breaking ties with "name came from toml 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 TOML 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 != "" && !sf.Anonymous { // unexported + continue + } + opts := getOptions(sf.Tag) + if opts.skip { + continue + } + 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 opts.name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { + tagged := opts.name != "" + name := opts.name + if name == "" { + name = sf.Name + } + fields = append(fields, field{name, tagged, index, ft}) + 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 { + f := field{name: ft.Name(), index: index, typ: ft} + next = append(next, f) + } + } + } + } + + sort.Sort(byName(fields)) + + // Delete all fields that are hidden by the Go rules for embedded fields, + // except that fields with TOML 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 +// TOML 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 +} diff --git a/vendor/github.com/Djarvur/go-err113/.gitignore b/vendor/github.com/Djarvur/go-err113/.gitignore new file mode 100644 index 000000000..66fd13c90 --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/Djarvur/go-err113/.golangci.yml b/vendor/github.com/Djarvur/go-err113/.golangci.yml new file mode 100644 index 000000000..2abdfc639 --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/.golangci.yml @@ -0,0 +1,150 @@ +# This file contains all available configuration options +# with their default values. + +# options for analysis running +run: + # default concurrency is a available CPU number + concurrency: 4 + + # timeout for analysis, e.g. 30s, 5m, default is 1m + deadline: 15m + + # exit code when at least one issue was found, default is 1 + issues-exit-code: 1 + + # include test files or not, default is true + tests: false + + # list of build tags, all linters use it. Default is empty list. + #build-tags: + # - mytag + + # which dirs to skip: they won't be analyzed; + # can use regexp here: generated.*, regexp is applied on full path; + # default value is empty list, but next dirs are always skipped independently + # from this option's value: + # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ + skip-dirs: + - /gen$ + + # which files to skip: they will be analyzed, but issues from them + # won't be reported. Default value is empty list, but there is + # no need to include all autogenerated files, we confidently recognize + # autogenerated files. If it's not please let us know. + skip-files: + - ".*\\.my\\.go$" + - lib/bad.go + - ".*\\.template\\.go$" + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number" + format: colored-line-number + + # print lines of code with issue, default is true + print-issued-lines: true + + # print linter name in the end of issue text, default is true + print-linter-name: true + +# all available settings of specific linters +linters-settings: + errcheck: + # report about not checking of errors in type assetions: `a := b.(MyStruct)`; + # default is false: such cases aren't reported by default. + check-type-assertions: false + + # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; + # default is false: such cases aren't reported by default. + check-blank: false + govet: + # report about shadowed variables + check-shadowing: true + + # Obtain type information from installed (to $GOPATH/pkg) package files: + # golangci-lint will execute `go install -i` and `go test -i` for analyzed packages + # before analyzing them. + # By default this option is disabled and govet gets type information by loader from source code. + # Loading from source code is slow, but it's done only once for all linters. + # Go-installing of packages first time is much slower than loading them from source code, + # therefore this option is disabled by default. + # But repeated installation is fast in go >= 1.10 because of build caching. + # Enable this option only if all conditions are met: + # 1. you use only "fast" linters (--fast e.g.): no program loading occurs + # 2. you use go >= 1.10 + # 3. you do repeated runs (false for CI) or cache $GOPATH/pkg or `go env GOCACHE` dir in CI. + use-installed-packages: false + golint: + # minimal confidence for issues, default is 0.8 + min-confidence: 0.8 + gofmt: + # simplify code: gofmt with `-s` option, true by default + simplify: true + gocyclo: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 10 + maligned: + # print struct with more effective memory layout or not, false by default + suggest-new: true + dupl: + # tokens count to trigger issue, 150 by default + threshold: 100 + goconst: + # minimal length of string constant, 3 by default + min-len: 3 + # minimal occurrences count to trigger, 3 by default + min-occurrences: 3 + depguard: + list-type: blacklist + include-go-root: false + packages: + - github.com/davecgh/go-spew/spew + +linters: + #enable: + # - staticcheck + # - unused + # - gosimple + enable-all: true + disable: + - lll + disable-all: false + #presets: + # - bugs + # - unused + fast: false + +issues: + # List of regexps of issue texts to exclude, empty list by default. + # But independently from this option we use default exclude patterns, + # it can be disabled by `exclude-use-default: false`. To list all + # excluded by default patterns execute `golangci-lint run --help` + exclude: + - "`parseTained` is unused" + - "`parseState` is unused" + + # Independently from option `exclude` we use default exclude patterns, + # it can be disabled by this option. To list all + # excluded by default patterns execute `golangci-lint run --help`. + # Default value for this option is false. + exclude-use-default: false + + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + max-per-linter: 0 + + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + max-same: 0 + + # Show only new issues: if there are unstaged changes or untracked files, + # only those changes are analyzed, else only changes in HEAD~ are analyzed. + # It's a super-useful option for integration of golangci-lint into existing + # large codebase. It's not practical to fix all existing issues at the moment + # of integration: much better don't allow issues in new code. + # Default is false. + new: false + + # Show only new issues created after git revision `REV` + #new-from-rev: REV + + # Show only new issues created in git patch with set file path. + #new-from-patch: path/to/patch/file \ No newline at end of file diff --git a/vendor/github.com/Djarvur/go-err113/.travis.yml b/vendor/github.com/Djarvur/go-err113/.travis.yml new file mode 100644 index 000000000..44fe77d53 --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/.travis.yml @@ -0,0 +1,24 @@ +language: go + +go: + - "1.13" + - "1.14" + - tip + +env: + - GO111MODULE=on + +before_install: + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover + - go get golang.org/x/tools/cmd/goimports + - wget -O - -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh + +script: + - test -z "$(goimports -d ./ 2>&1)" + - ./bin/golangci-lint run + - go test -v -race ./... + +after_success: + - test "$TRAVIS_GO_VERSION" = "1.14" && goveralls -service=travis-ci diff --git a/vendor/github.com/Djarvur/go-err113/LICENSE b/vendor/github.com/Djarvur/go-err113/LICENSE new file mode 100644 index 000000000..a78ad8c77 --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Djarvur + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/Djarvur/go-err113/README.adoc b/vendor/github.com/Djarvur/go-err113/README.adoc new file mode 100644 index 000000000..b4c1f4375 --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/README.adoc @@ -0,0 +1,73 @@ += err113 image:https://godoc.org/github.com/Djarvur/go-err113?status.svg["GoDoc",link="http://godoc.org/github.com/Djarvur/go-err113"] image:https://travis-ci.org/Djarvur/go-err113.svg["Build Status",link="https://travis-ci.org/Djarvur/go-err113"] image:https://coveralls.io/repos/Djarvur/go-err113/badge.svg?branch=master&service=github["Coverage Status",link="https://coveralls.io/github/Djarvur/go-err113?branch=master"] +Daniel Podolsky +:toc: + +Golang linter to check the errors handling expressions + +== Details + +Starting from Go 1.13 the standard `error` type behaviour was changed: one `error` could be derived from another with `fmt.Errorf()` method using `%w` format specifier. + +So the errors hierarchy could be built for flexible and responsible errors processing. + +And to make this possible at least two simple rules should be followed: + +1. `error` values should not be compared directly but with `errors.Is()` method. +1. `error` should not be created dynamically from scratch but by the wrapping the static (package-level) error. + +This linter is checking the code for these 2 rules compliance. + +=== Reports + +So, `err113` reports every `==` and `!=` comparison for exact `error` type variables except comparison to `nil` and `io.EOF`. + +Also, any call of `errors.New()` and `fmt.Errorf()` methods are reported except the calls used to initialise package-level variables and the `fmt.Errorf()` calls wrapping the other errors. + +Note: non-standard packages, like `github.com/pkg/errors` are ignored complitely. + +== Install + +``` +go get -u github.com/Djarvur/go-err113/cmd/err113 +``` + +== Usage + +Defined by link:https://pkg.go.dev/golang.org/x/tools/go/analysis/singlechecker[singlechecker] package. + +``` +err113: checks the error handling rules according to the Go 1.13 new error type + +Usage: err113 [-flag] [package] + + +Flags: + -V print version and exit + -all + no effect (deprecated) + -c int + display offending line with this many lines of context (default -1) + -cpuprofile string + write CPU profile to this file + -debug string + debug flags, any subset of "fpstv" + -fix + apply all suggested fixes + -flags + print analyzer flags in JSON + -json + emit JSON output + -memprofile string + write memory profile to this file + -source + no effect (deprecated) + -tags string + no effect (deprecated) + -trace string + write trace log to this file + -v no effect (deprecated) +``` + +== Thanks + +To link:https://github.com/quasilyte[Iskander (Alex) Sharipov] for the really useful advices. diff --git a/vendor/github.com/Djarvur/go-err113/comparison.go b/vendor/github.com/Djarvur/go-err113/comparison.go new file mode 100644 index 000000000..7e7777df6 --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/comparison.go @@ -0,0 +1,103 @@ +package err113 + +import ( + "fmt" + "go/ast" + "go/token" + "go/types" + + "golang.org/x/tools/go/analysis" +) + +func inspectComparision(pass *analysis.Pass, n ast.Node) bool { // nolint: unparam + // check whether the call expression matches time.Now().Sub() + be, ok := n.(*ast.BinaryExpr) + if !ok { + return true + } + + // check if it is a comparison operation + if be.Op != token.EQL && be.Op != token.NEQ { + return true + } + + // check that both left and right hand side are not nil + if pass.TypesInfo.Types[be.X].IsNil() || pass.TypesInfo.Types[be.Y].IsNil() { + return true + } + + // check that both left and right hand side are not io.EOF + if isEOF(be.X, pass.TypesInfo) || isEOF(be.Y, pass.TypesInfo) { + return true + } + + // check that both left and right hand side are errors + if !isError(be.X, pass.TypesInfo) && !isError(be.Y, pass.TypesInfo) { + return true + } + + oldExpr := render(pass.Fset, be) + + negate := "" + if be.Op == token.NEQ { + negate = "!" + } + + newExpr := fmt.Sprintf("%s%s.Is(%s, %s)", negate, "errors", be.X, be.Y) + + pass.Report( + analysis.Diagnostic{ + Pos: be.Pos(), + Message: fmt.Sprintf("do not compare errors directly, use errors.Is() instead: %q", oldExpr), + SuggestedFixes: []analysis.SuggestedFix{ + { + Message: fmt.Sprintf("should replace %q with %q", oldExpr, newExpr), + TextEdits: []analysis.TextEdit{ + { + Pos: be.Pos(), + End: be.End(), + NewText: []byte(newExpr), + }, + }, + }, + }, + }, + ) + + return true +} + +func isError(v ast.Expr, info *types.Info) bool { + if intf, ok := info.TypeOf(v).Underlying().(*types.Interface); ok { + return intf.NumMethods() == 1 && intf.Method(0).FullName() == "(error).Error" + } + + return false +} + +func isEOF(ex ast.Expr, info *types.Info) bool { + se, ok := ex.(*ast.SelectorExpr) + if !ok || se.Sel.Name != "EOF" { + return false + } + + if ep, ok := asImportedName(se.X, info); !ok || ep != "io" { + return false + } + + return true +} + +func asImportedName(ex ast.Expr, info *types.Info) (string, bool) { + ei, ok := ex.(*ast.Ident) + if !ok { + return "", false + } + + ep, ok := info.ObjectOf(ei).(*types.PkgName) + if !ok { + return "", false + } + + return ep.Imported().Name(), true +} diff --git a/vendor/github.com/Djarvur/go-err113/definition.go b/vendor/github.com/Djarvur/go-err113/definition.go new file mode 100644 index 000000000..79201c929 --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/definition.go @@ -0,0 +1,74 @@ +package err113 + +import ( + "go/ast" + "go/types" + "strings" + + "golang.org/x/tools/go/analysis" +) + +var methods2check = map[string]map[string]func(*ast.CallExpr, *types.Info) bool{ // nolint: gochecknoglobals + "errors": {"New": justTrue}, + "fmt": {"Errorf": checkWrap}, +} + +func justTrue(*ast.CallExpr, *types.Info) bool { + return true +} + +func checkWrap(ce *ast.CallExpr, info *types.Info) bool { + return !(len(ce.Args) > 0 && strings.Contains(toString(ce.Args[0], info), `%w`)) +} + +func inspectDefinition(pass *analysis.Pass, tlds map[*ast.CallExpr]struct{}, n ast.Node) bool { //nolint: unparam + // check whether the call expression matches time.Now().Sub() + ce, ok := n.(*ast.CallExpr) + if !ok { + return true + } + + if _, ok = tlds[ce]; ok { + return true + } + + fn, ok := ce.Fun.(*ast.SelectorExpr) + if !ok { + return true + } + + fxName, ok := asImportedName(fn.X, pass.TypesInfo) + if !ok { + return true + } + + methods, ok := methods2check[fxName] + if !ok { + return true + } + + checkFunc, ok := methods[fn.Sel.Name] + if !ok { + return true + } + + if !checkFunc(ce, pass.TypesInfo) { + return true + } + + pass.Reportf( + ce.Pos(), + "do not define dynamic errors, use wrapped static errors instead: %q", + render(pass.Fset, ce), + ) + + return true +} + +func toString(ex ast.Expr, info *types.Info) string { + if tv, ok := info.Types[ex]; ok && tv.Value != nil { + return tv.Value.String() + } + + return "" +} diff --git a/vendor/github.com/Djarvur/go-err113/err113.go b/vendor/github.com/Djarvur/go-err113/err113.go new file mode 100644 index 000000000..e9d93a7a0 --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/err113.go @@ -0,0 +1,90 @@ +// Package err113 is a Golang linter to check the errors handling expressions +package err113 + +import ( + "bytes" + "go/ast" + "go/printer" + "go/token" + + "golang.org/x/tools/go/analysis" +) + +// NewAnalyzer creates a new analysis.Analyzer instance tuned to run err113 checks +func NewAnalyzer() *analysis.Analyzer { + return &analysis.Analyzer{ + Name: "err113", + Doc: "checks the error handling rules according to the Go 1.13 new error type", + Run: run, + } +} + +func run(pass *analysis.Pass) (interface{}, error) { + for _, file := range pass.Files { + tlds := enumerateFileDecls(file) + + ast.Inspect( + file, + func(n ast.Node) bool { + return inspectComparision(pass, n) && + inspectDefinition(pass, tlds, n) + }, + ) + } + + return nil, nil +} + +// render returns the pretty-print of the given node +func render(fset *token.FileSet, x interface{}) string { + var buf bytes.Buffer + if err := printer.Fprint(&buf, fset, x); err != nil { + panic(err) + } + + return buf.String() +} + +func enumerateFileDecls(f *ast.File) map[*ast.CallExpr]struct{} { + res := make(map[*ast.CallExpr]struct{}) + + var ces []*ast.CallExpr // nolint: prealloc + + for _, d := range f.Decls { + ces = append(ces, enumerateDeclVars(d)...) + } + + for _, ce := range ces { + res[ce] = struct{}{} + } + + return res +} + +func enumerateDeclVars(d ast.Decl) (res []*ast.CallExpr) { + td, ok := d.(*ast.GenDecl) + if !ok || td.Tok != token.VAR { + return nil + } + + for _, s := range td.Specs { + res = append(res, enumerateSpecValues(s)...) + } + + return res +} + +func enumerateSpecValues(s ast.Spec) (res []*ast.CallExpr) { + vs, ok := s.(*ast.ValueSpec) + if !ok { + return nil + } + + for _, v := range vs.Values { + if ce, ok := v.(*ast.CallExpr); ok { + res = append(res, ce) + } + } + + return res +} diff --git a/vendor/github.com/Djarvur/go-err113/go.mod b/vendor/github.com/Djarvur/go-err113/go.mod new file mode 100644 index 000000000..6e28e9336 --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/go.mod @@ -0,0 +1,5 @@ +module github.com/Djarvur/go-err113 + +go 1.13 + +require golang.org/x/tools v0.0.0-20200324003944-a576cf524670 diff --git a/vendor/github.com/Djarvur/go-err113/go.sum b/vendor/github.com/Djarvur/go-err113/go.sum new file mode 100644 index 000000000..dab64209d --- /dev/null +++ b/vendor/github.com/Djarvur/go-err113/go.sum @@ -0,0 +1,20 @@ +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200324003944-a576cf524670 h1:fW7EP/GZqIvbHessHd1PLca+77TBOsRBqtaybMgXJq8= +golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/OpenPeeDeeP/depguard/.gitignore b/vendor/github.com/OpenPeeDeeP/depguard/.gitignore new file mode 100644 index 000000000..97cca67c6 --- /dev/null +++ b/vendor/github.com/OpenPeeDeeP/depguard/.gitignore @@ -0,0 +1,14 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +.idea diff --git a/vendor/github.com/OpenPeeDeeP/depguard/LICENSE b/vendor/github.com/OpenPeeDeeP/depguard/LICENSE new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/vendor/github.com/OpenPeeDeeP/depguard/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/vendor/github.com/OpenPeeDeeP/depguard/README.md b/vendor/github.com/OpenPeeDeeP/depguard/README.md new file mode 100644 index 000000000..d704ce6ad --- /dev/null +++ b/vendor/github.com/OpenPeeDeeP/depguard/README.md @@ -0,0 +1,77 @@ +# Depguard + +Go linter that checks package imports are in a list of acceptable packages. It +supports a white list and black list option and can do prefix or glob matching. +This allows you to allow imports from a whole organization or only +allow specific packages within a repository. It is recommended to use prefix +matching as it is faster than glob matching. The fewer glob matches the better. + +> If a pattern is matched by prefix it does not try to match via glob. + +## Install + +```bash +go get -u github.com/OpenPeeDeeP/depguard +``` + +## Config + +By default, Depguard looks for a file named `.depguard.json` in the current +current working directory. If it is somewhere else, pass in the `-c` flag with +the location of your configuration file. + +The following is an example configuration file. + +```json +{ + "type": "whitelist", + "packages": ["github.com/OpenPeeDeeP/depguard"], + "packageErrorMessages": { + "github.com/OpenPeeDeeP/depguards": "Please use \"github.com/OpenPeeDeeP/depguard\"," + }, + "inTests": ["github.com/stretchr/testify"], + "includeGoStdLib": true +} +``` + +- `type` can be either `whitelist` or `blacklist`. This check is case insensitive. + If not specified the default is `blacklist`. +- `packages` is a list of packages for the list type specified. +- `packageErrorMessages` is a mapping from packages to the error message to display +- `inTests` is a list of packages allowed/disallowed only in test files. +- Set `includeGoStdLib` (`includeGoRoot` for backwards compatability) to true if you want to check the list against standard lib. + If not specified the default is false. + +## Gometalinter + +The binary installation of this linter can be used with +[Gometalinter](github.com/alecthomas/gometalinter). + +If you use a configuration file for Gometalinter then the following will need to +be added to your configuration file. + +```json +{ + "linters": { + "depguard": { + "command": "depguard -c path/to/config.json", + "pattern": "PATH:LINE:COL:MESSAGE", + "installFrom": "github.com/OpenPeeDeeP/depguard", + "isFast": true, + "partitionStrategy": "packages" + } + } +} +``` + +If you prefer the command line way the following will work for you as well. + +```bash +gometalinter --linter='depguard:depguard -c path/to/config.json:PATH:LINE:COL:MESSAGE' +``` + +## Golangci-lint + +This linter was built with +[Golangci-lint](https://github.com/golangci/golangci-lint) in mind. It is compatable +and read their docs to see how to implement all their linters, including this one. diff --git a/vendor/github.com/OpenPeeDeeP/depguard/depguard.go b/vendor/github.com/OpenPeeDeeP/depguard/depguard.go new file mode 100644 index 000000000..1dbffb7d6 --- /dev/null +++ b/vendor/github.com/OpenPeeDeeP/depguard/depguard.go @@ -0,0 +1,241 @@ +package depguard + +import ( + "go/build" + "go/token" + "io/ioutil" + "path" + "sort" + "strings" + + "github.com/gobwas/glob" + "golang.org/x/tools/go/loader" +) + +// ListType states what kind of list is passed in. +type ListType int + +const ( + // LTBlacklist states the list given is a blacklist. (default) + LTBlacklist ListType = iota + // LTWhitelist states the list given is a whitelist. + LTWhitelist +) + +// StringToListType makes it easier to turn a string into a ListType. +// It assumes that the string representation is lower case. +var StringToListType = map[string]ListType{ + "whitelist": LTWhitelist, + "blacklist": LTBlacklist, +} + +// Issue with the package with PackageName at the Position. +type Issue struct { + PackageName string + Position token.Position +} + +// Depguard checks imports to make sure they follow the given list and constraints. +type Depguard struct { + ListType ListType + IncludeGoRoot bool + + Packages []string + prefixPackages []string + globPackages []glob.Glob + + TestPackages []string + prefixTestPackages []string + globTestPackages []glob.Glob + + prefixRoot []string +} + +// Run checks for dependencies given the program and validates them against +// Packages. +func (dg *Depguard) Run(config *loader.Config, prog *loader.Program) ([]*Issue, error) { + // Shortcut execution on an empty blacklist as that means every package is allowed + if dg.ListType == LTBlacklist && len(dg.Packages) == 0 { + return nil, nil + } + + if err := dg.initialize(config, prog); err != nil { + return nil, err + } + directImports, err := dg.createImportMap(prog) + if err != nil { + return nil, err + } + var issues []*Issue + for pkg, positions := range directImports { + for _, pos := range positions { + + prefixList, globList := dg.prefixPackages, dg.globPackages + if len(dg.TestPackages) > 0 && strings.Index(pos.Filename, "_test.go") != -1 { + prefixList, globList = dg.prefixTestPackages, dg.globTestPackages + } + + if dg.flagIt(pkg, prefixList, globList) { + issues = append(issues, &Issue{ + PackageName: pkg, + Position: pos, + }) + } + } + } + return issues, nil +} + +func (dg *Depguard) initialize(config *loader.Config, prog *loader.Program) error { + // parse ordinary guarded packages + for _, pkg := range dg.Packages { + if strings.ContainsAny(pkg, "!?*[]{}") { + g, err := glob.Compile(pkg, '/') + if err != nil { + return err + } + dg.globPackages = append(dg.globPackages, g) + } else { + dg.prefixPackages = append(dg.prefixPackages, pkg) + } + } + + // Sort the packages so we can have a faster search in the array + sort.Strings(dg.prefixPackages) + + // parse guarded tests packages + for _, pkg := range dg.TestPackages { + if strings.ContainsAny(pkg, "!?*[]{}") { + g, err := glob.Compile(pkg, '/') + if err != nil { + return err + } + dg.globTestPackages = append(dg.globTestPackages, g) + } else { + dg.prefixTestPackages = append(dg.prefixTestPackages, pkg) + } + } + + // Sort the test packages so we can have a faster search in the array + sort.Strings(dg.prefixTestPackages) + + if !dg.IncludeGoRoot { + var err error + dg.prefixRoot, err = listRootPrefixs(config.Build) + if err != nil { + return err + } + } + + return nil +} + +func (dg *Depguard) createImportMap(prog *loader.Program) (map[string][]token.Position, error) { + importMap := make(map[string][]token.Position) + // For the directly imported packages + for _, imported := range prog.InitialPackages() { + // Go through their files + for _, file := range imported.Files { + // And populate a map of all direct imports and their positions + // This will filter out GoRoot depending on the Depguard.IncludeGoRoot + for _, fileImport := range file.Imports { + fileImportPath := cleanBasicLitString(fileImport.Path.Value) + if !dg.IncludeGoRoot && dg.isRoot(fileImportPath) { + continue + } + position := prog.Fset.Position(fileImport.Pos()) + positions, found := importMap[fileImportPath] + if !found { + importMap[fileImportPath] = []token.Position{ + position, + } + continue + } + importMap[fileImportPath] = append(positions, position) + } + } + } + return importMap, nil +} + +func pkgInList(pkg string, prefixList []string, globList []glob.Glob) bool { + if pkgInPrefixList(pkg, prefixList) { + return true + } + return pkgInGlobList(pkg, globList) +} + +func pkgInPrefixList(pkg string, prefixList []string) bool { + // Idx represents where in the package slice the passed in package would go + // when sorted. -1 Just means that it would be at the very front of the slice. + idx := sort.Search(len(prefixList), func(i int) bool { + return prefixList[i] > pkg + }) - 1 + // This means that the package passed in has no way to be prefixed by anything + // in the package list as it is already smaller then everything + if idx == -1 { + return false + } + return strings.HasPrefix(pkg, prefixList[idx]) +} + +func pkgInGlobList(pkg string, globList []glob.Glob) bool { + for _, g := range globList { + if g.Match(pkg) { + return true + } + } + return false +} + +// InList | WhiteList | BlackList +// y | | x +// n | x | +func (dg *Depguard) flagIt(pkg string, prefixList []string, globList []glob.Glob) bool { + return pkgInList(pkg, prefixList, globList) == (dg.ListType == LTBlacklist) +} + +func cleanBasicLitString(value string) string { + return strings.Trim(value, "\"\\") +} + +// We can do this as all imports that are not root are either prefixed with a domain +// or prefixed with `./` or `/` to dictate it is a local file reference +func listRootPrefixs(buildCtx *build.Context) ([]string, error) { + if buildCtx == nil { + buildCtx = &build.Default + } + root := path.Join(buildCtx.GOROOT, "src") + fs, err := ioutil.ReadDir(root) + if err != nil { + return nil, err + } + var pkgPrefix []string + for _, f := range fs { + if !f.IsDir() { + continue + } + pkgPrefix = append(pkgPrefix, f.Name()) + } + return pkgPrefix, nil +} + +func (dg *Depguard) isRoot(importPath string) bool { + // Idx represents where in the package slice the passed in package would go + // when sorted. -1 Just means that it would be at the very front of the slice. + idx := sort.Search(len(dg.prefixRoot), func(i int) bool { + return dg.prefixRoot[i] > importPath + }) - 1 + // This means that the package passed in has no way to be prefixed by anything + // in the package list as it is already smaller then everything + if idx == -1 { + return false + } + // if it is prefixed by a root prefix we need to check if it is an exact match + // or prefix with `/` as this could return false posative if the domain was + // `archive.com` for example as `archive` is a go root package. + if strings.HasPrefix(importPath, dg.prefixRoot[idx]) { + return strings.HasPrefix(importPath, dg.prefixRoot[idx]+"/") || importPath == dg.prefixRoot[idx] + } + return false +} diff --git a/vendor/github.com/OpenPeeDeeP/depguard/go.mod b/vendor/github.com/OpenPeeDeeP/depguard/go.mod new file mode 100644 index 000000000..5ad37edb8 --- /dev/null +++ b/vendor/github.com/OpenPeeDeeP/depguard/go.mod @@ -0,0 +1,9 @@ +module github.com/OpenPeeDeeP/depguard + +go 1.13 + +require ( + github.com/gobwas/glob v0.2.3 + github.com/kisielk/gotool v1.0.0 + golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b +) diff --git a/vendor/github.com/OpenPeeDeeP/depguard/go.sum b/vendor/github.com/OpenPeeDeeP/depguard/go.sum new file mode 100644 index 000000000..24693c36d --- /dev/null +++ b/vendor/github.com/OpenPeeDeeP/depguard/go.sum @@ -0,0 +1,6 @@ +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b h1:7tibmaEqrQYA+q6ri7NQjuxqSwechjtDHKq6/e85S38= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/vendor/github.com/bombsimon/wsl/v3/.gitignore b/vendor/github.com/bombsimon/wsl/v3/.gitignore new file mode 100644 index 000000000..1c8eba613 --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v3/.gitignore @@ -0,0 +1,70 @@ + +# Created by https://www.gitignore.io/api/go,vim,macos + +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +### Go Patch ### +/vendor/ +/Godeps/ + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + + +# End of https://www.gitignore.io/api/go,vim,macos diff --git a/vendor/github.com/bombsimon/wsl/v3/.travis.yml b/vendor/github.com/bombsimon/wsl/v3/.travis.yml new file mode 100644 index 000000000..5e2e26ed1 --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v3/.travis.yml @@ -0,0 +1,25 @@ +--- +language: go + +go: + - 1.13.x + - 1.12.x + - 1.11.x + +env: + global: + - GO111MODULE=on + +install: + - go get -v golang.org/x/tools/cmd/cover github.com/mattn/goveralls + +script: + - go test -v -covermode=count -coverprofile=coverage.out + +after_script: + - $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci + +notifications: + email: false + +# vim: set ts=2 sw=2 et: diff --git a/vendor/github.com/bombsimon/wsl/v3/LICENSE b/vendor/github.com/bombsimon/wsl/v3/LICENSE new file mode 100644 index 000000000..4dade6d1c --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v3/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Simon Sawert + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/bombsimon/wsl/v3/README.md b/vendor/github.com/bombsimon/wsl/v3/README.md new file mode 100644 index 000000000..c5068a8ac --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v3/README.md @@ -0,0 +1,125 @@ +# WSL - Whitespace Linter + +[![forthebadge](https://forthebadge.com/images/badges/made-with-go.svg)](https://forthebadge.com) +[![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com) + +[![Build Status](https://travis-ci.org/bombsimon/wsl.svg?branch=master)](https://travis-ci.org/bombsimon/wsl) +[![Coverage Status](https://coveralls.io/repos/github/bombsimon/wsl/badge.svg?branch=master)](https://coveralls.io/github/bombsimon/wsl?branch=master) + +WSL is a linter that enforces a very **non scientific** vision of how to make +code more readable by enforcing empty lines at the right places. + +I think too much code out there is to cuddly and a bit too warm for it's own +good, making it harder for other people to read and understand. The linter will +warn about newlines in and around blocks, in the beginning of files and other +places in the code. + +**I know this linter is aggressive** and a lot of projects I've tested it on +have failed miserably. For this linter to be useful at all I want to be open to +new ideas, configurations and discussions! Also note that some of the warnings +might be bugs or unintentional false positives so I would love an +[issue](https://github.com/bombsimon/wsl/issues/new) to fix, discuss, change or +make something configurable! + +## Installation + +### By `go get` (local installation) + +You can do that by using: + +```sh +go get -u github.com/bombsimon/wsl/cmd/... +``` + +### By golangci-lint (CI automation) + +`wsl` is already integrated with +[golangci-lint](https://github.com/golangci/golangci-lint). Please refer to the +instructions there. + +## Usage + +How to use depends on how you install `wsl`. + +### With local binary + +The general command format for `wsl` is: + +```sh +$ wsl [flags] [files...] +$ wsl [flags] + +# Examples + +$ wsl ./main.go +$ wsl --no-test ./main.go +$ wsl --allow-cuddle-declarations ./main.go +$ wsl --no-test --allow-cuddle-declaration ./main.go +$ wsl --no-test --allow-trailing-comment ./myProject/... +``` + +The "..." wildcard is not used like other `go` commands but instead can only +be to a relative or absolute path. + +By default, the linter will run on `./...` which means all go files in the +current path and all subsequent paths, including test files. To disable linting +test files, use `-n` or `--no-test`. + +### By `golangci-lint` (CI automation) + +The recommended command is: + +```sh +golangci-lint run --disable-all --enable wsl +``` + +For more information, please refer to +[golangci-lint](https://github.com/golangci/golangci-lint)'s documentation. + +## Issues and configuration + +The linter suppers a few ways to configure it to satisfy more than one kind of +code style. These settings could be set either with flags or with YAML +configuration if used via `golangci-lint`. + +The supported configuration can be found [in the documentation](doc/configuration.md). + +Below are the available checklist for any hit from `wsl`. If you do not see any, +feel free to raise an [issue](https://github.com/bombsimon/wsl/issues/new). + +> **Note**: this linter doesn't take in consideration the issues that will be +> fixed with `go fmt -s` so ensure that the code is properly formatted before +> use. + +* [Anonymous switch statements should never be cuddled](doc/rules.md#anonymous-switch-statements-should-never-be-cuddled) +* [Append only allowed to cuddle with appended value](doc/rules.md#append-only-allowed-to-cuddle-with-appended-value) +* [Assignments should only be cuddled with other assignments](doc/rules.md#assignments-should-only-be-cuddled-with-other-assignments) +* [Block should not end with a whitespace (or comment)](doc/rules.md#block-should-not-end-with-a-whitespace-or-comment) +* [Block should not start with a whitespace](doc/rules.md#block-should-not-start-with-a-whitespace) +* [Case block should end with newline at this size](doc/rules.md#case-block-should-end-with-newline-at-this-size) +* [Branch statements should not be cuddled if block has more than two lines](doc/rules.md#branch-statements-should-not-be-cuddled-if-block-has-more-than-two-lines) +* [Declarations should never be cuddled](doc/rules.md#declarations-should-never-be-cuddled) +* [Defer statements should only be cuddled with expressions on same variable](doc/rules.md#defer-statements-should-only-be-cuddled-with-expressions-on-same-variable) +* [Expressions should not be cuddled with blocks](doc/rules.md#expressions-should-not-be-cuddled-with-blocks) +* [Expressions should not be cuddled with declarations or returns](doc/rules.md#expressions-should-not-be-cuddled-with-declarations-or-returns) +* [For statement without condition should never be cuddled](doc/rules.md#for-statement-without-condition-should-never-be-cuddled) +* [For statements should only be cuddled with assignments used in the iteration](doc/rules.md#for-statements-should-only-be-cuddled-with-assignments-used-in-the-iteration) +* [Go statements can only invoke functions assigned on line above](doc/rules.md#go-statements-can-only-invoke-functions-assigned-on-line-above) +* [If statements should only be cuddled with assignments](doc/rules.md#if-statements-should-only-be-cuddled-with-assignments) +* [If statements should only be cuddled with assignments used in the if + statement + itself](doc/rules.md#if-statements-should-only-be-cuddled-with-assignments-used-in-the-if-statement-itself) +* [If statements that check an error must be cuddled with the statement that assigned the error](doc/rules.md#if-statements-that-check-an-error-must-be-cuddled-with-the-statement-that-assigned-the-error) +* [Only cuddled expressions if assigning variable or using from line + above](doc/rules.md#only-cuddled-expressions-if-assigning-variable-or-using-from-line-above) +* [Only one cuddle assignment allowed before defer statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-defer-statement) +* [Only one cuddle assginment allowed before for statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-for-statement) +* [Only one cuddle assignment allowed before go statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-go-statement) +* [Only one cuddle assignment allowed before if statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-if-statement) +* [Only one cuddle assignment allowed before range statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-range-statement) +* [Only one cuddle assignment allowed before switch statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-switch-statement) +* [Only one cuddle assignment allowed before type switch statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-type-switch-statement) +* [Ranges should only be cuddled with assignments used in the iteration](doc/rules.md#ranges-should-only-be-cuddled-with-assignments-used-in-the-iteration) +* [Return statements should not be cuddled if block has more than two lines](doc/rules.md#return-statements-should-not-be-cuddled-if-block-has-more-than-two-lines) +* [Switch statements should only be cuddled with variables switched](doc/rules.md#switch-statements-should-only-be-cuddled-with-variables-switched) +* [Type switch statements should only be cuddled with variables switched](doc/rules.md#type-switch-statements-should-only-be-cuddled-with-variables-switched) diff --git a/vendor/github.com/bombsimon/wsl/v3/go.mod b/vendor/github.com/bombsimon/wsl/v3/go.mod new file mode 100644 index 000000000..0c325eda1 --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v3/go.mod @@ -0,0 +1,12 @@ +module github.com/bombsimon/wsl/v3 + +go 1.12 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/stretchr/testify v1.5.1 + gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect +) diff --git a/vendor/github.com/bombsimon/wsl/v3/go.sum b/vendor/github.com/bombsimon/wsl/v3/go.sum new file mode 100644 index 000000000..3bdb59247 --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v3/go.sum @@ -0,0 +1,25 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/bombsimon/wsl/v3/wsl.go b/vendor/github.com/bombsimon/wsl/v3/wsl.go new file mode 100644 index 000000000..3b4a4e9a1 --- /dev/null +++ b/vendor/github.com/bombsimon/wsl/v3/wsl.go @@ -0,0 +1,1122 @@ +package wsl + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "io/ioutil" + "reflect" + "strings" +) + +// Error reason strings +const ( + reasonMustCuddleErrCheck = "if statements that check an error must be cuddled with the statement that assigned the error" + reasonOnlyCuddleIfWithAssign = "if statements should only be cuddled with assignments" + reasonOnlyOneCuddle = "only one cuddle assignment allowed before if statement" + reasonOnlyCuddleWithUsedAssign = "if statements should only be cuddled with assignments used in the if statement itself" + reasonOnlyCuddle2LineReturn = "return statements should not be cuddled if block has more than two lines" + reasonMultiLineBranchCuddle = "branch statements should not be cuddled if block has more than two lines" + reasonAppendCuddledWithoutUse = "append only allowed to cuddle with appended value" + reasonAssignsCuddleAssign = "assignments should only be cuddled with other assignments" + reasonNeverCuddleDeclare = "declarations should never be cuddled" + reasonExpressionCuddledWithDeclOrRet = "expressions should not be cuddled with declarations or returns" + reasonExpressionCuddledWithBlock = "expressions should not be cuddled with blocks" + reasonExprCuddlingNonAssignedVar = "only cuddled expressions if assigning variable or using from line above" + reasonOneCuddleBeforeRange = "only one cuddle assignment allowed before range statement" + reasonRangeCuddledWithoutUse = "ranges should only be cuddled with assignments used in the iteration" + reasonOneCuddleBeforeDefer = "only one cuddle assignment allowed before defer statement" + reasonDeferCuddledWithOtherVar = "defer statements should only be cuddled with expressions on same variable" + reasonForWithoutCondition = "for statement without condition should never be cuddled" + reasonForWithMoreThanOneCuddle = "only one cuddle assignment allowed before for statement" + reasonForCuddledAssignWithoutUse = "for statements should only be cuddled with assignments used in the iteration" + reasonOneCuddleBeforeGo = "only one cuddle assignment allowed before go statement" + reasonGoFuncWithoutAssign = "go statements can only invoke functions assigned on line above" + reasonSwitchManyCuddles = "only one cuddle assignment allowed before switch statement" + reasonAnonSwitchCuddled = "anonymous switch statements should never be cuddled" + reasonSwitchCuddledWithoutUse = "switch statements should only be cuddled with variables switched" + reasonTypeSwitchTooCuddled = "only one cuddle assignment allowed before type switch statement" + reasonTypeSwitchCuddledWithoutUse = "type switch statements should only be cuddled with variables switched" + reasonBlockStartsWithWS = "block should not start with a whitespace" + reasonBlockEndsWithWS = "block should not end with a whitespace (or comment)" + reasonCaseBlockTooCuddly = "case block should end with newline at this size" +) + +// Warning strings +const ( + warnTypeNotImplement = "type not implemented" + warnStmtNotImplemented = "stmt type not implemented" + warnBodyStmtTypeNotImplemented = "body statement type not implemented " + warnWSNodeTypeNotImplemented = "whitespace node type not implemented " + warnUnknownLHS = "UNKNOWN LHS" + warnUnknownRHS = "UNKNOWN RHS" +) + +type Configuration struct { + // StrictAppend will do strict checking when assigning from append (x = + // append(x, y)). If this is set to true the append call must append either + // a variable assigned, called or used on the line above. Example on not + // allowed when this is true: + // + // x := []string{} + // y := "not going in X" + // x = append(x, "not y") // This is not allowed with StrictAppend + // z := "going in X" + // + // x = append(x, z) // This is allowed with StrictAppend + // + // m := transform(z) + // x = append(x, z) // So is this because Z is used above. + StrictAppend bool + + // AllowAssignAndCallCuddle allows assignments to be cuddled with variables + // used in calls on line above and calls to be cuddled with assignments of + // variables used in call on line above. + // Example supported with this set to true: + // + // x.Call() + // x = Assign() + // x.AnotherCall() + // x = AnotherAssign() + AllowAssignAndCallCuddle bool + + // AllowMultiLineAssignCuddle allows cuddling to assignments even if they + // span over multiple lines. This defaults to true which allows the + // following example: + // + // err := function( + // "multiple", "lines", + // ) + // if err != nil { + // // ... + // } + AllowMultiLineAssignCuddle bool + + // If the number of lines in a case block is equal to or lager than this + // number, the case *must* end white a newline. + ForceCaseTrailingWhitespaceLimit int + + // AllowTrailingComment will allow blocks to end with comments. + AllowTrailingComment bool + + // AllowSeparatedLeadingComment will allow multiple comments in the + // beginning of a block separated with newline. Example: + // func () { + // // Comment one + // + // // Comment two + // fmt.Println("x") + // } + AllowSeparatedLeadingComment bool + + // AllowCuddleDeclaration will allow multiple var/declaration statements to + // be cuddled. This defaults to false but setting it to true will enable the + // following example: + // var foo bool + // var err error + AllowCuddleDeclaration bool + + // AllowCuddleWithCalls is a list of call idents that everything can be + // cuddled with. Defaults to calls looking like locks to support a flow like + // this: + // + // mu.Lock() + // allow := thisAssignment + AllowCuddleWithCalls []string + + // AllowCuddleWithRHS is a list of right hand side variables that is allowed + // to be cuddled with anything. Defaults to assignments or calls looking + // like unlocks to support a flow like this: + // + // allow := thisAssignment() + // mu.Unlock() + AllowCuddleWithRHS []string + + // ForceCuddleErrCheckAndAssign will cause an error when an If statement that + // checks an error variable doesn't cuddle with the assignment of that variable. + // This defaults to false but setting it to true will cause the following + // to generate an error: + // + // err := ProduceError() + // + // if err != nil { + // return err + // } + ForceCuddleErrCheckAndAssign bool + + // When ForceCuddleErrCheckAndAssign is enabled this is a list of names + // used for error variables to check for in the conditional. + // Defaults to just "err" + ErrorVariableNames []string +} + +// DefaultConfig returns default configuration +func DefaultConfig() Configuration { + return Configuration{ + StrictAppend: true, + AllowAssignAndCallCuddle: true, + AllowMultiLineAssignCuddle: true, + AllowTrailingComment: false, + AllowSeparatedLeadingComment: false, + ForceCuddleErrCheckAndAssign: false, + ForceCaseTrailingWhitespaceLimit: 0, + AllowCuddleWithCalls: []string{"Lock", "RLock"}, + AllowCuddleWithRHS: []string{"Unlock", "RUnlock"}, + ErrorVariableNames: []string{"err"}, + } +} + +// Result represents the result of one error. +type Result struct { + FileName string + LineNumber int + Position token.Position + Reason string +} + +// String returns the filename, line number and reason of a Result. +func (r *Result) String() string { + return fmt.Sprintf("%s:%d: %s", r.FileName, r.LineNumber, r.Reason) +} + +type Processor struct { + config Configuration + result []Result + warnings []string + fileSet *token.FileSet + file *ast.File +} + +// NewProcessor will create a Processor. +func NewProcessorWithConfig(cfg Configuration) *Processor { + return &Processor{ + result: []Result{}, + config: cfg, + } +} + +// NewProcessor will create a Processor. +func NewProcessor() *Processor { + return NewProcessorWithConfig(DefaultConfig()) +} + +// ProcessFiles takes a string slice with file names (full paths) and lints +// them. +// nolint: gocritic +func (p *Processor) ProcessFiles(filenames []string) ([]Result, []string) { + for _, filename := range filenames { + data, err := ioutil.ReadFile(filename) + if err != nil { + panic(err) + } + + p.process(filename, data) + } + + return p.result, p.warnings +} + +func (p *Processor) process(filename string, data []byte) { + fileSet := token.NewFileSet() + file, err := parser.ParseFile(fileSet, filename, data, parser.ParseComments) + + // If the file is not parsable let's add a syntax error and move on. + if err != nil { + p.result = append(p.result, Result{ + FileName: filename, + LineNumber: 0, + Reason: fmt.Sprintf("invalid syntax, file cannot be linted (%s)", err.Error()), + }) + + return + } + + p.fileSet = fileSet + p.file = file + + for _, d := range p.file.Decls { + switch v := d.(type) { + case *ast.FuncDecl: + p.parseBlockBody(v.Name, v.Body) + case *ast.GenDecl: + // `go fmt` will handle proper spacing for GenDecl such as imports, + // constants etc. + default: + p.addWarning(warnTypeNotImplement, d.Pos(), v) + } + } +} + +// parseBlockBody will parse any kind of block statements such as switch cases +// and if statements. A list of Result is returned. +func (p *Processor) parseBlockBody(ident *ast.Ident, block *ast.BlockStmt) { + // Nothing to do if there's no value. + if reflect.ValueOf(block).IsNil() { + return + } + + // Start by finding leading and trailing whitespaces. + p.findLeadingAndTrailingWhitespaces(ident, block, nil) + + // Parse the block body contents. + p.parseBlockStatements(block.List) +} + +// parseBlockStatements will parse all the statements found in the body of a +// node. A list of Result is returned. +// nolint: gocognit +func (p *Processor) parseBlockStatements(statements []ast.Stmt) { + for i, stmt := range statements { + // Start by checking if this statement is another block (other than if, + // for and range). This could be assignment to a function, defer or go + // call with an inline function or similar. If this is found we start by + // parsing this body block before moving on. + for _, stmtBlocks := range p.findBlockStmt(stmt) { + p.parseBlockBody(nil, stmtBlocks) + } + + firstBodyStatement := p.firstBodyStatement(i, statements) + + // First statement, nothing to do. + if i == 0 { + continue + } + + previousStatement := statements[i-1] + cuddledWithLastStmt := p.nodeEnd(previousStatement) == p.nodeStart(stmt)-1 + + // If we're not cuddled and we don't need to enforce err-check cuddling + // then we can bail out here + if !cuddledWithLastStmt && !p.config.ForceCuddleErrCheckAndAssign { + continue + } + + // Extract assigned variables on the line above + // which is the only thing we allow cuddling with. If the assignment is + // made over multiple lines we should not allow cuddling. + var assignedOnLineAbove []string + + // We want to keep track of what was called on the line above to support + // special handling of things such as mutexes. + var calledOnLineAbove []string + + // Check if the previous statement spans over multiple lines. + var cuddledWithMultiLineAssignment = cuddledWithLastStmt && p.nodeStart(previousStatement) != p.nodeStart(stmt)-1 + + // Ensure previous line is not a multi line assignment and if not get + // rightAndLeftHandSide assigned variables. + if !cuddledWithMultiLineAssignment { + assignedOnLineAbove = p.findLHS(previousStatement) + calledOnLineAbove = p.findRHS(previousStatement) + } + + // If previous assignment is multi line and we allow it, fetch + // assignments (but only assignments). + if cuddledWithMultiLineAssignment && p.config.AllowMultiLineAssignCuddle { + if _, ok := previousStatement.(*ast.AssignStmt); ok { + assignedOnLineAbove = p.findLHS(previousStatement) + } + } + + // We could potentially have a block which require us to check the first + // argument before ruling out an allowed cuddle. + var assignedFirstInBlock []string + + if firstBodyStatement != nil { + assignedFirstInBlock = p.findLHS(firstBodyStatement) + } + + var ( + leftHandSide = p.findLHS(stmt) + rightHandSide = p.findRHS(stmt) + rightAndLeftHandSide = append(leftHandSide, rightHandSide...) + calledOrAssignedOnLineAbove = append(calledOnLineAbove, assignedOnLineAbove...) + ) + + // If we called some kind of lock on the line above we allow cuddling + // anything. + if atLeastOneInListsMatch(calledOnLineAbove, p.config.AllowCuddleWithCalls) { + continue + } + + // If we call some kind of unlock on this line we allow cuddling with + // anything. + if atLeastOneInListsMatch(rightHandSide, p.config.AllowCuddleWithRHS) { + continue + } + + moreThanOneStatementAbove := func() bool { + if i < 2 { + return false + } + + statementBeforePreviousStatement := statements[i-2] + + return p.nodeStart(previousStatement)-1 == p.nodeEnd(statementBeforePreviousStatement) + } + + isLastStatementInBlockOfOnlyTwoLines := func() bool { + // If we're the last statement, check if there's no more than two + // lines from the starting statement and the end of this statement. + // This is to support short return functions such as: + // func (t *Typ) X() { + // t.X = true + // return t + // } + // nolint: gocritic + if i == len(statements)-1 && i == 1 { + if p.nodeEnd(stmt)-p.nodeStart(previousStatement) <= 2 { + return true + } + } + + return false + } + + // If it's not an if statement and we're not cuddled move on. The only + // reason we need to keep going for if statements is to check if we + // should be cuddled with an error check. + if _, ok := stmt.(*ast.IfStmt); !ok { + if !cuddledWithLastStmt { + continue + } + } + + switch t := stmt.(type) { + case *ast.IfStmt: + checkingErrInitializedInline := func() bool { + if t.Init == nil { + return false + } + + // Variables were initialized inline in the if statement + // Let's make sure it's the err just to be safe + return atLeastOneInListsMatch(p.findLHS(t.Init), p.config.ErrorVariableNames) + } + + if !cuddledWithLastStmt { + checkingErr := atLeastOneInListsMatch(rightAndLeftHandSide, p.config.ErrorVariableNames) + if checkingErr { + if checkingErrInitializedInline() { + continue + } + + if atLeastOneInListsMatch(assignedOnLineAbove, p.config.ErrorVariableNames) { + p.addError(t.Pos(), reasonMustCuddleErrCheck) + } + } + + continue + } + + if len(assignedOnLineAbove) == 0 { + p.addError(t.Pos(), reasonOnlyCuddleIfWithAssign) + continue + } + + if moreThanOneStatementAbove() { + p.addError(t.Pos(), reasonOnlyOneCuddle) + continue + } + + if atLeastOneInListsMatch(rightAndLeftHandSide, assignedOnLineAbove) { + continue + } + + if atLeastOneInListsMatch(assignedOnLineAbove, assignedFirstInBlock) { + continue + } + + p.addError(t.Pos(), reasonOnlyCuddleWithUsedAssign) + case *ast.ReturnStmt: + if isLastStatementInBlockOfOnlyTwoLines() { + continue + } + + p.addError(t.Pos(), reasonOnlyCuddle2LineReturn) + case *ast.BranchStmt: + if isLastStatementInBlockOfOnlyTwoLines() { + continue + } + + p.addError(t.Pos(), reasonMultiLineBranchCuddle) + case *ast.AssignStmt: + // append is usually an assignment but should not be allowed to be + // cuddled with anything not appended. + if len(rightHandSide) > 0 && rightHandSide[len(rightHandSide)-1] == "append" { + if p.config.StrictAppend { + if !atLeastOneInListsMatch(calledOrAssignedOnLineAbove, rightHandSide) { + p.addError(t.Pos(), reasonAppendCuddledWithoutUse) + } + } + + continue + } + + if _, ok := previousStatement.(*ast.AssignStmt); ok { + continue + } + + // If the assignment is from a type or variable called on the line + // above we can allow it by setting AllowAssignAndCallCuddle to + // true. + // Example (x is used): + // x.function() + // a.Field = x.anotherFunction() + if p.config.AllowAssignAndCallCuddle { + if atLeastOneInListsMatch(calledOrAssignedOnLineAbove, rightAndLeftHandSide) { + continue + } + } + + p.addError(t.Pos(), reasonAssignsCuddleAssign) + case *ast.DeclStmt: + if !p.config.AllowCuddleDeclaration { + p.addError(t.Pos(), reasonNeverCuddleDeclare) + } + case *ast.ExprStmt: + switch previousStatement.(type) { + case *ast.DeclStmt, *ast.ReturnStmt: + p.addError(t.Pos(), reasonExpressionCuddledWithDeclOrRet) + case *ast.IfStmt, *ast.RangeStmt, *ast.SwitchStmt: + p.addError(t.Pos(), reasonExpressionCuddledWithBlock) + } + + // If the expression is called on a type or variable used or + // assigned on the line we can allow it by setting + // AllowAssignAndCallCuddle to true. + // Example of allowed cuddled (x is used): + // a.Field = x.func() + // x.function() + if p.config.AllowAssignAndCallCuddle { + if atLeastOneInListsMatch(calledOrAssignedOnLineAbove, rightAndLeftHandSide) { + continue + } + } + + // If we assigned variables on the line above but didn't use them in + // this expression there should probably be a newline between them. + if len(assignedOnLineAbove) > 0 && !atLeastOneInListsMatch(rightAndLeftHandSide, assignedOnLineAbove) { + p.addError(t.Pos(), reasonExprCuddlingNonAssignedVar) + } + case *ast.RangeStmt: + if moreThanOneStatementAbove() { + p.addError(t.Pos(), reasonOneCuddleBeforeRange) + continue + } + + if !atLeastOneInListsMatch(rightAndLeftHandSide, assignedOnLineAbove) { + if !atLeastOneInListsMatch(assignedOnLineAbove, assignedFirstInBlock) { + p.addError(t.Pos(), reasonRangeCuddledWithoutUse) + } + } + case *ast.DeferStmt: + if _, ok := previousStatement.(*ast.DeferStmt); ok { + // We may cuddle multiple defers to group logic. + continue + } + + // Special treatment of deferring body closes after error checking + // according to best practices. See + // https://github.com/bombsimon/wsl/issues/31 which links to + // discussion about error handling after HTTP requests. This is hard + // coded and very specific but for now this is to be seen as a + // special case. What this does is that it *only* allows a defer + // statement with `Close` on the right hand side to be cuddled with + // an if-statement to support this: + // resp, err := client.Do(req) + // if err != nil { + // return err + // } + // defer resp.Body.Close() + if _, ok := previousStatement.(*ast.IfStmt); ok { + if atLeastOneInListsMatch(rightHandSide, []string{"Close"}) { + continue + } + } + + if moreThanOneStatementAbove() { + p.addError(t.Pos(), reasonOneCuddleBeforeDefer) + + continue + } + + // Be extra nice with RHS, it's common to use this for locks: + // m.Lock() + // defer m.Unlock() + previousRHS := p.findRHS(previousStatement) + if atLeastOneInListsMatch(rightHandSide, previousRHS) { + continue + } + + if !atLeastOneInListsMatch(rightAndLeftHandSide, assignedOnLineAbove) { + p.addError(t.Pos(), reasonDeferCuddledWithOtherVar) + } + case *ast.ForStmt: + if len(rightAndLeftHandSide) == 0 { + p.addError(t.Pos(), reasonForWithoutCondition) + + continue + } + + if moreThanOneStatementAbove() { + p.addError(t.Pos(), reasonForWithMoreThanOneCuddle) + + continue + } + + // The same rule applies for ranges as for if statements, see + // comments regarding variable usages on the line before or as the + // first line in the block for details. + if !atLeastOneInListsMatch(rightAndLeftHandSide, assignedOnLineAbove) { + if !atLeastOneInListsMatch(assignedOnLineAbove, assignedFirstInBlock) { + p.addError(t.Pos(), reasonForCuddledAssignWithoutUse) + } + } + case *ast.GoStmt: + if _, ok := previousStatement.(*ast.GoStmt); ok { + continue + } + + if moreThanOneStatementAbove() { + p.addError(t.Pos(), reasonOneCuddleBeforeGo) + + continue + } + + if !atLeastOneInListsMatch(rightAndLeftHandSide, assignedOnLineAbove) { + p.addError(t.Pos(), reasonGoFuncWithoutAssign) + } + case *ast.SwitchStmt: + if moreThanOneStatementAbove() { + p.addError(t.Pos(), reasonSwitchManyCuddles) + + continue + } + + if !atLeastOneInListsMatch(rightAndLeftHandSide, assignedOnLineAbove) { + if len(rightAndLeftHandSide) == 0 { + p.addError(t.Pos(), reasonAnonSwitchCuddled) + } else { + p.addError(t.Pos(), reasonSwitchCuddledWithoutUse) + } + } + case *ast.TypeSwitchStmt: + if moreThanOneStatementAbove() { + p.addError(t.Pos(), reasonTypeSwitchTooCuddled) + + continue + } + + // Allowed to type assert on variable assigned on line above. + if !atLeastOneInListsMatch(rightHandSide, assignedOnLineAbove) { + // Allow type assertion on variables used in the first case + // immediately. + if !atLeastOneInListsMatch(assignedOnLineAbove, assignedFirstInBlock) { + p.addError(t.Pos(), reasonTypeSwitchCuddledWithoutUse) + } + } + case *ast.CaseClause, *ast.CommClause: + // Case clauses will be checked by not allowing leading ot trailing + // whitespaces within the block. There's nothing in the case itself + // that may be cuddled. + default: + p.addWarning(warnStmtNotImplemented, t.Pos(), t) + } + } +} + +// firstBodyStatement returns the first statement inside a body block. This is +// because variables may be cuddled with conditions or statements if it's used +// directly as the first argument inside a body. +// The body will then be parsed as a *ast.BlockStmt (regular block) or as a list +// of []ast.Stmt (case block). +func (p *Processor) firstBodyStatement(i int, allStmt []ast.Stmt) ast.Node { + stmt := allStmt[i] + + // Start by checking if the statement has a body (probably if-statement, + // a range, switch case or similar. Whenever a body is found we start by + // parsing it before moving on in the AST. + statementBody := reflect.Indirect(reflect.ValueOf(stmt)).FieldByName("Body") + + // Some cases allow cuddling depending on the first statement in a body + // of a block or case. If possible extract the first statement. + var firstBodyStatement ast.Node + + if !statementBody.IsValid() { + return firstBodyStatement + } + + switch statementBodyContent := statementBody.Interface().(type) { + case *ast.BlockStmt: + if len(statementBodyContent.List) > 0 { + firstBodyStatement = statementBodyContent.List[0] + + // If the first body statement is a *ast.CaseClause we're + // actually interested in the **next** body to know what's + // inside the first case. + if x, ok := firstBodyStatement.(*ast.CaseClause); ok { + if len(x.Body) > 0 { + firstBodyStatement = x.Body[0] + } + } + } + + p.parseBlockBody(nil, statementBodyContent) + case []ast.Stmt: + // The Body field for an *ast.CaseClause or *ast.CommClause is of type + // []ast.Stmt. We must check leading and trailing whitespaces and then + // pass the statements to parseBlockStatements to parse it's content. + var nextStatement ast.Node + + // Check if there's more statements (potential cases) after the + // current one. + if len(allStmt)-1 > i { + nextStatement = allStmt[i+1] + } + + p.findLeadingAndTrailingWhitespaces(nil, stmt, nextStatement) + p.parseBlockStatements(statementBodyContent) + default: + p.addWarning( + warnBodyStmtTypeNotImplemented, + stmt.Pos(), statementBodyContent, + ) + } + + return firstBodyStatement +} + +func (p *Processor) findLHS(node ast.Node) []string { + var lhs []string + + if node == nil { + return lhs + } + + switch t := node.(type) { + case *ast.BasicLit, *ast.FuncLit, *ast.SelectStmt, + *ast.LabeledStmt, *ast.ForStmt, *ast.SwitchStmt, + *ast.ReturnStmt, *ast.GoStmt, *ast.CaseClause, + *ast.CommClause, *ast.CallExpr, *ast.UnaryExpr, + *ast.BranchStmt, *ast.TypeSpec, *ast.ChanType, + *ast.DeferStmt, *ast.TypeAssertExpr, *ast.RangeStmt: + // Nothing to add to LHS + case *ast.IncDecStmt: + return p.findLHS(t.X) + case *ast.Ident: + return []string{t.Name} + case *ast.AssignStmt: + for _, v := range t.Lhs { + lhs = append(lhs, p.findLHS(v)...) + } + case *ast.GenDecl: + for _, v := range t.Specs { + lhs = append(lhs, p.findLHS(v)...) + } + case *ast.ValueSpec: + for _, v := range t.Names { + lhs = append(lhs, p.findLHS(v)...) + } + case *ast.BlockStmt: + for _, v := range t.List { + lhs = append(lhs, p.findLHS(v)...) + } + case *ast.BinaryExpr: + return append( + p.findLHS(t.X), + p.findLHS(t.Y)..., + ) + case *ast.DeclStmt: + return p.findLHS(t.Decl) + case *ast.IfStmt: + return p.findLHS(t.Cond) + case *ast.TypeSwitchStmt: + return p.findLHS(t.Assign) + case *ast.SendStmt: + return p.findLHS(t.Chan) + default: + if x, ok := maybeX(t); ok { + return p.findLHS(x) + } + + p.addWarning(warnUnknownLHS, t.Pos(), t) + } + + return lhs +} + +func (p *Processor) findRHS(node ast.Node) []string { + var rhs []string + + if node == nil { + return rhs + } + + switch t := node.(type) { + case *ast.BasicLit, *ast.SelectStmt, *ast.ChanType, + *ast.LabeledStmt, *ast.DeclStmt, *ast.BranchStmt, + *ast.TypeSpec, *ast.ArrayType, *ast.CaseClause, + *ast.CommClause, *ast.KeyValueExpr, *ast.MapType, + *ast.FuncLit: + // Nothing to add to RHS + case *ast.Ident: + return []string{t.Name} + case *ast.SelectorExpr: + // TODO: Should this be RHS? + // t.X is needed for defer as of now and t.Sel needed for special + // functions such as Lock() + rhs = p.findRHS(t.X) + rhs = append(rhs, p.findRHS(t.Sel)...) + case *ast.AssignStmt: + for _, v := range t.Rhs { + rhs = append(rhs, p.findRHS(v)...) + } + case *ast.CallExpr: + for _, v := range t.Args { + rhs = append(rhs, p.findRHS(v)...) + } + + rhs = append(rhs, p.findRHS(t.Fun)...) + case *ast.CompositeLit: + for _, v := range t.Elts { + rhs = append(rhs, p.findRHS(v)...) + } + case *ast.IfStmt: + rhs = append(rhs, p.findRHS(t.Cond)...) + rhs = append(rhs, p.findRHS(t.Init)...) + case *ast.BinaryExpr: + return append( + p.findRHS(t.X), + p.findRHS(t.Y)..., + ) + case *ast.TypeSwitchStmt: + return p.findRHS(t.Assign) + case *ast.ReturnStmt: + for _, v := range t.Results { + rhs = append(rhs, p.findRHS(v)...) + } + case *ast.BlockStmt: + for _, v := range t.List { + rhs = append(rhs, p.findRHS(v)...) + } + case *ast.SwitchStmt: + return p.findRHS(t.Tag) + case *ast.GoStmt: + return p.findRHS(t.Call) + case *ast.ForStmt: + return p.findRHS(t.Cond) + case *ast.DeferStmt: + return p.findRHS(t.Call) + case *ast.SendStmt: + return p.findLHS(t.Value) + case *ast.IndexExpr: + rhs = append(rhs, p.findRHS(t.Index)...) + rhs = append(rhs, p.findRHS(t.X)...) + case *ast.SliceExpr: + rhs = append(rhs, p.findRHS(t.X)...) + rhs = append(rhs, p.findRHS(t.Low)...) + rhs = append(rhs, p.findRHS(t.High)...) + default: + if x, ok := maybeX(t); ok { + return p.findRHS(x) + } + + p.addWarning(warnUnknownRHS, t.Pos(), t) + } + + return rhs +} + +func (p *Processor) findBlockStmt(node ast.Node) []*ast.BlockStmt { + var blocks []*ast.BlockStmt + + switch t := node.(type) { + case *ast.AssignStmt: + for _, x := range t.Rhs { + blocks = append(blocks, p.findBlockStmt(x)...) + } + case *ast.CallExpr: + blocks = append(blocks, p.findBlockStmt(t.Fun)...) + case *ast.FuncLit: + blocks = append(blocks, t.Body) + case *ast.ExprStmt: + blocks = append(blocks, p.findBlockStmt(t.X)...) + case *ast.ReturnStmt: + for _, x := range t.Results { + blocks = append(blocks, p.findBlockStmt(x)...) + } + case *ast.DeferStmt: + blocks = append(blocks, p.findBlockStmt(t.Call)...) + case *ast.GoStmt: + blocks = append(blocks, p.findBlockStmt(t.Call)...) + } + + return blocks +} + +// maybeX extracts the X field from an AST node and returns it with a true value +// if it exists. If the node doesn't have an X field nil and false is returned. +// Known fields with X that are handled: +// IndexExpr, ExprStmt, SelectorExpr, StarExpr, ParentExpr, TypeAssertExpr, +// RangeStmt, UnaryExpr, ParenExpr, SliceExpr, IncDecStmt. +func maybeX(node interface{}) (ast.Node, bool) { + maybeHasX := reflect.Indirect(reflect.ValueOf(node)).FieldByName("X") + if !maybeHasX.IsValid() { + return nil, false + } + + n, ok := maybeHasX.Interface().(ast.Node) + if !ok { + return nil, false + } + + return n, true +} + +func atLeastOneInListsMatch(listOne, listTwo []string) bool { + sliceToMap := func(s []string) map[string]struct{} { + m := map[string]struct{}{} + + for _, v := range s { + m[v] = struct{}{} + } + + return m + } + + m1 := sliceToMap(listOne) + m2 := sliceToMap(listTwo) + + for k1 := range m1 { + if _, ok := m2[k1]; ok { + return true + } + } + + for k2 := range m2 { + if _, ok := m1[k2]; ok { + return true + } + } + + return false +} + +// findLeadingAndTrailingWhitespaces will find leading and trailing whitespaces +// in a node. The method takes comments in consideration which will make the +// parser more gentle. +// nolint: gocognit +func (p *Processor) findLeadingAndTrailingWhitespaces(ident *ast.Ident, stmt, nextStatement ast.Node) { + var ( + allowedLinesBeforeFirstStatement = 1 + commentMap = ast.NewCommentMap(p.fileSet, stmt, p.file.Comments) + blockStatements []ast.Stmt + blockStartLine int + blockEndLine int + blockStartPos token.Pos + blockEndPos token.Pos + ) + + // Depending on the block type, get the statements in the block and where + // the block starts (and ends). + switch t := stmt.(type) { + case *ast.BlockStmt: + blockStatements = t.List + blockStartPos = t.Lbrace + blockEndPos = t.Rbrace + case *ast.CaseClause: + blockStatements = t.Body + blockStartPos = t.Colon + case *ast.CommClause: + blockStatements = t.Body + blockStartPos = t.Colon + default: + p.addWarning(warnWSNodeTypeNotImplemented, stmt.Pos(), stmt) + + return + } + + // Ignore empty blocks even if they have newlines or just comments. + if len(blockStatements) < 1 { + return + } + + blockStartLine = p.fileSet.Position(blockStartPos).Line + blockEndLine = p.fileSet.Position(blockEndPos).Line + + // No whitespace possible if LBrace and RBrace is on the same line. + if blockStartLine == blockEndLine { + return + } + + var ( + firstStatement = blockStatements[0] + lastStatement = blockStatements[len(blockStatements)-1] + seenCommentGroups = 0 + ) + + // Get the comment related to the first statement, we do allow commends in + // the beginning of a block before the first statement. + if c, ok := commentMap[firstStatement]; ok { + for _, commentGroup := range c { + // If the comment group is on the same line as the block start + // (LBrace) we should not consider it. + if p.nodeStart(commentGroup) == blockStartLine { + continue + } + + // We only care about comments before our statement from the comment + // map. As soon as we hit comments after our statement let's break + // out! + if commentGroup.Pos() > firstStatement.Pos() { + break + } + + // We store number of seen comment groups because we allow multiple + // groups with a newline between them. + seenCommentGroups++ + + // Support both /* multiline */ and //single line comments + for _, c := range commentGroup.List { + allowedLinesBeforeFirstStatement += len(strings.Split(c.Text, "\n")) + } + } + } + + // If we have multiple groups, add support for newline between each group. + if p.config.AllowSeparatedLeadingComment { + if seenCommentGroups > 1 { + allowedLinesBeforeFirstStatement += seenCommentGroups - 1 + } + } + + if p.nodeStart(firstStatement) != blockStartLine+allowedLinesBeforeFirstStatement { + p.addError( + blockStartPos, + reasonBlockStartsWithWS, + ) + } + + // If the blockEndLine is not 0 we're a regular block (not case). + if blockEndLine != 0 { + if p.config.AllowTrailingComment { + if lastComment, ok := commentMap[lastStatement]; ok { + var ( + lastCommentGroup = lastComment[len(lastComment)-1] + lastCommentLine = lastCommentGroup.List[len(lastCommentGroup.List)-1] + countNewlines = 0 + ) + + countNewlines += len(strings.Split(lastCommentLine.Text, "\n")) + + // No newlines between trailing comments and end of block. + if p.nodeStart(lastCommentLine)+countNewlines != blockEndLine-1 { + return + } + } + } + + if p.nodeEnd(lastStatement) != blockEndLine-1 && !isExampleFunc(ident) { + p.addError(blockEndPos, reasonBlockEndsWithWS) + } + + return + } + + // If we don't have any nextStatement the trailing whitespace will be + // handled when parsing the switch. If we do have a next statement we can + // see where it starts by getting it's colon position. We set the end of the + // current case to the position of the next case. + switch n := nextStatement.(type) { + case *ast.CaseClause: + blockEndPos = n.Case + case *ast.CommClause: + blockEndPos = n.Case + default: + // No more cases + return + } + + blockEndLine = p.fileSet.Position(blockEndPos).Line - 1 + + var ( + blockSize = blockEndLine - blockStartLine + caseTrailingCommentLines int + ) + + // TODO: I don't know what comments are bound to in cases. For regular + // blocks the last comment is bound to the last statement but for cases + // they are bound to the case clause expression. This will however get us all + // comments and depending on the case expression this gets tricky. + // + // To handle this I get the comment map from the current statement (the case + // itself) and iterate through all groups and all comment within all groups. + // I then get the comments after the last statement but before the next case + // clause and just map each line of comment that way. + for _, commentGroups := range commentMap { + for _, commentGroup := range commentGroups { + for _, comment := range commentGroup.List { + commentLine := p.fileSet.Position(comment.Pos()).Line + + // Ignore comments before the last statement. + if commentLine <= p.nodeStart(lastStatement) { + continue + } + + // Ignore comments after the end of this case. + if commentLine > blockEndLine { + continue + } + + // This allows /* multiline */ comments with newlines as well + // as regular (//) ones + caseTrailingCommentLines += len(strings.Split(comment.Text, "\n")) + } + } + } + + hasTrailingWhitespace := p.nodeEnd(lastStatement)+caseTrailingCommentLines != blockEndLine + + // If the force trailing limit is configured and we don't end with a newline. + if p.config.ForceCaseTrailingWhitespaceLimit > 0 && !hasTrailingWhitespace { + // Check if the block size is too big to miss the newline. + if blockSize >= p.config.ForceCaseTrailingWhitespaceLimit { + p.addError(lastStatement.Pos(), reasonCaseBlockTooCuddly) + } + } +} + +func isExampleFunc(ident *ast.Ident) bool { + return ident != nil && strings.HasPrefix(ident.Name, "Example") +} + +func (p *Processor) nodeStart(node ast.Node) int { + return p.fileSet.Position(node.Pos()).Line +} + +func (p *Processor) nodeEnd(node ast.Node) int { + return p.fileSet.Position(node.End()).Line +} + +// Add an error for the file and line number for the current token.Pos with the +// given reason. +func (p *Processor) addError(pos token.Pos, reason string) { + position := p.fileSet.Position(pos) + + p.result = append(p.result, Result{ + FileName: position.Filename, + LineNumber: position.Line, + Position: position, + Reason: reason, + }) +} + +func (p *Processor) addWarning(w string, pos token.Pos, t interface{}) { + position := p.fileSet.Position(pos) + + p.warnings = append(p.warnings, + fmt.Sprintf("%s:%d: %s (%T)", position.Filename, position.Line, w, t), + ) +} diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE new file mode 100644 index 000000000..bc52e96f2 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2012-2016 Dave Collins + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go new file mode 100644 index 000000000..792994785 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -0,0 +1,145 @@ +// Copyright (c) 2015-2016 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is not running on Google App Engine, compiled by GopherJS, and +// "-tags safe" is not added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// Go versions prior to 1.4 are disabled because they use a different layout +// for interfaces which make the implementation of unsafeReflectValue more complex. +// +build !js,!appengine,!safe,!disableunsafe,go1.4 + +package spew + +import ( + "reflect" + "unsafe" +) + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = false + + // ptrSize is the size of a pointer on the current arch. + ptrSize = unsafe.Sizeof((*byte)(nil)) +) + +type flag uintptr + +var ( + // flagRO indicates whether the value field of a reflect.Value + // is read-only. + flagRO flag + + // flagAddr indicates whether the address of the reflect.Value's + // value may be taken. + flagAddr flag +) + +// flagKindMask holds the bits that make up the kind +// part of the flags field. In all the supported versions, +// it is in the lower 5 bits. +const flagKindMask = flag(0x1f) + +// Different versions of Go have used different +// bit layouts for the flags type. This table +// records the known combinations. +var okFlags = []struct { + ro, addr flag +}{{ + // From Go 1.4 to 1.5 + ro: 1 << 5, + addr: 1 << 7, +}, { + // Up to Go tip. + ro: 1<<5 | 1<<6, + addr: 1 << 8, +}} + +var flagValOffset = func() uintptr { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") + } + return field.Offset +}() + +// flagField returns a pointer to the flag field of a reflect.Value. +func flagField(v *reflect.Value) *flag { + return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) +} + +// unsafeReflectValue converts the passed reflect.Value into a one that bypasses +// the typical safety restrictions preventing access to unaddressable and +// unexported data. It works by digging the raw pointer to the underlying +// value out of the protected value and generating a new unprotected (unsafe) +// reflect.Value to it. +// +// This allows us to check for implementations of the Stringer and error +// interfaces to be used for pretty printing ordinarily unaddressable and +// inaccessible values such as unexported struct fields. +func unsafeReflectValue(v reflect.Value) reflect.Value { + if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { + return v + } + flagFieldPtr := flagField(&v) + *flagFieldPtr &^= flagRO + *flagFieldPtr |= flagAddr + return v +} + +// Sanity checks against future reflect package changes +// to the type or semantics of the Value.flag field. +func init() { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") + } + if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { + panic("reflect.Value flag field has changed kind") + } + type t0 int + var t struct { + A t0 + // t0 will have flagEmbedRO set. + t0 + // a will have flagStickyRO set + a t0 + } + vA := reflect.ValueOf(t).FieldByName("A") + va := reflect.ValueOf(t).FieldByName("a") + vt0 := reflect.ValueOf(t).FieldByName("t0") + + // Infer flagRO from the difference between the flags + // for the (otherwise identical) fields in t. + flagPublic := *flagField(&vA) + flagWithRO := *flagField(&va) | *flagField(&vt0) + flagRO = flagPublic ^ flagWithRO + + // Infer flagAddr from the difference between a value + // taken from a pointer and not. + vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") + flagNoPtr := *flagField(&vA) + flagPtr := *flagField(&vPtrA) + flagAddr = flagNoPtr ^ flagPtr + + // Check that the inferred flags tally with one of the known versions. + for _, f := range okFlags { + if flagRO == f.ro && flagAddr == f.addr { + return + } + } + panic("reflect.Value read-only flag has changed semantics") +} diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go new file mode 100644 index 000000000..205c28d68 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -0,0 +1,38 @@ +// Copyright (c) 2015-2016 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is running on Google App Engine, compiled by GopherJS, or +// "-tags safe" is added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build js appengine safe disableunsafe !go1.4 + +package spew + +import "reflect" + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = true +) + +// unsafeReflectValue typically converts the passed reflect.Value into a one +// that bypasses the typical safety restrictions preventing access to +// unaddressable and unexported data. However, doing this relies on access to +// the unsafe package. This is a stub version which simply returns the passed +// reflect.Value when the unsafe package is not available. +func unsafeReflectValue(v reflect.Value) reflect.Value { + return v +} diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go new file mode 100644 index 000000000..1be8ce945 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/common.go @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "reflect" + "sort" + "strconv" +) + +// Some constants in the form of bytes to avoid string overhead. This mirrors +// the technique used in the fmt package. +var ( + panicBytes = []byte("(PANIC=") + plusBytes = []byte("+") + iBytes = []byte("i") + trueBytes = []byte("true") + falseBytes = []byte("false") + interfaceBytes = []byte("(interface {})") + commaNewlineBytes = []byte(",\n") + newlineBytes = []byte("\n") + openBraceBytes = []byte("{") + openBraceNewlineBytes = []byte("{\n") + closeBraceBytes = []byte("}") + asteriskBytes = []byte("*") + colonBytes = []byte(":") + colonSpaceBytes = []byte(": ") + openParenBytes = []byte("(") + closeParenBytes = []byte(")") + spaceBytes = []byte(" ") + pointerChainBytes = []byte("->") + nilAngleBytes = []byte("") + maxNewlineBytes = []byte("\n") + maxShortBytes = []byte("") + circularBytes = []byte("") + circularShortBytes = []byte("") + invalidAngleBytes = []byte("") + openBracketBytes = []byte("[") + closeBracketBytes = []byte("]") + percentBytes = []byte("%") + precisionBytes = []byte(".") + openAngleBytes = []byte("<") + closeAngleBytes = []byte(">") + openMapBytes = []byte("map[") + closeMapBytes = []byte("]") + lenEqualsBytes = []byte("len=") + capEqualsBytes = []byte("cap=") +) + +// hexDigits is used to map a decimal value to a hex digit. +var hexDigits = "0123456789abcdef" + +// catchPanic handles any panics that might occur during the handleMethods +// calls. +func catchPanic(w io.Writer, v reflect.Value) { + if err := recover(); err != nil { + w.Write(panicBytes) + fmt.Fprintf(w, "%v", err) + w.Write(closeParenBytes) + } +} + +// handleMethods attempts to call the Error and String methods on the underlying +// type the passed reflect.Value represents and outputes the result to Writer w. +// +// It handles panics in any called methods by catching and displaying the error +// as the formatted value. +func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { + // We need an interface to check if the type implements the error or + // Stringer interface. However, the reflect package won't give us an + // interface on certain things like unexported struct fields in order + // to enforce visibility rules. We use unsafe, when it's available, + // to bypass these restrictions since this package does not mutate the + // values. + if !v.CanInterface() { + if UnsafeDisabled { + return false + } + + v = unsafeReflectValue(v) + } + + // Choose whether or not to do error and Stringer interface lookups against + // the base type or a pointer to the base type depending on settings. + // Technically calling one of these methods with a pointer receiver can + // mutate the value, however, types which choose to satisify an error or + // Stringer interface with a pointer receiver should not be mutating their + // state inside these interface methods. + if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { + v = unsafeReflectValue(v) + } + if v.CanAddr() { + v = v.Addr() + } + + // Is it an error or Stringer? + switch iface := v.Interface().(type) { + case error: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.Error())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + + w.Write([]byte(iface.Error())) + return true + + case fmt.Stringer: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.String())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + w.Write([]byte(iface.String())) + return true + } + return false +} + +// printBool outputs a boolean value as true or false to Writer w. +func printBool(w io.Writer, val bool) { + if val { + w.Write(trueBytes) + } else { + w.Write(falseBytes) + } +} + +// printInt outputs a signed integer value to Writer w. +func printInt(w io.Writer, val int64, base int) { + w.Write([]byte(strconv.FormatInt(val, base))) +} + +// printUint outputs an unsigned integer value to Writer w. +func printUint(w io.Writer, val uint64, base int) { + w.Write([]byte(strconv.FormatUint(val, base))) +} + +// printFloat outputs a floating point value using the specified precision, +// which is expected to be 32 or 64bit, to Writer w. +func printFloat(w io.Writer, val float64, precision int) { + w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) +} + +// printComplex outputs a complex value using the specified float precision +// for the real and imaginary parts to Writer w. +func printComplex(w io.Writer, c complex128, floatPrecision int) { + r := real(c) + w.Write(openParenBytes) + w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) + i := imag(c) + if i >= 0 { + w.Write(plusBytes) + } + w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) + w.Write(iBytes) + w.Write(closeParenBytes) +} + +// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' +// prefix to Writer w. +func printHexPtr(w io.Writer, p uintptr) { + // Null pointer. + num := uint64(p) + if num == 0 { + w.Write(nilAngleBytes) + return + } + + // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix + buf := make([]byte, 18) + + // It's simpler to construct the hex string right to left. + base := uint64(16) + i := len(buf) - 1 + for num >= base { + buf[i] = hexDigits[num%base] + num /= base + i-- + } + buf[i] = hexDigits[num] + + // Add '0x' prefix. + i-- + buf[i] = 'x' + i-- + buf[i] = '0' + + // Strip unused leading bytes. + buf = buf[i:] + w.Write(buf) +} + +// valuesSorter implements sort.Interface to allow a slice of reflect.Value +// elements to be sorted. +type valuesSorter struct { + values []reflect.Value + strings []string // either nil or same len and values + cs *ConfigState +} + +// newValuesSorter initializes a valuesSorter instance, which holds a set of +// surrogate keys on which the data should be sorted. It uses flags in +// ConfigState to decide if and how to populate those surrogate keys. +func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { + vs := &valuesSorter{values: values, cs: cs} + if canSortSimply(vs.values[0].Kind()) { + return vs + } + if !cs.DisableMethods { + vs.strings = make([]string, len(values)) + for i := range vs.values { + b := bytes.Buffer{} + if !handleMethods(cs, &b, vs.values[i]) { + vs.strings = nil + break + } + vs.strings[i] = b.String() + } + } + if vs.strings == nil && cs.SpewKeys { + vs.strings = make([]string, len(values)) + for i := range vs.values { + vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) + } + } + return vs +} + +// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted +// directly, or whether it should be considered for sorting by surrogate keys +// (if the ConfigState allows it). +func canSortSimply(kind reflect.Kind) bool { + // This switch parallels valueSortLess, except for the default case. + switch kind { + case reflect.Bool: + return true + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return true + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + case reflect.Uintptr: + return true + case reflect.Array: + return true + } + return false +} + +// Len returns the number of values in the slice. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Len() int { + return len(s.values) +} + +// Swap swaps the values at the passed indices. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Swap(i, j int) { + s.values[i], s.values[j] = s.values[j], s.values[i] + if s.strings != nil { + s.strings[i], s.strings[j] = s.strings[j], s.strings[i] + } +} + +// valueSortLess returns whether the first value should sort before the second +// value. It is used by valueSorter.Less as part of the sort.Interface +// implementation. +func valueSortLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Bool: + return !a.Bool() && b.Bool() + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return a.Int() < b.Int() + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return a.Uint() < b.Uint() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.String: + return a.String() < b.String() + case reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Array: + // Compare the contents of both arrays. + l := a.Len() + for i := 0; i < l; i++ { + av := a.Index(i) + bv := b.Index(i) + if av.Interface() == bv.Interface() { + continue + } + return valueSortLess(av, bv) + } + } + return a.String() < b.String() +} + +// Less returns whether the value at index i should sort before the +// value at index j. It is part of the sort.Interface implementation. +func (s *valuesSorter) Less(i, j int) bool { + if s.strings == nil { + return valueSortLess(s.values[i], s.values[j]) + } + return s.strings[i] < s.strings[j] +} + +// sortValues is a sort function that handles both native types and any type that +// can be converted to error or Stringer. Other inputs are sorted according to +// their Value.String() value to ensure display stability. +func sortValues(values []reflect.Value, cs *ConfigState) { + if len(values) == 0 { + return + } + sort.Sort(newValuesSorter(values, cs)) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/config.go b/vendor/github.com/davecgh/go-spew/spew/config.go new file mode 100644 index 000000000..2e3d22f31 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/config.go @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "os" +) + +// ConfigState houses the configuration options used by spew to format and +// display values. There is a global instance, Config, that is used to control +// all top-level Formatter and Dump functionality. Each ConfigState instance +// provides methods equivalent to the top-level functions. +// +// The zero value for ConfigState provides no indentation. You would typically +// want to set it to a space or a tab. +// +// Alternatively, you can use NewDefaultConfig to get a ConfigState instance +// with default settings. See the documentation of NewDefaultConfig for default +// values. +type ConfigState struct { + // Indent specifies the string to use for each indentation level. The + // global config instance that all top-level functions use set this to a + // single space by default. If you would like more indentation, you might + // set this to a tab with "\t" or perhaps two spaces with " ". + Indent string + + // MaxDepth controls the maximum number of levels to descend into nested + // data structures. The default, 0, means there is no limit. + // + // NOTE: Circular data structures are properly detected, so it is not + // necessary to set this value unless you specifically want to limit deeply + // nested data structures. + MaxDepth int + + // DisableMethods specifies whether or not error and Stringer interfaces are + // invoked for types that implement them. + DisableMethods bool + + // DisablePointerMethods specifies whether or not to check for and invoke + // error and Stringer interfaces on types which only accept a pointer + // receiver when the current type is not a pointer. + // + // NOTE: This might be an unsafe action since calling one of these methods + // with a pointer receiver could technically mutate the value, however, + // in practice, types which choose to satisify an error or Stringer + // interface with a pointer receiver should not be mutating their state + // inside these interface methods. As a result, this option relies on + // access to the unsafe package, so it will not have any effect when + // running in environments without access to the unsafe package such as + // Google App Engine or with the "safe" build tag specified. + DisablePointerMethods bool + + // DisablePointerAddresses specifies whether to disable the printing of + // pointer addresses. This is useful when diffing data structures in tests. + DisablePointerAddresses bool + + // DisableCapacities specifies whether to disable the printing of capacities + // for arrays, slices, maps and channels. This is useful when diffing + // data structures in tests. + DisableCapacities bool + + // ContinueOnMethod specifies whether or not recursion should continue once + // a custom error or Stringer interface is invoked. The default, false, + // means it will print the results of invoking the custom error or Stringer + // interface and return immediately instead of continuing to recurse into + // the internals of the data type. + // + // NOTE: This flag does not have any effect if method invocation is disabled + // via the DisableMethods or DisablePointerMethods options. + ContinueOnMethod bool + + // SortKeys specifies map keys should be sorted before being printed. Use + // this to have a more deterministic, diffable output. Note that only + // native types (bool, int, uint, floats, uintptr and string) and types + // that support the error or Stringer interfaces (if methods are + // enabled) are supported, with other types sorted according to the + // reflect.Value.String() output which guarantees display stability. + SortKeys bool + + // SpewKeys specifies that, as a last resort attempt, map keys should + // be spewed to strings and sorted by those strings. This is only + // considered if SortKeys is true. + SpewKeys bool +} + +// Config is the active configuration of the top-level functions. +// The configuration can be changed by modifying the contents of spew.Config. +var Config = ConfigState{Indent: " "} + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the formatted string as a value that satisfies error. See NewFormatter +// for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, c.convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, c.convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, c.convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a Formatter interface returned by c.NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, c.convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Print(a ...interface{}) (n int, err error) { + return fmt.Print(c.convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, c.convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Println(a ...interface{}) (n int, err error) { + return fmt.Println(c.convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprint(a ...interface{}) string { + return fmt.Sprint(c.convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, c.convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a Formatter interface returned by c.NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintln(a ...interface{}) string { + return fmt.Sprintln(c.convertArgs(a)...) +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +c.Printf, c.Println, or c.Printf. +*/ +func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(c, v) +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { + fdump(c, w, a...) +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by modifying the public members +of c. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func (c *ConfigState) Dump(a ...interface{}) { + fdump(c, os.Stdout, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func (c *ConfigState) Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(c, &buf, a...) + return buf.String() +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a spew Formatter interface using +// the ConfigState associated with s. +func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = newFormatter(c, arg) + } + return formatters +} + +// NewDefaultConfig returns a ConfigState with the following default settings. +// +// Indent: " " +// MaxDepth: 0 +// DisableMethods: false +// DisablePointerMethods: false +// ContinueOnMethod: false +// SortKeys: false +func NewDefaultConfig() *ConfigState { + return &ConfigState{Indent: " "} +} diff --git a/vendor/github.com/davecgh/go-spew/spew/doc.go b/vendor/github.com/davecgh/go-spew/spew/doc.go new file mode 100644 index 000000000..aacaac6f1 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/doc.go @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Package spew implements a deep pretty printer for Go data structures to aid in +debugging. + +A quick overview of the additional features spew provides over the built-in +printing facilities for Go data types are as follows: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output (only when using + Dump style) + +There are two different approaches spew allows for dumping Go data structures: + + * Dump style which prints with newlines, customizable indentation, + and additional debug information such as types and all pointer addresses + used to indirect to the final value + * A custom Formatter interface that integrates cleanly with the standard fmt + package and replaces %v, %+v, %#v, and %#+v to provide inline printing + similar to the default %v while providing the additional functionality + outlined above and passing unsupported format verbs such as %x and %q + along to fmt + +Quick Start + +This section demonstrates how to quickly get started with spew. See the +sections below for further details on formatting and configuration options. + +To dump a variable with full newlines, indentation, type, and pointer +information use Dump, Fdump, or Sdump: + spew.Dump(myVar1, myVar2, ...) + spew.Fdump(someWriter, myVar1, myVar2, ...) + str := spew.Sdump(myVar1, myVar2, ...) + +Alternatively, if you would prefer to use format strings with a compacted inline +printing style, use the convenience wrappers Printf, Fprintf, etc with +%v (most compact), %+v (adds pointer addresses), %#v (adds types), or +%#+v (adds types and pointer addresses): + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +Configuration Options + +Configuration of spew is handled by fields in the ConfigState type. For +convenience, all of the top-level functions use a global state available +via the spew.Config global. + +It is also possible to create a ConfigState instance that provides methods +equivalent to the top-level functions. This allows concurrent configuration +options. See the ConfigState documentation for more details. + +The following configuration options are available: + * Indent + String to use for each indentation level for Dump functions. + It is a single space by default. A popular alternative is "\t". + + * MaxDepth + Maximum number of levels to descend into nested data structures. + There is no limit by default. + + * DisableMethods + Disables invocation of error and Stringer interface methods. + Method invocation is enabled by default. + + * DisablePointerMethods + Disables invocation of error and Stringer interface methods on types + which only accept pointer receivers from non-pointer variables. + Pointer method invocation is enabled by default. + + * DisablePointerAddresses + DisablePointerAddresses specifies whether to disable the printing of + pointer addresses. This is useful when diffing data structures in tests. + + * DisableCapacities + DisableCapacities specifies whether to disable the printing of + capacities for arrays, slices, maps and channels. This is useful when + diffing data structures in tests. + + * ContinueOnMethod + Enables recursion into types after invoking error and Stringer interface + methods. Recursion after method invocation is disabled by default. + + * SortKeys + Specifies map keys should be sorted before being printed. Use + this to have a more deterministic, diffable output. Note that + only native types (bool, int, uint, floats, uintptr and string) + and types which implement error or Stringer interfaces are + supported with other types sorted according to the + reflect.Value.String() output which guarantees display + stability. Natural map order is used by default. + + * SpewKeys + Specifies that, as a last resort attempt, map keys should be + spewed to strings and sorted by those strings. This is only + considered if SortKeys is true. + +Dump Usage + +Simply call spew.Dump with a list of variables you want to dump: + + spew.Dump(myVar1, myVar2, ...) + +You may also call spew.Fdump if you would prefer to output to an arbitrary +io.Writer. For example, to dump to standard error: + + spew.Fdump(os.Stderr, myVar1, myVar2, ...) + +A third option is to call spew.Sdump to get the formatted output as a string: + + str := spew.Sdump(myVar1, myVar2, ...) + +Sample Dump Output + +See the Dump example for details on the setup of the types and variables being +shown here. + + (main.Foo) { + unexportedField: (*main.Bar)(0xf84002e210)({ + flag: (main.Flag) flagTwo, + data: (uintptr) + }), + ExportedField: (map[interface {}]interface {}) (len=1) { + (string) (len=3) "one": (bool) true + } + } + +Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C +command as shown. + ([]uint8) (len=32 cap=32) { + 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | + 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| + 00000020 31 32 |12| + } + +Custom Formatter + +Spew provides a custom formatter that implements the fmt.Formatter interface +so that it integrates cleanly with standard fmt package printing functions. The +formatter is useful for inline printing of smaller data types similar to the +standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Custom Formatter Usage + +The simplest way to make use of the spew custom formatter is to call one of the +convenience functions such as spew.Printf, spew.Println, or spew.Printf. The +functions have syntax you are most likely already familiar with: + + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Println(myVar, myVar2) + spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +See the Index for the full list convenience functions. + +Sample Formatter Output + +Double pointer to a uint8: + %v: <**>5 + %+v: <**>(0xf8400420d0->0xf8400420c8)5 + %#v: (**uint8)5 + %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 + +Pointer to circular struct with a uint8 field and a pointer to itself: + %v: <*>{1 <*>} + %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} + %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} + %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} + +See the Printf example for details on the setup of variables being shown +here. + +Errors + +Since it is possible for custom Stringer/error interfaces to panic, spew +detects them and handles them internally by printing the panic information +inline with the output. Since spew is intended to provide deep pretty printing +capabilities on structures, it intentionally does not return any errors. +*/ +package spew diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go new file mode 100644 index 000000000..f78d89fc1 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/dump.go @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "encoding/hex" + "fmt" + "io" + "os" + "reflect" + "regexp" + "strconv" + "strings" +) + +var ( + // uint8Type is a reflect.Type representing a uint8. It is used to + // convert cgo types to uint8 slices for hexdumping. + uint8Type = reflect.TypeOf(uint8(0)) + + // cCharRE is a regular expression that matches a cgo char. + // It is used to detect character arrays to hexdump them. + cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) + + // cUnsignedCharRE is a regular expression that matches a cgo unsigned + // char. It is used to detect unsigned character arrays to hexdump + // them. + cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) + + // cUint8tCharRE is a regular expression that matches a cgo uint8_t. + // It is used to detect uint8_t arrays to hexdump them. + cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) +) + +// dumpState contains information about the state of a dump operation. +type dumpState struct { + w io.Writer + depth int + pointers map[uintptr]int + ignoreNextType bool + ignoreNextIndent bool + cs *ConfigState +} + +// indent performs indentation according to the depth level and cs.Indent +// option. +func (d *dumpState) indent() { + if d.ignoreNextIndent { + d.ignoreNextIndent = false + return + } + d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) +} + +// unpackValue returns values inside of non-nil interfaces when possible. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface && !v.IsNil() { + v = v.Elem() + } + return v +} + +// dumpPtr handles formatting of pointers by indirecting them as necessary. +func (d *dumpState) dumpPtr(v reflect.Value) { + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range d.pointers { + if depth >= d.depth { + delete(d.pointers, k) + } + } + + // Keep list of all dereferenced pointers to show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by dereferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := d.pointers[addr]; ok && pd < d.depth { + cycleFound = true + indirects-- + break + } + d.pointers[addr] = d.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type information. + d.w.Write(openParenBytes) + d.w.Write(bytes.Repeat(asteriskBytes, indirects)) + d.w.Write([]byte(ve.Type().String())) + d.w.Write(closeParenBytes) + + // Display pointer information. + if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { + d.w.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + d.w.Write(pointerChainBytes) + } + printHexPtr(d.w, addr) + } + d.w.Write(closeParenBytes) + } + + // Display dereferenced value. + d.w.Write(openParenBytes) + switch { + case nilFound: + d.w.Write(nilAngleBytes) + + case cycleFound: + d.w.Write(circularBytes) + + default: + d.ignoreNextType = true + d.dump(ve) + } + d.w.Write(closeParenBytes) +} + +// dumpSlice handles formatting of arrays and slices. Byte (uint8 under +// reflection) arrays and slices are dumped in hexdump -C fashion. +func (d *dumpState) dumpSlice(v reflect.Value) { + // Determine whether this type should be hex dumped or not. Also, + // for types which should be hexdumped, try to use the underlying data + // first, then fall back to trying to convert them to a uint8 slice. + var buf []uint8 + doConvert := false + doHexDump := false + numEntries := v.Len() + if numEntries > 0 { + vt := v.Index(0).Type() + vts := vt.String() + switch { + // C types that need to be converted. + case cCharRE.MatchString(vts): + fallthrough + case cUnsignedCharRE.MatchString(vts): + fallthrough + case cUint8tCharRE.MatchString(vts): + doConvert = true + + // Try to use existing uint8 slices and fall back to converting + // and copying if that fails. + case vt.Kind() == reflect.Uint8: + // We need an addressable interface to convert the type + // to a byte slice. However, the reflect package won't + // give us an interface on certain things like + // unexported struct fields in order to enforce + // visibility rules. We use unsafe, when available, to + // bypass these restrictions since this package does not + // mutate the values. + vs := v + if !vs.CanInterface() || !vs.CanAddr() { + vs = unsafeReflectValue(vs) + } + if !UnsafeDisabled { + vs = vs.Slice(0, numEntries) + + // Use the existing uint8 slice if it can be + // type asserted. + iface := vs.Interface() + if slice, ok := iface.([]uint8); ok { + buf = slice + doHexDump = true + break + } + } + + // The underlying data needs to be converted if it can't + // be type asserted to a uint8 slice. + doConvert = true + } + + // Copy and convert the underlying type if needed. + if doConvert && vt.ConvertibleTo(uint8Type) { + // Convert and copy each element into a uint8 byte + // slice. + buf = make([]uint8, numEntries) + for i := 0; i < numEntries; i++ { + vv := v.Index(i) + buf[i] = uint8(vv.Convert(uint8Type).Uint()) + } + doHexDump = true + } + } + + // Hexdump the entire slice as needed. + if doHexDump { + indent := strings.Repeat(d.cs.Indent, d.depth) + str := indent + hex.Dump(buf) + str = strings.Replace(str, "\n", "\n"+indent, -1) + str = strings.TrimRight(str, d.cs.Indent) + d.w.Write([]byte(str)) + return + } + + // Recursively call dump for each item. + for i := 0; i < numEntries; i++ { + d.dump(d.unpackValue(v.Index(i))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } +} + +// dump is the main workhorse for dumping a value. It uses the passed reflect +// value to figure out what kind of object we are dealing with and formats it +// appropriately. It is a recursive function, however circular data structures +// are detected and handled properly. +func (d *dumpState) dump(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + d.w.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + d.indent() + d.dumpPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !d.ignoreNextType { + d.indent() + d.w.Write(openParenBytes) + d.w.Write([]byte(v.Type().String())) + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + d.ignoreNextType = false + + // Display length and capacity if the built-in len and cap functions + // work with the value's kind and the len/cap itself is non-zero. + valueLen, valueCap := 0, 0 + switch v.Kind() { + case reflect.Array, reflect.Slice, reflect.Chan: + valueLen, valueCap = v.Len(), v.Cap() + case reflect.Map, reflect.String: + valueLen = v.Len() + } + if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { + d.w.Write(openParenBytes) + if valueLen != 0 { + d.w.Write(lenEqualsBytes) + printInt(d.w, int64(valueLen), 10) + } + if !d.cs.DisableCapacities && valueCap != 0 { + if valueLen != 0 { + d.w.Write(spaceBytes) + } + d.w.Write(capEqualsBytes) + printInt(d.w, int64(valueCap), 10) + } + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + + // Call Stringer/error interfaces if they exist and the handle methods flag + // is enabled + if !d.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(d.cs, d.w, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(d.w, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(d.w, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(d.w, v.Uint(), 10) + + case reflect.Float32: + printFloat(d.w, v.Float(), 32) + + case reflect.Float64: + printFloat(d.w, v.Float(), 64) + + case reflect.Complex64: + printComplex(d.w, v.Complex(), 32) + + case reflect.Complex128: + printComplex(d.w, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + d.dumpSlice(v) + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.String: + d.w.Write([]byte(strconv.Quote(v.String()))) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + d.w.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + numEntries := v.Len() + keys := v.MapKeys() + if d.cs.SortKeys { + sortValues(keys, d.cs) + } + for i, key := range keys { + d.dump(d.unpackValue(key)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.MapIndex(key))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Struct: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + vt := v.Type() + numFields := v.NumField() + for i := 0; i < numFields; i++ { + d.indent() + vtf := vt.Field(i) + d.w.Write([]byte(vtf.Name)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.Field(i))) + if i < (numFields - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(d.w, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(d.w, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it in case any new + // types are added. + default: + if v.CanInterface() { + fmt.Fprintf(d.w, "%v", v.Interface()) + } else { + fmt.Fprintf(d.w, "%v", v.String()) + } + } +} + +// fdump is a helper function to consolidate the logic from the various public +// methods which take varying writers and config states. +func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { + for _, arg := range a { + if arg == nil { + w.Write(interfaceBytes) + w.Write(spaceBytes) + w.Write(nilAngleBytes) + w.Write(newlineBytes) + continue + } + + d := dumpState{w: w, cs: cs} + d.pointers = make(map[uintptr]int) + d.dump(reflect.ValueOf(arg)) + d.w.Write(newlineBytes) + } +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func Fdump(w io.Writer, a ...interface{}) { + fdump(&Config, w, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(&Config, &buf, a...) + return buf.String() +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by an exported package global, +spew.Config. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func Dump(a ...interface{}) { + fdump(&Config, os.Stdout, a...) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go new file mode 100644 index 000000000..b04edb7d7 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/format.go @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" +) + +// supportedFlags is a list of all the character flags supported by fmt package. +const supportedFlags = "0-+# " + +// formatState implements the fmt.Formatter interface and contains information +// about the state of a formatting operation. The NewFormatter function can +// be used to get a new Formatter which can be used directly as arguments +// in standard fmt package printing calls. +type formatState struct { + value interface{} + fs fmt.State + depth int + pointers map[uintptr]int + ignoreNextType bool + cs *ConfigState +} + +// buildDefaultFormat recreates the original format string without precision +// and width information to pass in to fmt.Sprintf in the case of an +// unrecognized type. Unless new types are added to the language, this +// function won't ever be called. +func (f *formatState) buildDefaultFormat() (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + buf.WriteRune('v') + + format = buf.String() + return format +} + +// constructOrigFormat recreates the original format string including precision +// and width information to pass along to the standard fmt package. This allows +// automatic deferral of all format strings this package doesn't support. +func (f *formatState) constructOrigFormat(verb rune) (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + if width, ok := f.fs.Width(); ok { + buf.WriteString(strconv.Itoa(width)) + } + + if precision, ok := f.fs.Precision(); ok { + buf.Write(precisionBytes) + buf.WriteString(strconv.Itoa(precision)) + } + + buf.WriteRune(verb) + + format = buf.String() + return format +} + +// unpackValue returns values inside of non-nil interfaces when possible and +// ensures that types for values which have been unpacked from an interface +// are displayed when the show types flag is also set. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (f *formatState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface { + f.ignoreNextType = false + if !v.IsNil() { + v = v.Elem() + } + } + return v +} + +// formatPtr handles formatting of pointers by indirecting them as necessary. +func (f *formatState) formatPtr(v reflect.Value) { + // Display nil if top level pointer is nil. + showTypes := f.fs.Flag('#') + if v.IsNil() && (!showTypes || f.ignoreNextType) { + f.fs.Write(nilAngleBytes) + return + } + + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range f.pointers { + if depth >= f.depth { + delete(f.pointers, k) + } + } + + // Keep list of all dereferenced pointers to possibly show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by derferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := f.pointers[addr]; ok && pd < f.depth { + cycleFound = true + indirects-- + break + } + f.pointers[addr] = f.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type or indirection level depending on flags. + if showTypes && !f.ignoreNextType { + f.fs.Write(openParenBytes) + f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) + f.fs.Write([]byte(ve.Type().String())) + f.fs.Write(closeParenBytes) + } else { + if nilFound || cycleFound { + indirects += strings.Count(ve.Type().String(), "*") + } + f.fs.Write(openAngleBytes) + f.fs.Write([]byte(strings.Repeat("*", indirects))) + f.fs.Write(closeAngleBytes) + } + + // Display pointer information depending on flags. + if f.fs.Flag('+') && (len(pointerChain) > 0) { + f.fs.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + f.fs.Write(pointerChainBytes) + } + printHexPtr(f.fs, addr) + } + f.fs.Write(closeParenBytes) + } + + // Display dereferenced value. + switch { + case nilFound: + f.fs.Write(nilAngleBytes) + + case cycleFound: + f.fs.Write(circularShortBytes) + + default: + f.ignoreNextType = true + f.format(ve) + } +} + +// format is the main workhorse for providing the Formatter interface. It +// uses the passed reflect value to figure out what kind of object we are +// dealing with and formats it appropriately. It is a recursive function, +// however circular data structures are detected and handled properly. +func (f *formatState) format(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + f.fs.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + f.formatPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !f.ignoreNextType && f.fs.Flag('#') { + f.fs.Write(openParenBytes) + f.fs.Write([]byte(v.Type().String())) + f.fs.Write(closeParenBytes) + } + f.ignoreNextType = false + + // Call Stringer/error interfaces if they exist and the handle methods + // flag is enabled. + if !f.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(f.cs, f.fs, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(f.fs, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(f.fs, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(f.fs, v.Uint(), 10) + + case reflect.Float32: + printFloat(f.fs, v.Float(), 32) + + case reflect.Float64: + printFloat(f.fs, v.Float(), 64) + + case reflect.Complex64: + printComplex(f.fs, v.Complex(), 32) + + case reflect.Complex128: + printComplex(f.fs, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + f.fs.Write(openBracketBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + numEntries := v.Len() + for i := 0; i < numEntries; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(v.Index(i))) + } + } + f.depth-- + f.fs.Write(closeBracketBytes) + + case reflect.String: + f.fs.Write([]byte(v.String())) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + f.fs.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + + f.fs.Write(openMapBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + keys := v.MapKeys() + if f.cs.SortKeys { + sortValues(keys, f.cs) + } + for i, key := range keys { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(key)) + f.fs.Write(colonBytes) + f.ignoreNextType = true + f.format(f.unpackValue(v.MapIndex(key))) + } + } + f.depth-- + f.fs.Write(closeMapBytes) + + case reflect.Struct: + numFields := v.NumField() + f.fs.Write(openBraceBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + vt := v.Type() + for i := 0; i < numFields; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + vtf := vt.Field(i) + if f.fs.Flag('+') || f.fs.Flag('#') { + f.fs.Write([]byte(vtf.Name)) + f.fs.Write(colonBytes) + } + f.format(f.unpackValue(v.Field(i))) + } + } + f.depth-- + f.fs.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(f.fs, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(f.fs, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it if any get added. + default: + format := f.buildDefaultFormat() + if v.CanInterface() { + fmt.Fprintf(f.fs, format, v.Interface()) + } else { + fmt.Fprintf(f.fs, format, v.String()) + } + } +} + +// Format satisfies the fmt.Formatter interface. See NewFormatter for usage +// details. +func (f *formatState) Format(fs fmt.State, verb rune) { + f.fs = fs + + // Use standard formatting for verbs that are not v. + if verb != 'v' { + format := f.constructOrigFormat(verb) + fmt.Fprintf(fs, format, f.value) + return + } + + if f.value == nil { + if fs.Flag('#') { + fs.Write(interfaceBytes) + } + fs.Write(nilAngleBytes) + return + } + + f.format(reflect.ValueOf(f.value)) +} + +// newFormatter is a helper function to consolidate the logic from the various +// public methods which take varying config states. +func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { + fs := &formatState{value: v, cs: cs} + fs.pointers = make(map[uintptr]int) + return fs +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +Printf, Println, or Fprintf. +*/ +func NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(&Config, v) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/spew.go b/vendor/github.com/davecgh/go-spew/spew/spew.go new file mode 100644 index 000000000..32c0e3388 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/spew.go @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "fmt" + "io" +) + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the formatted string as a value that satisfies error. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a default Formatter interface returned by NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) +func Print(a ...interface{}) (n int, err error) { + return fmt.Print(convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) +func Println(a ...interface{}) (n int, err error) { + return fmt.Println(convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprint(a ...interface{}) string { + return fmt.Sprint(convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintln(a ...interface{}) string { + return fmt.Sprintln(convertArgs(a)...) +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a default spew Formatter interface. +func convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = NewFormatter(arg) + } + return formatters +} diff --git a/vendor/github.com/fatih/color/.travis.yml b/vendor/github.com/fatih/color/.travis.yml new file mode 100644 index 000000000..95f8a1ff5 --- /dev/null +++ b/vendor/github.com/fatih/color/.travis.yml @@ -0,0 +1,5 @@ +language: go +go: + - 1.8.x + - tip + diff --git a/vendor/github.com/fatih/color/Gopkg.lock b/vendor/github.com/fatih/color/Gopkg.lock new file mode 100644 index 000000000..7d879e9ca --- /dev/null +++ b/vendor/github.com/fatih/color/Gopkg.lock @@ -0,0 +1,27 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/mattn/go-colorable" + packages = ["."] + revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" + version = "v0.0.9" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "37707fdb30a5b38865cfb95e5aab41707daec7fd" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "e8a50671c3cb93ea935bf210b1cd20702876b9d9226129be581ef646d1565cdc" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/fatih/color/Gopkg.toml b/vendor/github.com/fatih/color/Gopkg.toml new file mode 100644 index 000000000..ff1617f71 --- /dev/null +++ b/vendor/github.com/fatih/color/Gopkg.toml @@ -0,0 +1,30 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/mattn/go-colorable" + version = "0.0.9" + +[[constraint]] + name = "github.com/mattn/go-isatty" + version = "0.0.3" diff --git a/vendor/github.com/fatih/color/LICENSE.md b/vendor/github.com/fatih/color/LICENSE.md new file mode 100644 index 000000000..25fdaf639 --- /dev/null +++ b/vendor/github.com/fatih/color/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Fatih Arslan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md new file mode 100644 index 000000000..3fc954460 --- /dev/null +++ b/vendor/github.com/fatih/color/README.md @@ -0,0 +1,179 @@ +# Color [![GoDoc](https://godoc.org/github.com/fatih/color?status.svg)](https://godoc.org/github.com/fatih/color) [![Build Status](https://img.shields.io/travis/fatih/color.svg?style=flat-square)](https://travis-ci.org/fatih/color) + + + +Color lets you use colorized outputs in terms of [ANSI Escape +Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It +has support for Windows too! The API can be used in several ways, pick one that +suits you. + + +![Color](https://i.imgur.com/c1JI0lA.png) + + +## Install + +```bash +go get github.com/fatih/color +``` + +Note that the `vendor` folder is here for stability. Remove the folder if you +already have the dependencies in your GOPATH. + +## Examples + +### Standard colors + +```go +// Print with default helper functions +color.Cyan("Prints text in cyan.") + +// A newline will be appended automatically +color.Blue("Prints %s in blue.", "text") + +// These are using the default foreground colors +color.Red("We have red") +color.Magenta("And many others ..") + +``` + +### Mix and reuse colors + +```go +// Create a new color object +c := color.New(color.FgCyan).Add(color.Underline) +c.Println("Prints cyan text with an underline.") + +// Or just add them to New() +d := color.New(color.FgCyan, color.Bold) +d.Printf("This prints bold cyan %s\n", "too!.") + +// Mix up foreground and background colors, create new mixes! +red := color.New(color.FgRed) + +boldRed := red.Add(color.Bold) +boldRed.Println("This will print text in bold red.") + +whiteBackground := red.Add(color.BgWhite) +whiteBackground.Println("Red text with white background.") +``` + +### Use your own output (io.Writer) + +```go +// Use your own io.Writer output +color.New(color.FgBlue).Fprintln(myWriter, "blue color!") + +blue := color.New(color.FgBlue) +blue.Fprint(writer, "This will print text in blue.") +``` + +### Custom print functions (PrintFunc) + +```go +// Create a custom print function for convenience +red := color.New(color.FgRed).PrintfFunc() +red("Warning") +red("Error: %s", err) + +// Mix up multiple attributes +notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() +notice("Don't forget this...") +``` + +### Custom fprint functions (FprintFunc) + +```go +blue := color.New(FgBlue).FprintfFunc() +blue(myWriter, "important notice: %s", stars) + +// Mix up with multiple attributes +success := color.New(color.Bold, color.FgGreen).FprintlnFunc() +success(myWriter, "Don't forget this...") +``` + +### Insert into noncolor strings (SprintFunc) + +```go +// Create SprintXxx functions to mix strings with other non-colorized strings: +yellow := color.New(color.FgYellow).SprintFunc() +red := color.New(color.FgRed).SprintFunc() +fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error")) + +info := color.New(color.FgWhite, color.BgGreen).SprintFunc() +fmt.Printf("This %s rocks!\n", info("package")) + +// Use helper functions +fmt.Println("This", color.RedString("warning"), "should be not neglected.") +fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.") + +// Windows supported too! Just don't forget to change the output to color.Output +fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) +``` + +### Plug into existing code + +```go +// Use handy standard colors +color.Set(color.FgYellow) + +fmt.Println("Existing text will now be in yellow") +fmt.Printf("This one %s\n", "too") + +color.Unset() // Don't forget to unset + +// You can mix up parameters +color.Set(color.FgMagenta, color.Bold) +defer color.Unset() // Use it in your function + +fmt.Println("All text will now be bold magenta.") +``` + +### Disable/Enable color + +There might be a case where you want to explicitly disable/enable color output. the +`go-isatty` package will automatically disable color output for non-tty output streams +(for example if the output were piped directly to `less`) + +`Color` has support to disable/enable colors both globally and for single color +definitions. For example suppose you have a CLI app and a `--no-color` bool flag. You +can easily disable the color output with: + +```go + +var flagNoColor = flag.Bool("no-color", false, "Disable color output") + +if *flagNoColor { + color.NoColor = true // disables colorized output +} +``` + +It also has support for single color definitions (local). You can +disable/enable color output on the fly: + +```go +c := color.New(color.FgCyan) +c.Println("Prints cyan text") + +c.DisableColor() +c.Println("This is printed without any color") + +c.EnableColor() +c.Println("This prints again cyan...") +``` + +## Todo + +* Save/Return previous values +* Evaluate fmt.Formatter interface + + +## Credits + + * [Fatih Arslan](https://github.com/fatih) + * Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable) + +## License + +The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details + diff --git a/vendor/github.com/fatih/color/color.go b/vendor/github.com/fatih/color/color.go new file mode 100644 index 000000000..91c8e9f06 --- /dev/null +++ b/vendor/github.com/fatih/color/color.go @@ -0,0 +1,603 @@ +package color + +import ( + "fmt" + "io" + "os" + "strconv" + "strings" + "sync" + + "github.com/mattn/go-colorable" + "github.com/mattn/go-isatty" +) + +var ( + // NoColor defines if the output is colorized or not. It's dynamically set to + // false or true based on the stdout's file descriptor referring to a terminal + // or not. This is a global option and affects all colors. For more control + // over each color block use the methods DisableColor() individually. + NoColor = os.Getenv("TERM") == "dumb" || + (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) + + // Output defines the standard output of the print functions. By default + // os.Stdout is used. + Output = colorable.NewColorableStdout() + + // Error defines a color supporting writer for os.Stderr. + Error = colorable.NewColorableStderr() + + // colorsCache is used to reduce the count of created Color objects and + // allows to reuse already created objects with required Attribute. + colorsCache = make(map[Attribute]*Color) + colorsCacheMu sync.Mutex // protects colorsCache +) + +// Color defines a custom color object which is defined by SGR parameters. +type Color struct { + params []Attribute + noColor *bool +} + +// Attribute defines a single SGR Code +type Attribute int + +const escape = "\x1b" + +// Base attributes +const ( + Reset Attribute = iota + Bold + Faint + Italic + Underline + BlinkSlow + BlinkRapid + ReverseVideo + Concealed + CrossedOut +) + +// Foreground text colors +const ( + FgBlack Attribute = iota + 30 + FgRed + FgGreen + FgYellow + FgBlue + FgMagenta + FgCyan + FgWhite +) + +// Foreground Hi-Intensity text colors +const ( + FgHiBlack Attribute = iota + 90 + FgHiRed + FgHiGreen + FgHiYellow + FgHiBlue + FgHiMagenta + FgHiCyan + FgHiWhite +) + +// Background text colors +const ( + BgBlack Attribute = iota + 40 + BgRed + BgGreen + BgYellow + BgBlue + BgMagenta + BgCyan + BgWhite +) + +// Background Hi-Intensity text colors +const ( + BgHiBlack Attribute = iota + 100 + BgHiRed + BgHiGreen + BgHiYellow + BgHiBlue + BgHiMagenta + BgHiCyan + BgHiWhite +) + +// New returns a newly created color object. +func New(value ...Attribute) *Color { + c := &Color{params: make([]Attribute, 0)} + c.Add(value...) + return c +} + +// Set sets the given parameters immediately. It will change the color of +// output with the given SGR parameters until color.Unset() is called. +func Set(p ...Attribute) *Color { + c := New(p...) + c.Set() + return c +} + +// Unset resets all escape attributes and clears the output. Usually should +// be called after Set(). +func Unset() { + if NoColor { + return + } + + fmt.Fprintf(Output, "%s[%dm", escape, Reset) +} + +// Set sets the SGR sequence. +func (c *Color) Set() *Color { + if c.isNoColorSet() { + return c + } + + fmt.Fprintf(Output, c.format()) + return c +} + +func (c *Color) unset() { + if c.isNoColorSet() { + return + } + + Unset() +} + +func (c *Color) setWriter(w io.Writer) *Color { + if c.isNoColorSet() { + return c + } + + fmt.Fprintf(w, c.format()) + return c +} + +func (c *Color) unsetWriter(w io.Writer) { + if c.isNoColorSet() { + return + } + + if NoColor { + return + } + + fmt.Fprintf(w, "%s[%dm", escape, Reset) +} + +// Add is used to chain SGR parameters. Use as many as parameters to combine +// and create custom color objects. Example: Add(color.FgRed, color.Underline). +func (c *Color) Add(value ...Attribute) *Color { + c.params = append(c.params, value...) + return c +} + +func (c *Color) prepend(value Attribute) { + c.params = append(c.params, 0) + copy(c.params[1:], c.params[0:]) + c.params[0] = value +} + +// Fprint formats using the default formats for its operands and writes to w. +// Spaces are added between operands when neither is a string. +// It returns the number of bytes written and any write error encountered. +// On Windows, users should wrap w with colorable.NewColorable() if w is of +// type *os.File. +func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + c.setWriter(w) + defer c.unsetWriter(w) + + return fmt.Fprint(w, a...) +} + +// Print formats using the default formats for its operands and writes to +// standard output. Spaces are added between operands when neither is a +// string. It returns the number of bytes written and any write error +// encountered. This is the standard fmt.Print() method wrapped with the given +// color. +func (c *Color) Print(a ...interface{}) (n int, err error) { + c.Set() + defer c.unset() + + return fmt.Fprint(Output, a...) +} + +// Fprintf formats according to a format specifier and writes to w. +// It returns the number of bytes written and any write error encountered. +// On Windows, users should wrap w with colorable.NewColorable() if w is of +// type *os.File. +func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + c.setWriter(w) + defer c.unsetWriter(w) + + return fmt.Fprintf(w, format, a...) +} + +// Printf formats according to a format specifier and writes to standard output. +// It returns the number of bytes written and any write error encountered. +// This is the standard fmt.Printf() method wrapped with the given color. +func (c *Color) Printf(format string, a ...interface{}) (n int, err error) { + c.Set() + defer c.unset() + + return fmt.Fprintf(Output, format, a...) +} + +// Fprintln formats using the default formats for its operands and writes to w. +// Spaces are always added between operands and a newline is appended. +// On Windows, users should wrap w with colorable.NewColorable() if w is of +// type *os.File. +func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + c.setWriter(w) + defer c.unsetWriter(w) + + return fmt.Fprintln(w, a...) +} + +// Println formats using the default formats for its operands and writes to +// standard output. Spaces are always added between operands and a newline is +// appended. It returns the number of bytes written and any write error +// encountered. This is the standard fmt.Print() method wrapped with the given +// color. +func (c *Color) Println(a ...interface{}) (n int, err error) { + c.Set() + defer c.unset() + + return fmt.Fprintln(Output, a...) +} + +// Sprint is just like Print, but returns a string instead of printing it. +func (c *Color) Sprint(a ...interface{}) string { + return c.wrap(fmt.Sprint(a...)) +} + +// Sprintln is just like Println, but returns a string instead of printing it. +func (c *Color) Sprintln(a ...interface{}) string { + return c.wrap(fmt.Sprintln(a...)) +} + +// Sprintf is just like Printf, but returns a string instead of printing it. +func (c *Color) Sprintf(format string, a ...interface{}) string { + return c.wrap(fmt.Sprintf(format, a...)) +} + +// FprintFunc returns a new function that prints the passed arguments as +// colorized with color.Fprint(). +func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) { + return func(w io.Writer, a ...interface{}) { + c.Fprint(w, a...) + } +} + +// PrintFunc returns a new function that prints the passed arguments as +// colorized with color.Print(). +func (c *Color) PrintFunc() func(a ...interface{}) { + return func(a ...interface{}) { + c.Print(a...) + } +} + +// FprintfFunc returns a new function that prints the passed arguments as +// colorized with color.Fprintf(). +func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) { + return func(w io.Writer, format string, a ...interface{}) { + c.Fprintf(w, format, a...) + } +} + +// PrintfFunc returns a new function that prints the passed arguments as +// colorized with color.Printf(). +func (c *Color) PrintfFunc() func(format string, a ...interface{}) { + return func(format string, a ...interface{}) { + c.Printf(format, a...) + } +} + +// FprintlnFunc returns a new function that prints the passed arguments as +// colorized with color.Fprintln(). +func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) { + return func(w io.Writer, a ...interface{}) { + c.Fprintln(w, a...) + } +} + +// PrintlnFunc returns a new function that prints the passed arguments as +// colorized with color.Println(). +func (c *Color) PrintlnFunc() func(a ...interface{}) { + return func(a ...interface{}) { + c.Println(a...) + } +} + +// SprintFunc returns a new function that returns colorized strings for the +// given arguments with fmt.Sprint(). Useful to put into or mix into other +// string. Windows users should use this in conjunction with color.Output, example: +// +// put := New(FgYellow).SprintFunc() +// fmt.Fprintf(color.Output, "This is a %s", put("warning")) +func (c *Color) SprintFunc() func(a ...interface{}) string { + return func(a ...interface{}) string { + return c.wrap(fmt.Sprint(a...)) + } +} + +// SprintfFunc returns a new function that returns colorized strings for the +// given arguments with fmt.Sprintf(). Useful to put into or mix into other +// string. Windows users should use this in conjunction with color.Output. +func (c *Color) SprintfFunc() func(format string, a ...interface{}) string { + return func(format string, a ...interface{}) string { + return c.wrap(fmt.Sprintf(format, a...)) + } +} + +// SprintlnFunc returns a new function that returns colorized strings for the +// given arguments with fmt.Sprintln(). Useful to put into or mix into other +// string. Windows users should use this in conjunction with color.Output. +func (c *Color) SprintlnFunc() func(a ...interface{}) string { + return func(a ...interface{}) string { + return c.wrap(fmt.Sprintln(a...)) + } +} + +// sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m" +// an example output might be: "1;36" -> bold cyan +func (c *Color) sequence() string { + format := make([]string, len(c.params)) + for i, v := range c.params { + format[i] = strconv.Itoa(int(v)) + } + + return strings.Join(format, ";") +} + +// wrap wraps the s string with the colors attributes. The string is ready to +// be printed. +func (c *Color) wrap(s string) string { + if c.isNoColorSet() { + return s + } + + return c.format() + s + c.unformat() +} + +func (c *Color) format() string { + return fmt.Sprintf("%s[%sm", escape, c.sequence()) +} + +func (c *Color) unformat() string { + return fmt.Sprintf("%s[%dm", escape, Reset) +} + +// DisableColor disables the color output. Useful to not change any existing +// code and still being able to output. Can be used for flags like +// "--no-color". To enable back use EnableColor() method. +func (c *Color) DisableColor() { + c.noColor = boolPtr(true) +} + +// EnableColor enables the color output. Use it in conjunction with +// DisableColor(). Otherwise this method has no side effects. +func (c *Color) EnableColor() { + c.noColor = boolPtr(false) +} + +func (c *Color) isNoColorSet() bool { + // check first if we have user setted action + if c.noColor != nil { + return *c.noColor + } + + // if not return the global option, which is disabled by default + return NoColor +} + +// Equals returns a boolean value indicating whether two colors are equal. +func (c *Color) Equals(c2 *Color) bool { + if len(c.params) != len(c2.params) { + return false + } + + for _, attr := range c.params { + if !c2.attrExists(attr) { + return false + } + } + + return true +} + +func (c *Color) attrExists(a Attribute) bool { + for _, attr := range c.params { + if attr == a { + return true + } + } + + return false +} + +func boolPtr(v bool) *bool { + return &v +} + +func getCachedColor(p Attribute) *Color { + colorsCacheMu.Lock() + defer colorsCacheMu.Unlock() + + c, ok := colorsCache[p] + if !ok { + c = New(p) + colorsCache[p] = c + } + + return c +} + +func colorPrint(format string, p Attribute, a ...interface{}) { + c := getCachedColor(p) + + if !strings.HasSuffix(format, "\n") { + format += "\n" + } + + if len(a) == 0 { + c.Print(format) + } else { + c.Printf(format, a...) + } +} + +func colorString(format string, p Attribute, a ...interface{}) string { + c := getCachedColor(p) + + if len(a) == 0 { + return c.SprintFunc()(format) + } + + return c.SprintfFunc()(format, a...) +} + +// Black is a convenient helper function to print with black foreground. A +// newline is appended to format by default. +func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) } + +// Red is a convenient helper function to print with red foreground. A +// newline is appended to format by default. +func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) } + +// Green is a convenient helper function to print with green foreground. A +// newline is appended to format by default. +func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) } + +// Yellow is a convenient helper function to print with yellow foreground. +// A newline is appended to format by default. +func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) } + +// Blue is a convenient helper function to print with blue foreground. A +// newline is appended to format by default. +func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) } + +// Magenta is a convenient helper function to print with magenta foreground. +// A newline is appended to format by default. +func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) } + +// Cyan is a convenient helper function to print with cyan foreground. A +// newline is appended to format by default. +func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) } + +// White is a convenient helper function to print with white foreground. A +// newline is appended to format by default. +func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) } + +// BlackString is a convenient helper function to return a string with black +// foreground. +func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) } + +// RedString is a convenient helper function to return a string with red +// foreground. +func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) } + +// GreenString is a convenient helper function to return a string with green +// foreground. +func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) } + +// YellowString is a convenient helper function to return a string with yellow +// foreground. +func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) } + +// BlueString is a convenient helper function to return a string with blue +// foreground. +func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) } + +// MagentaString is a convenient helper function to return a string with magenta +// foreground. +func MagentaString(format string, a ...interface{}) string { + return colorString(format, FgMagenta, a...) +} + +// CyanString is a convenient helper function to return a string with cyan +// foreground. +func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) } + +// WhiteString is a convenient helper function to return a string with white +// foreground. +func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) } + +// HiBlack is a convenient helper function to print with hi-intensity black foreground. A +// newline is appended to format by default. +func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) } + +// HiRed is a convenient helper function to print with hi-intensity red foreground. A +// newline is appended to format by default. +func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) } + +// HiGreen is a convenient helper function to print with hi-intensity green foreground. A +// newline is appended to format by default. +func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) } + +// HiYellow is a convenient helper function to print with hi-intensity yellow foreground. +// A newline is appended to format by default. +func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) } + +// HiBlue is a convenient helper function to print with hi-intensity blue foreground. A +// newline is appended to format by default. +func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) } + +// HiMagenta is a convenient helper function to print with hi-intensity magenta foreground. +// A newline is appended to format by default. +func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) } + +// HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A +// newline is appended to format by default. +func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) } + +// HiWhite is a convenient helper function to print with hi-intensity white foreground. A +// newline is appended to format by default. +func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) } + +// HiBlackString is a convenient helper function to return a string with hi-intensity black +// foreground. +func HiBlackString(format string, a ...interface{}) string { + return colorString(format, FgHiBlack, a...) +} + +// HiRedString is a convenient helper function to return a string with hi-intensity red +// foreground. +func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) } + +// HiGreenString is a convenient helper function to return a string with hi-intensity green +// foreground. +func HiGreenString(format string, a ...interface{}) string { + return colorString(format, FgHiGreen, a...) +} + +// HiYellowString is a convenient helper function to return a string with hi-intensity yellow +// foreground. +func HiYellowString(format string, a ...interface{}) string { + return colorString(format, FgHiYellow, a...) +} + +// HiBlueString is a convenient helper function to return a string with hi-intensity blue +// foreground. +func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) } + +// HiMagentaString is a convenient helper function to return a string with hi-intensity magenta +// foreground. +func HiMagentaString(format string, a ...interface{}) string { + return colorString(format, FgHiMagenta, a...) +} + +// HiCyanString is a convenient helper function to return a string with hi-intensity cyan +// foreground. +func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) } + +// HiWhiteString is a convenient helper function to return a string with hi-intensity white +// foreground. +func HiWhiteString(format string, a ...interface{}) string { + return colorString(format, FgHiWhite, a...) +} diff --git a/vendor/github.com/fatih/color/doc.go b/vendor/github.com/fatih/color/doc.go new file mode 100644 index 000000000..cf1e96500 --- /dev/null +++ b/vendor/github.com/fatih/color/doc.go @@ -0,0 +1,133 @@ +/* +Package color is an ANSI color package to output colorized or SGR defined +output to the standard output. The API can be used in several way, pick one +that suits you. + +Use simple and default helper functions with predefined foreground colors: + + color.Cyan("Prints text in cyan.") + + // a newline will be appended automatically + color.Blue("Prints %s in blue.", "text") + + // More default foreground colors.. + color.Red("We have red") + color.Yellow("Yellow color too!") + color.Magenta("And many others ..") + + // Hi-intensity colors + color.HiGreen("Bright green color.") + color.HiBlack("Bright black means gray..") + color.HiWhite("Shiny white color!") + +However there are times where custom color mixes are required. Below are some +examples to create custom color objects and use the print functions of each +separate color object. + + // Create a new color object + c := color.New(color.FgCyan).Add(color.Underline) + c.Println("Prints cyan text with an underline.") + + // Or just add them to New() + d := color.New(color.FgCyan, color.Bold) + d.Printf("This prints bold cyan %s\n", "too!.") + + + // Mix up foreground and background colors, create new mixes! + red := color.New(color.FgRed) + + boldRed := red.Add(color.Bold) + boldRed.Println("This will print text in bold red.") + + whiteBackground := red.Add(color.BgWhite) + whiteBackground.Println("Red text with White background.") + + // Use your own io.Writer output + color.New(color.FgBlue).Fprintln(myWriter, "blue color!") + + blue := color.New(color.FgBlue) + blue.Fprint(myWriter, "This will print text in blue.") + +You can create PrintXxx functions to simplify even more: + + // Create a custom print function for convenient + red := color.New(color.FgRed).PrintfFunc() + red("warning") + red("error: %s", err) + + // Mix up multiple attributes + notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() + notice("don't forget this...") + +You can also FprintXxx functions to pass your own io.Writer: + + blue := color.New(FgBlue).FprintfFunc() + blue(myWriter, "important notice: %s", stars) + + // Mix up with multiple attributes + success := color.New(color.Bold, color.FgGreen).FprintlnFunc() + success(myWriter, don't forget this...") + + +Or create SprintXxx functions to mix strings with other non-colorized strings: + + yellow := New(FgYellow).SprintFunc() + red := New(FgRed).SprintFunc() + + fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error")) + + info := New(FgWhite, BgGreen).SprintFunc() + fmt.Printf("this %s rocks!\n", info("package")) + +Windows support is enabled by default. All Print functions work as intended. +However only for color.SprintXXX functions, user should use fmt.FprintXXX and +set the output to color.Output: + + fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) + + info := New(FgWhite, BgGreen).SprintFunc() + fmt.Fprintf(color.Output, "this %s rocks!\n", info("package")) + +Using with existing code is possible. Just use the Set() method to set the +standard output to the given parameters. That way a rewrite of an existing +code is not required. + + // Use handy standard colors. + color.Set(color.FgYellow) + + fmt.Println("Existing text will be now in Yellow") + fmt.Printf("This one %s\n", "too") + + color.Unset() // don't forget to unset + + // You can mix up parameters + color.Set(color.FgMagenta, color.Bold) + defer color.Unset() // use it in your function + + fmt.Println("All text will be now bold magenta.") + +There might be a case where you want to disable color output (for example to +pipe the standard output of your app to somewhere else). `Color` has support to +disable colors both globally and for single color definition. For example +suppose you have a CLI app and a `--no-color` bool flag. You can easily disable +the color output with: + + var flagNoColor = flag.Bool("no-color", false, "Disable color output") + + if *flagNoColor { + color.NoColor = true // disables colorized output + } + +It also has support for single color definitions (local). You can +disable/enable color output on the fly: + + c := color.New(color.FgCyan) + c.Println("Prints cyan text") + + c.DisableColor() + c.Println("This is printed without any color") + + c.EnableColor() + c.Println("This prints again cyan...") +*/ +package color diff --git a/vendor/github.com/fsnotify/fsnotify/.editorconfig b/vendor/github.com/fsnotify/fsnotify/.editorconfig new file mode 100644 index 000000000..ba49e3c23 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 diff --git a/vendor/github.com/fsnotify/fsnotify/.gitignore b/vendor/github.com/fsnotify/fsnotify/.gitignore new file mode 100644 index 000000000..4cd0cbaf4 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.gitignore @@ -0,0 +1,6 @@ +# Setup a Global .gitignore for OS and editor generated files: +# https://help.github.com/articles/ignoring-files +# git config --global core.excludesfile ~/.gitignore_global + +.vagrant +*.sublime-project diff --git a/vendor/github.com/fsnotify/fsnotify/.travis.yml b/vendor/github.com/fsnotify/fsnotify/.travis.yml new file mode 100644 index 000000000..981d1bb81 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.travis.yml @@ -0,0 +1,30 @@ +sudo: false +language: go + +go: + - 1.8.x + - 1.9.x + - tip + +matrix: + allow_failures: + - go: tip + fast_finish: true + +before_script: + - go get -u github.com/golang/lint/golint + +script: + - go test -v --race ./... + +after_script: + - test -z "$(gofmt -s -l -w . | tee /dev/stderr)" + - test -z "$(golint ./... | tee /dev/stderr)" + - go vet ./... + +os: + - linux + - osx + +notifications: + email: false diff --git a/vendor/github.com/fsnotify/fsnotify/AUTHORS b/vendor/github.com/fsnotify/fsnotify/AUTHORS new file mode 100644 index 000000000..5ab5d41c5 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/AUTHORS @@ -0,0 +1,52 @@ +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# You can update this list using the following command: +# +# $ git shortlog -se | awk '{print $2 " " $3 " " $4}' + +# Please keep the list sorted. + +Aaron L +Adrien Bustany +Amit Krishnan +Anmol Sethi +Bjørn Erik Pedersen +Bruno Bigras +Caleb Spare +Case Nelson +Chris Howey +Christoffer Buchholz +Daniel Wagner-Hall +Dave Cheney +Evan Phoenix +Francisco Souza +Hari haran +John C Barstow +Kelvin Fo +Ken-ichirou MATSUZAWA +Matt Layher +Nathan Youngman +Nickolai Zeldovich +Patrick +Paul Hammond +Pawel Knap +Pieter Droogendijk +Pursuit92 +Riku Voipio +Rob Figueiredo +Rodrigo Chiossi +Slawek Ligus +Soge Zhang +Tiffany Jernigan +Tilak Sharma +Tom Payne +Travis Cline +Tudor Golubenco +Vahe Khachikyan +Yukang +bronze1man +debrando +henrikedwards +铁哥 diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md new file mode 100644 index 000000000..be4d7ea2c --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -0,0 +1,317 @@ +# Changelog + +## v1.4.7 / 2018-01-09 + +* BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine) +* Tests: Fix missing verb on format string (thanks @rchiossi) +* Linux: Fix deadlock in Remove (thanks @aarondl) +* Linux: Watch.Add improvements (avoid race, fix consistency, reduce garbage) (thanks @twpayne) +* Docs: Moved FAQ into the README (thanks @vahe) +* Linux: Properly handle inotify's IN_Q_OVERFLOW event (thanks @zeldovich) +* Docs: replace references to OS X with macOS + +## v1.4.2 / 2016-10-10 + +* Linux: use InotifyInit1 with IN_CLOEXEC to stop leaking a file descriptor to a child process when using fork/exec [#178](https://github.com/fsnotify/fsnotify/pull/178) (thanks @pattyshack) + +## v1.4.1 / 2016-10-04 + +* Fix flaky inotify stress test on Linux [#177](https://github.com/fsnotify/fsnotify/pull/177) (thanks @pattyshack) + +## v1.4.0 / 2016-10-01 + +* add a String() method to Event.Op [#165](https://github.com/fsnotify/fsnotify/pull/165) (thanks @oozie) + +## v1.3.1 / 2016-06-28 + +* Windows: fix for double backslash when watching the root of a drive [#151](https://github.com/fsnotify/fsnotify/issues/151) (thanks @brunoqc) + +## v1.3.0 / 2016-04-19 + +* Support linux/arm64 by [patching](https://go-review.googlesource.com/#/c/21971/) x/sys/unix and switching to to it from syscall (thanks @suihkulokki) [#135](https://github.com/fsnotify/fsnotify/pull/135) + +## v1.2.10 / 2016-03-02 + +* Fix golint errors in windows.go [#121](https://github.com/fsnotify/fsnotify/pull/121) (thanks @tiffanyfj) + +## v1.2.9 / 2016-01-13 + +kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsnotify/pull/111) (thanks @bep) + +## v1.2.8 / 2015-12-17 + +* kqueue: fix race condition in Close [#105](https://github.com/fsnotify/fsnotify/pull/105) (thanks @djui for reporting the issue and @ppknap for writing a failing test) +* inotify: fix race in test +* enable race detection for continuous integration (Linux, Mac, Windows) + +## v1.2.5 / 2015-10-17 + +* inotify: use epoll_create1 for arm64 support (requires Linux 2.6.27 or later) [#100](https://github.com/fsnotify/fsnotify/pull/100) (thanks @suihkulokki) +* inotify: fix path leaks [#73](https://github.com/fsnotify/fsnotify/pull/73) (thanks @chamaken) +* kqueue: watch for rename events on subdirectories [#83](https://github.com/fsnotify/fsnotify/pull/83) (thanks @guotie) +* kqueue: avoid infinite loops from symlinks cycles [#101](https://github.com/fsnotify/fsnotify/pull/101) (thanks @illicitonion) + +## v1.2.1 / 2015-10-14 + +* kqueue: don't watch named pipes [#98](https://github.com/fsnotify/fsnotify/pull/98) (thanks @evanphx) + +## v1.2.0 / 2015-02-08 + +* inotify: use epoll to wake up readEvents [#66](https://github.com/fsnotify/fsnotify/pull/66) (thanks @PieterD) +* inotify: closing watcher should now always shut down goroutine [#63](https://github.com/fsnotify/fsnotify/pull/63) (thanks @PieterD) +* kqueue: close kqueue after removing watches, fixes [#59](https://github.com/fsnotify/fsnotify/issues/59) + +## v1.1.1 / 2015-02-05 + +* inotify: Retry read on EINTR [#61](https://github.com/fsnotify/fsnotify/issues/61) (thanks @PieterD) + +## v1.1.0 / 2014-12-12 + +* kqueue: rework internals [#43](https://github.com/fsnotify/fsnotify/pull/43) + * add low-level functions + * only need to store flags on directories + * less mutexes [#13](https://github.com/fsnotify/fsnotify/issues/13) + * done can be an unbuffered channel + * remove calls to os.NewSyscallError +* More efficient string concatenation for Event.String() [#52](https://github.com/fsnotify/fsnotify/pull/52) (thanks @mdlayher) +* kqueue: fix regression in rework causing subdirectories to be watched [#48](https://github.com/fsnotify/fsnotify/issues/48) +* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51) + +## v1.0.4 / 2014-09-07 + +* kqueue: add dragonfly to the build tags. +* Rename source code files, rearrange code so exported APIs are at the top. +* Add done channel to example code. [#37](https://github.com/fsnotify/fsnotify/pull/37) (thanks @chenyukang) + +## v1.0.3 / 2014-08-19 + +* [Fix] Windows MOVED_TO now translates to Create like on BSD and Linux. [#36](https://github.com/fsnotify/fsnotify/issues/36) + +## v1.0.2 / 2014-08-17 + +* [Fix] Missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso) +* [Fix] Make ./path and path equivalent. (thanks @zhsso) + +## v1.0.0 / 2014-08-15 + +* [API] Remove AddWatch on Windows, use Add. +* Improve documentation for exported identifiers. [#30](https://github.com/fsnotify/fsnotify/issues/30) +* Minor updates based on feedback from golint. + +## dev / 2014-07-09 + +* Moved to [github.com/fsnotify/fsnotify](https://github.com/fsnotify/fsnotify). +* Use os.NewSyscallError instead of returning errno (thanks @hariharan-uno) + +## dev / 2014-07-04 + +* kqueue: fix incorrect mutex used in Close() +* Update example to demonstrate usage of Op. + +## dev / 2014-06-28 + +* [API] Don't set the Write Op for attribute notifications [#4](https://github.com/fsnotify/fsnotify/issues/4) +* Fix for String() method on Event (thanks Alex Brainman) +* Don't build on Plan 9 or Solaris (thanks @4ad) + +## dev / 2014-06-21 + +* Events channel of type Event rather than *Event. +* [internal] use syscall constants directly for inotify and kqueue. +* [internal] kqueue: rename events to kevents and fileEvent to event. + +## dev / 2014-06-19 + +* Go 1.3+ required on Windows (uses syscall.ERROR_MORE_DATA internally). +* [internal] remove cookie from Event struct (unused). +* [internal] Event struct has the same definition across every OS. +* [internal] remove internal watch and removeWatch methods. + +## dev / 2014-06-12 + +* [API] Renamed Watch() to Add() and RemoveWatch() to Remove(). +* [API] Pluralized channel names: Events and Errors. +* [API] Renamed FileEvent struct to Event. +* [API] Op constants replace methods like IsCreate(). + +## dev / 2014-06-12 + +* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98) + +## dev / 2014-05-23 + +* [API] Remove current implementation of WatchFlags. + * current implementation doesn't take advantage of OS for efficiency + * provides little benefit over filtering events as they are received, but has extra bookkeeping and mutexes + * no tests for the current implementation + * not fully implemented on Windows [#93](https://github.com/howeyc/fsnotify/issues/93#issuecomment-39285195) + +## v0.9.3 / 2014-12-31 + +* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51) + +## v0.9.2 / 2014-08-17 + +* [Backport] Fix missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso) + +## v0.9.1 / 2014-06-12 + +* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98) + +## v0.9.0 / 2014-01-17 + +* IsAttrib() for events that only concern a file's metadata [#79][] (thanks @abustany) +* [Fix] kqueue: fix deadlock [#77][] (thanks @cespare) +* [NOTICE] Development has moved to `code.google.com/p/go.exp/fsnotify` in preparation for inclusion in the Go standard library. + +## v0.8.12 / 2013-11-13 + +* [API] Remove FD_SET and friends from Linux adapter + +## v0.8.11 / 2013-11-02 + +* [Doc] Add Changelog [#72][] (thanks @nathany) +* [Doc] Spotlight and double modify events on macOS [#62][] (reported by @paulhammond) + +## v0.8.10 / 2013-10-19 + +* [Fix] kqueue: remove file watches when parent directory is removed [#71][] (reported by @mdwhatcott) +* [Fix] kqueue: race between Close and readEvents [#70][] (reported by @bernerdschaefer) +* [Doc] specify OS-specific limits in README (thanks @debrando) + +## v0.8.9 / 2013-09-08 + +* [Doc] Contributing (thanks @nathany) +* [Doc] update package path in example code [#63][] (thanks @paulhammond) +* [Doc] GoCI badge in README (Linux only) [#60][] +* [Doc] Cross-platform testing with Vagrant [#59][] (thanks @nathany) + +## v0.8.8 / 2013-06-17 + +* [Fix] Windows: handle `ERROR_MORE_DATA` on Windows [#49][] (thanks @jbowtie) + +## v0.8.7 / 2013-06-03 + +* [API] Make syscall flags internal +* [Fix] inotify: ignore event changes +* [Fix] race in symlink test [#45][] (reported by @srid) +* [Fix] tests on Windows +* lower case error messages + +## v0.8.6 / 2013-05-23 + +* kqueue: Use EVT_ONLY flag on Darwin +* [Doc] Update README with full example + +## v0.8.5 / 2013-05-09 + +* [Fix] inotify: allow monitoring of "broken" symlinks (thanks @tsg) + +## v0.8.4 / 2013-04-07 + +* [Fix] kqueue: watch all file events [#40][] (thanks @ChrisBuchholz) + +## v0.8.3 / 2013-03-13 + +* [Fix] inoitfy/kqueue memory leak [#36][] (reported by @nbkolchin) +* [Fix] kqueue: use fsnFlags for watching a directory [#33][] (reported by @nbkolchin) + +## v0.8.2 / 2013-02-07 + +* [Doc] add Authors +* [Fix] fix data races for map access [#29][] (thanks @fsouza) + +## v0.8.1 / 2013-01-09 + +* [Fix] Windows path separators +* [Doc] BSD License + +## v0.8.0 / 2012-11-09 + +* kqueue: directory watching improvements (thanks @vmirage) +* inotify: add `IN_MOVED_TO` [#25][] (requested by @cpisto) +* [Fix] kqueue: deleting watched directory [#24][] (reported by @jakerr) + +## v0.7.4 / 2012-10-09 + +* [Fix] inotify: fixes from https://codereview.appspot.com/5418045/ (ugorji) +* [Fix] kqueue: preserve watch flags when watching for delete [#21][] (reported by @robfig) +* [Fix] kqueue: watch the directory even if it isn't a new watch (thanks @robfig) +* [Fix] kqueue: modify after recreation of file + +## v0.7.3 / 2012-09-27 + +* [Fix] kqueue: watch with an existing folder inside the watched folder (thanks @vmirage) +* [Fix] kqueue: no longer get duplicate CREATE events + +## v0.7.2 / 2012-09-01 + +* kqueue: events for created directories + +## v0.7.1 / 2012-07-14 + +* [Fix] for renaming files + +## v0.7.0 / 2012-07-02 + +* [Feature] FSNotify flags +* [Fix] inotify: Added file name back to event path + +## v0.6.0 / 2012-06-06 + +* kqueue: watch files after directory created (thanks @tmc) + +## v0.5.1 / 2012-05-22 + +* [Fix] inotify: remove all watches before Close() + +## v0.5.0 / 2012-05-03 + +* [API] kqueue: return errors during watch instead of sending over channel +* kqueue: match symlink behavior on Linux +* inotify: add `DELETE_SELF` (requested by @taralx) +* [Fix] kqueue: handle EINTR (reported by @robfig) +* [Doc] Godoc example [#1][] (thanks @davecheney) + +## v0.4.0 / 2012-03-30 + +* Go 1 released: build with go tool +* [Feature] Windows support using winfsnotify +* Windows does not have attribute change notifications +* Roll attribute notifications into IsModify + +## v0.3.0 / 2012-02-19 + +* kqueue: add files when watch directory + +## v0.2.0 / 2011-12-30 + +* update to latest Go weekly code + +## v0.1.0 / 2011-10-19 + +* kqueue: add watch on file creation to match inotify +* kqueue: create file event +* inotify: ignore `IN_IGNORED` events +* event String() +* linux: common FileEvent functions +* initial commit + +[#79]: https://github.com/howeyc/fsnotify/pull/79 +[#77]: https://github.com/howeyc/fsnotify/pull/77 +[#72]: https://github.com/howeyc/fsnotify/issues/72 +[#71]: https://github.com/howeyc/fsnotify/issues/71 +[#70]: https://github.com/howeyc/fsnotify/issues/70 +[#63]: https://github.com/howeyc/fsnotify/issues/63 +[#62]: https://github.com/howeyc/fsnotify/issues/62 +[#60]: https://github.com/howeyc/fsnotify/issues/60 +[#59]: https://github.com/howeyc/fsnotify/issues/59 +[#49]: https://github.com/howeyc/fsnotify/issues/49 +[#45]: https://github.com/howeyc/fsnotify/issues/45 +[#40]: https://github.com/howeyc/fsnotify/issues/40 +[#36]: https://github.com/howeyc/fsnotify/issues/36 +[#33]: https://github.com/howeyc/fsnotify/issues/33 +[#29]: https://github.com/howeyc/fsnotify/issues/29 +[#25]: https://github.com/howeyc/fsnotify/issues/25 +[#24]: https://github.com/howeyc/fsnotify/issues/24 +[#21]: https://github.com/howeyc/fsnotify/issues/21 diff --git a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md new file mode 100644 index 000000000..828a60b24 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md @@ -0,0 +1,77 @@ +# Contributing + +## Issues + +* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/fsnotify/fsnotify/issues). +* Please indicate the platform you are using fsnotify on. +* A code example to reproduce the problem is appreciated. + +## Pull Requests + +### Contributor License Agreement + +fsnotify is derived from code in the [golang.org/x/exp](https://godoc.org/golang.org/x/exp) package and it may be included [in the standard library](https://github.com/fsnotify/fsnotify/issues/1) in the future. Therefore fsnotify carries the same [LICENSE](https://github.com/fsnotify/fsnotify/blob/master/LICENSE) as Go. Contributors retain their copyright, so you need to fill out a short form before we can accept your contribution: [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual). + +Please indicate that you have signed the CLA in your pull request. + +### How fsnotify is Developed + +* Development is done on feature branches. +* Tests are run on BSD, Linux, macOS and Windows. +* Pull requests are reviewed and [applied to master][am] using [hub][]. + * Maintainers may modify or squash commits rather than asking contributors to. +* To issue a new release, the maintainers will: + * Update the CHANGELOG + * Tag a version, which will become available through gopkg.in. + +### How to Fork + +For smooth sailing, always use the original import path. Installing with `go get` makes this easy. + +1. Install from GitHub (`go get -u github.com/fsnotify/fsnotify`) +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Ensure everything works and the tests pass (see below) +4. Commit your changes (`git commit -am 'Add some feature'`) + +Contribute upstream: + +1. Fork fsnotify on GitHub +2. Add your remote (`git remote add fork git@github.com:mycompany/repo.git`) +3. Push to the branch (`git push fork my-new-feature`) +4. Create a new Pull Request on GitHub + +This workflow is [thoroughly explained by Katrina Owen](https://splice.com/blog/contributing-open-source-git-repositories-go/). + +### Testing + +fsnotify uses build tags to compile different code on Linux, BSD, macOS, and Windows. + +Before doing a pull request, please do your best to test your changes on multiple platforms, and list which platforms you were able/unable to test on. + +To aid in cross-platform testing there is a Vagrantfile for Linux and BSD. + +* Install [Vagrant](http://www.vagrantup.com/) and [VirtualBox](https://www.virtualbox.org/) +* Setup [Vagrant Gopher](https://github.com/nathany/vagrant-gopher) in your `src` folder. +* Run `vagrant up` from the project folder. You can also setup just one box with `vagrant up linux` or `vagrant up bsd` (note: the BSD box doesn't support Windows hosts at this time, and NFS may prompt for your host OS password) +* Once setup, you can run the test suite on a given OS with a single command `vagrant ssh linux -c 'cd fsnotify/fsnotify; go test'`. +* When you're done, you will want to halt or destroy the Vagrant boxes. + +Notice: fsnotify file system events won't trigger in shared folders. The tests get around this limitation by using the /tmp directory. + +Right now there is no equivalent solution for Windows and macOS, but there are Windows VMs [freely available from Microsoft](http://www.modern.ie/en-us/virtualization-tools#downloads). + +### Maintainers + +Help maintaining fsnotify is welcome. To be a maintainer: + +* Submit a pull request and sign the CLA as above. +* You must be able to run the test suite on Mac, Windows, Linux and BSD. + +To keep master clean, the fsnotify project uses the "apply mail" workflow outlined in Nathaniel Talbott's post ["Merge pull request" Considered Harmful][am]. This requires installing [hub][]. + +All code changes should be internal pull requests. + +Releases are tagged using [Semantic Versioning](http://semver.org/). + +[hub]: https://github.com/github/hub +[am]: http://blog.spreedly.com/2014/06/24/merge-pull-request-considered-harmful/#.VGa5yZPF_Zs diff --git a/vendor/github.com/fsnotify/fsnotify/LICENSE b/vendor/github.com/fsnotify/fsnotify/LICENSE new file mode 100644 index 000000000..f21e54080 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2012 fsnotify Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md new file mode 100644 index 000000000..399320741 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/README.md @@ -0,0 +1,79 @@ +# File system notifications for Go + +[![GoDoc](https://godoc.org/github.com/fsnotify/fsnotify?status.svg)](https://godoc.org/github.com/fsnotify/fsnotify) [![Go Report Card](https://goreportcard.com/badge/github.com/fsnotify/fsnotify)](https://goreportcard.com/report/github.com/fsnotify/fsnotify) + +fsnotify utilizes [golang.org/x/sys](https://godoc.org/golang.org/x/sys) rather than `syscall` from the standard library. Ensure you have the latest version installed by running: + +```console +go get -u golang.org/x/sys/... +``` + +Cross platform: Windows, Linux, BSD and macOS. + +|Adapter |OS |Status | +|----------|----------|----------| +|inotify |Linux 2.6.27 or later, Android\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)| +|kqueue |BSD, macOS, iOS\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)| +|ReadDirectoryChangesW|Windows|Supported [![Build status](https://ci.appveyor.com/api/projects/status/ivwjubaih4r0udeh/branch/master?svg=true)](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)| +|FSEvents |macOS |[Planned](https://github.com/fsnotify/fsnotify/issues/11)| +|FEN |Solaris 11 |[In Progress](https://github.com/fsnotify/fsnotify/issues/12)| +|fanotify |Linux 2.6.37+ | | +|USN Journals |Windows |[Maybe](https://github.com/fsnotify/fsnotify/issues/53)| +|Polling |*All* |[Maybe](https://github.com/fsnotify/fsnotify/issues/9)| + +\* Android and iOS are untested. + +Please see [the documentation](https://godoc.org/github.com/fsnotify/fsnotify) and consult the [FAQ](#faq) for usage information. + +## API stability + +fsnotify is a fork of [howeyc/fsnotify](https://godoc.org/github.com/howeyc/fsnotify) with a new API as of v1.0. The API is based on [this design document](http://goo.gl/MrYxyA). + +All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based on [Semantic Versioning](http://semver.org/). Further API changes are [planned](https://github.com/fsnotify/fsnotify/milestones), and will be tagged with a new major revision number. + +Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`. + +## Contributing + +Please refer to [CONTRIBUTING][] before opening an issue or pull request. + +## Example + +See [example_test.go](https://github.com/fsnotify/fsnotify/blob/master/example_test.go). + +## FAQ + +**When a file is moved to another directory is it still being watched?** + +No (it shouldn't be, unless you are watching where it was moved to). + +**When I watch a directory, are all subdirectories watched as well?** + +No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap [#18][]). + +**Do I have to watch the Error and Event channels in a separate goroutine?** + +As of now, yes. Looking into making this single-thread friendly (see [howeyc #7][#7]) + +**Why am I receiving multiple events for the same file on OS X?** + +Spotlight indexing on OS X can result in multiple events (see [howeyc #62][#62]). A temporary workaround is to add your folder(s) to the *Spotlight Privacy settings* until we have a native FSEvents implementation (see [#11][]). + +**How many files can be watched at once?** + +There are OS-specific limits as to how many watches can be created: +* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error. +* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error. + +[#62]: https://github.com/howeyc/fsnotify/issues/62 +[#18]: https://github.com/fsnotify/fsnotify/issues/18 +[#11]: https://github.com/fsnotify/fsnotify/issues/11 +[#7]: https://github.com/howeyc/fsnotify/issues/7 + +[contributing]: https://github.com/fsnotify/fsnotify/blob/master/CONTRIBUTING.md + +## Related Projects + +* [notify](https://github.com/rjeczalik/notify) +* [fsevents](https://github.com/fsnotify/fsevents) + diff --git a/vendor/github.com/fsnotify/fsnotify/fen.go b/vendor/github.com/fsnotify/fsnotify/fen.go new file mode 100644 index 000000000..ced39cb88 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/fen.go @@ -0,0 +1,37 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build solaris + +package fsnotify + +import ( + "errors" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + return nil, errors.New("FEN based watcher not yet supported for fsnotify\n") +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + return nil +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + return nil +} + +// Remove stops watching the the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + return nil +} diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go new file mode 100644 index 000000000..190bf0de5 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -0,0 +1,66 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !plan9 + +// Package fsnotify provides a platform-independent interface for file system notifications. +package fsnotify + +import ( + "bytes" + "errors" + "fmt" +) + +// Event represents a single file system notification. +type Event struct { + Name string // Relative path to the file or directory. + Op Op // File operation that triggered the event. +} + +// Op describes a set of file operations. +type Op uint32 + +// These are the generalized file operations that can trigger a notification. +const ( + Create Op = 1 << iota + Write + Remove + Rename + Chmod +) + +func (op Op) String() string { + // Use a buffer for efficient string concatenation + var buffer bytes.Buffer + + if op&Create == Create { + buffer.WriteString("|CREATE") + } + if op&Remove == Remove { + buffer.WriteString("|REMOVE") + } + if op&Write == Write { + buffer.WriteString("|WRITE") + } + if op&Rename == Rename { + buffer.WriteString("|RENAME") + } + if op&Chmod == Chmod { + buffer.WriteString("|CHMOD") + } + if buffer.Len() == 0 { + return "" + } + return buffer.String()[1:] // Strip leading pipe +} + +// String returns a string representation of the event in the form +// "file: REMOVE|WRITE|..." +func (e Event) String() string { + return fmt.Sprintf("%q: %s", e.Name, e.Op.String()) +} + +// Common errors that can be reported by a watcher +var ErrEventOverflow = errors.New("fsnotify queue overflow") diff --git a/vendor/github.com/fsnotify/fsnotify/inotify.go b/vendor/github.com/fsnotify/fsnotify/inotify.go new file mode 100644 index 000000000..d9fd1b88a --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/inotify.go @@ -0,0 +1,337 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux + +package fsnotify + +import ( + "errors" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "sync" + "unsafe" + + "golang.org/x/sys/unix" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error + mu sync.Mutex // Map access + fd int + poller *fdPoller + watches map[string]*watch // Map of inotify watches (key: path) + paths map[int]string // Map of watched paths (key: watch descriptor) + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + doneResp chan struct{} // Channel to respond to Close +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + // Create inotify fd + fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC) + if fd == -1 { + return nil, errno + } + // Create epoll + poller, err := newFdPoller(fd) + if err != nil { + unix.Close(fd) + return nil, err + } + w := &Watcher{ + fd: fd, + poller: poller, + watches: make(map[string]*watch), + paths: make(map[int]string), + Events: make(chan Event), + Errors: make(chan error), + done: make(chan struct{}), + doneResp: make(chan struct{}), + } + + go w.readEvents() + return w, nil +} + +func (w *Watcher) isClosed() bool { + select { + case <-w.done: + return true + default: + return false + } +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + if w.isClosed() { + return nil + } + + // Send 'close' signal to goroutine, and set the Watcher to closed. + close(w.done) + + // Wake up goroutine + w.poller.wake() + + // Wait for goroutine to close + <-w.doneResp + + return nil +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + name = filepath.Clean(name) + if w.isClosed() { + return errors.New("inotify instance already closed") + } + + const agnosticEvents = unix.IN_MOVED_TO | unix.IN_MOVED_FROM | + unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY | + unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF + + var flags uint32 = agnosticEvents + + w.mu.Lock() + defer w.mu.Unlock() + watchEntry := w.watches[name] + if watchEntry != nil { + flags |= watchEntry.flags | unix.IN_MASK_ADD + } + wd, errno := unix.InotifyAddWatch(w.fd, name, flags) + if wd == -1 { + return errno + } + + if watchEntry == nil { + w.watches[name] = &watch{wd: uint32(wd), flags: flags} + w.paths[wd] = name + } else { + watchEntry.wd = uint32(wd) + watchEntry.flags = flags + } + + return nil +} + +// Remove stops watching the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + name = filepath.Clean(name) + + // Fetch the watch. + w.mu.Lock() + defer w.mu.Unlock() + watch, ok := w.watches[name] + + // Remove it from inotify. + if !ok { + return fmt.Errorf("can't remove non-existent inotify watch for: %s", name) + } + + // We successfully removed the watch if InotifyRmWatch doesn't return an + // error, we need to clean up our internal state to ensure it matches + // inotify's kernel state. + delete(w.paths, int(watch.wd)) + delete(w.watches, name) + + // inotify_rm_watch will return EINVAL if the file has been deleted; + // the inotify will already have been removed. + // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously + // by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE + // so that EINVAL means that the wd is being rm_watch()ed or its file removed + // by another thread and we have not received IN_IGNORE event. + success, errno := unix.InotifyRmWatch(w.fd, watch.wd) + if success == -1 { + // TODO: Perhaps it's not helpful to return an error here in every case. + // the only two possible errors are: + // EBADF, which happens when w.fd is not a valid file descriptor of any kind. + // EINVAL, which is when fd is not an inotify descriptor or wd is not a valid watch descriptor. + // Watch descriptors are invalidated when they are removed explicitly or implicitly; + // explicitly by inotify_rm_watch, implicitly when the file they are watching is deleted. + return errno + } + + return nil +} + +type watch struct { + wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) + flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) +} + +// readEvents reads from the inotify file descriptor, converts the +// received events into Event objects and sends them via the Events channel +func (w *Watcher) readEvents() { + var ( + buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events + n int // Number of bytes read with read() + errno error // Syscall errno + ok bool // For poller.wait + ) + + defer close(w.doneResp) + defer close(w.Errors) + defer close(w.Events) + defer unix.Close(w.fd) + defer w.poller.close() + + for { + // See if we have been closed. + if w.isClosed() { + return + } + + ok, errno = w.poller.wait() + if errno != nil { + select { + case w.Errors <- errno: + case <-w.done: + return + } + continue + } + + if !ok { + continue + } + + n, errno = unix.Read(w.fd, buf[:]) + // If a signal interrupted execution, see if we've been asked to close, and try again. + // http://man7.org/linux/man-pages/man7/signal.7.html : + // "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable" + if errno == unix.EINTR { + continue + } + + // unix.Read might have been woken up by Close. If so, we're done. + if w.isClosed() { + return + } + + if n < unix.SizeofInotifyEvent { + var err error + if n == 0 { + // If EOF is received. This should really never happen. + err = io.EOF + } else if n < 0 { + // If an error occurred while reading. + err = errno + } else { + // Read was too short. + err = errors.New("notify: short read in readEvents()") + } + select { + case w.Errors <- err: + case <-w.done: + return + } + continue + } + + var offset uint32 + // We don't know how many events we just read into the buffer + // While the offset points to at least one whole event... + for offset <= uint32(n-unix.SizeofInotifyEvent) { + // Point "raw" to the event in the buffer + raw := (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset])) + + mask := uint32(raw.Mask) + nameLen := uint32(raw.Len) + + if mask&unix.IN_Q_OVERFLOW != 0 { + select { + case w.Errors <- ErrEventOverflow: + case <-w.done: + return + } + } + + // If the event happened to the watched directory or the watched file, the kernel + // doesn't append the filename to the event, but we would like to always fill the + // the "Name" field with a valid filename. We retrieve the path of the watch from + // the "paths" map. + w.mu.Lock() + name, ok := w.paths[int(raw.Wd)] + // IN_DELETE_SELF occurs when the file/directory being watched is removed. + // This is a sign to clean up the maps, otherwise we are no longer in sync + // with the inotify kernel state which has already deleted the watch + // automatically. + if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { + delete(w.paths, int(raw.Wd)) + delete(w.watches, name) + } + w.mu.Unlock() + + if nameLen > 0 { + // Point "bytes" at the first byte of the filename + bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent])) + // The filename is padded with NULL bytes. TrimRight() gets rid of those. + name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") + } + + event := newEvent(name, mask) + + // Send the events that are not ignored on the events channel + if !event.ignoreLinux(mask) { + select { + case w.Events <- event: + case <-w.done: + return + } + } + + // Move to the next event in the buffer + offset += unix.SizeofInotifyEvent + nameLen + } + } +} + +// Certain types of events can be "ignored" and not sent over the Events +// channel. Such as events marked ignore by the kernel, or MODIFY events +// against files that do not exist. +func (e *Event) ignoreLinux(mask uint32) bool { + // Ignore anything the inotify API says to ignore + if mask&unix.IN_IGNORED == unix.IN_IGNORED { + return true + } + + // If the event is not a DELETE or RENAME, the file must exist. + // Otherwise the event is ignored. + // *Note*: this was put in place because it was seen that a MODIFY + // event was sent after the DELETE. This ignores that MODIFY and + // assumes a DELETE will come or has come if the file doesn't exist. + if !(e.Op&Remove == Remove || e.Op&Rename == Rename) { + _, statErr := os.Lstat(e.Name) + return os.IsNotExist(statErr) + } + return false +} + +// newEvent returns an platform-independent Event based on an inotify mask. +func newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { + e.Op |= Create + } + if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE { + e.Op |= Remove + } + if mask&unix.IN_MODIFY == unix.IN_MODIFY { + e.Op |= Write + } + if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { + e.Op |= Rename + } + if mask&unix.IN_ATTRIB == unix.IN_ATTRIB { + e.Op |= Chmod + } + return e +} diff --git a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go new file mode 100644 index 000000000..cc7db4b22 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go @@ -0,0 +1,187 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux + +package fsnotify + +import ( + "errors" + + "golang.org/x/sys/unix" +) + +type fdPoller struct { + fd int // File descriptor (as returned by the inotify_init() syscall) + epfd int // Epoll file descriptor + pipe [2]int // Pipe for waking up +} + +func emptyPoller(fd int) *fdPoller { + poller := new(fdPoller) + poller.fd = fd + poller.epfd = -1 + poller.pipe[0] = -1 + poller.pipe[1] = -1 + return poller +} + +// Create a new inotify poller. +// This creates an inotify handler, and an epoll handler. +func newFdPoller(fd int) (*fdPoller, error) { + var errno error + poller := emptyPoller(fd) + defer func() { + if errno != nil { + poller.close() + } + }() + poller.fd = fd + + // Create epoll fd + poller.epfd, errno = unix.EpollCreate1(0) + if poller.epfd == -1 { + return nil, errno + } + // Create pipe; pipe[0] is the read end, pipe[1] the write end. + errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK) + if errno != nil { + return nil, errno + } + + // Register inotify fd with epoll + event := unix.EpollEvent{ + Fd: int32(poller.fd), + Events: unix.EPOLLIN, + } + errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.fd, &event) + if errno != nil { + return nil, errno + } + + // Register pipe fd with epoll + event = unix.EpollEvent{ + Fd: int32(poller.pipe[0]), + Events: unix.EPOLLIN, + } + errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.pipe[0], &event) + if errno != nil { + return nil, errno + } + + return poller, nil +} + +// Wait using epoll. +// Returns true if something is ready to be read, +// false if there is not. +func (poller *fdPoller) wait() (bool, error) { + // 3 possible events per fd, and 2 fds, makes a maximum of 6 events. + // I don't know whether epoll_wait returns the number of events returned, + // or the total number of events ready. + // I decided to catch both by making the buffer one larger than the maximum. + events := make([]unix.EpollEvent, 7) + for { + n, errno := unix.EpollWait(poller.epfd, events, -1) + if n == -1 { + if errno == unix.EINTR { + continue + } + return false, errno + } + if n == 0 { + // If there are no events, try again. + continue + } + if n > 6 { + // This should never happen. More events were returned than should be possible. + return false, errors.New("epoll_wait returned more events than I know what to do with") + } + ready := events[:n] + epollhup := false + epollerr := false + epollin := false + for _, event := range ready { + if event.Fd == int32(poller.fd) { + if event.Events&unix.EPOLLHUP != 0 { + // This should not happen, but if it does, treat it as a wakeup. + epollhup = true + } + if event.Events&unix.EPOLLERR != 0 { + // If an error is waiting on the file descriptor, we should pretend + // something is ready to read, and let unix.Read pick up the error. + epollerr = true + } + if event.Events&unix.EPOLLIN != 0 { + // There is data to read. + epollin = true + } + } + if event.Fd == int32(poller.pipe[0]) { + if event.Events&unix.EPOLLHUP != 0 { + // Write pipe descriptor was closed, by us. This means we're closing down the + // watcher, and we should wake up. + } + if event.Events&unix.EPOLLERR != 0 { + // If an error is waiting on the pipe file descriptor. + // This is an absolute mystery, and should never ever happen. + return false, errors.New("Error on the pipe descriptor.") + } + if event.Events&unix.EPOLLIN != 0 { + // This is a regular wakeup, so we have to clear the buffer. + err := poller.clearWake() + if err != nil { + return false, err + } + } + } + } + + if epollhup || epollerr || epollin { + return true, nil + } + return false, nil + } +} + +// Close the write end of the poller. +func (poller *fdPoller) wake() error { + buf := make([]byte, 1) + n, errno := unix.Write(poller.pipe[1], buf) + if n == -1 { + if errno == unix.EAGAIN { + // Buffer is full, poller will wake. + return nil + } + return errno + } + return nil +} + +func (poller *fdPoller) clearWake() error { + // You have to be woken up a LOT in order to get to 100! + buf := make([]byte, 100) + n, errno := unix.Read(poller.pipe[0], buf) + if n == -1 { + if errno == unix.EAGAIN { + // Buffer is empty, someone else cleared our wake. + return nil + } + return errno + } + return nil +} + +// Close all poller file descriptors, but not the one passed to it. +func (poller *fdPoller) close() { + if poller.pipe[1] != -1 { + unix.Close(poller.pipe[1]) + } + if poller.pipe[0] != -1 { + unix.Close(poller.pipe[0]) + } + if poller.epfd != -1 { + unix.Close(poller.epfd) + } +} diff --git a/vendor/github.com/fsnotify/fsnotify/kqueue.go b/vendor/github.com/fsnotify/fsnotify/kqueue.go new file mode 100644 index 000000000..86e76a3d6 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/kqueue.go @@ -0,0 +1,521 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build freebsd openbsd netbsd dragonfly darwin + +package fsnotify + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "sync" + "time" + + "golang.org/x/sys/unix" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + + kq int // File descriptor (as returned by the kqueue() syscall). + + mu sync.Mutex // Protects access to watcher data + watches map[string]int // Map of watched file descriptors (key: path). + externalWatches map[string]bool // Map of watches added by user of the library. + dirFlags map[string]uint32 // Map of watched directories to fflags used in kqueue. + paths map[int]pathInfo // Map file descriptors to path names for processing kqueue events. + fileExists map[string]bool // Keep track of if we know this file exists (to stop duplicate create events). + isClosed bool // Set to true when Close() is first called +} + +type pathInfo struct { + name string + isDir bool +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + kq, err := kqueue() + if err != nil { + return nil, err + } + + w := &Watcher{ + kq: kq, + watches: make(map[string]int), + dirFlags: make(map[string]uint32), + paths: make(map[int]pathInfo), + fileExists: make(map[string]bool), + externalWatches: make(map[string]bool), + Events: make(chan Event), + Errors: make(chan error), + done: make(chan struct{}), + } + + go w.readEvents() + return w, nil +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return nil + } + w.isClosed = true + + // copy paths to remove while locked + var pathsToRemove = make([]string, 0, len(w.watches)) + for name := range w.watches { + pathsToRemove = append(pathsToRemove, name) + } + w.mu.Unlock() + // unlock before calling Remove, which also locks + + for _, name := range pathsToRemove { + w.Remove(name) + } + + // send a "quit" message to the reader goroutine + close(w.done) + + return nil +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + w.mu.Lock() + w.externalWatches[name] = true + w.mu.Unlock() + _, err := w.addWatch(name, noteAllEvents) + return err +} + +// Remove stops watching the the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + name = filepath.Clean(name) + w.mu.Lock() + watchfd, ok := w.watches[name] + w.mu.Unlock() + if !ok { + return fmt.Errorf("can't remove non-existent kevent watch for: %s", name) + } + + const registerRemove = unix.EV_DELETE + if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil { + return err + } + + unix.Close(watchfd) + + w.mu.Lock() + isDir := w.paths[watchfd].isDir + delete(w.watches, name) + delete(w.paths, watchfd) + delete(w.dirFlags, name) + w.mu.Unlock() + + // Find all watched paths that are in this directory that are not external. + if isDir { + var pathsToRemove []string + w.mu.Lock() + for _, path := range w.paths { + wdir, _ := filepath.Split(path.name) + if filepath.Clean(wdir) == name { + if !w.externalWatches[path.name] { + pathsToRemove = append(pathsToRemove, path.name) + } + } + } + w.mu.Unlock() + for _, name := range pathsToRemove { + // Since these are internal, not much sense in propagating error + // to the user, as that will just confuse them with an error about + // a path they did not explicitly watch themselves. + w.Remove(name) + } + } + + return nil +} + +// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) +const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME + +// keventWaitTime to block on each read from kevent +var keventWaitTime = durationToTimespec(100 * time.Millisecond) + +// addWatch adds name to the watched file set. +// The flags are interpreted as described in kevent(2). +// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. +func (w *Watcher) addWatch(name string, flags uint32) (string, error) { + var isDir bool + // Make ./name and name equivalent + name = filepath.Clean(name) + + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return "", errors.New("kevent instance already closed") + } + watchfd, alreadyWatching := w.watches[name] + // We already have a watch, but we can still override flags. + if alreadyWatching { + isDir = w.paths[watchfd].isDir + } + w.mu.Unlock() + + if !alreadyWatching { + fi, err := os.Lstat(name) + if err != nil { + return "", err + } + + // Don't watch sockets. + if fi.Mode()&os.ModeSocket == os.ModeSocket { + return "", nil + } + + // Don't watch named pipes. + if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe { + return "", nil + } + + // Follow Symlinks + // Unfortunately, Linux can add bogus symlinks to watch list without + // issue, and Windows can't do symlinks period (AFAIK). To maintain + // consistency, we will act like everything is fine. There will simply + // be no file events for broken symlinks. + // Hence the returns of nil on errors. + if fi.Mode()&os.ModeSymlink == os.ModeSymlink { + name, err = filepath.EvalSymlinks(name) + if err != nil { + return "", nil + } + + w.mu.Lock() + _, alreadyWatching = w.watches[name] + w.mu.Unlock() + + if alreadyWatching { + return name, nil + } + + fi, err = os.Lstat(name) + if err != nil { + return "", nil + } + } + + watchfd, err = unix.Open(name, openMode, 0700) + if watchfd == -1 { + return "", err + } + + isDir = fi.IsDir() + } + + const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE + if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil { + unix.Close(watchfd) + return "", err + } + + if !alreadyWatching { + w.mu.Lock() + w.watches[name] = watchfd + w.paths[watchfd] = pathInfo{name: name, isDir: isDir} + w.mu.Unlock() + } + + if isDir { + // Watch the directory if it has not been watched before, + // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) + w.mu.Lock() + + watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && + (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE) + // Store flags so this watch can be updated later + w.dirFlags[name] = flags + w.mu.Unlock() + + if watchDir { + if err := w.watchDirectoryFiles(name); err != nil { + return "", err + } + } + } + return name, nil +} + +// readEvents reads from kqueue and converts the received kevents into +// Event values that it sends down the Events channel. +func (w *Watcher) readEvents() { + eventBuffer := make([]unix.Kevent_t, 10) + +loop: + for { + // See if there is a message on the "done" channel + select { + case <-w.done: + break loop + default: + } + + // Get new events + kevents, err := read(w.kq, eventBuffer, &keventWaitTime) + // EINTR is okay, the syscall was interrupted before timeout expired. + if err != nil && err != unix.EINTR { + select { + case w.Errors <- err: + case <-w.done: + break loop + } + continue + } + + // Flush the events we received to the Events channel + for len(kevents) > 0 { + kevent := &kevents[0] + watchfd := int(kevent.Ident) + mask := uint32(kevent.Fflags) + w.mu.Lock() + path := w.paths[watchfd] + w.mu.Unlock() + event := newEvent(path.name, mask) + + if path.isDir && !(event.Op&Remove == Remove) { + // Double check to make sure the directory exists. This can happen when + // we do a rm -fr on a recursively watched folders and we receive a + // modification event first but the folder has been deleted and later + // receive the delete event + if _, err := os.Lstat(event.Name); os.IsNotExist(err) { + // mark is as delete event + event.Op |= Remove + } + } + + if event.Op&Rename == Rename || event.Op&Remove == Remove { + w.Remove(event.Name) + w.mu.Lock() + delete(w.fileExists, event.Name) + w.mu.Unlock() + } + + if path.isDir && event.Op&Write == Write && !(event.Op&Remove == Remove) { + w.sendDirectoryChangeEvents(event.Name) + } else { + // Send the event on the Events channel. + select { + case w.Events <- event: + case <-w.done: + break loop + } + } + + if event.Op&Remove == Remove { + // Look for a file that may have overwritten this. + // For example, mv f1 f2 will delete f2, then create f2. + if path.isDir { + fileDir := filepath.Clean(event.Name) + w.mu.Lock() + _, found := w.watches[fileDir] + w.mu.Unlock() + if found { + // make sure the directory exists before we watch for changes. When we + // do a recursive watch and perform rm -fr, the parent directory might + // have gone missing, ignore the missing directory and let the + // upcoming delete event remove the watch from the parent directory. + if _, err := os.Lstat(fileDir); err == nil { + w.sendDirectoryChangeEvents(fileDir) + } + } + } else { + filePath := filepath.Clean(event.Name) + if fileInfo, err := os.Lstat(filePath); err == nil { + w.sendFileCreatedEventIfNew(filePath, fileInfo) + } + } + } + + // Move to next event + kevents = kevents[1:] + } + } + + // cleanup + err := unix.Close(w.kq) + if err != nil { + // only way the previous loop breaks is if w.done was closed so we need to async send to w.Errors. + select { + case w.Errors <- err: + default: + } + } + close(w.Events) + close(w.Errors) +} + +// newEvent returns an platform-independent Event based on kqueue Fflags. +func newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&unix.NOTE_DELETE == unix.NOTE_DELETE { + e.Op |= Remove + } + if mask&unix.NOTE_WRITE == unix.NOTE_WRITE { + e.Op |= Write + } + if mask&unix.NOTE_RENAME == unix.NOTE_RENAME { + e.Op |= Rename + } + if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB { + e.Op |= Chmod + } + return e +} + +func newCreateEvent(name string) Event { + return Event{Name: name, Op: Create} +} + +// watchDirectoryFiles to mimic inotify when adding a watch on a directory +func (w *Watcher) watchDirectoryFiles(dirPath string) error { + // Get all files + files, err := ioutil.ReadDir(dirPath) + if err != nil { + return err + } + + for _, fileInfo := range files { + filePath := filepath.Join(dirPath, fileInfo.Name()) + filePath, err = w.internalWatch(filePath, fileInfo) + if err != nil { + return err + } + + w.mu.Lock() + w.fileExists[filePath] = true + w.mu.Unlock() + } + + return nil +} + +// sendDirectoryEvents searches the directory for newly created files +// and sends them over the event channel. This functionality is to have +// the BSD version of fsnotify match Linux inotify which provides a +// create event for files created in a watched directory. +func (w *Watcher) sendDirectoryChangeEvents(dirPath string) { + // Get all files + files, err := ioutil.ReadDir(dirPath) + if err != nil { + select { + case w.Errors <- err: + case <-w.done: + return + } + } + + // Search for new files + for _, fileInfo := range files { + filePath := filepath.Join(dirPath, fileInfo.Name()) + err := w.sendFileCreatedEventIfNew(filePath, fileInfo) + + if err != nil { + return + } + } +} + +// sendFileCreatedEvent sends a create event if the file isn't already being tracked. +func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) { + w.mu.Lock() + _, doesExist := w.fileExists[filePath] + w.mu.Unlock() + if !doesExist { + // Send create event + select { + case w.Events <- newCreateEvent(filePath): + case <-w.done: + return + } + } + + // like watchDirectoryFiles (but without doing another ReadDir) + filePath, err = w.internalWatch(filePath, fileInfo) + if err != nil { + return err + } + + w.mu.Lock() + w.fileExists[filePath] = true + w.mu.Unlock() + + return nil +} + +func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) { + if fileInfo.IsDir() { + // mimic Linux providing delete events for subdirectories + // but preserve the flags used if currently watching subdirectory + w.mu.Lock() + flags := w.dirFlags[name] + w.mu.Unlock() + + flags |= unix.NOTE_DELETE | unix.NOTE_RENAME + return w.addWatch(name, flags) + } + + // watch file to mimic Linux inotify + return w.addWatch(name, noteAllEvents) +} + +// kqueue creates a new kernel event queue and returns a descriptor. +func kqueue() (kq int, err error) { + kq, err = unix.Kqueue() + if kq == -1 { + return kq, err + } + return kq, nil +} + +// register events with the queue +func register(kq int, fds []int, flags int, fflags uint32) error { + changes := make([]unix.Kevent_t, len(fds)) + + for i, fd := range fds { + // SetKevent converts int to the platform-specific types: + unix.SetKevent(&changes[i], fd, unix.EVFILT_VNODE, flags) + changes[i].Fflags = fflags + } + + // register the events + success, err := unix.Kevent(kq, changes, nil, nil) + if success == -1 { + return err + } + return nil +} + +// read retrieves pending events, or waits until an event occurs. +// A timeout of nil blocks indefinitely, while 0 polls the queue. +func read(kq int, events []unix.Kevent_t, timeout *unix.Timespec) ([]unix.Kevent_t, error) { + n, err := unix.Kevent(kq, nil, events, timeout) + if err != nil { + return nil, err + } + return events[0:n], nil +} + +// durationToTimespec prepares a timeout value +func durationToTimespec(d time.Duration) unix.Timespec { + return unix.NsecToTimespec(d.Nanoseconds()) +} diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go new file mode 100644 index 000000000..7d8de1451 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go @@ -0,0 +1,11 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build freebsd openbsd netbsd dragonfly + +package fsnotify + +import "golang.org/x/sys/unix" + +const openMode = unix.O_NONBLOCK | unix.O_RDONLY diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go new file mode 100644 index 000000000..9139e1716 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go @@ -0,0 +1,12 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin + +package fsnotify + +import "golang.org/x/sys/unix" + +// note: this constant is not defined on BSD +const openMode = unix.O_EVTONLY diff --git a/vendor/github.com/fsnotify/fsnotify/windows.go b/vendor/github.com/fsnotify/fsnotify/windows.go new file mode 100644 index 000000000..09436f31d --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/windows.go @@ -0,0 +1,561 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package fsnotify + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "sync" + "syscall" + "unsafe" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error + isClosed bool // Set to true when Close() is first called + mu sync.Mutex // Map access + port syscall.Handle // Handle to completion port + watches watchMap // Map of watches (key: i-number) + input chan *input // Inputs to the reader are sent on this channel + quit chan chan<- error +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0) + if e != nil { + return nil, os.NewSyscallError("CreateIoCompletionPort", e) + } + w := &Watcher{ + port: port, + watches: make(watchMap), + input: make(chan *input, 1), + Events: make(chan Event, 50), + Errors: make(chan error), + quit: make(chan chan<- error, 1), + } + go w.readEvents() + return w, nil +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + if w.isClosed { + return nil + } + w.isClosed = true + + // Send "quit" message to the reader goroutine + ch := make(chan error) + w.quit <- ch + if err := w.wakeupReader(); err != nil { + return err + } + return <-ch +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + if w.isClosed { + return errors.New("watcher already closed") + } + in := &input{ + op: opAddWatch, + path: filepath.Clean(name), + flags: sysFSALLEVENTS, + reply: make(chan error), + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +// Remove stops watching the the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + in := &input{ + op: opRemoveWatch, + path: filepath.Clean(name), + reply: make(chan error), + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +const ( + // Options for AddWatch + sysFSONESHOT = 0x80000000 + sysFSONLYDIR = 0x1000000 + + // Events + sysFSACCESS = 0x1 + sysFSALLEVENTS = 0xfff + sysFSATTRIB = 0x4 + sysFSCLOSE = 0x18 + sysFSCREATE = 0x100 + sysFSDELETE = 0x200 + sysFSDELETESELF = 0x400 + sysFSMODIFY = 0x2 + sysFSMOVE = 0xc0 + sysFSMOVEDFROM = 0x40 + sysFSMOVEDTO = 0x80 + sysFSMOVESELF = 0x800 + + // Special events + sysFSIGNORED = 0x8000 + sysFSQOVERFLOW = 0x4000 +) + +func newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO { + e.Op |= Create + } + if mask&sysFSDELETE == sysFSDELETE || mask&sysFSDELETESELF == sysFSDELETESELF { + e.Op |= Remove + } + if mask&sysFSMODIFY == sysFSMODIFY { + e.Op |= Write + } + if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM { + e.Op |= Rename + } + if mask&sysFSATTRIB == sysFSATTRIB { + e.Op |= Chmod + } + return e +} + +const ( + opAddWatch = iota + opRemoveWatch +) + +const ( + provisional uint64 = 1 << (32 + iota) +) + +type input struct { + op int + path string + flags uint32 + reply chan error +} + +type inode struct { + handle syscall.Handle + volume uint32 + index uint64 +} + +type watch struct { + ov syscall.Overlapped + ino *inode // i-number + path string // Directory path + mask uint64 // Directory itself is being watched with these notify flags + names map[string]uint64 // Map of names being watched and their notify flags + rename string // Remembers the old name while renaming a file + buf [4096]byte +} + +type indexMap map[uint64]*watch +type watchMap map[uint32]indexMap + +func (w *Watcher) wakeupReader() error { + e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil) + if e != nil { + return os.NewSyscallError("PostQueuedCompletionStatus", e) + } + return nil +} + +func getDir(pathname string) (dir string, err error) { + attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname)) + if e != nil { + return "", os.NewSyscallError("GetFileAttributes", e) + } + if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { + dir = pathname + } else { + dir, _ = filepath.Split(pathname) + dir = filepath.Clean(dir) + } + return +} + +func getIno(path string) (ino *inode, err error) { + h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(path), + syscall.FILE_LIST_DIRECTORY, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + nil, syscall.OPEN_EXISTING, + syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0) + if e != nil { + return nil, os.NewSyscallError("CreateFile", e) + } + var fi syscall.ByHandleFileInformation + if e = syscall.GetFileInformationByHandle(h, &fi); e != nil { + syscall.CloseHandle(h) + return nil, os.NewSyscallError("GetFileInformationByHandle", e) + } + ino = &inode{ + handle: h, + volume: fi.VolumeSerialNumber, + index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow), + } + return ino, nil +} + +// Must run within the I/O thread. +func (m watchMap) get(ino *inode) *watch { + if i := m[ino.volume]; i != nil { + return i[ino.index] + } + return nil +} + +// Must run within the I/O thread. +func (m watchMap) set(ino *inode, watch *watch) { + i := m[ino.volume] + if i == nil { + i = make(indexMap) + m[ino.volume] = i + } + i[ino.index] = watch +} + +// Must run within the I/O thread. +func (w *Watcher) addWatch(pathname string, flags uint64) error { + dir, err := getDir(pathname) + if err != nil { + return err + } + if flags&sysFSONLYDIR != 0 && pathname != dir { + return nil + } + ino, err := getIno(dir) + if err != nil { + return err + } + w.mu.Lock() + watchEntry := w.watches.get(ino) + w.mu.Unlock() + if watchEntry == nil { + if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil { + syscall.CloseHandle(ino.handle) + return os.NewSyscallError("CreateIoCompletionPort", e) + } + watchEntry = &watch{ + ino: ino, + path: dir, + names: make(map[string]uint64), + } + w.mu.Lock() + w.watches.set(ino, watchEntry) + w.mu.Unlock() + flags |= provisional + } else { + syscall.CloseHandle(ino.handle) + } + if pathname == dir { + watchEntry.mask |= flags + } else { + watchEntry.names[filepath.Base(pathname)] |= flags + } + if err = w.startRead(watchEntry); err != nil { + return err + } + if pathname == dir { + watchEntry.mask &= ^provisional + } else { + watchEntry.names[filepath.Base(pathname)] &= ^provisional + } + return nil +} + +// Must run within the I/O thread. +func (w *Watcher) remWatch(pathname string) error { + dir, err := getDir(pathname) + if err != nil { + return err + } + ino, err := getIno(dir) + if err != nil { + return err + } + w.mu.Lock() + watch := w.watches.get(ino) + w.mu.Unlock() + if watch == nil { + return fmt.Errorf("can't remove non-existent watch for: %s", pathname) + } + if pathname == dir { + w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + watch.mask = 0 + } else { + name := filepath.Base(pathname) + w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED) + delete(watch.names, name) + } + return w.startRead(watch) +} + +// Must run within the I/O thread. +func (w *Watcher) deleteWatch(watch *watch) { + for name, mask := range watch.names { + if mask&provisional == 0 { + w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED) + } + delete(watch.names, name) + } + if watch.mask != 0 { + if watch.mask&provisional == 0 { + w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + } + watch.mask = 0 + } +} + +// Must run within the I/O thread. +func (w *Watcher) startRead(watch *watch) error { + if e := syscall.CancelIo(watch.ino.handle); e != nil { + w.Errors <- os.NewSyscallError("CancelIo", e) + w.deleteWatch(watch) + } + mask := toWindowsFlags(watch.mask) + for _, m := range watch.names { + mask |= toWindowsFlags(m) + } + if mask == 0 { + if e := syscall.CloseHandle(watch.ino.handle); e != nil { + w.Errors <- os.NewSyscallError("CloseHandle", e) + } + w.mu.Lock() + delete(w.watches[watch.ino.volume], watch.ino.index) + w.mu.Unlock() + return nil + } + e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], + uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) + if e != nil { + err := os.NewSyscallError("ReadDirectoryChanges", e) + if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { + // Watched directory was probably removed + if w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) { + if watch.mask&sysFSONESHOT != 0 { + watch.mask = 0 + } + } + err = nil + } + w.deleteWatch(watch) + w.startRead(watch) + return err + } + return nil +} + +// readEvents reads from the I/O completion port, converts the +// received events into Event objects and sends them via the Events channel. +// Entry point to the I/O thread. +func (w *Watcher) readEvents() { + var ( + n, key uint32 + ov *syscall.Overlapped + ) + runtime.LockOSThread() + + for { + e := syscall.GetQueuedCompletionStatus(w.port, &n, &key, &ov, syscall.INFINITE) + watch := (*watch)(unsafe.Pointer(ov)) + + if watch == nil { + select { + case ch := <-w.quit: + w.mu.Lock() + var indexes []indexMap + for _, index := range w.watches { + indexes = append(indexes, index) + } + w.mu.Unlock() + for _, index := range indexes { + for _, watch := range index { + w.deleteWatch(watch) + w.startRead(watch) + } + } + var err error + if e := syscall.CloseHandle(w.port); e != nil { + err = os.NewSyscallError("CloseHandle", e) + } + close(w.Events) + close(w.Errors) + ch <- err + return + case in := <-w.input: + switch in.op { + case opAddWatch: + in.reply <- w.addWatch(in.path, uint64(in.flags)) + case opRemoveWatch: + in.reply <- w.remWatch(in.path) + } + default: + } + continue + } + + switch e { + case syscall.ERROR_MORE_DATA: + if watch == nil { + w.Errors <- errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer") + } else { + // The i/o succeeded but the buffer is full. + // In theory we should be building up a full packet. + // In practice we can get away with just carrying on. + n = uint32(unsafe.Sizeof(watch.buf)) + } + case syscall.ERROR_ACCESS_DENIED: + // Watched directory was probably removed + w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) + w.deleteWatch(watch) + w.startRead(watch) + continue + case syscall.ERROR_OPERATION_ABORTED: + // CancelIo was called on this handle + continue + default: + w.Errors <- os.NewSyscallError("GetQueuedCompletionPort", e) + continue + case nil: + } + + var offset uint32 + for { + if n == 0 { + w.Events <- newEvent("", sysFSQOVERFLOW) + w.Errors <- errors.New("short read in readEvents()") + break + } + + // Point "raw" to the event in the buffer + raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset])) + buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName)) + name := syscall.UTF16ToString(buf[:raw.FileNameLength/2]) + fullname := filepath.Join(watch.path, name) + + var mask uint64 + switch raw.Action { + case syscall.FILE_ACTION_REMOVED: + mask = sysFSDELETESELF + case syscall.FILE_ACTION_MODIFIED: + mask = sysFSMODIFY + case syscall.FILE_ACTION_RENAMED_OLD_NAME: + watch.rename = name + case syscall.FILE_ACTION_RENAMED_NEW_NAME: + if watch.names[watch.rename] != 0 { + watch.names[name] |= watch.names[watch.rename] + delete(watch.names, watch.rename) + mask = sysFSMOVESELF + } + } + + sendNameEvent := func() { + if w.sendEvent(fullname, watch.names[name]&mask) { + if watch.names[name]&sysFSONESHOT != 0 { + delete(watch.names, name) + } + } + } + if raw.Action != syscall.FILE_ACTION_RENAMED_NEW_NAME { + sendNameEvent() + } + if raw.Action == syscall.FILE_ACTION_REMOVED { + w.sendEvent(fullname, watch.names[name]&sysFSIGNORED) + delete(watch.names, name) + } + if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) { + if watch.mask&sysFSONESHOT != 0 { + watch.mask = 0 + } + } + if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME { + fullname = filepath.Join(watch.path, watch.rename) + sendNameEvent() + } + + // Move to the next event in the buffer + if raw.NextEntryOffset == 0 { + break + } + offset += raw.NextEntryOffset + + // Error! + if offset >= n { + w.Errors <- errors.New("Windows system assumed buffer larger than it is, events have likely been missed.") + break + } + } + + if err := w.startRead(watch); err != nil { + w.Errors <- err + } + } +} + +func (w *Watcher) sendEvent(name string, mask uint64) bool { + if mask == 0 { + return false + } + event := newEvent(name, uint32(mask)) + select { + case ch := <-w.quit: + w.quit <- ch + case w.Events <- event: + } + return true +} + +func toWindowsFlags(mask uint64) uint32 { + var m uint32 + if mask&sysFSACCESS != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS + } + if mask&sysFSMODIFY != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE + } + if mask&sysFSATTRIB != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES + } + if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME + } + return m +} + +func toFSnotifyFlags(action uint32) uint64 { + switch action { + case syscall.FILE_ACTION_ADDED: + return sysFSCREATE + case syscall.FILE_ACTION_REMOVED: + return sysFSDELETE + case syscall.FILE_ACTION_MODIFIED: + return sysFSMODIFY + case syscall.FILE_ACTION_RENAMED_OLD_NAME: + return sysFSMOVEDFROM + case syscall.FILE_ACTION_RENAMED_NEW_NAME: + return sysFSMOVEDTO + } + return 0 +} diff --git a/vendor/github.com/go-critic/go-critic/LICENSE b/vendor/github.com/go-critic/go-critic/LICENSE new file mode 100644 index 000000000..b944b4bbd --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2018-2019 Alekseev Artem +Copyright (c) 2018-2019 Ravil Bikbulatov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-critic/go-critic/checkers/appendAssign_checker.go b/vendor/github.com/go-critic/go-critic/checkers/appendAssign_checker.go new file mode 100644 index 000000000..47d12f014 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/appendAssign_checker.go @@ -0,0 +1,102 @@ +package checkers + +import ( + "go/ast" + "go/token" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/astp" + "golang.org/x/tools/go/ast/astutil" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "appendAssign" + info.Tags = []string{"diagnostic"} + info.Summary = "Detects suspicious append result assignments" + info.Before = ` +p.positives = append(p.negatives, x) +p.negatives = append(p.negatives, y)` + info.After = ` +p.positives = append(p.positives, x) +p.negatives = append(p.negatives, y)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&appendAssignChecker{ctx: ctx}) + }) +} + +type appendAssignChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *appendAssignChecker) VisitStmt(stmt ast.Stmt) { + assign, ok := stmt.(*ast.AssignStmt) + if !ok || assign.Tok != token.ASSIGN || len(assign.Lhs) != len(assign.Rhs) { + return + } + for i, rhs := range assign.Rhs { + call, ok := rhs.(*ast.CallExpr) + if !ok || qualifiedName(call.Fun) != "append" { + continue + } + c.checkAppend(assign.Lhs[i], call) + } +} + +func (c *appendAssignChecker) checkAppend(x ast.Expr, call *ast.CallExpr) { + if call.Ellipsis != token.NoPos { + // Try to detect `xs = append(ys, xs...)` idiom. + for _, arg := range call.Args[1:] { + y := arg + if arg, ok := arg.(*ast.SliceExpr); ok { + y = arg.X + } + if astequal.Expr(x, y) { + return + } + } + } + + switch x := x.(type) { + case *ast.Ident: + if x.Name == "_" { + return // Don't check assignments to blank ident + } + case *ast.IndexExpr: + if !astp.IsIndexExpr(call.Args[0]) { + // Most likely `m[k] = append(x, ...)` + // pattern, where x was retrieved by m[k] before. + // + // TODO: it's possible to record such map/slice reads + // and check whether it was done before this call. + // But for now, treat it like x belongs to m[k]. + return + } + } + + switch y := call.Args[0].(type) { + case *ast.SliceExpr: + if _, ok := c.ctx.TypesInfo.TypeOf(y.X).(*types.Array); ok { + // Arrays are frequently used as scratch storages. + return + } + c.matchSlices(call, x, y.X) + case *ast.IndexExpr, *ast.Ident, *ast.SelectorExpr: + c.matchSlices(call, x, y) + } +} + +func (c *appendAssignChecker) matchSlices(cause ast.Node, x, y ast.Expr) { + if !astequal.Expr(x, astutil.Unparen(y)) { + c.warn(cause) + } +} + +func (c *appendAssignChecker) warn(cause ast.Node) { + c.ctx.Warn(cause, "append result not assigned to the same slice") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go b/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go new file mode 100644 index 000000000..63f5d9fea --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go @@ -0,0 +1,102 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astequal" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "appendCombine" + info.Tags = []string{"performance"} + info.Summary = "Detects `append` chains to the same slice that can be done in a single `append` call" + info.Before = ` +xs = append(xs, 1) +xs = append(xs, 2)` + info.After = `xs = append(xs, 1, 2)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmtList(&appendCombineChecker{ctx: ctx}) + }) +} + +type appendCombineChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *appendCombineChecker) VisitStmtList(list []ast.Stmt) { + var cause ast.Node // First append + var slice ast.Expr // Slice being appended to + chain := 0 // How much appends in a row we've seen + + // Break the chain. + // If enough appends are in chain, print warning. + flush := func() { + if chain > 1 { + c.warn(cause, chain) + } + chain = 0 + slice = nil + } + + for _, stmt := range list { + call := c.matchAppend(stmt, slice) + if call == nil { + flush() + continue + } + + if chain == 0 { + // First append in a chain. + chain = 1 + slice = call.Args[0] + cause = stmt + } else { + chain++ + } + } + + // Required for printing chains that consist of trailing + // statements from the list. + flush() +} + +func (c *appendCombineChecker) matchAppend(stmt ast.Stmt, slice ast.Expr) *ast.CallExpr { + // Seeking for: + // slice = append(slice, xs...) + // xs are 0-N append arguments, but not variadic argument, + // because it makes append combining impossible. + + assign := astcast.ToAssignStmt(stmt) + if len(assign.Lhs) != 1 || len(assign.Rhs) != 1 { + return nil + } + + call, ok := assign.Rhs[0].(*ast.CallExpr) + { + cond := ok && + qualifiedName(call.Fun) == "append" && + call.Ellipsis == token.NoPos && + astequal.Expr(assign.Lhs[0], call.Args[0]) + if !cond { + return nil + } + } + + // Check that current append slice match previous append slice. + // Otherwise we should break the chain. + if slice == nil || astequal.Expr(slice, call.Args[0]) { + return call + } + return nil +} + +func (c *appendCombineChecker) warn(cause ast.Node, chain int) { + c.ctx.Warn(cause, "can combine chain of %d appends into one", chain) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/argOrder_checker.go b/vendor/github.com/go-critic/go-critic/checkers/argOrder_checker.go new file mode 100644 index 000000000..85a6f7c66 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/argOrder_checker.go @@ -0,0 +1,98 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astp" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "argOrder" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects suspicious arguments order" + info.Before = `strings.HasPrefix("#", userpass)` + info.After = `strings.HasPrefix(userpass, "#")` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&argOrderChecker{ctx: ctx}) + }) +} + +type argOrderChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *argOrderChecker) VisitExpr(expr ast.Expr) { + call := astcast.ToCallExpr(expr) + + // For now only handle functions of 2 args. + // TODO(Quasilyte): generalize the algorithm and add more patterns. + if len(call.Args) != 2 { + return + } + + calledExpr := astcast.ToSelectorExpr(call.Fun) + obj, ok := c.ctx.TypesInfo.ObjectOf(astcast.ToIdent(calledExpr.X)).(*types.PkgName) + if !ok || !isStdlibPkg(obj.Imported()) { + return + } + + x := call.Args[0] + y := call.Args[1] + switch calledExpr.Sel.Name { + case "HasPrefix", "HasSuffix", "Contains", "TrimPrefix", "TrimSuffix", "Split": + if obj.Name() != "bytes" && obj.Name() != "strings" { + return + } + if c.isConstLiteral(x) && !c.isConstLiteral(y) { + c.warn(call) + } + } +} + +func (c *argOrderChecker) isConstLiteral(x ast.Expr) bool { + if c.ctx.TypesInfo.Types[x].Value != nil { + return true + } + + // Also permit byte slices. + switch x := x.(type) { + case *ast.CallExpr: + // Handle `[]byte("abc")` as well. + if len(x.Args) != 1 || !astp.IsBasicLit(x.Args[0]) { + return false + } + typ, ok := c.ctx.TypesInfo.TypeOf(x.Fun).(*types.Slice) + return ok && typep.HasUint8Kind(typ.Elem()) + + case *ast.CompositeLit: + // Check if it's a const byte slice. + typ, ok := c.ctx.TypesInfo.TypeOf(x).(*types.Slice) + if !ok || !typep.HasUint8Kind(typ.Elem()) { + return false + } + for _, elt := range x.Elts { + if !astp.IsBasicLit(elt) { + return false + } + } + return true + + default: + return false + } +} + +func (c *argOrderChecker) warn(call *ast.CallExpr) { + fixed := astcopy.CallExpr(call) + fixed.Args[0], fixed.Args[1] = fixed.Args[1], fixed.Args[0] + c.ctx.Warn(call, "probably meant `%s`", fixed) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/assignOp_checker.go b/vendor/github.com/go-critic/go-critic/checkers/assignOp_checker.go new file mode 100644 index 000000000..eb3428663 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/assignOp_checker.go @@ -0,0 +1,102 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "assignOp" + info.Tags = []string{"style"} + info.Summary = "Detects assignments that can be simplified by using assignment operators" + info.Before = `x = x * 2` + info.After = `x *= 2` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&assignOpChecker{ctx: ctx}) + }) +} + +type assignOpChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *assignOpChecker) VisitStmt(stmt ast.Stmt) { + assign, ok := stmt.(*ast.AssignStmt) + cond := ok && + assign.Tok == token.ASSIGN && + len(assign.Lhs) == 1 && + len(assign.Rhs) == 1 && + typep.SideEffectFree(c.ctx.TypesInfo, assign.Lhs[0]) + if !cond { + return + } + + // TODO(quasilyte): can take commutativity into account. + expr, ok := assign.Rhs[0].(*ast.BinaryExpr) + if !ok || !astequal.Expr(assign.Lhs[0], expr.X) { + return + } + + // TODO(quasilyte): perform unparen? + switch expr.Op { + case token.MUL: + c.warn(assign, token.MUL_ASSIGN, expr.Y) + case token.QUO: + c.warn(assign, token.QUO_ASSIGN, expr.Y) + case token.REM: + c.warn(assign, token.REM_ASSIGN, expr.Y) + case token.ADD: + c.warn(assign, token.ADD_ASSIGN, expr.Y) + case token.SUB: + c.warn(assign, token.SUB_ASSIGN, expr.Y) + case token.AND: + c.warn(assign, token.AND_ASSIGN, expr.Y) + case token.OR: + c.warn(assign, token.OR_ASSIGN, expr.Y) + case token.XOR: + c.warn(assign, token.XOR_ASSIGN, expr.Y) + case token.SHL: + c.warn(assign, token.SHL_ASSIGN, expr.Y) + case token.SHR: + c.warn(assign, token.SHR_ASSIGN, expr.Y) + case token.AND_NOT: + c.warn(assign, token.AND_NOT_ASSIGN, expr.Y) + } +} + +func (c *assignOpChecker) warn(cause *ast.AssignStmt, op token.Token, rhs ast.Expr) { + suggestion := c.simplify(cause, op, rhs) + c.ctx.Warn(cause, "replace `%s` with `%s`", cause, suggestion) +} + +func (c *assignOpChecker) simplify(cause *ast.AssignStmt, op token.Token, rhs ast.Expr) ast.Stmt { + if lit, ok := rhs.(*ast.BasicLit); ok && lit.Kind == token.INT && lit.Value == "1" { + switch op { + case token.ADD_ASSIGN: + return &ast.IncDecStmt{ + X: cause.Lhs[0], + TokPos: cause.TokPos, + Tok: token.INC, + } + case token.SUB_ASSIGN: + return &ast.IncDecStmt{ + X: cause.Lhs[0], + TokPos: cause.TokPos, + Tok: token.DEC, + } + } + } + suggestion := astcopy.AssignStmt(cause) + suggestion.Tok = op + suggestion.Rhs[0] = rhs + return suggestion +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/badCall_checker.go b/vendor/github.com/go-critic/go-critic/checkers/badCall_checker.go new file mode 100644 index 000000000..150cc6904 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/badCall_checker.go @@ -0,0 +1,63 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astcopy" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "badCall" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects suspicious function calls" + info.Before = `strings.Replace(s, from, to, 0)` + info.After = `strings.Replace(s, from, to, -1)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&badCallChecker{ctx: ctx}) + }) +} + +type badCallChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *badCallChecker) VisitExpr(expr ast.Expr) { + call := astcast.ToCallExpr(expr) + if len(call.Args) == 0 { + return + } + + // TODO(quasilyte): handle methods. + + switch qualifiedName(call.Fun) { + case "strings.Replace", "bytes.Replace": + if n := astcast.ToBasicLit(call.Args[3]); n.Value == "0" { + c.warnBadArg(n, "-1") + } + case "strings.SplitN", "bytes.SplitN": + if n := astcast.ToBasicLit(call.Args[2]); n.Value == "0" { + c.warnBadArg(n, "-1") + } + case "append": + if len(call.Args) == 1 { + c.warnAppend(call) + } + } +} + +func (c *badCallChecker) warnBadArg(badArg *ast.BasicLit, correction string) { + goodArg := astcopy.BasicLit(badArg) + goodArg.Value = correction + c.ctx.Warn(badArg, "suspicious arg %s, probably meant %s", + badArg, goodArg) +} + +func (c *badCallChecker) warnAppend(call *ast.CallExpr) { + c.ctx.Warn(call, "no-op append call, probably missing arguments") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go b/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go new file mode 100644 index 000000000..466a89cc3 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go @@ -0,0 +1,147 @@ +package checkers + +import ( + "go/ast" + "go/constant" + "go/token" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/typep" + "golang.org/x/tools/go/ast/astutil" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "badCond" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects suspicious condition expressions" + info.Before = ` +for i := 0; i > n; i++ { + xs[i] = 0 +}` + info.After = ` +for i := 0; i < n; i++ { + xs[i] = 0 +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForFuncDecl(&badCondChecker{ctx: ctx}) + }) +} + +type badCondChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *badCondChecker) VisitFuncDecl(decl *ast.FuncDecl) { + ast.Inspect(decl.Body, func(n ast.Node) bool { + switch n := n.(type) { + case *ast.ForStmt: + c.checkForStmt(n) + case ast.Expr: + c.checkExpr(n) + } + return true + }) +} + +func (c *badCondChecker) checkExpr(expr ast.Expr) { + // TODO(Quasilyte): recognize more patterns. + + cond := astcast.ToBinaryExpr(expr) + lhs := astcast.ToBinaryExpr(astutil.Unparen(cond.X)) + rhs := astcast.ToBinaryExpr(astutil.Unparen(cond.Y)) + + if cond.Op != token.LAND { + return + } + + // Notes: + // `x != a || x != b` handled by go vet. + + // Pattern 1. + // `x < a && x > b`; Where `a` is less than `b`. + if c.lessAndGreater(lhs, rhs) { + c.warnCond(cond, "always false") + return + } + + // Pattern 2. + // `x == a && x == b` + // + // Valid when `b == a` is intended, but still reported. + // We can disable "just suspicious" warnings by default + // is users are upset with the current behavior. + if c.equalToBoth(lhs, rhs) { + c.warnCond(cond, "suspicious") + return + } +} + +func (c *badCondChecker) equalToBoth(lhs, rhs *ast.BinaryExpr) bool { + return lhs.Op == token.EQL && rhs.Op == token.EQL && + astequal.Expr(lhs.X, rhs.X) +} + +func (c *badCondChecker) lessAndGreater(lhs, rhs *ast.BinaryExpr) bool { + if lhs.Op != token.LSS || rhs.Op != token.GTR { + return false + } + if !astequal.Expr(lhs.X, rhs.X) { + return false + } + a := c.ctx.TypesInfo.Types[lhs.Y].Value + b := c.ctx.TypesInfo.Types[rhs.Y].Value + return a != nil && b != nil && constant.Compare(a, token.LSS, b) +} + +func (c *badCondChecker) checkForStmt(stmt *ast.ForStmt) { + // TODO(Quasilyte): handle other kinds of bad conditionals. + + init := astcast.ToAssignStmt(stmt.Init) + if init.Tok != token.DEFINE || len(init.Lhs) != 1 || len(init.Rhs) != 1 { + return + } + if astcast.ToBasicLit(init.Rhs[0]).Value != "0" { + return + } + + iter := astcast.ToIdent(init.Lhs[0]) + cond := astcast.ToBinaryExpr(stmt.Cond) + if cond.Op != token.GTR || !astequal.Expr(iter, cond.X) { + return + } + if !typep.SideEffectFree(c.ctx.TypesInfo, cond.Y) { + return + } + + post := astcast.ToIncDecStmt(stmt.Post) + if post.Tok != token.INC || !astequal.Expr(iter, post.X) { + return + } + + mutated := lintutil.CouldBeMutated(c.ctx.TypesInfo, stmt.Body, cond.Y) || + lintutil.CouldBeMutated(c.ctx.TypesInfo, stmt.Body, iter) + if mutated { + return + } + + c.warnForStmt(stmt, cond) +} + +func (c *badCondChecker) warnForStmt(cause ast.Node, cond *ast.BinaryExpr) { + suggest := astcopy.BinaryExpr(cond) + suggest.Op = token.LSS + c.ctx.Warn(cause, "`%s` in loop; probably meant `%s`?", + cond, suggest) +} + +func (c *badCondChecker) warnCond(cond *ast.BinaryExpr, tag string) { + c.ctx.Warn(cond, "`%s` condition is %s", cond, tag) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/boolExprSimplify_checker.go b/vendor/github.com/go-critic/go-critic/checkers/boolExprSimplify_checker.go new file mode 100644 index 000000000..f4eb9ed73 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/boolExprSimplify_checker.go @@ -0,0 +1,344 @@ +package checkers + +import ( + "fmt" + "go/ast" + "go/token" + "strconv" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/astp" + "github.com/go-toolsmith/typep" + "golang.org/x/tools/go/ast/astutil" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "boolExprSimplify" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects bool expressions that can be simplified" + info.Before = ` +a := !(elapsed >= expectElapsedMin) +b := !(x) == !(y)` + info.After = ` +a := elapsed < expectElapsedMin +b := (x) == (y)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&boolExprSimplifyChecker{ctx: ctx}) + }) +} + +type boolExprSimplifyChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + hasFloats bool +} + +func (c *boolExprSimplifyChecker) VisitExpr(x ast.Expr) { + if !astp.IsBinaryExpr(x) && !astp.IsUnaryExpr(x) { + return + } + + // Throw away non-bool expressions and avoid redundant + // AST copying below. + if typ := c.ctx.TypesInfo.TypeOf(x); typ == nil || !typep.HasBoolKind(typ.Underlying()) { + return + } + + // We'll loose all types info after a copy, + // this is why we record valuable info before doing it. + c.hasFloats = lintutil.ContainsNode(x, func(n ast.Node) bool { + if x, ok := n.(*ast.BinaryExpr); ok { + return typep.HasFloatProp(c.ctx.TypesInfo.TypeOf(x.X).Underlying()) || + typep.HasFloatProp(c.ctx.TypesInfo.TypeOf(x.Y).Underlying()) + } + return false + }) + + y := c.simplifyBool(astcopy.Expr(x)) + if !astequal.Expr(x, y) { + c.warn(x, y) + } +} + +func (c *boolExprSimplifyChecker) simplifyBool(x ast.Expr) ast.Expr { + return astutil.Apply(x, nil, func(cur *astutil.Cursor) bool { + return c.doubleNegation(cur) || + c.negatedEquals(cur) || + c.invertComparison(cur) || + c.combineChecks(cur) || + c.removeIncDec(cur) || + c.foldRanges(cur) || + true + }).(ast.Expr) +} + +func (c *boolExprSimplifyChecker) doubleNegation(cur *astutil.Cursor) bool { + neg1 := astcast.ToUnaryExpr(cur.Node()) + neg2 := astcast.ToUnaryExpr(astutil.Unparen(neg1.X)) + if neg1.Op == token.NOT && neg2.Op == token.NOT { + cur.Replace(astutil.Unparen(neg2.X)) + return true + } + return false +} + +func (c *boolExprSimplifyChecker) negatedEquals(cur *astutil.Cursor) bool { + x, ok := cur.Node().(*ast.BinaryExpr) + if !ok || x.Op != token.EQL { + return false + } + neg1 := astcast.ToUnaryExpr(x.X) + neg2 := astcast.ToUnaryExpr(x.Y) + if neg1.Op == token.NOT && neg2.Op == token.NOT { + x.X = neg1.X + x.Y = neg2.X + return true + } + return false +} + +func (c *boolExprSimplifyChecker) invertComparison(cur *astutil.Cursor) bool { + if c.hasFloats { // See #673 + return false + } + + neg := astcast.ToUnaryExpr(cur.Node()) + cmp := astcast.ToBinaryExpr(astutil.Unparen(neg.X)) + if neg.Op != token.NOT { + return false + } + + // Replace operator to its negated form. + switch cmp.Op { + case token.EQL: + cmp.Op = token.NEQ + case token.NEQ: + cmp.Op = token.EQL + case token.LSS: + cmp.Op = token.GEQ + case token.GTR: + cmp.Op = token.LEQ + case token.LEQ: + cmp.Op = token.GTR + case token.GEQ: + cmp.Op = token.LSS + + default: + return false + } + cur.Replace(cmp) + return true +} + +func (c *boolExprSimplifyChecker) isSafe(x ast.Expr) bool { + return typep.SideEffectFree(c.ctx.TypesInfo, x) +} + +func (c *boolExprSimplifyChecker) combineChecks(cur *astutil.Cursor) bool { + or, ok := cur.Node().(*ast.BinaryExpr) + if !ok || or.Op != token.LOR { + return false + } + + lhs := astcast.ToBinaryExpr(astutil.Unparen(or.X)) + rhs := astcast.ToBinaryExpr(astutil.Unparen(or.Y)) + + if !astequal.Expr(lhs.X, rhs.X) || !astequal.Expr(lhs.Y, rhs.Y) { + return false + } + if !c.isSafe(lhs.X) || !c.isSafe(lhs.Y) { + return false + } + + combTable := [...]struct { + x token.Token + y token.Token + result token.Token + }{ + {token.GTR, token.EQL, token.GEQ}, + {token.EQL, token.GTR, token.GEQ}, + {token.LSS, token.EQL, token.LEQ}, + {token.EQL, token.LSS, token.LEQ}, + } + for _, comb := range &combTable { + if comb.x == lhs.Op && comb.y == rhs.Op { + lhs.Op = comb.result + cur.Replace(lhs) + return true + } + } + return false +} + +func (c *boolExprSimplifyChecker) removeIncDec(cur *astutil.Cursor) bool { + cmp := astcast.ToBinaryExpr(cur.Node()) + + matchOneWay := func(op token.Token, x, y *ast.BinaryExpr) bool { + if x.Op != op || astcast.ToBasicLit(x.Y).Value != "1" { + return false + } + if y.Op == op && astcast.ToBasicLit(y.Y).Value == "1" { + return false + } + return true + } + replace := func(lhsOp, rhsOp, replacement token.Token) bool { + lhs := astcast.ToBinaryExpr(cmp.X) + rhs := astcast.ToBinaryExpr(cmp.Y) + switch { + case matchOneWay(lhsOp, lhs, rhs): + cmp.X = lhs.X + cmp.Op = replacement + cur.Replace(cmp) + return true + case matchOneWay(rhsOp, rhs, lhs): + cmp.Y = rhs.X + cmp.Op = replacement + cur.Replace(cmp) + return true + default: + return false + } + } + + switch cmp.Op { + case token.GTR: + // `x > y-1` => `x >= y` + // `x+1 > y` => `x >= y` + return replace(token.ADD, token.SUB, token.GEQ) + + case token.GEQ: + // `x >= y+1` => `x > y` + // `x-1 >= y` => `x > y` + return replace(token.SUB, token.ADD, token.GTR) + + case token.LSS: + // `x < y+1` => `x <= y` + // `x-1 < y` => `x <= y` + return replace(token.SUB, token.ADD, token.LEQ) + + case token.LEQ: + // `x <= y-1` => `x < y` + // `x+1 <= y` => `x < y` + return replace(token.ADD, token.SUB, token.LSS) + + default: + return false + } +} + +func (c *boolExprSimplifyChecker) foldRanges(cur *astutil.Cursor) bool { + if c.hasFloats { // See #848 + return false + } + + e, ok := cur.Node().(*ast.BinaryExpr) + if !ok { + return false + } + lhs := astcast.ToBinaryExpr(e.X) + rhs := astcast.ToBinaryExpr(e.Y) + if !c.isSafe(lhs.X) || !c.isSafe(rhs.X) { + return false + } + if !astequal.Expr(lhs.X, rhs.X) { + return false + } + + c1, ok := c.int64val(lhs.Y) + if !ok { + return false + } + c2, ok := c.int64val(rhs.Y) + if !ok { + return false + } + + type combination struct { + lhsOp token.Token + rhsOp token.Token + rhsDiff int64 + resDelta int64 + } + match := func(comb *combination) bool { + if lhs.Op != comb.lhsOp || rhs.Op != comb.rhsOp { + return false + } + if c2-c1 != comb.rhsDiff { + return false + } + return true + } + + switch e.Op { + case token.LAND: + combTable := [...]combination{ + // `x > c && x < c+2` => `x == c+1` + {token.GTR, token.LSS, 2, 1}, + // `x >= c && x < c+1` => `x == c` + {token.GEQ, token.LSS, 1, 0}, + // `x > c && x <= c+1` => `x == c+1` + {token.GTR, token.LEQ, 1, 1}, + // `x >= c && x <= c` => `x == c` + {token.GEQ, token.LEQ, 0, 0}, + } + for _, comb := range combTable { + if match(&comb) { + lhs.Op = token.EQL + v := c1 + comb.resDelta + lhs.Y.(*ast.BasicLit).Value = fmt.Sprint(v) + cur.Replace(lhs) + return true + } + } + + case token.LOR: + combTable := [...]combination{ + // `x < c || x > c` => `x != c` + {token.LSS, token.GTR, 0, 0}, + // `x <= c || x > c+1` => `x != c+1` + {token.LEQ, token.GTR, 1, 1}, + // `x < c || x >= c+1` => `x != c` + {token.LSS, token.GEQ, 1, 0}, + // `x <= c || x >= c+2` => `x != c+1` + {token.LEQ, token.GEQ, 2, 1}, + } + for _, comb := range combTable { + if match(&comb) { + lhs.Op = token.NEQ + v := c1 + comb.resDelta + lhs.Y.(*ast.BasicLit).Value = fmt.Sprint(v) + cur.Replace(lhs) + return true + } + } + } + + return false +} + +func (c *boolExprSimplifyChecker) int64val(x ast.Expr) (int64, bool) { + // TODO(Quasilyte): if we had types info, we could use TypesInfo.Types[x].Value, + // but since copying erases leaves us without it, only basic literals are handled. + lit, ok := x.(*ast.BasicLit) + if !ok { + return 0, false + } + v, err := strconv.ParseInt(lit.Value, 10, 64) + if err != nil { + return 0, false + } + return v, true +} + +func (c *boolExprSimplifyChecker) warn(cause, suggestion ast.Expr) { + c.SkipChilds = true + c.ctx.Warn(cause, "can simplify `%s` to `%s`", cause, suggestion) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/builtinShadow_checker.go b/vendor/github.com/go-critic/go-critic/checkers/builtinShadow_checker.go new file mode 100644 index 000000000..24d8b7fff --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/builtinShadow_checker.go @@ -0,0 +1,36 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "builtinShadow" + info.Tags = []string{"style", "opinionated"} + info.Summary = "Detects when predeclared identifiers shadowed in assignments" + info.Before = `len := 10` + info.After = `length := 10` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForLocalDef(&builtinShadowChecker{ctx: ctx}, ctx.TypesInfo) + }) +} + +type builtinShadowChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *builtinShadowChecker) VisitLocalDef(name astwalk.Name, _ ast.Expr) { + if isBuiltin(name.ID.Name) { + c.warn(name.ID) + } +} + +func (c *builtinShadowChecker) warn(ident *ast.Ident) { + c.ctx.Warn(ident, "shadowing of predeclared identifier: %s", ident) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/captLocal_checker.go b/vendor/github.com/go-critic/go-critic/checkers/captLocal_checker.go new file mode 100644 index 000000000..bc9a2115f --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/captLocal_checker.go @@ -0,0 +1,49 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "captLocal" + info.Tags = []string{"style"} + info.Params = lintpack.CheckerParams{ + "paramsOnly": { + Value: true, + Usage: "whether to restrict checker to params only", + }, + } + info.Summary = "Detects capitalized names for local variables" + info.Before = `func f(IN int, OUT *int) (ERR error) {}` + info.After = `func f(in int, out *int) (err error) {}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &captLocalChecker{ctx: ctx} + c.paramsOnly = info.Params.Bool("paramsOnly") + return astwalk.WalkerForLocalDef(c, ctx.TypesInfo) + }) +} + +type captLocalChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + paramsOnly bool +} + +func (c *captLocalChecker) VisitLocalDef(def astwalk.Name, _ ast.Expr) { + if c.paramsOnly && def.Kind != astwalk.NameParam { + return + } + if ast.IsExported(def.ID.Name) { + c.warn(def.ID) + } +} + +func (c *captLocalChecker) warn(id ast.Node) { + c.ctx.Warn(id, "`%s' should not be capitalized", id) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/caseOrder_checker.go b/vendor/github.com/go-critic/go-critic/checkers/caseOrder_checker.go new file mode 100644 index 000000000..1ef4b53b7 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/caseOrder_checker.go @@ -0,0 +1,88 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "caseOrder" + info.Tags = []string{"diagnostic"} + info.Summary = "Detects erroneous case order inside switch statements" + info.Before = ` +switch x.(type) { +case ast.Expr: + fmt.Println("expr") +case *ast.BasicLit: + fmt.Println("basic lit") // Never executed +}` + info.After = ` +switch x.(type) { +case *ast.BasicLit: + fmt.Println("basic lit") // Now reachable +case ast.Expr: + fmt.Println("expr") +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&caseOrderChecker{ctx: ctx}) + }) +} + +type caseOrderChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *caseOrderChecker) VisitStmt(stmt ast.Stmt) { + switch stmt := stmt.(type) { + case *ast.TypeSwitchStmt: + c.checkTypeSwitch(stmt) + case *ast.SwitchStmt: + c.checkSwitch(stmt) + } +} + +func (c *caseOrderChecker) checkTypeSwitch(s *ast.TypeSwitchStmt) { + type ifaceType struct { + node ast.Node + typ *types.Interface + } + var ifaces []ifaceType // Interfaces seen so far + for _, cc := range s.Body.List { + cc := cc.(*ast.CaseClause) + for _, x := range cc.List { + typ := c.ctx.TypesInfo.TypeOf(x) + if typ == nil { + c.warnTypeImpl(cc, x) + return + } + for _, iface := range ifaces { + if types.Implements(typ, iface.typ) { + c.warnTypeSwitch(cc, x, iface.node) + break + } + } + if iface, ok := typ.Underlying().(*types.Interface); ok { + ifaces = append(ifaces, ifaceType{node: x, typ: iface}) + } + } + } +} + +func (c *caseOrderChecker) warnTypeSwitch(cause, concrete, iface ast.Node) { + c.ctx.Warn(cause, "case %s must go before the %s case", concrete, iface) +} + +func (c *caseOrderChecker) warnTypeImpl(cause, concrete ast.Node) { + c.ctx.Warn(cause, "type is not defined %s", concrete) +} + +func (c *caseOrderChecker) checkSwitch(s *ast.SwitchStmt) { + // TODO(Quasilyte): can handle expression cases that overlap. + // Cases that have narrower value range should go before wider ones. +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/checkers.go b/vendor/github.com/go-critic/go-critic/checkers/checkers.go new file mode 100644 index 000000000..96202221e --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/checkers.go @@ -0,0 +1,10 @@ +// Package checkers is a gocritic linter main checkers collection. +package checkers + +import ( + "github.com/go-lintpack/lintpack" +) + +var collection = &lintpack.CheckerCollection{ + URL: "https://github.com/go-critic/go-critic/checkers", +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/codegenComment_checker.go b/vendor/github.com/go-critic/go-critic/checkers/codegenComment_checker.go new file mode 100644 index 000000000..14d89da37 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/codegenComment_checker.go @@ -0,0 +1,61 @@ +package checkers + +import ( + "go/ast" + "regexp" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "codegenComment" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects malformed 'code generated' file comments" + info.Before = `// This file was automatically generated by foogen` + info.After = `// Code generated by foogen. DO NOT EDIT.` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + patterns := []string{ + "this (?:file|code) (?:was|is) auto(?:matically)? generated", + "this (?:file|code) (?:was|is) generated automatically", + "this (?:file|code) (?:was|is) generated by", + "this (?:file|code) (?:was|is) (?:auto(?:matically)? )?generated", + "this (?:file|code) (?:was|is) generated", + "code in this file (?:was|is) auto(?:matically)? generated", + "generated (?:file|code) - do not edit", + // TODO(Quasilyte): more of these. + } + re := regexp.MustCompile("(?i)" + strings.Join(patterns, "|")) + return &codegenCommentChecker{ + ctx: ctx, + badCommentRE: re, + } + }) +} + +type codegenCommentChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + badCommentRE *regexp.Regexp +} + +func (c *codegenCommentChecker) WalkFile(f *ast.File) { + if f.Doc == nil { + return + } + + for _, comment := range f.Doc.List { + if c.badCommentRE.MatchString(comment.Text) { + c.warn(comment) + return + } + } +} + +func (c *codegenCommentChecker) warn(cause ast.Node) { + c.ctx.Warn(cause, "comment should match `Code generated .* DO NOT EDIT.` regexp") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go b/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go new file mode 100644 index 000000000..ed75015e0 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go @@ -0,0 +1,77 @@ +package checkers + +import ( + "go/ast" + "regexp" + "strings" + "unicode" + "unicode/utf8" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "commentFormatting" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects comments with non-idiomatic formatting" + info.Before = `//This is a comment` + info.After = `// This is a comment` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + parts := []string{ + `^//\w+:.*$`, //key: value + `^//nolint$`, //nolint + `^//line /.*:\d+`, //line /path/to/file:123 + } + pat := "(?m)" + strings.Join(parts, "|") + pragmaRE := regexp.MustCompile(pat) + return astwalk.WalkerForComment(&commentFormattingChecker{ + ctx: ctx, + pragmaRE: pragmaRE, + }) + }) +} + +type commentFormattingChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + pragmaRE *regexp.Regexp +} + +func (c *commentFormattingChecker) VisitComment(cg *ast.CommentGroup) { + if strings.HasPrefix(cg.List[0].Text, "/*") { + return + } + for _, comment := range cg.List { + if len(comment.Text) <= len("// ") { + continue + } + if c.pragmaRE.MatchString(comment.Text) { + continue + } + + // Make a decision based on a first comment text rune. + r, _ := utf8.DecodeRuneInString(comment.Text[len("//"):]) + if !c.specialChar(r) && !unicode.IsSpace(r) { + c.warn(cg) + return + } + } +} + +func (c *commentFormattingChecker) specialChar(r rune) bool { + // Permitted list to avoid false-positives. + switch r { + case '+', '-', '#', '!': + return true + default: + return false + } +} + +func (c *commentFormattingChecker) warn(cg *ast.CommentGroup) { + c.ctx.Warn(cg, "put a space between `//` and comment text") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/commentedOutCode_checker.go b/vendor/github.com/go-critic/go-critic/checkers/commentedOutCode_checker.go new file mode 100644 index 000000000..0554e365e --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/commentedOutCode_checker.go @@ -0,0 +1,157 @@ +package checkers + +import ( + "fmt" + "go/ast" + "go/token" + "regexp" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/strparse" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "commentedOutCode" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects commented-out code inside function bodies" + info.Before = ` +// fmt.Println("Debugging hard") +foo(1, 2)` + info.After = `foo(1, 2)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForLocalComment(&commentedOutCodeChecker{ + ctx: ctx, + notQuiteFuncCall: regexp.MustCompile(`\w+\s+\([^)]*\)\s*$`), + }) + }) +} + +type commentedOutCodeChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + fn *ast.FuncDecl + + notQuiteFuncCall *regexp.Regexp +} + +func (c *commentedOutCodeChecker) EnterFunc(fn *ast.FuncDecl) bool { + c.fn = fn // Need to store current function inside checker context + return fn.Body != nil +} + +func (c *commentedOutCodeChecker) VisitLocalComment(cg *ast.CommentGroup) { + s := cg.Text() // Collect text once + + // We do multiple heuristics to avoid false positives. + // Many things can be improved here. + + markers := []string{ + "TODO", // TODO comments with code are permitted. + + // "http://" is interpreted as a label with comment. + // There are other protocols we might want to include. + "http://", + "https://", + + "e.g. ", // Clearly not a "selector expr" (mostly due to extra space) + } + for _, m := range markers { + if strings.Contains(s, m) { + return + } + } + + // Some very short comment that can be skipped. + // Usually triggering on these results in false positive. + // Unless there is a very popular call like print/println. + cond := len(s) < len("quite too short") && + !strings.Contains(s, "print") && + !strings.Contains(s, "fmt.") && + !strings.Contains(s, "log.") + if cond { + return + } + + // Almost looks like a commented-out function call, + // but there is a whitespace between function name and + // parameters list. Skip these to avoid false positives. + if c.notQuiteFuncCall.MatchString(s) { + return + } + + stmt := strparse.Stmt(s) + + if c.isPermittedStmt(stmt) { + return + } + + if stmt != strparse.BadStmt { + c.warn(cg) + return + } + + // Don't try to parse one-liner as block statement + if len(cg.List) == 1 && !strings.Contains(s, "\n") { + return + } + + // Some attempts to avoid false positives. + if c.skipBlock(s) { + return + } + + // Add braces to make block statement from + // multiple statements. + stmt = strparse.Stmt(fmt.Sprintf("{ %s }", s)) + + if stmt, ok := stmt.(*ast.BlockStmt); ok && len(stmt.List) != 0 { + c.warn(cg) + } +} + +func (c *commentedOutCodeChecker) skipBlock(s string) bool { + lines := strings.Split(s, "\n") // There is at least 1 line, that's invariant + + // Special example test block. + if isExampleTestFunc(c.fn) && strings.Contains(lines[0], "Output:") { + return true + } + + return false +} + +func (c *commentedOutCodeChecker) isPermittedStmt(stmt ast.Stmt) bool { + switch stmt := stmt.(type) { + case *ast.ExprStmt: + return c.isPermittedExpr(stmt.X) + case *ast.LabeledStmt: + return c.isPermittedStmt(stmt.Stmt) + case *ast.DeclStmt: + decl := stmt.Decl.(*ast.GenDecl) + return decl.Tok == token.TYPE + default: + return false + } +} + +func (c *commentedOutCodeChecker) isPermittedExpr(x ast.Expr) bool { + // Permit anything except expressions that can be used + // with complete result discarding. + switch x := x.(type) { + case *ast.CallExpr: + return false + case *ast.UnaryExpr: + // "<-" channel receive is not permitted. + return x.Op != token.ARROW + default: + return true + } +} + +func (c *commentedOutCodeChecker) warn(cause ast.Node) { + c.ctx.Warn(cause, "may want to remove commented-out code") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/commentedOutImport_checker.go b/vendor/github.com/go-critic/go-critic/checkers/commentedOutImport_checker.go new file mode 100644 index 000000000..5aeb86c07 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/commentedOutImport_checker.go @@ -0,0 +1,76 @@ +package checkers + +import ( + "go/ast" + "go/token" + "regexp" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "commentedOutImport" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects commented-out imports" + info.Before = ` +import ( + "fmt" + //"os" +)` + info.After = ` +import ( + "fmt" +)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + const pattern = `(?m)^(?://|/\*)?\s*"([a-zA-Z0-9_/]+)"\s*(?:\*/)?$` + return &commentedOutImportChecker{ + ctx: ctx, + importStringRE: regexp.MustCompile(pattern), + } + }) +} + +type commentedOutImportChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + importStringRE *regexp.Regexp +} + +func (c *commentedOutImportChecker) WalkFile(f *ast.File) { + // TODO(Quasilyte): handle commented-out import spec, + // for example: // import "errors". + + for _, decl := range f.Decls { + decl, ok := decl.(*ast.GenDecl) + if !ok || decl.Tok != token.IMPORT { + // Import decls can only be in the beginning of the file. + // If we've met some other decl, there will be no more + // import decls. + break + } + + // Find comments inside this import decl span. + for _, cg := range f.Comments { + if cg.Pos() > decl.Rparen { + break // Below the decl, stop. + } + if cg.Pos() < decl.Lparen { + continue // Before the decl, skip. + } + + for _, comment := range cg.List { + for _, m := range c.importStringRE.FindAllStringSubmatch(comment.Text, -1) { + c.warn(comment, m[1]) + } + } + } + } +} + +func (c *commentedOutImportChecker) warn(cause ast.Node, path string) { + c.ctx.Warn(cause, "remove commented-out %q import", path) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/defaultCaseOrder_checker.go b/vendor/github.com/go-critic/go-critic/checkers/defaultCaseOrder_checker.go new file mode 100644 index 000000000..caa0de657 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/defaultCaseOrder_checker.go @@ -0,0 +1,65 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "defaultCaseOrder" + info.Tags = []string{"style"} + info.Summary = "Detects when default case in switch isn't on 1st or last position" + info.Before = ` +switch { +case x > y: + // ... +default: // <- not the best position + // ... +case x == 10: + // ... +}` + info.After = ` +switch { +case x > y: + // ... +case x == 10: + // ... +default: // <- last case (could also be the first one) + // ... +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&defaultCaseOrderChecker{ctx: ctx}) + }) +} + +type defaultCaseOrderChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *defaultCaseOrderChecker) VisitStmt(stmt ast.Stmt) { + swtch, ok := stmt.(*ast.SwitchStmt) + if !ok { + return + } + for i, stmt := range swtch.Body.List { + caseStmt, ok := stmt.(*ast.CaseClause) + if !ok { + continue + } + // is `default` case + if caseStmt.List == nil { + if i != 0 && i != len(swtch.Body.List)-1 { + c.warn(caseStmt) + } + } + } +} + +func (c *defaultCaseOrderChecker) warn(cause *ast.CaseClause) { + c.ctx.Warn(cause, "consider to make `default` case as first or as last case") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go b/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go new file mode 100644 index 000000000..37675735b --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go @@ -0,0 +1,149 @@ +package checkers + +import ( + "go/ast" + "regexp" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "deprecatedComment" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects malformed 'deprecated' doc-comments" + info.Before = ` +// deprecated, use FuncNew instead +func FuncOld() int` + info.After = ` +// Deprecated: use FuncNew instead +func FuncOld() int` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &deprecatedCommentChecker{ctx: ctx} + + c.commonPatterns = []*regexp.Regexp{ + regexp.MustCompile(`(?i)this (?:function|type) is deprecated`), + regexp.MustCompile(`(?i)deprecated[.!]? use \S* instead`), + regexp.MustCompile(`(?i)\[\[deprecated\]\].*`), + regexp.MustCompile(`(?i)note: deprecated\b.*`), + regexp.MustCompile(`(?i)deprecated in.*`), + // TODO(quasilyte): more of these? + } + + // TODO(quasilyte): may want to generate this list programmatically. + // + // TODO(quasilyte): currently it only handles a single missing letter. + // Might want to handle other kinds of common misspell/typo kinds. + c.commonTypos = []string{ + "Dprecated: ", + "Derecated: ", + "Depecated: ", + "Deprcated: ", + "Depreated: ", + "Deprected: ", + "Deprecaed: ", + "Deprecatd: ", + "Deprecate: ", + "Derpecate: ", + "Derpecated: ", + "Depreacted: ", + } + for i := range c.commonTypos { + c.commonTypos[i] = strings.ToUpper(c.commonTypos[i]) + } + + return astwalk.WalkerForDocComment(c) + }) +} + +type deprecatedCommentChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + commonPatterns []*regexp.Regexp + commonTypos []string +} + +func (c *deprecatedCommentChecker) VisitDocComment(doc *ast.CommentGroup) { + // There are 3 accepted forms of deprecation comments: + // + // 1. inline, that can't be handled with a DocCommentVisitor. + // Note that "Deprecated: " may not even be the comment prefix there. + // Example: "The line number in the input. Deprecated: Kept for compatibility." + // TODO(quasilyte): fix it. + // + // 2. Longer form-1. It's a doc-comment that only contains "deprecation" notice. + // + // 3. Like form-2, but may also include doc-comment text. + // Distinguished by an empty line. + // + // See https://github.com/golang/go/issues/10909#issuecomment-136492606. + // + // It's desirable to see how people make mistakes with the format, + // this is why there is currently no special treatment for these cases. + // TODO(quasilyte): do more audits and grow the negative tests suite. + // + // TODO(quasilyte): there are also multi-line deprecation comments. + + for _, comment := range doc.List { + if strings.HasPrefix(comment.Text, "/*") { + // TODO(quasilyte): handle multi-line doc comments. + continue + } + l := comment.Text[len("//"):] + if len(l) < len("Deprecated: ") { + continue + } + l = strings.TrimSpace(l) + + // Check whether someone messed up with a prefix casing. + upcase := strings.ToUpper(l) + if strings.HasPrefix(upcase, "DEPRECATED: ") && !strings.HasPrefix(l, "Deprecated: ") { + c.warnCasing(comment, l) + return + } + + // Check is someone used comma instead of a colon. + if strings.HasPrefix(l, "Deprecated, ") { + c.warnComma(comment) + return + } + + // Check for other commonly used patterns. + for _, pat := range c.commonPatterns { + if pat.MatchString(l) { + c.warnPattern(comment) + return + } + } + + // Detect some simple typos. + for _, prefixWithTypo := range c.commonTypos { + if strings.HasPrefix(upcase, prefixWithTypo) { + c.warnTypo(comment, l) + return + } + } + } +} + +func (c *deprecatedCommentChecker) warnCasing(cause ast.Node, line string) { + prefix := line[:len("DEPRECATED: ")] + c.ctx.Warn(cause, "use `Deprecated: ` (note the casing) instead of `%s`", prefix) +} + +func (c *deprecatedCommentChecker) warnPattern(cause ast.Node) { + c.ctx.Warn(cause, "the proper format is `Deprecated: `") +} + +func (c *deprecatedCommentChecker) warnComma(cause ast.Node) { + c.ctx.Warn(cause, "use `:` instead of `,` in `Deprecated, `") +} + +func (c *deprecatedCommentChecker) warnTypo(cause ast.Node, line string) { + word := strings.Split(line, ":")[0] + c.ctx.Warn(cause, "typo in `%s`; should be `Deprecated`", word) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/docStub_checker.go b/vendor/github.com/go-critic/go-critic/checkers/docStub_checker.go new file mode 100644 index 000000000..5c771b31c --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/docStub_checker.go @@ -0,0 +1,95 @@ +package checkers + +import ( + "go/ast" + "go/token" + "regexp" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "docStub" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects comments that silence go lint complaints about doc-comment" + info.Before = ` +// Foo ... +func Foo() { +}` + info.After = ` +// (A) - remove the doc-comment stub +func Foo() {} +// (B) - replace it with meaningful comment +// Foo is a demonstration-only function. +func Foo() {}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + re := `(?i)^\.\.\.$|^\.$|^xxx\.?$|^whatever\.?$` + c := &docStubChecker{ + ctx: ctx, + stubCommentRE: regexp.MustCompile(re), + } + return c + }) +} + +type docStubChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + stubCommentRE *regexp.Regexp +} + +func (c *docStubChecker) WalkFile(f *ast.File) { + for _, decl := range f.Decls { + switch decl := decl.(type) { + case *ast.FuncDecl: + c.visitDoc(decl, decl.Name, decl.Doc, false) + case *ast.GenDecl: + if decl.Tok != token.TYPE { + continue + } + if len(decl.Specs) == 1 { + spec := decl.Specs[0].(*ast.TypeSpec) + // Only 1 spec, use doc from the decl itself. + c.visitDoc(spec, spec.Name, decl.Doc, true) + } + // N specs, use per-spec doc. + for _, spec := range decl.Specs { + spec := spec.(*ast.TypeSpec) + c.visitDoc(spec, spec.Name, spec.Doc, true) + } + } + } +} + +func (c *docStubChecker) visitDoc(decl ast.Node, sym *ast.Ident, doc *ast.CommentGroup, article bool) { + if !sym.IsExported() || doc == nil { + return + } + line := strings.TrimSpace(doc.List[0].Text[len("//"):]) + if article { + // Skip optional article. + for _, a := range []string{"The ", "An ", "A "} { + if strings.HasPrefix(line, a) { + line = line[len(a):] + break + } + } + } + if !strings.HasPrefix(line, sym.Name) { + return + } + line = strings.TrimSpace(line[len(sym.Name):]) + // Now try to detect the "stub" part. + if c.stubCommentRE.MatchString(line) { + c.warn(decl) + } +} + +func (c *docStubChecker) warn(cause ast.Node) { + c.ctx.Warn(cause, "silencing go lint doc-comment warnings is unadvised") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupArg_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupArg_checker.go new file mode 100644 index 000000000..819759403 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/dupArg_checker.go @@ -0,0 +1,133 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astequal" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "dupArg" + info.Tags = []string{"diagnostic"} + info.Summary = "Detects suspicious duplicated arguments" + info.Before = `copy(dst, dst)` + info.After = `copy(dst, src)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &dupArgChecker{ctx: ctx} + // newMatcherFunc returns a function that matches a call if + // args[xIndex] and args[yIndex] are equal. + newMatcherFunc := func(xIndex, yIndex int) func(*ast.CallExpr) bool { + return func(call *ast.CallExpr) bool { + if len(call.Args) <= xIndex || len(call.Args) <= yIndex { + return false + } + x := call.Args[xIndex] + y := call.Args[yIndex] + return astequal.Expr(x, y) + } + } + + // m maps pattern string to a matching function. + // String patterns are used for documentation purposes (readability). + m := map[string]func(*ast.CallExpr) bool{ + "(x, x, ...)": newMatcherFunc(0, 1), + "(x, _, x, ...)": newMatcherFunc(0, 2), + "(_, x, x, ...)": newMatcherFunc(1, 2), + } + + // TODO(quasilyte): handle x.Equal(x) cases. + // Example: *math/Big.Int.Cmp method. + + // TODO(quasilyte): more perky mode that will also + // report things like io.Copy(x, x). + // Probably safe thing to do even without that option + // if `x` is not interface (requires type checks + // that are not incorporated into this checker yet). + + c.matchers = map[string]func(*ast.CallExpr) bool{ + "copy": m["(x, x, ...)"], + + "math.Max": m["(x, x, ...)"], + "math.Min": m["(x, x, ...)"], + + "reflect.Copy": m["(x, x, ...)"], + "reflect.DeepEqual": m["(x, x, ...)"], + + "strings.Contains": m["(x, x, ...)"], + "strings.Compare": m["(x, x, ...)"], + "strings.EqualFold": m["(x, x, ...)"], + "strings.HasPrefix": m["(x, x, ...)"], + "strings.HasSuffix": m["(x, x, ...)"], + "strings.Index": m["(x, x, ...)"], + "strings.LastIndex": m["(x, x, ...)"], + "strings.Split": m["(x, x, ...)"], + "strings.SplitAfter": m["(x, x, ...)"], + "strings.SplitAfterN": m["(x, x, ...)"], + "strings.SplitN": m["(x, x, ...)"], + "strings.Replace": m["(_, x, x, ...)"], + "strings.ReplaceAll": m["(_, x, x, ...)"], + + "bytes.Contains": m["(x, x, ...)"], + "bytes.Compare": m["(x, x, ...)"], + "bytes.Equal": m["(x, x, ...)"], + "bytes.EqualFold": m["(x, x, ...)"], + "bytes.HasPrefix": m["(x, x, ...)"], + "bytes.HasSuffix": m["(x, x, ...)"], + "bytes.Index": m["(x, x, ...)"], + "bytes.LastIndex": m["(x, x, ...)"], + "bytes.Split": m["(x, x, ...)"], + "bytes.SplitAfter": m["(x, x, ...)"], + "bytes.SplitAfterN": m["(x, x, ...)"], + "bytes.SplitN": m["(x, x, ...)"], + "bytes.Replace": m["(_, x, x, ...)"], + "bytes.ReplaceAll": m["(_, x, x, ...)"], + + "types.Identical": m["(x, x, ...)"], + "types.IdenticalIgnoreTags": m["(x, x, ...)"], + + "draw.Draw": m["(x, _, x, ...)"], + + // TODO(quasilyte): more of these. + } + return astwalk.WalkerForExpr(c) + }) +} + +type dupArgChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + matchers map[string]func(*ast.CallExpr) bool +} + +func (c *dupArgChecker) VisitExpr(expr ast.Expr) { + call, ok := expr.(*ast.CallExpr) + if !ok { + return + } + + // TODO(quasilyte): this kind of check is needed in multiple + // places and the code is somewhat duplicated around. + // We probably need to stop using qualifiedName for non-experimental checkers. + if calledExpr, ok := call.Fun.(*ast.SelectorExpr); ok { + obj, ok := c.ctx.TypesInfo.ObjectOf(astcast.ToIdent(calledExpr.X)).(*types.PkgName) + if !ok || !isStdlibPkg(obj.Imported()) { + return + } + } + + m := c.matchers[qualifiedName(call.Fun)] + if m != nil && m(call) { + c.warn(call) + } +} + +func (c *dupArgChecker) warn(cause ast.Node) { + c.ctx.Warn(cause, "suspicious duplicated args in `%s`", cause) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupBranchBody_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupBranchBody_checker.go new file mode 100644 index 000000000..a13884873 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/dupBranchBody_checker.go @@ -0,0 +1,58 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astequal" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "dupBranchBody" + info.Tags = []string{"diagnostic"} + info.Summary = "Detects duplicated branch bodies inside conditional statements" + info.Before = ` +if cond { + println("cond=true") +} else { + println("cond=true") +}` + info.After = ` +if cond { + println("cond=true") +} else { + println("cond=false") +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&dupBranchBodyChecker{ctx: ctx}) + }) +} + +type dupBranchBodyChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *dupBranchBodyChecker) VisitStmt(stmt ast.Stmt) { + // TODO(quasilyte): extend to check switch statements as well. + // Should be very careful with type switches. + + if stmt, ok := stmt.(*ast.IfStmt); ok { + c.checkIf(stmt) + } +} + +func (c *dupBranchBodyChecker) checkIf(stmt *ast.IfStmt) { + thenBody := stmt.Body + elseBody, ok := stmt.Else.(*ast.BlockStmt) + if ok && astequal.Stmt(thenBody, elseBody) { + c.warnIf(stmt) + } +} + +func (c *dupBranchBodyChecker) warnIf(cause ast.Node) { + c.ctx.Warn(cause, "both branches in if statement has same body") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go new file mode 100644 index 000000000..26ef17398 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go @@ -0,0 +1,57 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "dupCase" + info.Tags = []string{"diagnostic"} + info.Summary = "Detects duplicated case clauses inside switch statements" + info.Before = ` +switch x { +case ys[0], ys[1], ys[2], ys[0], ys[4]: +}` + info.After = ` +switch x { +case ys[0], ys[1], ys[2], ys[3], ys[4]: +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&dupCaseChecker{ctx: ctx}) + }) +} + +type dupCaseChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + astSet lintutil.AstSet +} + +func (c *dupCaseChecker) VisitStmt(stmt ast.Stmt) { + if stmt, ok := stmt.(*ast.SwitchStmt); ok { + c.checkSwitch(stmt) + } +} + +func (c *dupCaseChecker) checkSwitch(stmt *ast.SwitchStmt) { + c.astSet.Clear() + for i := range stmt.Body.List { + cc := stmt.Body.List[i].(*ast.CaseClause) + for _, x := range cc.List { + if !c.astSet.Insert(x) { + c.warn(x) + } + } + } +} + +func (c *dupCaseChecker) warn(cause ast.Node) { + c.ctx.Warn(cause, "'case %s' is duplicated", cause) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupImports_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupImports_checker.go new file mode 100644 index 000000000..d531413a1 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/dupImports_checker.go @@ -0,0 +1,63 @@ +package checkers + +import ( + "fmt" + "go/ast" + + "github.com/go-lintpack/lintpack" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "dupImport" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects multiple imports of the same package under different aliases" + info.Before = ` +import ( + "fmt" + priting "fmt" // Imported the second time +)` + info.After = ` +import( + "fmt" +)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return &dupImportChecker{ctx: ctx} + }) +} + +type dupImportChecker struct { + ctx *lintpack.CheckerContext +} + +func (c *dupImportChecker) WalkFile(f *ast.File) { + imports := make(map[string][]*ast.ImportSpec) + for _, importDcl := range f.Imports { + pkg := importDcl.Path.Value + imports[pkg] = append(imports[pkg], importDcl) + } + + for _, importList := range imports { + if len(importList) == 1 { + continue + } + c.warn(importList) + } +} + +func (c *dupImportChecker) warn(importList []*ast.ImportSpec) { + msg := fmt.Sprintf("package is imported %d times under different aliases on lines", len(importList)) + for idx, importDcl := range importList { + switch { + case idx == len(importList)-1: + msg += " and" + case idx > 0: + msg += "," + } + msg += fmt.Sprintf(" %d", c.ctx.FileSet.Position(importDcl.Pos()).Line) + } + for _, importDcl := range importList { + c.ctx.Warn(importDcl, msg) + } +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupSubExpr_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupSubExpr_checker.go new file mode 100644 index 000000000..24bb52434 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/dupSubExpr_checker.go @@ -0,0 +1,102 @@ +package checkers + +import ( + "go/ast" + "go/token" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "dupSubExpr" + info.Tags = []string{"diagnostic"} + info.Summary = "Detects suspicious duplicated sub-expressions" + info.Before = ` +sort.Slice(xs, func(i, j int) bool { + return xs[i].v < xs[i].v // Duplicated index +})` + info.After = ` +sort.Slice(xs, func(i, j int) bool { + return xs[i].v < xs[j].v +})` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &dupSubExprChecker{ctx: ctx} + + ops := []struct { + op token.Token + float bool // Whether float args require special care + }{ + {op: token.LOR}, // x || x + {op: token.LAND}, // x && x + {op: token.OR}, // x | x + {op: token.AND}, // x & x + {op: token.XOR}, // x ^ x + {op: token.LSS}, // x < x + {op: token.GTR}, // x > x + {op: token.AND_NOT}, // x &^ x + {op: token.REM}, // x % x + + {op: token.EQL, float: true}, // x == x + {op: token.NEQ, float: true}, // x != x + {op: token.LEQ, float: true}, // x <= x + {op: token.GEQ, float: true}, // x >= x + {op: token.QUO, float: true}, // x / x + {op: token.SUB, float: true}, // x - x + } + + c.opSet = make(map[token.Token]bool) + c.floatOpsSet = make(map[token.Token]bool) + for _, opInfo := range ops { + c.opSet[opInfo.op] = true + if opInfo.float { + c.floatOpsSet[opInfo.op] = true + } + } + + return astwalk.WalkerForExpr(c) + }) +} + +type dupSubExprChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + // opSet is a set of binary operations that do not make + // sense with duplicated (same) RHS and LHS. + opSet map[token.Token]bool + + floatOpsSet map[token.Token]bool +} + +func (c *dupSubExprChecker) VisitExpr(expr ast.Expr) { + if expr, ok := expr.(*ast.BinaryExpr); ok { + c.checkBinaryExpr(expr) + } +} + +func (c *dupSubExprChecker) checkBinaryExpr(expr *ast.BinaryExpr) { + if !c.opSet[expr.Op] { + return + } + if c.resultIsFloat(expr.X) && c.floatOpsSet[expr.Op] { + return + } + if typep.SideEffectFree(c.ctx.TypesInfo, expr) && c.opSet[expr.Op] && astequal.Expr(expr.X, expr.Y) { + c.warn(expr) + } +} + +func (c *dupSubExprChecker) resultIsFloat(expr ast.Expr) bool { + typ, ok := c.ctx.TypesInfo.TypeOf(expr).(*types.Basic) + return ok && typ.Info()&types.IsFloat != 0 +} + +func (c *dupSubExprChecker) warn(cause *ast.BinaryExpr) { + c.ctx.Warn(cause, "suspicious identical LHS and RHS for `%s` operator", cause.Op) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go b/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go new file mode 100644 index 000000000..c3a9546bf --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go @@ -0,0 +1,71 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astp" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "elseif" + info.Tags = []string{"style"} + info.Params = lintpack.CheckerParams{ + "skipBalanced": { + Value: true, + Usage: "whether to skip balanced if-else pairs", + }, + } + info.Summary = "Detects else with nested if statement that can be replaced with else-if" + info.Before = ` +if cond1 { +} else { + if x := cond2; x { + } +}` + info.After = ` +if cond1 { +} else if x := cond2; x { +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &elseifChecker{ctx: ctx} + c.skipBalanced = info.Params.Bool("skipBalanced") + return astwalk.WalkerForStmt(c) + }) +} + +type elseifChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + skipBalanced bool +} + +func (c *elseifChecker) VisitStmt(stmt ast.Stmt) { + if stmt, ok := stmt.(*ast.IfStmt); ok { + elseBody, ok := stmt.Else.(*ast.BlockStmt) + if !ok || len(elseBody.List) != 1 { + return + } + innerIfStmt, ok := elseBody.List[0].(*ast.IfStmt) + if !ok { + return + } + balanced := len(stmt.Body.List) == 1 && + astp.IsIfStmt(stmt.Body.List[0]) + if balanced && c.skipBalanced { + return // Configured to skip balanced statements + } + if innerIfStmt.Else != nil { + return + } + c.warn(stmt.Else) + } +} + +func (c *elseifChecker) warn(cause ast.Node) { + c.ctx.Warn(cause, "can replace 'else {if cond {}}' with 'else if cond {}'") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/emptyFallthrough_checker.go b/vendor/github.com/go-critic/go-critic/checkers/emptyFallthrough_checker.go new file mode 100644 index 000000000..5908dfa31 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/emptyFallthrough_checker.go @@ -0,0 +1,70 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "emptyFallthrough" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects fallthrough that can be avoided by using multi case values" + info.Before = `switch kind { +case reflect.Int: + fallthrough +case reflect.Int32: + return Int +}` + info.After = `switch kind { +case reflect.Int, reflect.Int32: + return Int +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&emptyFallthroughChecker{ctx: ctx}) + }) +} + +type emptyFallthroughChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *emptyFallthroughChecker) VisitStmt(stmt ast.Stmt) { + ss, ok := stmt.(*ast.SwitchStmt) + if !ok { + return + } + + prevCaseDefault := false + for i := len(ss.Body.List) - 1; i >= 0; i-- { + if cc, ok := ss.Body.List[i].(*ast.CaseClause); ok { + warn := false + if len(cc.Body) == 1 { + if bs, ok := cc.Body[0].(*ast.BranchStmt); ok && bs.Tok == token.FALLTHROUGH { + warn = true + if prevCaseDefault { + c.warnDefault(bs) + } else { + c.warn(bs) + } + } + } + if !warn { + prevCaseDefault = cc.List == nil + } + } + } +} + +func (c *emptyFallthroughChecker) warnDefault(cause ast.Node) { + c.ctx.Warn(cause, "remove empty case containing only fallthrough to default case") +} + +func (c *emptyFallthroughChecker) warn(cause ast.Node) { + c.ctx.Warn(cause, "replace empty case containing only fallthrough with expression list") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/emptyStringTest_checker.go b/vendor/github.com/go-critic/go-critic/checkers/emptyStringTest_checker.go new file mode 100644 index 000000000..a7be906ed --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/emptyStringTest_checker.go @@ -0,0 +1,58 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "emptyStringTest" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects empty string checks that can be written more idiomatically" + info.Before = `len(s) == 0` + info.After = `s == ""` + info.Note = "See https://dmitri.shuralyov.com/idiomatic-go#empty-string-check." + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&emptyStringTestChecker{ctx: ctx}) + }) +} + +type emptyStringTestChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *emptyStringTestChecker) VisitExpr(e ast.Expr) { + cmp := astcast.ToBinaryExpr(e) + if cmp.Op != token.EQL && cmp.Op != token.NEQ { + return + } + lenCall := astcast.ToCallExpr(cmp.X) + if astcast.ToIdent(lenCall.Fun).Name != "len" { + return + } + s := lenCall.Args[0] + if !typep.HasStringProp(c.ctx.TypesInfo.TypeOf(s)) { + return + } + zero := astcast.ToBasicLit(cmp.Y) + if zero.Value != "0" { + return + } + c.warn(cmp, s) +} + +func (c *emptyStringTestChecker) warn(cmp *ast.BinaryExpr, s ast.Expr) { + suggest := astcopy.BinaryExpr(cmp) + suggest.X = s + suggest.Y = &ast.BasicLit{Value: `""`} + c.ctx.Warn(cmp, "replace `%s` with `%s`", cmp, suggest) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/equalFold_checker.go b/vendor/github.com/go-critic/go-critic/checkers/equalFold_checker.go new file mode 100644 index 000000000..265b2f79b --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/equalFold_checker.go @@ -0,0 +1,87 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astequal" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "equalFold" + info.Tags = []string{"performance", "experimental"} + info.Summary = "Detects unoptimal strings/bytes case-insensitive comparison" + info.Before = `strings.ToLower(x) == strings.ToLower(y)` + info.After = `strings.EqualFold(x, y)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&equalFoldChecker{ctx: ctx}) + }) +} + +type equalFoldChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *equalFoldChecker) VisitExpr(e ast.Expr) { + switch e := e.(type) { + case *ast.CallExpr: + c.checkBytes(e) + case *ast.BinaryExpr: + c.checkStrings(e) + } +} + +// uncaseCall simplifies lower(x) or upper(x) to x. +// If no simplification is applied, second return value is false. +func (c *equalFoldChecker) uncaseCall(x ast.Expr, lower, upper string) (ast.Expr, bool) { + call := astcast.ToCallExpr(x) + name := qualifiedName(call.Fun) + if name != lower && name != upper { + return x, false + } + return call.Args[0], true +} + +func (c *equalFoldChecker) checkBytes(expr *ast.CallExpr) { + if qualifiedName(expr.Fun) != "bytes.Equal" { + return + } + + x, ok1 := c.uncaseCall(expr.Args[0], "bytes.ToLower", "bytes.ToUpper") + y, ok2 := c.uncaseCall(expr.Args[1], "bytes.ToLower", "bytes.ToUpper") + if !ok1 && !ok2 { + return + } + if !astequal.Expr(x, y) { + c.warnBytes(expr, x, y) + } +} + +func (c *equalFoldChecker) checkStrings(expr *ast.BinaryExpr) { + if expr.Op != token.EQL && expr.Op != token.NEQ { + return + } + + x, ok1 := c.uncaseCall(expr.X, "strings.ToLower", "strings.ToUpper") + y, ok2 := c.uncaseCall(expr.Y, "strings.ToLower", "strings.ToUpper") + if !ok1 && !ok2 { + return + } + if !astequal.Expr(x, y) { + c.warnStrings(expr, x, y) + } +} + +func (c *equalFoldChecker) warnStrings(cause ast.Node, x, y ast.Expr) { + c.ctx.Warn(cause, "consider replacing with strings.EqualFold(%s, %s)", x, y) +} + +func (c *equalFoldChecker) warnBytes(cause ast.Node, x, y ast.Expr) { + c.ctx.Warn(cause, "consider replacing with bytes.EqualFold(%s, %s)", x, y) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/evalOrder_checker.go b/vendor/github.com/go-critic/go-critic/checkers/evalOrder_checker.go new file mode 100644 index 000000000..f76519cd7 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/evalOrder_checker.go @@ -0,0 +1,87 @@ +package checkers + +import ( + "go/ast" + "go/token" + "go/types" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "evalOrder" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects unwanted dependencies on the evaluation order" + info.Before = `return x, f(&x)` + info.After = ` +err := f(&x) +return x, err +` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&evalOrderChecker{ctx: ctx}) + }) +} + +type evalOrderChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *evalOrderChecker) VisitStmt(stmt ast.Stmt) { + ret := astcast.ToReturnStmt(stmt) + if len(ret.Results) < 2 { + return + } + + // TODO(quasilyte): handle selector expressions like o.val in addition + // to bare identifiers. + addrTake := &ast.UnaryExpr{Op: token.AND} + for _, res := range ret.Results { + id, ok := res.(*ast.Ident) + if !ok { + continue + } + addrTake.X = id // addrTake is &id now + for _, res := range ret.Results { + call, ok := res.(*ast.CallExpr) + if !ok { + continue + } + + // 1. Check if there is a call in form of id.method() where + // method takes id by a pointer. + if sel, ok := call.Fun.(*ast.SelectorExpr); ok { + if astequal.Node(sel.X, id) && c.hasPtrRecv(sel.Sel) { + c.warn(call) + } + } + + // 2. Check that there is no call that uses &id as an argument. + dependency := lintutil.ContainsNode(call, func(n ast.Node) bool { + return astequal.Node(addrTake, n) + }) + if dependency { + c.warn(call) + } + } + } +} + +func (c *evalOrderChecker) hasPtrRecv(fn *ast.Ident) bool { + sig, ok := c.ctx.TypesInfo.TypeOf(fn).(*types.Signature) + if !ok { + return false + } + return typep.IsPointer(sig.Recv().Type()) +} + +func (c *evalOrderChecker) warn(call *ast.CallExpr) { + c.ctx.Warn(call, "may want to evaluate %s before the return statement", call) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go b/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go new file mode 100644 index 000000000..05ed6ae9e --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go @@ -0,0 +1,78 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astfmt" + "github.com/go-toolsmith/astp" + "golang.org/x/tools/go/ast/astutil" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "exitAfterDefer" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects calls to exit/fatal inside functions that use defer" + info.Before = ` +defer os.Remove(filename) +if bad { + log.Fatalf("something bad happened") +}` + info.After = ` +defer os.Remove(filename) +if bad { + log.Printf("something bad happened") + return +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForFuncDecl(&exitAfterDeferChecker{ctx: ctx}) + }) +} + +type exitAfterDeferChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *exitAfterDeferChecker) VisitFuncDecl(fn *ast.FuncDecl) { + // TODO(Quasilyte): handle goto and other kinds of flow that break + // the algorithm below that expects the latter statement to be + // executed after the ones that come before it. + + var deferStmt *ast.DeferStmt + pre := func(cur *astutil.Cursor) bool { + // Don't recurse into local anonymous functions. + return !astp.IsFuncLit(cur.Node()) + } + post := func(cur *astutil.Cursor) bool { + switch n := cur.Node().(type) { + case *ast.DeferStmt: + deferStmt = n + case *ast.CallExpr: + if deferStmt != nil { + switch qualifiedName(n.Fun) { + case "log.Fatal", "log.Fatalf", "log.Fatalln", "os.Exit": + c.warn(n, deferStmt) + return false + } + } + } + return true + } + astutil.Apply(fn.Body, pre, post) +} + +func (c *exitAfterDeferChecker) warn(cause *ast.CallExpr, deferStmt *ast.DeferStmt) { + var s string + if fnlit, ok := deferStmt.Call.Fun.(*ast.FuncLit); ok { + // To avoid long and multi-line warning messages, + // collapse the function literals. + s = "defer " + astfmt.Sprint(fnlit.Type) + "{...}(...)" + } else { + s = astfmt.Sprint(deferStmt) + } + c.ctx.Warn(cause, "%s clutters `%s`", cause.Fun, s) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/flagDeref_checker.go b/vendor/github.com/go-critic/go-critic/checkers/flagDeref_checker.go new file mode 100644 index 000000000..cb9faee71 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/flagDeref_checker.go @@ -0,0 +1,65 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "flagDeref" + info.Tags = []string{"diagnostic"} + info.Summary = "Detects immediate dereferencing of `flag` package pointers" + info.Details = "Suggests to use pointer to array to avoid the copy using `&` on range expression." + info.Before = `b := *flag.Bool("b", false, "b docs")` + info.After = ` +var b bool +flag.BoolVar(&b, "b", false, "b docs")` + info.Note = ` +Dereferencing returned pointers will lead to hard to find errors +where flag values are not updated after flag.Parse().` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &flagDerefChecker{ + ctx: ctx, + flagPtrFuncs: map[string]bool{ + "flag.Bool": true, + "flag.Duration": true, + "flag.Float64": true, + "flag.Int": true, + "flag.Int64": true, + "flag.String": true, + "flag.Uint": true, + "flag.Uint64": true, + }, + } + return astwalk.WalkerForExpr(c) + }) +} + +type flagDerefChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + flagPtrFuncs map[string]bool +} + +func (c *flagDerefChecker) VisitExpr(expr ast.Expr) { + if expr, ok := expr.(*ast.StarExpr); ok { + call, ok := expr.X.(*ast.CallExpr) + if !ok { + return + } + called := qualifiedName(call.Fun) + if c.flagPtrFuncs[called] { + c.warn(expr, called+"Var") + } + } +} + +func (c *flagDerefChecker) warn(x ast.Node, suggestion string) { + c.ctx.Warn(x, "immediate deref in %s is most likely an error; consider using %s", + x, suggestion) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/flagName_checker.go b/vendor/github.com/go-critic/go-critic/checkers/flagName_checker.go new file mode 100644 index 000000000..1d43ba521 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/flagName_checker.go @@ -0,0 +1,68 @@ +package checkers + +import ( + "go/ast" + "go/constant" + "go/types" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "flagName" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects flag names with whitespace" + info.Before = `b := flag.Bool(" foo ", false, "description")` + info.After = `b := flag.Bool("foo", false, "description")` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&flagNameChecker{ctx: ctx}) + }) +} + +type flagNameChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *flagNameChecker) VisitExpr(expr ast.Expr) { + call := astcast.ToCallExpr(expr) + calledExpr := astcast.ToSelectorExpr(call.Fun) + obj, ok := c.ctx.TypesInfo.ObjectOf(astcast.ToIdent(calledExpr.X)).(*types.PkgName) + if !ok { + return + } + sym := calledExpr.Sel + pkg := obj.Imported() + if pkg.Path() != "flag" { + return + } + + switch sym.Name { + case "Bool", "Duration", "Float64", "String", + "Int", "Int64", "Uint", "Uint64": + c.checkFlagName(call, call.Args[0]) + case "BoolVar", "DurationVar", "Float64Var", "StringVar", + "IntVar", "Int64Var", "UintVar", "Uint64Var": + c.checkFlagName(call, call.Args[1]) + } +} + +func (c *flagNameChecker) checkFlagName(call *ast.CallExpr, arg ast.Expr) { + cv := c.ctx.TypesInfo.Types[arg].Value + if cv == nil { + return // Non-constant name + } + name := constant.StringVal(cv) + if strings.Contains(name, " ") { + c.warnWhitespace(call, name) + } +} + +func (c *flagNameChecker) warnWhitespace(cause ast.Node, name string) { + c.ctx.Warn(cause, "flag name %q contains whitespace", name) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/hexLiteral_checker.go b/vendor/github.com/go-critic/go-critic/checkers/hexLiteral_checker.go new file mode 100644 index 000000000..a700314cf --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/hexLiteral_checker.go @@ -0,0 +1,60 @@ +package checkers + +import ( + "go/ast" + "go/token" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "hexLiteral" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects hex literals that have mixed case letter digits" + info.Before = ` +x := 0X12 +y := 0xfF` + info.After = ` +x := 0x12 +// (A) +y := 0xff +// (B) +y := 0xFF` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&hexLiteralChecker{ctx: ctx}) + }) +} + +type hexLiteralChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *hexLiteralChecker) warn0X(lit *ast.BasicLit) { + suggest := "0x" + lit.Value[len("0X"):] + c.ctx.Warn(lit, "prefer 0x over 0X, s/%s/%s/", lit.Value, suggest) +} + +func (c *hexLiteralChecker) warnMixedDigits(lit *ast.BasicLit) { + c.ctx.Warn(lit, "don't mix hex literal letter digits casing") +} + +func (c *hexLiteralChecker) VisitExpr(expr ast.Expr) { + lit := astcast.ToBasicLit(expr) + if lit.Kind != token.INT || len(lit.Value) < 3 { + return + } + if strings.HasPrefix(lit.Value, "0X") { + c.warn0X(lit) + return + } + digits := lit.Value[len("0x"):] + if strings.ToLower(digits) != digits && strings.ToUpper(digits) != digits { + c.warnMixedDigits(lit) + } +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/hugeParam_checker.go b/vendor/github.com/go-critic/go-critic/checkers/hugeParam_checker.go new file mode 100644 index 000000000..656b4cc2d --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/hugeParam_checker.go @@ -0,0 +1,63 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "hugeParam" + info.Tags = []string{"performance"} + info.Params = lintpack.CheckerParams{ + "sizeThreshold": { + Value: 80, + Usage: "size in bytes that makes the warning trigger", + }, + } + info.Summary = "Detects params that incur excessive amount of copying" + info.Before = `func f(x [1024]int) {}` + info.After = `func f(x *[1024]int) {}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForFuncDecl(&hugeParamChecker{ + ctx: ctx, + sizeThreshold: int64(info.Params.Int("sizeThreshold")), + }) + }) +} + +type hugeParamChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + sizeThreshold int64 +} + +func (c *hugeParamChecker) VisitFuncDecl(decl *ast.FuncDecl) { + // TODO(quasilyte): maybe it's worthwhile to permit skipping + // test files for this checker? + if decl.Recv != nil { + c.checkParams(decl.Recv.List) + } + c.checkParams(decl.Type.Params.List) +} + +func (c *hugeParamChecker) checkParams(params []*ast.Field) { + for _, p := range params { + for _, id := range p.Names { + typ := c.ctx.TypesInfo.TypeOf(id) + size := c.ctx.SizesInfo.Sizeof(typ) + if size >= c.sizeThreshold { + c.warn(id, size) + } + } + } +} + +func (c *hugeParamChecker) warn(cause *ast.Ident, size int64) { + c.ctx.Warn(cause, "%s is heavy (%d bytes); consider passing it by pointer", + cause, size) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/ifElseChain_checker.go b/vendor/github.com/go-critic/go-critic/checkers/ifElseChain_checker.go new file mode 100644 index 000000000..c0a456afd --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/ifElseChain_checker.go @@ -0,0 +1,99 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "ifElseChain" + info.Tags = []string{"style"} + info.Summary = "Detects repeated if-else statements and suggests to replace them with switch statement" + info.Before = ` +if cond1 { + // Code A. +} else if cond2 { + // Code B. +} else { + // Code C. +}` + info.After = ` +switch { +case cond1: + // Code A. +case cond2: + // Code B. +default: + // Code C. +}` + info.Note = ` +Permits single else or else-if; repeated else-if or else + else-if +will trigger suggestion to use switch statement. +See [EffectiveGo#switch](https://golang.org/doc/effective_go.html#switch).` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&ifElseChainChecker{ctx: ctx}) + }) +} + +type ifElseChainChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + cause *ast.IfStmt + visited map[*ast.IfStmt]bool +} + +func (c *ifElseChainChecker) EnterFunc(fn *ast.FuncDecl) bool { + if fn.Body == nil { + return false + } + c.visited = make(map[*ast.IfStmt]bool) + return true +} + +func (c *ifElseChainChecker) VisitStmt(stmt ast.Stmt) { + if stmt, ok := stmt.(*ast.IfStmt); ok { + if c.visited[stmt] { + return + } + c.cause = stmt + c.checkIfStmt(stmt) + } +} + +func (c *ifElseChainChecker) checkIfStmt(stmt *ast.IfStmt) { + const minThreshold = 2 + if c.countIfelseLen(stmt) >= minThreshold { + c.warn() + } +} + +func (c *ifElseChainChecker) countIfelseLen(stmt *ast.IfStmt) int { + count := 0 + for { + switch e := stmt.Else.(type) { + case *ast.IfStmt: + if e.Init != nil { + return 0 // Give up + } + // Else if. + stmt = e + count++ + c.visited[e] = true + case *ast.BlockStmt: + // Else branch. + return count + 1 + default: + // No else or else if. + return count + } + } +} + +func (c *ifElseChainChecker) warn() { + c.ctx.Warn(c.cause, "rewrite if-else to switch statement") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/importShadow_checker.go b/vendor/github.com/go-critic/go-critic/checkers/importShadow_checker.go new file mode 100644 index 000000000..9a2ccc55e --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/importShadow_checker.go @@ -0,0 +1,47 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "importShadow" + info.Tags = []string{"style", "opinionated"} + info.Summary = "Detects when imported package names shadowed in the assignments" + info.Before = ` +// "path/filepath" is imported. +filepath := "foo.txt"` + info.After = ` +filename := "foo.txt"` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + ctx.Require.PkgObjects = true + return astwalk.WalkerForLocalDef(&importShadowChecker{ctx: ctx}, ctx.TypesInfo) + }) +} + +type importShadowChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *importShadowChecker) VisitLocalDef(def astwalk.Name, _ ast.Expr) { + for pkgObj, name := range c.ctx.PkgObjects { + if name == def.ID.Name && name != "_" { + c.warn(def.ID, name, pkgObj.Imported()) + } + } +} + +func (c *importShadowChecker) warn(id ast.Node, importedName string, pkg *types.Package) { + if isStdlibPkg(pkg) { + c.ctx.Warn(id, "shadow of imported package '%s'", importedName) + } else { + c.ctx.Warn(id, "shadow of imported from '%s' package '%s'", pkg.Path(), importedName) + } +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/indexAlloc_checker.go b/vendor/github.com/go-critic/go-critic/checkers/indexAlloc_checker.go new file mode 100644 index 000000000..8fbe98c9d --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/indexAlloc_checker.go @@ -0,0 +1,50 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "indexAlloc" + info.Tags = []string{"performance"} + info.Summary = "Detects strings.Index calls that may cause unwanted allocs" + info.Before = `strings.Index(string(x), y)` + info.After = `bytes.Index(x, []byte(y))` + info.Note = `See Go issue for details: https://github.com/golang/go/issues/25864` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&indexAllocChecker{ctx: ctx}) + }) +} + +type indexAllocChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *indexAllocChecker) VisitExpr(e ast.Expr) { + call := astcast.ToCallExpr(e) + if qualifiedName(call.Fun) != "strings.Index" { + return + } + stringConv := astcast.ToCallExpr(call.Args[0]) + if qualifiedName(stringConv.Fun) != "string" { + return + } + x := stringConv.Args[0] + y := call.Args[1] + if typep.SideEffectFree(c.ctx.TypesInfo, x) && typep.SideEffectFree(c.ctx.TypesInfo, y) { + c.warn(e, x, y) + } +} + +func (c *indexAllocChecker) warn(cause ast.Node, x, y ast.Expr) { + c.ctx.Warn(cause, "consider replacing %s with bytes.Index(%s, []byte(%s))", + cause, x, y) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/initClause_checker.go b/vendor/github.com/go-critic/go-critic/checkers/initClause_checker.go new file mode 100644 index 000000000..bfbd661b2 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/initClause_checker.go @@ -0,0 +1,56 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astp" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "initClause" + info.Tags = []string{"style", "opinionated", "experimental"} + info.Summary = "Detects non-assignment statements inside if/switch init clause" + info.Before = `if sideEffect(); cond { +}` + info.After = `sideEffect() +if cond { +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&initClauseChecker{ctx: ctx}) + }) +} + +type initClauseChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *initClauseChecker) VisitStmt(stmt ast.Stmt) { + initClause := c.getInitClause(stmt) + if initClause != nil && !astp.IsAssignStmt(initClause) { + c.warn(stmt, initClause) + } +} + +func (c *initClauseChecker) getInitClause(x ast.Stmt) ast.Stmt { + switch x := x.(type) { + case *ast.IfStmt: + return x.Init + case *ast.SwitchStmt: + return x.Init + default: + return nil + } +} + +func (c *initClauseChecker) warn(stmt, clause ast.Stmt) { + name := "if" + if astp.IsSwitchStmt(stmt) { + name = "switch" + } + c.ctx.Warn(stmt, "consider to move `%s` before %s", clause, name) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astfind.go b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astfind.go new file mode 100644 index 000000000..3c0a95afc --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astfind.go @@ -0,0 +1,27 @@ +package lintutil + +import ( + "go/ast" + + "golang.org/x/tools/go/ast/astutil" +) + +// FindNode applies pred for root and all it's childs until it returns true. +// Matched node is returned. +// If none of the nodes matched predicate, nil is returned. +func FindNode(root ast.Node, pred func(ast.Node) bool) ast.Node { + var found ast.Node + astutil.Apply(root, nil, func(cur *astutil.Cursor) bool { + if pred(cur.Node()) { + found = cur.Node() + return false + } + return true + }) + return found +} + +// ContainsNode reports whether `FindNode(root, pred)!=nil`. +func ContainsNode(root ast.Node, pred func(ast.Node) bool) bool { + return FindNode(root, pred) != nil +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astflow.go b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astflow.go new file mode 100644 index 000000000..63d181e5e --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astflow.go @@ -0,0 +1,86 @@ +package lintutil + +import ( + "go/ast" + "go/token" + "go/types" + + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/astp" + "github.com/go-toolsmith/typep" +) + +// Different utilities to make simple analysis over typed ast values flow. +// +// It's primitive and can't replace SSA, but the bright side is that +// it does not require building an additional IR eagerly. +// Expected to be used sparingly inside a few checkers. +// +// If proven really useful, can be moved to go-toolsmith library. + +// IsImmutable reports whether n can be midified through any operation. +func IsImmutable(info *types.Info, n ast.Expr) bool { + if astp.IsBasicLit(n) { + return true + } + tv, ok := info.Types[n] + return ok && !tv.Assignable() && !tv.Addressable() +} + +// CouldBeMutated reports whether dst can be modified inside body. +// +// Note that it does not take already existing pointers to dst. +// An example of safe and correct usage is checking of something +// that was just defined, so the dst is a result of that definition. +func CouldBeMutated(info *types.Info, body ast.Node, dst ast.Expr) bool { + if IsImmutable(info, dst) { // Fast path. + return false + } + + // We don't track pass-by-value. + // If it's already a pointer, passing it by value + // means that there can be a potential indirect modification. + // + // It's possible to be less conservative here and find at least + // one such value pass before giving up. + if typep.IsPointer(info.TypeOf(dst)) { + return true + } + + var isDst func(x ast.Expr) bool + if dst, ok := dst.(*ast.Ident); ok { + // Identifier can be shadowed, + // so we need to check the object as well. + obj := info.ObjectOf(dst) + if obj == nil { + return true // Being conservative + } + isDst = func(x ast.Expr) bool { + id, ok := x.(*ast.Ident) + return ok && id.Name == dst.Name && info.ObjectOf(id) == obj + } + } else { + isDst = func(x ast.Expr) bool { + return astequal.Expr(dst, x) + } + } + + return ContainsNode(body, func(n ast.Node) bool { + switch n := n.(type) { + case *ast.UnaryExpr: + if n.Op == token.AND && isDst(n.X) { + return true // Address taken + } + case *ast.AssignStmt: + for _, lhs := range n.Lhs { + if isDst(lhs) { + return true + } + } + case *ast.IncDecStmt: + // Incremented or decremented. + return isDst(n.X) + } + return false + }) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astset.go b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astset.go new file mode 100644 index 000000000..ebe7835e5 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astset.go @@ -0,0 +1,44 @@ +package lintutil + +import ( + "go/ast" + + "github.com/go-toolsmith/astequal" +) + +// AstSet is a simple ast.Node set. +// Zero value is ready to use set. +// Can be reused after Clear call. +type AstSet struct { + items []ast.Node +} + +// Contains reports whether s contains x. +func (s *AstSet) Contains(x ast.Node) bool { + for i := range s.items { + if astequal.Node(s.items[i], x) { + return true + } + } + return false +} + +// Insert pushes x in s if it's not already there. +// Returns true if element was inserted. +func (s *AstSet) Insert(x ast.Node) bool { + if s.Contains(x) { + return false + } + s.items = append(s.items, x) + return true +} + +// Clear removes all element from set. +func (s *AstSet) Clear() { + s.items = s.items[:0] +} + +// Len returns the number of elements contained inside s. +func (s *AstSet) Len() int { + return len(s.items) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/zero_value.go b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/zero_value.go new file mode 100644 index 000000000..4370f5818 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/zero_value.go @@ -0,0 +1,94 @@ +package lintutil + +import ( + "go/ast" + "go/constant" + "go/token" + "go/types" +) + +// IsZeroValue reports whether x represents zero value of its type. +// +// The functions is conservative and may return false for zero values +// if some cases are not handled in a comprehensive way +// but is should never return true for something that's not a proper zv. +func IsZeroValue(info *types.Info, x ast.Expr) bool { + switch x := x.(type) { + case *ast.BasicLit: + typ := info.TypeOf(x).Underlying().(*types.Basic) + v := info.Types[x].Value + var z constant.Value + switch { + case typ.Kind() == types.String: + z = constant.MakeString("") + case typ.Info()&types.IsInteger != 0: + z = constant.MakeInt64(0) + case typ.Info()&types.IsUnsigned != 0: + z = constant.MakeUint64(0) + case typ.Info()&types.IsFloat != 0: + z = constant.MakeFloat64(0) + default: + return false + } + return constant.Compare(v, token.EQL, z) + + case *ast.CompositeLit: + return len(x.Elts) == 0 + + default: + // Note that this function is not comprehensive. + return false + } +} + +// ZeroValueOf returns a zero value expression for typeExpr of type typ. +// If function can't find such a value, nil is returned. +func ZeroValueOf(typeExpr ast.Expr, typ types.Type) ast.Expr { + switch utyp := typ.Underlying().(type) { + case *types.Basic: + info := utyp.Info() + var zv ast.Expr + switch { + case info&types.IsInteger != 0: + zv = &ast.BasicLit{Kind: token.INT, Value: "0"} + case info&types.IsFloat != 0: + zv = &ast.BasicLit{Kind: token.FLOAT, Value: "0.0"} + case info&types.IsString != 0: + zv = &ast.BasicLit{Kind: token.STRING, Value: `""`} + case info&types.IsBoolean != 0: + zv = &ast.Ident{Name: "false"} + } + if isDefaultLiteralType(typ) { + return zv + } + return &ast.CallExpr{ + Fun: typeExpr, + Args: []ast.Expr{zv}, + } + + case *types.Slice, *types.Map, *types.Pointer, *types.Interface: + return &ast.CallExpr{ + Fun: typeExpr, + Args: []ast.Expr{&ast.Ident{Name: "nil"}}, + } + + case *types.Array, *types.Struct: + return &ast.CompositeLit{Type: typeExpr} + + default: + return nil + } +} + +func isDefaultLiteralType(typ types.Type) bool { + btyp, ok := typ.(*types.Basic) + if !ok { + return false + } + switch btyp.Kind() { + case types.Bool, types.Int, types.Float64, types.String: + return true + default: + return false + } +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/mapKey_checker.go b/vendor/github.com/go-critic/go-critic/checkers/mapKey_checker.go new file mode 100644 index 000000000..de3e781e5 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/mapKey_checker.go @@ -0,0 +1,124 @@ +package checkers + +import ( + "go/ast" + "go/types" + "strings" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astp" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "mapKey" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects suspicious map literal keys" + info.Before = ` +_ = map[string]int{ + "foo": 1, + "bar ": 2, +}` + info.After = ` +_ = map[string]int{ + "foo": 1, + "bar": 2, +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&mapKeyChecker{ctx: ctx}) + }) +} + +type mapKeyChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + astSet lintutil.AstSet +} + +func (c *mapKeyChecker) VisitExpr(expr ast.Expr) { + lit := astcast.ToCompositeLit(expr) + if len(lit.Elts) < 2 { + return + } + + typ, ok := c.ctx.TypesInfo.TypeOf(lit).Underlying().(*types.Map) + if !ok { + return + } + if !typep.HasStringKind(typ.Key().Underlying()) { + return + } + + c.checkWhitespace(lit) + c.checkDuplicates(lit) +} + +func (c *mapKeyChecker) checkDuplicates(lit *ast.CompositeLit) { + c.astSet.Clear() + + for _, elt := range lit.Elts { + kv := astcast.ToKeyValueExpr(elt) + if astp.IsBasicLit(kv.Key) { + // Basic lits are handled by the compiler. + continue + } + if !typep.SideEffectFree(c.ctx.TypesInfo, kv.Key) { + continue + } + if !c.astSet.Insert(kv.Key) { + c.warnDupKey(kv.Key) + } + } +} + +func (c *mapKeyChecker) checkWhitespace(lit *ast.CompositeLit) { + var whitespaceKey ast.Node + for _, elt := range lit.Elts { + key := astcast.ToBasicLit(astcast.ToKeyValueExpr(elt).Key) + if len(key.Value) < len(`" "`) { + continue + } + // s is unquoted string literal value. + s := key.Value[len(`"`) : len(key.Value)-len(`"`)] + if !strings.Contains(s, " ") { + continue + } + if whitespaceKey != nil { + // Already seen something with a whitespace. + // More than one entry => not suspicious. + return + } + if s == " " { + // If space is used as a key, maybe this map + // has something to do with spaces. Give up. + return + } + // Check if it has exactly 1 space prefix or suffix. + bad := strings.HasPrefix(s, " ") && !strings.HasPrefix(s, " ") || + strings.HasSuffix(s, " ") && !strings.HasSuffix(s, " ") + if !bad { + // These spaces can be a padding, + // or a legitimate part of a key. Give up. + return + } + whitespaceKey = key + } + + if whitespaceKey != nil { + c.warnWhitespace(whitespaceKey) + } +} + +func (c *mapKeyChecker) warnWhitespace(key ast.Node) { + c.ctx.Warn(key, "suspucious whitespace in %s key", key) +} + +func (c *mapKeyChecker) warnDupKey(key ast.Node) { + c.ctx.Warn(key, "suspicious duplicate %s key", key) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/methodExprCall_checker.go b/vendor/github.com/go-critic/go-critic/checkers/methodExprCall_checker.go new file mode 100644 index 000000000..60da11655 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/methodExprCall_checker.go @@ -0,0 +1,57 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "methodExprCall" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects method expression call that can be replaced with a method call" + info.Before = `f := foo{} +foo.bar(f)` + info.After = `f := foo{} +f.bar()` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&methodExprCallChecker{ctx: ctx}) + }) +} + +type methodExprCallChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *methodExprCallChecker) VisitExpr(x ast.Expr) { + call := astcast.ToCallExpr(x) + s := astcast.ToSelectorExpr(call.Fun) + + if len(call.Args) < 1 || astcast.ToIdent(call.Args[0]).Name == "nil" { + return + } + + if typep.IsTypeExpr(c.ctx.TypesInfo, s.X) { + c.warn(call, s) + } +} + +func (c *methodExprCallChecker) warn(cause *ast.CallExpr, s *ast.SelectorExpr) { + selector := astcopy.SelectorExpr(s) + selector.X = cause.Args[0] + + // Remove "&" from the receiver (if any). + if u, ok := selector.X.(*ast.UnaryExpr); ok && u.Op == token.AND { + selector.X = u.X + } + + c.ctx.Warn(cause, "consider to change `%s` to `%s`", cause.Fun, selector) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/nestingReduce_checker.go b/vendor/github.com/go-critic/go-critic/checkers/nestingReduce_checker.go new file mode 100644 index 000000000..4a0331d5c --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/nestingReduce_checker.go @@ -0,0 +1,73 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "nestingReduce" + info.Tags = []string{"style", "opinionated", "experimental"} + info.Params = lintpack.CheckerParams{ + "bodyWidth": { + Value: 5, + Usage: "min number of statements inside a branch to trigger a warning", + }, + } + info.Summary = "Finds where nesting level could be reduced" + info.Before = ` +for _, v := range a { + if v.Bool { + body() + } +}` + info.After = ` +for _, v := range a { + if !v.Bool { + continue + } + body() +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &nestingReduceChecker{ctx: ctx} + c.bodyWidth = info.Params.Int("bodyWidth") + return astwalk.WalkerForStmt(c) + }) +} + +type nestingReduceChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + bodyWidth int +} + +func (c *nestingReduceChecker) VisitStmt(stmt ast.Stmt) { + switch stmt := stmt.(type) { + case *ast.ForStmt: + c.checkLoopBody(stmt.Body.List) + case *ast.RangeStmt: + c.checkLoopBody(stmt.Body.List) + } +} + +func (c *nestingReduceChecker) checkLoopBody(body []ast.Stmt) { + if len(body) != 1 { + return + } + stmt, ok := body[0].(*ast.IfStmt) + if !ok { + return + } + if len(stmt.Body.List) >= c.bodyWidth && stmt.Else == nil { + c.warnLoop(stmt) + } +} + +func (c *nestingReduceChecker) warnLoop(cause ast.Node) { + c.ctx.Warn(cause, "invert if cond, replace body with `continue`, move old body after the statement") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/newDeref_checker.go b/vendor/github.com/go-critic/go-critic/checkers/newDeref_checker.go new file mode 100644 index 000000000..75e7f6428 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/newDeref_checker.go @@ -0,0 +1,45 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "golang.org/x/tools/go/ast/astutil" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "newDeref" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects immediate dereferencing of `new` expressions" + info.Before = `x := *new(bool)` + info.After = `x := false` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&newDerefChecker{ctx: ctx}) + }) +} + +type newDerefChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *newDerefChecker) VisitExpr(expr ast.Expr) { + deref := astcast.ToStarExpr(expr) + call := astcast.ToCallExpr(deref.X) + if astcast.ToIdent(call.Fun).Name == "new" { + typ := c.ctx.TypesInfo.TypeOf(call.Args[0]) + zv := lintutil.ZeroValueOf(astutil.Unparen(call.Args[0]), typ) + if zv != nil { + c.warn(expr, zv) + } + } +} + +func (c *newDerefChecker) warn(cause, suggestion ast.Expr) { + c.ctx.Warn(cause, "replace `%s` with `%s`", cause, suggestion) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/nilValReturn_checker.go b/vendor/github.com/go-critic/go-critic/checkers/nilValReturn_checker.go new file mode 100644 index 000000000..231e25800 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/nilValReturn_checker.go @@ -0,0 +1,64 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "nilValReturn" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects return statements those results evaluate to nil" + info.Before = ` +if err == nil { + return err +}` + info.After = ` +// (A) - return nil explicitly +if err == nil { + return nil +} +// (B) - typo in "==", change to "!=" +if err != nil { + return err +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&nilValReturnChecker{ctx: ctx}) + }) +} + +type nilValReturnChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *nilValReturnChecker) VisitStmt(stmt ast.Stmt) { + ifStmt, ok := stmt.(*ast.IfStmt) + if !ok || len(ifStmt.Body.List) != 1 { + return + } + ret, ok := ifStmt.Body.List[0].(*ast.ReturnStmt) + if !ok || len(ret.Results) != 1 { + return + } + expr, ok := ifStmt.Cond.(*ast.BinaryExpr) + cond := ok && + expr.Op == token.EQL && + typep.SideEffectFree(c.ctx.TypesInfo, expr.X) && + qualifiedName(expr.Y) == "nil" && + astequal.Expr(expr.X, ret.Results[0]) + if cond { + c.warn(ret, expr.X) + } +} + +func (c *nilValReturnChecker) warn(cause, val ast.Node) { + c.ctx.Warn(cause, "returned expr is always nil; replace %s with nil", val) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go b/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go new file mode 100644 index 000000000..e40ec6db5 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go @@ -0,0 +1,82 @@ +package checkers + +import ( + "go/ast" + "go/token" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "octalLiteral" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects octal literals passed to functions" + info.Before = `foo(02)` + info.After = `foo(2)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &octalLiteralChecker{ + ctx: ctx, + octFriendlyPkg: map[string]bool{ + "os": true, + "io/ioutil": true, + }, + } + return astwalk.WalkerForExpr(c) + }) +} + +type octalLiteralChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + octFriendlyPkg map[string]bool +} + +func (c *octalLiteralChecker) VisitExpr(expr ast.Expr) { + call := astcast.ToCallExpr(expr) + calledExpr := astcast.ToSelectorExpr(call.Fun) + ident := astcast.ToIdent(calledExpr.X) + + if obj, ok := c.ctx.TypesInfo.ObjectOf(ident).(*types.PkgName); ok { + pkg := obj.Imported() + if c.octFriendlyPkg[pkg.Path()] { + return + } + } + + for _, arg := range call.Args { + if lit := astcast.ToBasicLit(c.unsign(arg)); len(lit.Value) > 1 && + c.isIntLiteral(lit) && + c.isOctalLiteral(lit) { + c.warn(call) + return + } + } +} + +func (c *octalLiteralChecker) unsign(e ast.Expr) ast.Expr { + u, ok := e.(*ast.UnaryExpr) + if !ok { + return e + } + return u.X +} + +func (c *octalLiteralChecker) isIntLiteral(lit *ast.BasicLit) bool { + return lit.Kind == token.INT +} + +func (c *octalLiteralChecker) isOctalLiteral(lit *ast.BasicLit) bool { + return lit.Value[0] == '0' && + lit.Value[1] != 'x' && + lit.Value[1] != 'X' +} + +func (c *octalLiteralChecker) warn(expr ast.Expr) { + c.ctx.Warn(expr, "suspicious octal args in `%s`", expr) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/offBy1_checker.go b/vendor/github.com/go-critic/go-critic/checkers/offBy1_checker.go new file mode 100644 index 000000000..d5c8de0b7 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/offBy1_checker.go @@ -0,0 +1,66 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "offBy1" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects various off-by-one kind of errors" + info.Before = `xs[len(xs)]` + info.After = `xs[len(xs)-1]` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&offBy1Checker{ctx: ctx}) + }) +} + +type offBy1Checker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *offBy1Checker) VisitExpr(e ast.Expr) { + // TODO(Quasilyte): handle more off-by-1 patterns. + // TODO(Quasilyte): check whether go/analysis can help here. + + // Detect s[len(s)] expressions that always panic. + // The correct form is s[len(s)-1]. + + indexExpr := astcast.ToIndexExpr(e) + indexed := indexExpr.X + if !typep.IsSlice(c.ctx.TypesInfo.TypeOf(indexed)) { + return + } + if !typep.SideEffectFree(c.ctx.TypesInfo, indexed) { + return + } + call := astcast.ToCallExpr(indexExpr.Index) + if astcast.ToIdent(call.Fun).Name != "len" { + return + } + if len(call.Args) != 1 || !astequal.Expr(call.Args[0], indexed) { + return + } + c.warnLenIndex(indexExpr) +} + +func (c *offBy1Checker) warnLenIndex(cause *ast.IndexExpr) { + suggest := astcopy.IndexExpr(cause) + suggest.Index = &ast.BinaryExpr{ + Op: token.SUB, + X: cause.Index, + Y: &ast.BasicLit{Value: "1"}, + } + c.ctx.Warn(cause, "index expr always panics; maybe you wanted %s?", suggest) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/paramTypeCombine_checker.go b/vendor/github.com/go-critic/go-critic/checkers/paramTypeCombine_checker.go new file mode 100644 index 000000000..ffa74061e --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/paramTypeCombine_checker.go @@ -0,0 +1,86 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astequal" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "paramTypeCombine" + info.Tags = []string{"style", "opinionated"} + info.Summary = "Detects if function parameters could be combined by type and suggest the way to do it" + info.Before = `func foo(a, b int, c, d int, e, f int, g int) {}` + info.After = `func foo(a, b, c, d, e, f, g int) {}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForFuncDecl(¶mTypeCombineChecker{ctx: ctx}) + }) +} + +type paramTypeCombineChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *paramTypeCombineChecker) EnterFunc(*ast.FuncDecl) bool { + return true +} + +func (c *paramTypeCombineChecker) VisitFuncDecl(decl *ast.FuncDecl) { + typ := c.optimizeFuncType(decl.Type) + if !astequal.Expr(typ, decl.Type) { + c.warn(decl.Type, typ) + } +} + +func (c *paramTypeCombineChecker) optimizeFuncType(f *ast.FuncType) *ast.FuncType { + return &ast.FuncType{ + Params: c.optimizeParams(f.Params), + Results: c.optimizeParams(f.Results), + } +} +func (c *paramTypeCombineChecker) optimizeParams(params *ast.FieldList) *ast.FieldList { + // To avoid false positives, skip unnamed param lists. + // + // We're using a property that Go only permits unnamed params + // for the whole list, so it's enough to check whether any of + // ast.Field have empty name list. + skip := params == nil || + len(params.List) < 2 || + len(params.List[0].Names) == 0 + if skip { + return params + } + + list := []*ast.Field{} + names := make([]*ast.Ident, len(params.List[0].Names)) + copy(names, params.List[0].Names) + list = append(list, &ast.Field{ + Names: names, + Type: params.List[0].Type, + }) + for i, p := range params.List[1:] { + names = make([]*ast.Ident, len(p.Names)) + copy(names, p.Names) + if astequal.Expr(p.Type, params.List[i].Type) { + list[len(list)-1].Names = + append(list[len(list)-1].Names, names...) + } else { + list = append(list, &ast.Field{ + Names: names, + Type: params.List[i+1].Type, + }) + } + } + return &ast.FieldList{ + List: list, + } +} + +func (c *paramTypeCombineChecker) warn(f1, f2 *ast.FuncType) { + c.ctx.Warn(f1, "%s could be replaced with %s", f1, f2) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/ptrToRefParam_checker.go b/vendor/github.com/go-critic/go-critic/checkers/ptrToRefParam_checker.go new file mode 100644 index 000000000..dacffc85a --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/ptrToRefParam_checker.go @@ -0,0 +1,70 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "ptrToRefParam" + info.Tags = []string{"style", "opinionated", "experimental"} + info.Summary = "Detects input and output parameters that have a type of pointer to referential type" + info.Before = `func f(m *map[string]int) (*chan *int)` + info.After = `func f(m map[string]int) (chan *int)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForFuncDecl(&ptrToRefParamChecker{ctx: ctx}) + }) +} + +type ptrToRefParamChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *ptrToRefParamChecker) VisitFuncDecl(fn *ast.FuncDecl) { + c.checkParams(fn.Type.Params.List) + if fn.Type.Results != nil { + c.checkParams(fn.Type.Results.List) + } +} + +func (c *ptrToRefParamChecker) checkParams(params []*ast.Field) { + for _, param := range params { + ptr, ok := c.ctx.TypesInfo.TypeOf(param.Type).(*types.Pointer) + if !ok { + continue + } + + if c.isRefType(ptr.Elem()) { + if len(param.Names) == 0 { + c.ctx.Warn(param, "consider to make non-pointer type for `%s`", param.Type) + } else { + for i := range param.Names { + c.warn(param.Names[i]) + } + } + } + } +} + +func (c *ptrToRefParamChecker) isRefType(x types.Type) bool { + switch typ := x.(type) { + case *types.Map, *types.Chan, *types.Interface: + return true + case *types.Named: + // Handle underlying type only for interfaces. + if _, ok := typ.Underlying().(*types.Interface); ok { + return true + } + } + return false +} + +func (c *ptrToRefParamChecker) warn(id *ast.Ident) { + c.ctx.Warn(id, "consider `%s' to be of non-pointer type", id) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/rangeExprCopy_checker.go b/vendor/github.com/go-critic/go-critic/checkers/rangeExprCopy_checker.go new file mode 100644 index 000000000..387d1bbbc --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/rangeExprCopy_checker.go @@ -0,0 +1,80 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "rangeExprCopy" + info.Tags = []string{"performance"} + info.Params = lintpack.CheckerParams{ + "sizeThreshold": { + Value: 512, + Usage: "size in bytes that makes the warning trigger", + }, + "skipTestFuncs": { + Value: true, + Usage: "whether to check test functions", + }, + } + info.Summary = "Detects expensive copies of `for` loop range expressions" + info.Details = "Suggests to use pointer to array to avoid the copy using `&` on range expression." + info.Before = ` +var xs [2048]byte +for _, x := range xs { // Copies 2048 bytes + // Loop body. +}` + info.After = ` +var xs [2048]byte +for _, x := range &xs { // No copy + // Loop body. +}` + info.Note = "See Go issue for details: https://github.com/golang/go/issues/15812." + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &rangeExprCopyChecker{ctx: ctx} + c.sizeThreshold = int64(info.Params.Int("sizeThreshold")) + c.skipTestFuncs = info.Params.Bool("skipTestFuncs") + return astwalk.WalkerForStmt(c) + }) +} + +type rangeExprCopyChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + sizeThreshold int64 + skipTestFuncs bool +} + +func (c *rangeExprCopyChecker) EnterFunc(fn *ast.FuncDecl) bool { + return fn.Body != nil && + !(c.skipTestFuncs && isUnitTestFunc(c.ctx, fn)) +} + +func (c *rangeExprCopyChecker) VisitStmt(stmt ast.Stmt) { + rng, ok := stmt.(*ast.RangeStmt) + if !ok || rng.Key == nil || rng.Value == nil { + return + } + tv := c.ctx.TypesInfo.Types[rng.X] + if !tv.Addressable() { + return + } + if _, ok := tv.Type.(*types.Array); !ok { + return + } + if size := c.ctx.SizesInfo.Sizeof(tv.Type); size >= c.sizeThreshold { + c.warn(rng, size) + } +} + +func (c *rangeExprCopyChecker) warn(rng *ast.RangeStmt, size int64) { + c.ctx.Warn(rng, "copy of %s (%d bytes) can be avoided with &%s", + rng.X, size, rng.X) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/rangeValCopy_checker.go b/vendor/github.com/go-critic/go-critic/checkers/rangeValCopy_checker.go new file mode 100644 index 000000000..182538a9f --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/rangeValCopy_checker.go @@ -0,0 +1,75 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "rangeValCopy" + info.Tags = []string{"performance"} + info.Params = lintpack.CheckerParams{ + "sizeThreshold": { + Value: 128, + Usage: "size in bytes that makes the warning trigger", + }, + "skipTestFuncs": { + Value: true, + Usage: "whether to check test functions", + }, + } + info.Summary = "Detects loops that copy big objects during each iteration" + info.Details = "Suggests to use index access or take address and make use pointer instead." + info.Before = ` +xs := make([][1024]byte, length) +for _, x := range xs { + // Loop body. +}` + info.After = ` +xs := make([][1024]byte, length) +for i := range xs { + x := &xs[i] + // Loop body. +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &rangeValCopyChecker{ctx: ctx} + c.sizeThreshold = int64(info.Params.Int("sizeThreshold")) + c.skipTestFuncs = info.Params.Bool("skipTestFuncs") + return astwalk.WalkerForStmt(c) + }) +} + +type rangeValCopyChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + sizeThreshold int64 + skipTestFuncs bool +} + +func (c *rangeValCopyChecker) EnterFunc(fn *ast.FuncDecl) bool { + return fn.Body != nil && + !(c.skipTestFuncs && isUnitTestFunc(c.ctx, fn)) +} + +func (c *rangeValCopyChecker) VisitStmt(stmt ast.Stmt) { + rng, ok := stmt.(*ast.RangeStmt) + if !ok || rng.Value == nil { + return + } + typ := c.ctx.TypesInfo.TypeOf(rng.Value) + if typ == nil { + return + } + if size := c.ctx.SizesInfo.Sizeof(typ); size >= c.sizeThreshold { + c.warn(rng, size) + } +} + +func (c *rangeValCopyChecker) warn(n ast.Node, size int64) { + c.ctx.Warn(n, "each iteration copies %d bytes (consider pointers or indexing)", size) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/regexpMust_checker.go b/vendor/github.com/go-critic/go-critic/checkers/regexpMust_checker.go new file mode 100644 index 000000000..ef7a39787 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/regexpMust_checker.go @@ -0,0 +1,47 @@ +package checkers + +import ( + "go/ast" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astp" + "golang.org/x/tools/go/ast/astutil" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "regexpMust" + info.Tags = []string{"style"} + info.Summary = "Detects `regexp.Compile*` that can be replaced with `regexp.MustCompile*`" + info.Before = `re, _ := regexp.Compile("const pattern")` + info.After = `re := regexp.MustCompile("const pattern")` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(®expMustChecker{ctx: ctx}) + }) +} + +type regexpMustChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *regexpMustChecker) VisitExpr(x ast.Expr) { + if x, ok := x.(*ast.CallExpr); ok { + switch name := qualifiedName(x.Fun); name { + case "regexp.Compile", "regexp.CompilePOSIX": + // Only check for trivial string args, permit parenthesis. + if !astp.IsBasicLit(astutil.Unparen(x.Args[0])) { + return + } + c.warn(x, strings.Replace(name, "Compile", "MustCompile", 1)) + } + } +} + +func (c *regexpMustChecker) warn(cause *ast.CallExpr, suggestion string) { + c.ctx.Warn(cause, "for const patterns like %s, use %s", + cause.Args[0], suggestion) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/regexpPattern_checker.go b/vendor/github.com/go-critic/go-critic/checkers/regexpPattern_checker.go new file mode 100644 index 000000000..383deb5d4 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/regexpPattern_checker.go @@ -0,0 +1,68 @@ +package checkers + +import ( + "go/ast" + "go/constant" + "regexp" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "regexpPattern" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects suspicious regexp patterns" + info.Before = "regexp.MustCompile(`google.com|yandex.ru`)" + info.After = "regexp.MustCompile(`google\\.com|yandex\\.ru`)" + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + domains := []string{ + "com", + "org", + "info", + "net", + "ru", + "de", + } + + allDomains := strings.Join(domains, "|") + domainRE := regexp.MustCompile(`[^\\]\.(` + allDomains + `)\b`) + return astwalk.WalkerForExpr(®expPatternChecker{ + ctx: ctx, + domainRE: domainRE, + }) + }) +} + +type regexpPatternChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + domainRE *regexp.Regexp +} + +func (c *regexpPatternChecker) VisitExpr(x ast.Expr) { + call, ok := x.(*ast.CallExpr) + if !ok { + return + } + + switch qualifiedName(call.Fun) { + case "regexp.Compile", "regexp.CompilePOSIX", "regexp.MustCompile", "regexp.MustCompilePosix": + cv := c.ctx.TypesInfo.Types[call.Args[0]].Value + if cv == nil || cv.Kind() != constant.String { + return + } + s := constant.StringVal(cv) + if m := c.domainRE.FindStringSubmatch(s); m != nil { + c.warnDomain(call.Args[0], m[1]) + } + } +} + +func (c *regexpPatternChecker) warnDomain(cause ast.Expr, domain string) { + c.ctx.Warn(cause, "'.%s' should probably be '\\.%s'", domain, domain) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/singleCaseSwitch_checker.go b/vendor/github.com/go-critic/go-critic/checkers/singleCaseSwitch_checker.go new file mode 100644 index 000000000..6cdb06aef --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/singleCaseSwitch_checker.go @@ -0,0 +1,61 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "singleCaseSwitch" + info.Tags = []string{"style"} + info.Summary = "Detects switch statements that could be better written as if statement" + info.Before = ` +switch x := x.(type) { +case int: + body() +}` + info.After = ` +if x, ok := x.(int); ok { + body() +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&singleCaseSwitchChecker{ctx: ctx}) + }) +} + +type singleCaseSwitchChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *singleCaseSwitchChecker) VisitStmt(stmt ast.Stmt) { + switch stmt := stmt.(type) { + case *ast.SwitchStmt: + c.checkSwitchStmt(stmt, stmt.Body) + case *ast.TypeSwitchStmt: + c.checkSwitchStmt(stmt, stmt.Body) + } +} + +func (c *singleCaseSwitchChecker) checkSwitchStmt(stmt ast.Stmt, body *ast.BlockStmt) { + if len(body.List) == 1 { + if body.List[0].(*ast.CaseClause).List == nil { + // default case. + c.warnDefault(stmt) + } else if len(body.List[0].(*ast.CaseClause).List) == 1 { + c.warn(stmt) + } + } +} + +func (c *singleCaseSwitchChecker) warn(stmt ast.Stmt) { + c.ctx.Warn(stmt, "should rewrite switch statement to if statement") +} + +func (c *singleCaseSwitchChecker) warnDefault(stmt ast.Stmt) { + c.ctx.Warn(stmt, "found switch with default case only") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/sloppyLen_checker.go b/vendor/github.com/go-critic/go-critic/checkers/sloppyLen_checker.go new file mode 100644 index 000000000..45123ec6b --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/sloppyLen_checker.go @@ -0,0 +1,72 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astfmt" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "sloppyLen" + info.Tags = []string{"style"} + info.Summary = "Detects usage of `len` when result is obvious or doesn't make sense" + info.Before = ` +len(arr) >= 0 // Sloppy +len(arr) <= 0 // Sloppy +len(arr) < 0 // Doesn't make sense at all` + info.After = ` +len(arr) > 0 +len(arr) == 0` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&sloppyLenChecker{ctx: ctx}) + }) +} + +type sloppyLenChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *sloppyLenChecker) VisitExpr(x ast.Expr) { + expr, ok := x.(*ast.BinaryExpr) + if !ok { + return + } + + if expr.Op == token.LSS || expr.Op == token.GEQ || expr.Op == token.LEQ { + if c.isLenCall(expr.X) && c.isZero(expr.Y) { + c.warn(expr) + } + } +} + +func (c *sloppyLenChecker) isLenCall(x ast.Expr) bool { + call, ok := x.(*ast.CallExpr) + return ok && qualifiedName(call.Fun) == "len" && len(call.Args) == 1 +} + +func (c *sloppyLenChecker) isZero(x ast.Expr) bool { + value, ok := x.(*ast.BasicLit) + return ok && value.Value == "0" +} + +func (c *sloppyLenChecker) warn(cause *ast.BinaryExpr) { + info := "" + switch cause.Op { + case token.LSS: + info = "is always false" + case token.GEQ: + info = "is always true" + case token.LEQ: + expr := astcopy.BinaryExpr(cause) + expr.Op = token.EQL + info = astfmt.Sprintf("can be %s", expr) + } + c.ctx.Warn(cause, "%s %s", cause, info) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/sloppyReassign_checker.go b/vendor/github.com/go-critic/go-critic/checkers/sloppyReassign_checker.go new file mode 100644 index 000000000..1a7c19877 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/sloppyReassign_checker.go @@ -0,0 +1,80 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astequal" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "sloppyReassign" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects suspicious/confusing re-assignments" + info.Before = `if err = f(); err != nil { return err }` + info.After = `if err := f(); err != nil { return err }` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&sloppyReassignChecker{ctx: ctx}) + }) +} + +type sloppyReassignChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *sloppyReassignChecker) VisitStmt(stmt ast.Stmt) { + // Right now only check assignments in if statements init. + ifStmt := astcast.ToIfStmt(stmt) + assign := astcast.ToAssignStmt(ifStmt.Init) + if assign.Tok != token.ASSIGN { + return + } + + // TODO(Quasilyte): is handling of multi-value assignments worthwhile? + if len(assign.Lhs) != 1 || len(assign.Rhs) != 1 { + return + } + + // TODO(Quasilyte): handle not only the simplest, return-only case. + body := ifStmt.Body.List + if len(body) != 1 { + return + } + + // Variable that is being re-assigned. + reAssigned := astcast.ToIdent(assign.Lhs[0]) + if reAssigned.Name == "" { + return + } + + // TODO(Quasilyte): handle not only nil comparisons. + eqToNil := &ast.BinaryExpr{ + Op: token.NEQ, + X: reAssigned, + Y: &ast.Ident{Name: "nil"}, + } + if !astequal.Expr(ifStmt.Cond, eqToNil) { + return + } + + results := astcast.ToReturnStmt(body[0]).Results + for _, res := range results { + if astequal.Expr(reAssigned, res) { + c.warnAssignToDefine(assign, reAssigned.Name) + break + } + } +} + +func (c *sloppyReassignChecker) warnAssignToDefine(assign *ast.AssignStmt, name string) { + suggest := astcopy.AssignStmt(assign) + suggest.Tok = token.DEFINE + c.ctx.Warn(assign, "re-assignment to `%s` can be replaced with `%s`", name, suggest) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/stringXbytes_checker.go b/vendor/github.com/go-critic/go-critic/checkers/stringXbytes_checker.go new file mode 100644 index 000000000..74570108e --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/stringXbytes_checker.go @@ -0,0 +1,47 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/typep" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "stringXbytes" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects redundant conversions between string and []byte" + info.Before = `copy(b, []byte(s))` + info.After = `copy(b, s)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&stringXbytes{ctx: ctx}) + }) +} + +type stringXbytes struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *stringXbytes) VisitExpr(expr ast.Expr) { + x, ok := expr.(*ast.CallExpr) + if !ok || qualifiedName(x.Fun) != "copy" { + return + } + + src := x.Args[1] + + byteCast, ok := src.(*ast.CallExpr) + if ok && typep.IsTypeExpr(c.ctx.TypesInfo, byteCast.Fun) && + typep.HasStringProp(c.ctx.TypesInfo.TypeOf(byteCast.Args[0])) { + + c.warn(byteCast, byteCast.Args[0]) + } +} + +func (c *stringXbytes) warn(cause *ast.CallExpr, suggestion ast.Expr) { + c.ctx.Warn(cause, "can simplify `%s` to `%s`", cause, suggestion) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/switchTrue_checker.go b/vendor/github.com/go-critic/go-critic/checkers/switchTrue_checker.go new file mode 100644 index 000000000..3b2766276 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/switchTrue_checker.go @@ -0,0 +1,49 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "switchTrue" + info.Tags = []string{"style"} + info.Summary = "Detects switch-over-bool statements that use explicit `true` tag value" + info.Before = ` +switch true { +case x > y: +}` + info.After = ` +switch { +case x > y: +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&switchTrueChecker{ctx: ctx}) + }) +} + +type switchTrueChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *switchTrueChecker) VisitStmt(stmt ast.Stmt) { + if stmt, ok := stmt.(*ast.SwitchStmt); ok { + if qualifiedName(stmt.Tag) == "true" { + c.warn(stmt) + } + } +} + +func (c *switchTrueChecker) warn(cause *ast.SwitchStmt) { + if cause.Init == nil { + c.ctx.Warn(cause, "replace 'switch true {}' with 'switch {}'") + } else { + c.ctx.Warn(cause, "replace 'switch %s; true {}' with 'switch %s; {}'", + cause.Init, cause.Init) + } +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/truncateCmp_checker.go b/vendor/github.com/go-critic/go-critic/checkers/truncateCmp_checker.go new file mode 100644 index 000000000..f4cb9e866 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/truncateCmp_checker.go @@ -0,0 +1,117 @@ +package checkers + +import ( + "go/ast" + "go/token" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astp" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "truncateCmp" + info.Tags = []string{"diagnostic", "experimental"} + info.Params = lintpack.CheckerParams{ + "skipArchDependent": { + Value: true, + Usage: "whether to skip int/uint/uintptr types", + }, + } + info.Summary = "Detects potential truncation issues when comparing ints of different sizes" + info.Before = ` +func f(x int32, y int16) bool { + return int16(x) < y +}` + info.After = ` +func f(x int32, int16) bool { + return x < int32(y) +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &truncateCmpChecker{ctx: ctx} + c.skipArchDependent = info.Params.Bool("skipArchDependent") + return astwalk.WalkerForExpr(c) + }) +} + +type truncateCmpChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + skipArchDependent bool +} + +func (c *truncateCmpChecker) VisitExpr(expr ast.Expr) { + cmp := astcast.ToBinaryExpr(expr) + switch cmp.Op { + case token.LSS, token.GTR, token.LEQ, token.GEQ, token.EQL, token.NEQ: + if astp.IsBasicLit(cmp.X) || astp.IsBasicLit(cmp.Y) { + return // Don't bother about untyped consts + } + leftCast := c.isTruncCast(cmp.X) + rightCast := c.isTruncCast(cmp.Y) + switch { + case leftCast && rightCast: + return + case leftCast: + c.checkCmp(cmp.X, cmp.Y) + case rightCast: + c.checkCmp(cmp.Y, cmp.X) + } + default: + return + } +} + +func (c *truncateCmpChecker) isTruncCast(x ast.Expr) bool { + switch astcast.ToIdent(astcast.ToCallExpr(x).Fun).Name { + case "int8", "int16", "int32", "uint8", "uint16", "uint32": + return true + default: + return false + } +} + +func (c *truncateCmpChecker) checkCmp(cmpX, cmpY ast.Expr) { + // Check if we have a cast to a type that can truncate. + xcast := astcast.ToCallExpr(cmpX) + if len(xcast.Args) != 1 { + return // Just in case of the shadowed builtin + } + + x := xcast.Args[0] + y := cmpY + + // Check that both x and y are signed or unsigned int-typed. + xtyp, ok := c.ctx.TypesInfo.TypeOf(x).Underlying().(*types.Basic) + if !ok || xtyp.Info()&types.IsInteger == 0 { + return + } + ytyp, ok := c.ctx.TypesInfo.TypeOf(y).Underlying().(*types.Basic) + if !ok || xtyp.Info() != ytyp.Info() { + return + } + + xsize := c.ctx.SizesInfo.Sizeof(xtyp) + ysize := c.ctx.SizesInfo.Sizeof(ytyp) + if xsize <= ysize { + return + } + + if c.skipArchDependent { + switch xtyp.Kind() { + case types.Int, types.Uint, types.Uintptr: + return + } + } + + c.warn(xcast, xsize*8, ysize*8, xtyp.String()) +} + +func (c *truncateCmpChecker) warn(cause ast.Expr, xsize, ysize int64, suggest string) { + c.ctx.Warn(cause, "truncation in comparison %d->%d bit; cast the other operand to %s instead", xsize, ysize, suggest) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/typeAssertChain_checker.go b/vendor/github.com/go-critic/go-critic/checkers/typeAssertChain_checker.go new file mode 100644 index 000000000..c0c42e351 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/typeAssertChain_checker.go @@ -0,0 +1,132 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/astp" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "typeAssertChain" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects repeated type assertions and suggests to replace them with type switch statement" + info.Before = ` +if x, ok := v.(T1); ok { + // Code A, uses x. +} else if x, ok := v.(T2); ok { + // Code B, uses x. +} else if x, ok := v.(T3); ok { + // Code C, uses x. +}` + info.After = ` +switch x := v.(T1) { +case cond1: + // Code A, uses x. +case cond2: + // Code B, uses x. +default: + // Code C, uses x. +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&typeAssertChainChecker{ctx: ctx}) + }) +} + +type typeAssertChainChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + cause *ast.IfStmt + visited map[*ast.IfStmt]bool + typeSet lintutil.AstSet +} + +func (c *typeAssertChainChecker) EnterFunc(fn *ast.FuncDecl) bool { + if fn.Body == nil { + return false + } + c.visited = make(map[*ast.IfStmt]bool) + return true +} + +func (c *typeAssertChainChecker) VisitStmt(stmt ast.Stmt) { + ifstmt, ok := stmt.(*ast.IfStmt) + if !ok || c.visited[ifstmt] || ifstmt.Init == nil { + return + } + assertion := c.getTypeAssert(ifstmt) + if assertion == nil { + return + } + c.cause = ifstmt + c.checkIfStmt(ifstmt, assertion) +} + +func (c *typeAssertChainChecker) getTypeAssert(ifstmt *ast.IfStmt) *ast.TypeAssertExpr { + assign := astcast.ToAssignStmt(ifstmt.Init) + if len(assign.Lhs) != 2 || len(assign.Rhs) != 1 { + return nil + } + if !astp.IsIdent(assign.Lhs[0]) || assign.Tok != token.DEFINE { + return nil + } + if !astequal.Expr(assign.Lhs[1], ifstmt.Cond) { + return nil + } + + assertion, ok := assign.Rhs[0].(*ast.TypeAssertExpr) + if !ok { + return nil + } + return assertion +} + +func (c *typeAssertChainChecker) checkIfStmt(stmt *ast.IfStmt, assertion *ast.TypeAssertExpr) { + if c.countTypeAssertions(stmt, assertion) >= 2 { + c.warn() + } +} + +func (c *typeAssertChainChecker) countTypeAssertions(stmt *ast.IfStmt, assertion *ast.TypeAssertExpr) int { + c.typeSet.Clear() + + count := 1 + x := assertion.X + c.typeSet.Insert(assertion.Type) + for { + e, ok := stmt.Else.(*ast.IfStmt) + if !ok { + return count + } + assertion = c.getTypeAssert(e) + if assertion == nil { + return count + } + if !c.typeSet.Insert(assertion.Type) { + // Asserted type is duplicated. + // Type switch does not permit duplicate cases, + // so give up. + return 0 + } + if !astequal.Expr(x, assertion.X) { + // Mixed type asserting chain. + // Can't be easily translated to a type switch. + return 0 + } + stmt = e + count++ + c.visited[e] = true + } +} + +func (c *typeAssertChainChecker) warn() { + c.ctx.Warn(c.cause, "rewrite if-else to type switch statement") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/typeSwitchVar_checker.go b/vendor/github.com/go-critic/go-critic/checkers/typeSwitchVar_checker.go new file mode 100644 index 000000000..a113597b6 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/typeSwitchVar_checker.go @@ -0,0 +1,88 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/astp" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "typeSwitchVar" + info.Tags = []string{"style"} + info.Summary = "Detects type switches that can benefit from type guard clause with variable" + info.Before = ` +switch v.(type) { +case int: + return v.(int) +case point: + return v.(point).x + v.(point).y +default: + return 0 +}` + info.After = ` +switch v := v.(type) { +case int: + return v +case point: + return v.x + v.y +default: + return 0 +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&typeSwitchVarChecker{ctx: ctx}) + }) +} + +type typeSwitchVarChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *typeSwitchVarChecker) VisitStmt(stmt ast.Stmt) { + if stmt, ok := stmt.(*ast.TypeSwitchStmt); ok { + c.checkTypeSwitch(stmt) + } +} + +func (c *typeSwitchVarChecker) checkTypeSwitch(root *ast.TypeSwitchStmt) { + if astp.IsAssignStmt(root.Assign) { + return // Already with type guard + } + // Must be a *ast.ExprStmt then. + expr := root.Assign.(*ast.ExprStmt).X.(*ast.TypeAssertExpr).X + object := c.ctx.TypesInfo.ObjectOf(identOf(expr)) + if object == nil { + return // Give up: can't handle shadowing without object + } + + for i, clause := range root.Body.List { + clause := clause.(*ast.CaseClause) + // Multiple types in a list mean that assert.X will have + // a type of interface{} inside clause body. + // We are looking for precise type case. + if len(clause.List) != 1 { + continue + } + // Create artificial node just for matching. + assert1 := ast.TypeAssertExpr{X: expr, Type: clause.List[0]} + for _, stmt := range clause.Body { + assert2 := lintutil.FindNode(stmt, func(x ast.Node) bool { + return astequal.Node(&assert1, x) + }) + if object == c.ctx.TypesInfo.ObjectOf(identOf(assert2)) { + c.warn(root, i) + break + } + } + } +} + +func (c *typeSwitchVarChecker) warn(n ast.Node, caseIndex int) { + c.ctx.Warn(n, "case %d can benefit from type switch with assignment", caseIndex) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go b/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go new file mode 100644 index 000000000..a17c77b49 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go @@ -0,0 +1,86 @@ +package checkers + +import ( + "go/ast" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astp" + "golang.org/x/tools/go/ast/astutil" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "typeUnparen" + info.Tags = []string{"style", "opinionated"} + info.Summary = "Detects unneded parenthesis inside type expressions and suggests to remove them" + info.Before = `type foo [](func([](func())))` + info.After = `type foo []func([]func())` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForTypeExpr(&typeUnparenChecker{ctx: ctx}, ctx.TypesInfo) + }) +} + +type typeUnparenChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *typeUnparenChecker) VisitTypeExpr(x ast.Expr) { + switch x := x.(type) { + case *ast.ParenExpr: + switch x.X.(type) { + case *ast.StructType: + c.ctx.Warn(x, "could simplify (struct{...}) to struct{...}") + case *ast.InterfaceType: + c.ctx.Warn(x, "could simplify (interface{...}) to interface{...}") + default: + c.warn(x, c.unparenExpr(astcopy.Expr(x))) + } + default: + c.checkTypeExpr(x) + } +} + +func (c *typeUnparenChecker) checkTypeExpr(x ast.Expr) { + switch x := x.(type) { + case *ast.ArrayType: + // Arrays require extra care: we don't want to unparen + // length expression as they are not type expressions. + if !c.hasParens(x.Elt) { + return + } + noParens := astcopy.ArrayType(x) + noParens.Elt = c.unparenExpr(noParens.Elt) + c.warn(x, noParens) + case *ast.StructType, *ast.InterfaceType: + // Only nested fields are to be reported. + default: + if !c.hasParens(x) { + return + } + c.warn(x, c.unparenExpr(astcopy.Expr(x))) + } +} + +func (c *typeUnparenChecker) hasParens(x ast.Expr) bool { + return lintutil.ContainsNode(x, astp.IsParenExpr) +} + +func (c *typeUnparenChecker) unparenExpr(x ast.Expr) ast.Expr { + // Replace every paren expr with expression it encloses. + return astutil.Apply(x, nil, func(cur *astutil.Cursor) bool { + if paren, ok := cur.Node().(*ast.ParenExpr); ok { + cur.Replace(paren.X) + } + return true + }).(ast.Expr) +} + +func (c *typeUnparenChecker) warn(cause, noParens ast.Expr) { + c.SkipChilds = true + c.ctx.Warn(cause, "could simplify %s to %s", cause, noParens) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/underef_checker.go b/vendor/github.com/go-critic/go-critic/checkers/underef_checker.go new file mode 100644 index 000000000..dfc6077bb --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/underef_checker.go @@ -0,0 +1,127 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astp" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "underef" + info.Tags = []string{"style"} + info.Params = lintpack.CheckerParams{ + "skipRecvDeref": { + Value: true, + Usage: "whether to skip (*x).method() calls where x is a pointer receiver", + }, + } + info.Summary = "Detects dereference expressions that can be omitted" + info.Before = ` +(*k).field = 5 +v := (*a)[5] // only if a is array` + info.After = ` +k.field = 5 +v := a[5]` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &underefChecker{ctx: ctx} + c.skipRecvDeref = info.Params.Bool("skipRecvDeref") + return astwalk.WalkerForExpr(c) + }) +} + +type underefChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + skipRecvDeref bool +} + +func (c *underefChecker) VisitExpr(expr ast.Expr) { + switch n := expr.(type) { + case *ast.SelectorExpr: + expr := astcast.ToParenExpr(n.X) + if c.skipRecvDeref && c.isPtrRecvMethodCall(n.Sel) { + return + } + + if expr, ok := expr.X.(*ast.StarExpr); ok { + if c.checkStarExpr(expr) { + c.warnSelect(n) + } + } + case *ast.IndexExpr: + expr := astcast.ToParenExpr(n.X) + if expr, ok := expr.X.(*ast.StarExpr); ok { + if !c.checkStarExpr(expr) { + return + } + if c.checkArray(expr) { + c.warnArray(n) + } + } + } +} + +func (c *underefChecker) isPtrRecvMethodCall(fn *ast.Ident) bool { + typ, ok := c.ctx.TypesInfo.TypeOf(fn).(*types.Signature) + if ok && typ != nil && typ.Recv() != nil { + _, ok := typ.Recv().Type().(*types.Pointer) + return ok + } + return false +} + +func (c *underefChecker) underef(x *ast.ParenExpr) ast.Expr { + // If there is only 1 deref, can remove parenthesis, + // otherwise can remove StarExpr only. + dereferenced := x.X.(*ast.StarExpr).X + if astp.IsStarExpr(dereferenced) { + return &ast.ParenExpr{X: dereferenced} + } + return dereferenced +} + +func (c *underefChecker) warnSelect(expr *ast.SelectorExpr) { + // TODO: add () to function output. + c.ctx.Warn(expr, "could simplify %s to %s.%s", + expr, + c.underef(expr.X.(*ast.ParenExpr)), + expr.Sel.Name) +} + +func (c *underefChecker) warnArray(expr *ast.IndexExpr) { + c.ctx.Warn(expr, "could simplify %s to %s[%s]", + expr, + c.underef(expr.X.(*ast.ParenExpr)), + expr.Index) +} + +// checkStarExpr checks if ast.StarExpr could be simplified. +func (c *underefChecker) checkStarExpr(expr *ast.StarExpr) bool { + typ, ok := c.ctx.TypesInfo.TypeOf(expr.X).Underlying().(*types.Pointer) + if !ok { + return false + } + + switch typ.Elem().Underlying().(type) { + case *types.Pointer, *types.Interface: + return false + default: + return true + } +} + +func (c *underefChecker) checkArray(expr *ast.StarExpr) bool { + typ, ok := c.ctx.TypesInfo.TypeOf(expr.X).(*types.Pointer) + if !ok { + return false + } + _, ok = typ.Elem().(*types.Array) + return ok +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/unlabelStmt_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unlabelStmt_checker.go new file mode 100644 index 000000000..d90c65c2c --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/unlabelStmt_checker.go @@ -0,0 +1,170 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "unlabelStmt" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects redundant statement labels" + info.Before = ` +derp: +for x := range xs { + if x == 0 { + break derp + } +}` + info.After = ` +for x := range xs { + if x == 0 { + break + } +}` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmt(&unlabelStmtChecker{ctx: ctx}) + }) +} + +type unlabelStmtChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *unlabelStmtChecker) EnterFunc(fn *ast.FuncDecl) bool { + if fn.Body == nil { + return false + } + // TODO(Quasilyte): should not do additional traversal here. + // For now, skip all functions that contain goto statement. + return !lintutil.ContainsNode(fn.Body, func(n ast.Node) bool { + br, ok := n.(*ast.BranchStmt) + return ok && br.Tok == token.GOTO + }) +} + +func (c *unlabelStmtChecker) VisitStmt(stmt ast.Stmt) { + labeled, ok := stmt.(*ast.LabeledStmt) + if !ok || !c.canBreakFrom(labeled.Stmt) { + return + } + + // We have a labeled statement from that have labeled continue/break. + // This is an invariant, since unused label is a compile-time error + // and we're currently skipping functions containing goto. + // + // Also note that Go labels are function-scoped and there + // can be no re-definitions. This means that we don't + // need to care about label shadowing or things like that. + // + // The task is to find cases where labeled branch (continue/break) + // is redundant and can be re-written, decreasing the label usages + // and potentially leading to its redundancy, + // or finding the redundant labels right away. + + name := labeled.Label.Name + + // Simplest case that can prove that label is redundant. + // + // If labeled branch is somewhere inside the statement block itself + // and none of the nested break'able statements refer to that label, + // the label can be removed. + matchUsage := func(n ast.Node) bool { + return c.canBreakFrom(n) && c.usesLabel(c.blockStmtOf(n), name) + } + if !lintutil.ContainsNode(c.blockStmtOf(labeled.Stmt), matchUsage) { + c.warnRedundant(labeled) + return + } + + // Only for loops: if last stmt in list is a loop + // that contains labeled "continue" to the outer loop label, + // it can be refactored to use "break" instead. + if c.isLoop(labeled.Stmt) { + body := c.blockStmtOf(labeled.Stmt) + if len(body.List) == 0 { + return + } + last := body.List[len(body.List)-1] + if !c.isLoop(last) { + return + } + br := lintutil.FindNode(c.blockStmtOf(last), func(n ast.Node) bool { + br, ok := n.(*ast.BranchStmt) + return ok && br.Label != nil && + br.Label.Name == name && br.Tok == token.CONTINUE + }) + if br != nil { + c.warnLabeledContinue(br, name) + } + } +} + +// isLoop reports whether n is a loop of some kind. +// In other words, it tells whether n body can contain "continue" +// associated with n. +func (c *unlabelStmtChecker) isLoop(n ast.Node) bool { + switch n.(type) { + case *ast.ForStmt, *ast.RangeStmt: + return true + default: + return false + } +} + +// canBreakFrom reports whether it is possible to "break" or "continue" from n body. +func (c *unlabelStmtChecker) canBreakFrom(n ast.Node) bool { + switch n.(type) { + case *ast.RangeStmt, *ast.ForStmt, *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt: + return true + default: + return false + } +} + +// blockStmtOf returns body of specified node. +// +// TODO(quasilyte): handle other statements and see if it can be useful +// in other checkers. +func (c *unlabelStmtChecker) blockStmtOf(n ast.Node) *ast.BlockStmt { + switch n := n.(type) { + case *ast.RangeStmt: + return n.Body + case *ast.ForStmt: + return n.Body + case *ast.SwitchStmt: + return n.Body + case *ast.TypeSwitchStmt: + return n.Body + case *ast.SelectStmt: + return n.Body + + default: + return nil + } +} + +// usesLabel reports whether n contains a usage of label. +func (c *unlabelStmtChecker) usesLabel(n *ast.BlockStmt, label string) bool { + return lintutil.ContainsNode(n, func(n ast.Node) bool { + branch, ok := n.(*ast.BranchStmt) + return ok && branch.Label != nil && + branch.Label.Name == label && + (branch.Tok == token.CONTINUE || branch.Tok == token.BREAK) + }) +} + +func (c *unlabelStmtChecker) warnRedundant(cause *ast.LabeledStmt) { + c.ctx.Warn(cause, "label %s is redundant", cause.Label) +} + +func (c *unlabelStmtChecker) warnLabeledContinue(cause ast.Node, label string) { + c.ctx.Warn(cause, "change `continue %s` to `break`", label) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/unlambda_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unlambda_checker.go new file mode 100644 index 000000000..9e01299bf --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/unlambda_checker.go @@ -0,0 +1,79 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astequal" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "unlambda" + info.Tags = []string{"style"} + info.Summary = "Detects function literals that can be simplified" + info.Before = `func(x int) int { return fn(x) }` + info.After = `fn` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&unlambdaChecker{ctx: ctx}) + }) +} + +type unlambdaChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *unlambdaChecker) VisitExpr(x ast.Expr) { + fn, ok := x.(*ast.FuncLit) + if !ok || len(fn.Body.List) != 1 { + return + } + + ret, ok := fn.Body.List[0].(*ast.ReturnStmt) + if !ok || len(ret.Results) != 1 { + return + } + + result := astcast.ToCallExpr(ret.Results[0]) + callable := qualifiedName(result.Fun) + if callable == "" { + return // Skip tricky cases; only handle simple calls + } + if isBuiltin(callable) { + return // See #762 + } + if id, ok := result.Fun.(*ast.Ident); ok { + obj := c.ctx.TypesInfo.ObjectOf(id) + if _, ok := obj.(*types.Var); ok { + return // See #888 + } + } + fnType := c.ctx.TypesInfo.TypeOf(fn) + resultType := c.ctx.TypesInfo.TypeOf(result.Fun) + if !types.Identical(fnType, resultType) { + return + } + // Now check that all arguments match the parameters. + n := 0 + for _, params := range fn.Type.Params.List { + for _, id := range params.Names { + if !astequal.Expr(id, result.Args[n]) { + return + } + n++ + } + } + + if len(result.Args) == n { + c.warn(fn, callable) + } +} + +func (c *unlambdaChecker) warn(cause ast.Node, suggestion string) { + c.ctx.Warn(cause, "replace `%s` with `%s`", cause, suggestion) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/unnamedResult_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unnamedResult_checker.go new file mode 100644 index 000000000..09423250a --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/unnamedResult_checker.go @@ -0,0 +1,103 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "unnamedResult" + info.Tags = []string{"style", "opinionated", "experimental"} + info.Params = lintpack.CheckerParams{ + "checkExported": { + Value: false, + Usage: "whether to check exported functions", + }, + } + info.Summary = "Detects unnamed results that may benefit from names" + info.Before = `func f() (float64, float64)` + info.After = `func f() (x, y float64)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + c := &unnamedResultChecker{ctx: ctx} + c.checkExported = info.Params.Bool("checkExported") + return astwalk.WalkerForFuncDecl(c) + }) +} + +type unnamedResultChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + checkExported bool +} + +func (c *unnamedResultChecker) VisitFuncDecl(decl *ast.FuncDecl) { + if c.checkExported && !ast.IsExported(decl.Name.Name) { + return + } + results := decl.Type.Results + switch { + case results == nil: + return // Function has no results + case len(results.List) != 0 && results.List[0].Names != nil: + return // Skip named results + } + + typeName := func(x ast.Expr) string { return c.typeName(c.ctx.TypesInfo.TypeOf(x)) } + isError := func(x ast.Expr) bool { return qualifiedName(x) == "error" } + isBool := func(x ast.Expr) bool { return qualifiedName(x) == "bool" } + + // Main difference with case of len=2 is that we permit any + // typ1 as long as second type is either error or bool. + if results.NumFields() == 2 { + typ1, typ2 := results.List[0].Type, results.List[1].Type + name1, name2 := typeName(typ1), typeName(typ2) + cond := (name1 != name2 && name2 != "") || + (!isError(typ1) && isError(typ2)) || + (!isBool(typ1) && isBool(typ2)) + if !cond { + c.warn(decl) + } + return + } + + seen := make(map[string]bool, len(results.List)) + for i := range results.List { + typ := results.List[i].Type + name := typeName(typ) + isLast := i == len(results.List)-1 + + cond := !seen[name] || + (isLast && (isError(typ) || isBool(typ))) + if !cond { + c.warn(decl) + return + } + + seen[name] = true + } +} + +func (c *unnamedResultChecker) typeName(typ types.Type) string { + switch typ := typ.(type) { + case *types.Array: + return c.typeName(typ.Elem()) + case *types.Pointer: + return c.typeName(typ.Elem()) + case *types.Slice: + return c.typeName(typ.Elem()) + case *types.Named: + return typ.Obj().Name() + default: + return "" + } +} + +func (c *unnamedResultChecker) warn(n ast.Node) { + c.ctx.Warn(n, "consider giving a name to these results") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go new file mode 100644 index 000000000..e5dc45f7e --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go @@ -0,0 +1,69 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "unnecessaryBlock" + info.Tags = []string{"style", "opinionated", "experimental"} + info.Summary = "Detects unnecessary braced statement blocks" + info.Before = ` +x := 1 +{ + print(x) +}` + info.After = ` +x := 1 +print(x)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmtList(&unnecessaryBlockChecker{ctx: ctx}) + }) +} + +type unnecessaryBlockChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *unnecessaryBlockChecker) VisitStmtList(statements []ast.Stmt) { + // Using StmtListVisitor instead of StmtVisitor makes it easier to avoid + // false positives on IfStmt, RangeStmt, ForStmt and alike. + // We only inspect BlockStmt inside statement lists, so this method is not + // called for IfStmt itself, for example. + + for _, stmt := range statements { + stmt, ok := stmt.(*ast.BlockStmt) + if ok && !c.hasDefinitions(stmt) { + c.warn(stmt) + } + } +} + +func (c *unnecessaryBlockChecker) hasDefinitions(stmt *ast.BlockStmt) bool { + for _, bs := range stmt.List { + switch stmt := bs.(type) { + case *ast.AssignStmt: + if stmt.Tok == token.DEFINE { + return true + } + case *ast.DeclStmt: + decl := stmt.Decl.(*ast.GenDecl) + if len(decl.Specs) != 0 { + return true + } + } + } + + return false +} + +func (c *unnecessaryBlockChecker) warn(expr ast.Stmt) { + c.ctx.Warn(expr, "block doesn't have definitions, can be simply deleted") +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/unslice_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unslice_checker.go new file mode 100644 index 000000000..06d90819c --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/unslice_checker.go @@ -0,0 +1,59 @@ +package checkers + +import ( + "go/ast" + "go/types" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astequal" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "unslice" + info.Tags = []string{"style"} + info.Summary = "Detects slice expressions that can be simplified to sliced expression itself" + info.Before = ` +f(s[:]) // s is string +copy(b[:], values...) // b is []byte` + info.After = ` +f(s) +copy(b, values...)` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&unsliceChecker{ctx: ctx}) + }) +} + +type unsliceChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *unsliceChecker) VisitExpr(expr ast.Expr) { + unsliced := c.unslice(expr) + if !astequal.Expr(expr, unsliced) { + c.warn(expr, unsliced) + c.SkipChilds = true + } +} + +func (c *unsliceChecker) unslice(expr ast.Expr) ast.Expr { + slice, ok := expr.(*ast.SliceExpr) + if !ok || slice.Low != nil || slice.High != nil { + // No need to worry about 3-index slicing, + // because it's only permitted if expr.High is not nil. + return expr + } + switch c.ctx.TypesInfo.TypeOf(slice.X).(type) { + case *types.Slice, *types.Basic: + // Basic kind catches strings, Slice cathes everything else. + return c.unslice(slice.X) + } + return expr +} + +func (c *unsliceChecker) warn(cause, unsliced ast.Expr) { + c.ctx.Warn(cause, "could simplify %s to %s", cause, unsliced) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/utils.go b/vendor/github.com/go-critic/go-critic/checkers/utils.go new file mode 100644 index 000000000..ba4777dbd --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/utils.go @@ -0,0 +1,309 @@ +package checkers + +import ( + "go/ast" + "go/types" + "strings" + + "github.com/go-lintpack/lintpack" +) + +// goStdlib contains `go list std` command output list. +// Used to detect packages that belong to standard Go packages distribution. +var goStdlib = map[string]bool{ + "archive/tar": true, + "archive/zip": true, + "bufio": true, + "bytes": true, + "compress/bzip2": true, + "compress/flate": true, + "compress/gzip": true, + "compress/lzw": true, + "compress/zlib": true, + "container/heap": true, + "container/list": true, + "container/ring": true, + "context": true, + "crypto": true, + "crypto/aes": true, + "crypto/cipher": true, + "crypto/des": true, + "crypto/dsa": true, + "crypto/ecdsa": true, + "crypto/elliptic": true, + "crypto/hmac": true, + "crypto/internal/randutil": true, + "crypto/internal/subtle": true, + "crypto/md5": true, + "crypto/rand": true, + "crypto/rc4": true, + "crypto/rsa": true, + "crypto/sha1": true, + "crypto/sha256": true, + "crypto/sha512": true, + "crypto/subtle": true, + "crypto/tls": true, + "crypto/x509": true, + "crypto/x509/pkix": true, + "database/sql": true, + "database/sql/driver": true, + "debug/dwarf": true, + "debug/elf": true, + "debug/gosym": true, + "debug/macho": true, + "debug/pe": true, + "debug/plan9obj": true, + "encoding": true, + "encoding/ascii85": true, + "encoding/asn1": true, + "encoding/base32": true, + "encoding/base64": true, + "encoding/binary": true, + "encoding/csv": true, + "encoding/gob": true, + "encoding/hex": true, + "encoding/json": true, + "encoding/pem": true, + "encoding/xml": true, + "errors": true, + "expvar": true, + "flag": true, + "fmt": true, + "go/ast": true, + "go/build": true, + "go/constant": true, + "go/doc": true, + "go/format": true, + "go/importer": true, + "go/internal/gccgoimporter": true, + "go/internal/gcimporter": true, + "go/internal/srcimporter": true, + "go/parser": true, + "go/printer": true, + "go/scanner": true, + "go/token": true, + "go/types": true, + "hash": true, + "hash/adler32": true, + "hash/crc32": true, + "hash/crc64": true, + "hash/fnv": true, + "html": true, + "html/template": true, + "image": true, + "image/color": true, + "image/color/palette": true, + "image/draw": true, + "image/gif": true, + "image/internal/imageutil": true, + "image/jpeg": true, + "image/png": true, + "index/suffixarray": true, + "internal/bytealg": true, + "internal/cpu": true, + "internal/nettrace": true, + "internal/poll": true, + "internal/race": true, + "internal/singleflight": true, + "internal/syscall/unix": true, + "internal/syscall/windows": true, + "internal/syscall/windows/registry": true, + "internal/syscall/windows/sysdll": true, + "internal/testenv": true, + "internal/testlog": true, + "internal/trace": true, + "io": true, + "io/ioutil": true, + "log": true, + "log/syslog": true, + "math": true, + "math/big": true, + "math/bits": true, + "math/cmplx": true, + "math/rand": true, + "mime": true, + "mime/multipart": true, + "mime/quotedprintable": true, + "net": true, + "net/http": true, + "net/http/cgi": true, + "net/http/cookiejar": true, + "net/http/fcgi": true, + "net/http/httptest": true, + "net/http/httptrace": true, + "net/http/httputil": true, + "net/http/internal": true, + "net/http/pprof": true, + "net/internal/socktest": true, + "net/mail": true, + "net/rpc": true, + "net/rpc/jsonrpc": true, + "net/smtp": true, + "net/textproto": true, + "net/url": true, + "os": true, + "os/exec": true, + "os/signal": true, + "os/signal/internal/pty": true, + "os/user": true, + "path": true, + "path/filepath": true, + "plugin": true, + "reflect": true, + "regexp": true, + "regexp/syntax": true, + "runtime": true, + "runtime/cgo": true, + "runtime/debug": true, + "runtime/internal/atomic": true, + "runtime/internal/sys": true, + "runtime/pprof": true, + "runtime/pprof/internal/profile": true, + "runtime/race": true, + "runtime/trace": true, + "sort": true, + "strconv": true, + "strings": true, + "sync": true, + "sync/atomic": true, + "syscall": true, + "testing": true, + "testing/internal/testdeps": true, + "testing/iotest": true, + "testing/quick": true, + "text/scanner": true, + "text/tabwriter": true, + "text/template": true, + "text/template/parse": true, + "time": true, + "unicode": true, + "unicode/utf16": true, + "unicode/utf8": true, + "unsafe": true, +} + +var goBuiltins = map[string]bool{ + // Types + "bool": true, + "byte": true, + "complex64": true, + "complex128": true, + "error": true, + "float32": true, + "float64": true, + "int": true, + "int8": true, + "int16": true, + "int32": true, + "int64": true, + "rune": true, + "string": true, + "uint": true, + "uint8": true, + "uint16": true, + "uint32": true, + "uint64": true, + "uintptr": true, + + // Constants + "true": true, + "false": true, + "iota": true, + + // Zero value + "nil": true, + + // Functions + "append": true, + "cap": true, + "close": true, + "complex": true, + "copy": true, + "delete": true, + "imag": true, + "len": true, + "make": true, + "new": true, + "panic": true, + "print": true, + "println": true, + "real": true, + "recover": true, +} + +// isBuiltin reports whether sym belongs to a predefined identifier set. +func isBuiltin(sym string) bool { + return goBuiltins[sym] +} + +// isStdlibPkg reports whether pkg is a package from the Go standard library. +func isStdlibPkg(pkg *types.Package) bool { + return pkg != nil && goStdlib[pkg.Path()] +} + +// isExampleTestFunc reports whether FuncDecl looks like a testable example function. +func isExampleTestFunc(fn *ast.FuncDecl) bool { + return len(fn.Type.Params.List) == 0 && strings.HasPrefix(fn.Name.String(), "Example") +} + +// isUnitTestFunc reports whether FuncDecl declares testing function. +func isUnitTestFunc(ctx *lintpack.CheckerContext, fn *ast.FuncDecl) bool { + if !strings.HasPrefix(fn.Name.Name, "Test") { + return false + } + typ := ctx.TypesInfo.TypeOf(fn.Name) + if sig, ok := typ.(*types.Signature); ok { + return sig.Results().Len() == 0 && + sig.Params().Len() == 1 && + sig.Params().At(0).Type().String() == "*testing.T" + } + return false +} + +// qualifiedName returns called expr fully-quallified name. +// +// It works for simple identifiers like f => "f" and identifiers +// from other package like pkg.f => "pkg.f". +// +// For all unexpected expressions returns empty string. +func qualifiedName(x ast.Expr) string { + switch x := x.(type) { + case *ast.SelectorExpr: + pkg, ok := x.X.(*ast.Ident) + if !ok { + return "" + } + return pkg.Name + "." + x.Sel.Name + case *ast.Ident: + return x.Name + default: + return "" + } +} + +// identOf returns identifier for x that can be used to obtain associated types.Object. +// Returns nil for expressions that yield temporary results, like `f().field`. +func identOf(x ast.Node) *ast.Ident { + switch x := x.(type) { + case *ast.Ident: + return x + case *ast.SelectorExpr: + return identOf(x.Sel) + case *ast.TypeAssertExpr: + // x.(type) - x may contain ident. + return identOf(x.X) + case *ast.IndexExpr: + // x[i] - x may contain ident. + return identOf(x.X) + case *ast.StarExpr: + // *x - x may contain ident. + return identOf(x.X) + case *ast.SliceExpr: + // x[:] - x may contain ident. + return identOf(x.X) + + default: + // Note that this function is not comprehensive. + return nil + } +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/valSwap_checker.go b/vendor/github.com/go-critic/go-critic/checkers/valSwap_checker.go new file mode 100644 index 000000000..ab27f9200 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/valSwap_checker.go @@ -0,0 +1,64 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astequal" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "valSwap" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects value swapping code that are not using parallel assignment" + info.Before = ` +tmp := *x +*x = *y +*y = tmp` + info.After = `*x, *y = *y, *x` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForStmtList(&valSwapChecker{ctx: ctx}) + }) +} + +type valSwapChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *valSwapChecker) VisitStmtList(list []ast.Stmt) { + for len(list) >= 3 { + tmpAssign := astcast.ToAssignStmt(list[0]) + assignX := astcast.ToAssignStmt(list[1]) + assignY := astcast.ToAssignStmt(list[2]) + + cond := c.isSimpleAssign(tmpAssign) && + c.isSimpleAssign(assignX) && + c.isSimpleAssign(assignY) && + assignX.Tok == token.ASSIGN && + assignY.Tok == token.ASSIGN && + astequal.Expr(assignX.Lhs[0], tmpAssign.Rhs[0]) && + astequal.Expr(assignX.Rhs[0], assignY.Lhs[0]) && + astequal.Expr(assignY.Rhs[0], tmpAssign.Lhs[0]) + if cond { + c.warn(tmpAssign, assignX.Lhs[0], assignY.Lhs[0]) + list = list[3:] + } else { + list = list[1:] + } + } +} + +func (c *valSwapChecker) isSimpleAssign(x *ast.AssignStmt) bool { + return len(x.Lhs) == 1 && len(x.Rhs) == 1 +} + +func (c *valSwapChecker) warn(cause, x, y ast.Node) { + c.ctx.Warn(cause, "can re-write as `%s, %s = %s, %s`", + x, y, y, x) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/weakCond_checker.go b/vendor/github.com/go-critic/go-critic/checkers/weakCond_checker.go new file mode 100644 index 000000000..fcd9aee52 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/weakCond_checker.go @@ -0,0 +1,77 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-critic/go-critic/checkers/internal/lintutil" + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/typep" + "golang.org/x/tools/go/ast/astutil" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "weakCond" + info.Tags = []string{"diagnostic", "experimental"} + info.Summary = "Detects conditions that are unsafe due to not being exhaustive" + info.Before = `xs != nil && xs[0] != nil` + info.After = `len(xs) != 0 && xs[0] != nil` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&weakCondChecker{ctx: ctx}) + }) +} + +type weakCondChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *weakCondChecker) VisitExpr(expr ast.Expr) { + // TODO(Quasilyte): more patterns. + // TODO(Quasilyte): analyze and fix false positives. + + cond := astcast.ToBinaryExpr(expr) + lhs := astcast.ToBinaryExpr(astutil.Unparen(cond.X)) + rhs := astutil.Unparen(cond.Y) + + // Pattern 1. + // `x != nil && usageOf(x[i])` + // Pattern 2. + // `x == nil || usageOf(x[i])` + + // lhs is `x nil` + x := lhs.X + if !typep.IsSlice(c.ctx.TypesInfo.TypeOf(x)) { + return + } + if astcast.ToIdent(lhs.Y).Name != "nil" { + return + } + + pat1prefix := cond.Op == token.LAND && lhs.Op == token.NEQ + pat2prefix := cond.Op == token.LOR && lhs.Op == token.EQL + if !pat1prefix && !pat2prefix { + return + } + + if c.isIndexed(rhs, x) { + c.warn(expr, "nil check may not be enough, check for len") + } +} + +// isIndexed reports whether x is indexed inside given expr tree. +func (c *weakCondChecker) isIndexed(tree, x ast.Expr) bool { + return lintutil.ContainsNode(tree, func(n ast.Node) bool { + indexing := astcast.ToIndexExpr(n) + return astequal.Expr(x, indexing.X) + }) +} + +func (c *weakCondChecker) warn(cause ast.Node, suggest string) { + c.ctx.Warn(cause, "suspicious `%s`; %s", cause, suggest) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/whyNoLint_checker.go b/vendor/github.com/go-critic/go-critic/checkers/whyNoLint_checker.go new file mode 100644 index 000000000..52fefb82c --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/whyNoLint_checker.go @@ -0,0 +1,52 @@ +package checkers + +import ( + "go/ast" + "regexp" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" +) + +func init() { + info := lintpack.CheckerInfo{ + Name: "whyNoLint", + Tags: []string{"style", "experimental"}, + Summary: "Ensures that `//nolint` comments include an explanation", + Before: `//nolint`, + After: `//nolint // reason`, + } + re := regexp.MustCompile(`^// *nolint(?::[^ ]+)? *(.*)$`) + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForComment(&whyNoLintChecker{ + ctx: ctx, + re: re, + }) + }) +} + +type whyNoLintChecker struct { + astwalk.WalkHandler + + ctx *lintpack.CheckerContext + re *regexp.Regexp +} + +func (c whyNoLintChecker) VisitComment(cg *ast.CommentGroup) { + if strings.HasPrefix(cg.List[0].Text, "/*") { + return + } + for _, comment := range cg.List { + sl := c.re.FindStringSubmatch(comment.Text) + if len(sl) < 2 { + continue + } + + if s := sl[1]; !strings.HasPrefix(s, "//") || len(strings.TrimPrefix(s, "//")) == 0 { + c.ctx.Warn(cg, "include an explanation for nolint directive") + return + } + } +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/wrapperFunc_checker.go b/vendor/github.com/go-critic/go-critic/checkers/wrapperFunc_checker.go new file mode 100644 index 000000000..bba82e5ee --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/wrapperFunc_checker.go @@ -0,0 +1,224 @@ +package checkers + +import ( + "go/ast" + "go/token" + "go/types" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "wrapperFunc" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects function calls that can be replaced with convenience wrappers" + info.Before = `wg.Add(-1)` + info.After = `wg.Done()` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + type arg struct { + index int + value string + } + type pattern struct { + pkg string + typ string // Only for typ patterns + args []arg + suggestion string + } + type matcher struct { + pkgPatterns []pattern + typPatterns []pattern + } + + typPatterns := map[string][]arg{ + "sync.WaitGroup.Add => WaitGroup.Done": { + {0, "-1"}, + }, + + "bytes.Buffer.Truncate => Buffer.Reset": { + {0, "0"}, + }, + } + + pkgPatterns := map[string][]arg{ + "http.HandlerFunc => http.NotFoundHandler": { + {0, "http.NotFound"}, + }, + + "strings.SplitN => strings.Split": { + {2, "-1"}, + }, + "strings.Replace => strings.ReplaceAll": { + {3, "-1"}, + }, + "strings.TrimFunc => strings.TrimSpace": { + {1, "unicode.IsSpace"}, + }, + "strings.Map => strings.ToTitle": { + {0, "unicode.ToTitle"}, + }, + + "bytes.SplitN => bytes.Split": { + {2, "-1"}, + }, + "bytes.Replace => bytes.ReplaceAll": { + {3, "-1"}, + }, + "bytes.TrimFunc => bytes.TrimSpace": { + {1, "unicode.IsSpace"}, + }, + "bytes.Map => bytes.ToUpper": { + {0, "unicode.ToUpper"}, + }, + "bytes.Map => bytes.ToLower": { + {0, "unicode.ToLower"}, + }, + "bytes.Map => bytes.ToTitle": { + {0, "unicode.ToTitle"}, + }, + } + + matchers := make(map[string]*matcher) + + type templateKey struct { + from string + to string + } + decodeKey := func(key string) templateKey { + parts := strings.Split(key, " => ") + return templateKey{from: parts[0], to: parts[1]} + } + + // Expand pkg patterns. + for key, args := range pkgPatterns { + key := decodeKey(key) + parts := strings.Split(key.from, ".") + fn := parts[1] + m := matchers[fn] + if m == nil { + m = &matcher{} + matchers[fn] = m + } + m.pkgPatterns = append(m.pkgPatterns, pattern{ + pkg: parts[0], + args: args, + suggestion: key.to, + }) + } + // Expand typ patterns. + for key, args := range typPatterns { + key := decodeKey(key) + parts := strings.Split(key.from, ".") + fn := parts[2] + m := matchers[fn] + if m == nil { + m = &matcher{} + matchers[fn] = m + } + m.typPatterns = append(m.typPatterns, pattern{ + pkg: parts[0], + typ: parts[1], + args: args, + suggestion: key.to, + }) + } + + var valueOf func(x ast.Expr) string + valueOf = func(x ast.Expr) string { + switch x := x.(type) { + case *ast.Ident: + return x.Name + case *ast.SelectorExpr: + id, ok := x.X.(*ast.Ident) + if ok { + return id.Name + "." + x.Sel.Name + } + case *ast.BasicLit: + return x.Value + case *ast.UnaryExpr: + switch x.Op { + case token.SUB: + return "-" + valueOf(x.X) + case token.ADD: + return valueOf(x.X) + } + } + return "" + } + + findSuggestion := func(call *ast.CallExpr, pkg, typ string, patterns []pattern) string { + for _, pat := range patterns { + if pat.pkg != pkg || pat.typ != typ { + continue + } + for _, arg := range pat.args { + if arg.value == valueOf(call.Args[arg.index]) { + return pat.suggestion + } + } + } + return "" + } + + c := &wrapperFuncChecker{ctx: ctx} + c.findSuggestion = func(call *ast.CallExpr) string { + sel := astcast.ToSelectorExpr(call.Fun).Sel + if sel == nil { + return "" + } + x := astcast.ToSelectorExpr(call.Fun).X + + m := matchers[sel.Name] + if m == nil { + return "" + } + + if x, ok := x.(*ast.Ident); ok { + obj, ok := c.ctx.TypesInfo.ObjectOf(x).(*types.PkgName) + if ok { + return findSuggestion(call, obj.Name(), "", m.pkgPatterns) + } + } + + typ := c.ctx.TypesInfo.TypeOf(x) + tn, ok := typ.(*types.Named) + if !ok { + return "" + } + return findSuggestion( + call, + tn.Obj().Pkg().Name(), + tn.Obj().Name(), + m.typPatterns) + } + + return astwalk.WalkerForExpr(c) + }) +} + +type wrapperFuncChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext + + findSuggestion func(*ast.CallExpr) string +} + +func (c *wrapperFuncChecker) VisitExpr(expr ast.Expr) { + call := astcast.ToCallExpr(expr) + if len(call.Args) == 0 { + return + } + + if suggest := c.findSuggestion(call); suggest != "" { + c.warn(call, suggest) + } +} + +func (c *wrapperFuncChecker) warn(cause ast.Node, suggest string) { + c.ctx.Warn(cause, "use %s method in `%s`", suggest, cause) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/yodaStyleExpr_checker.go b/vendor/github.com/go-critic/go-critic/checkers/yodaStyleExpr_checker.go new file mode 100644 index 000000000..ddd3099fd --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/yodaStyleExpr_checker.go @@ -0,0 +1,66 @@ +package checkers + +import ( + "go/ast" + "go/token" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astp" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "yodaStyleExpr" + info.Tags = []string{"style", "experimental"} + info.Summary = "Detects Yoda style expressions and suggests to replace them" + info.Before = `return nil != ptr` + info.After = `return ptr != nil` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForLocalExpr(&yodaStyleExprChecker{ctx: ctx}) + }) +} + +type yodaStyleExprChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *yodaStyleExprChecker) VisitLocalExpr(expr ast.Expr) { + binexpr, ok := expr.(*ast.BinaryExpr) + if !ok { + return + } + switch binexpr.Op { + case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GEQ, token.GTR: + if c.isConstExpr(binexpr.X) && !c.isConstExpr(binexpr.Y) { + c.warn(binexpr) + } + } +} + +func (c *yodaStyleExprChecker) isConstExpr(expr ast.Expr) bool { + return qualifiedName(expr) == "nil" || astp.IsBasicLit(expr) +} + +func (c *yodaStyleExprChecker) invert(expr *ast.BinaryExpr) { + expr.X, expr.Y = expr.Y, expr.X + switch expr.Op { + case token.LSS: + expr.Op = token.GEQ + case token.LEQ: + expr.Op = token.GTR + case token.GEQ: + expr.Op = token.LSS + case token.GTR: + expr.Op = token.LEQ + } +} + +func (c *yodaStyleExprChecker) warn(expr *ast.BinaryExpr) { + e := astcopy.BinaryExpr(expr) + c.invert(e) + c.ctx.Warn(expr, "consider to change order in expression to %s", e) +} diff --git a/vendor/github.com/go-lintpack/lintpack/.travis.yml b/vendor/github.com/go-lintpack/lintpack/.travis.yml new file mode 100644 index 000000000..41a0cbac5 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/.travis.yml @@ -0,0 +1,7 @@ +language: go +go: + - 1.x +install: + - # Prevent default install action "go get -t -v ./...". +script: + - make ci diff --git a/vendor/github.com/go-lintpack/lintpack/LICENSE b/vendor/github.com/go-lintpack/lintpack/LICENSE new file mode 100644 index 000000000..de0abccdf --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2018, go-lintpack maintainers + +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 Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/go-lintpack/lintpack/Makefile b/vendor/github.com/go-lintpack/lintpack/Makefile new file mode 100644 index 000000000..63f21d2f9 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/Makefile @@ -0,0 +1,14 @@ +.PHONY: test ci + +%: # stubs to get makefile param for `test-checker` command + @: # see: https://stackoverflow.com/a/6273809/433041 + +build: + go build cmd/lintpack/build.go cmd/lintpack/main.go + +test: + go test -v -count=1 ./... + +ci: + go get -t -v ./... + go test -v -count=1 ./... diff --git a/vendor/github.com/go-lintpack/lintpack/README.md b/vendor/github.com/go-lintpack/lintpack/README.md new file mode 100644 index 000000000..5702228eb --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/README.md @@ -0,0 +1,32 @@ +[![Build Status][travis-image]][travis-url] +[![Go Report Card][go-report-image]][go-report-url] + +[travis-image]: https://travis-ci.org/go-critic/go-critic.svg?branch=master +[travis-url]: https://travis-ci.org/go-critic/go-critic +[go-report-image]: https://goreportcard.com/badge/github.com/go-critic/go-critic +[go-report-url]: https://goreportcard.com/report/github.com/go-critic/go-critic + +## Quick start / Installation / Usage + +Install `lintpack`: + +```bash +go get -v -u github.com/go-lintpack/lintpack/... +``` + +Install checkers from [go-critic/checkers](https://github.com/go-critic/checkers): + +```bash +# You'll need to have sources under your Go workspace first: +go get -v -u github.com/go-critic/checkers +# Now build a linter that includes all checks from that package: +lintpack build -o gocritic github.com/go-critic/checkers +# Executable gocritic is created and can be used as a standalone linter. +``` + +Produced binary includes basic help as well as supported checks documentation. + +So, the process is simple: + +* Get the `lintpack` linter builder +* Build linter from checks implemented in different repos, by various vendors diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/comment_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/comment_walker.go new file mode 100644 index 000000000..6c60e3fed --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/comment_walker.go @@ -0,0 +1,41 @@ +package astwalk + +import ( + "go/ast" + "strings" +) + +type commentWalker struct { + visitor CommentVisitor +} + +func (w *commentWalker) WalkFile(f *ast.File) { + if !w.visitor.EnterFile(f) { + return + } + + for _, cg := range f.Comments { + visitCommentGroups(cg, w.visitor.VisitComment) + } +} + +func visitCommentGroups(cg *ast.CommentGroup, visit func(*ast.CommentGroup)) { + var group []*ast.Comment + visitGroup := func(list []*ast.Comment) { + if len(list) == 0 { + return + } + cg := &ast.CommentGroup{List: list} + visit(cg) + } + for _, comment := range cg.List { + if strings.HasPrefix(comment.Text, "/*") { + visitGroup(group) + group = group[:0] + visitGroup([]*ast.Comment{comment}) + } else { + group = append(group, comment) + } + } + visitGroup(group) +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/doc_comment_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/doc_comment_walker.go new file mode 100644 index 000000000..39b536508 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/doc_comment_walker.go @@ -0,0 +1,48 @@ +package astwalk + +import ( + "go/ast" +) + +type docCommentWalker struct { + visitor DocCommentVisitor +} + +func (w *docCommentWalker) WalkFile(f *ast.File) { + for _, decl := range f.Decls { + switch decl := decl.(type) { + case *ast.FuncDecl: + if decl.Doc != nil { + w.visitor.VisitDocComment(decl.Doc) + } + case *ast.GenDecl: + if decl.Doc != nil { + w.visitor.VisitDocComment(decl.Doc) + } + for _, spec := range decl.Specs { + switch spec := spec.(type) { + case *ast.ImportSpec: + if spec.Doc != nil { + w.visitor.VisitDocComment(spec.Doc) + } + case *ast.ValueSpec: + if spec.Doc != nil { + w.visitor.VisitDocComment(spec.Doc) + } + case *ast.TypeSpec: + if spec.Doc != nil { + w.visitor.VisitDocComment(spec.Doc) + } + ast.Inspect(spec.Type, func(n ast.Node) bool { + if n, ok := n.(*ast.Field); ok { + if n.Doc != nil { + w.visitor.VisitDocComment(n.Doc) + } + } + return true + }) + } + } + } + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/expr_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/expr_walker.go new file mode 100644 index 000000000..64098b2b7 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/expr_walker.go @@ -0,0 +1,29 @@ +package astwalk + +import "go/ast" + +type exprWalker struct { + visitor ExprVisitor +} + +func (w *exprWalker) WalkFile(f *ast.File) { + if !w.visitor.EnterFile(f) { + return + } + + for _, decl := range f.Decls { + if decl, ok := decl.(*ast.FuncDecl); ok { + if !w.visitor.EnterFunc(decl) { + continue + } + } + + ast.Inspect(decl, func(x ast.Node) bool { + if x, ok := x.(ast.Expr); ok { + w.visitor.VisitExpr(x) + return !w.visitor.skipChilds() + } + return true + }) + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/func_decl_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/func_decl_walker.go new file mode 100644 index 000000000..90d921f6f --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/func_decl_walker.go @@ -0,0 +1,21 @@ +package astwalk + +import "go/ast" + +type funcDeclWalker struct { + visitor FuncDeclVisitor +} + +func (w *funcDeclWalker) WalkFile(f *ast.File) { + if !w.visitor.EnterFile(f) { + return + } + + for _, decl := range f.Decls { + decl, ok := decl.(*ast.FuncDecl) + if !ok || !w.visitor.EnterFunc(decl) { + continue + } + w.visitor.VisitFuncDecl(decl) + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/local_comment_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/local_comment_walker.go new file mode 100644 index 000000000..e042f0d5e --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/local_comment_walker.go @@ -0,0 +1,32 @@ +package astwalk + +import ( + "go/ast" +) + +type localCommentWalker struct { + visitor LocalCommentVisitor +} + +func (w *localCommentWalker) WalkFile(f *ast.File) { + if !w.visitor.EnterFile(f) { + return + } + + for _, decl := range f.Decls { + decl, ok := decl.(*ast.FuncDecl) + if !ok || !w.visitor.EnterFunc(decl) { + continue + } + + for _, cg := range f.Comments { + // Not sure that decls/comments are sorted + // by positions, so do a naive full scan for now. + if cg.Pos() < decl.Pos() || cg.Pos() > decl.End() { + continue + } + + visitCommentGroups(cg, w.visitor.VisitLocalComment) + } + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_visitor.go b/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_visitor.go new file mode 100644 index 000000000..bed0f44ab --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_visitor.go @@ -0,0 +1,51 @@ +package astwalk + +import ( + "go/ast" +) + +// LocalDefVisitor visits every name definitions inside a function. +// +// Next elements are considered as name definitions: +// - Function parameters (input, output, receiver) +// - Every LHS of ":=" assignment that defines a new name +// - Every local var/const declaration. +// +// NOTE: this visitor is experimental. +// This is also why it lives in a separate file. +type LocalDefVisitor interface { + walkerEvents + VisitLocalDef(Name, ast.Expr) +} + +type ( + // NameKind describes what kind of name Name object holds. + NameKind int + + // Name holds ver/const/param definition symbol info. + Name struct { + ID *ast.Ident + Kind NameKind + + // Index is NameVar-specific field that is used to + // specify nth tuple element being assigned to the name. + Index int + } +) + +// NOTE: set of name kinds is not stable and may change over time. +// +// TODO(quasilyte): is NameRecv/NameParam/NameResult granularity desired? +// TODO(quasilyte): is NameVar/NameBind (var vs :=) granularity desired? +const ( + // NameParam is function/method receiver/input/output name. + // Initializing expression is always nil. + NameParam NameKind = iota + // NameVar is var or ":=" declared name. + // Initizlizing expression may be nil for var-declared names + // without explicit initializing expression. + NameVar + // NameConst is const-declared name. + // Initializing expression is never nil. + NameConst +) diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_walker.go new file mode 100644 index 000000000..f6808cbb4 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_walker.go @@ -0,0 +1,118 @@ +package astwalk + +import ( + "go/ast" + "go/token" + "go/types" +) + +type localDefWalker struct { + visitor LocalDefVisitor + info *types.Info +} + +func (w *localDefWalker) WalkFile(f *ast.File) { + for _, decl := range f.Decls { + decl, ok := decl.(*ast.FuncDecl) + if !ok || !w.visitor.EnterFunc(decl) { + continue + } + w.walkFunc(decl) + } +} + +func (w *localDefWalker) walkFunc(decl *ast.FuncDecl) { + w.walkSignature(decl) + w.walkFuncBody(decl) +} + +func (w *localDefWalker) walkFuncBody(decl *ast.FuncDecl) { + ast.Inspect(decl.Body, func(x ast.Node) bool { + switch x := x.(type) { + case *ast.AssignStmt: + if x.Tok != token.DEFINE { + return false + } + if len(x.Lhs) != len(x.Rhs) { + // Multi-value assignment. + // Invariant: there is only 1 RHS. + for i, lhs := range x.Lhs { + id, ok := lhs.(*ast.Ident) + if !ok || w.info.Defs[id] == nil { + continue + } + def := Name{ID: id, Kind: NameVar, Index: i} + w.visitor.VisitLocalDef(def, x.Rhs[0]) + } + } else { + // Simple 1-1 assignments. + for i, lhs := range x.Lhs { + id, ok := lhs.(*ast.Ident) + if !ok || w.info.Defs[id] == nil { + continue + } + def := Name{ID: id, Kind: NameVar} + w.visitor.VisitLocalDef(def, x.Rhs[i]) + } + } + return false + + case *ast.GenDecl: + // Decls always introduce new names. + for _, spec := range x.Specs { + spec, ok := spec.(*ast.ValueSpec) + if !ok { // Ignore type/import specs + return false + } + switch { + case len(spec.Values) == 0: + // var-specific decls without explicit init. + for _, id := range spec.Names { + def := Name{ID: id, Kind: NameVar} + w.visitor.VisitLocalDef(def, nil) + } + case len(spec.Names) != len(spec.Values): + // var-specific decls that assign tuple results. + for i, id := range spec.Names { + def := Name{ID: id, Kind: NameVar, Index: i} + w.visitor.VisitLocalDef(def, spec.Values[0]) + } + default: + // Can be either var or const decl. + kind := NameVar + if x.Tok == token.CONST { + kind = NameConst + } + for i, id := range spec.Names { + def := Name{ID: id, Kind: kind} + w.visitor.VisitLocalDef(def, spec.Values[i]) + } + } + } + return false + } + + return true + }) +} + +func (w *localDefWalker) walkSignature(decl *ast.FuncDecl) { + for _, p := range decl.Type.Params.List { + for _, id := range p.Names { + def := Name{ID: id, Kind: NameParam} + w.visitor.VisitLocalDef(def, nil) + } + } + if decl.Type.Results != nil { + for _, p := range decl.Type.Results.List { + for _, id := range p.Names { + def := Name{ID: id, Kind: NameParam} + w.visitor.VisitLocalDef(def, nil) + } + } + } + if decl.Recv != nil && len(decl.Recv.List[0].Names) != 0 { + def := Name{ID: decl.Recv.List[0].Names[0], Kind: NameParam} + w.visitor.VisitLocalDef(def, nil) + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/local_expr_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/local_expr_walker.go new file mode 100644 index 000000000..951fd97e5 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/local_expr_walker.go @@ -0,0 +1,27 @@ +package astwalk + +import "go/ast" + +type localExprWalker struct { + visitor LocalExprVisitor +} + +func (w *localExprWalker) WalkFile(f *ast.File) { + if !w.visitor.EnterFile(f) { + return + } + + for _, decl := range f.Decls { + decl, ok := decl.(*ast.FuncDecl) + if !ok || !w.visitor.EnterFunc(decl) { + continue + } + ast.Inspect(decl.Body, func(x ast.Node) bool { + if x, ok := x.(ast.Expr); ok { + w.visitor.VisitLocalExpr(x) + return !w.visitor.skipChilds() + } + return true + }) + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_list_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_list_walker.go new file mode 100644 index 000000000..1cc0493a4 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_list_walker.go @@ -0,0 +1,31 @@ +package astwalk + +import "go/ast" + +type stmtListWalker struct { + visitor StmtListVisitor +} + +func (w *stmtListWalker) WalkFile(f *ast.File) { + if !w.visitor.EnterFile(f) { + return + } + + for _, decl := range f.Decls { + decl, ok := decl.(*ast.FuncDecl) + if !ok || !w.visitor.EnterFunc(decl) { + continue + } + ast.Inspect(decl.Body, func(x ast.Node) bool { + switch x := x.(type) { + case *ast.BlockStmt: + w.visitor.VisitStmtList(x.List) + case *ast.CaseClause: + w.visitor.VisitStmtList(x.Body) + case *ast.CommClause: + w.visitor.VisitStmtList(x.Body) + } + return !w.visitor.skipChilds() + }) + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_walker.go new file mode 100644 index 000000000..722eeb116 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_walker.go @@ -0,0 +1,27 @@ +package astwalk + +import "go/ast" + +type stmtWalker struct { + visitor StmtVisitor +} + +func (w *stmtWalker) WalkFile(f *ast.File) { + if !w.visitor.EnterFile(f) { + return + } + + for _, decl := range f.Decls { + decl, ok := decl.(*ast.FuncDecl) + if !ok || !w.visitor.EnterFunc(decl) { + continue + } + ast.Inspect(decl.Body, func(x ast.Node) bool { + if x, ok := x.(ast.Stmt); ok { + w.visitor.VisitStmt(x) + return !w.visitor.skipChilds() + } + return true + }) + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/type_expr_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/type_expr_walker.go new file mode 100644 index 000000000..24c150084 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/type_expr_walker.go @@ -0,0 +1,114 @@ +package astwalk + +import ( + "go/ast" + "go/token" + "go/types" + + "github.com/go-toolsmith/astp" + "github.com/go-toolsmith/typep" +) + +type typeExprWalker struct { + visitor TypeExprVisitor + info *types.Info +} + +func (w *typeExprWalker) WalkFile(f *ast.File) { + if !w.visitor.EnterFile(f) { + return + } + + for _, decl := range f.Decls { + if decl, ok := decl.(*ast.FuncDecl); ok { + if !w.visitor.EnterFunc(decl) { + continue + } + } + switch decl := decl.(type) { + case *ast.FuncDecl: + if !w.visitor.EnterFunc(decl) { + continue + } + w.walkSignature(decl.Type) + ast.Inspect(decl.Body, w.walk) + case *ast.GenDecl: + if decl.Tok == token.IMPORT { + continue + } + ast.Inspect(decl, w.walk) + } + } +} + +func (w *typeExprWalker) visit(x ast.Expr) bool { + w.visitor.VisitTypeExpr(x) + return !w.visitor.skipChilds() +} + +func (w *typeExprWalker) walk(x ast.Node) bool { + switch x := x.(type) { + case *ast.ParenExpr: + if typep.IsTypeExpr(w.info, x.X) { + return w.visit(x) + } + return true + case *ast.CallExpr: + // Pointer conversions require parenthesis around pointer type. + // These casts are represented as call expressions. + // Because it's impossible for the visitor to distinguish such + // "required" parenthesis, walker skips outmost parenthesis in such cases. + return w.inspectInner(x.Fun) + case *ast.SelectorExpr: + // Like with conversions, method expressions are another special. + return w.inspectInner(x.X) + case *ast.StarExpr: + if typep.IsTypeExpr(w.info, x.X) { + return w.visit(x) + } + return true + case *ast.MapType: + return w.visit(x) + case *ast.FuncType: + return w.visit(x) + case *ast.StructType: + return w.visit(x) + case *ast.InterfaceType: + if !w.visit(x) { + return false + } + for _, method := range x.Methods.List { + switch x := method.Type.(type) { + case *ast.FuncType: + w.walkSignature(x) + default: + // Embedded interface. + w.walk(x) + } + } + return false + case *ast.ArrayType: + return w.visit(x) + } + return true +} + +func (w *typeExprWalker) inspectInner(x ast.Expr) bool { + parens, ok := x.(*ast.ParenExpr) + if ok && typep.IsTypeExpr(w.info, parens.X) && astp.IsStarExpr(parens.X) { + ast.Inspect(parens.X, w.walk) + return false + } + return true +} + +func (w *typeExprWalker) walkSignature(typ *ast.FuncType) { + for _, p := range typ.Params.List { + ast.Inspect(p.Type, w.walk) + } + if typ.Results != nil { + for _, p := range typ.Results.List { + ast.Inspect(p.Type, w.walk) + } + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/visitor.go b/vendor/github.com/go-lintpack/lintpack/astwalk/visitor.go new file mode 100644 index 000000000..9f973a2b3 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/visitor.go @@ -0,0 +1,80 @@ +package astwalk + +import ( + "go/ast" +) + +// Visitor interfaces. +type ( + // DocCommentVisitor visits every doc-comment. + // Does not visit doc-comments for function-local definitions (types, etc). + // Also does not visit package doc-comment (file-level doc-comments). + DocCommentVisitor interface { + VisitDocComment(*ast.CommentGroup) + } + + // FuncDeclVisitor visits every top-level function declaration. + FuncDeclVisitor interface { + walkerEvents + VisitFuncDecl(*ast.FuncDecl) + } + + // ExprVisitor visits every expression inside AST file. + ExprVisitor interface { + walkerEvents + VisitExpr(ast.Expr) + } + + // LocalExprVisitor visits every expression inside function body. + LocalExprVisitor interface { + walkerEvents + VisitLocalExpr(ast.Expr) + } + + // StmtListVisitor visits every statement list inside function body. + // This includes block statement bodies as well as implicit blocks + // introduced by case clauses and alike. + StmtListVisitor interface { + walkerEvents + VisitStmtList([]ast.Stmt) + } + + // StmtVisitor visits every statement inside function body. + StmtVisitor interface { + walkerEvents + VisitStmt(ast.Stmt) + } + + // TypeExprVisitor visits every type describing expression. + // It also traverses struct types and interface types to run + // checker over their fields/method signatures. + TypeExprVisitor interface { + walkerEvents + VisitTypeExpr(ast.Expr) + } + + // LocalCommentVisitor visits every comment inside function body. + LocalCommentVisitor interface { + walkerEvents + VisitLocalComment(*ast.CommentGroup) + } + + // CommentVisitor visits every comment. + CommentVisitor interface { + walkerEvents + VisitComment(*ast.CommentGroup) + } +) + +// walkerEvents describes common hooks available for most visitor types. +type walkerEvents interface { + // EnterFile is called for every file that is about to be traversed. + // If false is returned, file is not visited. + EnterFile(*ast.File) bool + + // EnterFunc is called for every function declaration that is about + // to be traversed. If false is returned, function is not visited. + EnterFunc(*ast.FuncDecl) bool + + skipChilds() bool +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/walk_handler.go b/vendor/github.com/go-lintpack/lintpack/astwalk/walk_handler.go new file mode 100644 index 000000000..1f6e948d5 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/walk_handler.go @@ -0,0 +1,34 @@ +package astwalk + +import ( + "go/ast" +) + +// WalkHandler is a type to be embedded into every checker +// that uses astwalk walkers. +type WalkHandler struct { + // SkipChilds controls whether currently analyzed + // node childs should be traversed. + // + // Value is reset after each visitor invocation, + // so there is no need to set value back to false. + SkipChilds bool +} + +// EnterFile is a default walkerEvents.EnterFile implementation +// that reports every file as accepted candidate for checking. +func (w *WalkHandler) EnterFile(f *ast.File) bool { + return true +} + +// EnterFunc is a default walkerEvents.EnterFunc implementation +// that skips extern function (ones that do not have body). +func (w *WalkHandler) EnterFunc(decl *ast.FuncDecl) bool { + return decl.Body != nil +} + +func (w *WalkHandler) skipChilds() bool { + v := w.SkipChilds + w.SkipChilds = false + return v +} diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/walker.go new file mode 100644 index 000000000..fddae710a --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/astwalk/walker.go @@ -0,0 +1,57 @@ +package astwalk + +import ( + "go/types" + + "github.com/go-lintpack/lintpack" +) + +// WalkerForFuncDecl returns file walker implementation for FuncDeclVisitor. +func WalkerForFuncDecl(v FuncDeclVisitor) lintpack.FileWalker { + return &funcDeclWalker{visitor: v} +} + +// WalkerForExpr returns file walker implementation for ExprVisitor. +func WalkerForExpr(v ExprVisitor) lintpack.FileWalker { + return &exprWalker{visitor: v} +} + +// WalkerForLocalExpr returns file walker implementation for LocalExprVisitor. +func WalkerForLocalExpr(v LocalExprVisitor) lintpack.FileWalker { + return &localExprWalker{visitor: v} +} + +// WalkerForStmtList returns file walker implementation for StmtListVisitor. +func WalkerForStmtList(v StmtListVisitor) lintpack.FileWalker { + return &stmtListWalker{visitor: v} +} + +// WalkerForStmt returns file walker implementation for StmtVisitor. +func WalkerForStmt(v StmtVisitor) lintpack.FileWalker { + return &stmtWalker{visitor: v} +} + +// WalkerForTypeExpr returns file walker implementation for TypeExprVisitor. +func WalkerForTypeExpr(v TypeExprVisitor, info *types.Info) lintpack.FileWalker { + return &typeExprWalker{visitor: v, info: info} +} + +// WalkerForLocalComment returns file walker implementation for LocalCommentVisitor. +func WalkerForLocalComment(v LocalCommentVisitor) lintpack.FileWalker { + return &localCommentWalker{visitor: v} +} + +// WalkerForComment returns file walker implementation for CommentVisitor. +func WalkerForComment(v CommentVisitor) lintpack.FileWalker { + return &commentWalker{visitor: v} +} + +// WalkerForDocComment returns file walker implementation for DocCommentVisitor. +func WalkerForDocComment(v DocCommentVisitor) lintpack.FileWalker { + return &docCommentWalker{visitor: v} +} + +// WalkerForLocalDef returns file walker implementation for LocalDefVisitor. +func WalkerForLocalDef(v LocalDefVisitor, info *types.Info) lintpack.FileWalker { + return &localDefWalker{visitor: v, info: info} +} diff --git a/vendor/github.com/go-lintpack/lintpack/checkers_db.go b/vendor/github.com/go-lintpack/lintpack/checkers_db.go new file mode 100644 index 000000000..83d41b4e4 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/checkers_db.go @@ -0,0 +1,135 @@ +package lintpack + +import ( + "fmt" + "regexp" + "sort" + "strings" + + "github.com/go-toolsmith/astfmt" +) + +type checkerProto struct { + info *CheckerInfo + constructor func(*Context) *Checker +} + +// prototypes is a set of registered checkers that are not yet instantiated. +// Registration should be done with AddChecker function. +// Initialized checkers can be obtained with NewChecker function. +var prototypes = make(map[string]checkerProto) + +func getCheckersInfo() []*CheckerInfo { + infoList := make([]*CheckerInfo, 0, len(prototypes)) + for _, proto := range prototypes { + infoCopy := *proto.info + infoList = append(infoList, &infoCopy) + } + sort.Slice(infoList, func(i, j int) bool { + return infoList[i].Name < infoList[j].Name + }) + return infoList +} + +func addChecker(info *CheckerInfo, constructor func(*CheckerContext) FileWalker) { + if _, ok := prototypes[info.Name]; ok { + panic(fmt.Sprintf("checker with name %q already registered", info.Name)) + } + + // Validate param value type. + for pname, param := range info.Params { + switch param.Value.(type) { + case string, int, bool: + // OK. + default: + panic(fmt.Sprintf("unsupported %q param type value: %T", + pname, param.Value)) + } + } + + trimDocumentation := func(info *CheckerInfo) { + fields := []*string{ + &info.Summary, + &info.Details, + &info.Before, + &info.After, + &info.Note, + } + for _, f := range fields { + *f = strings.TrimSpace(*f) + } + } + + trimDocumentation(info) + + if err := validateCheckerInfo(info); err != nil { + panic(err) + } + + proto := checkerProto{ + info: info, + constructor: func(ctx *Context) *Checker { + var c Checker + c.Info = info + c.ctx = CheckerContext{ + Context: ctx, + printer: astfmt.NewPrinter(ctx.FileSet), + } + c.fileWalker = constructor(&c.ctx) + return &c + }, + } + + prototypes[info.Name] = proto +} + +func newChecker(ctx *Context, info *CheckerInfo) *Checker { + proto, ok := prototypes[info.Name] + if !ok { + panic(fmt.Sprintf("checker with name %q not registered", info.Name)) + } + return proto.constructor(ctx) +} + +func validateCheckerInfo(info *CheckerInfo) error { + steps := []func(*CheckerInfo) error{ + validateCheckerName, + validateCheckerDocumentation, + validateCheckerTags, + } + + for _, step := range steps { + if err := step(info); err != nil { + return fmt.Errorf("%q validation error: %v", info.Name, err) + } + } + return nil +} + +var validIdentRE = regexp.MustCompile(`^\w+$`) + +func validateCheckerName(info *CheckerInfo) error { + if !validIdentRE.MatchString(info.Name) { + return fmt.Errorf("checker name contains illegal chars") + } + return nil +} + +func validateCheckerDocumentation(info *CheckerInfo) error { + // TODO(Quasilyte): validate documentation. + return nil +} + +func validateCheckerTags(info *CheckerInfo) error { + tagSet := make(map[string]bool) + for _, tag := range info.Tags { + if tagSet[tag] { + return fmt.Errorf("duplicated tag %q", tag) + } + if !validIdentRE.MatchString(tag) { + return fmt.Errorf("checker tag %q contains illegal chars", tag) + } + tagSet[tag] = true + } + return nil +} diff --git a/vendor/github.com/go-lintpack/lintpack/context.go b/vendor/github.com/go-lintpack/lintpack/context.go new file mode 100644 index 000000000..8671e175c --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/context.go @@ -0,0 +1,35 @@ +package lintpack + +import ( + "go/ast" + "go/types" + "strconv" +) + +func resolvePkgObjects(ctx *Context, f *ast.File) { + ctx.PkgObjects = make(map[*types.PkgName]string, len(f.Imports)) + + for _, spec := range f.Imports { + if spec.Name != nil { + obj := ctx.TypesInfo.ObjectOf(spec.Name) + ctx.PkgObjects[obj.(*types.PkgName)] = spec.Name.Name + } else { + obj := ctx.TypesInfo.Implicits[spec] + ctx.PkgObjects[obj.(*types.PkgName)] = obj.Name() + } + } +} + +func resolvePkgRenames(ctx *Context, f *ast.File) { + ctx.PkgRenames = make(map[string]string) + + for _, spec := range f.Imports { + if spec.Name != nil { + path, err := strconv.Unquote(spec.Path.Value) + if err != nil { + panic(err) + } + ctx.PkgRenames[path] = spec.Name.Name + } + } +} diff --git a/vendor/github.com/go-lintpack/lintpack/doc.go b/vendor/github.com/go-lintpack/lintpack/doc.go new file mode 100644 index 000000000..4aba342f5 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/doc.go @@ -0,0 +1,5 @@ +// Package lintpack provides shared API between the linter and its checkers. +// +// Linter is usually implemented by creating instances of registered checkers. +// Checkers are registered by the AddChecker call. +package lintpack diff --git a/vendor/github.com/go-lintpack/lintpack/go.mod b/vendor/github.com/go-lintpack/lintpack/go.mod new file mode 100644 index 000000000..b2e4cd984 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/go.mod @@ -0,0 +1,11 @@ +module github.com/go-lintpack/lintpack + +require ( + github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6 + github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086 + github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30 + github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8 + github.com/google/go-cmp v0.2.0 + github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e + golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09 +) diff --git a/vendor/github.com/go-lintpack/lintpack/go.sum b/vendor/github.com/go-lintpack/lintpack/go.sum new file mode 100644 index 000000000..bd9f5dcb9 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/go.sum @@ -0,0 +1,14 @@ +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6 h1:aTBUNRTatDDU24gbOEKEoLiDwxtc98ga6K/iMTm6fvs= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086 h1:EIMuvbE9fbtQtimdLe5yeXjuC5CeKbQt8zH6GwtIrhM= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30 h1:zRJPftZJNLPDiOtvYbFRwjSbaJAcVOf80TeEmWGe2kQ= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8 h1:vVouagbdmqTVlCIAxpyYsNNTbkKZ3V66VpKOLU/s6W4= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09 h1:QJFxMApN9XdBRwtqXfOidB2azUCA4ziuiMTrQ1uBGxw= +golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/vendor/github.com/go-lintpack/lintpack/lintpack.go b/vendor/github.com/go-lintpack/lintpack/lintpack.go new file mode 100644 index 000000000..28c3a6354 --- /dev/null +++ b/vendor/github.com/go-lintpack/lintpack/lintpack.go @@ -0,0 +1,248 @@ +package lintpack + +import ( + "fmt" + "go/ast" + "go/token" + "go/types" + + "github.com/go-toolsmith/astfmt" +) + +// CheckerCollection provides additional information for a group of checkers. +type CheckerCollection struct { + // URL is a link for a main source of information on the collection. + URL string +} + +// AddChecker registers a new checker into a checkers pool. +// Constructor is used to create a new checker instance. +// Checker name (defined in CheckerInfo.Name) must be unique. +// +// CheckerInfo.Collection is automatically set to the coll (the receiver). +// +// If checker is never needed, for example if it is disabled, +// constructor will not be called. +func (coll *CheckerCollection) AddChecker(info *CheckerInfo, constructor func(*CheckerContext) FileWalker) { + if coll == nil { + panic(fmt.Sprintf("adding checker to a nil collection")) + } + info.Collection = coll + addChecker(info, constructor) +} + +// CheckerParam describes a single checker customizable parameter. +type CheckerParam struct { + // Value holds parameter bound value. + // It might be overwritten by the integrating linter. + // + // Permitted types include: + // - int + // - bool + // - string + Value interface{} + + // Usage gives an overview about what parameter does. + Usage string +} + +// CheckerParams holds all checker-specific parameters. +// +// Provides convenient access to the loosely typed underlying map. +type CheckerParams map[string]*CheckerParam + +// Int lookups pname key in underlying map and type-asserts it to int. +func (params CheckerParams) Int(pname string) int { return params[pname].Value.(int) } + +// Bool lookups pname key in underlying map and type-asserts it to bool. +func (params CheckerParams) Bool(pname string) bool { return params[pname].Value.(bool) } + +// String lookups pname key in underlying map and type-asserts it to string. +func (params CheckerParams) String(pname string) string { return params[pname].Value.(string) } + +// CheckerInfo holds checker metadata and structured documentation. +type CheckerInfo struct { + // Name is a checker name. + Name string + + // Tags is a list of labels that can be used to enable or disable checker. + // Common tags are "experimental" and "performance". + Tags []string + + // Params declares checker-specific parameters. Optional. + Params CheckerParams + + // Summary is a short one sentence description. + // Should not end with a period. + Summary string + + // Details extends summary with additional info. Optional. + Details string + + // Before is a code snippet of code that will violate rule. + Before string + + // After is a code snippet of fixed code that complies to the rule. + After string + + // Note is an optional caution message or advice. + Note string + + // Collection establishes a checker-to-collection relationship. + Collection *CheckerCollection +} + +// GetCheckersInfo returns a checkers info list for all registered checkers. +// The slice is sorted by a checker name. +// +// Info objects can be used to instantiate checkers with NewChecker function. +func GetCheckersInfo() []*CheckerInfo { + return getCheckersInfo() +} + +// HasTag reports whether checker described by the info has specified tag. +func (info *CheckerInfo) HasTag(tag string) bool { + for i := range info.Tags { + if info.Tags[i] == tag { + return true + } + } + return false +} + +// Checker is an implementation of a check that is described by the associated info. +type Checker struct { + // Info is an info object that was used to instantiate this checker. + Info *CheckerInfo + + ctx CheckerContext + + fileWalker FileWalker +} + +// Check runs rule checker over file f. +func (c *Checker) Check(f *ast.File) []Warning { + c.ctx.warnings = c.ctx.warnings[:0] + c.fileWalker.WalkFile(f) + return c.ctx.warnings +} + +// Warning represents issue that is found by checker. +type Warning struct { + // Node is an AST node that caused warning to trigger. + // Can be used to obtain proper error location. + Node ast.Node + + // Text is warning message without source location info. + Text string +} + +// NewChecker returns initialized checker identified by an info. +// info must be non-nil. +// Panics if info describes a checker that was not properly registered. +func NewChecker(ctx *Context, info *CheckerInfo) *Checker { + return newChecker(ctx, info) +} + +// Context is a readonly state shared among every checker. +type Context struct { + // TypesInfo carries parsed packages types information. + TypesInfo *types.Info + + // SizesInfo carries alignment and type size information. + // Arch-dependent. + SizesInfo types.Sizes + + // FileSet is a file set that was used during the program loading. + FileSet *token.FileSet + + // Pkg describes package that is being checked. + Pkg *types.Package + + // Filename is a currently checked file name. + Filename string + + // Require records what optional resources are required + // by the checkers set that use this context. + // + // Every require fields makes associated context field + // to be properly initialized. + // For example, Context.require.PkgObjects => Context.PkgObjects. + Require struct { + PkgObjects bool + PkgRenames bool + } + + // PkgObjects stores all imported packages and their local names. + PkgObjects map[*types.PkgName]string + + // PkgRenames maps package path to its local renaming. + // Contains no entries for packages that were imported without + // explicit local names. + PkgRenames map[string]string +} + +// NewContext returns new shared context to be used by every checker. +// +// All data carried by the context is readonly for checkers, +// but can be modified by the integrating application. +func NewContext(fset *token.FileSet, sizes types.Sizes) *Context { + return &Context{ + FileSet: fset, + SizesInfo: sizes, + TypesInfo: &types.Info{}, + } +} + +// SetPackageInfo sets package-related metadata. +// +// Must be called for every package being checked. +func (c *Context) SetPackageInfo(info *types.Info, pkg *types.Package) { + if info != nil { + // We do this kind of assignment to avoid + // changing c.typesInfo field address after + // every re-assignment. + *c.TypesInfo = *info + } + c.Pkg = pkg +} + +// SetFileInfo sets file-related metadata. +// +// Must be called for every source code file being checked. +func (c *Context) SetFileInfo(name string, f *ast.File) { + c.Filename = name + if c.Require.PkgObjects { + resolvePkgObjects(c, f) + } + if c.Require.PkgRenames { + resolvePkgRenames(c, f) + } +} + +// CheckerContext is checker-local context copy. +// Fields that are not from Context itself are writeable. +type CheckerContext struct { + *Context + + // printer used to format warning text. + printer *astfmt.Printer + + warnings []Warning +} + +// Warn adds a Warning to checker output. +func (ctx *CheckerContext) Warn(node ast.Node, format string, args ...interface{}) { + ctx.warnings = append(ctx.warnings, Warning{ + Text: ctx.printer.Sprintf(format, args...), + Node: node, + }) +} + +// FileWalker is an interface every checker should implement. +// +// The WalkFile method is executed for every Go file inside the +// package that is being checked. +type FileWalker interface { + WalkFile(*ast.File) +} diff --git a/vendor/github.com/go-toolsmith/astcast/.travis.yml b/vendor/github.com/go-toolsmith/astcast/.travis.yml new file mode 100644 index 000000000..c32ac0062 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcast/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.x +install: + - # Prevent default install action "go get -t -v ./...". +script: + - go get -t -v ./... + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/go-toolsmith/astcast/LICENSE b/vendor/github.com/go-toolsmith/astcast/LICENSE new file mode 100644 index 000000000..eef17180f --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcast/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 go-toolsmith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-toolsmith/astcast/README.md b/vendor/github.com/go-toolsmith/astcast/README.md new file mode 100644 index 000000000..b618da461 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcast/README.md @@ -0,0 +1,86 @@ +[![Go Report Card](https://goreportcard.com/badge/github.com/go-toolsmith/astcast)](https://goreportcard.com/report/github.com/go-toolsmith/astcast) +[![GoDoc](https://godoc.org/github.com/go-toolsmith/astcast?status.svg)](https://godoc.org/github.com/go-toolsmith/astcast) + +# astcast + +Package astcast wraps type assertion operations in such way that you don't have +to worry about nil pointer results anymore. + +## Installation + +```bash +go get -v github.com/go-toolsmith/astcast +``` + +## Example + +```go +package main + +import ( + "fmt" + + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/strparse" +) + +func main() { + x := strparse.Expr(`(foo * bar) + 1`) + + // x type is ast.Expr, we want to access bar operand + // that is a RHS of the LHS of the addition. + // Note that addition LHS (X field) is has parenthesis, + // so we have to remove them too. + + add := astcast.ToBinaryExpr(x) + mul := astcast.ToBinaryExpr(astcast.ToParenExpr(add.X).X) + bar := astcast.ToIdent(mul.Y) + fmt.Printf("%T %s\n", bar, bar.Name) // => *ast.Ident bar + + // If argument has different dynamic type, + // non-nil sentinel object of requested type is returned. + // Those sentinel objects are exported so if you need + // to know whether it was a nil interface value of + // failed type assertion, you can compare returned + // object with such a sentinel. + + y := astcast.ToCallExpr(strparse.Expr(`x`)) + if y == astcast.NilCallExpr { + fmt.Println("it is a sentinel, type assertion failed") + } +} +``` + +Without `astcast`, you would have to do a lots of type assertions: + +```go +package main + +import ( + "fmt" + + "github.com/go-toolsmith/strparse" +) + +func main() { + x := strparse.Expr(`(foo * bar) + 1`) + + add, ok := x.(*ast.BinaryExpr) + if !ok || add == nil { + return + } + additionLHS, ok := add.X.(*ast.ParenExpr) + if !ok || additionLHS == nil { + return + } + mul, ok := additionLHS.X.(*ast.BinaryExpr) + if !ok || mul == nil { + return + } + bar, ok := mul.Y.(*ast.Ident) + if !ok || bar == nil { + return + } + fmt.Printf("%T %s\n", bar, bar.Name) +} +``` diff --git a/vendor/github.com/go-toolsmith/astcast/astcast.go b/vendor/github.com/go-toolsmith/astcast/astcast.go new file mode 100644 index 000000000..746d568aa --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcast/astcast.go @@ -0,0 +1,590 @@ +// Code generated by astcast_generate.go; DO NOT EDIT + +// Package astcast wraps type assertion operations in such way that you don't have +// to worry about nil pointer results anymore. +package astcast + +import ( + "go/ast" +) + +// A set of sentinel nil-like values that are returned +// by all "casting" functions in case of failed type assertion. +var ( + NilArrayType = &ast.ArrayType{} + NilBadExpr = &ast.BadExpr{} + NilBasicLit = &ast.BasicLit{} + NilBinaryExpr = &ast.BinaryExpr{} + NilCallExpr = &ast.CallExpr{} + NilChanType = &ast.ChanType{} + NilCompositeLit = &ast.CompositeLit{} + NilEllipsis = &ast.Ellipsis{} + NilFuncLit = &ast.FuncLit{} + NilFuncType = &ast.FuncType{} + NilIdent = &ast.Ident{} + NilIndexExpr = &ast.IndexExpr{} + NilInterfaceType = &ast.InterfaceType{} + NilKeyValueExpr = &ast.KeyValueExpr{} + NilMapType = &ast.MapType{} + NilParenExpr = &ast.ParenExpr{} + NilSelectorExpr = &ast.SelectorExpr{} + NilSliceExpr = &ast.SliceExpr{} + NilStarExpr = &ast.StarExpr{} + NilStructType = &ast.StructType{} + NilTypeAssertExpr = &ast.TypeAssertExpr{} + NilUnaryExpr = &ast.UnaryExpr{} + NilAssignStmt = &ast.AssignStmt{} + NilBadStmt = &ast.BadStmt{} + NilBlockStmt = &ast.BlockStmt{} + NilBranchStmt = &ast.BranchStmt{} + NilCaseClause = &ast.CaseClause{} + NilCommClause = &ast.CommClause{} + NilDeclStmt = &ast.DeclStmt{} + NilDeferStmt = &ast.DeferStmt{} + NilEmptyStmt = &ast.EmptyStmt{} + NilExprStmt = &ast.ExprStmt{} + NilForStmt = &ast.ForStmt{} + NilGoStmt = &ast.GoStmt{} + NilIfStmt = &ast.IfStmt{} + NilIncDecStmt = &ast.IncDecStmt{} + NilLabeledStmt = &ast.LabeledStmt{} + NilRangeStmt = &ast.RangeStmt{} + NilReturnStmt = &ast.ReturnStmt{} + NilSelectStmt = &ast.SelectStmt{} + NilSendStmt = &ast.SendStmt{} + NilSwitchStmt = &ast.SwitchStmt{} + NilTypeSwitchStmt = &ast.TypeSwitchStmt{} + NilComment = &ast.Comment{} + NilCommentGroup = &ast.CommentGroup{} + NilFieldList = &ast.FieldList{} + NilFile = &ast.File{} + NilPackage = &ast.Package{} +) + +// ToArrayType returns x as a non-nil *ast.ArrayType. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilArrayType. +func ToArrayType(x ast.Node) *ast.ArrayType { + if x, ok := x.(*ast.ArrayType); ok { + return x + } + return NilArrayType +} + +// ToBadExpr returns x as a non-nil *ast.BadExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilBadExpr. +func ToBadExpr(x ast.Node) *ast.BadExpr { + if x, ok := x.(*ast.BadExpr); ok { + return x + } + return NilBadExpr +} + +// ToBasicLit returns x as a non-nil *ast.BasicLit. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilBasicLit. +func ToBasicLit(x ast.Node) *ast.BasicLit { + if x, ok := x.(*ast.BasicLit); ok { + return x + } + return NilBasicLit +} + +// ToBinaryExpr returns x as a non-nil *ast.BinaryExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilBinaryExpr. +func ToBinaryExpr(x ast.Node) *ast.BinaryExpr { + if x, ok := x.(*ast.BinaryExpr); ok { + return x + } + return NilBinaryExpr +} + +// ToCallExpr returns x as a non-nil *ast.CallExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilCallExpr. +func ToCallExpr(x ast.Node) *ast.CallExpr { + if x, ok := x.(*ast.CallExpr); ok { + return x + } + return NilCallExpr +} + +// ToChanType returns x as a non-nil *ast.ChanType. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilChanType. +func ToChanType(x ast.Node) *ast.ChanType { + if x, ok := x.(*ast.ChanType); ok { + return x + } + return NilChanType +} + +// ToCompositeLit returns x as a non-nil *ast.CompositeLit. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilCompositeLit. +func ToCompositeLit(x ast.Node) *ast.CompositeLit { + if x, ok := x.(*ast.CompositeLit); ok { + return x + } + return NilCompositeLit +} + +// ToEllipsis returns x as a non-nil *ast.Ellipsis. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilEllipsis. +func ToEllipsis(x ast.Node) *ast.Ellipsis { + if x, ok := x.(*ast.Ellipsis); ok { + return x + } + return NilEllipsis +} + +// ToFuncLit returns x as a non-nil *ast.FuncLit. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilFuncLit. +func ToFuncLit(x ast.Node) *ast.FuncLit { + if x, ok := x.(*ast.FuncLit); ok { + return x + } + return NilFuncLit +} + +// ToFuncType returns x as a non-nil *ast.FuncType. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilFuncType. +func ToFuncType(x ast.Node) *ast.FuncType { + if x, ok := x.(*ast.FuncType); ok { + return x + } + return NilFuncType +} + +// ToIdent returns x as a non-nil *ast.Ident. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilIdent. +func ToIdent(x ast.Node) *ast.Ident { + if x, ok := x.(*ast.Ident); ok { + return x + } + return NilIdent +} + +// ToIndexExpr returns x as a non-nil *ast.IndexExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilIndexExpr. +func ToIndexExpr(x ast.Node) *ast.IndexExpr { + if x, ok := x.(*ast.IndexExpr); ok { + return x + } + return NilIndexExpr +} + +// ToInterfaceType returns x as a non-nil *ast.InterfaceType. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilInterfaceType. +func ToInterfaceType(x ast.Node) *ast.InterfaceType { + if x, ok := x.(*ast.InterfaceType); ok { + return x + } + return NilInterfaceType +} + +// ToKeyValueExpr returns x as a non-nil *ast.KeyValueExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilKeyValueExpr. +func ToKeyValueExpr(x ast.Node) *ast.KeyValueExpr { + if x, ok := x.(*ast.KeyValueExpr); ok { + return x + } + return NilKeyValueExpr +} + +// ToMapType returns x as a non-nil *ast.MapType. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilMapType. +func ToMapType(x ast.Node) *ast.MapType { + if x, ok := x.(*ast.MapType); ok { + return x + } + return NilMapType +} + +// ToParenExpr returns x as a non-nil *ast.ParenExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilParenExpr. +func ToParenExpr(x ast.Node) *ast.ParenExpr { + if x, ok := x.(*ast.ParenExpr); ok { + return x + } + return NilParenExpr +} + +// ToSelectorExpr returns x as a non-nil *ast.SelectorExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilSelectorExpr. +func ToSelectorExpr(x ast.Node) *ast.SelectorExpr { + if x, ok := x.(*ast.SelectorExpr); ok { + return x + } + return NilSelectorExpr +} + +// ToSliceExpr returns x as a non-nil *ast.SliceExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilSliceExpr. +func ToSliceExpr(x ast.Node) *ast.SliceExpr { + if x, ok := x.(*ast.SliceExpr); ok { + return x + } + return NilSliceExpr +} + +// ToStarExpr returns x as a non-nil *ast.StarExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilStarExpr. +func ToStarExpr(x ast.Node) *ast.StarExpr { + if x, ok := x.(*ast.StarExpr); ok { + return x + } + return NilStarExpr +} + +// ToStructType returns x as a non-nil *ast.StructType. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilStructType. +func ToStructType(x ast.Node) *ast.StructType { + if x, ok := x.(*ast.StructType); ok { + return x + } + return NilStructType +} + +// ToTypeAssertExpr returns x as a non-nil *ast.TypeAssertExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilTypeAssertExpr. +func ToTypeAssertExpr(x ast.Node) *ast.TypeAssertExpr { + if x, ok := x.(*ast.TypeAssertExpr); ok { + return x + } + return NilTypeAssertExpr +} + +// ToUnaryExpr returns x as a non-nil *ast.UnaryExpr. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilUnaryExpr. +func ToUnaryExpr(x ast.Node) *ast.UnaryExpr { + if x, ok := x.(*ast.UnaryExpr); ok { + return x + } + return NilUnaryExpr +} + +// ToAssignStmt returns x as a non-nil *ast.AssignStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilAssignStmt. +func ToAssignStmt(x ast.Node) *ast.AssignStmt { + if x, ok := x.(*ast.AssignStmt); ok { + return x + } + return NilAssignStmt +} + +// ToBadStmt returns x as a non-nil *ast.BadStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilBadStmt. +func ToBadStmt(x ast.Node) *ast.BadStmt { + if x, ok := x.(*ast.BadStmt); ok { + return x + } + return NilBadStmt +} + +// ToBlockStmt returns x as a non-nil *ast.BlockStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilBlockStmt. +func ToBlockStmt(x ast.Node) *ast.BlockStmt { + if x, ok := x.(*ast.BlockStmt); ok { + return x + } + return NilBlockStmt +} + +// ToBranchStmt returns x as a non-nil *ast.BranchStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilBranchStmt. +func ToBranchStmt(x ast.Node) *ast.BranchStmt { + if x, ok := x.(*ast.BranchStmt); ok { + return x + } + return NilBranchStmt +} + +// ToCaseClause returns x as a non-nil *ast.CaseClause. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilCaseClause. +func ToCaseClause(x ast.Node) *ast.CaseClause { + if x, ok := x.(*ast.CaseClause); ok { + return x + } + return NilCaseClause +} + +// ToCommClause returns x as a non-nil *ast.CommClause. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilCommClause. +func ToCommClause(x ast.Node) *ast.CommClause { + if x, ok := x.(*ast.CommClause); ok { + return x + } + return NilCommClause +} + +// ToDeclStmt returns x as a non-nil *ast.DeclStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilDeclStmt. +func ToDeclStmt(x ast.Node) *ast.DeclStmt { + if x, ok := x.(*ast.DeclStmt); ok { + return x + } + return NilDeclStmt +} + +// ToDeferStmt returns x as a non-nil *ast.DeferStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilDeferStmt. +func ToDeferStmt(x ast.Node) *ast.DeferStmt { + if x, ok := x.(*ast.DeferStmt); ok { + return x + } + return NilDeferStmt +} + +// ToEmptyStmt returns x as a non-nil *ast.EmptyStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilEmptyStmt. +func ToEmptyStmt(x ast.Node) *ast.EmptyStmt { + if x, ok := x.(*ast.EmptyStmt); ok { + return x + } + return NilEmptyStmt +} + +// ToExprStmt returns x as a non-nil *ast.ExprStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilExprStmt. +func ToExprStmt(x ast.Node) *ast.ExprStmt { + if x, ok := x.(*ast.ExprStmt); ok { + return x + } + return NilExprStmt +} + +// ToForStmt returns x as a non-nil *ast.ForStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilForStmt. +func ToForStmt(x ast.Node) *ast.ForStmt { + if x, ok := x.(*ast.ForStmt); ok { + return x + } + return NilForStmt +} + +// ToGoStmt returns x as a non-nil *ast.GoStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilGoStmt. +func ToGoStmt(x ast.Node) *ast.GoStmt { + if x, ok := x.(*ast.GoStmt); ok { + return x + } + return NilGoStmt +} + +// ToIfStmt returns x as a non-nil *ast.IfStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilIfStmt. +func ToIfStmt(x ast.Node) *ast.IfStmt { + if x, ok := x.(*ast.IfStmt); ok { + return x + } + return NilIfStmt +} + +// ToIncDecStmt returns x as a non-nil *ast.IncDecStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilIncDecStmt. +func ToIncDecStmt(x ast.Node) *ast.IncDecStmt { + if x, ok := x.(*ast.IncDecStmt); ok { + return x + } + return NilIncDecStmt +} + +// ToLabeledStmt returns x as a non-nil *ast.LabeledStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilLabeledStmt. +func ToLabeledStmt(x ast.Node) *ast.LabeledStmt { + if x, ok := x.(*ast.LabeledStmt); ok { + return x + } + return NilLabeledStmt +} + +// ToRangeStmt returns x as a non-nil *ast.RangeStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilRangeStmt. +func ToRangeStmt(x ast.Node) *ast.RangeStmt { + if x, ok := x.(*ast.RangeStmt); ok { + return x + } + return NilRangeStmt +} + +// ToReturnStmt returns x as a non-nil *ast.ReturnStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilReturnStmt. +func ToReturnStmt(x ast.Node) *ast.ReturnStmt { + if x, ok := x.(*ast.ReturnStmt); ok { + return x + } + return NilReturnStmt +} + +// ToSelectStmt returns x as a non-nil *ast.SelectStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilSelectStmt. +func ToSelectStmt(x ast.Node) *ast.SelectStmt { + if x, ok := x.(*ast.SelectStmt); ok { + return x + } + return NilSelectStmt +} + +// ToSendStmt returns x as a non-nil *ast.SendStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilSendStmt. +func ToSendStmt(x ast.Node) *ast.SendStmt { + if x, ok := x.(*ast.SendStmt); ok { + return x + } + return NilSendStmt +} + +// ToSwitchStmt returns x as a non-nil *ast.SwitchStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilSwitchStmt. +func ToSwitchStmt(x ast.Node) *ast.SwitchStmt { + if x, ok := x.(*ast.SwitchStmt); ok { + return x + } + return NilSwitchStmt +} + +// ToTypeSwitchStmt returns x as a non-nil *ast.TypeSwitchStmt. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilTypeSwitchStmt. +func ToTypeSwitchStmt(x ast.Node) *ast.TypeSwitchStmt { + if x, ok := x.(*ast.TypeSwitchStmt); ok { + return x + } + return NilTypeSwitchStmt +} + +// ToComment returns x as a non-nil *ast.Comment. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilComment. +func ToComment(x ast.Node) *ast.Comment { + if x, ok := x.(*ast.Comment); ok { + return x + } + return NilComment +} + +// ToCommentGroup returns x as a non-nil *ast.CommentGroup. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilCommentGroup. +func ToCommentGroup(x ast.Node) *ast.CommentGroup { + if x, ok := x.(*ast.CommentGroup); ok { + return x + } + return NilCommentGroup +} + +// ToFieldList returns x as a non-nil *ast.FieldList. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilFieldList. +func ToFieldList(x ast.Node) *ast.FieldList { + if x, ok := x.(*ast.FieldList); ok { + return x + } + return NilFieldList +} + +// ToFile returns x as a non-nil *ast.File. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilFile. +func ToFile(x ast.Node) *ast.File { + if x, ok := x.(*ast.File); ok { + return x + } + return NilFile +} + +// ToPackage returns x as a non-nil *ast.Package. +// If ast.Node actually has such dynamic type, the result is +// identical to normal type assertion. In case if it has +// different type, the returned value is NilPackage. +func ToPackage(x ast.Node) *ast.Package { + if x, ok := x.(*ast.Package); ok { + return x + } + return NilPackage +} diff --git a/vendor/github.com/go-toolsmith/astcast/go.mod b/vendor/github.com/go-toolsmith/astcast/go.mod new file mode 100644 index 000000000..3e431993e --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcast/go.mod @@ -0,0 +1,6 @@ +module github.com/go-toolsmith/astcast + +require ( + github.com/go-toolsmith/astequal v1.0.0 // indirect + github.com/go-toolsmith/strparse v1.0.0 +) diff --git a/vendor/github.com/go-toolsmith/astcast/go.sum b/vendor/github.com/go-toolsmith/astcast/go.sum new file mode 100644 index 000000000..aa0857030 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcast/go.sum @@ -0,0 +1,4 @@ +github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= diff --git a/vendor/github.com/go-toolsmith/astcopy/.travis.yml b/vendor/github.com/go-toolsmith/astcopy/.travis.yml new file mode 100644 index 000000000..8994d395c --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcopy/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.x +install: + - # Prevent default install action "go get -t -v ./...". +script: + - go get -t -v ./... + - go tool vet . + - go test -v -race ./... \ No newline at end of file diff --git a/vendor/github.com/go-toolsmith/astcopy/LICENSE b/vendor/github.com/go-toolsmith/astcopy/LICENSE new file mode 100644 index 000000000..eef17180f --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcopy/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 go-toolsmith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-toolsmith/astcopy/README.md b/vendor/github.com/go-toolsmith/astcopy/README.md new file mode 100644 index 000000000..4dae5c41b --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcopy/README.md @@ -0,0 +1,41 @@ +[![Go Report Card](https://goreportcard.com/badge/github.com/go-toolsmith/astcopy)](https://goreportcard.com/report/github.com/go-toolsmith/astcopy) +[![GoDoc](https://godoc.org/github.com/go-toolsmith/astcopy?status.svg)](https://godoc.org/github.com/go-toolsmith/astcopy) +[![Build Status](https://travis-ci.org/go-toolsmith/astcopy.svg?branch=master)](https://travis-ci.org/go-toolsmith/astcopy) + +# astcopy + +Package astcopy implements Go AST reflection-free deep copy operations. + +## Installation: + +```bash +go get github.com/go-toolsmith/astcopy +``` + +## Example + +```go +package main + +import ( + "fmt" + "go/ast" + "go/token" + + "github.com/go-toolsmith/astcopy" + "github.com/go-toolsmith/astequal" + "github.com/go-toolsmith/strparse" +) + +func main() { + x := strparse.Expr(`1 + 2`).(*ast.BinaryExpr) + y := astcopy.BinaryExpr(x) + fmt.Println(astequal.Expr(x, y)) // => true + + // Now modify x and make sure y is not modified. + z := astcopy.BinaryExpr(y) + x.Op = token.SUB + fmt.Println(astequal.Expr(y, z)) // => true + fmt.Println(astequal.Expr(x, y)) // => false +} +``` diff --git a/vendor/github.com/go-toolsmith/astcopy/astcopy.go b/vendor/github.com/go-toolsmith/astcopy/astcopy.go new file mode 100644 index 000000000..2feffb199 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcopy/astcopy.go @@ -0,0 +1,955 @@ +// Package astcopy implements Go AST reflection-free deep copy operations. +package astcopy + +import ( + "go/ast" +) + +// Node returns x node deep copy. +// Copy of nil argument is nil. +func Node(x ast.Node) ast.Node { + return copyNode(x) +} + +// NodeList returns xs node slice deep copy. +// Copy of nil argument is nil. +func NodeList(xs []ast.Node) []ast.Node { + if xs == nil { + return nil + } + cp := make([]ast.Node, len(xs)) + for i := range xs { + cp[i] = copyNode(xs[i]) + } + return cp +} + +// Expr returns x expression deep copy. +// Copy of nil argument is nil. +func Expr(x ast.Expr) ast.Expr { + return copyExpr(x) +} + +// ExprList returns xs expression slice deep copy. +// Copy of nil argument is nil. +func ExprList(xs []ast.Expr) []ast.Expr { + if xs == nil { + return nil + } + cp := make([]ast.Expr, len(xs)) + for i := range xs { + cp[i] = copyExpr(xs[i]) + } + return cp +} + +// Stmt returns x statement deep copy. +// Copy of nil argument is nil. +func Stmt(x ast.Stmt) ast.Stmt { + return copyStmt(x) +} + +// StmtList returns xs statement slice deep copy. +// Copy of nil argument is nil. +func StmtList(xs []ast.Stmt) []ast.Stmt { + if xs == nil { + return nil + } + cp := make([]ast.Stmt, len(xs)) + for i := range xs { + cp[i] = copyStmt(xs[i]) + } + return cp +} + +// Decl returns x declaration deep copy. +// Copy of nil argument is nil. +func Decl(x ast.Decl) ast.Decl { + return copyDecl(x) +} + +// DeclList returns xs declaration slice deep copy. +// Copy of nil argument is nil. +func DeclList(xs []ast.Decl) []ast.Decl { + if xs == nil { + return nil + } + cp := make([]ast.Decl, len(xs)) + for i := range xs { + cp[i] = copyDecl(xs[i]) + } + return cp +} + +// BadExpr returns x deep copy. +// Copy of nil argument is nil. +func BadExpr(x *ast.BadExpr) *ast.BadExpr { + if x == nil { + return nil + } + cp := *x + return &cp +} + +// Ident returns x deep copy. +// Copy of nil argument is nil. +func Ident(x *ast.Ident) *ast.Ident { + if x == nil { + return nil + } + cp := *x + return &cp +} + +// IdentList returns xs identifier slice deep copy. +// Copy of nil argument is nil. +func IdentList(xs []*ast.Ident) []*ast.Ident { + if xs == nil { + return nil + } + cp := make([]*ast.Ident, len(xs)) + for i := range xs { + cp[i] = Ident(xs[i]) + } + return cp +} + +// Ellipsis returns x deep copy. +// Copy of nil argument is nil. +func Ellipsis(x *ast.Ellipsis) *ast.Ellipsis { + if x == nil { + return nil + } + cp := *x + cp.Elt = copyExpr(x.Elt) + return &cp +} + +// BasicLit returns x deep copy. +// Copy of nil argument is nil. +func BasicLit(x *ast.BasicLit) *ast.BasicLit { + if x == nil { + return nil + } + cp := *x + return &cp +} + +// FuncLit returns x deep copy. +// Copy of nil argument is nil. +func FuncLit(x *ast.FuncLit) *ast.FuncLit { + if x == nil { + return nil + } + cp := *x + cp.Type = FuncType(x.Type) + cp.Body = BlockStmt(x.Body) + return &cp +} + +// CompositeLit returns x deep copy. +// Copy of nil argument is nil. +func CompositeLit(x *ast.CompositeLit) *ast.CompositeLit { + if x == nil { + return nil + } + cp := *x + cp.Type = copyExpr(x.Type) + cp.Elts = ExprList(x.Elts) + return &cp +} + +// ParenExpr returns x deep copy. +// Copy of nil argument is nil. +func ParenExpr(x *ast.ParenExpr) *ast.ParenExpr { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + return &cp +} + +// SelectorExpr returns x deep copy. +// Copy of nil argument is nil. +func SelectorExpr(x *ast.SelectorExpr) *ast.SelectorExpr { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + cp.Sel = Ident(x.Sel) + return &cp +} + +// IndexExpr returns x deep copy. +// Copy of nil argument is nil. +func IndexExpr(x *ast.IndexExpr) *ast.IndexExpr { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + cp.Index = copyExpr(x.Index) + return &cp +} + +// SliceExpr returns x deep copy. +// Copy of nil argument is nil. +func SliceExpr(x *ast.SliceExpr) *ast.SliceExpr { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + cp.Low = copyExpr(x.Low) + cp.High = copyExpr(x.High) + cp.Max = copyExpr(x.Max) + return &cp +} + +// TypeAssertExpr returns x deep copy. +// Copy of nil argument is nil. +func TypeAssertExpr(x *ast.TypeAssertExpr) *ast.TypeAssertExpr { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + cp.Type = copyExpr(x.Type) + return &cp +} + +// CallExpr returns x deep copy. +// Copy of nil argument is nil. +func CallExpr(x *ast.CallExpr) *ast.CallExpr { + if x == nil { + return nil + } + cp := *x + cp.Fun = copyExpr(x.Fun) + cp.Args = ExprList(x.Args) + return &cp +} + +// StarExpr returns x deep copy. +// Copy of nil argument is nil. +func StarExpr(x *ast.StarExpr) *ast.StarExpr { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + return &cp +} + +// UnaryExpr returns x deep copy. +// Copy of nil argument is nil. +func UnaryExpr(x *ast.UnaryExpr) *ast.UnaryExpr { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + return &cp +} + +// BinaryExpr returns x deep copy. +// Copy of nil argument is nil. +func BinaryExpr(x *ast.BinaryExpr) *ast.BinaryExpr { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + cp.Y = copyExpr(x.Y) + return &cp +} + +// KeyValueExpr returns x deep copy. +// Copy of nil argument is nil. +func KeyValueExpr(x *ast.KeyValueExpr) *ast.KeyValueExpr { + if x == nil { + return nil + } + cp := *x + cp.Key = copyExpr(x.Key) + cp.Value = copyExpr(x.Value) + return &cp +} + +// ArrayType returns x deep copy. +// Copy of nil argument is nil. +func ArrayType(x *ast.ArrayType) *ast.ArrayType { + if x == nil { + return nil + } + cp := *x + cp.Len = copyExpr(x.Len) + cp.Elt = copyExpr(x.Elt) + return &cp +} + +// StructType returns x deep copy. +// Copy of nil argument is nil. +func StructType(x *ast.StructType) *ast.StructType { + if x == nil { + return nil + } + cp := *x + cp.Fields = FieldList(x.Fields) + return &cp +} + +// Field returns x deep copy. +// Copy of nil argument is nil. +func Field(x *ast.Field) *ast.Field { + if x == nil { + return nil + } + cp := *x + cp.Names = IdentList(x.Names) + cp.Type = copyExpr(x.Type) + cp.Tag = BasicLit(x.Tag) + cp.Doc = CommentGroup(x.Doc) + cp.Comment = CommentGroup(x.Comment) + return &cp +} + +// FieldList returns x deep copy. +// Copy of nil argument is nil. +func FieldList(x *ast.FieldList) *ast.FieldList { + if x == nil { + return nil + } + cp := *x + if x.List != nil { + cp.List = make([]*ast.Field, len(x.List)) + for i := range x.List { + cp.List[i] = Field(x.List[i]) + } + } + return &cp +} + +// FuncType returns x deep copy. +// Copy of nil argument is nil. +func FuncType(x *ast.FuncType) *ast.FuncType { + if x == nil { + return nil + } + cp := *x + cp.Params = FieldList(x.Params) + cp.Results = FieldList(x.Results) + return &cp +} + +// InterfaceType returns x deep copy. +// Copy of nil argument is nil. +func InterfaceType(x *ast.InterfaceType) *ast.InterfaceType { + if x == nil { + return nil + } + cp := *x + cp.Methods = FieldList(x.Methods) + return &cp +} + +// MapType returns x deep copy. +// Copy of nil argument is nil. +func MapType(x *ast.MapType) *ast.MapType { + if x == nil { + return nil + } + cp := *x + cp.Key = copyExpr(x.Key) + cp.Value = copyExpr(x.Value) + return &cp +} + +// ChanType returns x deep copy. +// Copy of nil argument is nil. +func ChanType(x *ast.ChanType) *ast.ChanType { + if x == nil { + return nil + } + cp := *x + cp.Value = copyExpr(x.Value) + return &cp +} + +// BlockStmt returns x deep copy. +// Copy of nil argument is nil. +func BlockStmt(x *ast.BlockStmt) *ast.BlockStmt { + if x == nil { + return nil + } + cp := *x + cp.List = StmtList(x.List) + return &cp +} + +// ImportSpec returns x deep copy. +// Copy of nil argument is nil. +func ImportSpec(x *ast.ImportSpec) *ast.ImportSpec { + if x == nil { + return nil + } + cp := *x + cp.Name = Ident(x.Name) + cp.Path = BasicLit(x.Path) + cp.Doc = CommentGroup(x.Doc) + cp.Comment = CommentGroup(x.Comment) + return &cp +} + +// ValueSpec returns x deep copy. +// Copy of nil argument is nil. +func ValueSpec(x *ast.ValueSpec) *ast.ValueSpec { + if x == nil { + return nil + } + cp := *x + cp.Names = IdentList(x.Names) + cp.Values = ExprList(x.Values) + cp.Type = copyExpr(x.Type) + cp.Doc = CommentGroup(x.Doc) + cp.Comment = CommentGroup(x.Comment) + return &cp +} + +// TypeSpec returns x deep copy. +// Copy of nil argument is nil. +func TypeSpec(x *ast.TypeSpec) *ast.TypeSpec { + if x == nil { + return nil + } + cp := *x + cp.Name = Ident(x.Name) + cp.Type = copyExpr(x.Type) + cp.Doc = CommentGroup(x.Doc) + cp.Comment = CommentGroup(x.Comment) + return &cp +} + +// Spec returns x deep copy. +// Copy of nil argument is nil. +func Spec(x ast.Spec) ast.Spec { + if x == nil { + return nil + } + + switch x := x.(type) { + case *ast.ImportSpec: + return ImportSpec(x) + case *ast.ValueSpec: + return ValueSpec(x) + case *ast.TypeSpec: + return TypeSpec(x) + default: + panic("unhandled spec") + } +} + +// SpecList returns xs spec slice deep copy. +// Copy of nil argument is nil. +func SpecList(xs []ast.Spec) []ast.Spec { + if xs == nil { + return nil + } + cp := make([]ast.Spec, len(xs)) + for i := range xs { + cp[i] = Spec(xs[i]) + } + return cp +} + +// BadStmt returns x deep copy. +// Copy of nil argument is nil. +func BadStmt(x *ast.BadStmt) *ast.BadStmt { + if x == nil { + return nil + } + cp := *x + return &cp +} + +// DeclStmt returns x deep copy. +// Copy of nil argument is nil. +func DeclStmt(x *ast.DeclStmt) *ast.DeclStmt { + if x == nil { + return nil + } + cp := *x + cp.Decl = copyDecl(x.Decl) + return &cp +} + +// EmptyStmt returns x deep copy. +// Copy of nil argument is nil. +func EmptyStmt(x *ast.EmptyStmt) *ast.EmptyStmt { + if x == nil { + return nil + } + cp := *x + return &cp +} + +// LabeledStmt returns x deep copy. +// Copy of nil argument is nil. +func LabeledStmt(x *ast.LabeledStmt) *ast.LabeledStmt { + if x == nil { + return nil + } + cp := *x + cp.Label = Ident(x.Label) + cp.Stmt = copyStmt(x.Stmt) + return &cp +} + +// ExprStmt returns x deep copy. +// Copy of nil argument is nil. +func ExprStmt(x *ast.ExprStmt) *ast.ExprStmt { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + return &cp +} + +// SendStmt returns x deep copy. +// Copy of nil argument is nil. +func SendStmt(x *ast.SendStmt) *ast.SendStmt { + if x == nil { + return nil + } + cp := *x + cp.Chan = copyExpr(x.Chan) + cp.Value = copyExpr(x.Value) + return &cp +} + +// IncDecStmt returns x deep copy. +// Copy of nil argument is nil. +func IncDecStmt(x *ast.IncDecStmt) *ast.IncDecStmt { + if x == nil { + return nil + } + cp := *x + cp.X = copyExpr(x.X) + return &cp +} + +// AssignStmt returns x deep copy. +// Copy of nil argument is nil. +func AssignStmt(x *ast.AssignStmt) *ast.AssignStmt { + if x == nil { + return nil + } + cp := *x + cp.Lhs = ExprList(x.Lhs) + cp.Rhs = ExprList(x.Rhs) + return &cp +} + +// GoStmt returns x deep copy. +// Copy of nil argument is nil. +func GoStmt(x *ast.GoStmt) *ast.GoStmt { + if x == nil { + return nil + } + cp := *x + cp.Call = CallExpr(x.Call) + return &cp +} + +// DeferStmt returns x deep copy. +// Copy of nil argument is nil. +func DeferStmt(x *ast.DeferStmt) *ast.DeferStmt { + if x == nil { + return nil + } + cp := *x + cp.Call = CallExpr(x.Call) + return &cp +} + +// ReturnStmt returns x deep copy. +// Copy of nil argument is nil. +func ReturnStmt(x *ast.ReturnStmt) *ast.ReturnStmt { + if x == nil { + return nil + } + cp := *x + cp.Results = ExprList(x.Results) + return &cp +} + +// BranchStmt returns x deep copy. +// Copy of nil argument is nil. +func BranchStmt(x *ast.BranchStmt) *ast.BranchStmt { + if x == nil { + return nil + } + cp := *x + cp.Label = Ident(x.Label) + return &cp +} + +// IfStmt returns x deep copy. +// Copy of nil argument is nil. +func IfStmt(x *ast.IfStmt) *ast.IfStmt { + if x == nil { + return nil + } + cp := *x + cp.Init = copyStmt(x.Init) + cp.Cond = copyExpr(x.Cond) + cp.Body = BlockStmt(x.Body) + cp.Else = copyStmt(x.Else) + return &cp +} + +// CaseClause returns x deep copy. +// Copy of nil argument is nil. +func CaseClause(x *ast.CaseClause) *ast.CaseClause { + if x == nil { + return nil + } + cp := *x + cp.List = ExprList(x.List) + cp.Body = StmtList(x.Body) + return &cp +} + +// SwitchStmt returns x deep copy. +// Copy of nil argument is nil. +func SwitchStmt(x *ast.SwitchStmt) *ast.SwitchStmt { + if x == nil { + return nil + } + cp := *x + cp.Init = copyStmt(x.Init) + cp.Tag = copyExpr(x.Tag) + cp.Body = BlockStmt(x.Body) + return &cp +} + +// TypeSwitchStmt returns x deep copy. +// Copy of nil argument is nil. +func TypeSwitchStmt(x *ast.TypeSwitchStmt) *ast.TypeSwitchStmt { + if x == nil { + return nil + } + cp := *x + cp.Init = copyStmt(x.Init) + cp.Assign = copyStmt(x.Assign) + cp.Body = BlockStmt(x.Body) + return &cp +} + +// CommClause returns x deep copy. +// Copy of nil argument is nil. +func CommClause(x *ast.CommClause) *ast.CommClause { + if x == nil { + return nil + } + cp := *x + cp.Comm = copyStmt(x.Comm) + cp.Body = StmtList(x.Body) + return &cp +} + +// SelectStmt returns x deep copy. +// Copy of nil argument is nil. +func SelectStmt(x *ast.SelectStmt) *ast.SelectStmt { + if x == nil { + return nil + } + cp := *x + cp.Body = BlockStmt(x.Body) + return &cp +} + +// ForStmt returns x deep copy. +// Copy of nil argument is nil. +func ForStmt(x *ast.ForStmt) *ast.ForStmt { + if x == nil { + return nil + } + cp := *x + cp.Init = copyStmt(x.Init) + cp.Cond = copyExpr(x.Cond) + cp.Post = copyStmt(x.Post) + cp.Body = BlockStmt(x.Body) + return &cp +} + +// RangeStmt returns x deep copy. +// Copy of nil argument is nil. +func RangeStmt(x *ast.RangeStmt) *ast.RangeStmt { + if x == nil { + return nil + } + cp := *x + cp.Key = copyExpr(x.Key) + cp.Value = copyExpr(x.Value) + cp.X = copyExpr(x.X) + cp.Body = BlockStmt(x.Body) + return &cp +} + +// Comment returns x deep copy. +// Copy of nil argument is nil. +func Comment(x *ast.Comment) *ast.Comment { + if x == nil { + return nil + } + cp := *x + return &cp +} + +// CommentGroup returns x deep copy. +// Copy of nil argument is nil. +func CommentGroup(x *ast.CommentGroup) *ast.CommentGroup { + if x == nil { + return nil + } + cp := *x + if x.List != nil { + cp.List = make([]*ast.Comment, len(x.List)) + for i := range x.List { + cp.List[i] = Comment(x.List[i]) + } + } + return &cp +} + +// File returns x deep copy. +// Copy of nil argument is nil. +func File(x *ast.File) *ast.File { + if x == nil { + return nil + } + cp := *x + cp.Doc = CommentGroup(x.Doc) + cp.Name = Ident(x.Name) + cp.Decls = DeclList(x.Decls) + cp.Imports = make([]*ast.ImportSpec, len(x.Imports)) + for i := range x.Imports { + cp.Imports[i] = ImportSpec(x.Imports[i]) + } + cp.Unresolved = IdentList(x.Unresolved) + cp.Comments = make([]*ast.CommentGroup, len(x.Comments)) + for i := range x.Comments { + cp.Comments[i] = CommentGroup(x.Comments[i]) + } + return &cp +} + +// Package returns x deep copy. +// Copy of nil argument is nil. +func Package(x *ast.Package) *ast.Package { + if x == nil { + return nil + } + cp := *x + cp.Files = make(map[string]*ast.File) + for filename, f := range x.Files { + cp.Files[filename] = f + } + return &cp +} + +// BadDecl returns x deep copy. +// Copy of nil argument is nil. +func BadDecl(x *ast.BadDecl) *ast.BadDecl { + if x == nil { + return nil + } + cp := *x + return &cp +} + +// GenDecl returns x deep copy. +// Copy of nil argument is nil. +func GenDecl(x *ast.GenDecl) *ast.GenDecl { + if x == nil { + return nil + } + cp := *x + cp.Specs = SpecList(x.Specs) + cp.Doc = CommentGroup(x.Doc) + return &cp +} + +// FuncDecl returns x deep copy. +// Copy of nil argument is nil. +func FuncDecl(x *ast.FuncDecl) *ast.FuncDecl { + if x == nil { + return nil + } + cp := *x + cp.Recv = FieldList(x.Recv) + cp.Name = Ident(x.Name) + cp.Type = FuncType(x.Type) + cp.Body = BlockStmt(x.Body) + cp.Doc = CommentGroup(x.Doc) + return &cp +} + +func copyNode(x ast.Node) ast.Node { + switch x := x.(type) { + case ast.Expr: + return copyExpr(x) + case ast.Stmt: + return copyStmt(x) + case ast.Decl: + return copyDecl(x) + + case ast.Spec: + return Spec(x) + case *ast.FieldList: + return FieldList(x) + case *ast.Comment: + return Comment(x) + case *ast.CommentGroup: + return CommentGroup(x) + case *ast.File: + return File(x) + case *ast.Package: + return Package(x) + + default: + panic("unhandled node") + } +} + +func copyExpr(x ast.Expr) ast.Expr { + if x == nil { + return nil + } + + switch x := x.(type) { + case *ast.BadExpr: + return BadExpr(x) + case *ast.Ident: + return Ident(x) + case *ast.Ellipsis: + return Ellipsis(x) + case *ast.BasicLit: + return BasicLit(x) + case *ast.FuncLit: + return FuncLit(x) + case *ast.CompositeLit: + return CompositeLit(x) + case *ast.ParenExpr: + return ParenExpr(x) + case *ast.SelectorExpr: + return SelectorExpr(x) + case *ast.IndexExpr: + return IndexExpr(x) + case *ast.SliceExpr: + return SliceExpr(x) + case *ast.TypeAssertExpr: + return TypeAssertExpr(x) + case *ast.CallExpr: + return CallExpr(x) + case *ast.StarExpr: + return StarExpr(x) + case *ast.UnaryExpr: + return UnaryExpr(x) + case *ast.BinaryExpr: + return BinaryExpr(x) + case *ast.KeyValueExpr: + return KeyValueExpr(x) + case *ast.ArrayType: + return ArrayType(x) + case *ast.StructType: + return StructType(x) + case *ast.FuncType: + return FuncType(x) + case *ast.InterfaceType: + return InterfaceType(x) + case *ast.MapType: + return MapType(x) + case *ast.ChanType: + return ChanType(x) + + default: + panic("unhandled expr") + } +} + +func copyStmt(x ast.Stmt) ast.Stmt { + if x == nil { + return nil + } + + switch x := x.(type) { + case *ast.BadStmt: + return BadStmt(x) + case *ast.DeclStmt: + return DeclStmt(x) + case *ast.EmptyStmt: + return EmptyStmt(x) + case *ast.LabeledStmt: + return LabeledStmt(x) + case *ast.ExprStmt: + return ExprStmt(x) + case *ast.SendStmt: + return SendStmt(x) + case *ast.IncDecStmt: + return IncDecStmt(x) + case *ast.AssignStmt: + return AssignStmt(x) + case *ast.GoStmt: + return GoStmt(x) + case *ast.DeferStmt: + return DeferStmt(x) + case *ast.ReturnStmt: + return ReturnStmt(x) + case *ast.BranchStmt: + return BranchStmt(x) + case *ast.BlockStmt: + return BlockStmt(x) + case *ast.IfStmt: + return IfStmt(x) + case *ast.CaseClause: + return CaseClause(x) + case *ast.SwitchStmt: + return SwitchStmt(x) + case *ast.TypeSwitchStmt: + return TypeSwitchStmt(x) + case *ast.CommClause: + return CommClause(x) + case *ast.SelectStmt: + return SelectStmt(x) + case *ast.ForStmt: + return ForStmt(x) + case *ast.RangeStmt: + return RangeStmt(x) + + default: + panic("unhandled stmt") + } +} + +func copyDecl(x ast.Decl) ast.Decl { + if x == nil { + return nil + } + + switch x := x.(type) { + case *ast.BadDecl: + return BadDecl(x) + case *ast.GenDecl: + return GenDecl(x) + case *ast.FuncDecl: + return FuncDecl(x) + + default: + panic("unhandled decl") + } +} diff --git a/vendor/github.com/go-toolsmith/astcopy/go.mod b/vendor/github.com/go-toolsmith/astcopy/go.mod new file mode 100644 index 000000000..6f3b3027a --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcopy/go.mod @@ -0,0 +1,6 @@ +module github.com/go-toolsmith/astcopy + +require ( + github.com/go-toolsmith/astequal v1.0.0 + github.com/go-toolsmith/strparse v1.0.0 +) diff --git a/vendor/github.com/go-toolsmith/astcopy/go.sum b/vendor/github.com/go-toolsmith/astcopy/go.sum new file mode 100644 index 000000000..aa0857030 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astcopy/go.sum @@ -0,0 +1,4 @@ +github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= diff --git a/vendor/github.com/go-toolsmith/astequal/.gitignore b/vendor/github.com/go-toolsmith/astequal/.gitignore new file mode 100644 index 000000000..f38c2b852 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astequal/.gitignore @@ -0,0 +1,5 @@ +bin +pkg +src/main +tmp + diff --git a/vendor/github.com/go-toolsmith/astequal/.travis.yml b/vendor/github.com/go-toolsmith/astequal/.travis.yml new file mode 100644 index 000000000..8994d395c --- /dev/null +++ b/vendor/github.com/go-toolsmith/astequal/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.x +install: + - # Prevent default install action "go get -t -v ./...". +script: + - go get -t -v ./... + - go tool vet . + - go test -v -race ./... \ No newline at end of file diff --git a/vendor/github.com/go-toolsmith/astequal/LICENSE b/vendor/github.com/go-toolsmith/astequal/LICENSE new file mode 100644 index 000000000..717f894f5 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astequal/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Iskander Sharipov / Quasilyte + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-toolsmith/astequal/README.md b/vendor/github.com/go-toolsmith/astequal/README.md new file mode 100644 index 000000000..b14f80f6f --- /dev/null +++ b/vendor/github.com/go-toolsmith/astequal/README.md @@ -0,0 +1,67 @@ +[![Go Report Card](https://goreportcard.com/badge/github.com/go-toolsmith/astequal)](https://goreportcard.com/report/github.com/go-toolsmith/astequal) +[![GoDoc](https://godoc.org/github.com/go-toolsmith/astequal?status.svg)](https://godoc.org/github.com/go-toolsmith/astequal) +[![Build Status](https://travis-ci.org/go-toolsmith/astequal.svg?branch=master)](https://travis-ci.org/go-toolsmith/astequal) + + +# astequal + +Package astequal provides AST (deep) equallity check operations. + +## Installation: + +```bash +go get github.com/go-toolsmith/astequal +``` + +## Example + +```go +package main + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "log" + "reflect" + + "github.com/go-toolsmith/astequal" +) + +func main() { + const code = ` + package foo + + func main() { + x := []int{1, 2, 3} + x := []int{1, 2, 3} + }` + + fset := token.NewFileSet() + pkg, err := parser.ParseFile(fset, "string", code, 0) + if err != nil { + log.Fatalf("parse error: %+v", err) + } + + fn := pkg.Decls[0].(*ast.FuncDecl) + x := fn.Body.List[0] + y := fn.Body.List[1] + + // Reflect DeepEqual will fail due to different Pos values. + // astequal only checks whether two nodes describe AST. + fmt.Println(reflect.DeepEqual(x, y)) // => false + fmt.Println(astequal.Node(x, y)) // => true + fmt.Println(astequal.Stmt(x, y)) // => true +} +``` + +## Performance + +`astequal` outperforms reflection-based comparison by a big margin: + +``` +BenchmarkEqualExpr/astequal.Expr-8 5000000 298 ns/op 0 B/op 0 allocs/op +BenchmarkEqualExpr/astequal.Node-8 3000000 409 ns/op 0 B/op 0 allocs/op +BenchmarkEqualExpr/reflect.DeepEqual-8 50000 38898 ns/op 10185 B/op 156 allocs/op +``` diff --git a/vendor/github.com/go-toolsmith/astequal/astequal.go b/vendor/github.com/go-toolsmith/astequal/astequal.go new file mode 100644 index 000000000..6a32d7218 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astequal/astequal.go @@ -0,0 +1,734 @@ +// Package astequal provides AST (deep) equallity check operations. +package astequal + +import ( + "go/ast" + "go/token" +) + +// Node reports whether two AST nodes are structurally (deep) equal. +// +// Nil arguments are permitted: true is returned if x and y are both nils. +// +// See also: Expr, Stmt, Decl functions. +func Node(x, y ast.Node) bool { + return astNodeEq(x, y) +} + +// Expr reports whether two AST expressions are structurally (deep) equal. +// +// Nil arguments are permitted: true is returned if x and y are both nils. +// ast.BadExpr comparison always yields false. +func Expr(x, y ast.Expr) bool { + return astExprEq(x, y) +} + +// Stmt reports whether two AST statements are structurally (deep) equal. +// +// Nil arguments are permitted: true is returned if x and y are both nils. +// ast.BadStmt comparison always yields false. +func Stmt(x, y ast.Stmt) bool { + return astStmtEq(x, y) +} + +// Decl reports whether two AST declarations are structurally (deep) equal. +// +// Nil arguments are permitted: true is returned if x and y are both nils. +// ast.BadDecl comparison always yields false. +func Decl(x, y ast.Decl) bool { + return astDeclEq(x, y) +} + +// Functions to perform deep equallity checks between arbitrary AST nodes. + +// Compare interface node types. +// +// Interfaces, as well as their values, can be nil. +// +// Even if AST does expect field X to be mandatory, +// nil checks are required as nodes can be constructed +// manually, or be partially invalid/incomplete. + +func astNodeEq(x, y ast.Node) bool { + switch x := x.(type) { + case ast.Expr: + y, ok := y.(ast.Expr) + return ok && astExprEq(x, y) + case ast.Stmt: + y, ok := y.(ast.Stmt) + return ok && astStmtEq(x, y) + case ast.Decl: + y, ok := y.(ast.Decl) + return ok && astDeclEq(x, y) + default: + return false + } +} + +func astExprEq(x, y ast.Expr) bool { + if x == nil || y == nil { + return x == y + } + + switch x := x.(type) { + case *ast.Ident: + y, ok := y.(*ast.Ident) + return ok && astIdentEq(x, y) + + case *ast.BasicLit: + y, ok := y.(*ast.BasicLit) + return ok && astBasicLitEq(x, y) + + case *ast.FuncLit: + y, ok := y.(*ast.FuncLit) + return ok && astFuncLitEq(x, y) + + case *ast.CompositeLit: + y, ok := y.(*ast.CompositeLit) + return ok && astCompositeLitEq(x, y) + + case *ast.ParenExpr: + y, ok := y.(*ast.ParenExpr) + return ok && astParenExprEq(x, y) + + case *ast.SelectorExpr: + y, ok := y.(*ast.SelectorExpr) + return ok && astSelectorExprEq(x, y) + + case *ast.IndexExpr: + y, ok := y.(*ast.IndexExpr) + return ok && astIndexExprEq(x, y) + + case *ast.SliceExpr: + y, ok := y.(*ast.SliceExpr) + return ok && astSliceExprEq(x, y) + + case *ast.TypeAssertExpr: + y, ok := y.(*ast.TypeAssertExpr) + return ok && astTypeAssertExprEq(x, y) + + case *ast.CallExpr: + y, ok := y.(*ast.CallExpr) + return ok && astCallExprEq(x, y) + + case *ast.StarExpr: + y, ok := y.(*ast.StarExpr) + return ok && astStarExprEq(x, y) + + case *ast.UnaryExpr: + y, ok := y.(*ast.UnaryExpr) + return ok && astUnaryExprEq(x, y) + + case *ast.BinaryExpr: + y, ok := y.(*ast.BinaryExpr) + return ok && astBinaryExprEq(x, y) + + case *ast.KeyValueExpr: + y, ok := y.(*ast.KeyValueExpr) + return ok && astKeyValueExprEq(x, y) + + case *ast.ArrayType: + y, ok := y.(*ast.ArrayType) + return ok && astArrayTypeEq(x, y) + + case *ast.StructType: + y, ok := y.(*ast.StructType) + return ok && astStructTypeEq(x, y) + + case *ast.FuncType: + y, ok := y.(*ast.FuncType) + return ok && astFuncTypeEq(x, y) + + case *ast.InterfaceType: + y, ok := y.(*ast.InterfaceType) + return ok && astInterfaceTypeEq(x, y) + + case *ast.MapType: + y, ok := y.(*ast.MapType) + return ok && astMapTypeEq(x, y) + + case *ast.ChanType: + y, ok := y.(*ast.ChanType) + return ok && astChanTypeEq(x, y) + + case *ast.Ellipsis: + y, ok := y.(*ast.Ellipsis) + return ok && astEllipsisEq(x, y) + + default: + return false + } +} + +func astStmtEq(x, y ast.Stmt) bool { + if x == nil || y == nil { + return x == y + } + + switch x := x.(type) { + case *ast.ExprStmt: + y, ok := y.(*ast.ExprStmt) + return ok && astExprStmtEq(x, y) + + case *ast.SendStmt: + y, ok := y.(*ast.SendStmt) + return ok && astSendStmtEq(x, y) + + case *ast.IncDecStmt: + y, ok := y.(*ast.IncDecStmt) + return ok && astIncDecStmtEq(x, y) + + case *ast.AssignStmt: + y, ok := y.(*ast.AssignStmt) + return ok && astAssignStmtEq(x, y) + + case *ast.GoStmt: + y, ok := y.(*ast.GoStmt) + return ok && astGoStmtEq(x, y) + + case *ast.DeferStmt: + y, ok := y.(*ast.DeferStmt) + return ok && astDeferStmtEq(x, y) + + case *ast.ReturnStmt: + y, ok := y.(*ast.ReturnStmt) + return ok && astReturnStmtEq(x, y) + + case *ast.BranchStmt: + y, ok := y.(*ast.BranchStmt) + return ok && astBranchStmtEq(x, y) + + case *ast.BlockStmt: + y, ok := y.(*ast.BlockStmt) + return ok && astBlockStmtEq(x, y) + + case *ast.IfStmt: + y, ok := y.(*ast.IfStmt) + return ok && astIfStmtEq(x, y) + + case *ast.CaseClause: + y, ok := y.(*ast.CaseClause) + return ok && astCaseClauseEq(x, y) + + case *ast.SwitchStmt: + y, ok := y.(*ast.SwitchStmt) + return ok && astSwitchStmtEq(x, y) + + case *ast.TypeSwitchStmt: + y, ok := y.(*ast.TypeSwitchStmt) + return ok && astTypeSwitchStmtEq(x, y) + + case *ast.CommClause: + y, ok := y.(*ast.CommClause) + return ok && astCommClauseEq(x, y) + + case *ast.SelectStmt: + y, ok := y.(*ast.SelectStmt) + return ok && astSelectStmtEq(x, y) + + case *ast.ForStmt: + y, ok := y.(*ast.ForStmt) + return ok && astForStmtEq(x, y) + + case *ast.RangeStmt: + y, ok := y.(*ast.RangeStmt) + return ok && astRangeStmtEq(x, y) + + case *ast.DeclStmt: + y, ok := y.(*ast.DeclStmt) + return ok && astDeclStmtEq(x, y) + + case *ast.LabeledStmt: + y, ok := y.(*ast.LabeledStmt) + return ok && astLabeledStmtEq(x, y) + + case *ast.EmptyStmt: + y, ok := y.(*ast.EmptyStmt) + return ok && astEmptyStmtEq(x, y) + + default: + return false + } +} + +func astDeclEq(x, y ast.Decl) bool { + if x == nil || y == nil { + return x == y + } + + switch x := x.(type) { + case *ast.GenDecl: + y, ok := y.(*ast.GenDecl) + return ok && astGenDeclEq(x, y) + + case *ast.FuncDecl: + y, ok := y.(*ast.FuncDecl) + return ok && astFuncDeclEq(x, y) + + default: + return false + } +} + +// Compare concrete nodes for equallity. +// +// Any node of pointer type permitted to be nil, +// hence nil checks are mandatory. + +func astIdentEq(x, y *ast.Ident) bool { + if x == nil || y == nil { + return x == y + } + return x.Name == y.Name +} + +func astKeyValueExprEq(x, y *ast.KeyValueExpr) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.Key, y.Key) && astExprEq(x.Value, y.Value) +} + +func astArrayTypeEq(x, y *ast.ArrayType) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.Len, y.Len) && astExprEq(x.Elt, y.Elt) +} + +func astStructTypeEq(x, y *ast.StructType) bool { + if x == nil || y == nil { + return x == y + } + return astFieldListEq(x.Fields, y.Fields) +} + +func astFuncTypeEq(x, y *ast.FuncType) bool { + if x == nil || y == nil { + return x == y + } + return astFieldListEq(x.Params, y.Params) && + astFieldListEq(x.Results, y.Results) +} + +func astBasicLitEq(x, y *ast.BasicLit) bool { + if x == nil || y == nil { + return x == y + } + return x.Kind == y.Kind && x.Value == y.Value +} + +func astBlockStmtEq(x, y *ast.BlockStmt) bool { + if x == nil || y == nil { + return x == y + } + return astStmtSliceEq(x.List, y.List) +} + +func astFieldEq(x, y *ast.Field) bool { + if x == nil || y == nil { + return x == y + } + return astIdentSliceEq(x.Names, y.Names) && + astExprEq(x.Type, y.Type) +} + +func astFuncLitEq(x, y *ast.FuncLit) bool { + if x == nil || y == nil { + return x == y + } + return astFuncTypeEq(x.Type, y.Type) && + astBlockStmtEq(x.Body, y.Body) +} + +func astCompositeLitEq(x, y *ast.CompositeLit) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.Type, y.Type) && + astExprSliceEq(x.Elts, y.Elts) +} + +func astSelectorExprEq(x, y *ast.SelectorExpr) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.X, y.X) && astIdentEq(x.Sel, y.Sel) +} + +func astIndexExprEq(x, y *ast.IndexExpr) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.X, y.X) && astExprEq(x.Index, y.Index) +} + +func astSliceExprEq(x, y *ast.SliceExpr) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.X, y.X) && + astExprEq(x.Low, y.Low) && + astExprEq(x.High, y.High) && + astExprEq(x.Max, y.Max) +} + +func astTypeAssertExprEq(x, y *ast.TypeAssertExpr) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.X, y.X) && astExprEq(x.Type, y.Type) +} + +func astInterfaceTypeEq(x, y *ast.InterfaceType) bool { + if x == nil || y == nil { + return x == y + } + return astFieldListEq(x.Methods, y.Methods) +} + +func astMapTypeEq(x, y *ast.MapType) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.Key, y.Key) && astExprEq(x.Value, y.Value) +} + +func astChanTypeEq(x, y *ast.ChanType) bool { + if x == nil || y == nil { + return x == y + } + return x.Dir == y.Dir && astExprEq(x.Value, y.Value) +} + +func astCallExprEq(x, y *ast.CallExpr) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.Fun, y.Fun) && + astExprSliceEq(x.Args, y.Args) && + (x.Ellipsis == 0) == (y.Ellipsis == 0) +} + +func astEllipsisEq(x, y *ast.Ellipsis) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.Elt, y.Elt) +} + +func astUnaryExprEq(x, y *ast.UnaryExpr) bool { + if x == nil || y == nil { + return x == y + } + return x.Op == y.Op && astExprEq(x.X, y.X) +} + +func astBinaryExprEq(x, y *ast.BinaryExpr) bool { + if x == nil || y == nil { + return x == y + } + return x.Op == y.Op && + astExprEq(x.X, y.X) && + astExprEq(x.Y, y.Y) +} + +func astParenExprEq(x, y *ast.ParenExpr) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.X, y.X) +} + +func astStarExprEq(x, y *ast.StarExpr) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.X, y.X) +} + +func astFieldListEq(x, y *ast.FieldList) bool { + if x == nil || y == nil { + return x == y + } + return astFieldSliceEq(x.List, y.List) +} + +func astEmptyStmtEq(x, y *ast.EmptyStmt) bool { + if x == nil || y == nil { + return x == y + } + return x.Implicit == y.Implicit +} + +func astLabeledStmtEq(x, y *ast.LabeledStmt) bool { + if x == nil || y == nil { + return x == y + } + return astIdentEq(x.Label, y.Label) && astStmtEq(x.Stmt, y.Stmt) +} + +func astExprStmtEq(x, y *ast.ExprStmt) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.X, y.X) +} + +func astSendStmtEq(x, y *ast.SendStmt) bool { + if x == nil || y == nil { + return x == y + } + return astExprEq(x.Chan, y.Chan) && astExprEq(x.Value, y.Value) +} + +func astDeclStmtEq(x, y *ast.DeclStmt) bool { + if x == nil || y == nil { + return x == y + } + return astDeclEq(x.Decl, y.Decl) +} + +func astIncDecStmtEq(x, y *ast.IncDecStmt) bool { + if x == nil || y == nil { + return x == y + } + return x.Tok == y.Tok && astExprEq(x.X, y.X) +} + +func astAssignStmtEq(x, y *ast.AssignStmt) bool { + if x == nil || y == nil { + return x == y + } + return x.Tok == y.Tok && + astExprSliceEq(x.Lhs, y.Lhs) && + astExprSliceEq(x.Rhs, y.Rhs) +} + +func astGoStmtEq(x, y *ast.GoStmt) bool { + if x == nil || y == nil { + return x == y + } + return astCallExprEq(x.Call, y.Call) +} + +func astDeferStmtEq(x, y *ast.DeferStmt) bool { + if x == nil || y == nil { + return x == y + } + return astCallExprEq(x.Call, y.Call) +} + +func astReturnStmtEq(x, y *ast.ReturnStmt) bool { + if x == nil || y == nil { + return x == y + } + return astExprSliceEq(x.Results, y.Results) +} + +func astBranchStmtEq(x, y *ast.BranchStmt) bool { + if x == nil || y == nil { + return x == y + } + return x.Tok == y.Tok && astIdentEq(x.Label, y.Label) +} + +func astIfStmtEq(x, y *ast.IfStmt) bool { + if x == nil || y == nil { + return x == y + } + return astStmtEq(x.Init, y.Init) && + astExprEq(x.Cond, y.Cond) && + astBlockStmtEq(x.Body, y.Body) && + astStmtEq(x.Else, y.Else) +} + +func astCaseClauseEq(x, y *ast.CaseClause) bool { + if x == nil || y == nil { + return x == y + } + return astExprSliceEq(x.List, y.List) && + astStmtSliceEq(x.Body, y.Body) +} + +func astSwitchStmtEq(x, y *ast.SwitchStmt) bool { + if x == nil || y == nil { + return x == y + } + return astStmtEq(x.Init, y.Init) && + astExprEq(x.Tag, y.Tag) && + astBlockStmtEq(x.Body, y.Body) +} + +func astTypeSwitchStmtEq(x, y *ast.TypeSwitchStmt) bool { + if x == nil || y == nil { + return x == y + } + return astStmtEq(x.Init, y.Init) && + astStmtEq(x.Assign, y.Assign) && + astBlockStmtEq(x.Body, y.Body) +} + +func astCommClauseEq(x, y *ast.CommClause) bool { + if x == nil || y == nil { + return x == y + } + return astStmtEq(x.Comm, y.Comm) && astStmtSliceEq(x.Body, y.Body) +} + +func astSelectStmtEq(x, y *ast.SelectStmt) bool { + if x == nil || y == nil { + return x == y + } + return astBlockStmtEq(x.Body, y.Body) +} + +func astForStmtEq(x, y *ast.ForStmt) bool { + if x == nil || y == nil { + return x == y + } + return astStmtEq(x.Init, y.Init) && + astExprEq(x.Cond, y.Cond) && + astStmtEq(x.Post, y.Post) && + astBlockStmtEq(x.Body, y.Body) +} + +func astRangeStmtEq(x, y *ast.RangeStmt) bool { + if x == nil || y == nil { + return x == y + } + return x.Tok == y.Tok && + astExprEq(x.Key, y.Key) && + astExprEq(x.Value, y.Value) && + astExprEq(x.X, y.X) && + astBlockStmtEq(x.Body, y.Body) +} + +func astFuncDeclEq(x, y *ast.FuncDecl) bool { + if x == nil || y == nil { + return x == y + } + return astFieldListEq(x.Recv, y.Recv) && + astIdentEq(x.Name, y.Name) && + astFuncTypeEq(x.Type, y.Type) && + astBlockStmtEq(x.Body, y.Body) +} + +func astGenDeclEq(x, y *ast.GenDecl) bool { + if x == nil || y == nil { + return x == y + } + + if x.Tok != y.Tok { + return false + } + if len(x.Specs) != len(y.Specs) { + return false + } + + switch x.Tok { + case token.IMPORT: + for i := range x.Specs { + xspec := x.Specs[i].(*ast.ImportSpec) + yspec := y.Specs[i].(*ast.ImportSpec) + if !astImportSpecEq(xspec, yspec) { + return false + } + } + case token.TYPE: + for i := range x.Specs { + xspec := x.Specs[i].(*ast.TypeSpec) + yspec := y.Specs[i].(*ast.TypeSpec) + if !astTypeSpecEq(xspec, yspec) { + return false + } + } + default: + for i := range x.Specs { + xspec := x.Specs[i].(*ast.ValueSpec) + yspec := y.Specs[i].(*ast.ValueSpec) + if !astValueSpecEq(xspec, yspec) { + return false + } + } + } + + return true +} + +func astImportSpecEq(x, y *ast.ImportSpec) bool { + if x == nil || y == nil { + return x == y + } + return astIdentEq(x.Name, y.Name) && astBasicLitEq(x.Path, y.Path) +} + +func astTypeSpecEq(x, y *ast.TypeSpec) bool { + if x == nil || y == nil { + return x == y + } + return astIdentEq(x.Name, y.Name) && astExprEq(x.Type, y.Type) +} + +func astValueSpecEq(x, y *ast.ValueSpec) bool { + if x == nil || y == nil { + return x == y + } + return astIdentSliceEq(x.Names, y.Names) && + astExprEq(x.Type, y.Type) && + astExprSliceEq(x.Values, y.Values) +} + +// Compare slices for equallity. +// +// Each slice element that has pointer type permitted to be nil, +// hence instead of using adhoc comparison of values, +// equallity functions that are defined above are used. + +func astIdentSliceEq(xs, ys []*ast.Ident) bool { + if len(xs) != len(ys) { + return false + } + for i := range xs { + if !astIdentEq(xs[i], ys[i]) { + return false + } + } + return true +} + +func astFieldSliceEq(xs, ys []*ast.Field) bool { + if len(xs) != len(ys) { + return false + } + for i := range xs { + if !astFieldEq(xs[i], ys[i]) { + return false + } + } + return true +} + +func astStmtSliceEq(xs, ys []ast.Stmt) bool { + if len(xs) != len(ys) { + return false + } + for i := range xs { + if !astStmtEq(xs[i], ys[i]) { + return false + } + } + return true +} + +func astExprSliceEq(xs, ys []ast.Expr) bool { + if len(xs) != len(ys) { + return false + } + for i := range xs { + if !astExprEq(xs[i], ys[i]) { + return false + } + } + return true +} diff --git a/vendor/github.com/go-toolsmith/astequal/go.mod b/vendor/github.com/go-toolsmith/astequal/go.mod new file mode 100644 index 000000000..86fa40772 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astequal/go.mod @@ -0,0 +1 @@ +module github.com/go-toolsmith/astequal diff --git a/vendor/github.com/go-toolsmith/astfmt/.travis.yml b/vendor/github.com/go-toolsmith/astfmt/.travis.yml new file mode 100644 index 000000000..c32ac0062 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astfmt/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.x +install: + - # Prevent default install action "go get -t -v ./...". +script: + - go get -t -v ./... + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/go-toolsmith/astfmt/LICENSE b/vendor/github.com/go-toolsmith/astfmt/LICENSE new file mode 100644 index 000000000..eef17180f --- /dev/null +++ b/vendor/github.com/go-toolsmith/astfmt/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 go-toolsmith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-toolsmith/astfmt/README.md b/vendor/github.com/go-toolsmith/astfmt/README.md new file mode 100644 index 000000000..954c92bf4 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astfmt/README.md @@ -0,0 +1,39 @@ +[![Go Report Card](https://goreportcard.com/badge/github.com/go-toolsmith/strparse)](https://goreportcard.com/report/github.com/go-toolsmith/strparse) +[![GoDoc](https://godoc.org/github.com/go-toolsmith/strparse?status.svg)](https://godoc.org/github.com/go-toolsmith/strparse) + + +# astfmt + +Package astfmt implements ast.Node formatting with fmt-like API. + +## Installation + +```bash +go get github.com/go-toolsmith/astfmt +``` + +## Example + +```go +package main + +import ( + "go/token" + "os" + + "github.com/go-toolsmith/astfmt" + "github.com/go-toolsmith/strparse" +) + +func Example() { + x := strparse.Expr(`foo(bar(baz(1+2)))`) + // astfmt functions add %s support for ast.Node arguments. + astfmt.Println(x) // => foo(bar(baz(1 + 2))) + astfmt.Fprintf(os.Stdout, "node=%s\n", x) // => node=foo(bar(baz(1 + 2))) + + // Can use specific file set with printer. + fset := token.NewFileSet() // Suppose this fset is used when parsing + pp := astfmt.NewPrinter(fset) + pp.Println(x) // => foo(bar(baz(1 + 2))) +} +``` diff --git a/vendor/github.com/go-toolsmith/astfmt/astfmt.go b/vendor/github.com/go-toolsmith/astfmt/astfmt.go new file mode 100644 index 000000000..ca993e033 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astfmt/astfmt.go @@ -0,0 +1,111 @@ +// Package astfmt implements `ast.Node` formatting with fmt-like API. +package astfmt + +import ( + "bytes" + "fmt" + "go/ast" + "go/printer" + "go/token" + "io" +) + +// Println calls fmt.Println with additional support of %s format +// for ast.Node arguments. +// +// Uses empty file set for AST printing. +func Println(args ...interface{}) error { + return defaultPrinter.Println(args...) +} + +// Fprintf calls fmt.Fprintf with additional support of %s format +// for ast.Node arguments. +// +// Uses empty file set for AST printing. +func Fprintf(w io.Writer, format string, args ...interface{}) error { + return defaultPrinter.Fprintf(w, format, args...) +} + +// Sprintf calls fmt.Sprintf with additional support of %s format +// for ast.Node arguments. +// +// Uses empty file set for AST printing. +func Sprintf(format string, args ...interface{}) string { + return defaultPrinter.Sprintf(format, args...) +} + +// Sprint calls fmt.Sprint with additional support of %s format +// for ast.Node arguments. +// +// Uses empty file set for AST printing. +func Sprint(args ...interface{}) string { + return defaultPrinter.Sprint(args...) +} + +// NewPrinter returns printer that uses bound file set when printing AST nodes. +func NewPrinter(fset *token.FileSet) *Printer { + return &Printer{fset: fset} +} + +// Printer provides API close to fmt package for printing AST nodes. +// Unlike freestanding functions from this package, it makes it possible +// to associate appropriate file set for better output. +type Printer struct { + fset *token.FileSet +} + +// Println printer method is like Println function, but uses bound file set when printing. +func (p *Printer) Println(args ...interface{}) error { + _, err := fmt.Println(wrapArgs(p.fset, args)...) + return err +} + +// Fprintf printer method is like Fprintf function, but uses bound file set when printing. +func (p *Printer) Fprintf(w io.Writer, format string, args ...interface{}) error { + _, err := fmt.Fprintf(w, format, wrapArgs(p.fset, args)...) + return err +} + +// Sprintf printer method is like Sprintf function, but uses bound file set when printing. +func (p *Printer) Sprintf(format string, args ...interface{}) string { + return fmt.Sprintf(format, wrapArgs(p.fset, args)...) +} + +// Sprint printer method is like Sprint function, but uses bound file set when printing. +func (p *Printer) Sprint(args ...interface{}) string { + return fmt.Sprint(wrapArgs(p.fset, args)...) +} + +// defaultPrinter is used in printing functions like Println. +// Uses empty file set. +var defaultPrinter = NewPrinter(token.NewFileSet()) + +// wrapArgs returns arguments slice with every ast.Node element +// replaced with fmtNode wrapper that supports additional formatting. +func wrapArgs(fset *token.FileSet, args []interface{}) []interface{} { + for i := range args { + if x, ok := args[i].(ast.Node); ok { + args[i] = fmtNode{fset: fset, node: x} + } + } + return args +} + +type fmtNode struct { + fset *token.FileSet + node ast.Node +} + +func (n fmtNode) String() string { + var buf bytes.Buffer + if err := printer.Fprint(&buf, n.fset, n.node); err != nil { + return fmt.Sprintf("%%!s(ast.Node=%s)", err) + } + return buf.String() +} + +func (n fmtNode) GoString() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "%#v", n.node) + return buf.String() +} diff --git a/vendor/github.com/go-toolsmith/astfmt/go.mod b/vendor/github.com/go-toolsmith/astfmt/go.mod new file mode 100644 index 000000000..d23db1566 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astfmt/go.mod @@ -0,0 +1,6 @@ +module github.com/go-toolsmith/astfmt + +require ( + github.com/go-toolsmith/astequal v1.0.0 // indirect + github.com/go-toolsmith/strparse v1.0.0 +) diff --git a/vendor/github.com/go-toolsmith/astfmt/go.sum b/vendor/github.com/go-toolsmith/astfmt/go.sum new file mode 100644 index 000000000..aa0857030 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astfmt/go.sum @@ -0,0 +1,4 @@ +github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= diff --git a/vendor/github.com/go-toolsmith/astp/.gitignore b/vendor/github.com/go-toolsmith/astp/.gitignore new file mode 100644 index 000000000..1f6187ecd --- /dev/null +++ b/vendor/github.com/go-toolsmith/astp/.gitignore @@ -0,0 +1,4 @@ +bin +pkg +src/main +tmp \ No newline at end of file diff --git a/vendor/github.com/go-toolsmith/astp/.travis.yml b/vendor/github.com/go-toolsmith/astp/.travis.yml new file mode 100644 index 000000000..8994d395c --- /dev/null +++ b/vendor/github.com/go-toolsmith/astp/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.x +install: + - # Prevent default install action "go get -t -v ./...". +script: + - go get -t -v ./... + - go tool vet . + - go test -v -race ./... \ No newline at end of file diff --git a/vendor/github.com/go-toolsmith/astp/LICENSE b/vendor/github.com/go-toolsmith/astp/LICENSE new file mode 100644 index 000000000..eef17180f --- /dev/null +++ b/vendor/github.com/go-toolsmith/astp/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 go-toolsmith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-toolsmith/astp/README.md b/vendor/github.com/go-toolsmith/astp/README.md new file mode 100644 index 000000000..7313c6ab8 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astp/README.md @@ -0,0 +1,39 @@ +[![Go Report Card](https://goreportcard.com/badge/github.com/go-toolsmith/astp)](https://goreportcard.com/report/github.com/go-toolsmith/astp) +[![GoDoc](https://godoc.org/github.com/go-toolsmith/astp?status.svg)](https://godoc.org/github.com/go-toolsmith/astp) +[![Build Status](https://travis-ci.org/go-toolsmith/astp.svg?branch=master)](https://travis-ci.org/go-toolsmith/astp) + + +# astp + +Package astp provides AST predicates. + +## Installation: + +```bash +go get github.com/go-toolsmith/astp +``` + +## Example + +```go +package main + +import ( + "fmt" + + "github.com/go-toolsmith/astp" + "github.com/go-toolsmith/strparse" +) + +func main() { + if astp.IsIdent(strparse.Expr(`x`)) { + fmt.Println("ident") + } + if astp.IsBlockStmt(strparse.Stmt(`{f()}`)) { + fmt.Println("block stmt") + } + if astp.IsGenDecl(strparse.Decl(`var x int = 10`)) { + fmt.Println("gen decl") + } +} +``` diff --git a/vendor/github.com/go-toolsmith/astp/decl.go b/vendor/github.com/go-toolsmith/astp/decl.go new file mode 100644 index 000000000..4654ad95c --- /dev/null +++ b/vendor/github.com/go-toolsmith/astp/decl.go @@ -0,0 +1,39 @@ +package astp + +import "go/ast" + +// IsDecl reports whether a node is a ast.Decl. +func IsDecl(node ast.Node) bool { + _, ok := node.(ast.Decl) + return ok +} + +// IsFuncDecl reports whether a given ast.Node is a function declaration (*ast.FuncDecl). +func IsFuncDecl(node ast.Node) bool { + _, ok := node.(*ast.FuncDecl) + return ok +} + +// IsGenDecl reports whether a given ast.Node is a generic declaration (*ast.GenDecl). +func IsGenDecl(node ast.Node) bool { + _, ok := node.(*ast.GenDecl) + return ok +} + +// IsImportSpec reports whether a given ast.Node is an import declaration (*ast.ImportSpec). +func IsImportSpec(node ast.Node) bool { + _, ok := node.(*ast.ImportSpec) + return ok +} + +// IsValueSpec reports whether a given ast.Node is a value declaration (*ast.ValueSpec). +func IsValueSpec(node ast.Node) bool { + _, ok := node.(*ast.ValueSpec) + return ok +} + +// IsTypeSpec reports whether a given ast.Node is a type declaration (*ast.TypeSpec). +func IsTypeSpec(node ast.Node) bool { + _, ok := node.(*ast.TypeSpec) + return ok +} diff --git a/vendor/github.com/go-toolsmith/astp/expr.go b/vendor/github.com/go-toolsmith/astp/expr.go new file mode 100644 index 000000000..adf9668ce --- /dev/null +++ b/vendor/github.com/go-toolsmith/astp/expr.go @@ -0,0 +1,141 @@ +package astp + +import "go/ast" + +// IsExpr reports whether a given ast.Node is an expression(ast.Expr). +func IsExpr(node ast.Node) bool { + _, ok := node.(ast.Expr) + return ok +} + +// IsBadExpr reports whether a given ast.Node is a bad expression (*ast.IsBadExpr). +func IsBadExpr(node ast.Node) bool { + _, ok := node.(*ast.BadExpr) + return ok +} + +// IsIdent reports whether a given ast.Node is an identifier (*ast.IsIdent). +func IsIdent(node ast.Node) bool { + _, ok := node.(*ast.Ident) + return ok +} + +// IsEllipsis reports whether a given ast.Node is an `...` (ellipsis) (*ast.IsEllipsis). +func IsEllipsis(node ast.Node) bool { + _, ok := node.(*ast.Ellipsis) + return ok +} + +// IsBasicLit reports whether a given ast.Node is a literal of basic type (*ast.IsBasicLit). +func IsBasicLit(node ast.Node) bool { + _, ok := node.(*ast.BasicLit) + return ok +} + +// IsFuncLit reports whether a given ast.Node is a function literal (*ast.IsFuncLit). +func IsFuncLit(node ast.Node) bool { + _, ok := node.(*ast.FuncLit) + return ok +} + +// IsCompositeLit reports whether a given ast.Node is a composite literal (*ast.IsCompositeLit). +func IsCompositeLit(node ast.Node) bool { + _, ok := node.(*ast.CompositeLit) + return ok +} + +// IsParenExpr reports whether a given ast.Node is a parenthesized expression (*ast.IsParenExpr). +func IsParenExpr(node ast.Node) bool { + _, ok := node.(*ast.ParenExpr) + return ok +} + +// IsSelectorExpr reports whether a given ast.Node is a selector expression (*ast.IsSelectorExpr). +func IsSelectorExpr(node ast.Node) bool { + _, ok := node.(*ast.SelectorExpr) + return ok +} + +// IsIndexExpr reports whether a given ast.Node is an index expression (*ast.IsIndexExpr). +func IsIndexExpr(node ast.Node) bool { + _, ok := node.(*ast.IndexExpr) + return ok +} + +// IsSliceExpr reports whether a given ast.Node is a slice expression (*ast.IsSliceExpr). +func IsSliceExpr(node ast.Node) bool { + _, ok := node.(*ast.SliceExpr) + return ok +} + +// IsTypeAssertExpr reports whether a given ast.Node is a type assert expression (*ast.IsTypeAssertExpr). +func IsTypeAssertExpr(node ast.Node) bool { + _, ok := node.(*ast.TypeAssertExpr) + return ok +} + +// IsCallExpr reports whether a given ast.Node is an expression followed by an argument list (*ast.IsCallExpr). +func IsCallExpr(node ast.Node) bool { + _, ok := node.(*ast.CallExpr) + return ok +} + +// IsStarExpr reports whether a given ast.Node is a star expression(unary "*" or apointer) (*ast.IsStarExpr) +func IsStarExpr(node ast.Node) bool { + _, ok := node.(*ast.StarExpr) + return ok +} + +// IsUnaryExpr reports whether a given ast.Node is a unary expression (*ast.IsUnaryExpr). +func IsUnaryExpr(node ast.Node) bool { + _, ok := node.(*ast.UnaryExpr) + return ok +} + +// IsBinaryExpr reports whether a given ast.Node is a binary expression (*ast.IsBinaryExpr). +func IsBinaryExpr(node ast.Node) bool { + _, ok := node.(*ast.BinaryExpr) + return ok +} + +// IsKeyValueExpr reports whether a given ast.Node is a (key:value) pair (*ast.IsKeyValueExpr). +func IsKeyValueExpr(node ast.Node) bool { + _, ok := node.(*ast.KeyValueExpr) + return ok +} + +// IsArrayType reports whether a given ast.Node is an array or slice type (*ast.IsArrayType). +func IsArrayType(node ast.Node) bool { + _, ok := node.(*ast.ArrayType) + return ok +} + +// IsStructType reports whether a given ast.Node is a struct type (*ast.IsStructType). +func IsStructType(node ast.Node) bool { + _, ok := node.(*ast.StructType) + return ok +} + +// IsFuncType reports whether a given ast.Node is a function type (*ast.IsFuncType). +func IsFuncType(node ast.Node) bool { + _, ok := node.(*ast.FuncType) + return ok +} + +// IsInterfaceType reports whether a given ast.Node is an interface type (*ast.IsInterfaceType). +func IsInterfaceType(node ast.Node) bool { + _, ok := node.(*ast.InterfaceType) + return ok +} + +// IsMapType reports whether a given ast.Node is a map type (*ast.IsMapType). +func IsMapType(node ast.Node) bool { + _, ok := node.(*ast.MapType) + return ok +} + +// IsChanType reports whether a given ast.Node is a channel type (*ast.IsChanType). +func IsChanType(node ast.Node) bool { + _, ok := node.(*ast.ChanType) + return ok +} diff --git a/vendor/github.com/go-toolsmith/astp/go.mod b/vendor/github.com/go-toolsmith/astp/go.mod new file mode 100644 index 000000000..023a09392 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astp/go.mod @@ -0,0 +1,6 @@ +module github.com/go-toolsmith/astp + +require ( + github.com/go-toolsmith/astequal v1.0.0 // indirect + github.com/go-toolsmith/strparse v1.0.0 +) diff --git a/vendor/github.com/go-toolsmith/astp/go.sum b/vendor/github.com/go-toolsmith/astp/go.sum new file mode 100644 index 000000000..aa0857030 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astp/go.sum @@ -0,0 +1,4 @@ +github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= diff --git a/vendor/github.com/go-toolsmith/astp/stmt.go b/vendor/github.com/go-toolsmith/astp/stmt.go new file mode 100644 index 000000000..19645d212 --- /dev/null +++ b/vendor/github.com/go-toolsmith/astp/stmt.go @@ -0,0 +1,135 @@ +package astp + +import "go/ast" + +// IsStmt reports whether a given ast.Node is a statement(ast.Stmt). +func IsStmt(node ast.Node) bool { + _, ok := node.(ast.Stmt) + return ok +} + +// IsBadStmt reports whether a given ast.Node is a bad statement(*ast.BadStmt) +func IsBadStmt(node ast.Node) bool { + _, ok := node.(*ast.BadStmt) + return ok +} + +// IsDeclStmt reports whether a given ast.Node is a declaration statement(*ast.DeclStmt) +func IsDeclStmt(node ast.Node) bool { + _, ok := node.(*ast.DeclStmt) + return ok +} + +// IsEmptyStmt reports whether a given ast.Node is an empty statement(*ast.EmptyStmt) +func IsEmptyStmt(node ast.Node) bool { + _, ok := node.(*ast.EmptyStmt) + return ok +} + +// IsLabeledStmt reports whether a given ast.Node is a label statement(*ast.LabeledStmt) +func IsLabeledStmt(node ast.Node) bool { + _, ok := node.(*ast.LabeledStmt) + return ok +} + +// IsExprStmt reports whether a given ast.Node is an expression statement(*ast.ExprStmt) +func IsExprStmt(node ast.Node) bool { + _, ok := node.(*ast.ExprStmt) + return ok +} + +// IsSendStmt reports whether a given ast.Node is a send to chan statement(*ast.SendStmt) +func IsSendStmt(node ast.Node) bool { + _, ok := node.(*ast.SendStmt) + return ok +} + +// IsIncDecStmt reports whether a given ast.Node is a increment/decrement statement(*ast.IncDecStmt) +func IsIncDecStmt(node ast.Node) bool { + _, ok := node.(*ast.IncDecStmt) + return ok +} + +// IsAssignStmt reports whether a given ast.Node is an assignment statement(*ast.AssignStmt) +func IsAssignStmt(node ast.Node) bool { + _, ok := node.(*ast.AssignStmt) + return ok +} + +// IsGoStmt reports whether a given ast.Node is a go statement(*ast.GoStmt) +func IsGoStmt(node ast.Node) bool { + _, ok := node.(*ast.GoStmt) + return ok +} + +// IsDeferStmt reports whether a given ast.Node is a defer statement(*ast.DeferStmt) +func IsDeferStmt(node ast.Node) bool { + _, ok := node.(*ast.DeferStmt) + return ok +} + +// IsReturnStmt reports whether a given ast.Node is a return statement(*ast.ReturnStmt) +func IsReturnStmt(node ast.Node) bool { + _, ok := node.(*ast.ReturnStmt) + return ok +} + +// IsBranchStmt reports whether a given ast.Node is a branch(goto/continue/break/fallthrough)statement(*ast.BranchStmt) +func IsBranchStmt(node ast.Node) bool { + _, ok := node.(*ast.BranchStmt) + return ok +} + +// IsBlockStmt reports whether a given ast.Node is a block statement(*ast.BlockStmt) +func IsBlockStmt(node ast.Node) bool { + _, ok := node.(*ast.BlockStmt) + return ok +} + +// IsIfStmt reports whether a given ast.Node is an if statement(*ast.IfStmt) +func IsIfStmt(node ast.Node) bool { + _, ok := node.(*ast.IfStmt) + return ok +} + +// IsCaseClause reports whether a given ast.Node is a case statement(*ast.CaseClause) +func IsCaseClause(node ast.Node) bool { + _, ok := node.(*ast.CaseClause) + return ok +} + +// IsSwitchStmt reports whether a given ast.Node is a switch statement(*ast.SwitchStmt) +func IsSwitchStmt(node ast.Node) bool { + _, ok := node.(*ast.SwitchStmt) + return ok +} + +// IsTypeSwitchStmt reports whether a given ast.Node is a type switch statement(*ast.TypeSwitchStmt) +func IsTypeSwitchStmt(node ast.Node) bool { + _, ok := node.(*ast.TypeSwitchStmt) + return ok +} + +// IsCommClause reports whether a given ast.Node is a select statement(*ast.CommClause) +func IsCommClause(node ast.Node) bool { + _, ok := node.(*ast.CommClause) + return ok +} + +// IsSelectStmt reports whether a given ast.Node is a selection statement(*ast.SelectStmt) +func IsSelectStmt(node ast.Node) bool { + _, ok := node.(*ast.SelectStmt) + return ok +} + +// IsForStmt reports whether a given ast.Node is a for statement(*ast.ForStmt) +func IsForStmt(node ast.Node) bool { + _, ok := node.(*ast.ForStmt) + return ok +} + +// IsRangeStmt reports whether a given ast.Node is a range statement(*ast.RangeStmt) +func IsRangeStmt(node ast.Node) bool { + _, ok := node.(*ast.RangeStmt) + return ok +} diff --git a/vendor/github.com/go-toolsmith/strparse/.travis.yml b/vendor/github.com/go-toolsmith/strparse/.travis.yml new file mode 100644 index 000000000..8994d395c --- /dev/null +++ b/vendor/github.com/go-toolsmith/strparse/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.x +install: + - # Prevent default install action "go get -t -v ./...". +script: + - go get -t -v ./... + - go tool vet . + - go test -v -race ./... \ No newline at end of file diff --git a/vendor/github.com/go-toolsmith/strparse/LICENSE b/vendor/github.com/go-toolsmith/strparse/LICENSE new file mode 100644 index 000000000..eef17180f --- /dev/null +++ b/vendor/github.com/go-toolsmith/strparse/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 go-toolsmith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-toolsmith/strparse/README.md b/vendor/github.com/go-toolsmith/strparse/README.md new file mode 100644 index 000000000..ae80a5398 --- /dev/null +++ b/vendor/github.com/go-toolsmith/strparse/README.md @@ -0,0 +1,34 @@ +[![Go Report Card](https://goreportcard.com/badge/github.com/go-toolsmith/strparse)](https://goreportcard.com/report/github.com/go-toolsmith/strparse) +[![GoDoc](https://godoc.org/github.com/go-toolsmith/strparse?status.svg)](https://godoc.org/github.com/go-toolsmith/strparse) +[![Build Status](https://travis-ci.org/go-toolsmith/strparse.svg?branch=master)](https://travis-ci.org/go-toolsmith/strparse) + + +# strparse + +Package strparse provides convenience wrappers around `go/parser` for simple +expression, statement and declaretion parsing from string. + +## Installation + +```bash +go get github.com/go-toolsmith/strparse +``` + +## Example + +```go +package main + +import ( + "go-toolsmith/astequal" + "go-toolsmith/strparse" +) + +func main() { + // Comparing AST strings for equallity (note different spacing): + x := strparse.Expr(`1 + f(v[0].X)`) + y := strparse.Expr(` 1+f( v[0].X ) `) + fmt.Println(astequal.Expr(x, y)) // => true +} + +``` diff --git a/vendor/github.com/go-toolsmith/strparse/go.mod b/vendor/github.com/go-toolsmith/strparse/go.mod new file mode 100644 index 000000000..ed9d88136 --- /dev/null +++ b/vendor/github.com/go-toolsmith/strparse/go.mod @@ -0,0 +1 @@ +module github.com/go-toolsmith/strparse diff --git a/vendor/github.com/go-toolsmith/strparse/strparse.go b/vendor/github.com/go-toolsmith/strparse/strparse.go new file mode 100644 index 000000000..894c7ebac --- /dev/null +++ b/vendor/github.com/go-toolsmith/strparse/strparse.go @@ -0,0 +1,59 @@ +// Package strparse provides convenience wrappers around `go/parser` for simple +// expression, statement and declaration parsing from string. +// +// Can be used to construct AST nodes using source syntax. +package strparse + +import ( + "go/ast" + "go/parser" + "go/token" +) + +var ( + // BadExpr is returned as a parse result for malformed expressions. + // Should be treated as constant or readonly variable. + BadExpr = &ast.BadExpr{} + + // BadStmt is returned as a parse result for malformed statmenents. + // Should be treated as constant or readonly variable. + BadStmt = &ast.BadStmt{} + + // BadDecl is returned as a parse result for malformed declarations. + // Should be treated as constant or readonly variable. + BadDecl = &ast.BadDecl{} +) + +// Expr parses single expression node from s. +// In case of parse error, BadExpr is returned. +func Expr(s string) ast.Expr { + node, err := parser.ParseExpr(s) + if err != nil { + return BadExpr + } + return node +} + +// Stmt parses single statement node from s. +// In case of parse error, BadStmt is returned. +func Stmt(s string) ast.Stmt { + node, err := parser.ParseFile(token.NewFileSet(), "", "package main;func main() {"+s+"}", 0) + if err != nil { + return BadStmt + } + fn := node.Decls[0].(*ast.FuncDecl) + if len(fn.Body.List) != 1 { + return BadStmt + } + return fn.Body.List[0] +} + +// Decl parses single declaration node from s. +// In case of parse error, BadDecl is returned. +func Decl(s string) ast.Decl { + node, err := parser.ParseFile(token.NewFileSet(), "", "package main;"+s, 0) + if err != nil || len(node.Decls) != 1 { + return BadDecl + } + return node.Decls[0] +} diff --git a/vendor/github.com/go-toolsmith/typep/.travis.yml b/vendor/github.com/go-toolsmith/typep/.travis.yml new file mode 100644 index 000000000..c32ac0062 --- /dev/null +++ b/vendor/github.com/go-toolsmith/typep/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.x +install: + - # Prevent default install action "go get -t -v ./...". +script: + - go get -t -v ./... + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/go-toolsmith/typep/LICENSE b/vendor/github.com/go-toolsmith/typep/LICENSE new file mode 100644 index 000000000..eef17180f --- /dev/null +++ b/vendor/github.com/go-toolsmith/typep/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 go-toolsmith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-toolsmith/typep/README.md b/vendor/github.com/go-toolsmith/typep/README.md new file mode 100644 index 000000000..736658012 --- /dev/null +++ b/vendor/github.com/go-toolsmith/typep/README.md @@ -0,0 +1,37 @@ +[![Go Report Card](https://goreportcard.com/badge/github.com/go-toolsmith/typep)](https://goreportcard.com/report/github.com/go-toolsmith/typep) +[![GoDoc](https://godoc.org/github.com/go-toolsmith/typep?status.svg)](https://godoc.org/github.com/go-toolsmith/typep) + + +# typep + +Package typep provides type predicates. + +## Installation: + +```bash +go get -v github.com/go-toolsmith/typep +``` + +## Example + +```go +package main + +import ( + "fmt" + + "github.com/go-toolsmith/typep" + "github.com/go-toolsmith/strparse" +) + +func main() { + floatTyp := types.Typ[types.Float32] + intTyp := types.Typ[types.Int] + ptr := types.NewPointer(intTyp) + arr := types.NewArray(intTyp, 64) + fmt.Println(typep.HasFloatProp(floatTyp)) // => true + fmt.Println(typep.HasFloatProp(intTyp)) // => false + fmt.Println(typep.IsPointer(ptr)) // => true + fmt.Println(typep.IsArray(arr)) // => true +} +``` diff --git a/vendor/github.com/go-toolsmith/typep/doc.go b/vendor/github.com/go-toolsmith/typep/doc.go new file mode 100644 index 000000000..990bc402c --- /dev/null +++ b/vendor/github.com/go-toolsmith/typep/doc.go @@ -0,0 +1,2 @@ +// Package typep provides type predicates. +package typep diff --git a/vendor/github.com/go-toolsmith/typep/go.mod b/vendor/github.com/go-toolsmith/typep/go.mod new file mode 100644 index 000000000..197a57d30 --- /dev/null +++ b/vendor/github.com/go-toolsmith/typep/go.mod @@ -0,0 +1 @@ +module github.com/go-toolsmith/typep diff --git a/vendor/github.com/go-toolsmith/typep/predicates.go b/vendor/github.com/go-toolsmith/typep/predicates.go new file mode 100644 index 000000000..70e5b55cd --- /dev/null +++ b/vendor/github.com/go-toolsmith/typep/predicates.go @@ -0,0 +1,36 @@ +package typep + +import ( + "go/ast" + "go/types" +) + +// IsTypeExpr reports whether x represents a type expression. +// +// Type expression does not evaluate to any run time value, +// but rather describes a type that is used inside Go expression. +// +// For example, (*T)(v) is a CallExpr that "calls" (*T). +// (*T) is a type expression that tells Go compiler type v should be converted to. +func IsTypeExpr(info *types.Info, x ast.Expr) bool { + switch x := x.(type) { + case *ast.StarExpr: + return IsTypeExpr(info, x.X) + case *ast.ParenExpr: + return IsTypeExpr(info, x.X) + case *ast.SelectorExpr: + return IsTypeExpr(info, x.Sel) + + case *ast.Ident: + // Identifier may be a type expression if object + // it reffers to is a type name. + _, ok := info.ObjectOf(x).(*types.TypeName) + return ok + + case *ast.FuncType, *ast.StructType, *ast.InterfaceType, *ast.ArrayType, *ast.MapType: + return true + + default: + return false + } +} diff --git a/vendor/github.com/go-toolsmith/typep/safeExpr.go b/vendor/github.com/go-toolsmith/typep/safeExpr.go new file mode 100644 index 000000000..7236e6e03 --- /dev/null +++ b/vendor/github.com/go-toolsmith/typep/safeExpr.go @@ -0,0 +1,62 @@ +package typep + +import ( + "go/ast" + "go/token" + "go/types" +) + +// SideEffectFree reports whether expr is softly safe expression and contains +// no significant side-effects. As opposed to strictly safe expressions, +// soft safe expressions permit some forms of side-effects, like +// panic possibility during indexing or nil pointer dereference. +// +// Uses types info to determine type conversion expressions that +// are the only permitted kinds of call expressions. +// Note that is does not check whether called function really +// has any side effects. The analysis is very conservative. +func SideEffectFree(info *types.Info, expr ast.Expr) bool { + // This list switch is not comprehensive and uses + // whitelist to be on the conservative side. + // Can be extended as needed. + + switch expr := expr.(type) { + case *ast.StarExpr: + return SideEffectFree(info, expr.X) + case *ast.BinaryExpr: + return SideEffectFree(info, expr.X) && + SideEffectFree(info, expr.Y) + case *ast.UnaryExpr: + return expr.Op != token.ARROW && + SideEffectFree(info, expr.X) + case *ast.BasicLit, *ast.Ident: + return true + case *ast.IndexExpr: + return SideEffectFree(info, expr.X) && + SideEffectFree(info, expr.Index) + case *ast.SelectorExpr: + return SideEffectFree(info, expr.X) + case *ast.ParenExpr: + return SideEffectFree(info, expr.X) + case *ast.CompositeLit: + return SideEffectFreeList(info, expr.Elts) + case *ast.CallExpr: + return IsTypeExpr(info, expr.Fun) && + SideEffectFreeList(info, expr.Args) + + default: + return false + } +} + +// SideEffectFreeList reports whether every expr in list is safe. +// +// See SideEffectFree. +func SideEffectFreeList(info *types.Info, list []ast.Expr) bool { + for _, expr := range list { + if !SideEffectFree(info, expr) { + return false + } + } + return true +} diff --git a/vendor/github.com/go-toolsmith/typep/simplePredicates.go b/vendor/github.com/go-toolsmith/typep/simplePredicates.go new file mode 100644 index 000000000..3bc9c29c8 --- /dev/null +++ b/vendor/github.com/go-toolsmith/typep/simplePredicates.go @@ -0,0 +1,359 @@ +// Code generated by simplePredicates_generate.go; DO NOT EDIT + +package typep + +import ( + "go/types" +) + +// Simple 1-to-1 type predicates via type assertion. + +// IsBasic reports whether a given type has *types.Basic type. +func IsBasic(typ types.Type) bool { + _, ok := typ.(*types.Basic) + return ok +} + +// IsArray reports whether a given type has *types.Array type. +func IsArray(typ types.Type) bool { + _, ok := typ.(*types.Array) + return ok +} + +// IsSlice reports whether a given type has *types.Slice type. +func IsSlice(typ types.Type) bool { + _, ok := typ.(*types.Slice) + return ok +} + +// IsStruct reports whether a given type has *types.Struct type. +func IsStruct(typ types.Type) bool { + _, ok := typ.(*types.Struct) + return ok +} + +// IsPointer reports whether a given type has *types.Pointer type. +func IsPointer(typ types.Type) bool { + _, ok := typ.(*types.Pointer) + return ok +} + +// IsTuple reports whether a given type has *types.Tuple type. +func IsTuple(typ types.Type) bool { + _, ok := typ.(*types.Tuple) + return ok +} + +// IsSignature reports whether a given type has *types.Signature type. +func IsSignature(typ types.Type) bool { + _, ok := typ.(*types.Signature) + return ok +} + +// IsInterface reports whether a given type has *types.Interface type. +func IsInterface(typ types.Type) bool { + _, ok := typ.(*types.Interface) + return ok +} + +// IsMap reports whether a given type has *types.Map type. +func IsMap(typ types.Type) bool { + _, ok := typ.(*types.Map) + return ok +} + +// IsChan reports whether a given type has *types.Chan type. +func IsChan(typ types.Type) bool { + _, ok := typ.(*types.Chan) + return ok +} + +// IsNamed reports whether a given type has *types.Named type. +func IsNamed(typ types.Type) bool { + _, ok := typ.(*types.Named) + return ok +} + +// *types.Basic predicates for the info field. + +// HasBooleanProp reports whether typ is a *types.Basic has IsBoolean property. +func HasBooleanProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsBoolean != 0 + } + return false +} + +// HasIntegerProp reports whether typ is a *types.Basic has IsInteger property. +func HasIntegerProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsInteger != 0 + } + return false +} + +// HasUnsignedProp reports whether typ is a *types.Basic has IsUnsigned property. +func HasUnsignedProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsUnsigned != 0 + } + return false +} + +// HasFloatProp reports whether typ is a *types.Basic has IsFloat property. +func HasFloatProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsFloat != 0 + } + return false +} + +// HasComplexProp reports whether typ is a *types.Basic has IsComplex property. +func HasComplexProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsComplex != 0 + } + return false +} + +// HasStringProp reports whether typ is a *types.Basic has IsString property. +func HasStringProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsString != 0 + } + return false +} + +// HasUntypedProp reports whether typ is a *types.Basic has IsUntyped property. +func HasUntypedProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsUntyped != 0 + } + return false +} + +// HasOrderedProp reports whether typ is a *types.Basic has IsOrdered property. +func HasOrderedProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsOrdered != 0 + } + return false +} + +// HasNumericProp reports whether typ is a *types.Basic has IsNumeric property. +func HasNumericProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsNumeric != 0 + } + return false +} + +// HasConstTypeProp reports whether typ is a *types.Basic has IsConstType property. +func HasConstTypeProp(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Info()&types.IsConstType != 0 + } + return false +} + +// *types.Basic predicates for the kind field. + +// HasBoolKind reports whether typ is a *types.Basic with its kind set to types.Bool. +func HasBoolKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Bool + } + return false +} + +// HasIntKind reports whether typ is a *types.Basic with its kind set to types.Int. +func HasIntKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Int + } + return false +} + +// HasInt8Kind reports whether typ is a *types.Basic with its kind set to types.Int8. +func HasInt8Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Int8 + } + return false +} + +// HasInt16Kind reports whether typ is a *types.Basic with its kind set to types.Int16. +func HasInt16Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Int16 + } + return false +} + +// HasInt32Kind reports whether typ is a *types.Basic with its kind set to types.Int32. +func HasInt32Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Int32 + } + return false +} + +// HasInt64Kind reports whether typ is a *types.Basic with its kind set to types.Int64. +func HasInt64Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Int64 + } + return false +} + +// HasUintKind reports whether typ is a *types.Basic with its kind set to types.Uint. +func HasUintKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Uint + } + return false +} + +// HasUint8Kind reports whether typ is a *types.Basic with its kind set to types.Uint8. +func HasUint8Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Uint8 + } + return false +} + +// HasUint16Kind reports whether typ is a *types.Basic with its kind set to types.Uint16. +func HasUint16Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Uint16 + } + return false +} + +// HasUint32Kind reports whether typ is a *types.Basic with its kind set to types.Uint32. +func HasUint32Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Uint32 + } + return false +} + +// HasUint64Kind reports whether typ is a *types.Basic with its kind set to types.Uint64. +func HasUint64Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Uint64 + } + return false +} + +// HasUintptrKind reports whether typ is a *types.Basic with its kind set to types.Uintptr. +func HasUintptrKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Uintptr + } + return false +} + +// HasFloat32Kind reports whether typ is a *types.Basic with its kind set to types.Float32. +func HasFloat32Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Float32 + } + return false +} + +// HasFloat64Kind reports whether typ is a *types.Basic with its kind set to types.Float64. +func HasFloat64Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Float64 + } + return false +} + +// HasComplex64Kind reports whether typ is a *types.Basic with its kind set to types.Complex64. +func HasComplex64Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Complex64 + } + return false +} + +// HasComplex128Kind reports whether typ is a *types.Basic with its kind set to types.Complex128. +func HasComplex128Kind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.Complex128 + } + return false +} + +// HasStringKind reports whether typ is a *types.Basic with its kind set to types.String. +func HasStringKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.String + } + return false +} + +// HasUnsafePointerKind reports whether typ is a *types.Basic with its kind set to types.UnsafePointer. +func HasUnsafePointerKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.UnsafePointer + } + return false +} + +// HasUntypedBoolKind reports whether typ is a *types.Basic with its kind set to types.UntypedBool. +func HasUntypedBoolKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.UntypedBool + } + return false +} + +// HasUntypedIntKind reports whether typ is a *types.Basic with its kind set to types.UntypedInt. +func HasUntypedIntKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.UntypedInt + } + return false +} + +// HasUntypedRuneKind reports whether typ is a *types.Basic with its kind set to types.UntypedRune. +func HasUntypedRuneKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.UntypedRune + } + return false +} + +// HasUntypedFloatKind reports whether typ is a *types.Basic with its kind set to types.UntypedFloat. +func HasUntypedFloatKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.UntypedFloat + } + return false +} + +// HasUntypedComplexKind reports whether typ is a *types.Basic with its kind set to types.UntypedComplex. +func HasUntypedComplexKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.UntypedComplex + } + return false +} + +// HasUntypedStringKind reports whether typ is a *types.Basic with its kind set to types.UntypedString. +func HasUntypedStringKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.UntypedString + } + return false +} + +// HasUntypedNilKind reports whether typ is a *types.Basic with its kind set to types.UntypedNil. +func HasUntypedNilKind(typ types.Type) bool { + if typ, ok := typ.(*types.Basic); ok { + return typ.Kind() == types.UntypedNil + } + return false +} diff --git a/vendor/github.com/gobwas/glob/.gitignore b/vendor/github.com/gobwas/glob/.gitignore new file mode 100644 index 000000000..b4ae623be --- /dev/null +++ b/vendor/github.com/gobwas/glob/.gitignore @@ -0,0 +1,8 @@ +glob.iml +.idea +*.cpu +*.mem +*.test +*.dot +*.png +*.svg diff --git a/vendor/github.com/gobwas/glob/.travis.yml b/vendor/github.com/gobwas/glob/.travis.yml new file mode 100644 index 000000000..e8a276826 --- /dev/null +++ b/vendor/github.com/gobwas/glob/.travis.yml @@ -0,0 +1,9 @@ +sudo: false + +language: go + +go: + - 1.5.3 + +script: + - go test -v ./... diff --git a/vendor/github.com/gobwas/glob/LICENSE b/vendor/github.com/gobwas/glob/LICENSE new file mode 100644 index 000000000..9d4735cad --- /dev/null +++ b/vendor/github.com/gobwas/glob/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Sergey Kamardin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/gobwas/glob/bench.sh b/vendor/github.com/gobwas/glob/bench.sh new file mode 100644 index 000000000..804cf22e6 --- /dev/null +++ b/vendor/github.com/gobwas/glob/bench.sh @@ -0,0 +1,26 @@ +#! /bin/bash + +bench() { + filename="/tmp/$1-$2.bench" + if test -e "${filename}"; + then + echo "Already exists ${filename}" + else + backup=`git rev-parse --abbrev-ref HEAD` + git checkout $1 + echo -n "Creating ${filename}... " + go test ./... -run=NONE -bench=$2 > "${filename}" -benchmem + echo "OK" + git checkout ${backup} + sleep 5 + fi +} + + +to=$1 +current=`git rev-parse --abbrev-ref HEAD` + +bench ${to} $2 +bench ${current} $2 + +benchcmp $3 "/tmp/${to}-$2.bench" "/tmp/${current}-$2.bench" diff --git a/vendor/github.com/gobwas/glob/compiler/compiler.go b/vendor/github.com/gobwas/glob/compiler/compiler.go new file mode 100644 index 000000000..02e7de80a --- /dev/null +++ b/vendor/github.com/gobwas/glob/compiler/compiler.go @@ -0,0 +1,525 @@ +package compiler + +// TODO use constructor with all matchers, and to their structs private +// TODO glue multiple Text nodes (like after QuoteMeta) + +import ( + "fmt" + "reflect" + + "github.com/gobwas/glob/match" + "github.com/gobwas/glob/syntax/ast" + "github.com/gobwas/glob/util/runes" +) + +func optimizeMatcher(matcher match.Matcher) match.Matcher { + switch m := matcher.(type) { + + case match.Any: + if len(m.Separators) == 0 { + return match.NewSuper() + } + + case match.AnyOf: + if len(m.Matchers) == 1 { + return m.Matchers[0] + } + + return m + + case match.List: + if m.Not == false && len(m.List) == 1 { + return match.NewText(string(m.List)) + } + + return m + + case match.BTree: + m.Left = optimizeMatcher(m.Left) + m.Right = optimizeMatcher(m.Right) + + r, ok := m.Value.(match.Text) + if !ok { + return m + } + + var ( + leftNil = m.Left == nil + rightNil = m.Right == nil + ) + if leftNil && rightNil { + return match.NewText(r.Str) + } + + _, leftSuper := m.Left.(match.Super) + lp, leftPrefix := m.Left.(match.Prefix) + la, leftAny := m.Left.(match.Any) + + _, rightSuper := m.Right.(match.Super) + rs, rightSuffix := m.Right.(match.Suffix) + ra, rightAny := m.Right.(match.Any) + + switch { + case leftSuper && rightSuper: + return match.NewContains(r.Str, false) + + case leftSuper && rightNil: + return match.NewSuffix(r.Str) + + case rightSuper && leftNil: + return match.NewPrefix(r.Str) + + case leftNil && rightSuffix: + return match.NewPrefixSuffix(r.Str, rs.Suffix) + + case rightNil && leftPrefix: + return match.NewPrefixSuffix(lp.Prefix, r.Str) + + case rightNil && leftAny: + return match.NewSuffixAny(r.Str, la.Separators) + + case leftNil && rightAny: + return match.NewPrefixAny(r.Str, ra.Separators) + } + + return m + } + + return matcher +} + +func compileMatchers(matchers []match.Matcher) (match.Matcher, error) { + if len(matchers) == 0 { + return nil, fmt.Errorf("compile error: need at least one matcher") + } + if len(matchers) == 1 { + return matchers[0], nil + } + if m := glueMatchers(matchers); m != nil { + return m, nil + } + + idx := -1 + maxLen := -1 + var val match.Matcher + for i, matcher := range matchers { + if l := matcher.Len(); l != -1 && l >= maxLen { + maxLen = l + idx = i + val = matcher + } + } + + if val == nil { // not found matcher with static length + r, err := compileMatchers(matchers[1:]) + if err != nil { + return nil, err + } + return match.NewBTree(matchers[0], nil, r), nil + } + + left := matchers[:idx] + var right []match.Matcher + if len(matchers) > idx+1 { + right = matchers[idx+1:] + } + + var l, r match.Matcher + var err error + if len(left) > 0 { + l, err = compileMatchers(left) + if err != nil { + return nil, err + } + } + + if len(right) > 0 { + r, err = compileMatchers(right) + if err != nil { + return nil, err + } + } + + return match.NewBTree(val, l, r), nil +} + +func glueMatchers(matchers []match.Matcher) match.Matcher { + if m := glueMatchersAsEvery(matchers); m != nil { + return m + } + if m := glueMatchersAsRow(matchers); m != nil { + return m + } + return nil +} + +func glueMatchersAsRow(matchers []match.Matcher) match.Matcher { + if len(matchers) <= 1 { + return nil + } + + var ( + c []match.Matcher + l int + ) + for _, matcher := range matchers { + if ml := matcher.Len(); ml == -1 { + return nil + } else { + c = append(c, matcher) + l += ml + } + } + return match.NewRow(l, c...) +} + +func glueMatchersAsEvery(matchers []match.Matcher) match.Matcher { + if len(matchers) <= 1 { + return nil + } + + var ( + hasAny bool + hasSuper bool + hasSingle bool + min int + separator []rune + ) + + for i, matcher := range matchers { + var sep []rune + + switch m := matcher.(type) { + case match.Super: + sep = []rune{} + hasSuper = true + + case match.Any: + sep = m.Separators + hasAny = true + + case match.Single: + sep = m.Separators + hasSingle = true + min++ + + case match.List: + if !m.Not { + return nil + } + sep = m.List + hasSingle = true + min++ + + default: + return nil + } + + // initialize + if i == 0 { + separator = sep + } + + if runes.Equal(sep, separator) { + continue + } + + return nil + } + + if hasSuper && !hasAny && !hasSingle { + return match.NewSuper() + } + + if hasAny && !hasSuper && !hasSingle { + return match.NewAny(separator) + } + + if (hasAny || hasSuper) && min > 0 && len(separator) == 0 { + return match.NewMin(min) + } + + every := match.NewEveryOf() + + if min > 0 { + every.Add(match.NewMin(min)) + + if !hasAny && !hasSuper { + every.Add(match.NewMax(min)) + } + } + + if len(separator) > 0 { + every.Add(match.NewContains(string(separator), true)) + } + + return every +} + +func minimizeMatchers(matchers []match.Matcher) []match.Matcher { + var done match.Matcher + var left, right, count int + + for l := 0; l < len(matchers); l++ { + for r := len(matchers); r > l; r-- { + if glued := glueMatchers(matchers[l:r]); glued != nil { + var swap bool + + if done == nil { + swap = true + } else { + cl, gl := done.Len(), glued.Len() + swap = cl > -1 && gl > -1 && gl > cl + swap = swap || count < r-l + } + + if swap { + done = glued + left = l + right = r + count = r - l + } + } + } + } + + if done == nil { + return matchers + } + + next := append(append([]match.Matcher{}, matchers[:left]...), done) + if right < len(matchers) { + next = append(next, matchers[right:]...) + } + + if len(next) == len(matchers) { + return next + } + + return minimizeMatchers(next) +} + +// minimizeAnyOf tries to apply some heuristics to minimize number of nodes in given tree +func minimizeTree(tree *ast.Node) *ast.Node { + switch tree.Kind { + case ast.KindAnyOf: + return minimizeTreeAnyOf(tree) + default: + return nil + } +} + +// minimizeAnyOf tries to find common children of given node of AnyOf pattern +// it searches for common children from left and from right +// if any common children are found – then it returns new optimized ast tree +// else it returns nil +func minimizeTreeAnyOf(tree *ast.Node) *ast.Node { + if !areOfSameKind(tree.Children, ast.KindPattern) { + return nil + } + + commonLeft, commonRight := commonChildren(tree.Children) + commonLeftCount, commonRightCount := len(commonLeft), len(commonRight) + if commonLeftCount == 0 && commonRightCount == 0 { // there are no common parts + return nil + } + + var result []*ast.Node + if commonLeftCount > 0 { + result = append(result, ast.NewNode(ast.KindPattern, nil, commonLeft...)) + } + + var anyOf []*ast.Node + for _, child := range tree.Children { + reuse := child.Children[commonLeftCount : len(child.Children)-commonRightCount] + var node *ast.Node + if len(reuse) == 0 { + // this pattern is completely reduced by commonLeft and commonRight patterns + // so it become nothing + node = ast.NewNode(ast.KindNothing, nil) + } else { + node = ast.NewNode(ast.KindPattern, nil, reuse...) + } + anyOf = appendIfUnique(anyOf, node) + } + switch { + case len(anyOf) == 1 && anyOf[0].Kind != ast.KindNothing: + result = append(result, anyOf[0]) + case len(anyOf) > 1: + result = append(result, ast.NewNode(ast.KindAnyOf, nil, anyOf...)) + } + + if commonRightCount > 0 { + result = append(result, ast.NewNode(ast.KindPattern, nil, commonRight...)) + } + + return ast.NewNode(ast.KindPattern, nil, result...) +} + +func commonChildren(nodes []*ast.Node) (commonLeft, commonRight []*ast.Node) { + if len(nodes) <= 1 { + return + } + + // find node that has least number of children + idx := leastChildren(nodes) + if idx == -1 { + return + } + tree := nodes[idx] + treeLength := len(tree.Children) + + // allocate max able size for rightCommon slice + // to get ability insert elements in reverse order (from end to start) + // without sorting + commonRight = make([]*ast.Node, treeLength) + lastRight := treeLength // will use this to get results as commonRight[lastRight:] + + var ( + breakLeft bool + breakRight bool + commonTotal int + ) + for i, j := 0, treeLength-1; commonTotal < treeLength && j >= 0 && !(breakLeft && breakRight); i, j = i+1, j-1 { + treeLeft := tree.Children[i] + treeRight := tree.Children[j] + + for k := 0; k < len(nodes) && !(breakLeft && breakRight); k++ { + // skip least children node + if k == idx { + continue + } + + restLeft := nodes[k].Children[i] + restRight := nodes[k].Children[j+len(nodes[k].Children)-treeLength] + + breakLeft = breakLeft || !treeLeft.Equal(restLeft) + + // disable searching for right common parts, if left part is already overlapping + breakRight = breakRight || (!breakLeft && j <= i) + breakRight = breakRight || !treeRight.Equal(restRight) + } + + if !breakLeft { + commonTotal++ + commonLeft = append(commonLeft, treeLeft) + } + if !breakRight { + commonTotal++ + lastRight = j + commonRight[j] = treeRight + } + } + + commonRight = commonRight[lastRight:] + + return +} + +func appendIfUnique(target []*ast.Node, val *ast.Node) []*ast.Node { + for _, n := range target { + if reflect.DeepEqual(n, val) { + return target + } + } + return append(target, val) +} + +func areOfSameKind(nodes []*ast.Node, kind ast.Kind) bool { + for _, n := range nodes { + if n.Kind != kind { + return false + } + } + return true +} + +func leastChildren(nodes []*ast.Node) int { + min := -1 + idx := -1 + for i, n := range nodes { + if idx == -1 || (len(n.Children) < min) { + min = len(n.Children) + idx = i + } + } + return idx +} + +func compileTreeChildren(tree *ast.Node, sep []rune) ([]match.Matcher, error) { + var matchers []match.Matcher + for _, desc := range tree.Children { + m, err := compile(desc, sep) + if err != nil { + return nil, err + } + matchers = append(matchers, optimizeMatcher(m)) + } + return matchers, nil +} + +func compile(tree *ast.Node, sep []rune) (m match.Matcher, err error) { + switch tree.Kind { + case ast.KindAnyOf: + // todo this could be faster on pattern_alternatives_combine_lite (see glob_test.go) + if n := minimizeTree(tree); n != nil { + return compile(n, sep) + } + matchers, err := compileTreeChildren(tree, sep) + if err != nil { + return nil, err + } + return match.NewAnyOf(matchers...), nil + + case ast.KindPattern: + if len(tree.Children) == 0 { + return match.NewNothing(), nil + } + matchers, err := compileTreeChildren(tree, sep) + if err != nil { + return nil, err + } + m, err = compileMatchers(minimizeMatchers(matchers)) + if err != nil { + return nil, err + } + + case ast.KindAny: + m = match.NewAny(sep) + + case ast.KindSuper: + m = match.NewSuper() + + case ast.KindSingle: + m = match.NewSingle(sep) + + case ast.KindNothing: + m = match.NewNothing() + + case ast.KindList: + l := tree.Value.(ast.List) + m = match.NewList([]rune(l.Chars), l.Not) + + case ast.KindRange: + r := tree.Value.(ast.Range) + m = match.NewRange(r.Lo, r.Hi, r.Not) + + case ast.KindText: + t := tree.Value.(ast.Text) + m = match.NewText(t.Text) + + default: + return nil, fmt.Errorf("could not compile tree: unknown node type") + } + + return optimizeMatcher(m), nil +} + +func Compile(tree *ast.Node, sep []rune) (match.Matcher, error) { + m, err := compile(tree, sep) + if err != nil { + return nil, err + } + + return m, nil +} diff --git a/vendor/github.com/gobwas/glob/glob.go b/vendor/github.com/gobwas/glob/glob.go new file mode 100644 index 000000000..2afde343a --- /dev/null +++ b/vendor/github.com/gobwas/glob/glob.go @@ -0,0 +1,80 @@ +package glob + +import ( + "github.com/gobwas/glob/compiler" + "github.com/gobwas/glob/syntax" +) + +// Glob represents compiled glob pattern. +type Glob interface { + Match(string) bool +} + +// Compile creates Glob for given pattern and strings (if any present after pattern) as separators. +// The pattern syntax is: +// +// pattern: +// { term } +// +// term: +// `*` matches any sequence of non-separator characters +// `**` matches any sequence of characters +// `?` matches any single non-separator character +// `[` [ `!` ] { character-range } `]` +// character class (must be non-empty) +// `{` pattern-list `}` +// pattern alternatives +// c matches character c (c != `*`, `**`, `?`, `\`, `[`, `{`, `}`) +// `\` c matches character c +// +// character-range: +// c matches character c (c != `\\`, `-`, `]`) +// `\` c matches character c +// lo `-` hi matches character c for lo <= c <= hi +// +// pattern-list: +// pattern { `,` pattern } +// comma-separated (without spaces) patterns +// +func Compile(pattern string, separators ...rune) (Glob, error) { + ast, err := syntax.Parse(pattern) + if err != nil { + return nil, err + } + + matcher, err := compiler.Compile(ast, separators) + if err != nil { + return nil, err + } + + return matcher, nil +} + +// MustCompile is the same as Compile, except that if Compile returns error, this will panic +func MustCompile(pattern string, separators ...rune) Glob { + g, err := Compile(pattern, separators...) + if err != nil { + panic(err) + } + + return g +} + +// QuoteMeta returns a string that quotes all glob pattern meta characters +// inside the argument text; For example, QuoteMeta(`{foo*}`) returns `\[foo\*\]`. +func QuoteMeta(s string) string { + b := make([]byte, 2*len(s)) + + // a byte loop is correct because all meta characters are ASCII + j := 0 + for i := 0; i < len(s); i++ { + if syntax.Special(s[i]) { + b[j] = '\\' + j++ + } + b[j] = s[i] + j++ + } + + return string(b[0:j]) +} diff --git a/vendor/github.com/gobwas/glob/match/any.go b/vendor/github.com/gobwas/glob/match/any.go new file mode 100644 index 000000000..514a9a5c4 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/any.go @@ -0,0 +1,45 @@ +package match + +import ( + "fmt" + "github.com/gobwas/glob/util/strings" +) + +type Any struct { + Separators []rune +} + +func NewAny(s []rune) Any { + return Any{s} +} + +func (self Any) Match(s string) bool { + return strings.IndexAnyRunes(s, self.Separators) == -1 +} + +func (self Any) Index(s string) (int, []int) { + found := strings.IndexAnyRunes(s, self.Separators) + switch found { + case -1: + case 0: + return 0, segments0 + default: + s = s[:found] + } + + segments := acquireSegments(len(s)) + for i := range s { + segments = append(segments, i) + } + segments = append(segments, len(s)) + + return 0, segments +} + +func (self Any) Len() int { + return lenNo +} + +func (self Any) String() string { + return fmt.Sprintf("", string(self.Separators)) +} diff --git a/vendor/github.com/gobwas/glob/match/any_of.go b/vendor/github.com/gobwas/glob/match/any_of.go new file mode 100644 index 000000000..8e65356cd --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/any_of.go @@ -0,0 +1,82 @@ +package match + +import "fmt" + +type AnyOf struct { + Matchers Matchers +} + +func NewAnyOf(m ...Matcher) AnyOf { + return AnyOf{Matchers(m)} +} + +func (self *AnyOf) Add(m Matcher) error { + self.Matchers = append(self.Matchers, m) + return nil +} + +func (self AnyOf) Match(s string) bool { + for _, m := range self.Matchers { + if m.Match(s) { + return true + } + } + + return false +} + +func (self AnyOf) Index(s string) (int, []int) { + index := -1 + + segments := acquireSegments(len(s)) + for _, m := range self.Matchers { + idx, seg := m.Index(s) + if idx == -1 { + continue + } + + if index == -1 || idx < index { + index = idx + segments = append(segments[:0], seg...) + continue + } + + if idx > index { + continue + } + + // here idx == index + segments = appendMerge(segments, seg) + } + + if index == -1 { + releaseSegments(segments) + return -1, nil + } + + return index, segments +} + +func (self AnyOf) Len() (l int) { + l = -1 + for _, m := range self.Matchers { + ml := m.Len() + switch { + case l == -1: + l = ml + continue + + case ml == -1: + return -1 + + case l != ml: + return -1 + } + } + + return +} + +func (self AnyOf) String() string { + return fmt.Sprintf("", self.Matchers) +} diff --git a/vendor/github.com/gobwas/glob/match/btree.go b/vendor/github.com/gobwas/glob/match/btree.go new file mode 100644 index 000000000..a8130e93e --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/btree.go @@ -0,0 +1,146 @@ +package match + +import ( + "fmt" + "unicode/utf8" +) + +type BTree struct { + Value Matcher + Left Matcher + Right Matcher + ValueLengthRunes int + LeftLengthRunes int + RightLengthRunes int + LengthRunes int +} + +func NewBTree(Value, Left, Right Matcher) (tree BTree) { + tree.Value = Value + tree.Left = Left + tree.Right = Right + + lenOk := true + if tree.ValueLengthRunes = Value.Len(); tree.ValueLengthRunes == -1 { + lenOk = false + } + + if Left != nil { + if tree.LeftLengthRunes = Left.Len(); tree.LeftLengthRunes == -1 { + lenOk = false + } + } + + if Right != nil { + if tree.RightLengthRunes = Right.Len(); tree.RightLengthRunes == -1 { + lenOk = false + } + } + + if lenOk { + tree.LengthRunes = tree.LeftLengthRunes + tree.ValueLengthRunes + tree.RightLengthRunes + } else { + tree.LengthRunes = -1 + } + + return tree +} + +func (self BTree) Len() int { + return self.LengthRunes +} + +// todo? +func (self BTree) Index(s string) (int, []int) { + return -1, nil +} + +func (self BTree) Match(s string) bool { + inputLen := len(s) + + // self.Length, self.RLen and self.LLen are values meaning the length of runes for each part + // here we manipulating byte length for better optimizations + // but these checks still works, cause minLen of 1-rune string is 1 byte. + if self.LengthRunes != -1 && self.LengthRunes > inputLen { + return false + } + + // try to cut unnecessary parts + // by knowledge of length of right and left part + var offset, limit int + if self.LeftLengthRunes >= 0 { + offset = self.LeftLengthRunes + } + if self.RightLengthRunes >= 0 { + limit = inputLen - self.RightLengthRunes + } else { + limit = inputLen + } + + for offset < limit { + // search for matching part in substring + index, segments := self.Value.Index(s[offset:limit]) + if index == -1 { + releaseSegments(segments) + return false + } + + l := s[:offset+index] + var left bool + if self.Left != nil { + left = self.Left.Match(l) + } else { + left = l == "" + } + + if left { + for i := len(segments) - 1; i >= 0; i-- { + length := segments[i] + + var right bool + var r string + // if there is no string for the right branch + if inputLen <= offset+index+length { + r = "" + } else { + r = s[offset+index+length:] + } + + if self.Right != nil { + right = self.Right.Match(r) + } else { + right = r == "" + } + + if right { + releaseSegments(segments) + return true + } + } + } + + _, step := utf8.DecodeRuneInString(s[offset+index:]) + offset += index + step + + releaseSegments(segments) + } + + return false +} + +func (self BTree) String() string { + const n string = "" + var l, r string + if self.Left == nil { + l = n + } else { + l = self.Left.String() + } + if self.Right == nil { + r = n + } else { + r = self.Right.String() + } + + return fmt.Sprintf("%s]>", l, self.Value, r) +} diff --git a/vendor/github.com/gobwas/glob/match/contains.go b/vendor/github.com/gobwas/glob/match/contains.go new file mode 100644 index 000000000..0998e95b0 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/contains.go @@ -0,0 +1,58 @@ +package match + +import ( + "fmt" + "strings" +) + +type Contains struct { + Needle string + Not bool +} + +func NewContains(needle string, not bool) Contains { + return Contains{needle, not} +} + +func (self Contains) Match(s string) bool { + return strings.Contains(s, self.Needle) != self.Not +} + +func (self Contains) Index(s string) (int, []int) { + var offset int + + idx := strings.Index(s, self.Needle) + + if !self.Not { + if idx == -1 { + return -1, nil + } + + offset = idx + len(self.Needle) + if len(s) <= offset { + return 0, []int{offset} + } + s = s[offset:] + } else if idx != -1 { + s = s[:idx] + } + + segments := acquireSegments(len(s) + 1) + for i := range s { + segments = append(segments, offset+i) + } + + return 0, append(segments, offset+len(s)) +} + +func (self Contains) Len() int { + return lenNo +} + +func (self Contains) String() string { + var not string + if self.Not { + not = "!" + } + return fmt.Sprintf("", not, self.Needle) +} diff --git a/vendor/github.com/gobwas/glob/match/every_of.go b/vendor/github.com/gobwas/glob/match/every_of.go new file mode 100644 index 000000000..7c968ee36 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/every_of.go @@ -0,0 +1,99 @@ +package match + +import ( + "fmt" +) + +type EveryOf struct { + Matchers Matchers +} + +func NewEveryOf(m ...Matcher) EveryOf { + return EveryOf{Matchers(m)} +} + +func (self *EveryOf) Add(m Matcher) error { + self.Matchers = append(self.Matchers, m) + return nil +} + +func (self EveryOf) Len() (l int) { + for _, m := range self.Matchers { + if ml := m.Len(); l > 0 { + l += ml + } else { + return -1 + } + } + + return +} + +func (self EveryOf) Index(s string) (int, []int) { + var index int + var offset int + + // make `in` with cap as len(s), + // cause it is the maximum size of output segments values + next := acquireSegments(len(s)) + current := acquireSegments(len(s)) + + sub := s + for i, m := range self.Matchers { + idx, seg := m.Index(sub) + if idx == -1 { + releaseSegments(next) + releaseSegments(current) + return -1, nil + } + + if i == 0 { + // we use copy here instead of `current = seg` + // cause seg is a slice from reusable buffer `in` + // and it could be overwritten in next iteration + current = append(current, seg...) + } else { + // clear the next + next = next[:0] + + delta := index - (idx + offset) + for _, ex := range current { + for _, n := range seg { + if ex+delta == n { + next = append(next, n) + } + } + } + + if len(next) == 0 { + releaseSegments(next) + releaseSegments(current) + return -1, nil + } + + current = append(current[:0], next...) + } + + index = idx + offset + sub = s[index:] + offset += idx + } + + releaseSegments(next) + + return index, current +} + +func (self EveryOf) Match(s string) bool { + for _, m := range self.Matchers { + if !m.Match(s) { + return false + } + } + + return true +} + +func (self EveryOf) String() string { + return fmt.Sprintf("", self.Matchers) +} diff --git a/vendor/github.com/gobwas/glob/match/list.go b/vendor/github.com/gobwas/glob/match/list.go new file mode 100644 index 000000000..7fd763ecd --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/list.go @@ -0,0 +1,49 @@ +package match + +import ( + "fmt" + "github.com/gobwas/glob/util/runes" + "unicode/utf8" +) + +type List struct { + List []rune + Not bool +} + +func NewList(list []rune, not bool) List { + return List{list, not} +} + +func (self List) Match(s string) bool { + r, w := utf8.DecodeRuneInString(s) + if len(s) > w { + return false + } + + inList := runes.IndexRune(self.List, r) != -1 + return inList == !self.Not +} + +func (self List) Len() int { + return lenOne +} + +func (self List) Index(s string) (int, []int) { + for i, r := range s { + if self.Not == (runes.IndexRune(self.List, r) == -1) { + return i, segmentsByRuneLength[utf8.RuneLen(r)] + } + } + + return -1, nil +} + +func (self List) String() string { + var not string + if self.Not { + not = "!" + } + + return fmt.Sprintf("", not, string(self.List)) +} diff --git a/vendor/github.com/gobwas/glob/match/match.go b/vendor/github.com/gobwas/glob/match/match.go new file mode 100644 index 000000000..f80e007fb --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/match.go @@ -0,0 +1,81 @@ +package match + +// todo common table of rune's length + +import ( + "fmt" + "strings" +) + +const lenOne = 1 +const lenZero = 0 +const lenNo = -1 + +type Matcher interface { + Match(string) bool + Index(string) (int, []int) + Len() int + String() string +} + +type Matchers []Matcher + +func (m Matchers) String() string { + var s []string + for _, matcher := range m { + s = append(s, fmt.Sprint(matcher)) + } + + return fmt.Sprintf("%s", strings.Join(s, ",")) +} + +// appendMerge merges and sorts given already SORTED and UNIQUE segments. +func appendMerge(target, sub []int) []int { + lt, ls := len(target), len(sub) + out := make([]int, 0, lt+ls) + + for x, y := 0, 0; x < lt || y < ls; { + if x >= lt { + out = append(out, sub[y:]...) + break + } + + if y >= ls { + out = append(out, target[x:]...) + break + } + + xValue := target[x] + yValue := sub[y] + + switch { + + case xValue == yValue: + out = append(out, xValue) + x++ + y++ + + case xValue < yValue: + out = append(out, xValue) + x++ + + case yValue < xValue: + out = append(out, yValue) + y++ + + } + } + + target = append(target[:0], out...) + + return target +} + +func reverseSegments(input []int) { + l := len(input) + m := l / 2 + + for i := 0; i < m; i++ { + input[i], input[l-i-1] = input[l-i-1], input[i] + } +} diff --git a/vendor/github.com/gobwas/glob/match/max.go b/vendor/github.com/gobwas/glob/match/max.go new file mode 100644 index 000000000..d72f69eff --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/max.go @@ -0,0 +1,49 @@ +package match + +import ( + "fmt" + "unicode/utf8" +) + +type Max struct { + Limit int +} + +func NewMax(l int) Max { + return Max{l} +} + +func (self Max) Match(s string) bool { + var l int + for range s { + l += 1 + if l > self.Limit { + return false + } + } + + return true +} + +func (self Max) Index(s string) (int, []int) { + segments := acquireSegments(self.Limit + 1) + segments = append(segments, 0) + var count int + for i, r := range s { + count++ + if count > self.Limit { + break + } + segments = append(segments, i+utf8.RuneLen(r)) + } + + return 0, segments +} + +func (self Max) Len() int { + return lenNo +} + +func (self Max) String() string { + return fmt.Sprintf("", self.Limit) +} diff --git a/vendor/github.com/gobwas/glob/match/min.go b/vendor/github.com/gobwas/glob/match/min.go new file mode 100644 index 000000000..db57ac8eb --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/min.go @@ -0,0 +1,57 @@ +package match + +import ( + "fmt" + "unicode/utf8" +) + +type Min struct { + Limit int +} + +func NewMin(l int) Min { + return Min{l} +} + +func (self Min) Match(s string) bool { + var l int + for range s { + l += 1 + if l >= self.Limit { + return true + } + } + + return false +} + +func (self Min) Index(s string) (int, []int) { + var count int + + c := len(s) - self.Limit + 1 + if c <= 0 { + return -1, nil + } + + segments := acquireSegments(c) + for i, r := range s { + count++ + if count >= self.Limit { + segments = append(segments, i+utf8.RuneLen(r)) + } + } + + if len(segments) == 0 { + return -1, nil + } + + return 0, segments +} + +func (self Min) Len() int { + return lenNo +} + +func (self Min) String() string { + return fmt.Sprintf("", self.Limit) +} diff --git a/vendor/github.com/gobwas/glob/match/nothing.go b/vendor/github.com/gobwas/glob/match/nothing.go new file mode 100644 index 000000000..0d4ecd36b --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/nothing.go @@ -0,0 +1,27 @@ +package match + +import ( + "fmt" +) + +type Nothing struct{} + +func NewNothing() Nothing { + return Nothing{} +} + +func (self Nothing) Match(s string) bool { + return len(s) == 0 +} + +func (self Nothing) Index(s string) (int, []int) { + return 0, segments0 +} + +func (self Nothing) Len() int { + return lenZero +} + +func (self Nothing) String() string { + return fmt.Sprintf("") +} diff --git a/vendor/github.com/gobwas/glob/match/prefix.go b/vendor/github.com/gobwas/glob/match/prefix.go new file mode 100644 index 000000000..a7347250e --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/prefix.go @@ -0,0 +1,50 @@ +package match + +import ( + "fmt" + "strings" + "unicode/utf8" +) + +type Prefix struct { + Prefix string +} + +func NewPrefix(p string) Prefix { + return Prefix{p} +} + +func (self Prefix) Index(s string) (int, []int) { + idx := strings.Index(s, self.Prefix) + if idx == -1 { + return -1, nil + } + + length := len(self.Prefix) + var sub string + if len(s) > idx+length { + sub = s[idx+length:] + } else { + sub = "" + } + + segments := acquireSegments(len(sub) + 1) + segments = append(segments, length) + for i, r := range sub { + segments = append(segments, length+i+utf8.RuneLen(r)) + } + + return idx, segments +} + +func (self Prefix) Len() int { + return lenNo +} + +func (self Prefix) Match(s string) bool { + return strings.HasPrefix(s, self.Prefix) +} + +func (self Prefix) String() string { + return fmt.Sprintf("", self.Prefix) +} diff --git a/vendor/github.com/gobwas/glob/match/prefix_any.go b/vendor/github.com/gobwas/glob/match/prefix_any.go new file mode 100644 index 000000000..8ee58fe1b --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/prefix_any.go @@ -0,0 +1,55 @@ +package match + +import ( + "fmt" + "strings" + "unicode/utf8" + + sutil "github.com/gobwas/glob/util/strings" +) + +type PrefixAny struct { + Prefix string + Separators []rune +} + +func NewPrefixAny(s string, sep []rune) PrefixAny { + return PrefixAny{s, sep} +} + +func (self PrefixAny) Index(s string) (int, []int) { + idx := strings.Index(s, self.Prefix) + if idx == -1 { + return -1, nil + } + + n := len(self.Prefix) + sub := s[idx+n:] + i := sutil.IndexAnyRunes(sub, self.Separators) + if i > -1 { + sub = sub[:i] + } + + seg := acquireSegments(len(sub) + 1) + seg = append(seg, n) + for i, r := range sub { + seg = append(seg, n+i+utf8.RuneLen(r)) + } + + return idx, seg +} + +func (self PrefixAny) Len() int { + return lenNo +} + +func (self PrefixAny) Match(s string) bool { + if !strings.HasPrefix(s, self.Prefix) { + return false + } + return sutil.IndexAnyRunes(s[len(self.Prefix):], self.Separators) == -1 +} + +func (self PrefixAny) String() string { + return fmt.Sprintf("", self.Prefix, string(self.Separators)) +} diff --git a/vendor/github.com/gobwas/glob/match/prefix_suffix.go b/vendor/github.com/gobwas/glob/match/prefix_suffix.go new file mode 100644 index 000000000..8208085a1 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/prefix_suffix.go @@ -0,0 +1,62 @@ +package match + +import ( + "fmt" + "strings" +) + +type PrefixSuffix struct { + Prefix, Suffix string +} + +func NewPrefixSuffix(p, s string) PrefixSuffix { + return PrefixSuffix{p, s} +} + +func (self PrefixSuffix) Index(s string) (int, []int) { + prefixIdx := strings.Index(s, self.Prefix) + if prefixIdx == -1 { + return -1, nil + } + + suffixLen := len(self.Suffix) + if suffixLen <= 0 { + return prefixIdx, []int{len(s) - prefixIdx} + } + + if (len(s) - prefixIdx) <= 0 { + return -1, nil + } + + segments := acquireSegments(len(s) - prefixIdx) + for sub := s[prefixIdx:]; ; { + suffixIdx := strings.LastIndex(sub, self.Suffix) + if suffixIdx == -1 { + break + } + + segments = append(segments, suffixIdx+suffixLen) + sub = sub[:suffixIdx] + } + + if len(segments) == 0 { + releaseSegments(segments) + return -1, nil + } + + reverseSegments(segments) + + return prefixIdx, segments +} + +func (self PrefixSuffix) Len() int { + return lenNo +} + +func (self PrefixSuffix) Match(s string) bool { + return strings.HasPrefix(s, self.Prefix) && strings.HasSuffix(s, self.Suffix) +} + +func (self PrefixSuffix) String() string { + return fmt.Sprintf("", self.Prefix, self.Suffix) +} diff --git a/vendor/github.com/gobwas/glob/match/range.go b/vendor/github.com/gobwas/glob/match/range.go new file mode 100644 index 000000000..ce30245a4 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/range.go @@ -0,0 +1,48 @@ +package match + +import ( + "fmt" + "unicode/utf8" +) + +type Range struct { + Lo, Hi rune + Not bool +} + +func NewRange(lo, hi rune, not bool) Range { + return Range{lo, hi, not} +} + +func (self Range) Len() int { + return lenOne +} + +func (self Range) Match(s string) bool { + r, w := utf8.DecodeRuneInString(s) + if len(s) > w { + return false + } + + inRange := r >= self.Lo && r <= self.Hi + + return inRange == !self.Not +} + +func (self Range) Index(s string) (int, []int) { + for i, r := range s { + if self.Not != (r >= self.Lo && r <= self.Hi) { + return i, segmentsByRuneLength[utf8.RuneLen(r)] + } + } + + return -1, nil +} + +func (self Range) String() string { + var not string + if self.Not { + not = "!" + } + return fmt.Sprintf("", not, string(self.Lo), string(self.Hi)) +} diff --git a/vendor/github.com/gobwas/glob/match/row.go b/vendor/github.com/gobwas/glob/match/row.go new file mode 100644 index 000000000..4379042e4 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/row.go @@ -0,0 +1,77 @@ +package match + +import ( + "fmt" +) + +type Row struct { + Matchers Matchers + RunesLength int + Segments []int +} + +func NewRow(len int, m ...Matcher) Row { + return Row{ + Matchers: Matchers(m), + RunesLength: len, + Segments: []int{len}, + } +} + +func (self Row) matchAll(s string) bool { + var idx int + for _, m := range self.Matchers { + length := m.Len() + + var next, i int + for next = range s[idx:] { + i++ + if i == length { + break + } + } + + if i < length || !m.Match(s[idx:idx+next+1]) { + return false + } + + idx += next + 1 + } + + return true +} + +func (self Row) lenOk(s string) bool { + var i int + for range s { + i++ + if i > self.RunesLength { + return false + } + } + return self.RunesLength == i +} + +func (self Row) Match(s string) bool { + return self.lenOk(s) && self.matchAll(s) +} + +func (self Row) Len() (l int) { + return self.RunesLength +} + +func (self Row) Index(s string) (int, []int) { + for i := range s { + if len(s[i:]) < self.RunesLength { + break + } + if self.matchAll(s[i:]) { + return i, self.Segments + } + } + return -1, nil +} + +func (self Row) String() string { + return fmt.Sprintf("", self.RunesLength, self.Matchers) +} diff --git a/vendor/github.com/gobwas/glob/match/segments.go b/vendor/github.com/gobwas/glob/match/segments.go new file mode 100644 index 000000000..9ea6f3094 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/segments.go @@ -0,0 +1,91 @@ +package match + +import ( + "sync" +) + +type SomePool interface { + Get() []int + Put([]int) +} + +var segmentsPools [1024]sync.Pool + +func toPowerOfTwo(v int) int { + v-- + v |= v >> 1 + v |= v >> 2 + v |= v >> 4 + v |= v >> 8 + v |= v >> 16 + v++ + + return v +} + +const ( + cacheFrom = 16 + cacheToAndHigher = 1024 + cacheFromIndex = 15 + cacheToAndHigherIndex = 1023 +) + +var ( + segments0 = []int{0} + segments1 = []int{1} + segments2 = []int{2} + segments3 = []int{3} + segments4 = []int{4} +) + +var segmentsByRuneLength [5][]int = [5][]int{ + 0: segments0, + 1: segments1, + 2: segments2, + 3: segments3, + 4: segments4, +} + +func init() { + for i := cacheToAndHigher; i >= cacheFrom; i >>= 1 { + func(i int) { + segmentsPools[i-1] = sync.Pool{New: func() interface{} { + return make([]int, 0, i) + }} + }(i) + } +} + +func getTableIndex(c int) int { + p := toPowerOfTwo(c) + switch { + case p >= cacheToAndHigher: + return cacheToAndHigherIndex + case p <= cacheFrom: + return cacheFromIndex + default: + return p - 1 + } +} + +func acquireSegments(c int) []int { + // make []int with less capacity than cacheFrom + // is faster than acquiring it from pool + if c < cacheFrom { + return make([]int, 0, c) + } + + return segmentsPools[getTableIndex(c)].Get().([]int)[:0] +} + +func releaseSegments(s []int) { + c := cap(s) + + // make []int with less capacity than cacheFrom + // is faster than acquiring it from pool + if c < cacheFrom { + return + } + + segmentsPools[getTableIndex(c)].Put(s) +} diff --git a/vendor/github.com/gobwas/glob/match/single.go b/vendor/github.com/gobwas/glob/match/single.go new file mode 100644 index 000000000..ee6e3954c --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/single.go @@ -0,0 +1,43 @@ +package match + +import ( + "fmt" + "github.com/gobwas/glob/util/runes" + "unicode/utf8" +) + +// single represents ? +type Single struct { + Separators []rune +} + +func NewSingle(s []rune) Single { + return Single{s} +} + +func (self Single) Match(s string) bool { + r, w := utf8.DecodeRuneInString(s) + if len(s) > w { + return false + } + + return runes.IndexRune(self.Separators, r) == -1 +} + +func (self Single) Len() int { + return lenOne +} + +func (self Single) Index(s string) (int, []int) { + for i, r := range s { + if runes.IndexRune(self.Separators, r) == -1 { + return i, segmentsByRuneLength[utf8.RuneLen(r)] + } + } + + return -1, nil +} + +func (self Single) String() string { + return fmt.Sprintf("", string(self.Separators)) +} diff --git a/vendor/github.com/gobwas/glob/match/suffix.go b/vendor/github.com/gobwas/glob/match/suffix.go new file mode 100644 index 000000000..85bea8c68 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/suffix.go @@ -0,0 +1,35 @@ +package match + +import ( + "fmt" + "strings" +) + +type Suffix struct { + Suffix string +} + +func NewSuffix(s string) Suffix { + return Suffix{s} +} + +func (self Suffix) Len() int { + return lenNo +} + +func (self Suffix) Match(s string) bool { + return strings.HasSuffix(s, self.Suffix) +} + +func (self Suffix) Index(s string) (int, []int) { + idx := strings.Index(s, self.Suffix) + if idx == -1 { + return -1, nil + } + + return 0, []int{idx + len(self.Suffix)} +} + +func (self Suffix) String() string { + return fmt.Sprintf("", self.Suffix) +} diff --git a/vendor/github.com/gobwas/glob/match/suffix_any.go b/vendor/github.com/gobwas/glob/match/suffix_any.go new file mode 100644 index 000000000..c5106f819 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/suffix_any.go @@ -0,0 +1,43 @@ +package match + +import ( + "fmt" + "strings" + + sutil "github.com/gobwas/glob/util/strings" +) + +type SuffixAny struct { + Suffix string + Separators []rune +} + +func NewSuffixAny(s string, sep []rune) SuffixAny { + return SuffixAny{s, sep} +} + +func (self SuffixAny) Index(s string) (int, []int) { + idx := strings.Index(s, self.Suffix) + if idx == -1 { + return -1, nil + } + + i := sutil.LastIndexAnyRunes(s[:idx], self.Separators) + 1 + + return i, []int{idx + len(self.Suffix) - i} +} + +func (self SuffixAny) Len() int { + return lenNo +} + +func (self SuffixAny) Match(s string) bool { + if !strings.HasSuffix(s, self.Suffix) { + return false + } + return sutil.IndexAnyRunes(s[:len(s)-len(self.Suffix)], self.Separators) == -1 +} + +func (self SuffixAny) String() string { + return fmt.Sprintf("", string(self.Separators), self.Suffix) +} diff --git a/vendor/github.com/gobwas/glob/match/super.go b/vendor/github.com/gobwas/glob/match/super.go new file mode 100644 index 000000000..3875950bb --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/super.go @@ -0,0 +1,33 @@ +package match + +import ( + "fmt" +) + +type Super struct{} + +func NewSuper() Super { + return Super{} +} + +func (self Super) Match(s string) bool { + return true +} + +func (self Super) Len() int { + return lenNo +} + +func (self Super) Index(s string) (int, []int) { + segments := acquireSegments(len(s) + 1) + for i := range s { + segments = append(segments, i) + } + segments = append(segments, len(s)) + + return 0, segments +} + +func (self Super) String() string { + return fmt.Sprintf("") +} diff --git a/vendor/github.com/gobwas/glob/match/text.go b/vendor/github.com/gobwas/glob/match/text.go new file mode 100644 index 000000000..0a17616d3 --- /dev/null +++ b/vendor/github.com/gobwas/glob/match/text.go @@ -0,0 +1,45 @@ +package match + +import ( + "fmt" + "strings" + "unicode/utf8" +) + +// raw represents raw string to match +type Text struct { + Str string + RunesLength int + BytesLength int + Segments []int +} + +func NewText(s string) Text { + return Text{ + Str: s, + RunesLength: utf8.RuneCountInString(s), + BytesLength: len(s), + Segments: []int{len(s)}, + } +} + +func (self Text) Match(s string) bool { + return self.Str == s +} + +func (self Text) Len() int { + return self.RunesLength +} + +func (self Text) Index(s string) (int, []int) { + index := strings.Index(s, self.Str) + if index == -1 { + return -1, nil + } + + return index, self.Segments +} + +func (self Text) String() string { + return fmt.Sprintf("", self.Str) +} diff --git a/vendor/github.com/gobwas/glob/readme.md b/vendor/github.com/gobwas/glob/readme.md new file mode 100644 index 000000000..f58144e73 --- /dev/null +++ b/vendor/github.com/gobwas/glob/readme.md @@ -0,0 +1,148 @@ +# glob.[go](https://golang.org) + +[![GoDoc][godoc-image]][godoc-url] [![Build Status][travis-image]][travis-url] + +> Go Globbing Library. + +## Install + +```shell + go get github.com/gobwas/glob +``` + +## Example + +```go + +package main + +import "github.com/gobwas/glob" + +func main() { + var g glob.Glob + + // create simple glob + g = glob.MustCompile("*.github.com") + g.Match("api.github.com") // true + + // quote meta characters and then create simple glob + g = glob.MustCompile(glob.QuoteMeta("*.github.com")) + g.Match("*.github.com") // true + + // create new glob with set of delimiters as ["."] + g = glob.MustCompile("api.*.com", '.') + g.Match("api.github.com") // true + g.Match("api.gi.hub.com") // false + + // create new glob with set of delimiters as ["."] + // but now with super wildcard + g = glob.MustCompile("api.**.com", '.') + g.Match("api.github.com") // true + g.Match("api.gi.hub.com") // true + + // create glob with single symbol wildcard + g = glob.MustCompile("?at") + g.Match("cat") // true + g.Match("fat") // true + g.Match("at") // false + + // create glob with single symbol wildcard and delimiters ['f'] + g = glob.MustCompile("?at", 'f') + g.Match("cat") // true + g.Match("fat") // false + g.Match("at") // false + + // create glob with character-list matchers + g = glob.MustCompile("[abc]at") + g.Match("cat") // true + g.Match("bat") // true + g.Match("fat") // false + g.Match("at") // false + + // create glob with character-list matchers + g = glob.MustCompile("[!abc]at") + g.Match("cat") // false + g.Match("bat") // false + g.Match("fat") // true + g.Match("at") // false + + // create glob with character-range matchers + g = glob.MustCompile("[a-c]at") + g.Match("cat") // true + g.Match("bat") // true + g.Match("fat") // false + g.Match("at") // false + + // create glob with character-range matchers + g = glob.MustCompile("[!a-c]at") + g.Match("cat") // false + g.Match("bat") // false + g.Match("fat") // true + g.Match("at") // false + + // create glob with pattern-alternatives list + g = glob.MustCompile("{cat,bat,[fr]at}") + g.Match("cat") // true + g.Match("bat") // true + g.Match("fat") // true + g.Match("rat") // true + g.Match("at") // false + g.Match("zat") // false +} + +``` + +## Performance + +This library is created for compile-once patterns. This means, that compilation could take time, but +strings matching is done faster, than in case when always parsing template. + +If you will not use compiled `glob.Glob` object, and do `g := glob.MustCompile(pattern); g.Match(...)` every time, then your code will be much more slower. + +Run `go test -bench=.` from source root to see the benchmarks: + +Pattern | Fixture | Match | Speed (ns/op) +--------|---------|-------|-------------- +`[a-z][!a-x]*cat*[h][!b]*eyes*` | `my cat has very bright eyes` | `true` | 432 +`[a-z][!a-x]*cat*[h][!b]*eyes*` | `my dog has very bright eyes` | `false` | 199 +`https://*.google.*` | `https://account.google.com` | `true` | 96 +`https://*.google.*` | `https://google.com` | `false` | 66 +`{https://*.google.*,*yandex.*,*yahoo.*,*mail.ru}` | `http://yahoo.com` | `true` | 163 +`{https://*.google.*,*yandex.*,*yahoo.*,*mail.ru}` | `http://google.com` | `false` | 197 +`{https://*gobwas.com,http://exclude.gobwas.com}` | `https://safe.gobwas.com` | `true` | 22 +`{https://*gobwas.com,http://exclude.gobwas.com}` | `http://safe.gobwas.com` | `false` | 24 +`abc*` | `abcdef` | `true` | 8.15 +`abc*` | `af` | `false` | 5.68 +`*def` | `abcdef` | `true` | 8.84 +`*def` | `af` | `false` | 5.74 +`ab*ef` | `abcdef` | `true` | 15.2 +`ab*ef` | `af` | `false` | 10.4 + +The same things with `regexp` package: + +Pattern | Fixture | Match | Speed (ns/op) +--------|---------|-------|-------------- +`^[a-z][^a-x].*cat.*[h][^b].*eyes.*$` | `my cat has very bright eyes` | `true` | 2553 +`^[a-z][^a-x].*cat.*[h][^b].*eyes.*$` | `my dog has very bright eyes` | `false` | 1383 +`^https:\/\/.*\.google\..*$` | `https://account.google.com` | `true` | 1205 +`^https:\/\/.*\.google\..*$` | `https://google.com` | `false` | 767 +`^(https:\/\/.*\.google\..*|.*yandex\..*|.*yahoo\..*|.*mail\.ru)$` | `http://yahoo.com` | `true` | 1435 +`^(https:\/\/.*\.google\..*|.*yandex\..*|.*yahoo\..*|.*mail\.ru)$` | `http://google.com` | `false` | 1674 +`^(https:\/\/.*gobwas\.com|http://exclude.gobwas.com)$` | `https://safe.gobwas.com` | `true` | 1039 +`^(https:\/\/.*gobwas\.com|http://exclude.gobwas.com)$` | `http://safe.gobwas.com` | `false` | 272 +`^abc.*$` | `abcdef` | `true` | 237 +`^abc.*$` | `af` | `false` | 100 +`^.*def$` | `abcdef` | `true` | 464 +`^.*def$` | `af` | `false` | 265 +`^ab.*ef$` | `abcdef` | `true` | 375 +`^ab.*ef$` | `af` | `false` | 145 + +[godoc-image]: https://godoc.org/github.com/gobwas/glob?status.svg +[godoc-url]: https://godoc.org/github.com/gobwas/glob +[travis-image]: https://travis-ci.org/gobwas/glob.svg?branch=master +[travis-url]: https://travis-ci.org/gobwas/glob + +## Syntax + +Syntax is inspired by [standard wildcards](http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm), +except that `**` is aka super-asterisk, that do not sensitive for separators. \ No newline at end of file diff --git a/vendor/github.com/gobwas/glob/syntax/ast/ast.go b/vendor/github.com/gobwas/glob/syntax/ast/ast.go new file mode 100644 index 000000000..3220a694a --- /dev/null +++ b/vendor/github.com/gobwas/glob/syntax/ast/ast.go @@ -0,0 +1,122 @@ +package ast + +import ( + "bytes" + "fmt" +) + +type Node struct { + Parent *Node + Children []*Node + Value interface{} + Kind Kind +} + +func NewNode(k Kind, v interface{}, ch ...*Node) *Node { + n := &Node{ + Kind: k, + Value: v, + } + for _, c := range ch { + Insert(n, c) + } + return n +} + +func (a *Node) Equal(b *Node) bool { + if a.Kind != b.Kind { + return false + } + if a.Value != b.Value { + return false + } + if len(a.Children) != len(b.Children) { + return false + } + for i, c := range a.Children { + if !c.Equal(b.Children[i]) { + return false + } + } + return true +} + +func (a *Node) String() string { + var buf bytes.Buffer + buf.WriteString(a.Kind.String()) + if a.Value != nil { + buf.WriteString(" =") + buf.WriteString(fmt.Sprintf("%v", a.Value)) + } + if len(a.Children) > 0 { + buf.WriteString(" [") + for i, c := range a.Children { + if i > 0 { + buf.WriteString(", ") + } + buf.WriteString(c.String()) + } + buf.WriteString("]") + } + return buf.String() +} + +func Insert(parent *Node, children ...*Node) { + parent.Children = append(parent.Children, children...) + for _, ch := range children { + ch.Parent = parent + } +} + +type List struct { + Not bool + Chars string +} + +type Range struct { + Not bool + Lo, Hi rune +} + +type Text struct { + Text string +} + +type Kind int + +const ( + KindNothing Kind = iota + KindPattern + KindList + KindRange + KindText + KindAny + KindSuper + KindSingle + KindAnyOf +) + +func (k Kind) String() string { + switch k { + case KindNothing: + return "Nothing" + case KindPattern: + return "Pattern" + case KindList: + return "List" + case KindRange: + return "Range" + case KindText: + return "Text" + case KindAny: + return "Any" + case KindSuper: + return "Super" + case KindSingle: + return "Single" + case KindAnyOf: + return "AnyOf" + default: + return "" + } +} diff --git a/vendor/github.com/gobwas/glob/syntax/ast/parser.go b/vendor/github.com/gobwas/glob/syntax/ast/parser.go new file mode 100644 index 000000000..429b40943 --- /dev/null +++ b/vendor/github.com/gobwas/glob/syntax/ast/parser.go @@ -0,0 +1,157 @@ +package ast + +import ( + "errors" + "fmt" + "github.com/gobwas/glob/syntax/lexer" + "unicode/utf8" +) + +type Lexer interface { + Next() lexer.Token +} + +type parseFn func(*Node, Lexer) (parseFn, *Node, error) + +func Parse(lexer Lexer) (*Node, error) { + var parser parseFn + + root := NewNode(KindPattern, nil) + + var ( + tree *Node + err error + ) + for parser, tree = parserMain, root; parser != nil; { + parser, tree, err = parser(tree, lexer) + if err != nil { + return nil, err + } + } + + return root, nil +} + +func parserMain(tree *Node, lex Lexer) (parseFn, *Node, error) { + for { + token := lex.Next() + switch token.Type { + case lexer.EOF: + return nil, tree, nil + + case lexer.Error: + return nil, tree, errors.New(token.Raw) + + case lexer.Text: + Insert(tree, NewNode(KindText, Text{token.Raw})) + return parserMain, tree, nil + + case lexer.Any: + Insert(tree, NewNode(KindAny, nil)) + return parserMain, tree, nil + + case lexer.Super: + Insert(tree, NewNode(KindSuper, nil)) + return parserMain, tree, nil + + case lexer.Single: + Insert(tree, NewNode(KindSingle, nil)) + return parserMain, tree, nil + + case lexer.RangeOpen: + return parserRange, tree, nil + + case lexer.TermsOpen: + a := NewNode(KindAnyOf, nil) + Insert(tree, a) + + p := NewNode(KindPattern, nil) + Insert(a, p) + + return parserMain, p, nil + + case lexer.Separator: + p := NewNode(KindPattern, nil) + Insert(tree.Parent, p) + + return parserMain, p, nil + + case lexer.TermsClose: + return parserMain, tree.Parent.Parent, nil + + default: + return nil, tree, fmt.Errorf("unexpected token: %s", token) + } + } + return nil, tree, fmt.Errorf("unknown error") +} + +func parserRange(tree *Node, lex Lexer) (parseFn, *Node, error) { + var ( + not bool + lo rune + hi rune + chars string + ) + for { + token := lex.Next() + switch token.Type { + case lexer.EOF: + return nil, tree, errors.New("unexpected end") + + case lexer.Error: + return nil, tree, errors.New(token.Raw) + + case lexer.Not: + not = true + + case lexer.RangeLo: + r, w := utf8.DecodeRuneInString(token.Raw) + if len(token.Raw) > w { + return nil, tree, fmt.Errorf("unexpected length of lo character") + } + lo = r + + case lexer.RangeBetween: + // + + case lexer.RangeHi: + r, w := utf8.DecodeRuneInString(token.Raw) + if len(token.Raw) > w { + return nil, tree, fmt.Errorf("unexpected length of lo character") + } + + hi = r + + if hi < lo { + return nil, tree, fmt.Errorf("hi character '%s' should be greater than lo '%s'", string(hi), string(lo)) + } + + case lexer.Text: + chars = token.Raw + + case lexer.RangeClose: + isRange := lo != 0 && hi != 0 + isChars := chars != "" + + if isChars == isRange { + return nil, tree, fmt.Errorf("could not parse range") + } + + if isRange { + Insert(tree, NewNode(KindRange, Range{ + Lo: lo, + Hi: hi, + Not: not, + })) + } else { + Insert(tree, NewNode(KindList, List{ + Chars: chars, + Not: not, + })) + } + + return parserMain, tree, nil + } + } +} diff --git a/vendor/github.com/gobwas/glob/syntax/lexer/lexer.go b/vendor/github.com/gobwas/glob/syntax/lexer/lexer.go new file mode 100644 index 000000000..a1c8d1962 --- /dev/null +++ b/vendor/github.com/gobwas/glob/syntax/lexer/lexer.go @@ -0,0 +1,273 @@ +package lexer + +import ( + "bytes" + "fmt" + "github.com/gobwas/glob/util/runes" + "unicode/utf8" +) + +const ( + char_any = '*' + char_comma = ',' + char_single = '?' + char_escape = '\\' + char_range_open = '[' + char_range_close = ']' + char_terms_open = '{' + char_terms_close = '}' + char_range_not = '!' + char_range_between = '-' +) + +var specials = []byte{ + char_any, + char_single, + char_escape, + char_range_open, + char_range_close, + char_terms_open, + char_terms_close, +} + +func Special(c byte) bool { + return bytes.IndexByte(specials, c) != -1 +} + +type tokens []Token + +func (i *tokens) shift() (ret Token) { + ret = (*i)[0] + copy(*i, (*i)[1:]) + *i = (*i)[:len(*i)-1] + return +} + +func (i *tokens) push(v Token) { + *i = append(*i, v) +} + +func (i *tokens) empty() bool { + return len(*i) == 0 +} + +var eof rune = 0 + +type lexer struct { + data string + pos int + err error + + tokens tokens + termsLevel int + + lastRune rune + lastRuneSize int + hasRune bool +} + +func NewLexer(source string) *lexer { + l := &lexer{ + data: source, + tokens: tokens(make([]Token, 0, 4)), + } + return l +} + +func (l *lexer) Next() Token { + if l.err != nil { + return Token{Error, l.err.Error()} + } + if !l.tokens.empty() { + return l.tokens.shift() + } + + l.fetchItem() + return l.Next() +} + +func (l *lexer) peek() (r rune, w int) { + if l.pos == len(l.data) { + return eof, 0 + } + + r, w = utf8.DecodeRuneInString(l.data[l.pos:]) + if r == utf8.RuneError { + l.errorf("could not read rune") + r = eof + w = 0 + } + + return +} + +func (l *lexer) read() rune { + if l.hasRune { + l.hasRune = false + l.seek(l.lastRuneSize) + return l.lastRune + } + + r, s := l.peek() + l.seek(s) + + l.lastRune = r + l.lastRuneSize = s + + return r +} + +func (l *lexer) seek(w int) { + l.pos += w +} + +func (l *lexer) unread() { + if l.hasRune { + l.errorf("could not unread rune") + return + } + l.seek(-l.lastRuneSize) + l.hasRune = true +} + +func (l *lexer) errorf(f string, v ...interface{}) { + l.err = fmt.Errorf(f, v...) +} + +func (l *lexer) inTerms() bool { + return l.termsLevel > 0 +} + +func (l *lexer) termsEnter() { + l.termsLevel++ +} + +func (l *lexer) termsLeave() { + l.termsLevel-- +} + +var inTextBreakers = []rune{char_single, char_any, char_range_open, char_terms_open} +var inTermsBreakers = append(inTextBreakers, char_terms_close, char_comma) + +func (l *lexer) fetchItem() { + r := l.read() + switch { + case r == eof: + l.tokens.push(Token{EOF, ""}) + + case r == char_terms_open: + l.termsEnter() + l.tokens.push(Token{TermsOpen, string(r)}) + + case r == char_comma && l.inTerms(): + l.tokens.push(Token{Separator, string(r)}) + + case r == char_terms_close && l.inTerms(): + l.tokens.push(Token{TermsClose, string(r)}) + l.termsLeave() + + case r == char_range_open: + l.tokens.push(Token{RangeOpen, string(r)}) + l.fetchRange() + + case r == char_single: + l.tokens.push(Token{Single, string(r)}) + + case r == char_any: + if l.read() == char_any { + l.tokens.push(Token{Super, string(r) + string(r)}) + } else { + l.unread() + l.tokens.push(Token{Any, string(r)}) + } + + default: + l.unread() + + var breakers []rune + if l.inTerms() { + breakers = inTermsBreakers + } else { + breakers = inTextBreakers + } + l.fetchText(breakers) + } +} + +func (l *lexer) fetchRange() { + var wantHi bool + var wantClose bool + var seenNot bool + for { + r := l.read() + if r == eof { + l.errorf("unexpected end of input") + return + } + + if wantClose { + if r != char_range_close { + l.errorf("expected close range character") + } else { + l.tokens.push(Token{RangeClose, string(r)}) + } + return + } + + if wantHi { + l.tokens.push(Token{RangeHi, string(r)}) + wantClose = true + continue + } + + if !seenNot && r == char_range_not { + l.tokens.push(Token{Not, string(r)}) + seenNot = true + continue + } + + if n, w := l.peek(); n == char_range_between { + l.seek(w) + l.tokens.push(Token{RangeLo, string(r)}) + l.tokens.push(Token{RangeBetween, string(n)}) + wantHi = true + continue + } + + l.unread() // unread first peek and fetch as text + l.fetchText([]rune{char_range_close}) + wantClose = true + } +} + +func (l *lexer) fetchText(breakers []rune) { + var data []rune + var escaped bool + +reading: + for { + r := l.read() + if r == eof { + break + } + + if !escaped { + if r == char_escape { + escaped = true + continue + } + + if runes.IndexRune(breakers, r) != -1 { + l.unread() + break reading + } + } + + escaped = false + data = append(data, r) + } + + if len(data) > 0 { + l.tokens.push(Token{Text, string(data)}) + } +} diff --git a/vendor/github.com/gobwas/glob/syntax/lexer/token.go b/vendor/github.com/gobwas/glob/syntax/lexer/token.go new file mode 100644 index 000000000..2797c4e83 --- /dev/null +++ b/vendor/github.com/gobwas/glob/syntax/lexer/token.go @@ -0,0 +1,88 @@ +package lexer + +import "fmt" + +type TokenType int + +const ( + EOF TokenType = iota + Error + Text + Char + Any + Super + Single + Not + Separator + RangeOpen + RangeClose + RangeLo + RangeHi + RangeBetween + TermsOpen + TermsClose +) + +func (tt TokenType) String() string { + switch tt { + case EOF: + return "eof" + + case Error: + return "error" + + case Text: + return "text" + + case Char: + return "char" + + case Any: + return "any" + + case Super: + return "super" + + case Single: + return "single" + + case Not: + return "not" + + case Separator: + return "separator" + + case RangeOpen: + return "range_open" + + case RangeClose: + return "range_close" + + case RangeLo: + return "range_lo" + + case RangeHi: + return "range_hi" + + case RangeBetween: + return "range_between" + + case TermsOpen: + return "terms_open" + + case TermsClose: + return "terms_close" + + default: + return "undef" + } +} + +type Token struct { + Type TokenType + Raw string +} + +func (t Token) String() string { + return fmt.Sprintf("%v<%q>", t.Type, t.Raw) +} diff --git a/vendor/github.com/gobwas/glob/syntax/syntax.go b/vendor/github.com/gobwas/glob/syntax/syntax.go new file mode 100644 index 000000000..1d168b148 --- /dev/null +++ b/vendor/github.com/gobwas/glob/syntax/syntax.go @@ -0,0 +1,14 @@ +package syntax + +import ( + "github.com/gobwas/glob/syntax/ast" + "github.com/gobwas/glob/syntax/lexer" +) + +func Parse(s string) (*ast.Node, error) { + return ast.Parse(lexer.NewLexer(s)) +} + +func Special(b byte) bool { + return lexer.Special(b) +} diff --git a/vendor/github.com/gobwas/glob/util/runes/runes.go b/vendor/github.com/gobwas/glob/util/runes/runes.go new file mode 100644 index 000000000..a72355641 --- /dev/null +++ b/vendor/github.com/gobwas/glob/util/runes/runes.go @@ -0,0 +1,154 @@ +package runes + +func Index(s, needle []rune) int { + ls, ln := len(s), len(needle) + + switch { + case ln == 0: + return 0 + case ln == 1: + return IndexRune(s, needle[0]) + case ln == ls: + if Equal(s, needle) { + return 0 + } + return -1 + case ln > ls: + return -1 + } + +head: + for i := 0; i < ls && ls-i >= ln; i++ { + for y := 0; y < ln; y++ { + if s[i+y] != needle[y] { + continue head + } + } + + return i + } + + return -1 +} + +func LastIndex(s, needle []rune) int { + ls, ln := len(s), len(needle) + + switch { + case ln == 0: + if ls == 0 { + return 0 + } + return ls + case ln == 1: + return IndexLastRune(s, needle[0]) + case ln == ls: + if Equal(s, needle) { + return 0 + } + return -1 + case ln > ls: + return -1 + } + +head: + for i := ls - 1; i >= 0 && i >= ln; i-- { + for y := ln - 1; y >= 0; y-- { + if s[i-(ln-y-1)] != needle[y] { + continue head + } + } + + return i - ln + 1 + } + + return -1 +} + +// IndexAny returns the index of the first instance of any Unicode code point +// from chars in s, or -1 if no Unicode code point from chars is present in s. +func IndexAny(s, chars []rune) int { + if len(chars) > 0 { + for i, c := range s { + for _, m := range chars { + if c == m { + return i + } + } + } + } + return -1 +} + +func Contains(s, needle []rune) bool { + return Index(s, needle) >= 0 +} + +func Max(s []rune) (max rune) { + for _, r := range s { + if r > max { + max = r + } + } + + return +} + +func Min(s []rune) rune { + min := rune(-1) + for _, r := range s { + if min == -1 { + min = r + continue + } + + if r < min { + min = r + } + } + + return min +} + +func IndexRune(s []rune, r rune) int { + for i, c := range s { + if c == r { + return i + } + } + return -1 +} + +func IndexLastRune(s []rune, r rune) int { + for i := len(s) - 1; i >= 0; i-- { + if s[i] == r { + return i + } + } + + return -1 +} + +func Equal(a, b []rune) bool { + if len(a) == len(b) { + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false + } + } + + return true + } + + return false +} + +// HasPrefix tests whether the string s begins with prefix. +func HasPrefix(s, prefix []rune) bool { + return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix) +} + +// HasSuffix tests whether the string s ends with suffix. +func HasSuffix(s, suffix []rune) bool { + return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix):], suffix) +} diff --git a/vendor/github.com/gobwas/glob/util/strings/strings.go b/vendor/github.com/gobwas/glob/util/strings/strings.go new file mode 100644 index 000000000..e8ee1920b --- /dev/null +++ b/vendor/github.com/gobwas/glob/util/strings/strings.go @@ -0,0 +1,39 @@ +package strings + +import ( + "strings" + "unicode/utf8" +) + +func IndexAnyRunes(s string, rs []rune) int { + for _, r := range rs { + if i := strings.IndexRune(s, r); i != -1 { + return i + } + } + + return -1 +} + +func LastIndexAnyRunes(s string, rs []rune) int { + for _, r := range rs { + i := -1 + if 0 <= r && r < utf8.RuneSelf { + i = strings.LastIndexByte(s, byte(r)) + } else { + sub := s + for len(sub) > 0 { + j := strings.IndexRune(s, r) + if j == -1 { + break + } + i = j + sub = sub[i+1:] + } + } + if i != -1 { + return i + } + } + return -1 +} diff --git a/vendor/github.com/gofrs/flock/.gitignore b/vendor/github.com/gofrs/flock/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/vendor/github.com/gofrs/flock/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/gofrs/flock/.travis.yml b/vendor/github.com/gofrs/flock/.travis.yml new file mode 100644 index 000000000..b791a7421 --- /dev/null +++ b/vendor/github.com/gofrs/flock/.travis.yml @@ -0,0 +1,10 @@ +language: go +go: + - 1.10.x + - 1.11.x +script: go test -v -check.vv -race ./... +sudo: false +notifications: + email: + on_success: never + on_failure: always diff --git a/vendor/github.com/gofrs/flock/LICENSE b/vendor/github.com/gofrs/flock/LICENSE new file mode 100644 index 000000000..aff7d358e --- /dev/null +++ b/vendor/github.com/gofrs/flock/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2015, Tim Heckman +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 linode-netint 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 HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gofrs/flock/README.md b/vendor/github.com/gofrs/flock/README.md new file mode 100644 index 000000000..71ce63692 --- /dev/null +++ b/vendor/github.com/gofrs/flock/README.md @@ -0,0 +1,41 @@ +# flock +[![TravisCI Build Status](https://img.shields.io/travis/gofrs/flock/master.svg?style=flat)](https://travis-ci.org/gofrs/flock) +[![GoDoc](https://img.shields.io/badge/godoc-flock-blue.svg?style=flat)](https://godoc.org/github.com/gofrs/flock) +[![License](https://img.shields.io/badge/license-BSD_3--Clause-brightgreen.svg?style=flat)](https://github.com/gofrs/flock/blob/master/LICENSE) +[![Go Report Card](https://goreportcard.com/badge/github.com/gofrs/flock)](https://goreportcard.com/report/github.com/gofrs/flock) + +`flock` implements a thread-safe sync.Locker interface for file locking. It also +includes a non-blocking TryLock() function to allow locking without blocking execution. + +## License +`flock` is released under the BSD 3-Clause License. See the `LICENSE` file for more details. + +## Go Compatibility +This package makes use of the `context` package that was introduced in Go 1.7. As such, this +package has an implicit dependency on Go 1.7+. + +## Installation +``` +go get -u github.com/gofrs/flock +``` + +## Usage +```Go +import "github.com/gofrs/flock" + +fileLock := flock.New("/var/lock/go-lock.lock") + +locked, err := fileLock.TryLock() + +if err != nil { + // handle locking error +} + +if locked { + // do work + fileLock.Unlock() +} +``` + +For more detailed usage information take a look at the package API docs on +[GoDoc](https://godoc.org/github.com/gofrs/flock). diff --git a/vendor/github.com/gofrs/flock/appveyor.yml b/vendor/github.com/gofrs/flock/appveyor.yml new file mode 100644 index 000000000..6848e94bf --- /dev/null +++ b/vendor/github.com/gofrs/flock/appveyor.yml @@ -0,0 +1,25 @@ +version: '{build}' + +build: false +deploy: false + +clone_folder: 'c:\gopath\src\github.com\gofrs\flock' + +environment: + GOPATH: 'c:\gopath' + GOVERSION: '1.11' + +init: + - git config --global core.autocrlf input + +install: + - rmdir c:\go /s /q + - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi + - msiexec /i go%GOVERSION%.windows-amd64.msi /q + - set Path=c:\go\bin;c:\gopath\bin;%Path% + - go version + - go env + +test_script: + - go get -t ./... + - go test -race -v ./... diff --git a/vendor/github.com/gofrs/flock/flock.go b/vendor/github.com/gofrs/flock/flock.go new file mode 100644 index 000000000..8f109b8a9 --- /dev/null +++ b/vendor/github.com/gofrs/flock/flock.go @@ -0,0 +1,127 @@ +// Copyright 2015 Tim Heckman. All rights reserved. +// Use of this source code is governed by the BSD 3-Clause +// license that can be found in the LICENSE file. + +// Package flock implements a thread-safe interface for file locking. +// It also includes a non-blocking TryLock() function to allow locking +// without blocking execution. +// +// Package flock is released under the BSD 3-Clause License. See the LICENSE file +// for more details. +// +// While using this library, remember that the locking behaviors are not +// guaranteed to be the same on each platform. For example, some UNIX-like +// operating systems will transparently convert a shared lock to an exclusive +// lock. If you Unlock() the flock from a location where you believe that you +// have the shared lock, you may accidentally drop the exclusive lock. +package flock + +import ( + "context" + "os" + "sync" + "time" +) + +// Flock is the struct type to handle file locking. All fields are unexported, +// with access to some of the fields provided by getter methods (Path() and Locked()). +type Flock struct { + path string + m sync.RWMutex + fh *os.File + l bool + r bool +} + +// New returns a new instance of *Flock. The only parameter +// it takes is the path to the desired lockfile. +func New(path string) *Flock { + return &Flock{path: path} +} + +// NewFlock returns a new instance of *Flock. The only parameter +// it takes is the path to the desired lockfile. +// +// Deprecated: Use New instead. +func NewFlock(path string) *Flock { + return New(path) +} + +// Close is equivalent to calling Unlock. +// +// This will release the lock and close the underlying file descriptor. +// It will not remove the file from disk, that's up to your application. +func (f *Flock) Close() error { + return f.Unlock() +} + +// Path returns the path as provided in NewFlock(). +func (f *Flock) Path() string { + return f.path +} + +// Locked returns the lock state (locked: true, unlocked: false). +// +// Warning: by the time you use the returned value, the state may have changed. +func (f *Flock) Locked() bool { + f.m.RLock() + defer f.m.RUnlock() + return f.l +} + +// RLocked returns the read lock state (locked: true, unlocked: false). +// +// Warning: by the time you use the returned value, the state may have changed. +func (f *Flock) RLocked() bool { + f.m.RLock() + defer f.m.RUnlock() + return f.r +} + +func (f *Flock) String() string { + return f.path +} + +// TryLockContext repeatedly tries to take an exclusive lock until one of the +// conditions is met: TryLock succeeds, TryLock fails with error, or Context +// Done channel is closed. +func (f *Flock) TryLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) { + return tryCtx(ctx, f.TryLock, retryDelay) +} + +// TryRLockContext repeatedly tries to take a shared lock until one of the +// conditions is met: TryRLock succeeds, TryRLock fails with error, or Context +// Done channel is closed. +func (f *Flock) TryRLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) { + return tryCtx(ctx, f.TryRLock, retryDelay) +} + +func tryCtx(ctx context.Context, fn func() (bool, error), retryDelay time.Duration) (bool, error) { + if ctx.Err() != nil { + return false, ctx.Err() + } + for { + if ok, err := fn(); ok || err != nil { + return ok, err + } + select { + case <-ctx.Done(): + return false, ctx.Err() + case <-time.After(retryDelay): + // try again + } + } +} + +func (f *Flock) setFh() error { + // open a new os.File instance + // create it if it doesn't exist, and open the file read-only. + fh, err := os.OpenFile(f.path, os.O_CREATE|os.O_RDONLY, os.FileMode(0600)) + if err != nil { + return err + } + + // set the filehandle on the struct + f.fh = fh + return nil +} diff --git a/vendor/github.com/gofrs/flock/flock_unix.go b/vendor/github.com/gofrs/flock/flock_unix.go new file mode 100644 index 000000000..45f71a707 --- /dev/null +++ b/vendor/github.com/gofrs/flock/flock_unix.go @@ -0,0 +1,195 @@ +// Copyright 2015 Tim Heckman. All rights reserved. +// Use of this source code is governed by the BSD 3-Clause +// license that can be found in the LICENSE file. + +// +build !windows + +package flock + +import ( + "os" + "syscall" +) + +// Lock is a blocking call to try and take an exclusive file lock. It will wait +// until it is able to obtain the exclusive file lock. It's recommended that +// TryLock() be used over this function. This function may block the ability to +// query the current Locked() or RLocked() status due to a RW-mutex lock. +// +// If we are already exclusive-locked, this function short-circuits and returns +// immediately assuming it can take the mutex lock. +// +// If the *Flock has a shared lock (RLock), this may transparently replace the +// shared lock with an exclusive lock on some UNIX-like operating systems. Be +// careful when using exclusive locks in conjunction with shared locks +// (RLock()), because calling Unlock() may accidentally release the exclusive +// lock that was once a shared lock. +func (f *Flock) Lock() error { + return f.lock(&f.l, syscall.LOCK_EX) +} + +// RLock is a blocking call to try and take a shared file lock. It will wait +// until it is able to obtain the shared file lock. It's recommended that +// TryRLock() be used over this function. This function may block the ability to +// query the current Locked() or RLocked() status due to a RW-mutex lock. +// +// If we are already shared-locked, this function short-circuits and returns +// immediately assuming it can take the mutex lock. +func (f *Flock) RLock() error { + return f.lock(&f.r, syscall.LOCK_SH) +} + +func (f *Flock) lock(locked *bool, flag int) error { + f.m.Lock() + defer f.m.Unlock() + + if *locked { + return nil + } + + if f.fh == nil { + if err := f.setFh(); err != nil { + return err + } + } + + if err := syscall.Flock(int(f.fh.Fd()), flag); err != nil { + shouldRetry, reopenErr := f.reopenFDOnError(err) + if reopenErr != nil { + return reopenErr + } + + if !shouldRetry { + return err + } + + if err = syscall.Flock(int(f.fh.Fd()), flag); err != nil { + return err + } + } + + *locked = true + return nil +} + +// Unlock is a function to unlock the file. This file takes a RW-mutex lock, so +// while it is running the Locked() and RLocked() functions will be blocked. +// +// This function short-circuits if we are unlocked already. If not, it calls +// syscall.LOCK_UN on the file and closes the file descriptor. It does not +// remove the file from disk. It's up to your application to do. +// +// Please note, if your shared lock became an exclusive lock this may +// unintentionally drop the exclusive lock if called by the consumer that +// believes they have a shared lock. Please see Lock() for more details. +func (f *Flock) Unlock() error { + f.m.Lock() + defer f.m.Unlock() + + // if we aren't locked or if the lockfile instance is nil + // just return a nil error because we are unlocked + if (!f.l && !f.r) || f.fh == nil { + return nil + } + + // mark the file as unlocked + if err := syscall.Flock(int(f.fh.Fd()), syscall.LOCK_UN); err != nil { + return err + } + + f.fh.Close() + + f.l = false + f.r = false + f.fh = nil + + return nil +} + +// TryLock is the preferred function for taking an exclusive file lock. This +// function takes an RW-mutex lock before it tries to lock the file, so there is +// the possibility that this function may block for a short time if another +// goroutine is trying to take any action. +// +// The actual file lock is non-blocking. If we are unable to get the exclusive +// file lock, the function will return false instead of waiting for the lock. If +// we get the lock, we also set the *Flock instance as being exclusive-locked. +func (f *Flock) TryLock() (bool, error) { + return f.try(&f.l, syscall.LOCK_EX) +} + +// TryRLock is the preferred function for taking a shared file lock. This +// function takes an RW-mutex lock before it tries to lock the file, so there is +// the possibility that this function may block for a short time if another +// goroutine is trying to take any action. +// +// The actual file lock is non-blocking. If we are unable to get the shared file +// lock, the function will return false instead of waiting for the lock. If we +// get the lock, we also set the *Flock instance as being share-locked. +func (f *Flock) TryRLock() (bool, error) { + return f.try(&f.r, syscall.LOCK_SH) +} + +func (f *Flock) try(locked *bool, flag int) (bool, error) { + f.m.Lock() + defer f.m.Unlock() + + if *locked { + return true, nil + } + + if f.fh == nil { + if err := f.setFh(); err != nil { + return false, err + } + } + + var retried bool +retry: + err := syscall.Flock(int(f.fh.Fd()), flag|syscall.LOCK_NB) + + switch err { + case syscall.EWOULDBLOCK: + return false, nil + case nil: + *locked = true + return true, nil + } + if !retried { + if shouldRetry, reopenErr := f.reopenFDOnError(err); reopenErr != nil { + return false, reopenErr + } else if shouldRetry { + retried = true + goto retry + } + } + + return false, err +} + +// reopenFDOnError determines whether we should reopen the file handle +// in readwrite mode and try again. This comes from util-linux/sys-utils/flock.c: +// Since Linux 3.4 (commit 55725513) +// Probably NFSv4 where flock() is emulated by fcntl(). +func (f *Flock) reopenFDOnError(err error) (bool, error) { + if err != syscall.EIO && err != syscall.EBADF { + return false, nil + } + if st, err := f.fh.Stat(); err == nil { + // if the file is able to be read and written + if st.Mode()&0600 == 0600 { + f.fh.Close() + f.fh = nil + + // reopen in read-write mode and set the filehandle + fh, err := os.OpenFile(f.path, os.O_CREATE|os.O_RDWR, os.FileMode(0600)) + if err != nil { + return false, err + } + f.fh = fh + return true, nil + } + } + + return false, nil +} diff --git a/vendor/github.com/gofrs/flock/flock_winapi.go b/vendor/github.com/gofrs/flock/flock_winapi.go new file mode 100644 index 000000000..fe405a255 --- /dev/null +++ b/vendor/github.com/gofrs/flock/flock_winapi.go @@ -0,0 +1,76 @@ +// Copyright 2015 Tim Heckman. All rights reserved. +// Use of this source code is governed by the BSD 3-Clause +// license that can be found in the LICENSE file. + +// +build windows + +package flock + +import ( + "syscall" + "unsafe" +) + +var ( + kernel32, _ = syscall.LoadLibrary("kernel32.dll") + procLockFileEx, _ = syscall.GetProcAddress(kernel32, "LockFileEx") + procUnlockFileEx, _ = syscall.GetProcAddress(kernel32, "UnlockFileEx") +) + +const ( + winLockfileFailImmediately = 0x00000001 + winLockfileExclusiveLock = 0x00000002 + winLockfileSharedLock = 0x00000000 +) + +// Use of 0x00000000 for the shared lock is a guess based on some the MS Windows +// `LockFileEX` docs, which document the `LOCKFILE_EXCLUSIVE_LOCK` flag as: +// +// > The function requests an exclusive lock. Otherwise, it requests a shared +// > lock. +// +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx + +func lockFileEx(handle syscall.Handle, flags uint32, reserved uint32, numberOfBytesToLockLow uint32, numberOfBytesToLockHigh uint32, offset *syscall.Overlapped) (bool, syscall.Errno) { + r1, _, errNo := syscall.Syscall6( + uintptr(procLockFileEx), + 6, + uintptr(handle), + uintptr(flags), + uintptr(reserved), + uintptr(numberOfBytesToLockLow), + uintptr(numberOfBytesToLockHigh), + uintptr(unsafe.Pointer(offset))) + + if r1 != 1 { + if errNo == 0 { + return false, syscall.EINVAL + } + + return false, errNo + } + + return true, 0 +} + +func unlockFileEx(handle syscall.Handle, reserved uint32, numberOfBytesToLockLow uint32, numberOfBytesToLockHigh uint32, offset *syscall.Overlapped) (bool, syscall.Errno) { + r1, _, errNo := syscall.Syscall6( + uintptr(procUnlockFileEx), + 5, + uintptr(handle), + uintptr(reserved), + uintptr(numberOfBytesToLockLow), + uintptr(numberOfBytesToLockHigh), + uintptr(unsafe.Pointer(offset)), + 0) + + if r1 != 1 { + if errNo == 0 { + return false, syscall.EINVAL + } + + return false, errNo + } + + return true, 0 +} diff --git a/vendor/github.com/gofrs/flock/flock_windows.go b/vendor/github.com/gofrs/flock/flock_windows.go new file mode 100644 index 000000000..9f4a5f10d --- /dev/null +++ b/vendor/github.com/gofrs/flock/flock_windows.go @@ -0,0 +1,140 @@ +// Copyright 2015 Tim Heckman. All rights reserved. +// Use of this source code is governed by the BSD 3-Clause +// license that can be found in the LICENSE file. + +package flock + +import ( + "syscall" +) + +// ErrorLockViolation is the error code returned from the Windows syscall when a +// lock would block and you ask to fail immediately. +const ErrorLockViolation syscall.Errno = 0x21 // 33 + +// Lock is a blocking call to try and take an exclusive file lock. It will wait +// until it is able to obtain the exclusive file lock. It's recommended that +// TryLock() be used over this function. This function may block the ability to +// query the current Locked() or RLocked() status due to a RW-mutex lock. +// +// If we are already locked, this function short-circuits and returns +// immediately assuming it can take the mutex lock. +func (f *Flock) Lock() error { + return f.lock(&f.l, winLockfileExclusiveLock) +} + +// RLock is a blocking call to try and take a shared file lock. It will wait +// until it is able to obtain the shared file lock. It's recommended that +// TryRLock() be used over this function. This function may block the ability to +// query the current Locked() or RLocked() status due to a RW-mutex lock. +// +// If we are already locked, this function short-circuits and returns +// immediately assuming it can take the mutex lock. +func (f *Flock) RLock() error { + return f.lock(&f.r, winLockfileSharedLock) +} + +func (f *Flock) lock(locked *bool, flag uint32) error { + f.m.Lock() + defer f.m.Unlock() + + if *locked { + return nil + } + + if f.fh == nil { + if err := f.setFh(); err != nil { + return err + } + } + + if _, errNo := lockFileEx(syscall.Handle(f.fh.Fd()), flag, 0, 1, 0, &syscall.Overlapped{}); errNo > 0 { + return errNo + } + + *locked = true + return nil +} + +// Unlock is a function to unlock the file. This file takes a RW-mutex lock, so +// while it is running the Locked() and RLocked() functions will be blocked. +// +// This function short-circuits if we are unlocked already. If not, it calls +// UnlockFileEx() on the file and closes the file descriptor. It does not remove +// the file from disk. It's up to your application to do. +func (f *Flock) Unlock() error { + f.m.Lock() + defer f.m.Unlock() + + // if we aren't locked or if the lockfile instance is nil + // just return a nil error because we are unlocked + if (!f.l && !f.r) || f.fh == nil { + return nil + } + + // mark the file as unlocked + if _, errNo := unlockFileEx(syscall.Handle(f.fh.Fd()), 0, 1, 0, &syscall.Overlapped{}); errNo > 0 { + return errNo + } + + f.fh.Close() + + f.l = false + f.r = false + f.fh = nil + + return nil +} + +// TryLock is the preferred function for taking an exclusive file lock. This +// function does take a RW-mutex lock before it tries to lock the file, so there +// is the possibility that this function may block for a short time if another +// goroutine is trying to take any action. +// +// The actual file lock is non-blocking. If we are unable to get the exclusive +// file lock, the function will return false instead of waiting for the lock. If +// we get the lock, we also set the *Flock instance as being exclusive-locked. +func (f *Flock) TryLock() (bool, error) { + return f.try(&f.l, winLockfileExclusiveLock) +} + +// TryRLock is the preferred function for taking a shared file lock. This +// function does take a RW-mutex lock before it tries to lock the file, so there +// is the possibility that this function may block for a short time if another +// goroutine is trying to take any action. +// +// The actual file lock is non-blocking. If we are unable to get the shared file +// lock, the function will return false instead of waiting for the lock. If we +// get the lock, we also set the *Flock instance as being shared-locked. +func (f *Flock) TryRLock() (bool, error) { + return f.try(&f.r, winLockfileSharedLock) +} + +func (f *Flock) try(locked *bool, flag uint32) (bool, error) { + f.m.Lock() + defer f.m.Unlock() + + if *locked { + return true, nil + } + + if f.fh == nil { + if err := f.setFh(); err != nil { + return false, err + } + } + + _, errNo := lockFileEx(syscall.Handle(f.fh.Fd()), flag|winLockfileFailImmediately, 0, 1, 0, &syscall.Overlapped{}) + + if errNo > 0 { + if errNo == ErrorLockViolation || errNo == syscall.ERROR_IO_PENDING { + return false, nil + } + + return false, errNo + } + + *locked = true + + return true, nil +} diff --git a/vendor/github.com/gogo/protobuf/AUTHORS b/vendor/github.com/gogo/protobuf/AUTHORS new file mode 100644 index 000000000..3d97fc7a2 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/AUTHORS @@ -0,0 +1,15 @@ +# This is the official list of GoGo authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS file, which +# lists people. For example, employees are listed in CONTRIBUTORS, +# but not in AUTHORS, because the employer holds the copyright. + +# Names should be added to this file as one of +# Organization's name +# Individual's name +# Individual's name + +# Please keep the list sorted. + +Sendgrid, Inc +Vastech SA (PTY) LTD +Walter Schulze diff --git a/vendor/github.com/gogo/protobuf/CONTRIBUTORS b/vendor/github.com/gogo/protobuf/CONTRIBUTORS new file mode 100644 index 000000000..1b4f6c208 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/CONTRIBUTORS @@ -0,0 +1,23 @@ +Anton Povarov +Brian Goff +Clayton Coleman +Denis Smirnov +DongYun Kang +Dwayne Schultz +Georg Apitz +Gustav Paul +Johan Brandhorst +John Shahid +John Tuley +Laurent +Patrick Lee +Peter Edge +Roger Johansson +Sam Nguyen +Sergio Arbeo +Stephen J Day +Tamir Duberstein +Todd Eisenberger +Tormod Erevik Lea +Vyacheslav Kim +Walter Schulze diff --git a/vendor/github.com/gogo/protobuf/LICENSE b/vendor/github.com/gogo/protobuf/LICENSE new file mode 100644 index 000000000..f57de90da --- /dev/null +++ b/vendor/github.com/gogo/protobuf/LICENSE @@ -0,0 +1,35 @@ +Copyright (c) 2013, The GoGo Authors. All rights reserved. + +Protocol Buffers for Go with Gadgets + +Go support for Protocol Buffers - Google's data interchange format + +Copyright 2010 The Go Authors. All rights reserved. +https://github.com/golang/protobuf + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/github.com/gogo/protobuf/proto/Makefile b/vendor/github.com/gogo/protobuf/proto/Makefile new file mode 100644 index 000000000..00d65f327 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/Makefile @@ -0,0 +1,43 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# 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. + +install: + go install + +test: install generate-test-pbs + go test + + +generate-test-pbs: + make install + make -C test_proto + make -C proto3_proto + make diff --git a/vendor/github.com/gogo/protobuf/proto/clone.go b/vendor/github.com/gogo/protobuf/proto/clone.go new file mode 100644 index 000000000..a26b046d9 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/clone.go @@ -0,0 +1,258 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +// Protocol buffer deep copy and merge. +// TODO: RawMessage. + +package proto + +import ( + "fmt" + "log" + "reflect" + "strings" +) + +// Clone returns a deep copy of a protocol buffer. +func Clone(src Message) Message { + in := reflect.ValueOf(src) + if in.IsNil() { + return src + } + out := reflect.New(in.Type().Elem()) + dst := out.Interface().(Message) + Merge(dst, src) + return dst +} + +// Merger is the interface representing objects that can merge messages of the same type. +type Merger interface { + // Merge merges src into this message. + // Required and optional fields that are set in src will be set to that value in dst. + // Elements of repeated fields will be appended. + // + // Merge may panic if called with a different argument type than the receiver. + Merge(src Message) +} + +// generatedMerger is the custom merge method that generated protos will have. +// We must add this method since a generate Merge method will conflict with +// many existing protos that have a Merge data field already defined. +type generatedMerger interface { + XXX_Merge(src Message) +} + +// Merge merges src into dst. +// Required and optional fields that are set in src will be set to that value in dst. +// Elements of repeated fields will be appended. +// Merge panics if src and dst are not the same type, or if dst is nil. +func Merge(dst, src Message) { + if m, ok := dst.(Merger); ok { + m.Merge(src) + return + } + + in := reflect.ValueOf(src) + out := reflect.ValueOf(dst) + if out.IsNil() { + panic("proto: nil destination") + } + if in.Type() != out.Type() { + panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src)) + } + if in.IsNil() { + return // Merge from nil src is a noop + } + if m, ok := dst.(generatedMerger); ok { + m.XXX_Merge(src) + return + } + mergeStruct(out.Elem(), in.Elem()) +} + +func mergeStruct(out, in reflect.Value) { + sprop := GetProperties(in.Type()) + for i := 0; i < in.NumField(); i++ { + f := in.Type().Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) + } + + if emIn, ok := in.Addr().Interface().(extensionsBytes); ok { + emOut := out.Addr().Interface().(extensionsBytes) + bIn := emIn.GetExtensions() + bOut := emOut.GetExtensions() + *bOut = append(*bOut, *bIn...) + } else if emIn, err := extendable(in.Addr().Interface()); err == nil { + emOut, _ := extendable(out.Addr().Interface()) + mIn, muIn := emIn.extensionsRead() + if mIn != nil { + mOut := emOut.extensionsWrite() + muIn.Lock() + mergeExtension(mOut, mIn) + muIn.Unlock() + } + } + + uf := in.FieldByName("XXX_unrecognized") + if !uf.IsValid() { + return + } + uin := uf.Bytes() + if len(uin) > 0 { + out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...)) + } +} + +// mergeAny performs a merge between two values of the same type. +// viaPtr indicates whether the values were indirected through a pointer (implying proto2). +// prop is set if this is a struct field (it may be nil). +func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) { + if in.Type() == protoMessageType { + if !in.IsNil() { + if out.IsNil() { + out.Set(reflect.ValueOf(Clone(in.Interface().(Message)))) + } else { + Merge(out.Interface().(Message), in.Interface().(Message)) + } + } + return + } + switch in.Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + if !viaPtr && isProto3Zero(in) { + return + } + out.Set(in) + case reflect.Interface: + // Probably a oneof field; copy non-nil values. + if in.IsNil() { + return + } + // Allocate destination if it is not set, or set to a different type. + // Otherwise we will merge as normal. + if out.IsNil() || out.Elem().Type() != in.Elem().Type() { + out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T) + } + mergeAny(out.Elem(), in.Elem(), false, nil) + case reflect.Map: + if in.Len() == 0 { + return + } + if out.IsNil() { + out.Set(reflect.MakeMap(in.Type())) + } + // For maps with value types of *T or []byte we need to deep copy each value. + elemKind := in.Type().Elem().Kind() + for _, key := range in.MapKeys() { + var val reflect.Value + switch elemKind { + case reflect.Ptr: + val = reflect.New(in.Type().Elem().Elem()) + mergeAny(val, in.MapIndex(key), false, nil) + case reflect.Slice: + val = in.MapIndex(key) + val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) + default: + val = in.MapIndex(key) + } + out.SetMapIndex(key, val) + } + case reflect.Ptr: + if in.IsNil() { + return + } + if out.IsNil() { + out.Set(reflect.New(in.Elem().Type())) + } + mergeAny(out.Elem(), in.Elem(), true, nil) + case reflect.Slice: + if in.IsNil() { + return + } + if in.Type().Elem().Kind() == reflect.Uint8 { + // []byte is a scalar bytes field, not a repeated field. + + // Edge case: if this is in a proto3 message, a zero length + // bytes field is considered the zero value, and should not + // be merged. + if prop != nil && prop.proto3 && in.Len() == 0 { + return + } + + // Make a deep copy. + // Append to []byte{} instead of []byte(nil) so that we never end up + // with a nil result. + out.SetBytes(append([]byte{}, in.Bytes()...)) + return + } + n := in.Len() + if out.IsNil() { + out.Set(reflect.MakeSlice(in.Type(), 0, n)) + } + switch in.Type().Elem().Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + out.Set(reflect.AppendSlice(out, in)) + default: + for i := 0; i < n; i++ { + x := reflect.Indirect(reflect.New(in.Type().Elem())) + mergeAny(x, in.Index(i), false, nil) + out.Set(reflect.Append(out, x)) + } + } + case reflect.Struct: + mergeStruct(out, in) + default: + // unknown type, so not a protocol buffer + log.Printf("proto: don't know how to copy %v", in) + } +} + +func mergeExtension(out, in map[int32]Extension) { + for extNum, eIn := range in { + eOut := Extension{desc: eIn.desc} + if eIn.value != nil { + v := reflect.New(reflect.TypeOf(eIn.value)).Elem() + mergeAny(v, reflect.ValueOf(eIn.value), false, nil) + eOut.value = v.Interface() + } + if eIn.enc != nil { + eOut.enc = make([]byte, len(eIn.enc)) + copy(eOut.enc, eIn.enc) + } + + out[extNum] = eOut + } +} diff --git a/vendor/github.com/gogo/protobuf/proto/custom_gogo.go b/vendor/github.com/gogo/protobuf/proto/custom_gogo.go new file mode 100644 index 000000000..24552483c --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/custom_gogo.go @@ -0,0 +1,39 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2018, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import "reflect" + +type custom interface { + Marshal() ([]byte, error) + Unmarshal(data []byte) error + Size() int +} + +var customType = reflect.TypeOf((*custom)(nil)).Elem() diff --git a/vendor/github.com/gogo/protobuf/proto/decode.go b/vendor/github.com/gogo/protobuf/proto/decode.go new file mode 100644 index 000000000..63b0f08be --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/decode.go @@ -0,0 +1,427 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +/* + * Routines for decoding protocol buffer data to construct in-memory representations. + */ + +import ( + "errors" + "fmt" + "io" +) + +// errOverflow is returned when an integer is too large to be represented. +var errOverflow = errors.New("proto: integer overflow") + +// ErrInternalBadWireType is returned by generated code when an incorrect +// wire type is encountered. It does not get returned to user code. +var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof") + +// DecodeVarint reads a varint-encoded integer from the slice. +// It returns the integer and the number of bytes consumed, or +// zero if there is not enough. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func DecodeVarint(buf []byte) (x uint64, n int) { + for shift := uint(0); shift < 64; shift += 7 { + if n >= len(buf) { + return 0, 0 + } + b := uint64(buf[n]) + n++ + x |= (b & 0x7F) << shift + if (b & 0x80) == 0 { + return x, n + } + } + + // The number is too large to represent in a 64-bit value. + return 0, 0 +} + +func (p *Buffer) decodeVarintSlow() (x uint64, err error) { + i := p.index + l := len(p.buf) + + for shift := uint(0); shift < 64; shift += 7 { + if i >= l { + err = io.ErrUnexpectedEOF + return + } + b := p.buf[i] + i++ + x |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + p.index = i + return + } + } + + // The number is too large to represent in a 64-bit value. + err = errOverflow + return +} + +// DecodeVarint reads a varint-encoded integer from the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) DecodeVarint() (x uint64, err error) { + i := p.index + buf := p.buf + + if i >= len(buf) { + return 0, io.ErrUnexpectedEOF + } else if buf[i] < 0x80 { + p.index++ + return uint64(buf[i]), nil + } else if len(buf)-i < 10 { + return p.decodeVarintSlow() + } + + var b uint64 + // we already checked the first byte + x = uint64(buf[i]) - 0x80 + i++ + + b = uint64(buf[i]) + i++ + x += b << 7 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 7 + + b = uint64(buf[i]) + i++ + x += b << 14 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 14 + + b = uint64(buf[i]) + i++ + x += b << 21 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 21 + + b = uint64(buf[i]) + i++ + x += b << 28 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 28 + + b = uint64(buf[i]) + i++ + x += b << 35 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 35 + + b = uint64(buf[i]) + i++ + x += b << 42 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 42 + + b = uint64(buf[i]) + i++ + x += b << 49 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 49 + + b = uint64(buf[i]) + i++ + x += b << 56 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 56 + + b = uint64(buf[i]) + i++ + x += b << 63 + if b&0x80 == 0 { + goto done + } + + return 0, errOverflow + +done: + p.index = i + return x, nil +} + +// DecodeFixed64 reads a 64-bit integer from the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) DecodeFixed64() (x uint64, err error) { + // x, err already 0 + i := p.index + 8 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-8]) + x |= uint64(p.buf[i-7]) << 8 + x |= uint64(p.buf[i-6]) << 16 + x |= uint64(p.buf[i-5]) << 24 + x |= uint64(p.buf[i-4]) << 32 + x |= uint64(p.buf[i-3]) << 40 + x |= uint64(p.buf[i-2]) << 48 + x |= uint64(p.buf[i-1]) << 56 + return +} + +// DecodeFixed32 reads a 32-bit integer from the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) DecodeFixed32() (x uint64, err error) { + // x, err already 0 + i := p.index + 4 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-4]) + x |= uint64(p.buf[i-3]) << 8 + x |= uint64(p.buf[i-2]) << 16 + x |= uint64(p.buf[i-1]) << 24 + return +} + +// DecodeZigzag64 reads a zigzag-encoded 64-bit integer +// from the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) DecodeZigzag64() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63) + return +} + +// DecodeZigzag32 reads a zigzag-encoded 32-bit integer +// from the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) DecodeZigzag32() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31)) + return +} + +// DecodeRawBytes reads a count-delimited byte buffer from the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) { + n, err := p.DecodeVarint() + if err != nil { + return nil, err + } + + nb := int(n) + if nb < 0 { + return nil, fmt.Errorf("proto: bad byte length %d", nb) + } + end := p.index + nb + if end < p.index || end > len(p.buf) { + return nil, io.ErrUnexpectedEOF + } + + if !alloc { + // todo: check if can get more uses of alloc=false + buf = p.buf[p.index:end] + p.index += nb + return + } + + buf = make([]byte, nb) + copy(buf, p.buf[p.index:]) + p.index += nb + return +} + +// DecodeStringBytes reads an encoded string from the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) DecodeStringBytes() (s string, err error) { + buf, err := p.DecodeRawBytes(false) + if err != nil { + return + } + return string(buf), nil +} + +// Unmarshaler is the interface representing objects that can +// unmarshal themselves. The argument points to data that may be +// overwritten, so implementations should not keep references to the +// buffer. +// Unmarshal implementations should not clear the receiver. +// Any unmarshaled data should be merged into the receiver. +// Callers of Unmarshal that do not want to retain existing data +// should Reset the receiver before calling Unmarshal. +type Unmarshaler interface { + Unmarshal([]byte) error +} + +// newUnmarshaler is the interface representing objects that can +// unmarshal themselves. The semantics are identical to Unmarshaler. +// +// This exists to support protoc-gen-go generated messages. +// The proto package will stop type-asserting to this interface in the future. +// +// DO NOT DEPEND ON THIS. +type newUnmarshaler interface { + XXX_Unmarshal([]byte) error +} + +// Unmarshal parses the protocol buffer representation in buf and places the +// decoded result in pb. If the struct underlying pb does not match +// the data in buf, the results can be unpredictable. +// +// Unmarshal resets pb before starting to unmarshal, so any +// existing data in pb is always removed. Use UnmarshalMerge +// to preserve and append to existing data. +func Unmarshal(buf []byte, pb Message) error { + pb.Reset() + if u, ok := pb.(newUnmarshaler); ok { + return u.XXX_Unmarshal(buf) + } + if u, ok := pb.(Unmarshaler); ok { + return u.Unmarshal(buf) + } + return NewBuffer(buf).Unmarshal(pb) +} + +// UnmarshalMerge parses the protocol buffer representation in buf and +// writes the decoded result to pb. If the struct underlying pb does not match +// the data in buf, the results can be unpredictable. +// +// UnmarshalMerge merges into existing data in pb. +// Most code should use Unmarshal instead. +func UnmarshalMerge(buf []byte, pb Message) error { + if u, ok := pb.(newUnmarshaler); ok { + return u.XXX_Unmarshal(buf) + } + if u, ok := pb.(Unmarshaler); ok { + // NOTE: The history of proto have unfortunately been inconsistent + // whether Unmarshaler should or should not implicitly clear itself. + // Some implementations do, most do not. + // Thus, calling this here may or may not do what people want. + // + // See https://github.com/golang/protobuf/issues/424 + return u.Unmarshal(buf) + } + return NewBuffer(buf).Unmarshal(pb) +} + +// DecodeMessage reads a count-delimited message from the Buffer. +func (p *Buffer) DecodeMessage(pb Message) error { + enc, err := p.DecodeRawBytes(false) + if err != nil { + return err + } + return NewBuffer(enc).Unmarshal(pb) +} + +// DecodeGroup reads a tag-delimited group from the Buffer. +// StartGroup tag is already consumed. This function consumes +// EndGroup tag. +func (p *Buffer) DecodeGroup(pb Message) error { + b := p.buf[p.index:] + x, y := findEndGroup(b) + if x < 0 { + return io.ErrUnexpectedEOF + } + err := Unmarshal(b[:x], pb) + p.index += y + return err +} + +// Unmarshal parses the protocol buffer representation in the +// Buffer and places the decoded result in pb. If the struct +// underlying pb does not match the data in the buffer, the results can be +// unpredictable. +// +// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal. +func (p *Buffer) Unmarshal(pb Message) error { + // If the object can unmarshal itself, let it. + if u, ok := pb.(newUnmarshaler); ok { + err := u.XXX_Unmarshal(p.buf[p.index:]) + p.index = len(p.buf) + return err + } + if u, ok := pb.(Unmarshaler); ok { + // NOTE: The history of proto have unfortunately been inconsistent + // whether Unmarshaler should or should not implicitly clear itself. + // Some implementations do, most do not. + // Thus, calling this here may or may not do what people want. + // + // See https://github.com/golang/protobuf/issues/424 + err := u.Unmarshal(p.buf[p.index:]) + p.index = len(p.buf) + return err + } + + // Slow workaround for messages that aren't Unmarshalers. + // This includes some hand-coded .pb.go files and + // bootstrap protos. + // TODO: fix all of those and then add Unmarshal to + // the Message interface. Then: + // The cast above and code below can be deleted. + // The old unmarshaler can be deleted. + // Clients can call Unmarshal directly (can already do that, actually). + var info InternalMessageInfo + err := info.Unmarshal(pb, p.buf[p.index:]) + p.index = len(p.buf) + return err +} diff --git a/vendor/github.com/gogo/protobuf/proto/deprecated.go b/vendor/github.com/gogo/protobuf/proto/deprecated.go new file mode 100644 index 000000000..35b882c09 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/deprecated.go @@ -0,0 +1,63 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2018 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +import "errors" + +// Deprecated: do not use. +type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 } + +// Deprecated: do not use. +func GetStats() Stats { return Stats{} } + +// Deprecated: do not use. +func MarshalMessageSet(interface{}) ([]byte, error) { + return nil, errors.New("proto: not implemented") +} + +// Deprecated: do not use. +func UnmarshalMessageSet([]byte, interface{}) error { + return errors.New("proto: not implemented") +} + +// Deprecated: do not use. +func MarshalMessageSetJSON(interface{}) ([]byte, error) { + return nil, errors.New("proto: not implemented") +} + +// Deprecated: do not use. +func UnmarshalMessageSetJSON([]byte, interface{}) error { + return errors.New("proto: not implemented") +} + +// Deprecated: do not use. +func RegisterMessageSetType(Message, int32, string) {} diff --git a/vendor/github.com/gogo/protobuf/proto/discard.go b/vendor/github.com/gogo/protobuf/proto/discard.go new file mode 100644 index 000000000..fe1bd7d90 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/discard.go @@ -0,0 +1,350 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2017 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +import ( + "fmt" + "reflect" + "strings" + "sync" + "sync/atomic" +) + +type generatedDiscarder interface { + XXX_DiscardUnknown() +} + +// DiscardUnknown recursively discards all unknown fields from this message +// and all embedded messages. +// +// When unmarshaling a message with unrecognized fields, the tags and values +// of such fields are preserved in the Message. This allows a later call to +// marshal to be able to produce a message that continues to have those +// unrecognized fields. To avoid this, DiscardUnknown is used to +// explicitly clear the unknown fields after unmarshaling. +// +// For proto2 messages, the unknown fields of message extensions are only +// discarded from messages that have been accessed via GetExtension. +func DiscardUnknown(m Message) { + if m, ok := m.(generatedDiscarder); ok { + m.XXX_DiscardUnknown() + return + } + // TODO: Dynamically populate a InternalMessageInfo for legacy messages, + // but the master branch has no implementation for InternalMessageInfo, + // so it would be more work to replicate that approach. + discardLegacy(m) +} + +// DiscardUnknown recursively discards all unknown fields. +func (a *InternalMessageInfo) DiscardUnknown(m Message) { + di := atomicLoadDiscardInfo(&a.discard) + if di == nil { + di = getDiscardInfo(reflect.TypeOf(m).Elem()) + atomicStoreDiscardInfo(&a.discard, di) + } + di.discard(toPointer(&m)) +} + +type discardInfo struct { + typ reflect.Type + + initialized int32 // 0: only typ is valid, 1: everything is valid + lock sync.Mutex + + fields []discardFieldInfo + unrecognized field +} + +type discardFieldInfo struct { + field field // Offset of field, guaranteed to be valid + discard func(src pointer) +} + +var ( + discardInfoMap = map[reflect.Type]*discardInfo{} + discardInfoLock sync.Mutex +) + +func getDiscardInfo(t reflect.Type) *discardInfo { + discardInfoLock.Lock() + defer discardInfoLock.Unlock() + di := discardInfoMap[t] + if di == nil { + di = &discardInfo{typ: t} + discardInfoMap[t] = di + } + return di +} + +func (di *discardInfo) discard(src pointer) { + if src.isNil() { + return // Nothing to do. + } + + if atomic.LoadInt32(&di.initialized) == 0 { + di.computeDiscardInfo() + } + + for _, fi := range di.fields { + sfp := src.offset(fi.field) + fi.discard(sfp) + } + + // For proto2 messages, only discard unknown fields in message extensions + // that have been accessed via GetExtension. + if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil { + // Ignore lock since DiscardUnknown is not concurrency safe. + emm, _ := em.extensionsRead() + for _, mx := range emm { + if m, ok := mx.value.(Message); ok { + DiscardUnknown(m) + } + } + } + + if di.unrecognized.IsValid() { + *src.offset(di.unrecognized).toBytes() = nil + } +} + +func (di *discardInfo) computeDiscardInfo() { + di.lock.Lock() + defer di.lock.Unlock() + if di.initialized != 0 { + return + } + t := di.typ + n := t.NumField() + + for i := 0; i < n; i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + + dfi := discardFieldInfo{field: toField(&f)} + tf := f.Type + + // Unwrap tf to get its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name)) + } + + switch tf.Kind() { + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name)) + case isSlice: // E.g., []*pb.T + discardInfo := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sps := src.getPointerSlice() + for _, sp := range sps { + if !sp.isNil() { + discardInfo.discard(sp) + } + } + } + default: // E.g., *pb.T + discardInfo := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sp := src.getPointer() + if !sp.isNil() { + discardInfo.discard(sp) + } + } + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name)) + default: // E.g., map[K]V + if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T) + dfi.discard = func(src pointer) { + sm := src.asPointerTo(tf).Elem() + if sm.Len() == 0 { + return + } + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + DiscardUnknown(val.Interface().(Message)) + } + } + } else { + dfi.discard = func(pointer) {} // Noop + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name)) + default: // E.g., interface{} + // TODO: Make this faster? + dfi.discard = func(src pointer) { + su := src.asPointerTo(tf).Elem() + if !su.IsNil() { + sv := su.Elem().Elem().Field(0) + if sv.Kind() == reflect.Ptr && sv.IsNil() { + return + } + switch sv.Type().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + DiscardUnknown(sv.Interface().(Message)) + } + } + } + } + default: + continue + } + di.fields = append(di.fields, dfi) + } + + di.unrecognized = invalidField + if f, ok := t.FieldByName("XXX_unrecognized"); ok { + if f.Type != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + di.unrecognized = toField(&f) + } + + atomic.StoreInt32(&di.initialized, 1) +} + +func discardLegacy(m Message) { + v := reflect.ValueOf(m) + if v.Kind() != reflect.Ptr || v.IsNil() { + return + } + v = v.Elem() + if v.Kind() != reflect.Struct { + return + } + t := v.Type() + + for i := 0; i < v.NumField(); i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + vf := v.Field(i) + tf := f.Type + + // Unwrap tf to get its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name)) + } + + switch tf.Kind() { + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name)) + case isSlice: // E.g., []*pb.T + for j := 0; j < vf.Len(); j++ { + discardLegacy(vf.Index(j).Interface().(Message)) + } + default: // E.g., *pb.T + discardLegacy(vf.Interface().(Message)) + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name)) + default: // E.g., map[K]V + tv := vf.Type().Elem() + if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T) + for _, key := range vf.MapKeys() { + val := vf.MapIndex(key) + discardLegacy(val.Interface().(Message)) + } + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name)) + default: // E.g., test_proto.isCommunique_Union interface + if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" { + vf = vf.Elem() // E.g., *test_proto.Communique_Msg + if !vf.IsNil() { + vf = vf.Elem() // E.g., test_proto.Communique_Msg + vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value + if vf.Kind() == reflect.Ptr { + discardLegacy(vf.Interface().(Message)) + } + } + } + } + } + } + + if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() { + if vf.Type() != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + vf.Set(reflect.ValueOf([]byte(nil))) + } + + // For proto2 messages, only discard unknown fields in message extensions + // that have been accessed via GetExtension. + if em, err := extendable(m); err == nil { + // Ignore lock since discardLegacy is not concurrency safe. + emm, _ := em.extensionsRead() + for _, mx := range emm { + if m, ok := mx.value.(Message); ok { + discardLegacy(m) + } + } + } +} diff --git a/vendor/github.com/gogo/protobuf/proto/duration.go b/vendor/github.com/gogo/protobuf/proto/duration.go new file mode 100644 index 000000000..93464c91c --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/duration.go @@ -0,0 +1,100 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +// This file implements conversions between google.protobuf.Duration +// and time.Duration. + +import ( + "errors" + "fmt" + "time" +) + +const ( + // Range of a Duration in seconds, as specified in + // google/protobuf/duration.proto. This is about 10,000 years in seconds. + maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60) + minSeconds = -maxSeconds +) + +// validateDuration determines whether the Duration is valid according to the +// definition in google/protobuf/duration.proto. A valid Duration +// may still be too large to fit into a time.Duration (the range of Duration +// is about 10,000 years, and the range of time.Duration is about 290). +func validateDuration(d *duration) error { + if d == nil { + return errors.New("duration: nil Duration") + } + if d.Seconds < minSeconds || d.Seconds > maxSeconds { + return fmt.Errorf("duration: %#v: seconds out of range", d) + } + if d.Nanos <= -1e9 || d.Nanos >= 1e9 { + return fmt.Errorf("duration: %#v: nanos out of range", d) + } + // Seconds and Nanos must have the same sign, unless d.Nanos is zero. + if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) { + return fmt.Errorf("duration: %#v: seconds and nanos have different signs", d) + } + return nil +} + +// DurationFromProto converts a Duration to a time.Duration. DurationFromProto +// returns an error if the Duration is invalid or is too large to be +// represented in a time.Duration. +func durationFromProto(p *duration) (time.Duration, error) { + if err := validateDuration(p); err != nil { + return 0, err + } + d := time.Duration(p.Seconds) * time.Second + if int64(d/time.Second) != p.Seconds { + return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p) + } + if p.Nanos != 0 { + d += time.Duration(p.Nanos) + if (d < 0) != (p.Nanos < 0) { + return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p) + } + } + return d, nil +} + +// DurationProto converts a time.Duration to a Duration. +func durationProto(d time.Duration) *duration { + nanos := d.Nanoseconds() + secs := nanos / 1e9 + nanos -= secs * 1e9 + return &duration{ + Seconds: secs, + Nanos: int32(nanos), + } +} diff --git a/vendor/github.com/gogo/protobuf/proto/duration_gogo.go b/vendor/github.com/gogo/protobuf/proto/duration_gogo.go new file mode 100644 index 000000000..e748e1730 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/duration_gogo.go @@ -0,0 +1,49 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2016, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "reflect" + "time" +) + +var durationType = reflect.TypeOf((*time.Duration)(nil)).Elem() + +type duration struct { + Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"` + Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"` +} + +func (m *duration) Reset() { *m = duration{} } +func (*duration) ProtoMessage() {} +func (*duration) String() string { return "duration" } + +func init() { + RegisterType((*duration)(nil), "gogo.protobuf.proto.duration") +} diff --git a/vendor/github.com/gogo/protobuf/proto/encode.go b/vendor/github.com/gogo/protobuf/proto/encode.go new file mode 100644 index 000000000..3abfed2cf --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/encode.go @@ -0,0 +1,203 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +/* + * Routines for encoding data into the wire format for protocol buffers. + */ + +import ( + "errors" + "reflect" +) + +var ( + // errRepeatedHasNil is the error returned if Marshal is called with + // a struct with a repeated field containing a nil element. + errRepeatedHasNil = errors.New("proto: repeated field has nil element") + + // errOneofHasNil is the error returned if Marshal is called with + // a struct with a oneof field containing a nil element. + errOneofHasNil = errors.New("proto: oneof field has nil value") + + // ErrNil is the error returned if Marshal is called with nil. + ErrNil = errors.New("proto: Marshal called with nil") + + // ErrTooLarge is the error returned if Marshal is called with a + // message that encodes to >2GB. + ErrTooLarge = errors.New("proto: message encodes to over 2 GB") +) + +// The fundamental encoders that put bytes on the wire. +// Those that take integer types all accept uint64 and are +// therefore of type valueEncoder. + +const maxVarintBytes = 10 // maximum length of a varint + +// EncodeVarint returns the varint encoding of x. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +// Not used by the package itself, but helpful to clients +// wishing to use the same encoding. +func EncodeVarint(x uint64) []byte { + var buf [maxVarintBytes]byte + var n int + for n = 0; x > 127; n++ { + buf[n] = 0x80 | uint8(x&0x7F) + x >>= 7 + } + buf[n] = uint8(x) + n++ + return buf[0:n] +} + +// EncodeVarint writes a varint-encoded integer to the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) EncodeVarint(x uint64) error { + for x >= 1<<7 { + p.buf = append(p.buf, uint8(x&0x7f|0x80)) + x >>= 7 + } + p.buf = append(p.buf, uint8(x)) + return nil +} + +// SizeVarint returns the varint encoding size of an integer. +func SizeVarint(x uint64) int { + switch { + case x < 1<<7: + return 1 + case x < 1<<14: + return 2 + case x < 1<<21: + return 3 + case x < 1<<28: + return 4 + case x < 1<<35: + return 5 + case x < 1<<42: + return 6 + case x < 1<<49: + return 7 + case x < 1<<56: + return 8 + case x < 1<<63: + return 9 + } + return 10 +} + +// EncodeFixed64 writes a 64-bit integer to the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) EncodeFixed64(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24), + uint8(x>>32), + uint8(x>>40), + uint8(x>>48), + uint8(x>>56)) + return nil +} + +// EncodeFixed32 writes a 32-bit integer to the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) EncodeFixed32(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24)) + return nil +} + +// EncodeZigzag64 writes a zigzag-encoded 64-bit integer +// to the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) EncodeZigzag64(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} + +// EncodeZigzag32 writes a zigzag-encoded 32-bit integer +// to the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) EncodeZigzag32(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) +} + +// EncodeRawBytes writes a count-delimited byte buffer to the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (p *Buffer) EncodeRawBytes(b []byte) error { + p.EncodeVarint(uint64(len(b))) + p.buf = append(p.buf, b...) + return nil +} + +// EncodeStringBytes writes an encoded string to the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) EncodeStringBytes(s string) error { + p.EncodeVarint(uint64(len(s))) + p.buf = append(p.buf, s...) + return nil +} + +// Marshaler is the interface representing objects that can marshal themselves. +type Marshaler interface { + Marshal() ([]byte, error) +} + +// EncodeMessage writes the protocol buffer to the Buffer, +// prefixed by a varint-encoded length. +func (p *Buffer) EncodeMessage(pb Message) error { + siz := Size(pb) + p.EncodeVarint(uint64(siz)) + return p.Marshal(pb) +} + +// All protocol buffer fields are nillable, but be careful. +func isNil(v reflect.Value) bool { + switch v.Kind() { + case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return v.IsNil() + } + return false +} diff --git a/vendor/github.com/gogo/protobuf/proto/encode_gogo.go b/vendor/github.com/gogo/protobuf/proto/encode_gogo.go new file mode 100644 index 000000000..0f5fb173e --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/encode_gogo.go @@ -0,0 +1,33 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +func NewRequiredNotSetError(field string) *RequiredNotSetError { + return &RequiredNotSetError{field} +} diff --git a/vendor/github.com/gogo/protobuf/proto/equal.go b/vendor/github.com/gogo/protobuf/proto/equal.go new file mode 100644 index 000000000..d4db5a1c1 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/equal.go @@ -0,0 +1,300 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +// Protocol buffer comparison. + +package proto + +import ( + "bytes" + "log" + "reflect" + "strings" +) + +/* +Equal returns true iff protocol buffers a and b are equal. +The arguments must both be pointers to protocol buffer structs. + +Equality is defined in this way: + - Two messages are equal iff they are the same type, + corresponding fields are equal, unknown field sets + are equal, and extensions sets are equal. + - Two set scalar fields are equal iff their values are equal. + If the fields are of a floating-point type, remember that + NaN != x for all x, including NaN. If the message is defined + in a proto3 .proto file, fields are not "set"; specifically, + zero length proto3 "bytes" fields are equal (nil == {}). + - Two repeated fields are equal iff their lengths are the same, + and their corresponding elements are equal. Note a "bytes" field, + although represented by []byte, is not a repeated field and the + rule for the scalar fields described above applies. + - Two unset fields are equal. + - Two unknown field sets are equal if their current + encoded state is equal. + - Two extension sets are equal iff they have corresponding + elements that are pairwise equal. + - Two map fields are equal iff their lengths are the same, + and they contain the same set of elements. Zero-length map + fields are equal. + - Every other combination of things are not equal. + +The return value is undefined if a and b are not protocol buffers. +*/ +func Equal(a, b Message) bool { + if a == nil || b == nil { + return a == b + } + v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b) + if v1.Type() != v2.Type() { + return false + } + if v1.Kind() == reflect.Ptr { + if v1.IsNil() { + return v2.IsNil() + } + if v2.IsNil() { + return false + } + v1, v2 = v1.Elem(), v2.Elem() + } + if v1.Kind() != reflect.Struct { + return false + } + return equalStruct(v1, v2) +} + +// v1 and v2 are known to have the same type. +func equalStruct(v1, v2 reflect.Value) bool { + sprop := GetProperties(v1.Type()) + for i := 0; i < v1.NumField(); i++ { + f := v1.Type().Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + f1, f2 := v1.Field(i), v2.Field(i) + if f.Type.Kind() == reflect.Ptr { + if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 { + // both unset + continue + } else if n1 != n2 { + // set/unset mismatch + return false + } + f1, f2 = f1.Elem(), f2.Elem() + } + if !equalAny(f1, f2, sprop.Prop[i]) { + return false + } + } + + if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() { + em2 := v2.FieldByName("XXX_InternalExtensions") + if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) { + return false + } + } + + if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { + em2 := v2.FieldByName("XXX_extensions") + if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { + return false + } + } + + uf := v1.FieldByName("XXX_unrecognized") + if !uf.IsValid() { + return true + } + + u1 := uf.Bytes() + u2 := v2.FieldByName("XXX_unrecognized").Bytes() + return bytes.Equal(u1, u2) +} + +// v1 and v2 are known to have the same type. +// prop may be nil. +func equalAny(v1, v2 reflect.Value, prop *Properties) bool { + if v1.Type() == protoMessageType { + m1, _ := v1.Interface().(Message) + m2, _ := v2.Interface().(Message) + return Equal(m1, m2) + } + switch v1.Kind() { + case reflect.Bool: + return v1.Bool() == v2.Bool() + case reflect.Float32, reflect.Float64: + return v1.Float() == v2.Float() + case reflect.Int32, reflect.Int64: + return v1.Int() == v2.Int() + case reflect.Interface: + // Probably a oneof field; compare the inner values. + n1, n2 := v1.IsNil(), v2.IsNil() + if n1 || n2 { + return n1 == n2 + } + e1, e2 := v1.Elem(), v2.Elem() + if e1.Type() != e2.Type() { + return false + } + return equalAny(e1, e2, nil) + case reflect.Map: + if v1.Len() != v2.Len() { + return false + } + for _, key := range v1.MapKeys() { + val2 := v2.MapIndex(key) + if !val2.IsValid() { + // This key was not found in the second map. + return false + } + if !equalAny(v1.MapIndex(key), val2, nil) { + return false + } + } + return true + case reflect.Ptr: + // Maps may have nil values in them, so check for nil. + if v1.IsNil() && v2.IsNil() { + return true + } + if v1.IsNil() != v2.IsNil() { + return false + } + return equalAny(v1.Elem(), v2.Elem(), prop) + case reflect.Slice: + if v1.Type().Elem().Kind() == reflect.Uint8 { + // short circuit: []byte + + // Edge case: if this is in a proto3 message, a zero length + // bytes field is considered the zero value. + if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 { + return true + } + if v1.IsNil() != v2.IsNil() { + return false + } + return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte)) + } + + if v1.Len() != v2.Len() { + return false + } + for i := 0; i < v1.Len(); i++ { + if !equalAny(v1.Index(i), v2.Index(i), prop) { + return false + } + } + return true + case reflect.String: + return v1.Interface().(string) == v2.Interface().(string) + case reflect.Struct: + return equalStruct(v1, v2) + case reflect.Uint32, reflect.Uint64: + return v1.Uint() == v2.Uint() + } + + // unknown type, so not a protocol buffer + log.Printf("proto: don't know how to compare %v", v1) + return false +} + +// base is the struct type that the extensions are based on. +// x1 and x2 are InternalExtensions. +func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool { + em1, _ := x1.extensionsRead() + em2, _ := x2.extensionsRead() + return equalExtMap(base, em1, em2) +} + +func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { + if len(em1) != len(em2) { + return false + } + + for extNum, e1 := range em1 { + e2, ok := em2[extNum] + if !ok { + return false + } + + m1, m2 := e1.value, e2.value + + if m1 == nil && m2 == nil { + // Both have only encoded form. + if bytes.Equal(e1.enc, e2.enc) { + continue + } + // The bytes are different, but the extensions might still be + // equal. We need to decode them to compare. + } + + if m1 != nil && m2 != nil { + // Both are unencoded. + if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { + return false + } + continue + } + + // At least one is encoded. To do a semantically correct comparison + // we need to unmarshal them first. + var desc *ExtensionDesc + if m := extensionMaps[base]; m != nil { + desc = m[extNum] + } + if desc == nil { + // If both have only encoded form and the bytes are the same, + // it is handled above. We get here when the bytes are different. + // We don't know how to decode it, so just compare them as byte + // slices. + log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) + return false + } + var err error + if m1 == nil { + m1, err = decodeExtension(e1.enc, desc) + } + if m2 == nil && err == nil { + m2, err = decodeExtension(e2.enc, desc) + } + if err != nil { + // The encoded form is invalid. + log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err) + return false + } + if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { + return false + } + } + + return true +} diff --git a/vendor/github.com/gogo/protobuf/proto/extensions.go b/vendor/github.com/gogo/protobuf/proto/extensions.go new file mode 100644 index 000000000..686bd2a09 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/extensions.go @@ -0,0 +1,604 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +/* + * Types and routines for supporting protocol buffer extensions. + */ + +import ( + "errors" + "fmt" + "io" + "reflect" + "strconv" + "sync" +) + +// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message. +var ErrMissingExtension = errors.New("proto: missing extension") + +// ExtensionRange represents a range of message extensions for a protocol buffer. +// Used in code generated by the protocol compiler. +type ExtensionRange struct { + Start, End int32 // both inclusive +} + +// extendableProto is an interface implemented by any protocol buffer generated by the current +// proto compiler that may be extended. +type extendableProto interface { + Message + ExtensionRangeArray() []ExtensionRange + extensionsWrite() map[int32]Extension + extensionsRead() (map[int32]Extension, sync.Locker) +} + +// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous +// version of the proto compiler that may be extended. +type extendableProtoV1 interface { + Message + ExtensionRangeArray() []ExtensionRange + ExtensionMap() map[int32]Extension +} + +// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto. +type extensionAdapter struct { + extendableProtoV1 +} + +func (e extensionAdapter) extensionsWrite() map[int32]Extension { + return e.ExtensionMap() +} + +func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) { + return e.ExtensionMap(), notLocker{} +} + +// notLocker is a sync.Locker whose Lock and Unlock methods are nops. +type notLocker struct{} + +func (n notLocker) Lock() {} +func (n notLocker) Unlock() {} + +// extendable returns the extendableProto interface for the given generated proto message. +// If the proto message has the old extension format, it returns a wrapper that implements +// the extendableProto interface. +func extendable(p interface{}) (extendableProto, error) { + switch p := p.(type) { + case extendableProto: + if isNilPtr(p) { + return nil, fmt.Errorf("proto: nil %T is not extendable", p) + } + return p, nil + case extendableProtoV1: + if isNilPtr(p) { + return nil, fmt.Errorf("proto: nil %T is not extendable", p) + } + return extensionAdapter{p}, nil + case extensionsBytes: + return slowExtensionAdapter{p}, nil + } + // Don't allocate a specific error containing %T: + // this is the hot path for Clone and MarshalText. + return nil, errNotExtendable +} + +var errNotExtendable = errors.New("proto: not an extendable proto.Message") + +func isNilPtr(x interface{}) bool { + v := reflect.ValueOf(x) + return v.Kind() == reflect.Ptr && v.IsNil() +} + +// XXX_InternalExtensions is an internal representation of proto extensions. +// +// Each generated message struct type embeds an anonymous XXX_InternalExtensions field, +// thus gaining the unexported 'extensions' method, which can be called only from the proto package. +// +// The methods of XXX_InternalExtensions are not concurrency safe in general, +// but calls to logically read-only methods such as has and get may be executed concurrently. +type XXX_InternalExtensions struct { + // The struct must be indirect so that if a user inadvertently copies a + // generated message and its embedded XXX_InternalExtensions, they + // avoid the mayhem of a copied mutex. + // + // The mutex serializes all logically read-only operations to p.extensionMap. + // It is up to the client to ensure that write operations to p.extensionMap are + // mutually exclusive with other accesses. + p *struct { + mu sync.Mutex + extensionMap map[int32]Extension + } +} + +// extensionsWrite returns the extension map, creating it on first use. +func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension { + if e.p == nil { + e.p = new(struct { + mu sync.Mutex + extensionMap map[int32]Extension + }) + e.p.extensionMap = make(map[int32]Extension) + } + return e.p.extensionMap +} + +// extensionsRead returns the extensions map for read-only use. It may be nil. +// The caller must hold the returned mutex's lock when accessing Elements within the map. +func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) { + if e.p == nil { + return nil, nil + } + return e.p.extensionMap, &e.p.mu +} + +// ExtensionDesc represents an extension specification. +// Used in generated code from the protocol compiler. +type ExtensionDesc struct { + ExtendedType Message // nil pointer to the type that is being extended + ExtensionType interface{} // nil pointer to the extension type + Field int32 // field number + Name string // fully-qualified name of extension, for text formatting + Tag string // protobuf tag style + Filename string // name of the file in which the extension is defined +} + +func (ed *ExtensionDesc) repeated() bool { + t := reflect.TypeOf(ed.ExtensionType) + return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 +} + +// Extension represents an extension in a message. +type Extension struct { + // When an extension is stored in a message using SetExtension + // only desc and value are set. When the message is marshaled + // enc will be set to the encoded form of the message. + // + // When a message is unmarshaled and contains extensions, each + // extension will have only enc set. When such an extension is + // accessed using GetExtension (or GetExtensions) desc and value + // will be set. + desc *ExtensionDesc + value interface{} + enc []byte +} + +// SetRawExtension is for testing only. +func SetRawExtension(base Message, id int32, b []byte) { + if ebase, ok := base.(extensionsBytes); ok { + clearExtension(base, id) + ext := ebase.GetExtensions() + *ext = append(*ext, b...) + return + } + epb, err := extendable(base) + if err != nil { + return + } + extmap := epb.extensionsWrite() + extmap[id] = Extension{enc: b} +} + +// isExtensionField returns true iff the given field number is in an extension range. +func isExtensionField(pb extendableProto, field int32) bool { + for _, er := range pb.ExtensionRangeArray() { + if er.Start <= field && field <= er.End { + return true + } + } + return false +} + +// checkExtensionTypes checks that the given extension is valid for pb. +func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { + var pbi interface{} = pb + // Check the extended type. + if ea, ok := pbi.(extensionAdapter); ok { + pbi = ea.extendableProtoV1 + } + if ea, ok := pbi.(slowExtensionAdapter); ok { + pbi = ea.extensionsBytes + } + if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b { + return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a) + } + // Check the range. + if !isExtensionField(pb, extension.Field) { + return errors.New("proto: bad extension number; not in declared ranges") + } + return nil +} + +// extPropKey is sufficient to uniquely identify an extension. +type extPropKey struct { + base reflect.Type + field int32 +} + +var extProp = struct { + sync.RWMutex + m map[extPropKey]*Properties +}{ + m: make(map[extPropKey]*Properties), +} + +func extensionProperties(ed *ExtensionDesc) *Properties { + key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field} + + extProp.RLock() + if prop, ok := extProp.m[key]; ok { + extProp.RUnlock() + return prop + } + extProp.RUnlock() + + extProp.Lock() + defer extProp.Unlock() + // Check again. + if prop, ok := extProp.m[key]; ok { + return prop + } + + prop := new(Properties) + prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil) + extProp.m[key] = prop + return prop +} + +// HasExtension returns whether the given extension is present in pb. +func HasExtension(pb Message, extension *ExtensionDesc) bool { + if epb, doki := pb.(extensionsBytes); doki { + ext := epb.GetExtensions() + buf := *ext + o := 0 + for o < len(buf) { + tag, n := DecodeVarint(buf[o:]) + fieldNum := int32(tag >> 3) + if int32(fieldNum) == extension.Field { + return true + } + wireType := int(tag & 0x7) + o += n + l, err := size(buf[o:], wireType) + if err != nil { + return false + } + o += l + } + return false + } + // TODO: Check types, field numbers, etc.? + epb, err := extendable(pb) + if err != nil { + return false + } + extmap, mu := epb.extensionsRead() + if extmap == nil { + return false + } + mu.Lock() + _, ok := extmap[extension.Field] + mu.Unlock() + return ok +} + +// ClearExtension removes the given extension from pb. +func ClearExtension(pb Message, extension *ExtensionDesc) { + clearExtension(pb, extension.Field) +} + +func clearExtension(pb Message, fieldNum int32) { + if epb, ok := pb.(extensionsBytes); ok { + offset := 0 + for offset != -1 { + offset = deleteExtension(epb, fieldNum, offset) + } + return + } + epb, err := extendable(pb) + if err != nil { + return + } + // TODO: Check types, field numbers, etc.? + extmap := epb.extensionsWrite() + delete(extmap, fieldNum) +} + +// GetExtension retrieves a proto2 extended field from pb. +// +// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil), +// then GetExtension parses the encoded field and returns a Go value of the specified type. +// If the field is not present, then the default value is returned (if one is specified), +// otherwise ErrMissingExtension is reported. +// +// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil), +// then GetExtension returns the raw encoded bytes of the field extension. +func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { + if epb, doki := pb.(extensionsBytes); doki { + ext := epb.GetExtensions() + return decodeExtensionFromBytes(extension, *ext) + } + + epb, err := extendable(pb) + if err != nil { + return nil, err + } + + if extension.ExtendedType != nil { + // can only check type if this is a complete descriptor + if cerr := checkExtensionTypes(epb, extension); cerr != nil { + return nil, cerr + } + } + + emap, mu := epb.extensionsRead() + if emap == nil { + return defaultExtensionValue(extension) + } + mu.Lock() + defer mu.Unlock() + e, ok := emap[extension.Field] + if !ok { + // defaultExtensionValue returns the default value or + // ErrMissingExtension if there is no default. + return defaultExtensionValue(extension) + } + + if e.value != nil { + // Already decoded. Check the descriptor, though. + if e.desc != extension { + // This shouldn't happen. If it does, it means that + // GetExtension was called twice with two different + // descriptors with the same field number. + return nil, errors.New("proto: descriptor conflict") + } + return e.value, nil + } + + if extension.ExtensionType == nil { + // incomplete descriptor + return e.enc, nil + } + + v, err := decodeExtension(e.enc, extension) + if err != nil { + return nil, err + } + + // Remember the decoded version and drop the encoded version. + // That way it is safe to mutate what we return. + e.value = v + e.desc = extension + e.enc = nil + emap[extension.Field] = e + return e.value, nil +} + +// defaultExtensionValue returns the default value for extension. +// If no default for an extension is defined ErrMissingExtension is returned. +func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) { + if extension.ExtensionType == nil { + // incomplete descriptor, so no default + return nil, ErrMissingExtension + } + + t := reflect.TypeOf(extension.ExtensionType) + props := extensionProperties(extension) + + sf, _, err := fieldDefault(t, props) + if err != nil { + return nil, err + } + + if sf == nil || sf.value == nil { + // There is no default value. + return nil, ErrMissingExtension + } + + if t.Kind() != reflect.Ptr { + // We do not need to return a Ptr, we can directly return sf.value. + return sf.value, nil + } + + // We need to return an interface{} that is a pointer to sf.value. + value := reflect.New(t).Elem() + value.Set(reflect.New(value.Type().Elem())) + if sf.kind == reflect.Int32 { + // We may have an int32 or an enum, but the underlying data is int32. + // Since we can't set an int32 into a non int32 reflect.value directly + // set it as a int32. + value.Elem().SetInt(int64(sf.value.(int32))) + } else { + value.Elem().Set(reflect.ValueOf(sf.value)) + } + return value.Interface(), nil +} + +// decodeExtension decodes an extension encoded in b. +func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { + t := reflect.TypeOf(extension.ExtensionType) + unmarshal := typeUnmarshaler(t, extension.Tag) + + // t is a pointer to a struct, pointer to basic type or a slice. + // Allocate space to store the pointer/slice. + value := reflect.New(t).Elem() + + var err error + for { + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + wire := int(x) & 7 + + b, err = unmarshal(b, valToPointer(value.Addr()), wire) + if err != nil { + return nil, err + } + + if len(b) == 0 { + break + } + } + return value.Interface(), nil +} + +// GetExtensions returns a slice of the extensions present in pb that are also listed in es. +// The returned slice has the same length as es; missing extensions will appear as nil elements. +func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { + epb, err := extendable(pb) + if err != nil { + return nil, err + } + extensions = make([]interface{}, len(es)) + for i, e := range es { + extensions[i], err = GetExtension(epb, e) + if err == ErrMissingExtension { + err = nil + } + if err != nil { + return + } + } + return +} + +// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order. +// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing +// just the Field field, which defines the extension's field number. +func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { + epb, err := extendable(pb) + if err != nil { + return nil, err + } + registeredExtensions := RegisteredExtensions(pb) + + emap, mu := epb.extensionsRead() + if emap == nil { + return nil, nil + } + mu.Lock() + defer mu.Unlock() + extensions := make([]*ExtensionDesc, 0, len(emap)) + for extid, e := range emap { + desc := e.desc + if desc == nil { + desc = registeredExtensions[extid] + if desc == nil { + desc = &ExtensionDesc{Field: extid} + } + } + + extensions = append(extensions, desc) + } + return extensions, nil +} + +// SetExtension sets the specified extension of pb to the specified value. +func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { + if epb, ok := pb.(extensionsBytes); ok { + newb, err := encodeExtension(extension, value) + if err != nil { + return err + } + bb := epb.GetExtensions() + *bb = append(*bb, newb...) + return nil + } + epb, err := extendable(pb) + if err != nil { + return err + } + if err := checkExtensionTypes(epb, extension); err != nil { + return err + } + typ := reflect.TypeOf(extension.ExtensionType) + if typ != reflect.TypeOf(value) { + return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType) + } + // nil extension values need to be caught early, because the + // encoder can't distinguish an ErrNil due to a nil extension + // from an ErrNil due to a missing field. Extensions are + // always optional, so the encoder would just swallow the error + // and drop all the extensions from the encoded message. + if reflect.ValueOf(value).IsNil() { + return fmt.Errorf("proto: SetExtension called with nil value of type %T", value) + } + + extmap := epb.extensionsWrite() + extmap[extension.Field] = Extension{desc: extension, value: value} + return nil +} + +// ClearAllExtensions clears all extensions from pb. +func ClearAllExtensions(pb Message) { + if epb, doki := pb.(extensionsBytes); doki { + ext := epb.GetExtensions() + *ext = []byte{} + return + } + epb, err := extendable(pb) + if err != nil { + return + } + m := epb.extensionsWrite() + for k := range m { + delete(m, k) + } +} + +// A global registry of extensions. +// The generated code will register the generated descriptors by calling RegisterExtension. + +var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc) + +// RegisterExtension is called from the generated code. +func RegisterExtension(desc *ExtensionDesc) { + st := reflect.TypeOf(desc.ExtendedType).Elem() + m := extensionMaps[st] + if m == nil { + m = make(map[int32]*ExtensionDesc) + extensionMaps[st] = m + } + if _, ok := m[desc.Field]; ok { + panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field))) + } + m[desc.Field] = desc +} + +// RegisteredExtensions returns a map of the registered extensions of a +// protocol buffer struct, indexed by the extension number. +// The argument pb should be a nil pointer to the struct type. +func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { + return extensionMaps[reflect.TypeOf(pb).Elem()] +} diff --git a/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go b/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go new file mode 100644 index 000000000..53ebd8cca --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go @@ -0,0 +1,368 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "bytes" + "errors" + "fmt" + "io" + "reflect" + "sort" + "strings" + "sync" +) + +type extensionsBytes interface { + Message + ExtensionRangeArray() []ExtensionRange + GetExtensions() *[]byte +} + +type slowExtensionAdapter struct { + extensionsBytes +} + +func (s slowExtensionAdapter) extensionsWrite() map[int32]Extension { + panic("Please report a bug to github.com/gogo/protobuf if you see this message: Writing extensions is not supported for extensions stored in a byte slice field.") +} + +func (s slowExtensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) { + b := s.GetExtensions() + m, err := BytesToExtensionsMap(*b) + if err != nil { + panic(err) + } + return m, notLocker{} +} + +func GetBoolExtension(pb Message, extension *ExtensionDesc, ifnotset bool) bool { + if reflect.ValueOf(pb).IsNil() { + return ifnotset + } + value, err := GetExtension(pb, extension) + if err != nil { + return ifnotset + } + if value == nil { + return ifnotset + } + if value.(*bool) == nil { + return ifnotset + } + return *(value.(*bool)) +} + +func (this *Extension) Equal(that *Extension) bool { + if err := this.Encode(); err != nil { + return false + } + if err := that.Encode(); err != nil { + return false + } + return bytes.Equal(this.enc, that.enc) +} + +func (this *Extension) Compare(that *Extension) int { + if err := this.Encode(); err != nil { + return 1 + } + if err := that.Encode(); err != nil { + return -1 + } + return bytes.Compare(this.enc, that.enc) +} + +func SizeOfInternalExtension(m extendableProto) (n int) { + info := getMarshalInfo(reflect.TypeOf(m)) + return info.sizeV1Extensions(m.extensionsWrite()) +} + +type sortableMapElem struct { + field int32 + ext Extension +} + +func newSortableExtensionsFromMap(m map[int32]Extension) sortableExtensions { + s := make(sortableExtensions, 0, len(m)) + for k, v := range m { + s = append(s, &sortableMapElem{field: k, ext: v}) + } + return s +} + +type sortableExtensions []*sortableMapElem + +func (this sortableExtensions) Len() int { return len(this) } + +func (this sortableExtensions) Swap(i, j int) { this[i], this[j] = this[j], this[i] } + +func (this sortableExtensions) Less(i, j int) bool { return this[i].field < this[j].field } + +func (this sortableExtensions) String() string { + sort.Sort(this) + ss := make([]string, len(this)) + for i := range this { + ss[i] = fmt.Sprintf("%d: %v", this[i].field, this[i].ext) + } + return "map[" + strings.Join(ss, ",") + "]" +} + +func StringFromInternalExtension(m extendableProto) string { + return StringFromExtensionsMap(m.extensionsWrite()) +} + +func StringFromExtensionsMap(m map[int32]Extension) string { + return newSortableExtensionsFromMap(m).String() +} + +func StringFromExtensionsBytes(ext []byte) string { + m, err := BytesToExtensionsMap(ext) + if err != nil { + panic(err) + } + return StringFromExtensionsMap(m) +} + +func EncodeInternalExtension(m extendableProto, data []byte) (n int, err error) { + return EncodeExtensionMap(m.extensionsWrite(), data) +} + +func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) { + o := 0 + for _, e := range m { + if err := e.Encode(); err != nil { + return 0, err + } + n := copy(data[o:], e.enc) + if n != len(e.enc) { + return 0, io.ErrShortBuffer + } + o += n + } + return o, nil +} + +func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) { + e := m[id] + if err := e.Encode(); err != nil { + return nil, err + } + return e.enc, nil +} + +func size(buf []byte, wire int) (int, error) { + switch wire { + case WireVarint: + _, n := DecodeVarint(buf) + return n, nil + case WireFixed64: + return 8, nil + case WireBytes: + v, n := DecodeVarint(buf) + return int(v) + n, nil + case WireFixed32: + return 4, nil + case WireStartGroup: + offset := 0 + for { + u, n := DecodeVarint(buf[offset:]) + fwire := int(u & 0x7) + offset += n + if fwire == WireEndGroup { + return offset, nil + } + s, err := size(buf[offset:], wire) + if err != nil { + return 0, err + } + offset += s + } + } + return 0, fmt.Errorf("proto: can't get size for unknown wire type %d", wire) +} + +func BytesToExtensionsMap(buf []byte) (map[int32]Extension, error) { + m := make(map[int32]Extension) + i := 0 + for i < len(buf) { + tag, n := DecodeVarint(buf[i:]) + if n <= 0 { + return nil, fmt.Errorf("unable to decode varint") + } + fieldNum := int32(tag >> 3) + wireType := int(tag & 0x7) + l, err := size(buf[i+n:], wireType) + if err != nil { + return nil, err + } + end := i + int(l) + n + m[int32(fieldNum)] = Extension{enc: buf[i:end]} + i = end + } + return m, nil +} + +func NewExtension(e []byte) Extension { + ee := Extension{enc: make([]byte, len(e))} + copy(ee.enc, e) + return ee +} + +func AppendExtension(e Message, tag int32, buf []byte) { + if ee, eok := e.(extensionsBytes); eok { + ext := ee.GetExtensions() + *ext = append(*ext, buf...) + return + } + if ee, eok := e.(extendableProto); eok { + m := ee.extensionsWrite() + ext := m[int32(tag)] // may be missing + ext.enc = append(ext.enc, buf...) + m[int32(tag)] = ext + } +} + +func encodeExtension(extension *ExtensionDesc, value interface{}) ([]byte, error) { + u := getMarshalInfo(reflect.TypeOf(extension.ExtendedType)) + ei := u.getExtElemInfo(extension) + v := value + p := toAddrPointer(&v, ei.isptr) + siz := ei.sizer(p, SizeVarint(ei.wiretag)) + buf := make([]byte, 0, siz) + return ei.marshaler(buf, p, ei.wiretag, false) +} + +func decodeExtensionFromBytes(extension *ExtensionDesc, buf []byte) (interface{}, error) { + o := 0 + for o < len(buf) { + tag, n := DecodeVarint((buf)[o:]) + fieldNum := int32(tag >> 3) + wireType := int(tag & 0x7) + if o+n > len(buf) { + return nil, fmt.Errorf("unable to decode extension") + } + l, err := size((buf)[o+n:], wireType) + if err != nil { + return nil, err + } + if int32(fieldNum) == extension.Field { + if o+n+l > len(buf) { + return nil, fmt.Errorf("unable to decode extension") + } + v, err := decodeExtension((buf)[o:o+n+l], extension) + if err != nil { + return nil, err + } + return v, nil + } + o += n + l + } + return defaultExtensionValue(extension) +} + +func (this *Extension) Encode() error { + if this.enc == nil { + var err error + this.enc, err = encodeExtension(this.desc, this.value) + if err != nil { + return err + } + } + return nil +} + +func (this Extension) GoString() string { + if err := this.Encode(); err != nil { + return fmt.Sprintf("error encoding extension: %v", err) + } + return fmt.Sprintf("proto.NewExtension(%#v)", this.enc) +} + +func SetUnsafeExtension(pb Message, fieldNum int32, value interface{}) error { + typ := reflect.TypeOf(pb).Elem() + ext, ok := extensionMaps[typ] + if !ok { + return fmt.Errorf("proto: bad extended type; %s is not extendable", typ.String()) + } + desc, ok := ext[fieldNum] + if !ok { + return errors.New("proto: bad extension number; not in declared ranges") + } + return SetExtension(pb, desc, value) +} + +func GetUnsafeExtension(pb Message, fieldNum int32) (interface{}, error) { + typ := reflect.TypeOf(pb).Elem() + ext, ok := extensionMaps[typ] + if !ok { + return nil, fmt.Errorf("proto: bad extended type; %s is not extendable", typ.String()) + } + desc, ok := ext[fieldNum] + if !ok { + return nil, fmt.Errorf("unregistered field number %d", fieldNum) + } + return GetExtension(pb, desc) +} + +func NewUnsafeXXX_InternalExtensions(m map[int32]Extension) XXX_InternalExtensions { + x := &XXX_InternalExtensions{ + p: new(struct { + mu sync.Mutex + extensionMap map[int32]Extension + }), + } + x.p.extensionMap = m + return *x +} + +func GetUnsafeExtensionsMap(extendable Message) map[int32]Extension { + pb := extendable.(extendableProto) + return pb.extensionsWrite() +} + +func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int { + ext := pb.GetExtensions() + for offset < len(*ext) { + tag, n1 := DecodeVarint((*ext)[offset:]) + fieldNum := int32(tag >> 3) + wireType := int(tag & 0x7) + n2, err := size((*ext)[offset+n1:], wireType) + if err != nil { + panic(err) + } + newOffset := offset + n1 + n2 + if fieldNum == theFieldNum { + *ext = append((*ext)[:offset], (*ext)[newOffset:]...) + return offset + } + offset = newOffset + } + return -1 +} diff --git a/vendor/github.com/gogo/protobuf/proto/lib.go b/vendor/github.com/gogo/protobuf/proto/lib.go new file mode 100644 index 000000000..d17f80209 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/lib.go @@ -0,0 +1,967 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +/* +Package proto converts data structures to and from the wire format of +protocol buffers. It works in concert with the Go source code generated +for .proto files by the protocol compiler. + +A summary of the properties of the protocol buffer interface +for a protocol buffer variable v: + + - Names are turned from camel_case to CamelCase for export. + - There are no methods on v to set fields; just treat + them as structure fields. + - There are getters that return a field's value if set, + and return the field's default value if unset. + The getters work even if the receiver is a nil message. + - The zero value for a struct is its correct initialization state. + All desired fields must be set before marshaling. + - A Reset() method will restore a protobuf struct to its zero state. + - Non-repeated fields are pointers to the values; nil means unset. + That is, optional or required field int32 f becomes F *int32. + - Repeated fields are slices. + - Helper functions are available to aid the setting of fields. + msg.Foo = proto.String("hello") // set field + - Constants are defined to hold the default values of all fields that + have them. They have the form Default_StructName_FieldName. + Because the getter methods handle defaulted values, + direct use of these constants should be rare. + - Enums are given type names and maps from names to values. + Enum values are prefixed by the enclosing message's name, or by the + enum's type name if it is a top-level enum. Enum types have a String + method, and a Enum method to assist in message construction. + - Nested messages, groups and enums have type names prefixed with the name of + the surrounding message type. + - Extensions are given descriptor names that start with E_, + followed by an underscore-delimited list of the nested messages + that contain it (if any) followed by the CamelCased name of the + extension field itself. HasExtension, ClearExtension, GetExtension + and SetExtension are functions for manipulating extensions. + - Oneof field sets are given a single field in their message, + with distinguished wrapper types for each possible field value. + - Marshal and Unmarshal are functions to encode and decode the wire format. + +When the .proto file specifies `syntax="proto3"`, there are some differences: + + - Non-repeated fields of non-message type are values instead of pointers. + - Enum types do not get an Enum method. + +The simplest way to describe this is to see an example. +Given file test.proto, containing + + package example; + + enum FOO { X = 17; } + + message Test { + required string label = 1; + optional int32 type = 2 [default=77]; + repeated int64 reps = 3; + optional group OptionalGroup = 4 { + required string RequiredField = 5; + } + oneof union { + int32 number = 6; + string name = 7; + } + } + +The resulting file, test.pb.go, is: + + package example + + import proto "github.com/gogo/protobuf/proto" + import math "math" + + type FOO int32 + const ( + FOO_X FOO = 17 + ) + var FOO_name = map[int32]string{ + 17: "X", + } + var FOO_value = map[string]int32{ + "X": 17, + } + + func (x FOO) Enum() *FOO { + p := new(FOO) + *p = x + return p + } + func (x FOO) String() string { + return proto.EnumName(FOO_name, int32(x)) + } + func (x *FOO) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FOO_value, data) + if err != nil { + return err + } + *x = FOO(value) + return nil + } + + type Test struct { + Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"` + Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"` + Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"` + Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` + // Types that are valid to be assigned to Union: + // *Test_Number + // *Test_Name + Union isTest_Union `protobuf_oneof:"union"` + XXX_unrecognized []byte `json:"-"` + } + func (m *Test) Reset() { *m = Test{} } + func (m *Test) String() string { return proto.CompactTextString(m) } + func (*Test) ProtoMessage() {} + + type isTest_Union interface { + isTest_Union() + } + + type Test_Number struct { + Number int32 `protobuf:"varint,6,opt,name=number"` + } + type Test_Name struct { + Name string `protobuf:"bytes,7,opt,name=name"` + } + + func (*Test_Number) isTest_Union() {} + func (*Test_Name) isTest_Union() {} + + func (m *Test) GetUnion() isTest_Union { + if m != nil { + return m.Union + } + return nil + } + const Default_Test_Type int32 = 77 + + func (m *Test) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" + } + + func (m *Test) GetType() int32 { + if m != nil && m.Type != nil { + return *m.Type + } + return Default_Test_Type + } + + func (m *Test) GetOptionalgroup() *Test_OptionalGroup { + if m != nil { + return m.Optionalgroup + } + return nil + } + + type Test_OptionalGroup struct { + RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"` + } + func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} } + func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) } + + func (m *Test_OptionalGroup) GetRequiredField() string { + if m != nil && m.RequiredField != nil { + return *m.RequiredField + } + return "" + } + + func (m *Test) GetNumber() int32 { + if x, ok := m.GetUnion().(*Test_Number); ok { + return x.Number + } + return 0 + } + + func (m *Test) GetName() string { + if x, ok := m.GetUnion().(*Test_Name); ok { + return x.Name + } + return "" + } + + func init() { + proto.RegisterEnum("example.FOO", FOO_name, FOO_value) + } + +To create and play with a Test object: + + package main + + import ( + "log" + + "github.com/gogo/protobuf/proto" + pb "./example.pb" + ) + + func main() { + test := &pb.Test{ + Label: proto.String("hello"), + Type: proto.Int32(17), + Reps: []int64{1, 2, 3}, + Optionalgroup: &pb.Test_OptionalGroup{ + RequiredField: proto.String("good bye"), + }, + Union: &pb.Test_Name{"fred"}, + } + data, err := proto.Marshal(test) + if err != nil { + log.Fatal("marshaling error: ", err) + } + newTest := &pb.Test{} + err = proto.Unmarshal(data, newTest) + if err != nil { + log.Fatal("unmarshaling error: ", err) + } + // Now test and newTest contain the same data. + if test.GetLabel() != newTest.GetLabel() { + log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) + } + // Use a type switch to determine which oneof was set. + switch u := test.Union.(type) { + case *pb.Test_Number: // u.Number contains the number. + case *pb.Test_Name: // u.Name contains the string. + } + // etc. + } +*/ +package proto + +import ( + "encoding/json" + "fmt" + "log" + "reflect" + "sort" + "strconv" + "sync" +) + +// RequiredNotSetError is an error type returned by either Marshal or Unmarshal. +// Marshal reports this when a required field is not initialized. +// Unmarshal reports this when a required field is missing from the wire data. +type RequiredNotSetError struct{ field string } + +func (e *RequiredNotSetError) Error() string { + if e.field == "" { + return fmt.Sprintf("proto: required field not set") + } + return fmt.Sprintf("proto: required field %q not set", e.field) +} +func (e *RequiredNotSetError) RequiredNotSet() bool { + return true +} + +type invalidUTF8Error struct{ field string } + +func (e *invalidUTF8Error) Error() string { + if e.field == "" { + return "proto: invalid UTF-8 detected" + } + return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field) +} +func (e *invalidUTF8Error) InvalidUTF8() bool { + return true +} + +// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8. +// This error should not be exposed to the external API as such errors should +// be recreated with the field information. +var errInvalidUTF8 = &invalidUTF8Error{} + +// isNonFatal reports whether the error is either a RequiredNotSet error +// or a InvalidUTF8 error. +func isNonFatal(err error) bool { + if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() { + return true + } + if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() { + return true + } + return false +} + +type nonFatal struct{ E error } + +// Merge merges err into nf and reports whether it was successful. +// Otherwise it returns false for any fatal non-nil errors. +func (nf *nonFatal) Merge(err error) (ok bool) { + if err == nil { + return true // not an error + } + if !isNonFatal(err) { + return false // fatal error + } + if nf.E == nil { + nf.E = err // store first instance of non-fatal error + } + return true +} + +// Message is implemented by generated protocol buffer messages. +type Message interface { + Reset() + String() string + ProtoMessage() +} + +// A Buffer is a buffer manager for marshaling and unmarshaling +// protocol buffers. It may be reused between invocations to +// reduce memory usage. It is not necessary to use a Buffer; +// the global functions Marshal and Unmarshal create a +// temporary Buffer and are fine for most applications. +type Buffer struct { + buf []byte // encode/decode byte stream + index int // read point + + deterministic bool +} + +// NewBuffer allocates a new Buffer and initializes its internal data to +// the contents of the argument slice. +func NewBuffer(e []byte) *Buffer { + return &Buffer{buf: e} +} + +// Reset resets the Buffer, ready for marshaling a new protocol buffer. +func (p *Buffer) Reset() { + p.buf = p.buf[0:0] // for reading/writing + p.index = 0 // for reading +} + +// SetBuf replaces the internal buffer with the slice, +// ready for unmarshaling the contents of the slice. +func (p *Buffer) SetBuf(s []byte) { + p.buf = s + p.index = 0 +} + +// Bytes returns the contents of the Buffer. +func (p *Buffer) Bytes() []byte { return p.buf } + +// SetDeterministic sets whether to use deterministic serialization. +// +// Deterministic serialization guarantees that for a given binary, equal +// messages will always be serialized to the same bytes. This implies: +// +// - Repeated serialization of a message will return the same bytes. +// - Different processes of the same binary (which may be executing on +// different machines) will serialize equal messages to the same bytes. +// +// Note that the deterministic serialization is NOT canonical across +// languages. It is not guaranteed to remain stable over time. It is unstable +// across different builds with schema changes due to unknown fields. +// Users who need canonical serialization (e.g., persistent storage in a +// canonical form, fingerprinting, etc.) should define their own +// canonicalization specification and implement their own serializer rather +// than relying on this API. +// +// If deterministic serialization is requested, map entries will be sorted +// by keys in lexographical order. This is an implementation detail and +// subject to change. +func (p *Buffer) SetDeterministic(deterministic bool) { + p.deterministic = deterministic +} + +/* + * Helper routines for simplifying the creation of optional fields of basic type. + */ + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { + return &v +} + +// Int32 is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it. +func Int32(v int32) *int32 { + return &v +} + +// Int is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it, but unlike Int32 +// its argument value is an int. +func Int(v int) *int32 { + p := new(int32) + *p = int32(v) + return p +} + +// Int64 is a helper routine that allocates a new int64 value +// to store v and returns a pointer to it. +func Int64(v int64) *int64 { + return &v +} + +// Float32 is a helper routine that allocates a new float32 value +// to store v and returns a pointer to it. +func Float32(v float32) *float32 { + return &v +} + +// Float64 is a helper routine that allocates a new float64 value +// to store v and returns a pointer to it. +func Float64(v float64) *float64 { + return &v +} + +// Uint32 is a helper routine that allocates a new uint32 value +// to store v and returns a pointer to it. +func Uint32(v uint32) *uint32 { + return &v +} + +// Uint64 is a helper routine that allocates a new uint64 value +// to store v and returns a pointer to it. +func Uint64(v uint64) *uint64 { + return &v +} + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +func String(v string) *string { + return &v +} + +// EnumName is a helper function to simplify printing protocol buffer enums +// by name. Given an enum map and a value, it returns a useful string. +func EnumName(m map[int32]string, v int32) string { + s, ok := m[v] + if ok { + return s + } + return strconv.Itoa(int(v)) +} + +// UnmarshalJSONEnum is a helper function to simplify recovering enum int values +// from their JSON-encoded representation. Given a map from the enum's symbolic +// names to its int values, and a byte buffer containing the JSON-encoded +// value, it returns an int32 that can be cast to the enum type by the caller. +// +// The function can deal with both JSON representations, numeric and symbolic. +func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) { + if data[0] == '"' { + // New style: enums are strings. + var repr string + if err := json.Unmarshal(data, &repr); err != nil { + return -1, err + } + val, ok := m[repr] + if !ok { + return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr) + } + return val, nil + } + // Old style: enums are ints. + var val int32 + if err := json.Unmarshal(data, &val); err != nil { + return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName) + } + return val, nil +} + +// DebugPrint dumps the encoded data in b in a debugging format with a header +// including the string s. Used in testing but made available for general debugging. +func (p *Buffer) DebugPrint(s string, b []byte) { + var u uint64 + + obuf := p.buf + sindex := p.index + p.buf = b + p.index = 0 + depth := 0 + + fmt.Printf("\n--- %s ---\n", s) + +out: + for { + for i := 0; i < depth; i++ { + fmt.Print(" ") + } + + index := p.index + if index == len(p.buf) { + break + } + + op, err := p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: fetching op err %v\n", index, err) + break out + } + tag := op >> 3 + wire := op & 7 + + switch wire { + default: + fmt.Printf("%3d: t=%3d unknown wire=%d\n", + index, tag, wire) + break out + + case WireBytes: + var r []byte + + r, err = p.DecodeRawBytes(false) + if err != nil { + break out + } + fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r)) + if len(r) <= 6 { + for i := 0; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } else { + for i := 0; i < 3; i++ { + fmt.Printf(" %.2x", r[i]) + } + fmt.Printf(" ..") + for i := len(r) - 3; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } + fmt.Printf("\n") + + case WireFixed32: + u, err = p.DecodeFixed32() + if err != nil { + fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u) + + case WireFixed64: + u, err = p.DecodeFixed64() + if err != nil { + fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u) + + case WireVarint: + u, err = p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u) + + case WireStartGroup: + fmt.Printf("%3d: t=%3d start\n", index, tag) + depth++ + + case WireEndGroup: + depth-- + fmt.Printf("%3d: t=%3d end\n", index, tag) + } + } + + if depth != 0 { + fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth) + } + fmt.Printf("\n") + + p.buf = obuf + p.index = sindex +} + +// SetDefaults sets unset protocol buffer fields to their default values. +// It only modifies fields that are both unset and have defined defaults. +// It recursively sets default values in any non-nil sub-messages. +func SetDefaults(pb Message) { + setDefaults(reflect.ValueOf(pb), true, false) +} + +// v is a struct. +func setDefaults(v reflect.Value, recur, zeros bool) { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + + defaultMu.RLock() + dm, ok := defaults[v.Type()] + defaultMu.RUnlock() + if !ok { + dm = buildDefaultMessage(v.Type()) + defaultMu.Lock() + defaults[v.Type()] = dm + defaultMu.Unlock() + } + + for _, sf := range dm.scalars { + f := v.Field(sf.index) + if !f.IsNil() { + // field already set + continue + } + dv := sf.value + if dv == nil && !zeros { + // no explicit default, and don't want to set zeros + continue + } + fptr := f.Addr().Interface() // **T + // TODO: Consider batching the allocations we do here. + switch sf.kind { + case reflect.Bool: + b := new(bool) + if dv != nil { + *b = dv.(bool) + } + *(fptr.(**bool)) = b + case reflect.Float32: + f := new(float32) + if dv != nil { + *f = dv.(float32) + } + *(fptr.(**float32)) = f + case reflect.Float64: + f := new(float64) + if dv != nil { + *f = dv.(float64) + } + *(fptr.(**float64)) = f + case reflect.Int32: + // might be an enum + if ft := f.Type(); ft != int32PtrType { + // enum + f.Set(reflect.New(ft.Elem())) + if dv != nil { + f.Elem().SetInt(int64(dv.(int32))) + } + } else { + // int32 field + i := new(int32) + if dv != nil { + *i = dv.(int32) + } + *(fptr.(**int32)) = i + } + case reflect.Int64: + i := new(int64) + if dv != nil { + *i = dv.(int64) + } + *(fptr.(**int64)) = i + case reflect.String: + s := new(string) + if dv != nil { + *s = dv.(string) + } + *(fptr.(**string)) = s + case reflect.Uint8: + // exceptional case: []byte + var b []byte + if dv != nil { + db := dv.([]byte) + b = make([]byte, len(db)) + copy(b, db) + } else { + b = []byte{} + } + *(fptr.(*[]byte)) = b + case reflect.Uint32: + u := new(uint32) + if dv != nil { + *u = dv.(uint32) + } + *(fptr.(**uint32)) = u + case reflect.Uint64: + u := new(uint64) + if dv != nil { + *u = dv.(uint64) + } + *(fptr.(**uint64)) = u + default: + log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind) + } + } + + for _, ni := range dm.nested { + f := v.Field(ni) + // f is *T or T or []*T or []T + switch f.Kind() { + case reflect.Struct: + setDefaults(f, recur, zeros) + + case reflect.Ptr: + if f.IsNil() { + continue + } + setDefaults(f, recur, zeros) + + case reflect.Slice: + for i := 0; i < f.Len(); i++ { + e := f.Index(i) + if e.Kind() == reflect.Ptr && e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + + case reflect.Map: + for _, k := range f.MapKeys() { + e := f.MapIndex(k) + if e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + } + } +} + +var ( + // defaults maps a protocol buffer struct type to a slice of the fields, + // with its scalar fields set to their proto-declared non-zero default values. + defaultMu sync.RWMutex + defaults = make(map[reflect.Type]defaultMessage) + + int32PtrType = reflect.TypeOf((*int32)(nil)) +) + +// defaultMessage represents information about the default values of a message. +type defaultMessage struct { + scalars []scalarField + nested []int // struct field index of nested messages +} + +type scalarField struct { + index int // struct field index + kind reflect.Kind // element type (the T in *T or []T) + value interface{} // the proto-declared default value, or nil +} + +// t is a struct type. +func buildDefaultMessage(t reflect.Type) (dm defaultMessage) { + sprop := GetProperties(t) + for _, prop := range sprop.Prop { + fi, ok := sprop.decoderTags.get(prop.Tag) + if !ok { + // XXX_unrecognized + continue + } + ft := t.Field(fi).Type + + sf, nested, err := fieldDefault(ft, prop) + switch { + case err != nil: + log.Print(err) + case nested: + dm.nested = append(dm.nested, fi) + case sf != nil: + sf.index = fi + dm.scalars = append(dm.scalars, *sf) + } + } + + return dm +} + +// fieldDefault returns the scalarField for field type ft. +// sf will be nil if the field can not have a default. +// nestedMessage will be true if this is a nested message. +// Note that sf.index is not set on return. +func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) { + var canHaveDefault bool + switch ft.Kind() { + case reflect.Struct: + nestedMessage = true // non-nullable + + case reflect.Ptr: + if ft.Elem().Kind() == reflect.Struct { + nestedMessage = true + } else { + canHaveDefault = true // proto2 scalar field + } + + case reflect.Slice: + switch ft.Elem().Kind() { + case reflect.Ptr, reflect.Struct: + nestedMessage = true // repeated message + case reflect.Uint8: + canHaveDefault = true // bytes field + } + + case reflect.Map: + if ft.Elem().Kind() == reflect.Ptr { + nestedMessage = true // map with message values + } + } + + if !canHaveDefault { + if nestedMessage { + return nil, true, nil + } + return nil, false, nil + } + + // We now know that ft is a pointer or slice. + sf = &scalarField{kind: ft.Elem().Kind()} + + // scalar fields without defaults + if !prop.HasDefault { + return sf, false, nil + } + + // a scalar field: either *T or []byte + switch ft.Elem().Kind() { + case reflect.Bool: + x, err := strconv.ParseBool(prop.Default) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Float32: + x, err := strconv.ParseFloat(prop.Default, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err) + } + sf.value = float32(x) + case reflect.Float64: + x, err := strconv.ParseFloat(prop.Default, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Int32: + x, err := strconv.ParseInt(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err) + } + sf.value = int32(x) + case reflect.Int64: + x, err := strconv.ParseInt(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.String: + sf.value = prop.Default + case reflect.Uint8: + // []byte (not *uint8) + sf.value = []byte(prop.Default) + case reflect.Uint32: + x, err := strconv.ParseUint(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err) + } + sf.value = uint32(x) + case reflect.Uint64: + x, err := strconv.ParseUint(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err) + } + sf.value = x + default: + return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind()) + } + + return sf, false, nil +} + +// mapKeys returns a sort.Interface to be used for sorting the map keys. +// Map fields may have key types of non-float scalars, strings and enums. +func mapKeys(vs []reflect.Value) sort.Interface { + s := mapKeySorter{vs: vs} + + // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps. + if len(vs) == 0 { + return s + } + switch vs[0].Kind() { + case reflect.Int32, reflect.Int64: + s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() } + case reflect.Uint32, reflect.Uint64: + s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() } + case reflect.Bool: + s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true + case reflect.String: + s.less = func(a, b reflect.Value) bool { return a.String() < b.String() } + default: + panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind())) + } + + return s +} + +type mapKeySorter struct { + vs []reflect.Value + less func(a, b reflect.Value) bool +} + +func (s mapKeySorter) Len() int { return len(s.vs) } +func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] } +func (s mapKeySorter) Less(i, j int) bool { + return s.less(s.vs[i], s.vs[j]) +} + +// isProto3Zero reports whether v is a zero proto3 value. +func isProto3Zero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return !v.Bool() + case reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint32, reflect.Uint64: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.String: + return v.String() == "" + } + return false +} + +// ProtoPackageIsVersion2 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the proto package. +const GoGoProtoPackageIsVersion2 = true + +// ProtoPackageIsVersion1 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the proto package. +const GoGoProtoPackageIsVersion1 = true + +// InternalMessageInfo is a type used internally by generated .pb.go files. +// This type is not intended to be used by non-generated code. +// This type is not subject to any compatibility guarantee. +type InternalMessageInfo struct { + marshal *marshalInfo + unmarshal *unmarshalInfo + merge *mergeInfo + discard *discardInfo +} diff --git a/vendor/github.com/gogo/protobuf/proto/lib_gogo.go b/vendor/github.com/gogo/protobuf/proto/lib_gogo.go new file mode 100644 index 000000000..b3aa39190 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/lib_gogo.go @@ -0,0 +1,50 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "encoding/json" + "strconv" +) + +type Sizer interface { + Size() int +} + +type ProtoSizer interface { + ProtoSize() int +} + +func MarshalJSONEnum(m map[int32]string, value int32) ([]byte, error) { + s, ok := m[value] + if !ok { + s = strconv.Itoa(int(value)) + } + return json.Marshal(s) +} diff --git a/vendor/github.com/gogo/protobuf/proto/message_set.go b/vendor/github.com/gogo/protobuf/proto/message_set.go new file mode 100644 index 000000000..f48a75676 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/message_set.go @@ -0,0 +1,181 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +/* + * Support for message sets. + */ + +import ( + "errors" +) + +// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. +// A message type ID is required for storing a protocol buffer in a message set. +var errNoMessageTypeID = errors.New("proto does not have a message type ID") + +// The first two types (_MessageSet_Item and messageSet) +// model what the protocol compiler produces for the following protocol message: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } +// That is the MessageSet wire format. We can't use a proto to generate these +// because that would introduce a circular dependency between it and this package. + +type _MessageSet_Item struct { + TypeId *int32 `protobuf:"varint,2,req,name=type_id"` + Message []byte `protobuf:"bytes,3,req,name=message"` +} + +type messageSet struct { + Item []*_MessageSet_Item `protobuf:"group,1,rep"` + XXX_unrecognized []byte + // TODO: caching? +} + +// Make sure messageSet is a Message. +var _ Message = (*messageSet)(nil) + +// messageTypeIder is an interface satisfied by a protocol buffer type +// that may be stored in a MessageSet. +type messageTypeIder interface { + MessageTypeId() int32 +} + +func (ms *messageSet) find(pb Message) *_MessageSet_Item { + mti, ok := pb.(messageTypeIder) + if !ok { + return nil + } + id := mti.MessageTypeId() + for _, item := range ms.Item { + if *item.TypeId == id { + return item + } + } + return nil +} + +func (ms *messageSet) Has(pb Message) bool { + return ms.find(pb) != nil +} + +func (ms *messageSet) Unmarshal(pb Message) error { + if item := ms.find(pb); item != nil { + return Unmarshal(item.Message, pb) + } + if _, ok := pb.(messageTypeIder); !ok { + return errNoMessageTypeID + } + return nil // TODO: return error instead? +} + +func (ms *messageSet) Marshal(pb Message) error { + msg, err := Marshal(pb) + if err != nil { + return err + } + if item := ms.find(pb); item != nil { + // reuse existing item + item.Message = msg + return nil + } + + mti, ok := pb.(messageTypeIder) + if !ok { + return errNoMessageTypeID + } + + mtid := mti.MessageTypeId() + ms.Item = append(ms.Item, &_MessageSet_Item{ + TypeId: &mtid, + Message: msg, + }) + return nil +} + +func (ms *messageSet) Reset() { *ms = messageSet{} } +func (ms *messageSet) String() string { return CompactTextString(ms) } +func (*messageSet) ProtoMessage() {} + +// Support for the message_set_wire_format message option. + +func skipVarint(buf []byte) []byte { + i := 0 + for ; buf[i]&0x80 != 0; i++ { + } + return buf[i+1:] +} + +// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. +// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option. +func unmarshalMessageSet(buf []byte, exts interface{}) error { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + m = exts.extensionsWrite() + case map[int32]Extension: + m = exts + default: + return errors.New("proto: not an extension map") + } + + ms := new(messageSet) + if err := Unmarshal(buf, ms); err != nil { + return err + } + for _, item := range ms.Item { + id := *item.TypeId + msg := item.Message + + // Restore wire type and field number varint, plus length varint. + // Be careful to preserve duplicate items. + b := EncodeVarint(uint64(id)<<3 | WireBytes) + if ext, ok := m[id]; ok { + // Existing data; rip off the tag and length varint + // so we join the new data correctly. + // We can assume that ext.enc is set because we are unmarshaling. + o := ext.enc[len(b):] // skip wire type and field number + _, n := DecodeVarint(o) // calculate length of length varint + o = o[n:] // skip length varint + msg = append(o, msg...) // join old data and new data + } + b = append(b, EncodeVarint(uint64(len(msg)))...) + b = append(b, msg...) + + m[id] = Extension{enc: b} + } + return nil +} diff --git a/vendor/github.com/gogo/protobuf/proto/pointer_reflect.go b/vendor/github.com/gogo/protobuf/proto/pointer_reflect.go new file mode 100644 index 000000000..b6cad9083 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/pointer_reflect.go @@ -0,0 +1,357 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +// +build purego appengine js + +// This file contains an implementation of proto field accesses using package reflect. +// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can +// be used on App Engine. + +package proto + +import ( + "reflect" + "sync" +) + +const unsafeAllowed = false + +// A field identifies a field in a struct, accessible from a pointer. +// In this implementation, a field is identified by the sequence of field indices +// passed to reflect's FieldByIndex. +type field []int + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return f.Index +} + +// invalidField is an invalid field identifier. +var invalidField = field(nil) + +// zeroField is a noop when calling pointer.offset. +var zeroField = field([]int{}) + +// IsValid reports whether the field identifier is valid. +func (f field) IsValid() bool { return f != nil } + +// The pointer type is for the table-driven decoder. +// The implementation here uses a reflect.Value of pointer type to +// create a generic pointer. In pointer_unsafe.go we use unsafe +// instead of reflect to implement the same (but faster) interface. +type pointer struct { + v reflect.Value +} + +// toPointer converts an interface of pointer type to a pointer +// that points to the same target. +func toPointer(i *Message) pointer { + return pointer{v: reflect.ValueOf(*i)} +} + +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr bool) pointer { + v := reflect.ValueOf(*i) + u := reflect.New(v.Type()) + u.Elem().Set(v) + return pointer{v: u} +} + +// valToPointer converts v to a pointer. v must be of pointer type. +func valToPointer(v reflect.Value) pointer { + return pointer{v: v} +} + +// offset converts from a pointer to a structure to a pointer to +// one of its fields. +func (p pointer) offset(f field) pointer { + return pointer{v: p.v.Elem().FieldByIndex(f).Addr()} +} + +func (p pointer) isNil() bool { + return p.v.IsNil() +} + +// grow updates the slice s in place to make it one element longer. +// s must be addressable. +// Returns the (addressable) new element. +func grow(s reflect.Value) reflect.Value { + n, m := s.Len(), s.Cap() + if n < m { + s.SetLen(n + 1) + } else { + s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem()))) + } + return s.Index(n) +} + +func (p pointer) toInt64() *int64 { + return p.v.Interface().(*int64) +} +func (p pointer) toInt64Ptr() **int64 { + return p.v.Interface().(**int64) +} +func (p pointer) toInt64Slice() *[]int64 { + return p.v.Interface().(*[]int64) +} + +var int32ptr = reflect.TypeOf((*int32)(nil)) + +func (p pointer) toInt32() *int32 { + return p.v.Convert(int32ptr).Interface().(*int32) +} + +// The toInt32Ptr/Slice methods don't work because of enums. +// Instead, we must use set/get methods for the int32ptr/slice case. +/* + func (p pointer) toInt32Ptr() **int32 { + return p.v.Interface().(**int32) +} + func (p pointer) toInt32Slice() *[]int32 { + return p.v.Interface().(*[]int32) +} +*/ +func (p pointer) getInt32Ptr() *int32 { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + return p.v.Elem().Interface().(*int32) + } + // an enum + return p.v.Elem().Convert(int32PtrType).Interface().(*int32) +} +func (p pointer) setInt32Ptr(v int32) { + // Allocate value in a *int32. Possibly convert that to a *enum. + // Then assign it to a **int32 or **enum. + // Note: we can convert *int32 to *enum, but we can't convert + // **int32 to **enum! + p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem())) +} + +// getInt32Slice copies []int32 from p as a new slice. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) getInt32Slice() []int32 { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + return p.v.Elem().Interface().([]int32) + } + // an enum + // Allocate a []int32, then assign []enum's values into it. + // Note: we can't convert []enum to []int32. + slice := p.v.Elem() + s := make([]int32, slice.Len()) + for i := 0; i < slice.Len(); i++ { + s[i] = int32(slice.Index(i).Int()) + } + return s +} + +// setInt32Slice copies []int32 into p as a new slice. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) setInt32Slice(v []int32) { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + p.v.Elem().Set(reflect.ValueOf(v)) + return + } + // an enum + // Allocate a []enum, then assign []int32's values into it. + // Note: we can't convert []enum to []int32. + slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v)) + for i, x := range v { + slice.Index(i).SetInt(int64(x)) + } + p.v.Elem().Set(slice) +} +func (p pointer) appendInt32Slice(v int32) { + grow(p.v.Elem()).SetInt(int64(v)) +} + +func (p pointer) toUint64() *uint64 { + return p.v.Interface().(*uint64) +} +func (p pointer) toUint64Ptr() **uint64 { + return p.v.Interface().(**uint64) +} +func (p pointer) toUint64Slice() *[]uint64 { + return p.v.Interface().(*[]uint64) +} +func (p pointer) toUint32() *uint32 { + return p.v.Interface().(*uint32) +} +func (p pointer) toUint32Ptr() **uint32 { + return p.v.Interface().(**uint32) +} +func (p pointer) toUint32Slice() *[]uint32 { + return p.v.Interface().(*[]uint32) +} +func (p pointer) toBool() *bool { + return p.v.Interface().(*bool) +} +func (p pointer) toBoolPtr() **bool { + return p.v.Interface().(**bool) +} +func (p pointer) toBoolSlice() *[]bool { + return p.v.Interface().(*[]bool) +} +func (p pointer) toFloat64() *float64 { + return p.v.Interface().(*float64) +} +func (p pointer) toFloat64Ptr() **float64 { + return p.v.Interface().(**float64) +} +func (p pointer) toFloat64Slice() *[]float64 { + return p.v.Interface().(*[]float64) +} +func (p pointer) toFloat32() *float32 { + return p.v.Interface().(*float32) +} +func (p pointer) toFloat32Ptr() **float32 { + return p.v.Interface().(**float32) +} +func (p pointer) toFloat32Slice() *[]float32 { + return p.v.Interface().(*[]float32) +} +func (p pointer) toString() *string { + return p.v.Interface().(*string) +} +func (p pointer) toStringPtr() **string { + return p.v.Interface().(**string) +} +func (p pointer) toStringSlice() *[]string { + return p.v.Interface().(*[]string) +} +func (p pointer) toBytes() *[]byte { + return p.v.Interface().(*[]byte) +} +func (p pointer) toBytesSlice() *[][]byte { + return p.v.Interface().(*[][]byte) +} +func (p pointer) toExtensions() *XXX_InternalExtensions { + return p.v.Interface().(*XXX_InternalExtensions) +} +func (p pointer) toOldExtensions() *map[int32]Extension { + return p.v.Interface().(*map[int32]Extension) +} +func (p pointer) getPointer() pointer { + return pointer{v: p.v.Elem()} +} +func (p pointer) setPointer(q pointer) { + p.v.Elem().Set(q.v) +} +func (p pointer) appendPointer(q pointer) { + grow(p.v.Elem()).Set(q.v) +} + +// getPointerSlice copies []*T from p as a new []pointer. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) getPointerSlice() []pointer { + if p.v.IsNil() { + return nil + } + n := p.v.Elem().Len() + s := make([]pointer, n) + for i := 0; i < n; i++ { + s[i] = pointer{v: p.v.Elem().Index(i)} + } + return s +} + +// setPointerSlice copies []pointer into p as a new []*T. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) setPointerSlice(v []pointer) { + if v == nil { + p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem()) + return + } + s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v)) + for _, p := range v { + s = reflect.Append(s, p.v) + } + p.v.Elem().Set(s) +} + +// getInterfacePointer returns a pointer that points to the +// interface data of the interface pointed by p. +func (p pointer) getInterfacePointer() pointer { + if p.v.Elem().IsNil() { + return pointer{v: p.v.Elem()} + } + return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct +} + +func (p pointer) asPointerTo(t reflect.Type) reflect.Value { + // TODO: check that p.v.Type().Elem() == t? + return p.v +} + +func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} + +var atomicLock sync.Mutex diff --git a/vendor/github.com/gogo/protobuf/proto/pointer_reflect_gogo.go b/vendor/github.com/gogo/protobuf/proto/pointer_reflect_gogo.go new file mode 100644 index 000000000..7ffd3c29d --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/pointer_reflect_gogo.go @@ -0,0 +1,59 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2018, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build purego appengine js + +// This file contains an implementation of proto field accesses using package reflect. +// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can +// be used on App Engine. + +package proto + +import ( + "reflect" +) + +// TODO: untested, so probably incorrect. + +func (p pointer) getRef() pointer { + return pointer{v: p.v.Addr()} +} + +func (p pointer) appendRef(v pointer, typ reflect.Type) { + slice := p.getSlice(typ) + elem := v.asPointerTo(typ).Elem() + newSlice := reflect.Append(slice, elem) + slice.Set(newSlice) +} + +func (p pointer) getSlice(typ reflect.Type) reflect.Value { + sliceTyp := reflect.SliceOf(typ) + slice := p.asPointerTo(sliceTyp) + slice = slice.Elem() + return slice +} diff --git a/vendor/github.com/gogo/protobuf/proto/pointer_unsafe.go b/vendor/github.com/gogo/protobuf/proto/pointer_unsafe.go new file mode 100644 index 000000000..d55a335d9 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/pointer_unsafe.go @@ -0,0 +1,308 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +// +build !purego,!appengine,!js + +// This file contains the implementation of the proto field accesses using package unsafe. + +package proto + +import ( + "reflect" + "sync/atomic" + "unsafe" +) + +const unsafeAllowed = true + +// A field identifies a field in a struct, accessible from a pointer. +// In this implementation, a field is identified by its byte offset from the start of the struct. +type field uintptr + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return field(f.Offset) +} + +// invalidField is an invalid field identifier. +const invalidField = ^field(0) + +// zeroField is a noop when calling pointer.offset. +const zeroField = field(0) + +// IsValid reports whether the field identifier is valid. +func (f field) IsValid() bool { + return f != invalidField +} + +// The pointer type below is for the new table-driven encoder/decoder. +// The implementation here uses unsafe.Pointer to create a generic pointer. +// In pointer_reflect.go we use reflect instead of unsafe to implement +// the same (but slower) interface. +type pointer struct { + p unsafe.Pointer +} + +// size of pointer +var ptrSize = unsafe.Sizeof(uintptr(0)) + +// toPointer converts an interface of pointer type to a pointer +// that points to the same target. +func toPointer(i *Message) pointer { + // Super-tricky - read pointer out of data word of interface value. + // Saves ~25ns over the equivalent: + // return valToPointer(reflect.ValueOf(*i)) + return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} +} + +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr bool) pointer { + // Super-tricky - read or get the address of data word of interface value. + if isptr { + // The interface is of pointer type, thus it is a direct interface. + // The data word is the pointer data itself. We take its address. + return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)} + } + // The interface is not of pointer type. The data word is the pointer + // to the data. + return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} +} + +// valToPointer converts v to a pointer. v must be of pointer type. +func valToPointer(v reflect.Value) pointer { + return pointer{p: unsafe.Pointer(v.Pointer())} +} + +// offset converts from a pointer to a structure to a pointer to +// one of its fields. +func (p pointer) offset(f field) pointer { + // For safety, we should panic if !f.IsValid, however calling panic causes + // this to no longer be inlineable, which is a serious performance cost. + /* + if !f.IsValid() { + panic("invalid field") + } + */ + return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))} +} + +func (p pointer) isNil() bool { + return p.p == nil +} + +func (p pointer) toInt64() *int64 { + return (*int64)(p.p) +} +func (p pointer) toInt64Ptr() **int64 { + return (**int64)(p.p) +} +func (p pointer) toInt64Slice() *[]int64 { + return (*[]int64)(p.p) +} +func (p pointer) toInt32() *int32 { + return (*int32)(p.p) +} + +// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist. +/* + func (p pointer) toInt32Ptr() **int32 { + return (**int32)(p.p) + } + func (p pointer) toInt32Slice() *[]int32 { + return (*[]int32)(p.p) + } +*/ +func (p pointer) getInt32Ptr() *int32 { + return *(**int32)(p.p) +} +func (p pointer) setInt32Ptr(v int32) { + *(**int32)(p.p) = &v +} + +// getInt32Slice loads a []int32 from p. +// The value returned is aliased with the original slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) getInt32Slice() []int32 { + return *(*[]int32)(p.p) +} + +// setInt32Slice stores a []int32 to p. +// The value set is aliased with the input slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) setInt32Slice(v []int32) { + *(*[]int32)(p.p) = v +} + +// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead? +func (p pointer) appendInt32Slice(v int32) { + s := (*[]int32)(p.p) + *s = append(*s, v) +} + +func (p pointer) toUint64() *uint64 { + return (*uint64)(p.p) +} +func (p pointer) toUint64Ptr() **uint64 { + return (**uint64)(p.p) +} +func (p pointer) toUint64Slice() *[]uint64 { + return (*[]uint64)(p.p) +} +func (p pointer) toUint32() *uint32 { + return (*uint32)(p.p) +} +func (p pointer) toUint32Ptr() **uint32 { + return (**uint32)(p.p) +} +func (p pointer) toUint32Slice() *[]uint32 { + return (*[]uint32)(p.p) +} +func (p pointer) toBool() *bool { + return (*bool)(p.p) +} +func (p pointer) toBoolPtr() **bool { + return (**bool)(p.p) +} +func (p pointer) toBoolSlice() *[]bool { + return (*[]bool)(p.p) +} +func (p pointer) toFloat64() *float64 { + return (*float64)(p.p) +} +func (p pointer) toFloat64Ptr() **float64 { + return (**float64)(p.p) +} +func (p pointer) toFloat64Slice() *[]float64 { + return (*[]float64)(p.p) +} +func (p pointer) toFloat32() *float32 { + return (*float32)(p.p) +} +func (p pointer) toFloat32Ptr() **float32 { + return (**float32)(p.p) +} +func (p pointer) toFloat32Slice() *[]float32 { + return (*[]float32)(p.p) +} +func (p pointer) toString() *string { + return (*string)(p.p) +} +func (p pointer) toStringPtr() **string { + return (**string)(p.p) +} +func (p pointer) toStringSlice() *[]string { + return (*[]string)(p.p) +} +func (p pointer) toBytes() *[]byte { + return (*[]byte)(p.p) +} +func (p pointer) toBytesSlice() *[][]byte { + return (*[][]byte)(p.p) +} +func (p pointer) toExtensions() *XXX_InternalExtensions { + return (*XXX_InternalExtensions)(p.p) +} +func (p pointer) toOldExtensions() *map[int32]Extension { + return (*map[int32]Extension)(p.p) +} + +// getPointerSlice loads []*T from p as a []pointer. +// The value returned is aliased with the original slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) getPointerSlice() []pointer { + // Super-tricky - p should point to a []*T where T is a + // message type. We load it as []pointer. + return *(*[]pointer)(p.p) +} + +// setPointerSlice stores []pointer into p as a []*T. +// The value set is aliased with the input slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) setPointerSlice(v []pointer) { + // Super-tricky - p should point to a []*T where T is a + // message type. We store it as []pointer. + *(*[]pointer)(p.p) = v +} + +// getPointer loads the pointer at p and returns it. +func (p pointer) getPointer() pointer { + return pointer{p: *(*unsafe.Pointer)(p.p)} +} + +// setPointer stores the pointer q at p. +func (p pointer) setPointer(q pointer) { + *(*unsafe.Pointer)(p.p) = q.p +} + +// append q to the slice pointed to by p. +func (p pointer) appendPointer(q pointer) { + s := (*[]unsafe.Pointer)(p.p) + *s = append(*s, q.p) +} + +// getInterfacePointer returns a pointer that points to the +// interface data of the interface pointed by p. +func (p pointer) getInterfacePointer() pointer { + // Super-tricky - read pointer out of data word of interface value. + return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]} +} + +// asPointerTo returns a reflect.Value that is a pointer to an +// object of type t stored at p. +func (p pointer) asPointerTo(t reflect.Type) reflect.Value { + return reflect.NewAt(t, p.p) +} + +func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { + return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { + return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { + return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { + return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} diff --git a/vendor/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go b/vendor/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go new file mode 100644 index 000000000..aca8eed02 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go @@ -0,0 +1,56 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2018, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build !purego,!appengine,!js + +// This file contains the implementation of the proto field accesses using package unsafe. + +package proto + +import ( + "reflect" + "unsafe" +) + +func (p pointer) getRef() pointer { + return pointer{p: (unsafe.Pointer)(&p.p)} +} + +func (p pointer) appendRef(v pointer, typ reflect.Type) { + slice := p.getSlice(typ) + elem := v.asPointerTo(typ).Elem() + newSlice := reflect.Append(slice, elem) + slice.Set(newSlice) +} + +func (p pointer) getSlice(typ reflect.Type) reflect.Value { + sliceTyp := reflect.SliceOf(typ) + slice := p.asPointerTo(sliceTyp) + slice = slice.Elem() + return slice +} diff --git a/vendor/github.com/gogo/protobuf/proto/properties.go b/vendor/github.com/gogo/protobuf/proto/properties.go new file mode 100644 index 000000000..c9e5fa020 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/properties.go @@ -0,0 +1,599 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +/* + * Routines for encoding data into the wire format for protocol buffers. + */ + +import ( + "fmt" + "log" + "os" + "reflect" + "sort" + "strconv" + "strings" + "sync" +) + +const debug bool = false + +// Constants that identify the encoding of a value on the wire. +const ( + WireVarint = 0 + WireFixed64 = 1 + WireBytes = 2 + WireStartGroup = 3 + WireEndGroup = 4 + WireFixed32 = 5 +) + +// tagMap is an optimization over map[int]int for typical protocol buffer +// use-cases. Encoded protocol buffers are often in tag order with small tag +// numbers. +type tagMap struct { + fastTags []int + slowTags map[int]int +} + +// tagMapFastLimit is the upper bound on the tag number that will be stored in +// the tagMap slice rather than its map. +const tagMapFastLimit = 1024 + +func (p *tagMap) get(t int) (int, bool) { + if t > 0 && t < tagMapFastLimit { + if t >= len(p.fastTags) { + return 0, false + } + fi := p.fastTags[t] + return fi, fi >= 0 + } + fi, ok := p.slowTags[t] + return fi, ok +} + +func (p *tagMap) put(t int, fi int) { + if t > 0 && t < tagMapFastLimit { + for len(p.fastTags) < t+1 { + p.fastTags = append(p.fastTags, -1) + } + p.fastTags[t] = fi + return + } + if p.slowTags == nil { + p.slowTags = make(map[int]int) + } + p.slowTags[t] = fi +} + +// StructProperties represents properties for all the fields of a struct. +// decoderTags and decoderOrigNames should only be used by the decoder. +type StructProperties struct { + Prop []*Properties // properties for each field + reqCount int // required count + decoderTags tagMap // map from proto tag to struct field number + decoderOrigNames map[string]int // map from original name to struct field number + order []int // list of struct field numbers in tag order + + // OneofTypes contains information about the oneof fields in this message. + // It is keyed by the original name of a field. + OneofTypes map[string]*OneofProperties +} + +// OneofProperties represents information about a specific field in a oneof. +type OneofProperties struct { + Type reflect.Type // pointer to generated struct type for this oneof field + Field int // struct field number of the containing oneof in the message + Prop *Properties +} + +// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec. +// See encode.go, (*Buffer).enc_struct. + +func (sp *StructProperties) Len() int { return len(sp.order) } +func (sp *StructProperties) Less(i, j int) bool { + return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag +} +func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] } + +// Properties represents the protocol-specific behavior of a single struct field. +type Properties struct { + Name string // name of the field, for error messages + OrigName string // original name before protocol compiler (always set) + JSONName string // name to use for JSON; determined by protoc + Wire string + WireType int + Tag int + Required bool + Optional bool + Repeated bool + Packed bool // relevant for repeated primitives only + Enum string // set for enum types only + proto3 bool // whether this is known to be a proto3 field + oneof bool // whether this is a oneof field + + Default string // default value + HasDefault bool // whether an explicit default was provided + CustomType string + CastType string + StdTime bool + StdDuration bool + WktPointer bool + + stype reflect.Type // set for struct types only + ctype reflect.Type // set for custom types only + sprop *StructProperties // set for struct types only + + mtype reflect.Type // set for map types only + MapKeyProp *Properties // set for map types only + MapValProp *Properties // set for map types only +} + +// String formats the properties in the protobuf struct field tag style. +func (p *Properties) String() string { + s := p.Wire + s += "," + s += strconv.Itoa(p.Tag) + if p.Required { + s += ",req" + } + if p.Optional { + s += ",opt" + } + if p.Repeated { + s += ",rep" + } + if p.Packed { + s += ",packed" + } + s += ",name=" + p.OrigName + if p.JSONName != p.OrigName { + s += ",json=" + p.JSONName + } + if p.proto3 { + s += ",proto3" + } + if p.oneof { + s += ",oneof" + } + if len(p.Enum) > 0 { + s += ",enum=" + p.Enum + } + if p.HasDefault { + s += ",def=" + p.Default + } + return s +} + +// Parse populates p by parsing a string in the protobuf struct field tag style. +func (p *Properties) Parse(s string) { + // "bytes,49,opt,name=foo,def=hello!" + fields := strings.Split(s, ",") // breaks def=, but handled below. + if len(fields) < 2 { + fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) + return + } + + p.Wire = fields[0] + switch p.Wire { + case "varint": + p.WireType = WireVarint + case "fixed32": + p.WireType = WireFixed32 + case "fixed64": + p.WireType = WireFixed64 + case "zigzag32": + p.WireType = WireVarint + case "zigzag64": + p.WireType = WireVarint + case "bytes", "group": + p.WireType = WireBytes + // no numeric converter for non-numeric types + default: + fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) + return + } + + var err error + p.Tag, err = strconv.Atoi(fields[1]) + if err != nil { + return + } + +outer: + for i := 2; i < len(fields); i++ { + f := fields[i] + switch { + case f == "req": + p.Required = true + case f == "opt": + p.Optional = true + case f == "rep": + p.Repeated = true + case f == "packed": + p.Packed = true + case strings.HasPrefix(f, "name="): + p.OrigName = f[5:] + case strings.HasPrefix(f, "json="): + p.JSONName = f[5:] + case strings.HasPrefix(f, "enum="): + p.Enum = f[5:] + case f == "proto3": + p.proto3 = true + case f == "oneof": + p.oneof = true + case strings.HasPrefix(f, "def="): + p.HasDefault = true + p.Default = f[4:] // rest of string + if i+1 < len(fields) { + // Commas aren't escaped, and def is always last. + p.Default += "," + strings.Join(fields[i+1:], ",") + break outer + } + case strings.HasPrefix(f, "embedded="): + p.OrigName = strings.Split(f, "=")[1] + case strings.HasPrefix(f, "customtype="): + p.CustomType = strings.Split(f, "=")[1] + case strings.HasPrefix(f, "casttype="): + p.CastType = strings.Split(f, "=")[1] + case f == "stdtime": + p.StdTime = true + case f == "stdduration": + p.StdDuration = true + case f == "wktptr": + p.WktPointer = true + } + } +} + +var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() + +// setFieldProps initializes the field properties for submessages and maps. +func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { + isMap := typ.Kind() == reflect.Map + if len(p.CustomType) > 0 && !isMap { + p.ctype = typ + p.setTag(lockGetProp) + return + } + if p.StdTime && !isMap { + p.setTag(lockGetProp) + return + } + if p.StdDuration && !isMap { + p.setTag(lockGetProp) + return + } + if p.WktPointer && !isMap { + p.setTag(lockGetProp) + return + } + switch t1 := typ; t1.Kind() { + case reflect.Struct: + p.stype = typ + case reflect.Ptr: + if t1.Elem().Kind() == reflect.Struct { + p.stype = t1.Elem() + } + case reflect.Slice: + switch t2 := t1.Elem(); t2.Kind() { + case reflect.Ptr: + switch t3 := t2.Elem(); t3.Kind() { + case reflect.Struct: + p.stype = t3 + } + case reflect.Struct: + p.stype = t2 + } + + case reflect.Map: + + p.mtype = t1 + p.MapKeyProp = &Properties{} + p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) + p.MapValProp = &Properties{} + vtype := p.mtype.Elem() + if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { + // The value type is not a message (*T) or bytes ([]byte), + // so we need encoders for the pointer to this type. + vtype = reflect.PtrTo(vtype) + } + + p.MapValProp.CustomType = p.CustomType + p.MapValProp.StdDuration = p.StdDuration + p.MapValProp.StdTime = p.StdTime + p.MapValProp.WktPointer = p.WktPointer + p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) + } + p.setTag(lockGetProp) +} + +func (p *Properties) setTag(lockGetProp bool) { + if p.stype != nil { + if lockGetProp { + p.sprop = GetProperties(p.stype) + } else { + p.sprop = getPropertiesLocked(p.stype) + } + } +} + +var ( + marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() +) + +// Init populates the properties from a protocol buffer struct tag. +func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) { + p.init(typ, name, tag, f, true) +} + +func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) { + // "bytes,49,opt,def=hello!" + p.Name = name + p.OrigName = name + if tag == "" { + return + } + p.Parse(tag) + p.setFieldProps(typ, f, lockGetProp) +} + +var ( + propertiesMu sync.RWMutex + propertiesMap = make(map[reflect.Type]*StructProperties) +) + +// GetProperties returns the list of properties for the type represented by t. +// t must represent a generated struct type of a protocol message. +func GetProperties(t reflect.Type) *StructProperties { + if t.Kind() != reflect.Struct { + panic("proto: type must have kind struct") + } + + // Most calls to GetProperties in a long-running program will be + // retrieving details for types we have seen before. + propertiesMu.RLock() + sprop, ok := propertiesMap[t] + propertiesMu.RUnlock() + if ok { + return sprop + } + + propertiesMu.Lock() + sprop = getPropertiesLocked(t) + propertiesMu.Unlock() + return sprop +} + +// getPropertiesLocked requires that propertiesMu is held. +func getPropertiesLocked(t reflect.Type) *StructProperties { + if prop, ok := propertiesMap[t]; ok { + return prop + } + + prop := new(StructProperties) + // in case of recursive protos, fill this in now. + propertiesMap[t] = prop + + // build properties + prop.Prop = make([]*Properties, t.NumField()) + prop.order = make([]int, t.NumField()) + + isOneofMessage := false + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + p := new(Properties) + name := f.Name + p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) + + oneof := f.Tag.Get("protobuf_oneof") // special case + if oneof != "" { + isOneofMessage = true + // Oneof fields don't use the traditional protobuf tag. + p.OrigName = oneof + } + prop.Prop[i] = p + prop.order[i] = i + if debug { + print(i, " ", f.Name, " ", t.String(), " ") + if p.Tag > 0 { + print(p.String()) + } + print("\n") + } + } + + // Re-order prop.order. + sort.Sort(prop) + + type oneofMessage interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) + } + if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); isOneofMessage && ok { + var oots []interface{} + _, _, _, oots = om.XXX_OneofFuncs() + + // Interpret oneof metadata. + prop.OneofTypes = make(map[string]*OneofProperties) + for _, oot := range oots { + oop := &OneofProperties{ + Type: reflect.ValueOf(oot).Type(), // *T + Prop: new(Properties), + } + sft := oop.Type.Elem().Field(0) + oop.Prop.Name = sft.Name + oop.Prop.Parse(sft.Tag.Get("protobuf")) + // There will be exactly one interface field that + // this new value is assignable to. + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if f.Type.Kind() != reflect.Interface { + continue + } + if !oop.Type.AssignableTo(f.Type) { + continue + } + oop.Field = i + break + } + prop.OneofTypes[oop.Prop.OrigName] = oop + } + } + + // build required counts + // build tags + reqCount := 0 + prop.decoderOrigNames = make(map[string]int) + for i, p := range prop.Prop { + if strings.HasPrefix(p.Name, "XXX_") { + // Internal fields should not appear in tags/origNames maps. + // They are handled specially when encoding and decoding. + continue + } + if p.Required { + reqCount++ + } + prop.decoderTags.put(p.Tag, i) + prop.decoderOrigNames[p.OrigName] = i + } + prop.reqCount = reqCount + + return prop +} + +// A global registry of enum types. +// The generated code will register the generated maps by calling RegisterEnum. + +var enumValueMaps = make(map[string]map[string]int32) +var enumStringMaps = make(map[string]map[int32]string) + +// RegisterEnum is called from the generated code to install the enum descriptor +// maps into the global table to aid parsing text format protocol buffers. +func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) { + if _, ok := enumValueMaps[typeName]; ok { + panic("proto: duplicate enum registered: " + typeName) + } + enumValueMaps[typeName] = valueMap + if _, ok := enumStringMaps[typeName]; ok { + panic("proto: duplicate enum registered: " + typeName) + } + enumStringMaps[typeName] = unusedNameMap +} + +// EnumValueMap returns the mapping from names to integers of the +// enum type enumType, or a nil if not found. +func EnumValueMap(enumType string) map[string]int32 { + return enumValueMaps[enumType] +} + +// A registry of all linked message types. +// The string is a fully-qualified proto name ("pkg.Message"). +var ( + protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers + protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types + revProtoTypes = make(map[reflect.Type]string) +) + +// RegisterType is called from generated code and maps from the fully qualified +// proto name to the type (pointer to struct) of the protocol buffer. +func RegisterType(x Message, name string) { + if _, ok := protoTypedNils[name]; ok { + // TODO: Some day, make this a panic. + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 { + // Generated code always calls RegisterType with nil x. + // This check is just for extra safety. + protoTypedNils[name] = x + } else { + protoTypedNils[name] = reflect.Zero(t).Interface().(Message) + } + revProtoTypes[t] = name +} + +// RegisterMapType is called from generated code and maps from the fully qualified +// proto name to the native map type of the proto map definition. +func RegisterMapType(x interface{}, name string) { + if reflect.TypeOf(x).Kind() != reflect.Map { + panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name)) + } + if _, ok := protoMapTypes[name]; ok { + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + protoMapTypes[name] = t + revProtoTypes[t] = name +} + +// MessageName returns the fully-qualified proto name for the given message type. +func MessageName(x Message) string { + type xname interface { + XXX_MessageName() string + } + if m, ok := x.(xname); ok { + return m.XXX_MessageName() + } + return revProtoTypes[reflect.TypeOf(x)] +} + +// MessageType returns the message type (pointer to struct) for a named message. +// The type is not guaranteed to implement proto.Message if the name refers to a +// map entry. +func MessageType(name string) reflect.Type { + if t, ok := protoTypedNils[name]; ok { + return reflect.TypeOf(t) + } + return protoMapTypes[name] +} + +// A registry of all linked proto files. +var ( + protoFiles = make(map[string][]byte) // file name => fileDescriptor +) + +// RegisterFile is called from generated code and maps from the +// full file name of a .proto file to its compressed FileDescriptorProto. +func RegisterFile(filename string, fileDescriptor []byte) { + protoFiles[filename] = fileDescriptor +} + +// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. +func FileDescriptor(filename string) []byte { return protoFiles[filename] } diff --git a/vendor/github.com/gogo/protobuf/proto/properties_gogo.go b/vendor/github.com/gogo/protobuf/proto/properties_gogo.go new file mode 100644 index 000000000..40ea3dd93 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/properties_gogo.go @@ -0,0 +1,36 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2018, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "reflect" +) + +var sizerType = reflect.TypeOf((*Sizer)(nil)).Elem() +var protosizerType = reflect.TypeOf((*ProtoSizer)(nil)).Elem() diff --git a/vendor/github.com/gogo/protobuf/proto/skip_gogo.go b/vendor/github.com/gogo/protobuf/proto/skip_gogo.go new file mode 100644 index 000000000..5a5fd93f7 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/skip_gogo.go @@ -0,0 +1,119 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "fmt" + "io" +) + +func Skip(data []byte) (n int, err error) { + l := len(data) + index := 0 + for index < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if index >= l { + return 0, io.ErrUnexpectedEOF + } + b := data[index] + index++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for { + if index >= l { + return 0, io.ErrUnexpectedEOF + } + index++ + if data[index-1] < 0x80 { + break + } + } + return index, nil + case 1: + index += 8 + return index, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if index >= l { + return 0, io.ErrUnexpectedEOF + } + b := data[index] + index++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + index += length + return index, nil + case 3: + for { + var innerWire uint64 + var start int = index + for shift := uint(0); ; shift += 7 { + if index >= l { + return 0, io.ErrUnexpectedEOF + } + b := data[index] + index++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := Skip(data[start:]) + if err != nil { + return 0, err + } + index = start + next + } + return index, nil + case 4: + return index, nil + case 5: + index += 4 + return index, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} diff --git a/vendor/github.com/gogo/protobuf/proto/table_marshal.go b/vendor/github.com/gogo/protobuf/proto/table_marshal.go new file mode 100644 index 000000000..9b1538d05 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/table_marshal.go @@ -0,0 +1,3006 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +import ( + "errors" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// a sizer takes a pointer to a field and the size of its tag, computes the size of +// the encoded data. +type sizer func(pointer, int) int + +// a marshaler takes a byte slice, a pointer to a field, and its tag (in wire format), +// marshals the field to the end of the slice, returns the slice and error (if any). +type marshaler func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) + +// marshalInfo is the information used for marshaling a message. +type marshalInfo struct { + typ reflect.Type + fields []*marshalFieldInfo + unrecognized field // offset of XXX_unrecognized + extensions field // offset of XXX_InternalExtensions + v1extensions field // offset of XXX_extensions + sizecache field // offset of XXX_sizecache + initialized int32 // 0 -- only typ is set, 1 -- fully initialized + messageset bool // uses message set wire format + hasmarshaler bool // has custom marshaler + sync.RWMutex // protect extElems map, also for initialization + extElems map[int32]*marshalElemInfo // info of extension elements + + hassizer bool // has custom sizer + hasprotosizer bool // has custom protosizer + + bytesExtensions field // offset of XXX_extensions where the field type is []byte +} + +// marshalFieldInfo is the information used for marshaling a field of a message. +type marshalFieldInfo struct { + field field + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isPointer bool + required bool // field is required + name string // name of the field, for error reporting + oneofElems map[reflect.Type]*marshalElemInfo // info of oneof elements +} + +// marshalElemInfo is the information used for marshaling an extension or oneof element. +type marshalElemInfo struct { + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only) +} + +var ( + marshalInfoMap = map[reflect.Type]*marshalInfo{} + marshalInfoLock sync.Mutex + + uint8SliceType = reflect.TypeOf(([]uint8)(nil)).Kind() +) + +// getMarshalInfo returns the information to marshal a given type of message. +// The info it returns may not necessarily initialized. +// t is the type of the message (NOT the pointer to it). +func getMarshalInfo(t reflect.Type) *marshalInfo { + marshalInfoLock.Lock() + u, ok := marshalInfoMap[t] + if !ok { + u = &marshalInfo{typ: t} + marshalInfoMap[t] = u + } + marshalInfoLock.Unlock() + return u +} + +// Size is the entry point from generated code, +// and should be ONLY called by generated code. +// It computes the size of encoded data of msg. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Size(msg Message) int { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return 0 + } + return u.size(ptr) +} + +// Marshal is the entry point from generated code, +// and should be ONLY called by generated code. +// It marshals msg to the end of b. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Marshal(b []byte, msg Message, deterministic bool) ([]byte, error) { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return b, ErrNil + } + return u.marshal(b, ptr, deterministic) +} + +func getMessageMarshalInfo(msg interface{}, a *InternalMessageInfo) *marshalInfo { + // u := a.marshal, but atomically. + // We use an atomic here to ensure memory consistency. + u := atomicLoadMarshalInfo(&a.marshal) + if u == nil { + // Get marshal information from type of message. + t := reflect.ValueOf(msg).Type() + if t.Kind() != reflect.Ptr { + panic(fmt.Sprintf("cannot handle non-pointer message type %v", t)) + } + u = getMarshalInfo(t.Elem()) + // Store it in the cache for later users. + // a.marshal = u, but atomically. + atomicStoreMarshalInfo(&a.marshal, u) + } + return u +} + +// size is the main function to compute the size of the encoded data of a message. +// ptr is the pointer to the message. +func (u *marshalInfo) size(ptr pointer) int { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + // Uses the message's Size method if available + if u.hassizer { + s := ptr.asPointerTo(u.typ).Interface().(Sizer) + return s.Size() + } + // Uses the message's ProtoSize method if available + if u.hasprotosizer { + s := ptr.asPointerTo(u.typ).Interface().(ProtoSizer) + return s.ProtoSize() + } + + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b, _ := m.Marshal() + return len(b) + } + + n := 0 + for _, f := range u.fields { + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + n += f.sizer(ptr.offset(f.field), f.tagsize) + } + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + n += u.sizeMessageSet(e) + } else { + n += u.sizeExtensions(e) + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + n += u.sizeV1Extensions(m) + } + if u.bytesExtensions.IsValid() { + s := *ptr.offset(u.bytesExtensions).toBytes() + n += len(s) + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + n += len(s) + } + + // cache the result for use in marshal + if u.sizecache.IsValid() { + atomic.StoreInt32(ptr.offset(u.sizecache).toInt32(), int32(n)) + } + return n +} + +// cachedsize gets the size from cache. If there is no cache (i.e. message is not generated), +// fall back to compute the size. +func (u *marshalInfo) cachedsize(ptr pointer) int { + if u.sizecache.IsValid() { + return int(atomic.LoadInt32(ptr.offset(u.sizecache).toInt32())) + } + return u.size(ptr) +} + +// marshal is the main function to marshal a message. It takes a byte slice and appends +// the encoded data to the end of the slice, returns the slice and error (if any). +// ptr is the pointer to the message. +// If deterministic is true, map is marshaled in deterministic order. +func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte, error) { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b1, err := m.Marshal() + b = append(b, b1...) + return b, err + } + + var err, errLater error + // The old marshaler encodes extensions at beginning. + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + b, err = u.appendMessageSet(b, e, deterministic) + } else { + b, err = u.appendExtensions(b, e, deterministic) + } + if err != nil { + return b, err + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + b, err = u.appendV1Extensions(b, m, deterministic) + if err != nil { + return b, err + } + } + if u.bytesExtensions.IsValid() { + s := *ptr.offset(u.bytesExtensions).toBytes() + b = append(b, s...) + } + for _, f := range u.fields { + if f.required { + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // Required field is not set. + // We record the error but keep going, to give a complete marshaling. + if errLater == nil { + errLater = &RequiredNotSetError{f.name} + } + continue + } + } + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + b, err = f.marshaler(b, ptr.offset(f.field), f.wiretag, deterministic) + if err != nil { + if err1, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errLater == nil { + errLater = &RequiredNotSetError{f.name + "." + err1.field} + } + continue + } + if err == errRepeatedHasNil { + err = errors.New("proto: repeated field " + f.name + " has nil element") + } + if err == errInvalidUTF8 { + if errLater == nil { + fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name + errLater = &invalidUTF8Error{fullName} + } + continue + } + return b, err + } + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + b = append(b, s...) + } + return b, errLater +} + +// computeMarshalInfo initializes the marshal info. +func (u *marshalInfo) computeMarshalInfo() { + u.Lock() + defer u.Unlock() + if u.initialized != 0 { // non-atomic read is ok as it is protected by the lock + return + } + + t := u.typ + u.unrecognized = invalidField + u.extensions = invalidField + u.v1extensions = invalidField + u.bytesExtensions = invalidField + u.sizecache = invalidField + isOneofMessage := false + + if reflect.PtrTo(t).Implements(sizerType) { + u.hassizer = true + } + if reflect.PtrTo(t).Implements(protosizerType) { + u.hasprotosizer = true + } + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if reflect.PtrTo(t).Implements(marshalerType) { + u.hasmarshaler = true + atomic.StoreInt32(&u.initialized, 1) + return + } + + n := t.NumField() + + // deal with XXX fields first + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if f.Tag.Get("protobuf_oneof") != "" { + isOneofMessage = true + } + if !strings.HasPrefix(f.Name, "XXX_") { + continue + } + switch f.Name { + case "XXX_sizecache": + u.sizecache = toField(&f) + case "XXX_unrecognized": + u.unrecognized = toField(&f) + case "XXX_InternalExtensions": + u.extensions = toField(&f) + u.messageset = f.Tag.Get("protobuf_messageset") == "1" + case "XXX_extensions": + if f.Type.Kind() == reflect.Map { + u.v1extensions = toField(&f) + } else { + u.bytesExtensions = toField(&f) + } + case "XXX_NoUnkeyedLiteral": + // nothing to do + default: + panic("unknown XXX field: " + f.Name) + } + n-- + } + + // get oneof implementers + var oneofImplementers []interface{} + // gogo: isOneofMessage is needed for embedded oneof messages, without a marshaler and unmarshaler + if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok && isOneofMessage { + _, _, _, oneofImplementers = m.XXX_OneofFuncs() + } + + // normal fields + fields := make([]marshalFieldInfo, n) // batch allocation + u.fields = make([]*marshalFieldInfo, 0, n) + for i, j := 0, 0; i < t.NumField(); i++ { + f := t.Field(i) + + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + field := &fields[j] + j++ + field.name = f.Name + u.fields = append(u.fields, field) + if f.Tag.Get("protobuf_oneof") != "" { + field.computeOneofFieldInfo(&f, oneofImplementers) + continue + } + if f.Tag.Get("protobuf") == "" { + // field has no tag (not in generated message), ignore it + u.fields = u.fields[:len(u.fields)-1] + j-- + continue + } + field.computeMarshalFieldInfo(&f) + } + + // fields are marshaled in tag order on the wire. + sort.Sort(byTag(u.fields)) + + atomic.StoreInt32(&u.initialized, 1) +} + +// helper for sorting fields by tag +type byTag []*marshalFieldInfo + +func (a byTag) Len() int { return len(a) } +func (a byTag) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byTag) Less(i, j int) bool { return a[i].wiretag < a[j].wiretag } + +// getExtElemInfo returns the information to marshal an extension element. +// The info it returns is initialized. +func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo { + // get from cache first + u.RLock() + e, ok := u.extElems[desc.Field] + u.RUnlock() + if ok { + return e + } + + t := reflect.TypeOf(desc.ExtensionType) // pointer or slice to basic type or struct + tags := strings.Split(desc.Tag, ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + sizr, marshalr := typeMarshaler(t, tags, false, false) + e = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizr, + marshaler: marshalr, + isptr: t.Kind() == reflect.Ptr, + } + + // update cache + u.Lock() + if u.extElems == nil { + u.extElems = make(map[int32]*marshalElemInfo) + } + u.extElems[desc.Field] = e + u.Unlock() + return e +} + +// computeMarshalFieldInfo fills up the information to marshal a field. +func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) { + // parse protobuf tag of the field. + // tag has format of "bytes,49,opt,name=foo,def=hello!" + tags := strings.Split(f.Tag.Get("protobuf"), ",") + if tags[0] == "" { + return + } + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + if tags[2] == "req" { + fi.required = true + } + fi.setTag(f, tag, wt) + fi.setMarshaler(f, tags) +} + +func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) { + fi.field = toField(f) + fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire. + fi.isPointer = true + fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f) + fi.oneofElems = make(map[reflect.Type]*marshalElemInfo) + + ityp := f.Type // interface type + for _, o := range oneofImplementers { + t := reflect.TypeOf(o) + if !t.Implements(ityp) { + continue + } + sf := t.Elem().Field(0) // oneof implementer is a struct with a single field + tags := strings.Split(sf.Tag.Get("protobuf"), ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + sizr, marshalr := typeMarshaler(sf.Type, tags, false, true) // oneof should not omit any zero value + fi.oneofElems[t.Elem()] = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizr, + marshaler: marshalr, + } + } +} + +type oneofMessage interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) +} + +// wiretype returns the wire encoding of the type. +func wiretype(encoding string) uint64 { + switch encoding { + case "fixed32": + return WireFixed32 + case "fixed64": + return WireFixed64 + case "varint", "zigzag32", "zigzag64": + return WireVarint + case "bytes": + return WireBytes + case "group": + return WireStartGroup + } + panic("unknown wire type " + encoding) +} + +// setTag fills up the tag (in wire format) and its size in the info of a field. +func (fi *marshalFieldInfo) setTag(f *reflect.StructField, tag int, wt uint64) { + fi.field = toField(f) + fi.wiretag = uint64(tag)<<3 | wt + fi.tagsize = SizeVarint(uint64(tag) << 3) +} + +// setMarshaler fills up the sizer and marshaler in the info of a field. +func (fi *marshalFieldInfo) setMarshaler(f *reflect.StructField, tags []string) { + switch f.Type.Kind() { + case reflect.Map: + // map field + fi.isPointer = true + fi.sizer, fi.marshaler = makeMapMarshaler(f) + return + case reflect.Ptr, reflect.Slice: + fi.isPointer = true + } + fi.sizer, fi.marshaler = typeMarshaler(f.Type, tags, true, false) +} + +// typeMarshaler returns the sizer and marshaler of a given field. +// t is the type of the field. +// tags is the generated "protobuf" tag of the field. +// If nozero is true, zero value is not marshaled to the wire. +// If oneof is true, it is a oneof field. +func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, marshaler) { + encoding := tags[0] + + pointer := false + slice := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + packed := false + proto3 := false + ctype := false + isTime := false + isDuration := false + isWktPointer := false + validateUTF8 := true + for i := 2; i < len(tags); i++ { + if tags[i] == "packed" { + packed = true + } + if tags[i] == "proto3" { + proto3 = true + } + if strings.HasPrefix(tags[i], "customtype=") { + ctype = true + } + if tags[i] == "stdtime" { + isTime = true + } + if tags[i] == "stdduration" { + isDuration = true + } + if tags[i] == "wktptr" { + isWktPointer = true + } + } + validateUTF8 = validateUTF8 && proto3 + if !proto3 && !pointer && !slice { + nozero = false + } + + if ctype { + if reflect.PtrTo(t).Implements(customType) { + if slice { + return makeMessageRefSliceMarshaler(getMarshalInfo(t)) + } + if pointer { + return makeCustomPtrMarshaler(getMarshalInfo(t)) + } + return makeCustomMarshaler(getMarshalInfo(t)) + } else { + panic(fmt.Sprintf("custom type: type: %v, does not implement the proto.custom interface", t)) + } + } + + if isTime { + if pointer { + if slice { + return makeTimePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeTimePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeTimeSliceMarshaler(getMarshalInfo(t)) + } + return makeTimeMarshaler(getMarshalInfo(t)) + } + + if isDuration { + if pointer { + if slice { + return makeDurationPtrSliceMarshaler(getMarshalInfo(t)) + } + return makeDurationPtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeDurationSliceMarshaler(getMarshalInfo(t)) + } + return makeDurationMarshaler(getMarshalInfo(t)) + } + + if isWktPointer { + switch t.Kind() { + case reflect.Float64: + if pointer { + if slice { + return makeStdDoubleValuePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeStdDoubleValuePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeStdDoubleValueSliceMarshaler(getMarshalInfo(t)) + } + return makeStdDoubleValueMarshaler(getMarshalInfo(t)) + case reflect.Float32: + if pointer { + if slice { + return makeStdFloatValuePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeStdFloatValuePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeStdFloatValueSliceMarshaler(getMarshalInfo(t)) + } + return makeStdFloatValueMarshaler(getMarshalInfo(t)) + case reflect.Int64: + if pointer { + if slice { + return makeStdInt64ValuePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeStdInt64ValuePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeStdInt64ValueSliceMarshaler(getMarshalInfo(t)) + } + return makeStdInt64ValueMarshaler(getMarshalInfo(t)) + case reflect.Uint64: + if pointer { + if slice { + return makeStdUInt64ValuePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeStdUInt64ValuePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeStdUInt64ValueSliceMarshaler(getMarshalInfo(t)) + } + return makeStdUInt64ValueMarshaler(getMarshalInfo(t)) + case reflect.Int32: + if pointer { + if slice { + return makeStdInt32ValuePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeStdInt32ValuePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeStdInt32ValueSliceMarshaler(getMarshalInfo(t)) + } + return makeStdInt32ValueMarshaler(getMarshalInfo(t)) + case reflect.Uint32: + if pointer { + if slice { + return makeStdUInt32ValuePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeStdUInt32ValuePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeStdUInt32ValueSliceMarshaler(getMarshalInfo(t)) + } + return makeStdUInt32ValueMarshaler(getMarshalInfo(t)) + case reflect.Bool: + if pointer { + if slice { + return makeStdBoolValuePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeStdBoolValuePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeStdBoolValueSliceMarshaler(getMarshalInfo(t)) + } + return makeStdBoolValueMarshaler(getMarshalInfo(t)) + case reflect.String: + if pointer { + if slice { + return makeStdStringValuePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeStdStringValuePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeStdStringValueSliceMarshaler(getMarshalInfo(t)) + } + return makeStdStringValueMarshaler(getMarshalInfo(t)) + case uint8SliceType: + if pointer { + if slice { + return makeStdBytesValuePtrSliceMarshaler(getMarshalInfo(t)) + } + return makeStdBytesValuePtrMarshaler(getMarshalInfo(t)) + } + if slice { + return makeStdBytesValueSliceMarshaler(getMarshalInfo(t)) + } + return makeStdBytesValueMarshaler(getMarshalInfo(t)) + default: + panic(fmt.Sprintf("unknown wktpointer type %#v", t)) + } + } + + switch t.Kind() { + case reflect.Bool: + if pointer { + return sizeBoolPtr, appendBoolPtr + } + if slice { + if packed { + return sizeBoolPackedSlice, appendBoolPackedSlice + } + return sizeBoolSlice, appendBoolSlice + } + if nozero { + return sizeBoolValueNoZero, appendBoolValueNoZero + } + return sizeBoolValue, appendBoolValue + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixed32Ptr, appendFixed32Ptr + } + if slice { + if packed { + return sizeFixed32PackedSlice, appendFixed32PackedSlice + } + return sizeFixed32Slice, appendFixed32Slice + } + if nozero { + return sizeFixed32ValueNoZero, appendFixed32ValueNoZero + } + return sizeFixed32Value, appendFixed32Value + case "varint": + if pointer { + return sizeVarint32Ptr, appendVarint32Ptr + } + if slice { + if packed { + return sizeVarint32PackedSlice, appendVarint32PackedSlice + } + return sizeVarint32Slice, appendVarint32Slice + } + if nozero { + return sizeVarint32ValueNoZero, appendVarint32ValueNoZero + } + return sizeVarint32Value, appendVarint32Value + } + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixedS32Ptr, appendFixedS32Ptr + } + if slice { + if packed { + return sizeFixedS32PackedSlice, appendFixedS32PackedSlice + } + return sizeFixedS32Slice, appendFixedS32Slice + } + if nozero { + return sizeFixedS32ValueNoZero, appendFixedS32ValueNoZero + } + return sizeFixedS32Value, appendFixedS32Value + case "varint": + if pointer { + return sizeVarintS32Ptr, appendVarintS32Ptr + } + if slice { + if packed { + return sizeVarintS32PackedSlice, appendVarintS32PackedSlice + } + return sizeVarintS32Slice, appendVarintS32Slice + } + if nozero { + return sizeVarintS32ValueNoZero, appendVarintS32ValueNoZero + } + return sizeVarintS32Value, appendVarintS32Value + case "zigzag32": + if pointer { + return sizeZigzag32Ptr, appendZigzag32Ptr + } + if slice { + if packed { + return sizeZigzag32PackedSlice, appendZigzag32PackedSlice + } + return sizeZigzag32Slice, appendZigzag32Slice + } + if nozero { + return sizeZigzag32ValueNoZero, appendZigzag32ValueNoZero + } + return sizeZigzag32Value, appendZigzag32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixed64Ptr, appendFixed64Ptr + } + if slice { + if packed { + return sizeFixed64PackedSlice, appendFixed64PackedSlice + } + return sizeFixed64Slice, appendFixed64Slice + } + if nozero { + return sizeFixed64ValueNoZero, appendFixed64ValueNoZero + } + return sizeFixed64Value, appendFixed64Value + case "varint": + if pointer { + return sizeVarint64Ptr, appendVarint64Ptr + } + if slice { + if packed { + return sizeVarint64PackedSlice, appendVarint64PackedSlice + } + return sizeVarint64Slice, appendVarint64Slice + } + if nozero { + return sizeVarint64ValueNoZero, appendVarint64ValueNoZero + } + return sizeVarint64Value, appendVarint64Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixedS64Ptr, appendFixedS64Ptr + } + if slice { + if packed { + return sizeFixedS64PackedSlice, appendFixedS64PackedSlice + } + return sizeFixedS64Slice, appendFixedS64Slice + } + if nozero { + return sizeFixedS64ValueNoZero, appendFixedS64ValueNoZero + } + return sizeFixedS64Value, appendFixedS64Value + case "varint": + if pointer { + return sizeVarintS64Ptr, appendVarintS64Ptr + } + if slice { + if packed { + return sizeVarintS64PackedSlice, appendVarintS64PackedSlice + } + return sizeVarintS64Slice, appendVarintS64Slice + } + if nozero { + return sizeVarintS64ValueNoZero, appendVarintS64ValueNoZero + } + return sizeVarintS64Value, appendVarintS64Value + case "zigzag64": + if pointer { + return sizeZigzag64Ptr, appendZigzag64Ptr + } + if slice { + if packed { + return sizeZigzag64PackedSlice, appendZigzag64PackedSlice + } + return sizeZigzag64Slice, appendZigzag64Slice + } + if nozero { + return sizeZigzag64ValueNoZero, appendZigzag64ValueNoZero + } + return sizeZigzag64Value, appendZigzag64Value + } + case reflect.Float32: + if pointer { + return sizeFloat32Ptr, appendFloat32Ptr + } + if slice { + if packed { + return sizeFloat32PackedSlice, appendFloat32PackedSlice + } + return sizeFloat32Slice, appendFloat32Slice + } + if nozero { + return sizeFloat32ValueNoZero, appendFloat32ValueNoZero + } + return sizeFloat32Value, appendFloat32Value + case reflect.Float64: + if pointer { + return sizeFloat64Ptr, appendFloat64Ptr + } + if slice { + if packed { + return sizeFloat64PackedSlice, appendFloat64PackedSlice + } + return sizeFloat64Slice, appendFloat64Slice + } + if nozero { + return sizeFloat64ValueNoZero, appendFloat64ValueNoZero + } + return sizeFloat64Value, appendFloat64Value + case reflect.String: + if validateUTF8 { + if pointer { + return sizeStringPtr, appendUTF8StringPtr + } + if slice { + return sizeStringSlice, appendUTF8StringSlice + } + if nozero { + return sizeStringValueNoZero, appendUTF8StringValueNoZero + } + return sizeStringValue, appendUTF8StringValue + } + if pointer { + return sizeStringPtr, appendStringPtr + } + if slice { + return sizeStringSlice, appendStringSlice + } + if nozero { + return sizeStringValueNoZero, appendStringValueNoZero + } + return sizeStringValue, appendStringValue + case reflect.Slice: + if slice { + return sizeBytesSlice, appendBytesSlice + } + if oneof { + // Oneof bytes field may also have "proto3" tag. + // We want to marshal it as a oneof field. Do this + // check before the proto3 check. + return sizeBytesOneof, appendBytesOneof + } + if proto3 { + return sizeBytes3, appendBytes3 + } + return sizeBytes, appendBytes + case reflect.Struct: + switch encoding { + case "group": + if slice { + return makeGroupSliceMarshaler(getMarshalInfo(t)) + } + return makeGroupMarshaler(getMarshalInfo(t)) + case "bytes": + if pointer { + if slice { + return makeMessageSliceMarshaler(getMarshalInfo(t)) + } + return makeMessageMarshaler(getMarshalInfo(t)) + } else { + if slice { + return makeMessageRefSliceMarshaler(getMarshalInfo(t)) + } + return makeMessageRefMarshaler(getMarshalInfo(t)) + } + } + } + panic(fmt.Sprintf("unknown or mismatched type: type: %v, wire type: %v", t, encoding)) +} + +// Below are functions to size/marshal a specific type of a field. +// They are stored in the field's info, and called by function pointers. +// They have type sizer or marshaler. + +func sizeFixed32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixed32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixed32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixedS32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixedS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixedS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFloat32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFloat32ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + return (4 + tagsize) * len(s) +} +func sizeFloat32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixed64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixed64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixed64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFixedS64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixedS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixedS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFloat64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFloat64ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + return (8 + tagsize) * len(s) +} +func sizeFloat64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeVarint32Value(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarint32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarint32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarint64Value(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + return SizeVarint(v) + tagsize +} +func sizeVarint64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return SizeVarint(v) + tagsize +} +func sizeVarint64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return SizeVarint(*p) + tagsize +} +func sizeVarint64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(v) + tagsize + } + return n +} +func sizeVarint64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize + } + return n +} +func sizeZigzag32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize + } + return n +} +func sizeZigzag64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeBoolValue(_ pointer, tagsize int) int { + return 1 + tagsize +} +func sizeBoolValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toBool() + if !v { + return 0 + } + return 1 + tagsize +} +func sizeBoolPtr(ptr pointer, tagsize int) int { + p := *ptr.toBoolPtr() + if p == nil { + return 0 + } + return 1 + tagsize +} +func sizeBoolSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + return (1 + tagsize) * len(s) +} +func sizeBoolPackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return 0 + } + return len(s) + SizeVarint(uint64(len(s))) + tagsize +} +func sizeStringValue(ptr pointer, tagsize int) int { + v := *ptr.toString() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toString() + if v == "" { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringPtr(ptr pointer, tagsize int) int { + p := *ptr.toStringPtr() + if p == nil { + return 0 + } + v := *p + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringSlice(ptr pointer, tagsize int) int { + s := *ptr.toStringSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} +func sizeBytes(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if v == nil { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytes3(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if len(v) == 0 { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesOneof(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesSlice(ptr pointer, tagsize int) int { + s := *ptr.toBytesSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} + +// appendFixed32 appends an encoded fixed32 to b. +func appendFixed32(b []byte, v uint32) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24)) + return b +} + +// appendFixed64 appends an encoded fixed64 to b. +func appendFixed64(b []byte, v uint64) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24), + byte(v>>32), + byte(v>>40), + byte(v>>48), + byte(v>>56)) + return b +} + +// appendVarint appends an encoded varint to b. +func appendVarint(b []byte, v uint64) []byte { + // TODO: make 1-byte (maybe 2-byte) case inline-able, once we + // have non-leaf inliner. + switch { + case v < 1<<7: + b = append(b, byte(v)) + case v < 1<<14: + b = append(b, + byte(v&0x7f|0x80), + byte(v>>7)) + case v < 1<<21: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte(v>>14)) + case v < 1<<28: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte(v>>21)) + case v < 1<<35: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte(v>>28)) + case v < 1<<42: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte(v>>35)) + case v < 1<<49: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte(v>>42)) + case v < 1<<56: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte(v>>49)) + case v < 1<<63: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte(v>>56)) + default: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte((v>>56)&0x7f|0x80), + 1) + } + return b +} + +func appendFixed32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, *p) + return b, nil +} +func appendFixed32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixed32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixedS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(*p)) + return b, nil +} +func appendFixedS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFixedS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFloat32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(*p)) + return b, nil +} +func appendFloat32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFloat32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFixed64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, *p) + return b, nil +} +func appendFixed64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixed64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixedS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(*p)) + return b, nil +} +func appendFixedS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFixedS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFloat64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(*p)) + return b, nil +} +func appendFloat64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendFloat64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendVarint32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarint32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, *p) + return b, nil +} +func appendVarint64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + } + return b, nil +} +func appendVarint64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, v) + } + return b, nil +} +func appendVarintS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendZigzag32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendZigzag64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendBoolValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + if !v { + return b, nil + } + b = appendVarint(b, wiretag) + b = append(b, 1) + return b, nil +} + +func appendBoolPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toBoolPtr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + if *p { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(len(s))) + for _, v := range s { + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + if v == "" { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toStringPtr() + if p == nil { + return b, nil + } + v := *p + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toStringSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} +func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + v := *ptr.toString() + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + v := *ptr.toString() + if v == "" { + return b, nil + } + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + p := *ptr.toStringPtr() + if p == nil { + return b, nil + } + v := *p + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + s := *ptr.toStringSlice() + for _, v := range s { + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if v == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytes3(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if len(v) == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesOneof(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBytesSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} + +// makeGroupMarshaler returns the sizer and marshaler for a group. +// u is the marshal info of the underlying message. +func makeGroupMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + return u.size(p) + 2*tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + var err error + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, p, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + return b, err + } +} + +// makeGroupSliceMarshaler returns the sizer and marshaler for a group slice. +// u is the marshal info of the underlying message. +func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + n += u.size(v) + 2*tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getPointerSlice() + var err error + var nerr nonFatal + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, v, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + if !nerr.Merge(err) { + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, nerr.E + } +} + +// makeMessageMarshaler returns the sizer and marshaler for a message field. +// u is the marshal info of the message. +func makeMessageMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + siz := u.size(p) + return siz + SizeVarint(uint64(siz)) + tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(p) + b = appendVarint(b, uint64(siz)) + return u.marshal(b, p, deterministic) + } +} + +// makeMessageSliceMarshaler returns the sizer and marshaler for a message slice. +// u is the marshal info of the message. +func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + siz := u.size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getPointerSlice() + var err error + var nerr nonFatal + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(v) + b = appendVarint(b, uint64(siz)) + b, err = u.marshal(b, v, deterministic) + + if !nerr.Merge(err) { + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, nerr.E + } +} + +// makeMapMarshaler returns the sizer and marshaler for a map field. +// f is the pointer to the reflect data structure of the field. +func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) { + // figure out key and value type + t := f.Type + keyType := t.Key() + valType := t.Elem() + tags := strings.Split(f.Tag.Get("protobuf"), ",") + keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",") + valTags := strings.Split(f.Tag.Get("protobuf_val"), ",") + stdOptions := false + for _, t := range tags { + if strings.HasPrefix(t, "customtype=") { + valTags = append(valTags, t) + } + if t == "stdtime" { + valTags = append(valTags, t) + stdOptions = true + } + if t == "stdduration" { + valTags = append(valTags, t) + stdOptions = true + } + if t == "wktptr" { + valTags = append(valTags, t) + } + } + keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map + valSizer, valMarshaler := typeMarshaler(valType, valTags, false, false) // don't omit zero value in map + keyWireTag := 1<<3 | wiretype(keyTags[0]) + valWireTag := 2<<3 | wiretype(valTags[0]) + + // We create an interface to get the addresses of the map key and value. + // If value is pointer-typed, the interface is a direct interface, the + // idata itself is the value. Otherwise, the idata is the pointer to the + // value. + // Key cannot be pointer-typed. + valIsPtr := valType.Kind() == reflect.Ptr + + // If value is a message with nested maps, calling + // valSizer in marshal may be quadratic. We should use + // cached version in marshal (but not in size). + // If value is not message type, we don't have size cache, + // but it cannot be nested either. Just use valSizer. + valCachedSizer := valSizer + if valIsPtr && !stdOptions && valType.Elem().Kind() == reflect.Struct { + u := getMarshalInfo(valType.Elem()) + valCachedSizer = func(ptr pointer, tagsize int) int { + // Same as message sizer, but use cache. + p := ptr.getPointer() + if p.isNil() { + return 0 + } + siz := u.cachedsize(p) + return siz + SizeVarint(uint64(siz)) + tagsize + } + } + return func(ptr pointer, tagsize int) int { + m := ptr.asPointerTo(t).Elem() // the map + n := 0 + for _, k := range m.MapKeys() { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value + siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, tag uint64, deterministic bool) ([]byte, error) { + m := ptr.asPointerTo(t).Elem() // the map + var err error + keys := m.MapKeys() + if len(keys) > 1 && deterministic { + sort.Sort(mapKeys(keys)) + } + + var nerr nonFatal + for _, k := range keys { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value + b = appendVarint(b, tag) + siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + b = appendVarint(b, uint64(siz)) + b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic) + if !nerr.Merge(err) { + return b, err + } + b, err = valMarshaler(b, vaddr, valWireTag, deterministic) + if err != ErrNil && !nerr.Merge(err) { // allow nil value in map + return b, err + } + } + return b, nerr.E + } +} + +// makeOneOfMarshaler returns the sizer and marshaler for a oneof field. +// fi is the marshal info of the field. +// f is the pointer to the reflect data structure of the field. +func makeOneOfMarshaler(fi *marshalFieldInfo, f *reflect.StructField) (sizer, marshaler) { + // Oneof field is an interface. We need to get the actual data type on the fly. + t := f.Type + return func(ptr pointer, _ int) int { + p := ptr.getInterfacePointer() + if p.isNil() { + return 0 + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + e := fi.oneofElems[telem] + return e.sizer(p, e.tagsize) + }, + func(b []byte, ptr pointer, _ uint64, deterministic bool) ([]byte, error) { + p := ptr.getInterfacePointer() + if p.isNil() { + return b, nil + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + if telem.Field(0).Type.Kind() == reflect.Ptr && p.getPointer().isNil() { + return b, errOneofHasNil + } + e := fi.oneofElems[telem] + return e.marshaler(b, p, e.wiretag, deterministic) + } +} + +// sizeExtensions computes the size of encoded data for a XXX_InternalExtensions field. +func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + n += len(e.enc) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, ei.tagsize) + } + mu.Unlock() + return n +} + +// appendExtensions marshals a XXX_InternalExtensions field to the end of byte slice b. +func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + var nerr nonFatal + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E + } + + // Sort the keys to provide a deterministic encoding. + // Not sure this is required, but the old code does it. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E +} + +// message set format is: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } + +// sizeMessageSet computes the size of encoded data for a XXX_InternalExtensions field +// in message set format (above). +func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + for id, e := range m { + n += 2 // start group, end group. tag = 1 (size=1) + n += SizeVarint(uint64(id)) + 1 // type_id, tag = 2 (size=1) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + siz := len(msgWithLen) + n += siz + 1 // message, tag = 3 (size=1) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, 1) // message, tag = 3 (size=1) + } + mu.Unlock() + return n +} + +// appendMessageSet marshals a XXX_InternalExtensions field in message set format (above) +// to the end of byte slice b. +func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + var nerr nonFatal + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for id, e := range m { + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + if !nerr.Merge(err) { + return b, err + } + b = append(b, 1<<3|WireEndGroup) + } + return b, nerr.E + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, id := range keys { + e := m[int32(id)] + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + b = append(b, 1<<3|WireEndGroup) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E +} + +// sizeV1Extensions computes the size of encoded data for a V1-API extension field. +func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int { + if m == nil { + return 0 + } + + n := 0 + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + n += len(e.enc) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, ei.tagsize) + } + return n +} + +// appendV1Extensions marshals a V1-API extension field to the end of byte slice b. +func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, deterministic bool) ([]byte, error) { + if m == nil { + return b, nil + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + var err error + var nerr nonFatal + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E +} + +// newMarshaler is the interface representing objects that can marshal themselves. +// +// This exists to support protoc-gen-go generated messages. +// The proto package will stop type-asserting to this interface in the future. +// +// DO NOT DEPEND ON THIS. +type newMarshaler interface { + XXX_Size() int + XXX_Marshal(b []byte, deterministic bool) ([]byte, error) +} + +// Size returns the encoded size of a protocol buffer message. +// This is the main entry point. +func Size(pb Message) int { + if m, ok := pb.(newMarshaler); ok { + return m.XXX_Size() + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + b, _ := m.Marshal() + return len(b) + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return 0 + } + var info InternalMessageInfo + return info.Size(pb) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, returning the data. +// This is the main entry point. +func Marshal(pb Message) ([]byte, error) { + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + b := make([]byte, 0, siz) + return m.XXX_Marshal(b, false) + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + return m.Marshal() + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return nil, ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + b := make([]byte, 0, siz) + return info.Marshal(b, pb, false) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, writing the result to the +// Buffer. +// This is an alternative entry point. It is not necessary to use +// a Buffer for most applications. +func (p *Buffer) Marshal(pb Message) error { + var err error + if p.deterministic { + if _, ok := pb.(Marshaler); ok { + return fmt.Errorf("proto: deterministic not supported by the Marshal method of %T", pb) + } + } + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + p.grow(siz) // make sure buf has enough capacity + p.buf, err = m.XXX_Marshal(p.buf, p.deterministic) + return err + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + var b []byte + b, err = m.Marshal() + p.buf = append(p.buf, b...) + return err + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + p.grow(siz) // make sure buf has enough capacity + p.buf, err = info.Marshal(p.buf, pb, p.deterministic) + return err +} + +// grow grows the buffer's capacity, if necessary, to guarantee space for +// another n bytes. After grow(n), at least n bytes can be written to the +// buffer without another allocation. +func (p *Buffer) grow(n int) { + need := len(p.buf) + n + if need <= cap(p.buf) { + return + } + newCap := len(p.buf) * 2 + if newCap < need { + newCap = need + } + p.buf = append(make([]byte, 0, newCap), p.buf...) +} diff --git a/vendor/github.com/gogo/protobuf/proto/table_marshal_gogo.go b/vendor/github.com/gogo/protobuf/proto/table_marshal_gogo.go new file mode 100644 index 000000000..997f57c1e --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/table_marshal_gogo.go @@ -0,0 +1,388 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2018, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "reflect" + "time" +) + +// makeMessageRefMarshaler differs a bit from makeMessageMarshaler +// It marshal a message T instead of a *T +func makeMessageRefMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + siz := u.size(ptr) + return siz + SizeVarint(uint64(siz)) + tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + b = appendVarint(b, wiretag) + siz := u.cachedsize(ptr) + b = appendVarint(b, uint64(siz)) + return u.marshal(b, ptr, deterministic) + } +} + +// makeMessageRefSliceMarshaler differs quite a lot from makeMessageSliceMarshaler +// It marshals a slice of messages []T instead of []*T +func makeMessageRefSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + e := elem.Interface() + v := toAddrPointer(&e, false) + siz := u.size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + var err, errreq error + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + e := elem.Interface() + v := toAddrPointer(&e, false) + b = appendVarint(b, wiretag) + siz := u.size(v) + b = appendVarint(b, uint64(siz)) + b, err = u.marshal(b, v, deterministic) + + if err != nil { + if _, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errreq == nil { + errreq = err + } + continue + } + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + + return b, errreq + } +} + +func makeCustomPtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + m := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(custom) + siz := m.Size() + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + m := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(custom) + siz := m.Size() + buf, err := m.Marshal() + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + return b, nil + } +} + +func makeCustomMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + m := ptr.asPointerTo(u.typ).Interface().(custom) + siz := m.Size() + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + m := ptr.asPointerTo(u.typ).Interface().(custom) + siz := m.Size() + buf, err := m.Marshal() + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + return b, nil + } +} + +func makeTimeMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*time.Time) + ts, err := timestampProto(*t) + if err != nil { + return 0 + } + siz := Size(ts) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*time.Time) + ts, err := timestampProto(*t) + if err != nil { + return nil, err + } + buf, err := Marshal(ts) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeTimePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Time) + ts, err := timestampProto(*t) + if err != nil { + return 0 + } + siz := Size(ts) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Time) + ts, err := timestampProto(*t) + if err != nil { + return nil, err + } + buf, err := Marshal(ts) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeTimeSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(time.Time) + ts, err := timestampProto(t) + if err != nil { + return 0 + } + siz := Size(ts) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(time.Time) + ts, err := timestampProto(t) + if err != nil { + return nil, err + } + siz := Size(ts) + buf, err := Marshal(ts) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeTimePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*time.Time) + ts, err := timestampProto(*t) + if err != nil { + return 0 + } + siz := Size(ts) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*time.Time) + ts, err := timestampProto(*t) + if err != nil { + return nil, err + } + siz := Size(ts) + buf, err := Marshal(ts) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeDurationMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + d := ptr.asPointerTo(u.typ).Interface().(*time.Duration) + dur := durationProto(*d) + siz := Size(dur) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + d := ptr.asPointerTo(u.typ).Interface().(*time.Duration) + dur := durationProto(*d) + buf, err := Marshal(dur) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeDurationPtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + d := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Duration) + dur := durationProto(*d) + siz := Size(dur) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + d := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Duration) + dur := durationProto(*d) + buf, err := Marshal(dur) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeDurationSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + d := elem.Interface().(time.Duration) + dur := durationProto(d) + siz := Size(dur) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + d := elem.Interface().(time.Duration) + dur := durationProto(d) + siz := Size(dur) + buf, err := Marshal(dur) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeDurationPtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + d := elem.Interface().(*time.Duration) + dur := durationProto(*d) + siz := Size(dur) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + d := elem.Interface().(*time.Duration) + dur := durationProto(*d) + siz := Size(dur) + buf, err := Marshal(dur) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} diff --git a/vendor/github.com/gogo/protobuf/proto/table_merge.go b/vendor/github.com/gogo/protobuf/proto/table_merge.go new file mode 100644 index 000000000..f520106e0 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/table_merge.go @@ -0,0 +1,657 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +import ( + "fmt" + "reflect" + "strings" + "sync" + "sync/atomic" +) + +// Merge merges the src message into dst. +// This assumes that dst and src of the same type and are non-nil. +func (a *InternalMessageInfo) Merge(dst, src Message) { + mi := atomicLoadMergeInfo(&a.merge) + if mi == nil { + mi = getMergeInfo(reflect.TypeOf(dst).Elem()) + atomicStoreMergeInfo(&a.merge, mi) + } + mi.merge(toPointer(&dst), toPointer(&src)) +} + +type mergeInfo struct { + typ reflect.Type + + initialized int32 // 0: only typ is valid, 1: everything is valid + lock sync.Mutex + + fields []mergeFieldInfo + unrecognized field // Offset of XXX_unrecognized +} + +type mergeFieldInfo struct { + field field // Offset of field, guaranteed to be valid + + // isPointer reports whether the value in the field is a pointer. + // This is true for the following situations: + // * Pointer to struct + // * Pointer to basic type (proto2 only) + // * Slice (first value in slice header is a pointer) + // * String (first value in string header is a pointer) + isPointer bool + + // basicWidth reports the width of the field assuming that it is directly + // embedded in the struct (as is the case for basic types in proto3). + // The possible values are: + // 0: invalid + // 1: bool + // 4: int32, uint32, float32 + // 8: int64, uint64, float64 + basicWidth int + + // Where dst and src are pointers to the types being merged. + merge func(dst, src pointer) +} + +var ( + mergeInfoMap = map[reflect.Type]*mergeInfo{} + mergeInfoLock sync.Mutex +) + +func getMergeInfo(t reflect.Type) *mergeInfo { + mergeInfoLock.Lock() + defer mergeInfoLock.Unlock() + mi := mergeInfoMap[t] + if mi == nil { + mi = &mergeInfo{typ: t} + mergeInfoMap[t] = mi + } + return mi +} + +// merge merges src into dst assuming they are both of type *mi.typ. +func (mi *mergeInfo) merge(dst, src pointer) { + if dst.isNil() { + panic("proto: nil destination") + } + if src.isNil() { + return // Nothing to do. + } + + if atomic.LoadInt32(&mi.initialized) == 0 { + mi.computeMergeInfo() + } + + for _, fi := range mi.fields { + sfp := src.offset(fi.field) + + // As an optimization, we can avoid the merge function call cost + // if we know for sure that the source will have no effect + // by checking if it is the zero value. + if unsafeAllowed { + if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string + continue + } + if fi.basicWidth > 0 { + switch { + case fi.basicWidth == 1 && !*sfp.toBool(): + continue + case fi.basicWidth == 4 && *sfp.toUint32() == 0: + continue + case fi.basicWidth == 8 && *sfp.toUint64() == 0: + continue + } + } + } + + dfp := dst.offset(fi.field) + fi.merge(dfp, sfp) + } + + // TODO: Make this faster? + out := dst.asPointerTo(mi.typ).Elem() + in := src.asPointerTo(mi.typ).Elem() + if emIn, err := extendable(in.Addr().Interface()); err == nil { + emOut, _ := extendable(out.Addr().Interface()) + mIn, muIn := emIn.extensionsRead() + if mIn != nil { + mOut := emOut.extensionsWrite() + muIn.Lock() + mergeExtension(mOut, mIn) + muIn.Unlock() + } + } + + if mi.unrecognized.IsValid() { + if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 { + *dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...) + } + } +} + +func (mi *mergeInfo) computeMergeInfo() { + mi.lock.Lock() + defer mi.lock.Unlock() + if mi.initialized != 0 { + return + } + t := mi.typ + n := t.NumField() + + props := GetProperties(t) + for i := 0; i < n; i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + + mfi := mergeFieldInfo{field: toField(&f)} + tf := f.Type + + // As an optimization, we can avoid the merge function call cost + // if we know for sure that the source will have no effect + // by checking if it is the zero value. + if unsafeAllowed { + switch tf.Kind() { + case reflect.Ptr, reflect.Slice, reflect.String: + // As a special case, we assume slices and strings are pointers + // since we know that the first field in the SliceSlice or + // StringHeader is a data pointer. + mfi.isPointer = true + case reflect.Bool: + mfi.basicWidth = 1 + case reflect.Int32, reflect.Uint32, reflect.Float32: + mfi.basicWidth = 4 + case reflect.Int64, reflect.Uint64, reflect.Float64: + mfi.basicWidth = 8 + } + } + + // Unwrap tf to get at its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic("both pointer and slice for basic type in " + tf.Name()) + } + + switch tf.Kind() { + case reflect.Int32: + switch { + case isSlice: // E.g., []int32 + mfi.merge = func(dst, src pointer) { + // NOTE: toInt32Slice is not defined (see pointer_reflect.go). + /* + sfsp := src.toInt32Slice() + if *sfsp != nil { + dfsp := dst.toInt32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []int64{} + } + } + */ + sfs := src.getInt32Slice() + if sfs != nil { + dfs := dst.getInt32Slice() + dfs = append(dfs, sfs...) + if dfs == nil { + dfs = []int32{} + } + dst.setInt32Slice(dfs) + } + } + case isPointer: // E.g., *int32 + mfi.merge = func(dst, src pointer) { + // NOTE: toInt32Ptr is not defined (see pointer_reflect.go). + /* + sfpp := src.toInt32Ptr() + if *sfpp != nil { + dfpp := dst.toInt32Ptr() + if *dfpp == nil { + *dfpp = Int32(**sfpp) + } else { + **dfpp = **sfpp + } + } + */ + sfp := src.getInt32Ptr() + if sfp != nil { + dfp := dst.getInt32Ptr() + if dfp == nil { + dst.setInt32Ptr(*sfp) + } else { + *dfp = *sfp + } + } + } + default: // E.g., int32 + mfi.merge = func(dst, src pointer) { + if v := *src.toInt32(); v != 0 { + *dst.toInt32() = v + } + } + } + case reflect.Int64: + switch { + case isSlice: // E.g., []int64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toInt64Slice() + if *sfsp != nil { + dfsp := dst.toInt64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []int64{} + } + } + } + case isPointer: // E.g., *int64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toInt64Ptr() + if *sfpp != nil { + dfpp := dst.toInt64Ptr() + if *dfpp == nil { + *dfpp = Int64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., int64 + mfi.merge = func(dst, src pointer) { + if v := *src.toInt64(); v != 0 { + *dst.toInt64() = v + } + } + } + case reflect.Uint32: + switch { + case isSlice: // E.g., []uint32 + mfi.merge = func(dst, src pointer) { + sfsp := src.toUint32Slice() + if *sfsp != nil { + dfsp := dst.toUint32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []uint32{} + } + } + } + case isPointer: // E.g., *uint32 + mfi.merge = func(dst, src pointer) { + sfpp := src.toUint32Ptr() + if *sfpp != nil { + dfpp := dst.toUint32Ptr() + if *dfpp == nil { + *dfpp = Uint32(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., uint32 + mfi.merge = func(dst, src pointer) { + if v := *src.toUint32(); v != 0 { + *dst.toUint32() = v + } + } + } + case reflect.Uint64: + switch { + case isSlice: // E.g., []uint64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toUint64Slice() + if *sfsp != nil { + dfsp := dst.toUint64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []uint64{} + } + } + } + case isPointer: // E.g., *uint64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toUint64Ptr() + if *sfpp != nil { + dfpp := dst.toUint64Ptr() + if *dfpp == nil { + *dfpp = Uint64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., uint64 + mfi.merge = func(dst, src pointer) { + if v := *src.toUint64(); v != 0 { + *dst.toUint64() = v + } + } + } + case reflect.Float32: + switch { + case isSlice: // E.g., []float32 + mfi.merge = func(dst, src pointer) { + sfsp := src.toFloat32Slice() + if *sfsp != nil { + dfsp := dst.toFloat32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []float32{} + } + } + } + case isPointer: // E.g., *float32 + mfi.merge = func(dst, src pointer) { + sfpp := src.toFloat32Ptr() + if *sfpp != nil { + dfpp := dst.toFloat32Ptr() + if *dfpp == nil { + *dfpp = Float32(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., float32 + mfi.merge = func(dst, src pointer) { + if v := *src.toFloat32(); v != 0 { + *dst.toFloat32() = v + } + } + } + case reflect.Float64: + switch { + case isSlice: // E.g., []float64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toFloat64Slice() + if *sfsp != nil { + dfsp := dst.toFloat64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []float64{} + } + } + } + case isPointer: // E.g., *float64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toFloat64Ptr() + if *sfpp != nil { + dfpp := dst.toFloat64Ptr() + if *dfpp == nil { + *dfpp = Float64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., float64 + mfi.merge = func(dst, src pointer) { + if v := *src.toFloat64(); v != 0 { + *dst.toFloat64() = v + } + } + } + case reflect.Bool: + switch { + case isSlice: // E.g., []bool + mfi.merge = func(dst, src pointer) { + sfsp := src.toBoolSlice() + if *sfsp != nil { + dfsp := dst.toBoolSlice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []bool{} + } + } + } + case isPointer: // E.g., *bool + mfi.merge = func(dst, src pointer) { + sfpp := src.toBoolPtr() + if *sfpp != nil { + dfpp := dst.toBoolPtr() + if *dfpp == nil { + *dfpp = Bool(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., bool + mfi.merge = func(dst, src pointer) { + if v := *src.toBool(); v { + *dst.toBool() = v + } + } + } + case reflect.String: + switch { + case isSlice: // E.g., []string + mfi.merge = func(dst, src pointer) { + sfsp := src.toStringSlice() + if *sfsp != nil { + dfsp := dst.toStringSlice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []string{} + } + } + } + case isPointer: // E.g., *string + mfi.merge = func(dst, src pointer) { + sfpp := src.toStringPtr() + if *sfpp != nil { + dfpp := dst.toStringPtr() + if *dfpp == nil { + *dfpp = String(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., string + mfi.merge = func(dst, src pointer) { + if v := *src.toString(); v != "" { + *dst.toString() = v + } + } + } + case reflect.Slice: + isProto3 := props.Prop[i].proto3 + switch { + case isPointer: + panic("bad pointer in byte slice case in " + tf.Name()) + case tf.Elem().Kind() != reflect.Uint8: + panic("bad element kind in byte slice case in " + tf.Name()) + case isSlice: // E.g., [][]byte + mfi.merge = func(dst, src pointer) { + sbsp := src.toBytesSlice() + if *sbsp != nil { + dbsp := dst.toBytesSlice() + for _, sb := range *sbsp { + if sb == nil { + *dbsp = append(*dbsp, nil) + } else { + *dbsp = append(*dbsp, append([]byte{}, sb...)) + } + } + if *dbsp == nil { + *dbsp = [][]byte{} + } + } + } + default: // E.g., []byte + mfi.merge = func(dst, src pointer) { + sbp := src.toBytes() + if *sbp != nil { + dbp := dst.toBytes() + if !isProto3 || len(*sbp) > 0 { + *dbp = append([]byte{}, *sbp...) + } + } + } + } + case reflect.Struct: + switch { + case !isPointer: + mergeInfo := getMergeInfo(tf) + mfi.merge = func(dst, src pointer) { + mergeInfo.merge(dst, src) + } + case isSlice: // E.g., []*pb.T + mergeInfo := getMergeInfo(tf) + mfi.merge = func(dst, src pointer) { + sps := src.getPointerSlice() + if sps != nil { + dps := dst.getPointerSlice() + for _, sp := range sps { + var dp pointer + if !sp.isNil() { + dp = valToPointer(reflect.New(tf)) + mergeInfo.merge(dp, sp) + } + dps = append(dps, dp) + } + if dps == nil { + dps = []pointer{} + } + dst.setPointerSlice(dps) + } + } + default: // E.g., *pb.T + mergeInfo := getMergeInfo(tf) + mfi.merge = func(dst, src pointer) { + sp := src.getPointer() + if !sp.isNil() { + dp := dst.getPointer() + if dp.isNil() { + dp = valToPointer(reflect.New(tf)) + dst.setPointer(dp) + } + mergeInfo.merge(dp, sp) + } + } + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic("bad pointer or slice in map case in " + tf.Name()) + default: // E.g., map[K]V + mfi.merge = func(dst, src pointer) { + sm := src.asPointerTo(tf).Elem() + if sm.Len() == 0 { + return + } + dm := dst.asPointerTo(tf).Elem() + if dm.IsNil() { + dm.Set(reflect.MakeMap(tf)) + } + + switch tf.Elem().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + val = reflect.ValueOf(Clone(val.Interface().(Message))) + dm.SetMapIndex(key, val) + } + case reflect.Slice: // E.g. Bytes type (e.g., []byte) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) + dm.SetMapIndex(key, val) + } + default: // Basic type (e.g., string) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + dm.SetMapIndex(key, val) + } + } + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic("bad pointer or slice in interface case in " + tf.Name()) + default: // E.g., interface{} + // TODO: Make this faster? + mfi.merge = func(dst, src pointer) { + su := src.asPointerTo(tf).Elem() + if !su.IsNil() { + du := dst.asPointerTo(tf).Elem() + typ := su.Elem().Type() + if du.IsNil() || du.Elem().Type() != typ { + du.Set(reflect.New(typ.Elem())) // Initialize interface if empty + } + sv := su.Elem().Elem().Field(0) + if sv.Kind() == reflect.Ptr && sv.IsNil() { + return + } + dv := du.Elem().Elem().Field(0) + if dv.Kind() == reflect.Ptr && dv.IsNil() { + dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty + } + switch sv.Type().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + Merge(dv.Interface().(Message), sv.Interface().(Message)) + case reflect.Slice: // E.g. Bytes type (e.g., []byte) + dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...))) + default: // Basic type (e.g., string) + dv.Set(sv) + } + } + } + } + default: + panic(fmt.Sprintf("merger not found for type:%s", tf)) + } + mi.fields = append(mi.fields, mfi) + } + + mi.unrecognized = invalidField + if f, ok := t.FieldByName("XXX_unrecognized"); ok { + if f.Type != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + mi.unrecognized = toField(&f) + } + + atomic.StoreInt32(&mi.initialized, 1) +} diff --git a/vendor/github.com/gogo/protobuf/proto/table_unmarshal.go b/vendor/github.com/gogo/protobuf/proto/table_unmarshal.go new file mode 100644 index 000000000..bb2622f28 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/table_unmarshal.go @@ -0,0 +1,2245 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +import ( + "errors" + "fmt" + "io" + "math" + "reflect" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// Unmarshal is the entry point from the generated .pb.go files. +// This function is not intended to be used by non-generated code. +// This function is not subject to any compatibility guarantee. +// msg contains a pointer to a protocol buffer struct. +// b is the data to be unmarshaled into the protocol buffer. +// a is a pointer to a place to store cached unmarshal information. +func (a *InternalMessageInfo) Unmarshal(msg Message, b []byte) error { + // Load the unmarshal information for this message type. + // The atomic load ensures memory consistency. + u := atomicLoadUnmarshalInfo(&a.unmarshal) + if u == nil { + // Slow path: find unmarshal info for msg, update a with it. + u = getUnmarshalInfo(reflect.TypeOf(msg).Elem()) + atomicStoreUnmarshalInfo(&a.unmarshal, u) + } + // Then do the unmarshaling. + err := u.unmarshal(toPointer(&msg), b) + return err +} + +type unmarshalInfo struct { + typ reflect.Type // type of the protobuf struct + + // 0 = only typ field is initialized + // 1 = completely initialized + initialized int32 + lock sync.Mutex // prevents double initialization + dense []unmarshalFieldInfo // fields indexed by tag # + sparse map[uint64]unmarshalFieldInfo // fields indexed by tag # + reqFields []string // names of required fields + reqMask uint64 // 1< 0 { + // Read tag and wire type. + // Special case 1 and 2 byte varints. + var x uint64 + if b[0] < 128 { + x = uint64(b[0]) + b = b[1:] + } else if len(b) >= 2 && b[1] < 128 { + x = uint64(b[0]&0x7f) + uint64(b[1])<<7 + b = b[2:] + } else { + var n int + x, n = decodeVarint(b) + if n == 0 { + return io.ErrUnexpectedEOF + } + b = b[n:] + } + tag := x >> 3 + wire := int(x) & 7 + + // Dispatch on the tag to one of the unmarshal* functions below. + var f unmarshalFieldInfo + if tag < uint64(len(u.dense)) { + f = u.dense[tag] + } else { + f = u.sparse[tag] + } + if fn := f.unmarshal; fn != nil { + var err error + b, err = fn(b, m.offset(f.field), wire) + if err == nil { + reqMask |= f.reqMask + continue + } + if r, ok := err.(*RequiredNotSetError); ok { + // Remember this error, but keep parsing. We need to produce + // a full parse even if a required field is missing. + if errLater == nil { + errLater = r + } + reqMask |= f.reqMask + continue + } + if err != errInternalBadWireType { + if err == errInvalidUTF8 { + if errLater == nil { + fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name + errLater = &invalidUTF8Error{fullName} + } + continue + } + return err + } + // Fragments with bad wire type are treated as unknown fields. + } + + // Unknown tag. + if !u.unrecognized.IsValid() { + // Don't keep unrecognized data; just skip it. + var err error + b, err = skipField(b, wire) + if err != nil { + return err + } + continue + } + // Keep unrecognized data around. + // maybe in extensions, maybe in the unrecognized field. + z := m.offset(u.unrecognized).toBytes() + var emap map[int32]Extension + var e Extension + for _, r := range u.extensionRanges { + if uint64(r.Start) <= tag && tag <= uint64(r.End) { + if u.extensions.IsValid() { + mp := m.offset(u.extensions).toExtensions() + emap = mp.extensionsWrite() + e = emap[int32(tag)] + z = &e.enc + break + } + if u.oldExtensions.IsValid() { + p := m.offset(u.oldExtensions).toOldExtensions() + emap = *p + if emap == nil { + emap = map[int32]Extension{} + *p = emap + } + e = emap[int32(tag)] + z = &e.enc + break + } + if u.bytesExtensions.IsValid() { + z = m.offset(u.bytesExtensions).toBytes() + break + } + panic("no extensions field available") + } + } + // Use wire type to skip data. + var err error + b0 := b + b, err = skipField(b, wire) + if err != nil { + return err + } + *z = encodeVarint(*z, tag<<3|uint64(wire)) + *z = append(*z, b0[:len(b0)-len(b)]...) + + if emap != nil { + emap[int32(tag)] = e + } + } + if reqMask != u.reqMask && errLater == nil { + // A required field of this message is missing. + for _, n := range u.reqFields { + if reqMask&1 == 0 { + errLater = &RequiredNotSetError{n} + } + reqMask >>= 1 + } + } + return errLater +} + +// computeUnmarshalInfo fills in u with information for use +// in unmarshaling protocol buffers of type u.typ. +func (u *unmarshalInfo) computeUnmarshalInfo() { + u.lock.Lock() + defer u.lock.Unlock() + if u.initialized != 0 { + return + } + t := u.typ + n := t.NumField() + + // Set up the "not found" value for the unrecognized byte buffer. + // This is the default for proto3. + u.unrecognized = invalidField + u.extensions = invalidField + u.oldExtensions = invalidField + u.bytesExtensions = invalidField + + // List of the generated type and offset for each oneof field. + type oneofField struct { + ityp reflect.Type // interface type of oneof field + field field // offset in containing message + } + var oneofFields []oneofField + + for i := 0; i < n; i++ { + f := t.Field(i) + if f.Name == "XXX_unrecognized" { + // The byte slice used to hold unrecognized input is special. + if f.Type != reflect.TypeOf(([]byte)(nil)) { + panic("bad type for XXX_unrecognized field: " + f.Type.Name()) + } + u.unrecognized = toField(&f) + continue + } + if f.Name == "XXX_InternalExtensions" { + // Ditto here. + if f.Type != reflect.TypeOf(XXX_InternalExtensions{}) { + panic("bad type for XXX_InternalExtensions field: " + f.Type.Name()) + } + u.extensions = toField(&f) + if f.Tag.Get("protobuf_messageset") == "1" { + u.isMessageSet = true + } + continue + } + if f.Name == "XXX_extensions" { + // An older form of the extensions field. + if f.Type == reflect.TypeOf((map[int32]Extension)(nil)) { + u.oldExtensions = toField(&f) + continue + } else if f.Type == reflect.TypeOf(([]byte)(nil)) { + u.bytesExtensions = toField(&f) + continue + } + panic("bad type for XXX_extensions field: " + f.Type.Name()) + } + if f.Name == "XXX_NoUnkeyedLiteral" || f.Name == "XXX_sizecache" { + continue + } + + oneof := f.Tag.Get("protobuf_oneof") + if oneof != "" { + oneofFields = append(oneofFields, oneofField{f.Type, toField(&f)}) + // The rest of oneof processing happens below. + continue + } + + tags := f.Tag.Get("protobuf") + tagArray := strings.Split(tags, ",") + if len(tagArray) < 2 { + panic("protobuf tag not enough fields in " + t.Name() + "." + f.Name + ": " + tags) + } + tag, err := strconv.Atoi(tagArray[1]) + if err != nil { + panic("protobuf tag field not an integer: " + tagArray[1]) + } + + name := "" + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + } + + // Extract unmarshaling function from the field (its type and tags). + unmarshal := fieldUnmarshaler(&f) + + // Required field? + var reqMask uint64 + if tagArray[2] == "req" { + bit := len(u.reqFields) + u.reqFields = append(u.reqFields, name) + reqMask = uint64(1) << uint(bit) + // TODO: if we have more than 64 required fields, we end up + // not verifying that all required fields are present. + // Fix this, perhaps using a count of required fields? + } + + // Store the info in the correct slot in the message. + u.setTag(tag, toField(&f), unmarshal, reqMask, name) + } + + // Find any types associated with oneof fields. + // TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it? + fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs") + // gogo: len(oneofFields) > 0 is needed for embedded oneof messages, without a marshaler and unmarshaler + if fn.IsValid() && len(oneofFields) > 0 { + res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{} + for i := res.Len() - 1; i >= 0; i-- { + v := res.Index(i) // interface{} + tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X + typ := tptr.Elem() // Msg_X + + f := typ.Field(0) // oneof implementers have one field + baseUnmarshal := fieldUnmarshaler(&f) + tags := strings.Split(f.Tag.Get("protobuf"), ",") + fieldNum, err := strconv.Atoi(tags[1]) + if err != nil { + panic("protobuf tag field not an integer: " + tags[1]) + } + var name string + for _, tag := range tags { + if strings.HasPrefix(tag, "name=") { + name = strings.TrimPrefix(tag, "name=") + break + } + } + + // Find the oneof field that this struct implements. + // Might take O(n^2) to process all of the oneofs, but who cares. + for _, of := range oneofFields { + if tptr.Implements(of.ityp) { + // We have found the corresponding interface for this struct. + // That lets us know where this struct should be stored + // when we encounter it during unmarshaling. + unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) + u.setTag(fieldNum, of.field, unmarshal, 0, name) + } + } + } + } + + // Get extension ranges, if any. + fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") + if fn.IsValid() { + if !u.extensions.IsValid() && !u.oldExtensions.IsValid() && !u.bytesExtensions.IsValid() { + panic("a message with extensions, but no extensions field in " + t.Name()) + } + u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange) + } + + // Explicitly disallow tag 0. This will ensure we flag an error + // when decoding a buffer of all zeros. Without this code, we + // would decode and skip an all-zero buffer of even length. + // [0 0] is [tag=0/wiretype=varint varint-encoded-0]. + u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) { + return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w) + }, 0, "") + + // Set mask for required field check. + u.reqMask = uint64(1)<= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here? + for len(u.dense) <= tag { + u.dense = append(u.dense, unmarshalFieldInfo{}) + } + u.dense[tag] = i + return + } + if u.sparse == nil { + u.sparse = map[uint64]unmarshalFieldInfo{} + } + u.sparse[uint64(tag)] = i +} + +// fieldUnmarshaler returns an unmarshaler for the given field. +func fieldUnmarshaler(f *reflect.StructField) unmarshaler { + if f.Type.Kind() == reflect.Map { + return makeUnmarshalMap(f) + } + return typeUnmarshaler(f.Type, f.Tag.Get("protobuf")) +} + +// typeUnmarshaler returns an unmarshaler for the given field type / field tag pair. +func typeUnmarshaler(t reflect.Type, tags string) unmarshaler { + tagArray := strings.Split(tags, ",") + encoding := tagArray[0] + name := "unknown" + ctype := false + isTime := false + isDuration := false + isWktPointer := false + proto3 := false + validateUTF8 := true + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + if tag == "proto3" { + proto3 = true + } + if strings.HasPrefix(tag, "customtype=") { + ctype = true + } + if tag == "stdtime" { + isTime = true + } + if tag == "stdduration" { + isDuration = true + } + if tag == "wktptr" { + isWktPointer = true + } + } + validateUTF8 = validateUTF8 && proto3 + + // Figure out packaging (pointer, slice, or both) + slice := false + pointer := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + if ctype { + if reflect.PtrTo(t).Implements(customType) { + if slice { + return makeUnmarshalCustomSlice(getUnmarshalInfo(t), name) + } + if pointer { + return makeUnmarshalCustomPtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalCustom(getUnmarshalInfo(t), name) + } else { + panic(fmt.Sprintf("custom type: type: %v, does not implement the proto.custom interface", t)) + } + } + + if isTime { + if pointer { + if slice { + return makeUnmarshalTimePtrSlice(getUnmarshalInfo(t), name) + } + return makeUnmarshalTimePtr(getUnmarshalInfo(t), name) + } + if slice { + return makeUnmarshalTimeSlice(getUnmarshalInfo(t), name) + } + return makeUnmarshalTime(getUnmarshalInfo(t), name) + } + + if isDuration { + if pointer { + if slice { + return makeUnmarshalDurationPtrSlice(getUnmarshalInfo(t), name) + } + return makeUnmarshalDurationPtr(getUnmarshalInfo(t), name) + } + if slice { + return makeUnmarshalDurationSlice(getUnmarshalInfo(t), name) + } + return makeUnmarshalDuration(getUnmarshalInfo(t), name) + } + + if isWktPointer { + switch t.Kind() { + case reflect.Float64: + if pointer { + if slice { + return makeStdDoubleValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdDoubleValuePtrUnmarshaler(getUnmarshalInfo(t), name) + } + if slice { + return makeStdDoubleValueSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdDoubleValueUnmarshaler(getUnmarshalInfo(t), name) + case reflect.Float32: + if pointer { + if slice { + return makeStdFloatValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdFloatValuePtrUnmarshaler(getUnmarshalInfo(t), name) + } + if slice { + return makeStdFloatValueSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdFloatValueUnmarshaler(getUnmarshalInfo(t), name) + case reflect.Int64: + if pointer { + if slice { + return makeStdInt64ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdInt64ValuePtrUnmarshaler(getUnmarshalInfo(t), name) + } + if slice { + return makeStdInt64ValueSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdInt64ValueUnmarshaler(getUnmarshalInfo(t), name) + case reflect.Uint64: + if pointer { + if slice { + return makeStdUInt64ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdUInt64ValuePtrUnmarshaler(getUnmarshalInfo(t), name) + } + if slice { + return makeStdUInt64ValueSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdUInt64ValueUnmarshaler(getUnmarshalInfo(t), name) + case reflect.Int32: + if pointer { + if slice { + return makeStdInt32ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdInt32ValuePtrUnmarshaler(getUnmarshalInfo(t), name) + } + if slice { + return makeStdInt32ValueSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdInt32ValueUnmarshaler(getUnmarshalInfo(t), name) + case reflect.Uint32: + if pointer { + if slice { + return makeStdUInt32ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdUInt32ValuePtrUnmarshaler(getUnmarshalInfo(t), name) + } + if slice { + return makeStdUInt32ValueSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdUInt32ValueUnmarshaler(getUnmarshalInfo(t), name) + case reflect.Bool: + if pointer { + if slice { + return makeStdBoolValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdBoolValuePtrUnmarshaler(getUnmarshalInfo(t), name) + } + if slice { + return makeStdBoolValueSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdBoolValueUnmarshaler(getUnmarshalInfo(t), name) + case reflect.String: + if pointer { + if slice { + return makeStdStringValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdStringValuePtrUnmarshaler(getUnmarshalInfo(t), name) + } + if slice { + return makeStdStringValueSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdStringValueUnmarshaler(getUnmarshalInfo(t), name) + case uint8SliceType: + if pointer { + if slice { + return makeStdBytesValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdBytesValuePtrUnmarshaler(getUnmarshalInfo(t), name) + } + if slice { + return makeStdBytesValueSliceUnmarshaler(getUnmarshalInfo(t), name) + } + return makeStdBytesValueUnmarshaler(getUnmarshalInfo(t), name) + default: + panic(fmt.Sprintf("unknown wktpointer type %#v", t)) + } + } + + // We'll never have both pointer and slice for basic types. + if pointer && slice && t.Kind() != reflect.Struct { + panic("both pointer and slice for basic type in " + t.Name()) + } + + switch t.Kind() { + case reflect.Bool: + if pointer { + return unmarshalBoolPtr + } + if slice { + return unmarshalBoolSlice + } + return unmarshalBoolValue + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixedS32Ptr + } + if slice { + return unmarshalFixedS32Slice + } + return unmarshalFixedS32Value + case "varint": + // this could be int32 or enum + if pointer { + return unmarshalInt32Ptr + } + if slice { + return unmarshalInt32Slice + } + return unmarshalInt32Value + case "zigzag32": + if pointer { + return unmarshalSint32Ptr + } + if slice { + return unmarshalSint32Slice + } + return unmarshalSint32Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixedS64Ptr + } + if slice { + return unmarshalFixedS64Slice + } + return unmarshalFixedS64Value + case "varint": + if pointer { + return unmarshalInt64Ptr + } + if slice { + return unmarshalInt64Slice + } + return unmarshalInt64Value + case "zigzag64": + if pointer { + return unmarshalSint64Ptr + } + if slice { + return unmarshalSint64Slice + } + return unmarshalSint64Value + } + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixed32Ptr + } + if slice { + return unmarshalFixed32Slice + } + return unmarshalFixed32Value + case "varint": + if pointer { + return unmarshalUint32Ptr + } + if slice { + return unmarshalUint32Slice + } + return unmarshalUint32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixed64Ptr + } + if slice { + return unmarshalFixed64Slice + } + return unmarshalFixed64Value + case "varint": + if pointer { + return unmarshalUint64Ptr + } + if slice { + return unmarshalUint64Slice + } + return unmarshalUint64Value + } + case reflect.Float32: + if pointer { + return unmarshalFloat32Ptr + } + if slice { + return unmarshalFloat32Slice + } + return unmarshalFloat32Value + case reflect.Float64: + if pointer { + return unmarshalFloat64Ptr + } + if slice { + return unmarshalFloat64Slice + } + return unmarshalFloat64Value + case reflect.Map: + panic("map type in typeUnmarshaler in " + t.Name()) + case reflect.Slice: + if pointer { + panic("bad pointer in slice case in " + t.Name()) + } + if slice { + return unmarshalBytesSlice + } + return unmarshalBytesValue + case reflect.String: + if validateUTF8 { + if pointer { + return unmarshalUTF8StringPtr + } + if slice { + return unmarshalUTF8StringSlice + } + return unmarshalUTF8StringValue + } + if pointer { + return unmarshalStringPtr + } + if slice { + return unmarshalStringSlice + } + return unmarshalStringValue + case reflect.Struct: + // message or group field + if !pointer { + switch encoding { + case "bytes": + if slice { + return makeUnmarshalMessageSlice(getUnmarshalInfo(t), name) + } + return makeUnmarshalMessage(getUnmarshalInfo(t), name) + } + } + switch encoding { + case "bytes": + if slice { + return makeUnmarshalMessageSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalMessagePtr(getUnmarshalInfo(t), name) + case "group": + if slice { + return makeUnmarshalGroupSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalGroupPtr(getUnmarshalInfo(t), name) + } + } + panic(fmt.Sprintf("unmarshaler not found type:%s encoding:%s", t, encoding)) +} + +// Below are all the unmarshalers for individual fields of various types. + +func unmarshalInt64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64() = v + return b, nil +} + +func unmarshalInt64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalInt64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalSint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64() = v + return b, nil +} + +func unmarshalSint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalSint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalUint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64() = v + return b, nil +} + +func unmarshalUint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64Ptr() = &v + return b, nil +} + +func unmarshalUint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalInt32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + *f.toInt32() = v + return b, nil +} + +func unmarshalInt32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalInt32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalSint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + *f.toInt32() = v + return b, nil +} + +func unmarshalSint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalSint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalUint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32() = v + return b, nil +} + +func unmarshalUint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32Ptr() = &v + return b, nil +} + +func unmarshalUint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalFixed64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64() = v + return b[8:], nil +} + +func unmarshalFixed64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixed64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixedS64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64() = v + return b[8:], nil +} + +func unmarshalFixedS64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixedS64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixed32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32() = v + return b[4:], nil +} + +func unmarshalFixed32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32Ptr() = &v + return b[4:], nil +} + +func unmarshalFixed32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalFixedS32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + *f.toInt32() = v + return b[4:], nil +} + +func unmarshalFixedS32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.setInt32Ptr(v) + return b[4:], nil +} + +func unmarshalFixedS32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + return b[4:], nil +} + +func unmarshalBoolValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + // Note: any length varint is allowed, even though any sane + // encoder will use one byte. + // See https://github.com/golang/protobuf/issues/76 + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + // TODO: check if x>1? Tests seem to indicate no. + v := x != 0 + *f.toBool() = v + return b[n:], nil +} + +func unmarshalBoolPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + *f.toBoolPtr() = &v + return b[n:], nil +} + +func unmarshalBoolSlice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + b = b[n:] + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + return b[n:], nil +} + +func unmarshalFloat64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64() = v + return b[8:], nil +} + +func unmarshalFloat64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64Ptr() = &v + return b[8:], nil +} + +func unmarshalFloat64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFloat32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32() = v + return b[4:], nil +} + +func unmarshalFloat32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32Ptr() = &v + return b[4:], nil +} + +func unmarshalFloat32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + *f.toString() = v + return b[x:], nil +} + +func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + *f.toStringPtr() = &v + return b[x:], nil +} + +func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + s := f.toStringSlice() + *s = append(*s, v) + return b[x:], nil +} + +func unmarshalUTF8StringValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + *f.toString() = v + if !utf8.ValidString(v) { + return b[x:], errInvalidUTF8 + } + return b[x:], nil +} + +func unmarshalUTF8StringPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + *f.toStringPtr() = &v + if !utf8.ValidString(v) { + return b[x:], errInvalidUTF8 + } + return b[x:], nil +} + +func unmarshalUTF8StringSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + s := f.toStringSlice() + *s = append(*s, v) + if !utf8.ValidString(v) { + return b[x:], errInvalidUTF8 + } + return b[x:], nil +} + +var emptyBuf [0]byte + +func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // The use of append here is a trick which avoids the zeroing + // that would be required if we used a make/copy pair. + // We append to emptyBuf instead of nil because we want + // a non-nil result even when the length is 0. + v := append(emptyBuf[:], b[:x]...) + *f.toBytes() = v + return b[x:], nil +} + +func unmarshalBytesSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := append(emptyBuf[:], b[:x]...) + s := f.toBytesSlice() + *s = append(*s, v) + return b[x:], nil +} + +func makeUnmarshalMessagePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // First read the message field to see if something is there. + // The semantics of multiple submessages are weird. Instead of + // the last one winning (as it is for all other fields), multiple + // submessages are merged. + v := f.getPointer() + if v.isNil() { + v = valToPointer(reflect.New(sub.typ)) + f.setPointer(v) + } + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + return b[x:], err + } +} + +func makeUnmarshalMessageSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := valToPointer(reflect.New(sub.typ)) + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + f.appendPointer(v) + return b[x:], err + } +} + +func makeUnmarshalGroupPtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + return nil, io.ErrUnexpectedEOF + } + v := f.getPointer() + if v.isNil() { + v = valToPointer(reflect.New(sub.typ)) + f.setPointer(v) + } + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + return b[y:], err + } +} + +func makeUnmarshalGroupSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + return nil, io.ErrUnexpectedEOF + } + v := valToPointer(reflect.New(sub.typ)) + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + f.appendPointer(v) + return b[y:], err + } +} + +func makeUnmarshalMap(f *reflect.StructField) unmarshaler { + t := f.Type + kt := t.Key() + vt := t.Elem() + tagArray := strings.Split(f.Tag.Get("protobuf"), ",") + valTags := strings.Split(f.Tag.Get("protobuf_val"), ",") + for _, t := range tagArray { + if strings.HasPrefix(t, "customtype=") { + valTags = append(valTags, t) + } + if t == "stdtime" { + valTags = append(valTags, t) + } + if t == "stdduration" { + valTags = append(valTags, t) + } + if t == "wktptr" { + valTags = append(valTags, t) + } + } + unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key")) + unmarshalVal := typeUnmarshaler(vt, strings.Join(valTags, ",")) + return func(b []byte, f pointer, w int) ([]byte, error) { + // The map entry is a submessage. Figure out how big it is. + if w != WireBytes { + return nil, fmt.Errorf("proto: bad wiretype for map field: got %d want %d", w, WireBytes) + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + r := b[x:] // unused data to return + b = b[:x] // data for map entry + + // Note: we could use #keys * #values ~= 200 functions + // to do map decoding without reflection. Probably not worth it. + // Maps will be somewhat slow. Oh well. + + // Read key and value from data. + var nerr nonFatal + k := reflect.New(kt) + v := reflect.New(vt) + for len(b) > 0 { + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + wire := int(x) & 7 + b = b[n:] + + var err error + switch x >> 3 { + case 1: + b, err = unmarshalKey(b, valToPointer(k), wire) + case 2: + b, err = unmarshalVal(b, valToPointer(v), wire) + default: + err = errInternalBadWireType // skip unknown tag + } + + if nerr.Merge(err) { + continue + } + if err != errInternalBadWireType { + return nil, err + } + + // Skip past unknown fields. + b, err = skipField(b, wire) + if err != nil { + return nil, err + } + } + + // Get map, allocate if needed. + m := f.asPointerTo(t).Elem() // an addressable map[K]T + if m.IsNil() { + m.Set(reflect.MakeMap(t)) + } + + // Insert into map. + m.SetMapIndex(k.Elem(), v.Elem()) + + return r, nerr.E + } +} + +// makeUnmarshalOneof makes an unmarshaler for oneof fields. +// for: +// message Msg { +// oneof F { +// int64 X = 1; +// float64 Y = 2; +// } +// } +// typ is the type of the concrete entry for a oneof case (e.g. Msg_X). +// ityp is the interface type of the oneof field (e.g. isMsg_F). +// unmarshal is the unmarshaler for the base type of the oneof case (e.g. int64). +// Note that this function will be called once for each case in the oneof. +func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshaler { + sf := typ.Field(0) + field0 := toField(&sf) + return func(b []byte, f pointer, w int) ([]byte, error) { + // Allocate holder for value. + v := reflect.New(typ) + + // Unmarshal data into holder. + // We unmarshal into the first field of the holder object. + var err error + var nerr nonFatal + b, err = unmarshal(b, valToPointer(v).offset(field0), w) + if !nerr.Merge(err) { + return nil, err + } + + // Write pointer to holder into target field. + f.asPointerTo(ityp).Elem().Set(v) + + return b, nerr.E + } +} + +// Error used by decode internally. +var errInternalBadWireType = errors.New("proto: internal error: bad wiretype") + +// skipField skips past a field of type wire and returns the remaining bytes. +func skipField(b []byte, wire int) ([]byte, error) { + switch wire { + case WireVarint: + _, k := decodeVarint(b) + if k == 0 { + return b, io.ErrUnexpectedEOF + } + b = b[k:] + case WireFixed32: + if len(b) < 4 { + return b, io.ErrUnexpectedEOF + } + b = b[4:] + case WireFixed64: + if len(b) < 8 { + return b, io.ErrUnexpectedEOF + } + b = b[8:] + case WireBytes: + m, k := decodeVarint(b) + if k == 0 || uint64(len(b)-k) < m { + return b, io.ErrUnexpectedEOF + } + b = b[uint64(k)+m:] + case WireStartGroup: + _, i := findEndGroup(b) + if i == -1 { + return b, io.ErrUnexpectedEOF + } + b = b[i:] + default: + return b, fmt.Errorf("proto: can't skip unknown wire type %d", wire) + } + return b, nil +} + +// findEndGroup finds the index of the next EndGroup tag. +// Groups may be nested, so the "next" EndGroup tag is the first +// unpaired EndGroup. +// findEndGroup returns the indexes of the start and end of the EndGroup tag. +// Returns (-1,-1) if it can't find one. +func findEndGroup(b []byte) (int, int) { + depth := 1 + i := 0 + for { + x, n := decodeVarint(b[i:]) + if n == 0 { + return -1, -1 + } + j := i + i += n + switch x & 7 { + case WireVarint: + _, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + case WireFixed32: + if len(b)-4 < i { + return -1, -1 + } + i += 4 + case WireFixed64: + if len(b)-8 < i { + return -1, -1 + } + i += 8 + case WireBytes: + m, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + if uint64(len(b)-i) < m { + return -1, -1 + } + i += int(m) + case WireStartGroup: + depth++ + case WireEndGroup: + depth-- + if depth == 0 { + return j, i + } + default: + return -1, -1 + } + } +} + +// encodeVarint appends a varint-encoded integer to b and returns the result. +func encodeVarint(b []byte, x uint64) []byte { + for x >= 1<<7 { + b = append(b, byte(x&0x7f|0x80)) + x >>= 7 + } + return append(b, byte(x)) +} + +// decodeVarint reads a varint-encoded integer from b. +// Returns the decoded integer and the number of bytes read. +// If there is an error, it returns 0,0. +func decodeVarint(b []byte) (uint64, int) { + var x, y uint64 + if len(b) == 0 { + goto bad + } + x = uint64(b[0]) + if x < 0x80 { + return x, 1 + } + x -= 0x80 + + if len(b) <= 1 { + goto bad + } + y = uint64(b[1]) + x += y << 7 + if y < 0x80 { + return x, 2 + } + x -= 0x80 << 7 + + if len(b) <= 2 { + goto bad + } + y = uint64(b[2]) + x += y << 14 + if y < 0x80 { + return x, 3 + } + x -= 0x80 << 14 + + if len(b) <= 3 { + goto bad + } + y = uint64(b[3]) + x += y << 21 + if y < 0x80 { + return x, 4 + } + x -= 0x80 << 21 + + if len(b) <= 4 { + goto bad + } + y = uint64(b[4]) + x += y << 28 + if y < 0x80 { + return x, 5 + } + x -= 0x80 << 28 + + if len(b) <= 5 { + goto bad + } + y = uint64(b[5]) + x += y << 35 + if y < 0x80 { + return x, 6 + } + x -= 0x80 << 35 + + if len(b) <= 6 { + goto bad + } + y = uint64(b[6]) + x += y << 42 + if y < 0x80 { + return x, 7 + } + x -= 0x80 << 42 + + if len(b) <= 7 { + goto bad + } + y = uint64(b[7]) + x += y << 49 + if y < 0x80 { + return x, 8 + } + x -= 0x80 << 49 + + if len(b) <= 8 { + goto bad + } + y = uint64(b[8]) + x += y << 56 + if y < 0x80 { + return x, 9 + } + x -= 0x80 << 56 + + if len(b) <= 9 { + goto bad + } + y = uint64(b[9]) + x += y << 63 + if y < 2 { + return x, 10 + } + +bad: + return 0, 0 +} diff --git a/vendor/github.com/gogo/protobuf/proto/table_unmarshal_gogo.go b/vendor/github.com/gogo/protobuf/proto/table_unmarshal_gogo.go new file mode 100644 index 000000000..00d6c7ad9 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/table_unmarshal_gogo.go @@ -0,0 +1,385 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2018, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "io" + "reflect" +) + +func makeUnmarshalMessage(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // First read the message field to see if something is there. + // The semantics of multiple submessages are weird. Instead of + // the last one winning (as it is for all other fields), multiple + // submessages are merged. + v := f // gogo: changed from v := f.getPointer() + if v.isNil() { + v = valToPointer(reflect.New(sub.typ)) + f.setPointer(v) + } + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + return b[x:], err + } +} + +func makeUnmarshalMessageSlice(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := valToPointer(reflect.New(sub.typ)) + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + f.appendRef(v, sub.typ) // gogo: changed from f.appendPointer(v) + return b[x:], err + } +} + +func makeUnmarshalCustomPtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.New(sub.typ)) + m := s.Interface().(custom) + if err := m.Unmarshal(b[:x]); err != nil { + return nil, err + } + return b[x:], nil + } +} + +func makeUnmarshalCustomSlice(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := reflect.New(sub.typ) + c := m.Interface().(custom) + if err := c.Unmarshal(b[:x]); err != nil { + return nil, err + } + v := valToPointer(m) + f.appendRef(v, sub.typ) + return b[x:], nil + } +} + +func makeUnmarshalCustom(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + + m := f.asPointerTo(sub.typ).Interface().(custom) + if err := m.Unmarshal(b[:x]); err != nil { + return nil, err + } + return b[x:], nil + } +} + +func makeUnmarshalTime(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := ×tamp{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + t, err := timestampFromProto(m) + if err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(t)) + return b[x:], nil + } +} + +func makeUnmarshalTimePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := ×tamp{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + t, err := timestampFromProto(m) + if err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&t)) + return b[x:], nil + } +} + +func makeUnmarshalTimePtrSlice(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := ×tamp{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + t, err := timestampFromProto(m) + if err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&t)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeUnmarshalTimeSlice(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := ×tamp{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + t, err := timestampFromProto(m) + if err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(t)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeUnmarshalDurationPtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &duration{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + d, err := durationFromProto(m) + if err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&d)) + return b[x:], nil + } +} + +func makeUnmarshalDuration(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &duration{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + d, err := durationFromProto(m) + if err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(d)) + return b[x:], nil + } +} + +func makeUnmarshalDurationPtrSlice(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &duration{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + d, err := durationFromProto(m) + if err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&d)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeUnmarshalDurationSlice(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &duration{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + d, err := durationFromProto(m) + if err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(d)) + slice.Set(newSlice) + return b[x:], nil + } +} diff --git a/vendor/github.com/gogo/protobuf/proto/text.go b/vendor/github.com/gogo/protobuf/proto/text.go new file mode 100644 index 000000000..0407ba85d --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/text.go @@ -0,0 +1,928 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +// Functions for writing the text protocol buffer format. + +import ( + "bufio" + "bytes" + "encoding" + "errors" + "fmt" + "io" + "log" + "math" + "reflect" + "sort" + "strings" + "sync" + "time" +) + +var ( + newline = []byte("\n") + spaces = []byte(" ") + endBraceNewline = []byte("}\n") + backslashN = []byte{'\\', 'n'} + backslashR = []byte{'\\', 'r'} + backslashT = []byte{'\\', 't'} + backslashDQ = []byte{'\\', '"'} + backslashBS = []byte{'\\', '\\'} + posInf = []byte("inf") + negInf = []byte("-inf") + nan = []byte("nan") +) + +type writer interface { + io.Writer + WriteByte(byte) error +} + +// textWriter is an io.Writer that tracks its indentation level. +type textWriter struct { + ind int + complete bool // if the current position is a complete line + compact bool // whether to write out as a one-liner + w writer +} + +func (w *textWriter) WriteString(s string) (n int, err error) { + if !strings.Contains(s, "\n") { + if !w.compact && w.complete { + w.writeIndent() + } + w.complete = false + return io.WriteString(w.w, s) + } + // WriteString is typically called without newlines, so this + // codepath and its copy are rare. We copy to avoid + // duplicating all of Write's logic here. + return w.Write([]byte(s)) +} + +func (w *textWriter) Write(p []byte) (n int, err error) { + newlines := bytes.Count(p, newline) + if newlines == 0 { + if !w.compact && w.complete { + w.writeIndent() + } + n, err = w.w.Write(p) + w.complete = false + return n, err + } + + frags := bytes.SplitN(p, newline, newlines+1) + if w.compact { + for i, frag := range frags { + if i > 0 { + if err := w.w.WriteByte(' '); err != nil { + return n, err + } + n++ + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + } + return n, nil + } + + for i, frag := range frags { + if w.complete { + w.writeIndent() + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + if i+1 < len(frags) { + if err := w.w.WriteByte('\n'); err != nil { + return n, err + } + n++ + } + } + w.complete = len(frags[len(frags)-1]) == 0 + return n, nil +} + +func (w *textWriter) WriteByte(c byte) error { + if w.compact && c == '\n' { + c = ' ' + } + if !w.compact && w.complete { + w.writeIndent() + } + err := w.w.WriteByte(c) + w.complete = c == '\n' + return err +} + +func (w *textWriter) indent() { w.ind++ } + +func (w *textWriter) unindent() { + if w.ind == 0 { + log.Print("proto: textWriter unindented too far") + return + } + w.ind-- +} + +func writeName(w *textWriter, props *Properties) error { + if _, err := w.WriteString(props.OrigName); err != nil { + return err + } + if props.Wire != "group" { + return w.WriteByte(':') + } + return nil +} + +func requiresQuotes(u string) bool { + // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. + for _, ch := range u { + switch { + case ch == '.' || ch == '/' || ch == '_': + continue + case '0' <= ch && ch <= '9': + continue + case 'A' <= ch && ch <= 'Z': + continue + case 'a' <= ch && ch <= 'z': + continue + default: + return true + } + } + return false +} + +// isAny reports whether sv is a google.protobuf.Any message +func isAny(sv reflect.Value) bool { + type wkt interface { + XXX_WellKnownType() string + } + t, ok := sv.Addr().Interface().(wkt) + return ok && t.XXX_WellKnownType() == "Any" +} + +// writeProto3Any writes an expanded google.protobuf.Any message. +// +// It returns (false, nil) if sv value can't be unmarshaled (e.g. because +// required messages are not linked in). +// +// It returns (true, error) when sv was written in expanded format or an error +// was encountered. +func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) { + turl := sv.FieldByName("TypeUrl") + val := sv.FieldByName("Value") + if !turl.IsValid() || !val.IsValid() { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + b, ok := val.Interface().([]byte) + if !ok { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + parts := strings.Split(turl.String(), "/") + mt := MessageType(parts[len(parts)-1]) + if mt == nil { + return false, nil + } + m := reflect.New(mt.Elem()) + if err := Unmarshal(b, m.Interface().(Message)); err != nil { + return false, nil + } + w.Write([]byte("[")) + u := turl.String() + if requiresQuotes(u) { + writeString(w, u) + } else { + w.Write([]byte(u)) + } + if w.compact { + w.Write([]byte("]:<")) + } else { + w.Write([]byte("]: <\n")) + w.ind++ + } + if err := tm.writeStruct(w, m.Elem()); err != nil { + return true, err + } + if w.compact { + w.Write([]byte("> ")) + } else { + w.ind-- + w.Write([]byte(">\n")) + } + return true, nil +} + +func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { + if tm.ExpandAny && isAny(sv) { + if canExpand, err := tm.writeProto3Any(w, sv); canExpand { + return err + } + } + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < sv.NumField(); i++ { + fv := sv.Field(i) + props := sprops.Prop[i] + name := st.Field(i).Name + + if name == "XXX_NoUnkeyedLiteral" { + continue + } + + if strings.HasPrefix(name, "XXX_") { + // There are two XXX_ fields: + // XXX_unrecognized []byte + // XXX_extensions map[int32]proto.Extension + // The first is handled here; + // the second is handled at the bottom of this function. + if name == "XXX_unrecognized" && !fv.IsNil() { + if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Field not filled in. This could be an optional field or + // a required field that wasn't filled in. Either way, there + // isn't anything we can show for it. + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + // Repeated field that is empty, or a bytes field that is unused. + continue + } + + if props.Repeated && fv.Kind() == reflect.Slice { + // Repeated field. + for j := 0; j < fv.Len(); j++ { + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + v := fv.Index(j) + if v.Kind() == reflect.Ptr && v.IsNil() { + // A nil message in a repeated field is not valid, + // but we can handle that more gracefully than panicking. + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + continue + } + if len(props.Enum) > 0 { + if err := tm.writeEnum(w, v, props); err != nil { + return err + } + } else if err := tm.writeAny(w, v, props); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Map { + // Map fields are rendered as a repeated struct with key/value fields. + keys := fv.MapKeys() + sort.Sort(mapKeys(keys)) + for _, key := range keys { + val := fv.MapIndex(key) + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + // open struct + if err := w.WriteByte('<'); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + // key + if _, err := w.WriteString("key:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, key, props.MapKeyProp); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + // nil values aren't legal, but we can avoid panicking because of them. + if val.Kind() != reflect.Ptr || !val.IsNil() { + // value + if _, err := w.WriteString("value:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, val, props.MapValProp); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + // close struct + w.unindent() + if err := w.WriteByte('>'); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 { + // empty bytes field + continue + } + if props.proto3 && fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice { + // proto3 non-repeated scalar field; skip if zero value + if isProto3Zero(fv) { + continue + } + } + + if fv.Kind() == reflect.Interface { + // Check if it is a oneof. + if st.Field(i).Tag.Get("protobuf_oneof") != "" { + // fv is nil, or holds a pointer to generated struct. + // That generated struct has exactly one field, + // which has a protobuf struct tag. + if fv.IsNil() { + continue + } + inner := fv.Elem().Elem() // interface -> *T -> T + tag := inner.Type().Field(0).Tag.Get("protobuf") + props = new(Properties) // Overwrite the outer props var, but not its pointee. + props.Parse(tag) + // Write the value in the oneof, not the oneof itself. + fv = inner.Field(0) + + // Special case to cope with malformed messages gracefully: + // If the value in the oneof is a nil pointer, don't panic + // in writeAny. + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Use errors.New so writeAny won't render quotes. + msg := errors.New("/* nil */") + fv = reflect.ValueOf(&msg).Elem() + } + } + } + + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + + if len(props.Enum) > 0 { + if err := tm.writeEnum(w, fv, props); err != nil { + return err + } + } else if err := tm.writeAny(w, fv, props); err != nil { + return err + } + + if err := w.WriteByte('\n'); err != nil { + return err + } + } + + // Extensions (the XXX_extensions field). + pv := sv + if pv.CanAddr() { + pv = sv.Addr() + } else { + pv = reflect.New(sv.Type()) + pv.Elem().Set(sv) + } + if _, err := extendable(pv.Interface()); err == nil { + if err := tm.writeExtensions(w, pv); err != nil { + return err + } + } + + return nil +} + +// writeAny writes an arbitrary field. +func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { + v = reflect.Indirect(v) + + if props != nil { + if len(props.CustomType) > 0 { + custom, ok := v.Interface().(Marshaler) + if ok { + data, err := custom.Marshal() + if err != nil { + return err + } + if err := writeString(w, string(data)); err != nil { + return err + } + return nil + } + } else if len(props.CastType) > 0 { + if _, ok := v.Interface().(interface { + String() string + }); ok { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + _, err := fmt.Fprintf(w, "%d", v.Interface()) + return err + } + } + } else if props.StdTime { + t, ok := v.Interface().(time.Time) + if !ok { + return fmt.Errorf("stdtime is not time.Time, but %T", v.Interface()) + } + tproto, err := timestampProto(t) + if err != nil { + return err + } + propsCopy := *props // Make a copy so that this is goroutine-safe + propsCopy.StdTime = false + err = tm.writeAny(w, reflect.ValueOf(tproto), &propsCopy) + return err + } else if props.StdDuration { + d, ok := v.Interface().(time.Duration) + if !ok { + return fmt.Errorf("stdtime is not time.Duration, but %T", v.Interface()) + } + dproto := durationProto(d) + propsCopy := *props // Make a copy so that this is goroutine-safe + propsCopy.StdDuration = false + err := tm.writeAny(w, reflect.ValueOf(dproto), &propsCopy) + return err + } + } + + // Floats have special cases. + if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { + x := v.Float() + var b []byte + switch { + case math.IsInf(x, 1): + b = posInf + case math.IsInf(x, -1): + b = negInf + case math.IsNaN(x): + b = nan + } + if b != nil { + _, err := w.Write(b) + return err + } + // Other values are handled below. + } + + // We don't attempt to serialise every possible value type; only those + // that can occur in protocol buffers. + switch v.Kind() { + case reflect.Slice: + // Should only be a []byte; repeated fields are handled in writeStruct. + if err := writeString(w, string(v.Bytes())); err != nil { + return err + } + case reflect.String: + if err := writeString(w, v.String()); err != nil { + return err + } + case reflect.Struct: + // Required/optional group/message. + var bra, ket byte = '<', '>' + if props != nil && props.Wire == "group" { + bra, ket = '{', '}' + } + if err := w.WriteByte(bra); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + if v.CanAddr() { + // Calling v.Interface on a struct causes the reflect package to + // copy the entire struct. This is racy with the new Marshaler + // since we atomically update the XXX_sizecache. + // + // Thus, we retrieve a pointer to the struct if possible to avoid + // a race since v.Interface on the pointer doesn't copy the struct. + // + // If v is not addressable, then we are not worried about a race + // since it implies that the binary Marshaler cannot possibly be + // mutating this value. + v = v.Addr() + } + if etm, ok := v.Interface().(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() + if err != nil { + return err + } + if _, err = w.Write(text); err != nil { + return err + } + } else { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if err := tm.writeStruct(w, v); err != nil { + return err + } + } + w.unindent() + if err := w.WriteByte(ket); err != nil { + return err + } + default: + _, err := fmt.Fprint(w, v.Interface()) + return err + } + return nil +} + +// equivalent to C's isprint. +func isprint(c byte) bool { + return c >= 0x20 && c < 0x7f +} + +// writeString writes a string in the protocol buffer text format. +// It is similar to strconv.Quote except we don't use Go escape sequences, +// we treat the string as a byte sequence, and we use octal escapes. +// These differences are to maintain interoperability with the other +// languages' implementations of the text format. +func writeString(w *textWriter, s string) error { + // use WriteByte here to get any needed indent + if err := w.WriteByte('"'); err != nil { + return err + } + // Loop over the bytes, not the runes. + for i := 0; i < len(s); i++ { + var err error + // Divergence from C++: we don't escape apostrophes. + // There's no need to escape them, and the C++ parser + // copes with a naked apostrophe. + switch c := s[i]; c { + case '\n': + _, err = w.w.Write(backslashN) + case '\r': + _, err = w.w.Write(backslashR) + case '\t': + _, err = w.w.Write(backslashT) + case '"': + _, err = w.w.Write(backslashDQ) + case '\\': + _, err = w.w.Write(backslashBS) + default: + if isprint(c) { + err = w.w.WriteByte(c) + } else { + _, err = fmt.Fprintf(w.w, "\\%03o", c) + } + } + if err != nil { + return err + } + } + return w.WriteByte('"') +} + +func writeUnknownStruct(w *textWriter, data []byte) (err error) { + if !w.compact { + if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil { + return err + } + } + b := NewBuffer(data) + for b.index < len(b.buf) { + x, err := b.DecodeVarint() + if err != nil { + _, ferr := fmt.Fprintf(w, "/* %v */\n", err) + return ferr + } + wire, tag := x&7, x>>3 + if wire == WireEndGroup { + w.unindent() + if _, werr := w.Write(endBraceNewline); werr != nil { + return werr + } + continue + } + if _, ferr := fmt.Fprint(w, tag); ferr != nil { + return ferr + } + if wire != WireStartGroup { + if err = w.WriteByte(':'); err != nil { + return err + } + } + if !w.compact || wire == WireStartGroup { + if err = w.WriteByte(' '); err != nil { + return err + } + } + switch wire { + case WireBytes: + buf, e := b.DecodeRawBytes(false) + if e == nil { + _, err = fmt.Fprintf(w, "%q", buf) + } else { + _, err = fmt.Fprintf(w, "/* %v */", e) + } + case WireFixed32: + x, err = b.DecodeFixed32() + err = writeUnknownInt(w, x, err) + case WireFixed64: + x, err = b.DecodeFixed64() + err = writeUnknownInt(w, x, err) + case WireStartGroup: + err = w.WriteByte('{') + w.indent() + case WireVarint: + x, err = b.DecodeVarint() + err = writeUnknownInt(w, x, err) + default: + _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire) + } + if err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + return nil +} + +func writeUnknownInt(w *textWriter, x uint64, err error) error { + if err == nil { + _, err = fmt.Fprint(w, x) + } else { + _, err = fmt.Fprintf(w, "/* %v */", err) + } + return err +} + +type int32Slice []int32 + +func (s int32Slice) Len() int { return len(s) } +func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// writeExtensions writes all the extensions in pv. +// pv is assumed to be a pointer to a protocol message struct that is extendable. +func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error { + emap := extensionMaps[pv.Type().Elem()] + e := pv.Interface().(Message) + + var m map[int32]Extension + var mu sync.Locker + if em, ok := e.(extensionsBytes); ok { + eb := em.GetExtensions() + var err error + m, err = BytesToExtensionsMap(*eb) + if err != nil { + return err + } + mu = notLocker{} + } else if _, ok := e.(extendableProto); ok { + ep, _ := extendable(e) + m, mu = ep.extensionsRead() + if m == nil { + return nil + } + } + + // Order the extensions by ID. + // This isn't strictly necessary, but it will give us + // canonical output, which will also make testing easier. + + mu.Lock() + ids := make([]int32, 0, len(m)) + for id := range m { + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) + mu.Unlock() + + for _, extNum := range ids { + ext := m[extNum] + var desc *ExtensionDesc + if emap != nil { + desc = emap[extNum] + } + if desc == nil { + // Unknown extension. + if err := writeUnknownStruct(w, ext.enc); err != nil { + return err + } + continue + } + + pb, err := GetExtension(e, desc) + if err != nil { + return fmt.Errorf("failed getting extension: %v", err) + } + + // Repeated extensions will appear as a slice. + if !desc.repeated() { + if err := tm.writeExtension(w, desc.Name, pb); err != nil { + return err + } + } else { + v := reflect.ValueOf(pb) + for i := 0; i < v.Len(); i++ { + if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { + return err + } + } + } + } + return nil +} + +func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error { + if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + return nil +} + +func (w *textWriter) writeIndent() { + if !w.complete { + return + } + remain := w.ind * 2 + for remain > 0 { + n := remain + if n > len(spaces) { + n = len(spaces) + } + w.w.Write(spaces[:n]) + remain -= n + } + w.complete = false +} + +// TextMarshaler is a configurable text format marshaler. +type TextMarshaler struct { + Compact bool // use compact text format (one line). + ExpandAny bool // expand google.protobuf.Any messages of known types +} + +// Marshal writes a given protocol buffer in text format. +// The only errors returned are from w. +func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error { + val := reflect.ValueOf(pb) + if pb == nil || val.IsNil() { + w.Write([]byte("")) + return nil + } + var bw *bufio.Writer + ww, ok := w.(writer) + if !ok { + bw = bufio.NewWriter(w) + ww = bw + } + aw := &textWriter{ + w: ww, + complete: true, + compact: tm.Compact, + } + + if etm, ok := pb.(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() + if err != nil { + return err + } + if _, err = aw.Write(text); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil + } + // Dereference the received pointer so we don't have outer < and >. + v := reflect.Indirect(val) + if err := tm.writeStruct(aw, v); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil +} + +// Text is the same as Marshal, but returns the string directly. +func (tm *TextMarshaler) Text(pb Message) string { + var buf bytes.Buffer + tm.Marshal(&buf, pb) + return buf.String() +} + +var ( + defaultTextMarshaler = TextMarshaler{} + compactTextMarshaler = TextMarshaler{Compact: true} +) + +// TODO: consider removing some of the Marshal functions below. + +// MarshalText writes a given protocol buffer in text format. +// The only errors returned are from w. +func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) } + +// MarshalTextString is the same as MarshalText, but returns the string directly. +func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) } + +// CompactText writes a given protocol buffer in compact text format (one line). +func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) } + +// CompactTextString is the same as CompactText, but returns the string directly. +func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) } diff --git a/vendor/github.com/gogo/protobuf/proto/text_gogo.go b/vendor/github.com/gogo/protobuf/proto/text_gogo.go new file mode 100644 index 000000000..1d6c6aa0e --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/text_gogo.go @@ -0,0 +1,57 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "fmt" + "reflect" +) + +func (tm *TextMarshaler) writeEnum(w *textWriter, v reflect.Value, props *Properties) error { + m, ok := enumStringMaps[props.Enum] + if !ok { + if err := tm.writeAny(w, v, props); err != nil { + return err + } + } + key := int32(0) + if v.Kind() == reflect.Ptr { + key = int32(v.Elem().Int()) + } else { + key = int32(v.Int()) + } + s, ok := m[key] + if !ok { + if err := tm.writeAny(w, v, props); err != nil { + return err + } + } + _, err := fmt.Fprint(w, s) + return err +} diff --git a/vendor/github.com/gogo/protobuf/proto/text_parser.go b/vendor/github.com/gogo/protobuf/proto/text_parser.go new file mode 100644 index 000000000..1ce0be2fa --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/text_parser.go @@ -0,0 +1,1018 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +// Functions for parsing the Text protocol buffer format. +// TODO: message sets. + +import ( + "encoding" + "errors" + "fmt" + "reflect" + "strconv" + "strings" + "time" + "unicode/utf8" +) + +// Error string emitted when deserializing Any and fields are already set +const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set" + +type ParseError struct { + Message string + Line int // 1-based line number + Offset int // 0-based byte offset from start of input +} + +func (p *ParseError) Error() string { + if p.Line == 1 { + // show offset only for first line + return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message) + } + return fmt.Sprintf("line %d: %v", p.Line, p.Message) +} + +type token struct { + value string + err *ParseError + line int // line number + offset int // byte number from start of input, not start of line + unquoted string // the unquoted version of value, if it was a quoted string +} + +func (t *token) String() string { + if t.err == nil { + return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset) + } + return fmt.Sprintf("parse error: %v", t.err) +} + +type textParser struct { + s string // remaining input + done bool // whether the parsing is finished (success or error) + backed bool // whether back() was called + offset, line int + cur token +} + +func newTextParser(s string) *textParser { + p := new(textParser) + p.s = s + p.line = 1 + p.cur.line = 1 + return p +} + +func (p *textParser) errorf(format string, a ...interface{}) *ParseError { + pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset} + p.cur.err = pe + p.done = true + return pe +} + +// Numbers and identifiers are matched by [-+._A-Za-z0-9] +func isIdentOrNumberChar(c byte) bool { + switch { + case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z': + return true + case '0' <= c && c <= '9': + return true + } + switch c { + case '-', '+', '.', '_': + return true + } + return false +} + +func isWhitespace(c byte) bool { + switch c { + case ' ', '\t', '\n', '\r': + return true + } + return false +} + +func isQuote(c byte) bool { + switch c { + case '"', '\'': + return true + } + return false +} + +func (p *textParser) skipWhitespace() { + i := 0 + for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') { + if p.s[i] == '#' { + // comment; skip to end of line or input + for i < len(p.s) && p.s[i] != '\n' { + i++ + } + if i == len(p.s) { + break + } + } + if p.s[i] == '\n' { + p.line++ + } + i++ + } + p.offset += i + p.s = p.s[i:len(p.s)] + if len(p.s) == 0 { + p.done = true + } +} + +func (p *textParser) advance() { + // Skip whitespace + p.skipWhitespace() + if p.done { + return + } + + // Start of non-whitespace + p.cur.err = nil + p.cur.offset, p.cur.line = p.offset, p.line + p.cur.unquoted = "" + switch p.s[0] { + case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/': + // Single symbol + p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] + case '"', '\'': + // Quoted string + i := 1 + for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' { + if p.s[i] == '\\' && i+1 < len(p.s) { + // skip escaped char + i++ + } + i++ + } + if i >= len(p.s) || p.s[i] != p.s[0] { + p.errorf("unmatched quote") + return + } + unq, err := unquoteC(p.s[1:i], rune(p.s[0])) + if err != nil { + p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err) + return + } + p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)] + p.cur.unquoted = unq + default: + i := 0 + for i < len(p.s) && isIdentOrNumberChar(p.s[i]) { + i++ + } + if i == 0 { + p.errorf("unexpected byte %#x", p.s[0]) + return + } + p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)] + } + p.offset += len(p.cur.value) +} + +var ( + errBadUTF8 = errors.New("proto: bad UTF-8") +) + +func unquoteC(s string, quote rune) (string, error) { + // This is based on C++'s tokenizer.cc. + // Despite its name, this is *not* parsing C syntax. + // For instance, "\0" is an invalid quoted string. + + // Avoid allocation in trivial cases. + simple := true + for _, r := range s { + if r == '\\' || r == quote { + simple = false + break + } + } + if simple { + return s, nil + } + + buf := make([]byte, 0, 3*len(s)/2) + for len(s) > 0 { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", errBadUTF8 + } + s = s[n:] + if r != '\\' { + if r < utf8.RuneSelf { + buf = append(buf, byte(r)) + } else { + buf = append(buf, string(r)...) + } + continue + } + + ch, tail, err := unescape(s) + if err != nil { + return "", err + } + buf = append(buf, ch...) + s = tail + } + return string(buf), nil +} + +func unescape(s string) (ch string, tail string, err error) { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", "", errBadUTF8 + } + s = s[n:] + switch r { + case 'a': + return "\a", s, nil + case 'b': + return "\b", s, nil + case 'f': + return "\f", s, nil + case 'n': + return "\n", s, nil + case 'r': + return "\r", s, nil + case 't': + return "\t", s, nil + case 'v': + return "\v", s, nil + case '?': + return "?", s, nil // trigraph workaround + case '\'', '"', '\\': + return string(r), s, nil + case '0', '1', '2', '3', '4', '5', '6', '7': + if len(s) < 2 { + return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) + } + ss := string(r) + s[:2] + s = s[2:] + i, err := strconv.ParseUint(ss, 8, 8) + if err != nil { + return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss) + } + return string([]byte{byte(i)}), s, nil + case 'x', 'X', 'u', 'U': + var n int + switch r { + case 'x', 'X': + n = 2 + case 'u': + n = 4 + case 'U': + n = 8 + } + if len(s) < n { + return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n) + } + ss := s[:n] + s = s[n:] + i, err := strconv.ParseUint(ss, 16, 64) + if err != nil { + return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss) + } + if r == 'x' || r == 'X' { + return string([]byte{byte(i)}), s, nil + } + if i > utf8.MaxRune { + return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss) + } + return string(i), s, nil + } + return "", "", fmt.Errorf(`unknown escape \%c`, r) +} + +// Back off the parser by one token. Can only be done between calls to next(). +// It makes the next advance() a no-op. +func (p *textParser) back() { p.backed = true } + +// Advances the parser and returns the new current token. +func (p *textParser) next() *token { + if p.backed || p.done { + p.backed = false + return &p.cur + } + p.advance() + if p.done { + p.cur.value = "" + } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) { + // Look for multiple quoted strings separated by whitespace, + // and concatenate them. + cat := p.cur + for { + p.skipWhitespace() + if p.done || !isQuote(p.s[0]) { + break + } + p.advance() + if p.cur.err != nil { + return &p.cur + } + cat.value += " " + p.cur.value + cat.unquoted += p.cur.unquoted + } + p.done = false // parser may have seen EOF, but we want to return cat + p.cur = cat + } + return &p.cur +} + +func (p *textParser) consumeToken(s string) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != s { + p.back() + return p.errorf("expected %q, found %q", s, tok.value) + } + return nil +} + +// Return a RequiredNotSetError indicating which required field was not set. +func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError { + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < st.NumField(); i++ { + if !isNil(sv.Field(i)) { + continue + } + + props := sprops.Prop[i] + if props.Required { + return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)} + } + } + return &RequiredNotSetError{fmt.Sprintf("%v.", st)} // should not happen +} + +// Returns the index in the struct for the named field, as well as the parsed tag properties. +func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) { + i, ok := sprops.decoderOrigNames[name] + if ok { + return i, sprops.Prop[i], true + } + return -1, nil, false +} + +// Consume a ':' from the input stream (if the next token is a colon), +// returning an error if a colon is needed but not present. +func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ":" { + // Colon is optional when the field is a group or message. + needColon := true + switch props.Wire { + case "group": + needColon = false + case "bytes": + // A "bytes" field is either a message, a string, or a repeated field; + // those three become *T, *string and []T respectively, so we can check for + // this field being a pointer to a non-string. + if typ.Kind() == reflect.Ptr { + // *T or *string + if typ.Elem().Kind() == reflect.String { + break + } + } else if typ.Kind() == reflect.Slice { + // []T or []*T + if typ.Elem().Kind() != reflect.Ptr { + break + } + } else if typ.Kind() == reflect.String { + // The proto3 exception is for a string field, + // which requires a colon. + break + } + needColon = false + } + if needColon { + return p.errorf("expected ':', found %q", tok.value) + } + p.back() + } + return nil +} + +func (p *textParser) readStruct(sv reflect.Value, terminator string) error { + st := sv.Type() + sprops := GetProperties(st) + reqCount := sprops.reqCount + var reqFieldErr error + fieldSet := make(map[string]bool) + // A struct is a sequence of "name: value", terminated by one of + // '>' or '}', or the end of the input. A name may also be + // "[extension]" or "[type/url]". + // + // The whole struct can also be an expanded Any message, like: + // [type/url] < ... struct contents ... > + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + if tok.value == "[" { + // Looks like an extension or an Any. + // + // TODO: Check whether we need to handle + // namespace rooted names (e.g. ".something.Foo"). + extName, err := p.consumeExtName() + if err != nil { + return err + } + + if s := strings.LastIndex(extName, "/"); s >= 0 { + // If it contains a slash, it's an Any type URL. + messageName := extName[s+1:] + mt := MessageType(messageName) + if mt == nil { + return p.errorf("unrecognized message %q in google.protobuf.Any", messageName) + } + tok = p.next() + if tok.err != nil { + return tok.err + } + // consume an optional colon + if tok.value == ":" { + tok = p.next() + if tok.err != nil { + return tok.err + } + } + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + v := reflect.New(mt.Elem()) + if pe := p.readStruct(v.Elem(), terminator); pe != nil { + return pe + } + b, err := Marshal(v.Interface().(Message)) + if err != nil { + return p.errorf("failed to marshal message of type %q: %v", messageName, err) + } + if fieldSet["type_url"] { + return p.errorf(anyRepeatedlyUnpacked, "type_url") + } + if fieldSet["value"] { + return p.errorf(anyRepeatedlyUnpacked, "value") + } + sv.FieldByName("TypeUrl").SetString(extName) + sv.FieldByName("Value").SetBytes(b) + fieldSet["type_url"] = true + fieldSet["value"] = true + continue + } + + var desc *ExtensionDesc + // This could be faster, but it's functional. + // TODO: Do something smarter than a linear scan. + for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) { + if d.Name == extName { + desc = d + break + } + } + if desc == nil { + return p.errorf("unrecognized extension %q", extName) + } + + props := &Properties{} + props.Parse(desc.Tag) + + typ := reflect.TypeOf(desc.ExtensionType) + if err := p.checkForColon(props, typ); err != nil { + return err + } + + rep := desc.repeated() + + // Read the extension structure, and set it in + // the value we're constructing. + var ext reflect.Value + if !rep { + ext = reflect.New(typ).Elem() + } else { + ext = reflect.New(typ.Elem()).Elem() + } + if err := p.readAny(ext, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } + ep := sv.Addr().Interface().(Message) + if !rep { + SetExtension(ep, desc, ext.Interface()) + } else { + old, err := GetExtension(ep, desc) + var sl reflect.Value + if err == nil { + sl = reflect.ValueOf(old) // existing slice + } else { + sl = reflect.MakeSlice(typ, 0, 1) + } + sl = reflect.Append(sl, ext) + SetExtension(ep, desc, sl.Interface()) + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + continue + } + + // This is a normal, non-extension field. + name := tok.value + var dst reflect.Value + fi, props, ok := structFieldByName(sprops, name) + if ok { + dst = sv.Field(fi) + } else if oop, ok := sprops.OneofTypes[name]; ok { + // It is a oneof. + props = oop.Prop + nv := reflect.New(oop.Type.Elem()) + dst = nv.Elem().Field(0) + field := sv.Field(oop.Field) + if !field.IsNil() { + return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name) + } + field.Set(nv) + } + if !dst.IsValid() { + return p.errorf("unknown field name %q in %v", name, st) + } + + if dst.Kind() == reflect.Map { + // Consume any colon. + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Construct the map if it doesn't already exist. + if dst.IsNil() { + dst.Set(reflect.MakeMap(dst.Type())) + } + key := reflect.New(dst.Type().Key()).Elem() + val := reflect.New(dst.Type().Elem()).Elem() + + // The map entry should be this sequence of tokens: + // < key : KEY value : VALUE > + // However, implementations may omit key or value, and technically + // we should support them in any order. See b/28924776 for a time + // this went wrong. + + tok := p.next() + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + switch tok.value { + case "key": + if err := p.consumeToken(":"); err != nil { + return err + } + if err := p.readAny(key, props.MapKeyProp); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + case "value": + if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil { + return err + } + if err := p.readAny(val, props.MapValProp); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + default: + p.back() + return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) + } + } + + dst.SetMapIndex(key, val) + continue + } + + // Check that it's not already set if it's not a repeated field. + if !props.Repeated && fieldSet[name] { + return p.errorf("non-repeated field %q was repeated", name) + } + + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Parse into the field. + fieldSet[name] = true + if err := p.readAny(dst, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } + if props.Required { + reqCount-- + } + + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + + } + + if reqCount > 0 { + return p.missingRequiredFieldError(sv) + } + return reqFieldErr +} + +// consumeExtName consumes extension name or expanded Any type URL and the +// following ']'. It returns the name or URL consumed. +func (p *textParser) consumeExtName() (string, error) { + tok := p.next() + if tok.err != nil { + return "", tok.err + } + + // If extension name or type url is quoted, it's a single token. + if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] { + name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0])) + if err != nil { + return "", err + } + return name, p.consumeToken("]") + } + + // Consume everything up to "]" + var parts []string + for tok.value != "]" { + parts = append(parts, tok.value) + tok = p.next() + if tok.err != nil { + return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) + } + if p.done && tok.value != "]" { + return "", p.errorf("unclosed type_url or extension name") + } + } + return strings.Join(parts, ""), nil +} + +// consumeOptionalSeparator consumes an optional semicolon or comma. +// It is used in readStruct to provide backward compatibility. +func (p *textParser) consumeOptionalSeparator() error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ";" && tok.value != "," { + p.back() + } + return nil +} + +func (p *textParser) readAny(v reflect.Value, props *Properties) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == "" { + return p.errorf("unexpected EOF") + } + if len(props.CustomType) > 0 { + if props.Repeated { + t := reflect.TypeOf(v.Interface()) + if t.Kind() == reflect.Slice { + tc := reflect.TypeOf(new(Marshaler)) + ok := t.Elem().Implements(tc.Elem()) + if ok { + fv := v + flen := fv.Len() + if flen == fv.Cap() { + nav := reflect.MakeSlice(v.Type(), flen, 2*flen+1) + reflect.Copy(nav, fv) + fv.Set(nav) + } + fv.SetLen(flen + 1) + + // Read one. + p.back() + return p.readAny(fv.Index(flen), props) + } + } + } + if reflect.TypeOf(v.Interface()).Kind() == reflect.Ptr { + custom := reflect.New(props.ctype.Elem()).Interface().(Unmarshaler) + err := custom.Unmarshal([]byte(tok.unquoted)) + if err != nil { + return p.errorf("%v %v: %v", err, v.Type(), tok.value) + } + v.Set(reflect.ValueOf(custom)) + } else { + custom := reflect.New(reflect.TypeOf(v.Interface())).Interface().(Unmarshaler) + err := custom.Unmarshal([]byte(tok.unquoted)) + if err != nil { + return p.errorf("%v %v: %v", err, v.Type(), tok.value) + } + v.Set(reflect.Indirect(reflect.ValueOf(custom))) + } + return nil + } + if props.StdTime { + fv := v + p.back() + props.StdTime = false + tproto := ×tamp{} + err := p.readAny(reflect.ValueOf(tproto).Elem(), props) + props.StdTime = true + if err != nil { + return err + } + tim, err := timestampFromProto(tproto) + if err != nil { + return err + } + if props.Repeated { + t := reflect.TypeOf(v.Interface()) + if t.Kind() == reflect.Slice { + if t.Elem().Kind() == reflect.Ptr { + ts := fv.Interface().([]*time.Time) + ts = append(ts, &tim) + fv.Set(reflect.ValueOf(ts)) + return nil + } else { + ts := fv.Interface().([]time.Time) + ts = append(ts, tim) + fv.Set(reflect.ValueOf(ts)) + return nil + } + } + } + if reflect.TypeOf(v.Interface()).Kind() == reflect.Ptr { + v.Set(reflect.ValueOf(&tim)) + } else { + v.Set(reflect.Indirect(reflect.ValueOf(&tim))) + } + return nil + } + if props.StdDuration { + fv := v + p.back() + props.StdDuration = false + dproto := &duration{} + err := p.readAny(reflect.ValueOf(dproto).Elem(), props) + props.StdDuration = true + if err != nil { + return err + } + dur, err := durationFromProto(dproto) + if err != nil { + return err + } + if props.Repeated { + t := reflect.TypeOf(v.Interface()) + if t.Kind() == reflect.Slice { + if t.Elem().Kind() == reflect.Ptr { + ds := fv.Interface().([]*time.Duration) + ds = append(ds, &dur) + fv.Set(reflect.ValueOf(ds)) + return nil + } else { + ds := fv.Interface().([]time.Duration) + ds = append(ds, dur) + fv.Set(reflect.ValueOf(ds)) + return nil + } + } + } + if reflect.TypeOf(v.Interface()).Kind() == reflect.Ptr { + v.Set(reflect.ValueOf(&dur)) + } else { + v.Set(reflect.Indirect(reflect.ValueOf(&dur))) + } + return nil + } + switch fv := v; fv.Kind() { + case reflect.Slice: + at := v.Type() + if at.Elem().Kind() == reflect.Uint8 { + // Special case for []byte + if tok.value[0] != '"' && tok.value[0] != '\'' { + // Deliberately written out here, as the error after + // this switch statement would write "invalid []byte: ...", + // which is not as user-friendly. + return p.errorf("invalid string: %v", tok.value) + } + bytes := []byte(tok.unquoted) + fv.Set(reflect.ValueOf(bytes)) + return nil + } + // Repeated field. + if tok.value == "[" { + // Repeated field with list notation, like [1,2,3]. + for { + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + err := p.readAny(fv.Index(fv.Len()-1), props) + if err != nil { + return err + } + ntok := p.next() + if ntok.err != nil { + return ntok.err + } + if ntok.value == "]" { + break + } + if ntok.value != "," { + return p.errorf("Expected ']' or ',' found %q", ntok.value) + } + } + return nil + } + // One value of the repeated field. + p.back() + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + return p.readAny(fv.Index(fv.Len()-1), props) + case reflect.Bool: + // true/1/t/True or false/f/0/False. + switch tok.value { + case "true", "1", "t", "True": + fv.SetBool(true) + return nil + case "false", "0", "f", "False": + fv.SetBool(false) + return nil + } + case reflect.Float32, reflect.Float64: + v := tok.value + // Ignore 'f' for compatibility with output generated by C++, but don't + // remove 'f' when the value is "-inf" or "inf". + if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" { + v = v[:len(v)-1] + } + if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil { + fv.SetFloat(f) + return nil + } + case reflect.Int8: + if x, err := strconv.ParseInt(tok.value, 0, 8); err == nil { + fv.SetInt(x) + return nil + } + case reflect.Int16: + if x, err := strconv.ParseInt(tok.value, 0, 16); err == nil { + fv.SetInt(x) + return nil + } + case reflect.Int32: + if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil { + fv.SetInt(x) + return nil + } + + if len(props.Enum) == 0 { + break + } + m, ok := enumValueMaps[props.Enum] + if !ok { + break + } + x, ok := m[tok.value] + if !ok { + break + } + fv.SetInt(int64(x)) + return nil + case reflect.Int64: + if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil { + fv.SetInt(x) + return nil + } + + case reflect.Ptr: + // A basic field (indirected through pointer), or a repeated message/group + p.back() + fv.Set(reflect.New(fv.Type().Elem())) + return p.readAny(fv.Elem(), props) + case reflect.String: + if tok.value[0] == '"' || tok.value[0] == '\'' { + fv.SetString(tok.unquoted) + return nil + } + case reflect.Struct: + var terminator string + switch tok.value { + case "{": + terminator = "}" + case "<": + terminator = ">" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + // TODO: Handle nested messages which implement encoding.TextUnmarshaler. + return p.readStruct(fv, terminator) + case reflect.Uint8: + if x, err := strconv.ParseUint(tok.value, 0, 8); err == nil { + fv.SetUint(x) + return nil + } + case reflect.Uint16: + if x, err := strconv.ParseUint(tok.value, 0, 16); err == nil { + fv.SetUint(x) + return nil + } + case reflect.Uint32: + if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { + fv.SetUint(uint64(x)) + return nil + } + case reflect.Uint64: + if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil { + fv.SetUint(x) + return nil + } + } + return p.errorf("invalid %v: %v", v.Type(), tok.value) +} + +// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb +// before starting to unmarshal, so any existing data in pb is always removed. +// If a required field is not set and no other error occurs, +// UnmarshalText returns *RequiredNotSetError. +func UnmarshalText(s string, pb Message) error { + if um, ok := pb.(encoding.TextUnmarshaler); ok { + return um.UnmarshalText([]byte(s)) + } + pb.Reset() + v := reflect.ValueOf(pb) + return newTextParser(s).readStruct(v.Elem(), "") +} diff --git a/vendor/github.com/gogo/protobuf/proto/timestamp.go b/vendor/github.com/gogo/protobuf/proto/timestamp.go new file mode 100644 index 000000000..9324f6542 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/timestamp.go @@ -0,0 +1,113 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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. + +package proto + +// This file implements operations on google.protobuf.Timestamp. + +import ( + "errors" + "fmt" + "time" +) + +const ( + // Seconds field of the earliest valid Timestamp. + // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). + minValidSeconds = -62135596800 + // Seconds field just after the latest valid Timestamp. + // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). + maxValidSeconds = 253402300800 +) + +// validateTimestamp determines whether a Timestamp is valid. +// A valid timestamp represents a time in the range +// [0001-01-01, 10000-01-01) and has a Nanos field +// in the range [0, 1e9). +// +// If the Timestamp is valid, validateTimestamp returns nil. +// Otherwise, it returns an error that describes +// the problem. +// +// Every valid Timestamp can be represented by a time.Time, but the converse is not true. +func validateTimestamp(ts *timestamp) error { + if ts == nil { + return errors.New("timestamp: nil Timestamp") + } + if ts.Seconds < minValidSeconds { + return fmt.Errorf("timestamp: %#v before 0001-01-01", ts) + } + if ts.Seconds >= maxValidSeconds { + return fmt.Errorf("timestamp: %#v after 10000-01-01", ts) + } + if ts.Nanos < 0 || ts.Nanos >= 1e9 { + return fmt.Errorf("timestamp: %#v: nanos not in range [0, 1e9)", ts) + } + return nil +} + +// TimestampFromProto converts a google.protobuf.Timestamp proto to a time.Time. +// It returns an error if the argument is invalid. +// +// Unlike most Go functions, if Timestamp returns an error, the first return value +// is not the zero time.Time. Instead, it is the value obtained from the +// time.Unix function when passed the contents of the Timestamp, in the UTC +// locale. This may or may not be a meaningful time; many invalid Timestamps +// do map to valid time.Times. +// +// A nil Timestamp returns an error. The first return value in that case is +// undefined. +func timestampFromProto(ts *timestamp) (time.Time, error) { + // Don't return the zero value on error, because corresponds to a valid + // timestamp. Instead return whatever time.Unix gives us. + var t time.Time + if ts == nil { + t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp + } else { + t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC() + } + return t, validateTimestamp(ts) +} + +// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. +// It returns an error if the resulting Timestamp is invalid. +func timestampProto(t time.Time) (*timestamp, error) { + seconds := t.Unix() + nanos := int32(t.Sub(time.Unix(seconds, 0))) + ts := ×tamp{ + Seconds: seconds, + Nanos: nanos, + } + if err := validateTimestamp(ts); err != nil { + return nil, err + } + return ts, nil +} diff --git a/vendor/github.com/gogo/protobuf/proto/timestamp_gogo.go b/vendor/github.com/gogo/protobuf/proto/timestamp_gogo.go new file mode 100644 index 000000000..38439fa99 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/timestamp_gogo.go @@ -0,0 +1,49 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2016, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "reflect" + "time" +) + +var timeType = reflect.TypeOf((*time.Time)(nil)).Elem() + +type timestamp struct { + Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"` + Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"` +} + +func (m *timestamp) Reset() { *m = timestamp{} } +func (*timestamp) ProtoMessage() {} +func (*timestamp) String() string { return "timestamp" } + +func init() { + RegisterType((*timestamp)(nil), "gogo.protobuf.proto.timestamp") +} diff --git a/vendor/github.com/gogo/protobuf/proto/wrappers.go b/vendor/github.com/gogo/protobuf/proto/wrappers.go new file mode 100644 index 000000000..b175d1b64 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/wrappers.go @@ -0,0 +1,1888 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2018, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "io" + "reflect" +) + +func makeStdDoubleValueMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*float64) + v := &float64Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*float64) + v := &float64Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdDoubleValuePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*float64) + v := &float64Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*float64) + v := &float64Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdDoubleValueSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(float64) + v := &float64Value{t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(float64) + v := &float64Value{t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdDoubleValuePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*float64) + v := &float64Value{*t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*float64) + v := &float64Value{*t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdDoubleValueUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &float64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(m.Value)) + return b[x:], nil + } +} + +func makeStdDoubleValuePtrUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &float64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&m.Value)) + return b[x:], nil + } +} + +func makeStdDoubleValuePtrSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &float64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdDoubleValueSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &float64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdFloatValueMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*float32) + v := &float32Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*float32) + v := &float32Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdFloatValuePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*float32) + v := &float32Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*float32) + v := &float32Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdFloatValueSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(float32) + v := &float32Value{t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(float32) + v := &float32Value{t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdFloatValuePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*float32) + v := &float32Value{*t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*float32) + v := &float32Value{*t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdFloatValueUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &float32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(m.Value)) + return b[x:], nil + } +} + +func makeStdFloatValuePtrUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &float32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&m.Value)) + return b[x:], nil + } +} + +func makeStdFloatValuePtrSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &float32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdFloatValueSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &float32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdInt64ValueMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*int64) + v := &int64Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*int64) + v := &int64Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdInt64ValuePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*int64) + v := &int64Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*int64) + v := &int64Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdInt64ValueSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(int64) + v := &int64Value{t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(int64) + v := &int64Value{t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdInt64ValuePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*int64) + v := &int64Value{*t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*int64) + v := &int64Value{*t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdInt64ValueUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &int64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(m.Value)) + return b[x:], nil + } +} + +func makeStdInt64ValuePtrUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &int64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&m.Value)) + return b[x:], nil + } +} + +func makeStdInt64ValuePtrSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &int64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdInt64ValueSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &int64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdUInt64ValueMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*uint64) + v := &uint64Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*uint64) + v := &uint64Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdUInt64ValuePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*uint64) + v := &uint64Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*uint64) + v := &uint64Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdUInt64ValueSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(uint64) + v := &uint64Value{t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(uint64) + v := &uint64Value{t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdUInt64ValuePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*uint64) + v := &uint64Value{*t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*uint64) + v := &uint64Value{*t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdUInt64ValueUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &uint64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(m.Value)) + return b[x:], nil + } +} + +func makeStdUInt64ValuePtrUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &uint64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&m.Value)) + return b[x:], nil + } +} + +func makeStdUInt64ValuePtrSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &uint64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdUInt64ValueSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &uint64Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdInt32ValueMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*int32) + v := &int32Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*int32) + v := &int32Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdInt32ValuePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*int32) + v := &int32Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*int32) + v := &int32Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdInt32ValueSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(int32) + v := &int32Value{t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(int32) + v := &int32Value{t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdInt32ValuePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*int32) + v := &int32Value{*t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*int32) + v := &int32Value{*t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdInt32ValueUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &int32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(m.Value)) + return b[x:], nil + } +} + +func makeStdInt32ValuePtrUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &int32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&m.Value)) + return b[x:], nil + } +} + +func makeStdInt32ValuePtrSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &int32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdInt32ValueSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &int32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdUInt32ValueMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*uint32) + v := &uint32Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*uint32) + v := &uint32Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdUInt32ValuePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*uint32) + v := &uint32Value{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*uint32) + v := &uint32Value{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdUInt32ValueSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(uint32) + v := &uint32Value{t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(uint32) + v := &uint32Value{t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdUInt32ValuePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*uint32) + v := &uint32Value{*t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*uint32) + v := &uint32Value{*t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdUInt32ValueUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &uint32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(m.Value)) + return b[x:], nil + } +} + +func makeStdUInt32ValuePtrUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &uint32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&m.Value)) + return b[x:], nil + } +} + +func makeStdUInt32ValuePtrSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &uint32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdUInt32ValueSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &uint32Value{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdBoolValueMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*bool) + v := &boolValue{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*bool) + v := &boolValue{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdBoolValuePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*bool) + v := &boolValue{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*bool) + v := &boolValue{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdBoolValueSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(bool) + v := &boolValue{t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(bool) + v := &boolValue{t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdBoolValuePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*bool) + v := &boolValue{*t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*bool) + v := &boolValue{*t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdBoolValueUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &boolValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(m.Value)) + return b[x:], nil + } +} + +func makeStdBoolValuePtrUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &boolValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&m.Value)) + return b[x:], nil + } +} + +func makeStdBoolValuePtrSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &boolValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdBoolValueSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &boolValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdStringValueMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*string) + v := &stringValue{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*string) + v := &stringValue{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdStringValuePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*string) + v := &stringValue{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*string) + v := &stringValue{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdStringValueSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(string) + v := &stringValue{t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(string) + v := &stringValue{t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdStringValuePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*string) + v := &stringValue{*t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*string) + v := &stringValue{*t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdStringValueUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &stringValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(m.Value)) + return b[x:], nil + } +} + +func makeStdStringValuePtrUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &stringValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&m.Value)) + return b[x:], nil + } +} + +func makeStdStringValuePtrSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &stringValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdStringValueSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &stringValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdBytesValueMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + t := ptr.asPointerTo(u.typ).Interface().(*[]byte) + v := &bytesValue{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + t := ptr.asPointerTo(u.typ).Interface().(*[]byte) + v := &bytesValue{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdBytesValuePtrMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + if ptr.isNil() { + return 0 + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*[]byte) + v := &bytesValue{*t} + siz := Size(v) + return tagsize + SizeVarint(uint64(siz)) + siz + }, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + if ptr.isNil() { + return b, nil + } + t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*[]byte) + v := &bytesValue{*t} + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(buf))) + b = append(b, buf...) + return b, nil + } +} + +func makeStdBytesValueSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(u.typ) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().([]byte) + v := &bytesValue{t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(u.typ) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().([]byte) + v := &bytesValue{t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdBytesValuePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + n := 0 + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*[]byte) + v := &bytesValue{*t} + siz := Size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getSlice(reflect.PtrTo(u.typ)) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + t := elem.Interface().(*[]byte) + v := &bytesValue{*t} + siz := Size(v) + buf, err := Marshal(v) + if err != nil { + return nil, err + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(siz)) + b = append(b, buf...) + } + + return b, nil + } +} + +func makeStdBytesValueUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &bytesValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(sub.typ).Elem() + s.Set(reflect.ValueOf(m.Value)) + return b[x:], nil + } +} + +func makeStdBytesValuePtrUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &bytesValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem() + s.Set(reflect.ValueOf(&m.Value)) + return b[x:], nil + } +} + +func makeStdBytesValuePtrSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &bytesValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(reflect.PtrTo(sub.typ)) + newSlice := reflect.Append(slice, reflect.ValueOf(&m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} + +func makeStdBytesValueSliceUnmarshaler(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return nil, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + m := &bytesValue{} + if err := Unmarshal(b[:x], m); err != nil { + return nil, err + } + slice := f.getSlice(sub.typ) + newSlice := reflect.Append(slice, reflect.ValueOf(m.Value)) + slice.Set(newSlice) + return b[x:], nil + } +} diff --git a/vendor/github.com/gogo/protobuf/proto/wrappers_gogo.go b/vendor/github.com/gogo/protobuf/proto/wrappers_gogo.go new file mode 100644 index 000000000..c1cf7bf85 --- /dev/null +++ b/vendor/github.com/gogo/protobuf/proto/wrappers_gogo.go @@ -0,0 +1,113 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2018, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +type float64Value struct { + Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *float64Value) Reset() { *m = float64Value{} } +func (*float64Value) ProtoMessage() {} +func (*float64Value) String() string { return "float64" } + +type float32Value struct { + Value float32 `protobuf:"fixed32,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *float32Value) Reset() { *m = float32Value{} } +func (*float32Value) ProtoMessage() {} +func (*float32Value) String() string { return "float32" } + +type int64Value struct { + Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *int64Value) Reset() { *m = int64Value{} } +func (*int64Value) ProtoMessage() {} +func (*int64Value) String() string { return "int64" } + +type uint64Value struct { + Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *uint64Value) Reset() { *m = uint64Value{} } +func (*uint64Value) ProtoMessage() {} +func (*uint64Value) String() string { return "uint64" } + +type int32Value struct { + Value int32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *int32Value) Reset() { *m = int32Value{} } +func (*int32Value) ProtoMessage() {} +func (*int32Value) String() string { return "int32" } + +type uint32Value struct { + Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *uint32Value) Reset() { *m = uint32Value{} } +func (*uint32Value) ProtoMessage() {} +func (*uint32Value) String() string { return "uint32" } + +type boolValue struct { + Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *boolValue) Reset() { *m = boolValue{} } +func (*boolValue) ProtoMessage() {} +func (*boolValue) String() string { return "bool" } + +type stringValue struct { + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *stringValue) Reset() { *m = stringValue{} } +func (*stringValue) ProtoMessage() {} +func (*stringValue) String() string { return "string" } + +type bytesValue struct { + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *bytesValue) Reset() { *m = bytesValue{} } +func (*bytesValue) ProtoMessage() {} +func (*bytesValue) String() string { return "[]byte" } + +func init() { + RegisterType((*float64Value)(nil), "gogo.protobuf.proto.DoubleValue") + RegisterType((*float32Value)(nil), "gogo.protobuf.proto.FloatValue") + RegisterType((*int64Value)(nil), "gogo.protobuf.proto.Int64Value") + RegisterType((*uint64Value)(nil), "gogo.protobuf.proto.UInt64Value") + RegisterType((*int32Value)(nil), "gogo.protobuf.proto.Int32Value") + RegisterType((*uint32Value)(nil), "gogo.protobuf.proto.UInt32Value") + RegisterType((*boolValue)(nil), "gogo.protobuf.proto.BoolValue") + RegisterType((*stringValue)(nil), "gogo.protobuf.proto.StringValue") + RegisterType((*bytesValue)(nil), "gogo.protobuf.proto.BytesValue") +} diff --git a/vendor/github.com/golangci/check/LICENSE b/vendor/github.com/golangci/check/LICENSE new file mode 100644 index 000000000..5a1774b8e --- /dev/null +++ b/vendor/github.com/golangci/check/LICENSE @@ -0,0 +1,674 @@ +GNU 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. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + opennota Copyright (C) 2013 opennota + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +{http://www.gnu.org/licenses/}. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +{http://www.gnu.org/philosophy/why-not-lgpl.html}. diff --git a/vendor/github.com/golangci/check/cmd/structcheck/structcheck.go b/vendor/github.com/golangci/check/cmd/structcheck/structcheck.go new file mode 100644 index 000000000..5dc5f8380 --- /dev/null +++ b/vendor/github.com/golangci/check/cmd/structcheck/structcheck.go @@ -0,0 +1,193 @@ +// structcheck +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package structcheck + +import ( + "flag" + "fmt" + "go/ast" + "go/token" + "go/types" + + "golang.org/x/tools/go/loader" +) + +var ( + assignmentsOnly = flag.Bool("structcheck.a", false, "Count assignments only") + loadTestFiles = flag.Bool("structcheck.t", false, "Load test files too") + buildTags = flag.String("structcheck.tags", "", "Build tags") +) + +type visitor struct { + prog *loader.Program + pkg *loader.PackageInfo + m map[types.Type]map[string]int + skip map[types.Type]struct{} +} + +func (v *visitor) decl(t types.Type, fieldName string) { + if _, ok := v.m[t]; !ok { + v.m[t] = make(map[string]int) + } + if _, ok := v.m[t][fieldName]; !ok { + v.m[t][fieldName] = 0 + } +} + +func (v *visitor) assignment(t types.Type, fieldName string) { + if _, ok := v.m[t]; !ok { + v.m[t] = make(map[string]int) + } + if _, ok := v.m[t][fieldName]; ok { + v.m[t][fieldName]++ + } else { + v.m[t][fieldName] = 1 + } +} + +func (v *visitor) typeSpec(node *ast.TypeSpec) { + if strukt, ok := node.Type.(*ast.StructType); ok { + t := v.pkg.Info.Defs[node.Name].Type() + for _, f := range strukt.Fields.List { + if len(f.Names) > 0 { + fieldName := f.Names[0].Name + v.decl(t, fieldName) + } + } + } +} + +func (v *visitor) typeAndFieldName(expr *ast.SelectorExpr) (types.Type, string, bool) { + selection := v.pkg.Info.Selections[expr] + if selection == nil { + return nil, "", false + } + recv := selection.Recv() + if ptr, ok := recv.(*types.Pointer); ok { + recv = ptr.Elem() + } + return recv, selection.Obj().Name(), true +} + +func (v *visitor) assignStmt(node *ast.AssignStmt) { + for _, lhs := range node.Lhs { + var selector *ast.SelectorExpr + switch expr := lhs.(type) { + case *ast.SelectorExpr: + selector = expr + case *ast.IndexExpr: + if expr, ok := expr.X.(*ast.SelectorExpr); ok { + selector = expr + } + } + if selector != nil { + if t, fn, ok := v.typeAndFieldName(selector); ok { + v.assignment(t, fn) + } + } + } +} + +func (v *visitor) compositeLiteral(node *ast.CompositeLit) { + t := v.pkg.Info.Types[node.Type].Type + for _, expr := range node.Elts { + if kv, ok := expr.(*ast.KeyValueExpr); ok { + if ident, ok := kv.Key.(*ast.Ident); ok { + v.assignment(t, ident.Name) + } + } else { + // Struct literal with positional values. + // All the fields are assigned. + v.skip[t] = struct{}{} + break + } + } +} + +func (v *visitor) Visit(node ast.Node) ast.Visitor { + switch node := node.(type) { + case *ast.TypeSpec: + v.typeSpec(node) + + case *ast.AssignStmt: + if *assignmentsOnly { + v.assignStmt(node) + } + + case *ast.SelectorExpr: + if !*assignmentsOnly { + if t, fn, ok := v.typeAndFieldName(node); ok { + v.assignment(t, fn) + } + } + + case *ast.CompositeLit: + v.compositeLiteral(node) + } + + return v +} + +type Issue struct { + Pos token.Position + Type string + FieldName string +} + +func Run(program *loader.Program, reportExported bool) []Issue { + var issues []Issue + for _, pkg := range program.InitialPackages() { + visitor := &visitor{ + m: make(map[types.Type]map[string]int), + skip: make(map[types.Type]struct{}), + prog: program, + pkg: pkg, + } + for _, f := range pkg.Files { + ast.Walk(visitor, f) + } + + for t := range visitor.m { + if _, skip := visitor.skip[t]; skip { + continue + } + for fieldName, v := range visitor.m[t] { + if !reportExported && ast.IsExported(fieldName) { + continue + } + if v == 0 { + field, _, _ := types.LookupFieldOrMethod(t, false, pkg.Pkg, fieldName) + if field == nil { + fmt.Printf("%s: unknown field or method: %s.%s\n", pkg.Pkg.Path(), t, fieldName) + continue + } + if fieldName == "XMLName" { + if named, ok := field.Type().(*types.Named); ok && named.Obj().Pkg().Path() == "encoding/xml" { + continue + } + } + pos := program.Fset.Position(field.Pos()) + issues = append(issues, Issue{ + Pos: pos, + Type: types.TypeString(t, nil), + FieldName: fieldName, + }) + } + } + } + } + + return issues +} diff --git a/vendor/github.com/golangci/check/cmd/varcheck/varcheck.go b/vendor/github.com/golangci/check/cmd/varcheck/varcheck.go new file mode 100644 index 000000000..8e93e0473 --- /dev/null +++ b/vendor/github.com/golangci/check/cmd/varcheck/varcheck.go @@ -0,0 +1,163 @@ +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package varcheck + +import ( + "flag" + "go/ast" + "go/token" + "strings" + + "go/types" + + "golang.org/x/tools/go/loader" +) + +var ( + buildTags = flag.String("varcheck.tags", "", "Build tags") +) + +type object struct { + pkgPath string + name string +} + +type visitor struct { + prog *loader.Program + pkg *loader.PackageInfo + uses map[object]int + positions map[object]token.Position + insideFunc bool +} + +func getKey(obj types.Object) object { + if obj == nil { + return object{} + } + + pkg := obj.Pkg() + pkgPath := "" + if pkg != nil { + pkgPath = pkg.Path() + } + + return object{ + pkgPath: pkgPath, + name: obj.Name(), + } +} + +func (v *visitor) decl(obj types.Object) { + key := getKey(obj) + if _, ok := v.uses[key]; !ok { + v.uses[key] = 0 + } + if _, ok := v.positions[key]; !ok { + v.positions[key] = v.prog.Fset.Position(obj.Pos()) + } +} + +func (v *visitor) use(obj types.Object) { + key := getKey(obj) + if _, ok := v.uses[key]; ok { + v.uses[key]++ + } else { + v.uses[key] = 1 + } +} + +func isReserved(name string) bool { + return name == "_" || strings.HasPrefix(strings.ToLower(name), "_cgo_") +} + +func (v *visitor) Visit(node ast.Node) ast.Visitor { + switch node := node.(type) { + case *ast.Ident: + v.use(v.pkg.Info.Uses[node]) + + case *ast.ValueSpec: + if !v.insideFunc { + for _, ident := range node.Names { + if !isReserved(ident.Name) { + v.decl(v.pkg.Info.Defs[ident]) + } + } + } + for _, val := range node.Values { + ast.Walk(v, val) + } + if node.Type != nil { + ast.Walk(v, node.Type) + } + return nil + + case *ast.FuncDecl: + if node.Body != nil { + v.insideFunc = true + ast.Walk(v, node.Body) + v.insideFunc = false + } + + if node.Recv != nil { + ast.Walk(v, node.Recv) + } + if node.Type != nil { + ast.Walk(v, node.Type) + } + + return nil + } + + return v +} + +type Issue struct { + Pos token.Position + VarName string +} + +func Run(program *loader.Program, reportExported bool) []Issue { + var issues []Issue + uses := make(map[object]int) + positions := make(map[object]token.Position) + + for _, pkgInfo := range program.InitialPackages() { + if pkgInfo.Pkg.Path() == "unsafe" { + continue + } + + v := &visitor{ + prog: program, + pkg: pkgInfo, + uses: uses, + positions: positions, + } + + for _, f := range v.pkg.Files { + ast.Walk(v, f) + } + } + + for obj, useCount := range uses { + if useCount == 0 && (reportExported || !ast.IsExported(obj.name)) { + pos := positions[obj] + issues = append(issues, Issue{ + Pos: pos, + VarName: obj.name, + }) + } + } + + return issues +} diff --git a/vendor/github.com/golangci/dupl/.travis.yml b/vendor/github.com/golangci/dupl/.travis.yml new file mode 100644 index 000000000..33de24c0f --- /dev/null +++ b/vendor/github.com/golangci/dupl/.travis.yml @@ -0,0 +1,5 @@ +language: go +go: + - 1.3 + - 1.8 + - 1.9 diff --git a/vendor/github.com/golangci/dupl/LICENSE b/vendor/github.com/golangci/dupl/LICENSE new file mode 100644 index 000000000..ab317d841 --- /dev/null +++ b/vendor/github.com/golangci/dupl/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Michal Bohuslávek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/golangci/dupl/README.md b/vendor/github.com/golangci/dupl/README.md new file mode 100644 index 000000000..f34901d7a --- /dev/null +++ b/vendor/github.com/golangci/dupl/README.md @@ -0,0 +1,63 @@ +# dupl [![Build Status](https://travis-ci.org/mibk/dupl.png)](https://travis-ci.org/mibk/dupl) + +**dupl** is a tool written in Go for finding code clones. So far it can find clones only +in the Go source files. The method uses suffix tree for serialized ASTs. It ignores values +of AST nodes. It just operates with their types (e.g. `if a == 13 {}` and `if x == 100 {}` are +considered the same provided it exceeds the minimal token sequence size). + +Due to the used method dupl can report so called "false positives" on the output. These are +the ones we do not consider clones (whether they are too small, or the values of the matched +tokens are completely different). + +## Installation + +```bash +go get -u github.com/golangci/dupl +``` + +## Usage + +``` +Usage of dupl: + dupl [flags] [paths] + +Paths: + If the given path is a file, dupl will use it regardless of + the file extension. If it is a directory it will recursively + search for *.go files in that directory. + + If no path is given dupl will recursively search for *.go + files in the current directory. + +Flags: + -files + read file names from stdin one at each line + -html + output the results as HTML, including duplicate code fragments + -plumbing + plumbing (easy-to-parse) output for consumption by scripts or tools + -t, -threshold size + minimum token sequence size as a clone (default 15) + -vendor + check files in vendor directory + -v, -verbose + explain what is being done + +Examples: + dupl -t 100 + Search clones in the current directory of size at least + 100 tokens. + dupl $(find app/ -name '*_test.go') + Search for clones in tests in the app directory. + find app/ -name '*_test.go' |dupl -files + The same as above. +``` + +## Example + +The reduced output of this command with the following parameters for the [Docker](https://www.docker.com) source code +looks like [this](http://htmlpreview.github.io/?https://github.com/golangci/dupl/blob/master/_output_example/docker.html). + +```bash +$ dupl -t 200 -html >docker.html +``` diff --git a/vendor/github.com/golangci/dupl/job/buildtree.go b/vendor/github.com/golangci/dupl/job/buildtree.go new file mode 100644 index 000000000..e9aad54c0 --- /dev/null +++ b/vendor/github.com/golangci/dupl/job/buildtree.go @@ -0,0 +1,22 @@ +package job + +import ( + "github.com/golangci/dupl/suffixtree" + "github.com/golangci/dupl/syntax" +) + +func BuildTree(schan chan []*syntax.Node) (t *suffixtree.STree, d *[]*syntax.Node, done chan bool) { + t = suffixtree.New() + data := make([]*syntax.Node, 0, 100) + done = make(chan bool) + go func() { + for seq := range schan { + data = append(data, seq...) + for _, node := range seq { + t.Update(node) + } + } + done <- true + }() + return t, &data, done +} diff --git a/vendor/github.com/golangci/dupl/job/parse.go b/vendor/github.com/golangci/dupl/job/parse.go new file mode 100644 index 000000000..eb9d7c625 --- /dev/null +++ b/vendor/github.com/golangci/dupl/job/parse.go @@ -0,0 +1,36 @@ +package job + +import ( + "log" + + "github.com/golangci/dupl/syntax" + "github.com/golangci/dupl/syntax/golang" +) + +func Parse(fchan chan string) chan []*syntax.Node { + + // parse AST + achan := make(chan *syntax.Node) + go func() { + for file := range fchan { + ast, err := golang.Parse(file) + if err != nil { + log.Println(err) + continue + } + achan <- ast + } + close(achan) + }() + + // serialize + schan := make(chan []*syntax.Node) + go func() { + for ast := range achan { + seq := syntax.Serialize(ast) + schan <- seq + } + close(schan) + }() + return schan +} diff --git a/vendor/github.com/golangci/dupl/main.go b/vendor/github.com/golangci/dupl/main.go new file mode 100644 index 000000000..3030a97ae --- /dev/null +++ b/vendor/github.com/golangci/dupl/main.go @@ -0,0 +1,148 @@ +package dupl + +import ( + "flag" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "sort" + + "github.com/golangci/dupl/job" + "github.com/golangci/dupl/printer" + "github.com/golangci/dupl/syntax" +) + +const defaultThreshold = 15 + +var ( + paths = []string{"."} + vendor = flag.Bool("dupl.vendor", false, "") + verbose = flag.Bool("dupl.verbose", false, "") + files = flag.Bool("dupl.files", false, "") + + html = flag.Bool("dupl.html", false, "") + plumbing = flag.Bool("dupl.plumbing", false, "") +) + +const ( + vendorDirPrefix = "vendor" + string(filepath.Separator) + vendorDirInPath = string(filepath.Separator) + vendorDirPrefix +) + +func init() { + flag.BoolVar(verbose, "dupl.v", false, "alias for -verbose") +} + +func Run(files []string, threshold int) ([]printer.Issue, error) { + fchan := make(chan string, 1024) + go func() { + for _, f := range files { + fchan <- f + } + close(fchan) + }() + schan := job.Parse(fchan) + t, data, done := job.BuildTree(schan) + <-done + + // finish stream + t.Update(&syntax.Node{Type: -1}) + + mchan := t.FindDuplOver(threshold) + duplChan := make(chan syntax.Match) + go func() { + for m := range mchan { + match := syntax.FindSyntaxUnits(*data, m, threshold) + if len(match.Frags) > 0 { + duplChan <- match + } + } + close(duplChan) + }() + + return makeIssues(duplChan) +} + +func makeIssues(duplChan <-chan syntax.Match) ([]printer.Issue, error) { + groups := make(map[string][][]*syntax.Node) + for dupl := range duplChan { + groups[dupl.Hash] = append(groups[dupl.Hash], dupl.Frags...) + } + keys := make([]string, 0, len(groups)) + for k := range groups { + keys = append(keys, k) + } + sort.Strings(keys) + + p := printer.NewPlumbing(ioutil.ReadFile) + + var issues []printer.Issue + for _, k := range keys { + uniq := unique(groups[k]) + if len(uniq) > 1 { + i, err := p.MakeIssues(uniq) + if err != nil { + return nil, err + } + issues = append(issues, i...) + } + } + + return issues, nil +} + +func unique(group [][]*syntax.Node) [][]*syntax.Node { + fileMap := make(map[string]map[int]struct{}) + + var newGroup [][]*syntax.Node + for _, seq := range group { + node := seq[0] + file, ok := fileMap[node.Filename] + if !ok { + file = make(map[int]struct{}) + fileMap[node.Filename] = file + } + if _, ok := file[node.Pos]; !ok { + file[node.Pos] = struct{}{} + newGroup = append(newGroup, seq) + } + } + return newGroup +} + +func usage() { + fmt.Fprintln(os.Stderr, `Usage: dupl [flags] [paths] + +Paths: + If the given path is a file, dupl will use it regardless of + the file extension. If it is a directory, it will recursively + search for *.go files in that directory. + + If no path is given, dupl will recursively search for *.go + files in the current directory. + +Flags: + -files + read file names from stdin one at each line + -html + output the results as HTML, including duplicate code fragments + -plumbing + plumbing (easy-to-parse) output for consumption by scripts or tools + -t, -threshold size + minimum token sequence size as a clone (default 15) + -vendor + check files in vendor directory + -v, -verbose + explain what is being done + +Examples: + dupl -t 100 + Search clones in the current directory of size at least + 100 tokens. + dupl $(find app/ -name '*_test.go') + Search for clones in tests in the app directory. + find app/ -name '*_test.go' |dupl -files + The same as above.`) + os.Exit(2) +} diff --git a/vendor/github.com/golangci/dupl/printer/html.go b/vendor/github.com/golangci/dupl/printer/html.go new file mode 100644 index 000000000..5ad9e25c7 --- /dev/null +++ b/vendor/github.com/golangci/dupl/printer/html.go @@ -0,0 +1,120 @@ +package printer + +import ( + "bytes" + "fmt" + "io" + "regexp" + "sort" + + "github.com/golangci/dupl/syntax" +) + +type html struct { + iota int + w io.Writer + ReadFile +} + +func NewHTML(w io.Writer, fread ReadFile) Printer { + return &html{w: w, ReadFile: fread} +} + +func (p *html) PrintHeader() error { + _, err := fmt.Fprint(p.w, ` + +Duplicates + +`) + return err +} + +func (p *html) PrintClones(dups [][]*syntax.Node) error { + p.iota++ + fmt.Fprintf(p.w, "

#%d found %d clones

\n", p.iota, len(dups)) + + clones := make([]clone, len(dups)) + for i, dup := range dups { + cnt := len(dup) + if cnt == 0 { + panic("zero length dup") + } + nstart := dup[0] + nend := dup[cnt-1] + + file, err := p.ReadFile(nstart.Filename) + if err != nil { + return err + } + + lineStart, _ := blockLines(file, nstart.Pos, nend.End) + cl := clone{filename: nstart.Filename, lineStart: lineStart} + start := findLineBeg(file, nstart.Pos) + content := append(toWhitespace(file[start:nstart.Pos]), file[nstart.Pos:nend.End]...) + cl.fragment = deindent(content) + clones[i] = cl + } + + sort.Sort(byNameAndLine(clones)) + for _, cl := range clones { + fmt.Fprintf(p.w, "

%s:%d

\n
%s
\n", cl.filename, cl.lineStart, cl.fragment) + } + return nil +} + +func (*html) PrintFooter() error { return nil } + +func findLineBeg(file []byte, index int) int { + for i := index; i >= 0; i-- { + if file[i] == '\n' { + return i + 1 + } + } + return 0 +} + +func toWhitespace(str []byte) []byte { + var out []byte + for _, c := range bytes.Runes(str) { + if c == '\t' { + out = append(out, '\t') + } else { + out = append(out, ' ') + } + } + return out +} + +func deindent(block []byte) []byte { + const maxVal = 99 + min := maxVal + re := regexp.MustCompile(`(^|\n)(\t*)\S`) + for _, line := range re.FindAllSubmatch(block, -1) { + indent := line[2] + if len(indent) < min { + min = len(indent) + } + } + if min == 0 || min == maxVal { + return block + } + block = block[min:] +Loop: + for i := 0; i < len(block); i++ { + if block[i] == '\n' && i != len(block)-1 { + for j := 0; j < min; j++ { + if block[i+j+1] != '\t' { + continue Loop + } + } + block = append(block[:i+1], block[i+1+min:]...) + } + } + return block +} diff --git a/vendor/github.com/golangci/dupl/printer/plumbing.go b/vendor/github.com/golangci/dupl/printer/plumbing.go new file mode 100644 index 000000000..cf39d01b7 --- /dev/null +++ b/vendor/github.com/golangci/dupl/printer/plumbing.go @@ -0,0 +1,50 @@ +package printer + +import ( + "sort" + + "github.com/golangci/dupl/syntax" +) + +type Clone clone + +func (c Clone) Filename() string { + return c.filename +} + +func (c Clone) LineStart() int { + return c.lineStart +} + +func (c Clone) LineEnd() int { + return c.lineEnd +} + +type Issue struct { + From, To Clone +} + +type Plumbing struct { + ReadFile +} + +func NewPlumbing(fread ReadFile) *Plumbing { + return &Plumbing{fread} +} + +func (p *Plumbing) MakeIssues(dups [][]*syntax.Node) ([]Issue, error) { + clones, err := prepareClonesInfo(p.ReadFile, dups) + if err != nil { + return nil, err + } + sort.Sort(byNameAndLine(clones)) + var issues []Issue + for i, cl := range clones { + nextCl := clones[(i+1)%len(clones)] + issues = append(issues, Issue{ + From: Clone(cl), + To: Clone(nextCl), + }) + } + return issues, nil +} diff --git a/vendor/github.com/golangci/dupl/printer/printer.go b/vendor/github.com/golangci/dupl/printer/printer.go new file mode 100644 index 000000000..385217bfc --- /dev/null +++ b/vendor/github.com/golangci/dupl/printer/printer.go @@ -0,0 +1,11 @@ +package printer + +import "github.com/golangci/dupl/syntax" + +type ReadFile func(filename string) ([]byte, error) + +type Printer interface { + PrintHeader() error + PrintClones(dups [][]*syntax.Node) error + PrintFooter() error +} diff --git a/vendor/github.com/golangci/dupl/printer/text.go b/vendor/github.com/golangci/dupl/printer/text.go new file mode 100644 index 000000000..8359fa76f --- /dev/null +++ b/vendor/github.com/golangci/dupl/printer/text.go @@ -0,0 +1,100 @@ +package printer + +import ( + "fmt" + "io" + "sort" + + "github.com/golangci/dupl/syntax" +) + +type text struct { + cnt int + w io.Writer + ReadFile +} + +func NewText(w io.Writer, fread ReadFile) Printer { + return &text{w: w, ReadFile: fread} +} + +func (p *text) PrintHeader() error { return nil } + +func (p *text) PrintClones(dups [][]*syntax.Node) error { + p.cnt++ + fmt.Fprintf(p.w, "found %d clones:\n", len(dups)) + clones, err := prepareClonesInfo(p.ReadFile, dups) + if err != nil { + return err + } + sort.Sort(byNameAndLine(clones)) + for _, cl := range clones { + fmt.Fprintf(p.w, " %s:%d,%d\n", cl.filename, cl.lineStart, cl.lineEnd) + } + return nil +} + +func (p *text) PrintFooter() error { + _, err := fmt.Fprintf(p.w, "\nFound total %d clone groups.\n", p.cnt) + return err +} + +func prepareClonesInfo(fread ReadFile, dups [][]*syntax.Node) ([]clone, error) { + clones := make([]clone, len(dups)) + for i, dup := range dups { + cnt := len(dup) + if cnt == 0 { + panic("zero length dup") + } + nstart := dup[0] + nend := dup[cnt-1] + + file, err := fread(nstart.Filename) + if err != nil { + return nil, err + } + + cl := clone{filename: nstart.Filename} + cl.lineStart, cl.lineEnd = blockLines(file, nstart.Pos, nend.End) + clones[i] = cl + } + return clones, nil +} + +func blockLines(file []byte, from, to int) (int, int) { + line := 1 + lineStart, lineEnd := 0, 0 + for offset, b := range file { + if b == '\n' { + line++ + } + if offset == from { + lineStart = line + } + if offset == to-1 { + lineEnd = line + break + } + } + return lineStart, lineEnd +} + +type clone struct { + filename string + lineStart int + lineEnd int + fragment []byte +} + +type byNameAndLine []clone + +func (c byNameAndLine) Len() int { return len(c) } + +func (c byNameAndLine) Swap(i, j int) { c[i], c[j] = c[j], c[i] } + +func (c byNameAndLine) Less(i, j int) bool { + if c[i].filename == c[j].filename { + return c[i].lineStart < c[j].lineStart + } + return c[i].filename < c[j].filename +} diff --git a/vendor/github.com/golangci/dupl/suffixtree/dupl.go b/vendor/github.com/golangci/dupl/suffixtree/dupl.go new file mode 100644 index 000000000..ab145b4f3 --- /dev/null +++ b/vendor/github.com/golangci/dupl/suffixtree/dupl.go @@ -0,0 +1,98 @@ +package suffixtree + +import "sort" + +type Match struct { + Ps []Pos + Len Pos +} + +type posList struct { + positions []Pos +} + +func newPosList() *posList { + return &posList{make([]Pos, 0)} +} + +func (p *posList) append(p2 *posList) { + p.positions = append(p.positions, p2.positions...) +} + +func (p *posList) add(pos Pos) { + p.positions = append(p.positions, pos) +} + +type contextList struct { + lists map[int]*posList +} + +func newContextList() *contextList { + return &contextList{make(map[int]*posList)} +} + +func (c *contextList) getAll() []Pos { + keys := make([]int, 0, len(c.lists)) + for k := range c.lists { + keys = append(keys, k) + } + sort.Ints(keys) + var ps []Pos + for _, k := range keys { + ps = append(ps, c.lists[k].positions...) + } + return ps +} + +func (c *contextList) append(c2 *contextList) { + for lc, pl := range c2.lists { + if _, ok := c.lists[lc]; ok { + c.lists[lc].append(pl) + } else { + c.lists[lc] = pl + } + } +} + +// FindDuplOver find pairs of maximal duplicities over a threshold +// length. +func (t *STree) FindDuplOver(threshold int) <-chan Match { + auxTran := newTran(0, 0, t.root) + ch := make(chan Match) + go func() { + walkTrans(auxTran, 0, threshold, ch) + close(ch) + }() + return ch +} + +func walkTrans(parent *tran, length, threshold int, ch chan<- Match) *contextList { + s := parent.state + + cl := newContextList() + + if len(s.trans) == 0 { + pl := newPosList() + start := parent.end + 1 - Pos(length) + pl.add(start) + ch := 0 + if start > 0 { + ch = s.tree.data[start-1].Val() + } + cl.lists[ch] = pl + return cl + } + + for _, t := range s.trans { + ln := length + t.len() + cl2 := walkTrans(t, ln, threshold, ch) + if ln >= threshold { + cl.append(cl2) + } + } + if length >= threshold && len(cl.lists) > 1 { + m := Match{cl.getAll(), Pos(length)} + ch <- m + } + return cl +} diff --git a/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go b/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go new file mode 100644 index 000000000..738015025 --- /dev/null +++ b/vendor/github.com/golangci/dupl/suffixtree/suffixtree.go @@ -0,0 +1,216 @@ +package suffixtree + +import ( + "bytes" + "fmt" + "math" + "strings" +) + +const infinity = math.MaxInt32 + +// Pos denotes position in data slice. +type Pos int32 + +type Token interface { + Val() int +} + +// STree is a struct representing a suffix tree. +type STree struct { + data []Token + root *state + auxState *state // auxiliary state + + // active point + s *state + start, end Pos +} + +// New creates new suffix tree. +func New() *STree { + t := new(STree) + t.data = make([]Token, 0, 50) + t.root = newState(t) + t.auxState = newState(t) + t.root.linkState = t.auxState + t.s = t.root + return t +} + +// Update refreshes the suffix tree to by new data. +func (t *STree) Update(data ...Token) { + t.data = append(t.data, data...) + for _ = range data { + t.update() + t.s, t.start = t.canonize(t.s, t.start, t.end) + t.end++ + } +} + +// update transforms suffix tree T(n) to T(n+1). +func (t *STree) update() { + oldr := t.root + + // (s, (start, end)) is the canonical reference pair for the active point + s := t.s + start, end := t.start, t.end + var r *state + for { + var endPoint bool + r, endPoint = t.testAndSplit(s, start, end-1) + if endPoint { + break + } + r.fork(end) + if oldr != t.root { + oldr.linkState = r + } + oldr = r + s, start = t.canonize(s.linkState, start, end-1) + } + if oldr != t.root { + oldr.linkState = r + } + + // update active point + t.s = s + t.start = start +} + +// testAndSplit tests whether a state with canonical ref. pair +// (s, (start, end)) is the end point, that is, a state that have +// a c-transition. If not, then state (exs, (start, end)) is made +// explicit (if not already so). +func (t *STree) testAndSplit(s *state, start, end Pos) (exs *state, endPoint bool) { + c := t.data[t.end] + if start <= end { + tr := s.findTran(t.data[start]) + splitPoint := tr.start + end - start + 1 + if t.data[splitPoint].Val() == c.Val() { + return s, true + } + // make the (s, (start, end)) state explicit + newSt := newState(s.tree) + newSt.addTran(splitPoint, tr.end, tr.state) + tr.end = splitPoint - 1 + tr.state = newSt + return newSt, false + } + if s == t.auxState || s.findTran(c) != nil { + return s, true + } + return s, false +} + +// canonize returns updated state and start position for ref. pair +// (s, (start, end)) of state r so the new ref. pair is canonical, +// that is, referenced from the closest explicit ancestor of r. +func (t *STree) canonize(s *state, start, end Pos) (*state, Pos) { + if s == t.auxState { + s, start = t.root, start+1 + } + if start > end { + return s, start + } + + var tr *tran + for { + if start <= end { + tr = s.findTran(t.data[start]) + if tr == nil { + panic(fmt.Sprintf("there should be some transition for '%d' at %d", + t.data[start].Val(), start)) + } + } + if tr.end-tr.start > end-start { + break + } + start += tr.end - tr.start + 1 + s = tr.state + } + if s == nil { + panic("there should always be some suffix link resolution") + } + return s, start +} + +func (t *STree) At(p Pos) Token { + if p < 0 || p >= Pos(len(t.data)) { + panic("position out of bounds") + } + return t.data[p] +} + +func (t *STree) String() string { + buf := new(bytes.Buffer) + printState(buf, t.root, 0) + return buf.String() +} + +func printState(buf *bytes.Buffer, s *state, ident int) { + for _, tr := range s.trans { + fmt.Fprint(buf, strings.Repeat(" ", ident)) + fmt.Fprintf(buf, "* (%d, %d)\n", tr.start, tr.ActEnd()) + printState(buf, tr.state, ident+1) + } +} + +// state is an explicit state of the suffix tree. +type state struct { + tree *STree + trans []*tran + linkState *state +} + +func newState(t *STree) *state { + return &state{ + tree: t, + trans: make([]*tran, 0), + linkState: nil, + } +} + +func (s *state) addTran(start, end Pos, r *state) { + s.trans = append(s.trans, newTran(start, end, r)) +} + +// fork creates a new branch from the state s. +func (s *state) fork(i Pos) *state { + r := newState(s.tree) + s.addTran(i, infinity, r) + return r +} + +// findTran finds c-transition. +func (s *state) findTran(c Token) *tran { + for _, tran := range s.trans { + if s.tree.data[tran.start].Val() == c.Val() { + return tran + } + } + return nil +} + +// tran represents a state's transition. +type tran struct { + start, end Pos + state *state +} + +func newTran(start, end Pos, s *state) *tran { + return &tran{start, end, s} +} + +func (t *tran) len() int { + return int(t.end - t.start + 1) +} + +// ActEnd returns actual end position as consistent with +// the actual length of the data in the STree. +func (t *tran) ActEnd() Pos { + if t.end == infinity { + return Pos(len(t.state.tree.data)) - 1 + } + return t.end +} diff --git a/vendor/github.com/golangci/dupl/syntax/golang/golang.go b/vendor/github.com/golangci/dupl/syntax/golang/golang.go new file mode 100644 index 000000000..a0b1e77e1 --- /dev/null +++ b/vendor/github.com/golangci/dupl/syntax/golang/golang.go @@ -0,0 +1,392 @@ +package golang + +import ( + "go/ast" + "go/parser" + "go/token" + + "github.com/golangci/dupl/syntax" +) + +const ( + BadNode = iota + File + ArrayType + AssignStmt + BasicLit + BinaryExpr + BlockStmt + BranchStmt + CallExpr + CaseClause + ChanType + CommClause + CompositeLit + DeclStmt + DeferStmt + Ellipsis + EmptyStmt + ExprStmt + Field + FieldList + ForStmt + FuncDecl + FuncLit + FuncType + GenDecl + GoStmt + Ident + IfStmt + IncDecStmt + IndexExpr + InterfaceType + KeyValueExpr + LabeledStmt + MapType + ParenExpr + RangeStmt + ReturnStmt + SelectStmt + SelectorExpr + SendStmt + SliceExpr + StarExpr + StructType + SwitchStmt + TypeAssertExpr + TypeSpec + TypeSwitchStmt + UnaryExpr + ValueSpec +) + +// Parse the given file and return uniform syntax tree. +func Parse(filename string) (*syntax.Node, error) { + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, filename, nil, 0) + if err != nil { + return nil, err + } + t := &transformer{ + fileset: fset, + filename: filename, + } + return t.trans(file), nil +} + +type transformer struct { + fileset *token.FileSet + filename string +} + +// trans transforms given golang AST to uniform tree structure. +func (t *transformer) trans(node ast.Node) (o *syntax.Node) { + o = syntax.NewNode() + o.Filename = t.filename + st, end := node.Pos(), node.End() + o.Pos, o.End = t.fileset.File(st).Offset(st), t.fileset.File(end).Offset(end) + + switch n := node.(type) { + case *ast.ArrayType: + o.Type = ArrayType + if n.Len != nil { + o.AddChildren(t.trans(n.Len)) + } + o.AddChildren(t.trans(n.Elt)) + + case *ast.AssignStmt: + o.Type = AssignStmt + for _, e := range n.Rhs { + o.AddChildren(t.trans(e)) + } + + for _, e := range n.Lhs { + o.AddChildren(t.trans(e)) + } + + case *ast.BasicLit: + o.Type = BasicLit + + case *ast.BinaryExpr: + o.Type = BinaryExpr + o.AddChildren(t.trans(n.X), t.trans(n.Y)) + + case *ast.BlockStmt: + o.Type = BlockStmt + for _, stmt := range n.List { + o.AddChildren(t.trans(stmt)) + } + + case *ast.BranchStmt: + o.Type = BranchStmt + if n.Label != nil { + o.AddChildren(t.trans(n.Label)) + } + + case *ast.CallExpr: + o.Type = CallExpr + o.AddChildren(t.trans(n.Fun)) + for _, arg := range n.Args { + o.AddChildren(t.trans(arg)) + } + + case *ast.CaseClause: + o.Type = CaseClause + for _, e := range n.List { + o.AddChildren(t.trans(e)) + } + for _, stmt := range n.Body { + o.AddChildren(t.trans(stmt)) + } + + case *ast.ChanType: + o.Type = ChanType + o.AddChildren(t.trans(n.Value)) + + case *ast.CommClause: + o.Type = CommClause + if n.Comm != nil { + o.AddChildren(t.trans(n.Comm)) + } + for _, stmt := range n.Body { + o.AddChildren(t.trans(stmt)) + } + + case *ast.CompositeLit: + o.Type = CompositeLit + if n.Type != nil { + o.AddChildren(t.trans(n.Type)) + } + for _, e := range n.Elts { + o.AddChildren(t.trans(e)) + } + + case *ast.DeclStmt: + o.Type = DeclStmt + o.AddChildren(t.trans(n.Decl)) + + case *ast.DeferStmt: + o.Type = DeferStmt + o.AddChildren(t.trans(n.Call)) + + case *ast.Ellipsis: + o.Type = Ellipsis + if n.Elt != nil { + o.AddChildren(t.trans(n.Elt)) + } + + case *ast.EmptyStmt: + o.Type = EmptyStmt + + case *ast.ExprStmt: + o.Type = ExprStmt + o.AddChildren(t.trans(n.X)) + + case *ast.Field: + o.Type = Field + for _, name := range n.Names { + o.AddChildren(t.trans(name)) + } + o.AddChildren(t.trans(n.Type)) + + case *ast.FieldList: + o.Type = FieldList + for _, field := range n.List { + o.AddChildren(t.trans(field)) + } + + case *ast.File: + o.Type = File + for _, decl := range n.Decls { + if genDecl, ok := decl.(*ast.GenDecl); ok && genDecl.Tok == token.IMPORT { + // skip import declarations + continue + } + o.AddChildren(t.trans(decl)) + } + + case *ast.ForStmt: + o.Type = ForStmt + if n.Init != nil { + o.AddChildren(t.trans(n.Init)) + } + if n.Cond != nil { + o.AddChildren(t.trans(n.Cond)) + } + if n.Post != nil { + o.AddChildren(t.trans(n.Post)) + } + o.AddChildren(t.trans(n.Body)) + + case *ast.FuncDecl: + o.Type = FuncDecl + if n.Recv != nil { + o.AddChildren(t.trans(n.Recv)) + } + o.AddChildren(t.trans(n.Name), t.trans(n.Type)) + if n.Body != nil { + o.AddChildren(t.trans(n.Body)) + } + + case *ast.FuncLit: + o.Type = FuncLit + o.AddChildren(t.trans(n.Type), t.trans(n.Body)) + + case *ast.FuncType: + o.Type = FuncType + o.AddChildren(t.trans(n.Params)) + if n.Results != nil { + o.AddChildren(t.trans(n.Results)) + } + + case *ast.GenDecl: + o.Type = GenDecl + for _, spec := range n.Specs { + o.AddChildren(t.trans(spec)) + } + + case *ast.GoStmt: + o.Type = GoStmt + o.AddChildren(t.trans(n.Call)) + + case *ast.Ident: + o.Type = Ident + + case *ast.IfStmt: + o.Type = IfStmt + if n.Init != nil { + o.AddChildren(t.trans(n.Init)) + } + o.AddChildren(t.trans(n.Cond), t.trans(n.Body)) + if n.Else != nil { + o.AddChildren(t.trans(n.Else)) + } + + case *ast.IncDecStmt: + o.Type = IncDecStmt + o.AddChildren(t.trans(n.X)) + + case *ast.IndexExpr: + o.Type = IndexExpr + o.AddChildren(t.trans(n.X), t.trans(n.Index)) + + case *ast.InterfaceType: + o.Type = InterfaceType + o.AddChildren(t.trans(n.Methods)) + + case *ast.KeyValueExpr: + o.Type = KeyValueExpr + o.AddChildren(t.trans(n.Key), t.trans(n.Value)) + + case *ast.LabeledStmt: + o.Type = LabeledStmt + o.AddChildren(t.trans(n.Label), t.trans(n.Stmt)) + + case *ast.MapType: + o.Type = MapType + o.AddChildren(t.trans(n.Key), t.trans(n.Value)) + + case *ast.ParenExpr: + o.Type = ParenExpr + o.AddChildren(t.trans(n.X)) + + case *ast.RangeStmt: + o.Type = RangeStmt + if n.Key != nil { + o.AddChildren(t.trans(n.Key)) + } + if n.Value != nil { + o.AddChildren(t.trans(n.Value)) + } + o.AddChildren(t.trans(n.X), t.trans(n.Body)) + + case *ast.ReturnStmt: + o.Type = ReturnStmt + for _, e := range n.Results { + o.AddChildren(t.trans(e)) + } + + case *ast.SelectStmt: + o.Type = SelectStmt + o.AddChildren(t.trans(n.Body)) + + case *ast.SelectorExpr: + o.Type = SelectorExpr + o.AddChildren(t.trans(n.X), t.trans(n.Sel)) + + case *ast.SendStmt: + o.Type = SendStmt + o.AddChildren(t.trans(n.Chan), t.trans(n.Value)) + + case *ast.SliceExpr: + o.Type = SliceExpr + o.AddChildren(t.trans(n.X)) + if n.Low != nil { + o.AddChildren(t.trans(n.Low)) + } + if n.High != nil { + o.AddChildren(t.trans(n.High)) + } + if n.Max != nil { + o.AddChildren(t.trans(n.Max)) + } + + case *ast.StarExpr: + o.Type = StarExpr + o.AddChildren(t.trans(n.X)) + + case *ast.StructType: + o.Type = StructType + o.AddChildren(t.trans(n.Fields)) + + case *ast.SwitchStmt: + o.Type = SwitchStmt + if n.Init != nil { + o.AddChildren(t.trans(n.Init)) + } + if n.Tag != nil { + o.AddChildren(t.trans(n.Tag)) + } + o.AddChildren(t.trans(n.Body)) + + case *ast.TypeAssertExpr: + o.Type = TypeAssertExpr + o.AddChildren(t.trans(n.X)) + if n.Type != nil { + o.AddChildren(t.trans(n.Type)) + } + + case *ast.TypeSpec: + o.Type = TypeSpec + o.AddChildren(t.trans(n.Name), t.trans(n.Type)) + + case *ast.TypeSwitchStmt: + o.Type = TypeSwitchStmt + if n.Init != nil { + o.AddChildren(t.trans(n.Init)) + } + o.AddChildren(t.trans(n.Assign), t.trans(n.Body)) + + case *ast.UnaryExpr: + o.Type = UnaryExpr + o.AddChildren(t.trans(n.X)) + + case *ast.ValueSpec: + o.Type = ValueSpec + for _, name := range n.Names { + o.AddChildren(t.trans(name)) + } + if n.Type != nil { + o.AddChildren(t.trans(n.Type)) + } + for _, val := range n.Values { + o.AddChildren(t.trans(val)) + } + + default: + o.Type = BadNode + + } + + return o +} diff --git a/vendor/github.com/golangci/dupl/syntax/syntax.go b/vendor/github.com/golangci/dupl/syntax/syntax.go new file mode 100644 index 000000000..e2c750afd --- /dev/null +++ b/vendor/github.com/golangci/dupl/syntax/syntax.go @@ -0,0 +1,175 @@ +package syntax + +import ( + "crypto/sha1" + + "github.com/golangci/dupl/suffixtree" +) + +type Node struct { + Type int + Filename string + Pos, End int + Children []*Node + Owns int +} + +func NewNode() *Node { + return &Node{} +} + +func (n *Node) AddChildren(children ...*Node) { + n.Children = append(n.Children, children...) +} + +func (n *Node) Val() int { + return n.Type +} + +type Match struct { + Hash string + Frags [][]*Node +} + +func Serialize(n *Node) []*Node { + stream := make([]*Node, 0, 10) + serial(n, &stream) + return stream +} + +func serial(n *Node, stream *[]*Node) int { + *stream = append(*stream, n) + var count int + for _, child := range n.Children { + count += serial(child, stream) + } + n.Owns = count + return count + 1 +} + +// FindSyntaxUnits finds all complete syntax units in the match group and returns them +// with the corresponding hash. +func FindSyntaxUnits(data []*Node, m suffixtree.Match, threshold int) Match { + if len(m.Ps) == 0 { + return Match{} + } + firstSeq := data[m.Ps[0] : m.Ps[0]+m.Len] + indexes := getUnitsIndexes(firstSeq, threshold) + + // TODO: is this really working? + indexCnt := len(indexes) + if indexCnt > 0 { + lasti := indexes[indexCnt-1] + firstn := firstSeq[lasti] + for i := 1; i < len(m.Ps); i++ { + n := data[int(m.Ps[i])+lasti] + if firstn.Owns != n.Owns { + indexes = indexes[:indexCnt-1] + break + } + } + } + if len(indexes) == 0 || isCyclic(indexes, firstSeq) || spansMultipleFiles(indexes, firstSeq) { + return Match{} + } + + match := Match{Frags: make([][]*Node, len(m.Ps))} + for i, pos := range m.Ps { + match.Frags[i] = make([]*Node, len(indexes)) + for j, index := range indexes { + match.Frags[i][j] = data[int(pos)+index] + } + } + + lastIndex := indexes[len(indexes)-1] + match.Hash = hashSeq(firstSeq[indexes[0] : lastIndex+firstSeq[lastIndex].Owns]) + return match +} + +func getUnitsIndexes(nodeSeq []*Node, threshold int) []int { + var indexes []int + var split bool + for i := 0; i < len(nodeSeq); { + n := nodeSeq[i] + switch { + case n.Owns >= len(nodeSeq)-i: + // not complete syntax unit + i++ + split = true + continue + case n.Owns+1 < threshold: + split = true + default: + if split { + indexes = indexes[:0] + split = false + } + indexes = append(indexes, i) + } + i += n.Owns + 1 + } + return indexes +} + +// isCyclic finds out whether there is a repetive pattern in the found clone. If positive, +// it return false to point out that the clone would be redundant. +func isCyclic(indexes []int, nodes []*Node) bool { + cnt := len(indexes) + if cnt <= 1 { + return false + } + + alts := make(map[int]bool) + for i := 1; i <= cnt/2; i++ { + if cnt%i == 0 { + alts[i] = true + } + } + + for i := 0; i < indexes[cnt/2]; i++ { + nstart := nodes[i+indexes[0]] + AltLoop: + for alt := range alts { + for j := alt; j < cnt; j += alt { + index := i + indexes[j] + if index < len(nodes) { + nalt := nodes[index] + if nstart.Owns == nalt.Owns && nstart.Type == nalt.Type { + continue + } + } else if i >= indexes[alt] { + return true + } + delete(alts, alt) + continue AltLoop + } + } + if len(alts) == 0 { + return false + } + } + return true +} + +func spansMultipleFiles(indexes []int, nodes []*Node) bool { + if len(indexes) < 2 { + return false + } + f := nodes[indexes[0]].Filename + for i := 1; i < len(indexes); i++ { + if nodes[indexes[i]].Filename != f { + return true + } + } + return false +} + +func hashSeq(nodes []*Node) string { + h := sha1.New() + bytes := make([]byte, len(nodes)) + for i, node := range nodes { + bytes[i] = byte(node.Type) + } + h.Write(bytes) + return string(h.Sum(nil)) +} diff --git a/vendor/github.com/golangci/errcheck/LICENSE b/vendor/github.com/golangci/errcheck/LICENSE new file mode 100644 index 000000000..a2b16b5bd --- /dev/null +++ b/vendor/github.com/golangci/errcheck/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2013 Kamil Kisiel + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/golangci/errcheck/golangci/golangci.go b/vendor/github.com/golangci/errcheck/golangci/golangci.go new file mode 100644 index 000000000..1095adeb4 --- /dev/null +++ b/vendor/github.com/golangci/errcheck/golangci/golangci.go @@ -0,0 +1,85 @@ +package golangci + +import ( + "regexp" + + "github.com/golangci/errcheck/internal/errcheck" + "golang.org/x/tools/go/loader" +) + +var dotStar = regexp.MustCompile(".*") + +type Issue errcheck.UncheckedError + +func Run(program *loader.Program, checkBlank, checkAsserts bool) ([]Issue, error) { + return RunWithConfig(program, &Config{ + Blank: checkBlank, + Asserts: checkAsserts, + }) +} + +// Config is a copy of the `errcheck.Checker` with exported `Exclude` field. +type Config struct { + // ignore is a map of package names to regular expressions. Identifiers from a package are + // checked against its regular expressions and if any of the expressions match the call + // is not checked. + Ignore map[string]*regexp.Regexp + + // If blank is true then assignments to the blank identifier are also considered to be + // ignored errors. + Blank bool + + // If asserts is true then ignored type assertion results are also checked + Asserts bool + + // build tags + Tags []string + + Verbose bool + + // If true, checking of _test.go files is disabled + WithoutTests bool + + // Excluded functions. + Exclude map[string]bool +} + +// RunWithConfig runs the `errchecker` linter with all its options. +func RunWithConfig(program *loader.Program, c *Config) ([]Issue, error) { + checker := errcheck.NewChecker() + checker.Tags = c.Tags + checker.Blank = c.Blank + checker.Asserts = c.Asserts + checker.Verbose = c.Verbose + checker.WithoutTests = c.WithoutTests + + checker.SetExclude(c.Exclude) + + checker.Ignore = map[string]*regexp.Regexp{} + for pkg, re := range c.Ignore { + checker.Ignore[pkg] = re + } + + if err := checker.CheckProgram(program); err != nil { + if e, ok := err.(*errcheck.UncheckedErrors); ok { + return makeIssues(e), nil + } + if err == errcheck.ErrNoGoFiles { + return nil, nil + } + + return nil, err + } + + // no issues + return nil, nil +} + +func makeIssues(e *errcheck.UncheckedErrors) []Issue { + var ret []Issue + for _, uncheckedError := range e.Errors { + ret = append(ret, Issue(uncheckedError)) + } + + return ret +} diff --git a/vendor/github.com/golangci/errcheck/internal/errcheck/errcheck.go b/vendor/github.com/golangci/errcheck/internal/errcheck/errcheck.go new file mode 100644 index 000000000..2a698fcee --- /dev/null +++ b/vendor/github.com/golangci/errcheck/internal/errcheck/errcheck.go @@ -0,0 +1,538 @@ +// Package errcheck is the library used to implement the errcheck command-line tool. +// +// Note: The API of this package has not been finalized and may change at any point. +package errcheck + +import ( + "bufio" + "errors" + "fmt" + "go/ast" + "go/build" + "go/token" + "go/types" + "os" + "regexp" + "sort" + "strings" + "sync" + + "golang.org/x/tools/go/loader" +) + +var errorType *types.Interface + +func init() { + errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) + +} + +var ( + // ErrNoGoFiles is returned when CheckPackage is run on a package with no Go source files + ErrNoGoFiles = errors.New("package contains no go source files") +) + +// UncheckedError indicates the position of an unchecked error return. +type UncheckedError struct { + Pos token.Position + Line string + FuncName string +} + +// UncheckedErrors is returned from the CheckPackage function if the package contains +// any unchecked errors. +// Errors should be appended using the Append method, which is safe to use concurrently. +type UncheckedErrors struct { + mu sync.Mutex + + // Errors is a list of all the unchecked errors in the package. + // Printing an error reports its position within the file and the contents of the line. + Errors []UncheckedError +} + +func (e *UncheckedErrors) Append(errors ...UncheckedError) { + e.mu.Lock() + defer e.mu.Unlock() + e.Errors = append(e.Errors, errors...) +} + +func (e *UncheckedErrors) Error() string { + return fmt.Sprintf("%d unchecked errors", len(e.Errors)) +} + +// Len is the number of elements in the collection. +func (e *UncheckedErrors) Len() int { return len(e.Errors) } + +// Swap swaps the elements with indexes i and j. +func (e *UncheckedErrors) Swap(i, j int) { e.Errors[i], e.Errors[j] = e.Errors[j], e.Errors[i] } + +type byName struct{ *UncheckedErrors } + +// Less reports whether the element with index i should sort before the element with index j. +func (e byName) Less(i, j int) bool { + ei, ej := e.Errors[i], e.Errors[j] + + pi, pj := ei.Pos, ej.Pos + + if pi.Filename != pj.Filename { + return pi.Filename < pj.Filename + } + if pi.Line != pj.Line { + return pi.Line < pj.Line + } + if pi.Column != pj.Column { + return pi.Column < pj.Column + } + + return ei.Line < ej.Line +} + +type Checker struct { + // ignore is a map of package names to regular expressions. Identifiers from a package are + // checked against its regular expressions and if any of the expressions match the call + // is not checked. + Ignore map[string]*regexp.Regexp + + // If blank is true then assignments to the blank identifier are also considered to be + // ignored errors. + Blank bool + + // If asserts is true then ignored type assertion results are also checked + Asserts bool + + // build tags + Tags []string + + Verbose bool + + // If true, checking of _test.go files is disabled + WithoutTests bool + + exclude map[string]bool +} + +func NewChecker() *Checker { + c := Checker{} + c.SetExclude(map[string]bool{}) + return &c +} + +func (c *Checker) SetExclude(l map[string]bool) { + // Default exclude for stdlib functions + c.exclude = map[string]bool{ + "math/rand.Read": true, + "(*math/rand.Rand).Read": true, + + "(*bytes.Buffer).Write": true, + "(*bytes.Buffer).WriteByte": true, + "(*bytes.Buffer).WriteRune": true, + "(*bytes.Buffer).WriteString": true, + + "(*strings.Builder).Write": true, + "(*strings.Builder).WriteByte": true, + "(*strings.Builder).WriteRune": true, + "(*strings.Builder).WriteString": true, + } + for k := range l { + c.exclude[k] = true + } +} + +func (c *Checker) logf(msg string, args ...interface{}) { + if c.Verbose { + fmt.Fprintf(os.Stderr, msg+"\n", args...) + } +} + +func (c *Checker) load(paths ...string) (*loader.Program, error) { + ctx := build.Default + for _, tag := range c.Tags { + ctx.BuildTags = append(ctx.BuildTags, tag) + } + loadcfg := loader.Config{ + Build: &ctx, + } + rest, err := loadcfg.FromArgs(paths, !c.WithoutTests) + if err != nil { + return nil, fmt.Errorf("could not parse arguments: %s", err) + } + if len(rest) > 0 { + return nil, fmt.Errorf("unhandled extra arguments: %v", rest) + } + + return loadcfg.Load() +} + +func (c *Checker) CheckProgram(program *loader.Program) error { + var wg sync.WaitGroup + u := &UncheckedErrors{} + for _, pkgInfo := range program.InitialPackages() { + if pkgInfo.Pkg.Path() == "unsafe" { // not a real package + continue + } + + wg.Add(1) + + go func(pkgInfo *loader.PackageInfo) { + defer wg.Done() + c.logf("Checking %s", pkgInfo.Pkg.Path()) + + v := &visitor{ + prog: program, + pkg: pkgInfo, + ignore: c.Ignore, + blank: c.Blank, + asserts: c.Asserts, + lines: make(map[string][]string), + exclude: c.exclude, + errors: []UncheckedError{}, + } + + for _, astFile := range v.pkg.Files { + ast.Walk(v, astFile) + } + u.Append(v.errors...) + }(pkgInfo) + } + + wg.Wait() + if u.Len() > 0 { + sort.Sort(byName{u}) + return u + } + return nil +} + +// CheckPackages checks packages for errors. +func (c *Checker) CheckPackages(paths ...string) error { + program, err := c.load(paths...) + if err != nil { + return fmt.Errorf("could not type check: %s", err) + } + + return c.CheckProgram(program) +} + +// visitor implements the errcheck algorithm +type visitor struct { + prog *loader.Program + pkg *loader.PackageInfo + ignore map[string]*regexp.Regexp + blank bool + asserts bool + lines map[string][]string + exclude map[string]bool + + errors []UncheckedError +} + +func getSelName(sel *ast.SelectorExpr) string { + if ident, ok := sel.X.(*ast.Ident); ok { + return fmt.Sprintf("%s.%s", ident.Name, sel.Sel.Name) + } + + if s, ok := sel.X.(*ast.SelectorExpr); ok { + return fmt.Sprintf("%s.%s", getSelName(s), sel.Sel.Name) + } + + return "" +} + +func (v *visitor) fullNameForPrinting(call *ast.CallExpr) (string, bool) { + if ident, ok := call.Fun.(*ast.Ident); ok { + return ident.Name, true + } + + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return "", false + } + + name := getSelName(sel) + if name != "" { + return name, true + } + + fn, ok := v.pkg.ObjectOf(sel.Sel).(*types.Func) + if !ok { + // Shouldn't happen, but be paranoid + return "", false + } + // The name is fully qualified by the import path, possible type, + // function/method name and pointer receiver. + // + // TODO(dh): vendored packages will have /vendor/ in their name, + // thus not matching vendored standard library packages. If we + // want to support vendored stdlib packages, we need to implement + // FullName with our own logic. + return fn.FullName(), true +} + +func (v *visitor) fullName(call *ast.CallExpr) (string, bool) { + if ident, ok := call.Fun.(*ast.Ident); ok { + return ident.Name, true + } + + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return "", false + } + + fn, ok := v.pkg.ObjectOf(sel.Sel).(*types.Func) + if !ok { + // Shouldn't happen, but be paranoid + return "", false + } + // The name is fully qualified by the import path, possible type, + // function/method name and pointer receiver. + // + // TODO(dh): vendored packages will have /vendor/ in their name, + // thus not matching vendored standard library packages. If we + // want to support vendored stdlib packages, we need to implement + // FullName with our own logic. + return fn.FullName(), true +} + +func (v *visitor) excludeCall(call *ast.CallExpr) bool { + if name, ok := v.fullName(call); ok { + return v.exclude[name] + } + + return false +} + +func (v *visitor) ignoreCall(call *ast.CallExpr) bool { + if v.excludeCall(call) { + return true + } + + // Try to get an identifier. + // Currently only supports simple expressions: + // 1. f() + // 2. x.y.f() + var id *ast.Ident + switch exp := call.Fun.(type) { + case (*ast.Ident): + id = exp + case (*ast.SelectorExpr): + id = exp.Sel + default: + // eg: *ast.SliceExpr, *ast.IndexExpr + } + + if id == nil { + return false + } + + // If we got an identifier for the function, see if it is ignored + if re, ok := v.ignore[""]; ok && re.MatchString(id.Name) { + return true + } + + if obj := v.pkg.Uses[id]; obj != nil { + if pkg := obj.Pkg(); pkg != nil { + if re, ok := v.ignore[pkg.Path()]; ok { + return re.MatchString(id.Name) + } + + // if current package being considered is vendored, check to see if it should be ignored based + // on the unvendored path. + if nonVendoredPkg, ok := nonVendoredPkgPath(pkg.Path()); ok { + if re, ok := v.ignore[nonVendoredPkg]; ok { + return re.MatchString(id.Name) + } + } + } + } + + return false +} + +// nonVendoredPkgPath returns the unvendored version of the provided package path (or returns the provided path if it +// does not represent a vendored path). The second return value is true if the provided package was vendored, false +// otherwise. +func nonVendoredPkgPath(pkgPath string) (string, bool) { + lastVendorIndex := strings.LastIndex(pkgPath, "/vendor/") + if lastVendorIndex == -1 { + return pkgPath, false + } + return pkgPath[lastVendorIndex+len("/vendor/"):], true +} + +// errorsByArg returns a slice s such that +// len(s) == number of return types of call +// s[i] == true iff return type at position i from left is an error type +func (v *visitor) errorsByArg(call *ast.CallExpr) []bool { + switch t := v.pkg.Types[call].Type.(type) { + case *types.Named: + // Single return + return []bool{isErrorType(t)} + case *types.Pointer: + // Single return via pointer + return []bool{isErrorType(t)} + case *types.Tuple: + // Multiple returns + s := make([]bool, t.Len()) + for i := 0; i < t.Len(); i++ { + switch et := t.At(i).Type().(type) { + case *types.Named: + // Single return + s[i] = isErrorType(et) + case *types.Pointer: + // Single return via pointer + s[i] = isErrorType(et) + default: + s[i] = false + } + } + return s + } + return []bool{false} +} + +func (v *visitor) callReturnsError(call *ast.CallExpr) bool { + if v.isRecover(call) { + return true + } + for _, isError := range v.errorsByArg(call) { + if isError { + return true + } + } + return false +} + +// isRecover returns true if the given CallExpr is a call to the built-in recover() function. +func (v *visitor) isRecover(call *ast.CallExpr) bool { + if fun, ok := call.Fun.(*ast.Ident); ok { + if _, ok := v.pkg.Uses[fun].(*types.Builtin); ok { + return fun.Name == "recover" + } + } + return false +} + +func (v *visitor) addErrorAtPosition(position token.Pos, call *ast.CallExpr) { + pos := v.prog.Fset.Position(position) + lines, ok := v.lines[pos.Filename] + if !ok { + lines = readfile(pos.Filename) + v.lines[pos.Filename] = lines + } + + line := "??" + if pos.Line-1 < len(lines) { + line = strings.TrimSpace(lines[pos.Line-1]) + } + + var name string + if call != nil { + name, _ = v.fullNameForPrinting(call) + } + + v.errors = append(v.errors, UncheckedError{pos, line, name}) +} + +func readfile(filename string) []string { + var f, err = os.Open(filename) + if err != nil { + return nil + } + defer f.Close() + + var lines []string + var scanner = bufio.NewScanner(f) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + return lines +} + +func (v *visitor) Visit(node ast.Node) ast.Visitor { + switch stmt := node.(type) { + case *ast.ExprStmt: + if call, ok := stmt.X.(*ast.CallExpr); ok { + if !v.ignoreCall(call) && v.callReturnsError(call) { + v.addErrorAtPosition(call.Lparen, call) + } + } + case *ast.GoStmt: + if !v.ignoreCall(stmt.Call) && v.callReturnsError(stmt.Call) { + v.addErrorAtPosition(stmt.Call.Lparen, stmt.Call) + } + case *ast.DeferStmt: + if !v.ignoreCall(stmt.Call) && v.callReturnsError(stmt.Call) { + v.addErrorAtPosition(stmt.Call.Lparen, stmt.Call) + } + case *ast.AssignStmt: + if len(stmt.Rhs) == 1 { + // single value on rhs; check against lhs identifiers + if call, ok := stmt.Rhs[0].(*ast.CallExpr); ok { + if !v.blank { + break + } + if v.ignoreCall(call) { + break + } + isError := v.errorsByArg(call) + for i := 0; i < len(stmt.Lhs); i++ { + if id, ok := stmt.Lhs[i].(*ast.Ident); ok { + // We shortcut calls to recover() because errorsByArg can't + // check its return types for errors since it returns interface{}. + if id.Name == "_" && (v.isRecover(call) || isError[i]) { + v.addErrorAtPosition(id.NamePos, call) + } + } + } + } else if assert, ok := stmt.Rhs[0].(*ast.TypeAssertExpr); ok { + if !v.asserts { + break + } + if assert.Type == nil { + // type switch + break + } + if len(stmt.Lhs) < 2 { + // assertion result not read + v.addErrorAtPosition(stmt.Rhs[0].Pos(), nil) + } else if id, ok := stmt.Lhs[1].(*ast.Ident); ok && v.blank && id.Name == "_" { + // assertion result ignored + v.addErrorAtPosition(id.NamePos, nil) + } + } + } else { + // multiple value on rhs; in this case a call can't return + // multiple values. Assume len(stmt.Lhs) == len(stmt.Rhs) + for i := 0; i < len(stmt.Lhs); i++ { + if id, ok := stmt.Lhs[i].(*ast.Ident); ok { + if call, ok := stmt.Rhs[i].(*ast.CallExpr); ok { + if !v.blank { + continue + } + if v.ignoreCall(call) { + continue + } + if id.Name == "_" && v.callReturnsError(call) { + v.addErrorAtPosition(id.NamePos, call) + } + } else if assert, ok := stmt.Rhs[i].(*ast.TypeAssertExpr); ok { + if !v.asserts { + continue + } + if assert.Type == nil { + // Shouldn't happen anyway, no multi assignment in type switches + continue + } + v.addErrorAtPosition(id.NamePos, nil) + } + } + } + } + default: + } + return v +} + +func isErrorType(t types.Type) bool { + return types.Implements(t, errorType) +} diff --git a/vendor/github.com/golangci/go-misc/LICENSE b/vendor/github.com/golangci/go-misc/LICENSE new file mode 100644 index 000000000..cc42dd45d --- /dev/null +++ b/vendor/github.com/golangci/go-misc/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 Rémy Oudompheng. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * The name of Rémy Oudompheng may not be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/github.com/golangci/go-misc/deadcode/README.md b/vendor/github.com/golangci/go-misc/deadcode/README.md new file mode 100644 index 000000000..550423128 --- /dev/null +++ b/vendor/github.com/golangci/go-misc/deadcode/README.md @@ -0,0 +1,18 @@ +# deadcode + +`deadcode` is a very simple utility which detects unused declarations in a Go package. + +## Usage +``` +deadcode [-test] [packages] + + -test Include test files + packages A list of packages using the same conventions as the go tool +``` + +## Limitations + +* Self-referential unused code is not currently reported +* A single package can be tested at a time +* Unused methods are not reported + diff --git a/vendor/github.com/golangci/go-misc/deadcode/deadcode.go b/vendor/github.com/golangci/go-misc/deadcode/deadcode.go new file mode 100644 index 000000000..2e7cfc962 --- /dev/null +++ b/vendor/github.com/golangci/go-misc/deadcode/deadcode.go @@ -0,0 +1,135 @@ +package deadcode + +import ( + "fmt" + "go/ast" + "go/token" + "go/types" + "os" + "path/filepath" + "sort" + "strings" + + "golang.org/x/tools/go/loader" +) + +var exitCode int + +var ( + withTestFiles bool +) + +type Issue struct { + Pos token.Position + UnusedIdentName string +} + +func Run(program *loader.Program) ([]Issue, error) { + ctx := &Context{ + program: program, + } + report := ctx.Process() + var issues []Issue + for _, obj := range report { + issues = append(issues, Issue{ + Pos: program.Fset.Position(obj.Pos()), + UnusedIdentName: obj.Name(), + }) + } + + return issues, nil +} + +func fatalf(format string, args ...interface{}) { + panic(fmt.Errorf(format, args...)) +} + +type Context struct { + cwd string + withTests bool + + program *loader.Program +} + +// pos resolves a compact position encoding into a verbose one +func (ctx *Context) pos(pos token.Pos) token.Position { + if ctx.cwd == "" { + ctx.cwd, _ = os.Getwd() + } + p := ctx.program.Fset.Position(pos) + f, err := filepath.Rel(ctx.cwd, p.Filename) + if err == nil { + p.Filename = f + } + return p +} + +// error formats the error to standard error, adding program +// identification and a newline +func (ctx *Context) errorf(pos token.Pos, format string, args ...interface{}) { + p := ctx.pos(pos) + fmt.Fprintf(os.Stderr, p.String()+": "+format+"\n", args...) + exitCode = 2 +} + +func (ctx *Context) Load(args ...string) { + // TODO +} + +func (ctx *Context) Process() []types.Object { + prog := ctx.program + var allUnused []types.Object + for _, pkg := range prog.Imported { + unused := ctx.doPackage(prog, pkg) + allUnused = append(allUnused, unused...) + } + for _, pkg := range prog.Created { + unused := ctx.doPackage(prog, pkg) + allUnused = append(allUnused, unused...) + } + sort.Sort(objects(allUnused)) + return allUnused +} + +func isTestFuncByName(name string) bool { + return strings.HasPrefix(name, "Test") || strings.HasPrefix(name, "Benchmark") || strings.HasPrefix(name, "Example") +} + +func (ctx *Context) doPackage(prog *loader.Program, pkg *loader.PackageInfo) []types.Object { + used := make(map[types.Object]bool) + for _, file := range pkg.Files { + ast.Inspect(file, func(n ast.Node) bool { + id, ok := n.(*ast.Ident) + if !ok { + return true + } + obj := pkg.Info.Uses[id] + if obj != nil { + used[obj] = true + } + return false + }) + } + + global := pkg.Pkg.Scope() + var unused []types.Object + for _, name := range global.Names() { + if pkg.Pkg.Name() == "main" && name == "main" { + continue + } + obj := global.Lookup(name) + _, isSig := obj.Type().(*types.Signature) + pos := ctx.pos(obj.Pos()) + isTestMethod := isSig && isTestFuncByName(obj.Name()) && strings.HasSuffix(pos.Filename, "_test.go") + if !used[obj] && ((pkg.Pkg.Name() == "main" && !isTestMethod) || !ast.IsExported(name)) { + unused = append(unused, obj) + } + } + return unused +} + +type objects []types.Object + +func (s objects) Len() int { return len(s) } +func (s objects) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s objects) Less(i, j int) bool { return s[i].Pos() < s[j].Pos() } diff --git a/vendor/github.com/golangci/goconst/LICENSE b/vendor/github.com/golangci/goconst/LICENSE new file mode 100644 index 000000000..e92649543 --- /dev/null +++ b/vendor/github.com/golangci/goconst/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Jonathan Gautheron + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/golangci/goconst/README.md b/vendor/github.com/golangci/goconst/README.md new file mode 100644 index 000000000..04fc9b015 --- /dev/null +++ b/vendor/github.com/golangci/goconst/README.md @@ -0,0 +1,49 @@ +# goconst + +Find repeated strings that could be replaced by a constant. + +### Motivation + +There are obvious benefits to using constants instead of repeating strings, mostly to ease maintenance. Cannot argue against changing a single constant versus many strings. + +While this could be considered a beginner mistake, across time, multiple packages and large codebases, some repetition could have slipped in. + +### Get Started + + $ go get github.com/jgautheron/goconst/cmd/goconst + $ goconst ./... + +### Usage + +``` +Usage: + + goconst ARGS + +Flags: + + -ignore exclude files matching the given regular expression + -ignore-tests exclude tests from the search (default: true) + -min-occurrences report from how many occurrences (default: 2) + -min-length only report strings with the minimum given length (default: 3) + -match-constant look for existing constants matching the values + -numbers search also for duplicated numbers + -min minimum value, only works with -numbers + -max maximum value, only works with -numbers + -output output formatting (text or json) + +Examples: + + goconst ./... + goconst -ignore "yacc|\.pb\." $GOPATH/src/github.com/cockroachdb/cockroach/... + goconst -min-occurrences 3 -output json $GOPATH/src/github.com/cockroachdb/cockroach + goconst -numbers -min 60 -max 512 . +``` + +### Other static analysis tools + +- [gogetimports](https://github.com/jgautheron/gogetimports): Get a JSON-formatted list of imports. +- [usedexports](https://github.com/jgautheron/usedexports): Find exported variables that could be unexported. + +### License +MIT diff --git a/vendor/github.com/golangci/goconst/parser.go b/vendor/github.com/golangci/goconst/parser.go new file mode 100644 index 000000000..ab5f99a50 --- /dev/null +++ b/vendor/github.com/golangci/goconst/parser.go @@ -0,0 +1,188 @@ +// Package goconst finds repeated strings that could be replaced by a constant. +// +// There are obvious benefits to using constants instead of repeating strings, +// mostly to ease maintenance. Cannot argue against changing a single constant versus many strings. +// While this could be considered a beginner mistake, across time, +// multiple packages and large codebases, some repetition could have slipped in. +package goconst + +import ( + "go/ast" + "go/parser" + "go/token" + "log" + "os" + "path/filepath" + "regexp" + "strings" +) + +const ( + testSuffix = "_test.go" +) + +type Parser struct { + // Meant to be passed via New() + path, ignore string + ignoreTests, matchConstant bool + minLength int + + supportedTokens []token.Token + + // Internals + strs Strings + consts Constants +} + +// New creates a new instance of the parser. +// This is your entry point if you'd like to use goconst as an API. +func New(path, ignore string, ignoreTests, matchConstant, numbers bool, minLength int) *Parser { + supportedTokens := []token.Token{token.STRING} + if numbers { + supportedTokens = append(supportedTokens, token.INT, token.FLOAT) + } + + return &Parser{ + path: path, + ignore: ignore, + ignoreTests: ignoreTests, + matchConstant: matchConstant, + minLength: minLength, + supportedTokens: supportedTokens, + + // Initialize the maps + strs: Strings{}, + consts: Constants{}, + } +} + +// ParseTree will search the given path for occurrences that could be moved into constants. +// If "..." is appended, the search will be recursive. +func (p *Parser) ParseTree() (Strings, Constants, error) { + pathLen := len(p.path) + // Parse recursively the given path if the recursive notation is found + if pathLen >= 5 && p.path[pathLen-3:] == "..." { + filepath.Walk(p.path[:pathLen-3], func(path string, f os.FileInfo, err error) error { + if err != nil { + log.Println(err) + // resume walking + return nil + } + + if f.IsDir() { + p.parseDir(path) + } + return nil + }) + } else { + p.parseDir(p.path) + } + return p.strs, p.consts, nil +} + +func (p *Parser) parseDir(dir string) error { + fset := token.NewFileSet() + pkgs, err := parser.ParseDir(fset, dir, func(info os.FileInfo) bool { + valid, name := true, info.Name() + + if p.ignoreTests { + if strings.HasSuffix(name, testSuffix) { + valid = false + } + } + + if len(p.ignore) != 0 { + match, err := regexp.MatchString(p.ignore, dir+name) + if err != nil { + log.Fatal(err) + return true + } + if match { + valid = false + } + } + + return valid + }, 0) + if err != nil { + return err + } + + for _, pkg := range pkgs { + for fn, f := range pkg.Files { + ast.Walk(&treeVisitor{ + fileSet: fset, + packageName: pkg.Name, + fileName: fn, + p: p, + }, f) + } + } + + return nil +} + +type Strings map[string][]ExtendedPos +type Constants map[string]ConstType + +type ConstType struct { + token.Position + Name, packageName string +} + +type ExtendedPos struct { + token.Position + packageName string +} + +type Issue struct { + Pos token.Position + OccurencesCount int + Str string + MatchingConst string +} + +type Config struct { + MatchWithConstants bool + MinStringLength int + MinOccurrences int +} + +func Run(files []*ast.File, fset *token.FileSet, cfg *Config) ([]Issue, error) { + p := New("", "", false, cfg.MatchWithConstants, false, cfg.MinStringLength) + var issues []Issue + for _, f := range files { + ast.Walk(&treeVisitor{ + fileSet: fset, + packageName: "", + fileName: "", + p: p, + }, f) + } + + for str, item := range p.strs { + // Filter out items whose occurrences don't match the min value + if len(item) < cfg.MinOccurrences { + delete(p.strs, str) + } + } + + for str, item := range p.strs { + fi := item[0] + i := Issue{ + Pos: fi.Position, + OccurencesCount: len(item), + Str: str, + } + + if len(p.consts) != 0 { + if cst, ok := p.consts[str]; ok { + // const should be in the same package and exported + i.MatchingConst = cst.Name + } + } + issues = append(issues, i) + } + + return issues, nil +} diff --git a/vendor/github.com/golangci/goconst/visitor.go b/vendor/github.com/golangci/goconst/visitor.go new file mode 100644 index 000000000..a86421f6d --- /dev/null +++ b/vendor/github.com/golangci/goconst/visitor.go @@ -0,0 +1,143 @@ +package goconst + +import ( + "go/ast" + "go/token" + "strings" +) + +// treeVisitor carries the package name and file name +// for passing it to the imports map, and the fileSet for +// retrieving the token.Position. +type treeVisitor struct { + p *Parser + fileSet *token.FileSet + packageName, fileName string +} + +// Visit browses the AST tree for strings that could be potentially +// replaced by constants. +// A map of existing constants is built as well (-match-constant). +func (v *treeVisitor) Visit(node ast.Node) ast.Visitor { + if node == nil { + return v + } + + // A single case with "ast.BasicLit" would be much easier + // but then we wouldn't be able to tell in which context + // the string is defined (could be a constant definition). + switch t := node.(type) { + // Scan for constants in an attempt to match strings with existing constants + case *ast.GenDecl: + if !v.p.matchConstant { + return v + } + if t.Tok != token.CONST { + return v + } + + for _, spec := range t.Specs { + val := spec.(*ast.ValueSpec) + for i, str := range val.Values { + lit, ok := str.(*ast.BasicLit) + if !ok || !v.isSupported(lit.Kind) { + continue + } + + v.addConst(val.Names[i].Name, lit.Value, val.Names[i].Pos()) + } + } + + // foo := "moo" + case *ast.AssignStmt: + for _, rhs := range t.Rhs { + lit, ok := rhs.(*ast.BasicLit) + if !ok || !v.isSupported(lit.Kind) { + continue + } + + v.addString(lit.Value, rhs.(*ast.BasicLit).Pos()) + } + + // if foo == "moo" + case *ast.BinaryExpr: + if t.Op != token.EQL && t.Op != token.NEQ { + return v + } + + var lit *ast.BasicLit + var ok bool + + lit, ok = t.X.(*ast.BasicLit) + if ok && v.isSupported(lit.Kind) { + v.addString(lit.Value, lit.Pos()) + } + + lit, ok = t.Y.(*ast.BasicLit) + if ok && v.isSupported(lit.Kind) { + v.addString(lit.Value, lit.Pos()) + } + + // case "foo": + case *ast.CaseClause: + for _, item := range t.List { + lit, ok := item.(*ast.BasicLit) + if ok && v.isSupported(lit.Kind) { + v.addString(lit.Value, lit.Pos()) + } + } + + // return "boo" + case *ast.ReturnStmt: + for _, item := range t.Results { + lit, ok := item.(*ast.BasicLit) + if ok && v.isSupported(lit.Kind) { + v.addString(lit.Value, lit.Pos()) + } + } + } + + return v +} + +// addString adds a string in the map along with its position in the tree. +func (v *treeVisitor) addString(str string, pos token.Pos) { + str = strings.Replace(str, `"`, "", 2) + + // Ignore empty strings + if len(str) == 0 { + return + } + + if len(str) < v.p.minLength { + return + } + + _, ok := v.p.strs[str] + if !ok { + v.p.strs[str] = make([]ExtendedPos, 0) + } + v.p.strs[str] = append(v.p.strs[str], ExtendedPos{ + packageName: v.packageName, + Position: v.fileSet.Position(pos), + }) +} + +// addConst adds a const in the map along with its position in the tree. +func (v *treeVisitor) addConst(name string, val string, pos token.Pos) { + val = strings.Replace(val, `"`, "", 2) + v.p.consts[val] = ConstType{ + Name: name, + packageName: v.packageName, + Position: v.fileSet.Position(pos), + } +} + +func (v *treeVisitor) isSupported(tk token.Token) bool { + for _, s := range v.p.supportedTokens { + if tk == s { + return true + } + } + return false +} diff --git a/vendor/github.com/golangci/gocyclo/CONTRIBUTORS b/vendor/github.com/golangci/gocyclo/CONTRIBUTORS new file mode 100644 index 000000000..1c09f1a06 --- /dev/null +++ b/vendor/github.com/golangci/gocyclo/CONTRIBUTORS @@ -0,0 +1,7 @@ +# Names should be added to this file like so: +# Name + +# Please keep the list sorted. + +Frederik Zipp +Harshavardhana diff --git a/vendor/github.com/golangci/gocyclo/LICENSE b/vendor/github.com/golangci/gocyclo/LICENSE new file mode 100644 index 000000000..45f88d6cb --- /dev/null +++ b/vendor/github.com/golangci/gocyclo/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Frederik Zipp. 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 the copyright owner nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/golangci/gocyclo/pkg/gocyclo/gocyclo.go b/vendor/github.com/golangci/gocyclo/pkg/gocyclo/gocyclo.go new file mode 100644 index 000000000..a1f33310f --- /dev/null +++ b/vendor/github.com/golangci/gocyclo/pkg/gocyclo/gocyclo.go @@ -0,0 +1,82 @@ +package gocyclo + +import ( + "fmt" + "go/token" + + "go/ast" +) + +type Stat struct { + PkgName string + FuncName string + Complexity int + Pos token.Position +} + +func (s Stat) String() string { + return fmt.Sprintf("%d %s %s %s", s.Complexity, s.PkgName, s.FuncName, s.Pos) +} + +func BuildStats(f *ast.File, fset *token.FileSet, stats []Stat) []Stat { + for _, decl := range f.Decls { + if fn, ok := decl.(*ast.FuncDecl); ok { + stats = append(stats, Stat{ + PkgName: f.Name.Name, + FuncName: funcName(fn), + Complexity: complexity(fn), + Pos: fset.Position(fn.Pos()), + }) + } + } + return stats +} + +// funcName returns the name representation of a function or method: +// "(Type).Name" for methods or simply "Name" for functions. +func funcName(fn *ast.FuncDecl) string { + if fn.Recv != nil { + if fn.Recv.NumFields() > 0 { + typ := fn.Recv.List[0].Type + return fmt.Sprintf("(%s).%s", recvString(typ), fn.Name) + } + } + return fn.Name.Name +} + +// recvString returns a string representation of recv of the +// form "T", "*T", or "BADRECV" (if not a proper receiver type). +func recvString(recv ast.Expr) string { + switch t := recv.(type) { + case *ast.Ident: + return t.Name + case *ast.StarExpr: + return "*" + recvString(t.X) + } + return "BADRECV" +} + +// complexity calculates the cyclomatic complexity of a function. +func complexity(fn *ast.FuncDecl) int { + v := complexityVisitor{} + ast.Walk(&v, fn) + return v.Complexity +} + +type complexityVisitor struct { + // Complexity is the cyclomatic complexity + Complexity int +} + +// Visit implements the ast.Visitor interface. +func (v *complexityVisitor) Visit(n ast.Node) ast.Visitor { + switch n := n.(type) { + case *ast.FuncDecl, *ast.IfStmt, *ast.ForStmt, *ast.RangeStmt, *ast.CaseClause, *ast.CommClause: + v.Complexity++ + case *ast.BinaryExpr: + if n.Op == token.LAND || n.Op == token.LOR { + v.Complexity++ + } + } + return v +} diff --git a/vendor/github.com/golangci/gofmt/gofmt/LICENSE b/vendor/github.com/golangci/gofmt/gofmt/LICENSE new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/vendor/github.com/golangci/gofmt/gofmt/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/golangci/gofmt/gofmt/doc.go b/vendor/github.com/golangci/gofmt/gofmt/doc.go new file mode 100644 index 000000000..da0c8581d --- /dev/null +++ b/vendor/github.com/golangci/gofmt/gofmt/doc.go @@ -0,0 +1,104 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Gofmt formats Go programs. +It uses tabs for indentation and blanks for alignment. +Alignment assumes that an editor is using a fixed-width font. + +Without an explicit path, it processes the standard input. Given a file, +it operates on that file; given a directory, it operates on all .go files in +that directory, recursively. (Files starting with a period are ignored.) +By default, gofmt prints the reformatted sources to standard output. + +Usage: + gofmt [flags] [path ...] + +The flags are: + -d + Do not print reformatted sources to standard output. + If a file's formatting is different than gofmt's, print diffs + to standard output. + -e + Print all (including spurious) errors. + -l + Do not print reformatted sources to standard output. + If a file's formatting is different from gofmt's, print its name + to standard output. + -r rule + Apply the rewrite rule to the source before reformatting. + -s + Try to simplify code (after applying the rewrite rule, if any). + -w + Do not print reformatted sources to standard output. + If a file's formatting is different from gofmt's, overwrite it + with gofmt's version. If an error occurred during overwriting, + the original file is restored from an automatic backup. + +Debugging support: + -cpuprofile filename + Write cpu profile to the specified file. + + +The rewrite rule specified with the -r flag must be a string of the form: + + pattern -> replacement + +Both pattern and replacement must be valid Go expressions. +In the pattern, single-character lowercase identifiers serve as +wildcards matching arbitrary sub-expressions; those expressions +will be substituted for the same identifiers in the replacement. + +When gofmt reads from standard input, it accepts either a full Go program +or a program fragment. A program fragment must be a syntactically +valid declaration list, statement list, or expression. When formatting +such a fragment, gofmt preserves leading indentation as well as leading +and trailing spaces, so that individual sections of a Go program can be +formatted by piping them through gofmt. + +Examples + +To check files for unnecessary parentheses: + + gofmt -r '(a) -> a' -l *.go + +To remove the parentheses: + + gofmt -r '(a) -> a' -w *.go + +To convert the package tree from explicit slice upper bounds to implicit ones: + + gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src + +The simplify command + +When invoked with -s gofmt will make the following source transformations where possible. + + An array, slice, or map composite literal of the form: + []T{T{}, T{}} + will be simplified to: + []T{{}, {}} + + A slice expression of the form: + s[a:len(s)] + will be simplified to: + s[a:] + + A range of the form: + for x, _ = range v {...} + will be simplified to: + for x = range v {...} + + A range of the form: + for _ = range v {...} + will be simplified to: + for range v {...} + +This may result in changes that are incompatible with earlier versions of Go. +*/ +package gofmt + +// BUG(rsc): The implementation of -r is a bit slow. +// BUG(gri): If -w fails, the restored original file may not have some of the +// original file attributes. diff --git a/vendor/github.com/golangci/gofmt/gofmt/gofmt.go b/vendor/github.com/golangci/gofmt/gofmt/gofmt.go new file mode 100644 index 000000000..fb9c8cb37 --- /dev/null +++ b/vendor/github.com/golangci/gofmt/gofmt/gofmt.go @@ -0,0 +1,327 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gofmt + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/parser" + "go/printer" + "go/scanner" + "go/token" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "runtime/pprof" + "strings" + "sync" +) + +var ( + // main operation modes + list = flag.Bool("gofmt.l", false, "list files whose formatting differs from gofmt's") + write = flag.Bool("gofmt.w", false, "write result to (source) file instead of stdout") + rewriteRule = flag.String("gofmt.r", "", "rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')") + simplifyAST = flag.Bool("gofmt.s", false, "simplify code") + doDiff = flag.Bool("gofmt.d", false, "display diffs instead of rewriting files") + allErrors = flag.Bool("gofmt.e", false, "report all errors (not just the first 10 on different lines)") + + // debugging + cpuprofile = flag.String("gofmt.cpuprofile", "", "write cpu profile to this file") +) + +const ( + tabWidth = 8 + printerMode = printer.UseSpaces | printer.TabIndent +) + +var ( + fileSet = token.NewFileSet() // per process FileSet + exitCode = 0 + rewrite func(*ast.File) *ast.File + parserMode parser.Mode + parserModeInitOnce sync.Once +) + +func report(err error) { + scanner.PrintError(os.Stderr, err) + exitCode = 2 +} + +func usage() { + fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n") + flag.PrintDefaults() +} + +func initParserMode() { + parserModeInitOnce.Do(func() { + parserMode = parser.ParseComments + if *allErrors { + parserMode |= parser.AllErrors + } + }) +} + +func isGoFile(f os.FileInfo) bool { + // ignore non-Go files + name := f.Name() + return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") +} + +// If in == nil, the source is the contents of the file with the given filename. +func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error { + var perm os.FileMode = 0644 + if in == nil { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + return err + } + in = f + perm = fi.Mode().Perm() + } + + src, err := ioutil.ReadAll(in) + if err != nil { + return err + } + + file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, stdin) + if err != nil { + return err + } + + if rewrite != nil { + if sourceAdj == nil { + file = rewrite(file) + } else { + fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n") + } + } + + ast.SortImports(fileSet, file) + + if *simplifyAST { + simplify(file) + } + + res, err := format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth}) + if err != nil { + return err + } + + if !bytes.Equal(src, res) { + // formatting has changed + if *list { + fmt.Fprintln(out, filename) + } + if *write { + // make a temporary backup before overwriting original + bakname, err := backupFile(filename+".", src, perm) + if err != nil { + return err + } + err = ioutil.WriteFile(filename, res, perm) + if err != nil { + os.Rename(bakname, filename) + return err + } + err = os.Remove(bakname) + if err != nil { + return err + } + } + if *doDiff { + data, err := diff(src, res, filename) + if err != nil { + return fmt.Errorf("computing diff: %s", err) + } + fmt.Printf("diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename)) + out.Write(data) + } + } + + if !*list && !*write && !*doDiff { + _, err = out.Write(res) + } + + return err +} + +func visitFile(path string, f os.FileInfo, err error) error { + if err == nil && isGoFile(f) { + err = processFile(path, nil, os.Stdout, false) + } + // Don't complain if a file was deleted in the meantime (i.e. + // the directory changed concurrently while running gofmt). + if err != nil && !os.IsNotExist(err) { + report(err) + } + return nil +} + +func walkDir(path string) { + filepath.Walk(path, visitFile) +} + +func gofmtMain() { + flag.Usage = usage + flag.Parse() + + if *cpuprofile != "" { + f, err := os.Create(*cpuprofile) + if err != nil { + fmt.Fprintf(os.Stderr, "creating cpu profile: %s\n", err) + exitCode = 2 + return + } + defer f.Close() + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + } + + initParserMode() + initRewrite() + + if flag.NArg() == 0 { + if *write { + fmt.Fprintln(os.Stderr, "error: cannot use -w with standard input") + exitCode = 2 + return + } + if err := processFile("", os.Stdin, os.Stdout, true); err != nil { + report(err) + } + return + } + + for i := 0; i < flag.NArg(); i++ { + path := flag.Arg(i) + switch dir, err := os.Stat(path); { + case err != nil: + report(err) + case dir.IsDir(): + walkDir(path) + default: + if err := processFile(path, nil, os.Stdout, false); err != nil { + report(err) + } + } + } +} + +func writeTempFile(dir, prefix string, data []byte) (string, error) { + file, err := ioutil.TempFile(dir, prefix) + if err != nil { + return "", err + } + _, err = file.Write(data) + if err1 := file.Close(); err == nil { + err = err1 + } + if err != nil { + os.Remove(file.Name()) + return "", err + } + return file.Name(), nil +} + +func diff(b1, b2 []byte, filename string) (data []byte, err error) { + f1, err := writeTempFile("", "gofmt", b1) + if err != nil { + return + } + defer os.Remove(f1) + + f2, err := writeTempFile("", "gofmt", b2) + if err != nil { + return + } + defer os.Remove(f2) + + cmd := "diff" + if runtime.GOOS == "plan9" { + cmd = "/bin/ape/diff" + } + + data, err = exec.Command(cmd, "-u", f1, f2).CombinedOutput() + if len(data) > 0 { + // diff exits with a non-zero status when the files don't match. + // Ignore that failure as long as we get output. + return replaceTempFilename(data, filename) + } + return +} + +// replaceTempFilename replaces temporary filenames in diff with actual one. +// +// --- /tmp/gofmt316145376 2017-02-03 19:13:00.280468375 -0500 +// +++ /tmp/gofmt617882815 2017-02-03 19:13:00.280468375 -0500 +// ... +// -> +// --- path/to/file.go.orig 2017-02-03 19:13:00.280468375 -0500 +// +++ path/to/file.go 2017-02-03 19:13:00.280468375 -0500 +// ... +func replaceTempFilename(diff []byte, filename string) ([]byte, error) { + bs := bytes.SplitN(diff, []byte{'\n'}, 3) + if len(bs) < 3 { + return nil, fmt.Errorf("got unexpected diff for %s", filename) + } + // Preserve timestamps. + var t0, t1 []byte + if i := bytes.LastIndexByte(bs[0], '\t'); i != -1 { + t0 = bs[0][i:] + } + if i := bytes.LastIndexByte(bs[1], '\t'); i != -1 { + t1 = bs[1][i:] + } + // Always print filepath with slash separator. + f := filepath.ToSlash(filename) + bs[0] = []byte(fmt.Sprintf("--- %s%s", f+".orig", t0)) + bs[1] = []byte(fmt.Sprintf("+++ %s%s", f, t1)) + return bytes.Join(bs, []byte{'\n'}), nil +} + +const chmodSupported = runtime.GOOS != "windows" + +// backupFile writes data to a new file named filename with permissions perm, +// with 0 && isSpace(src[i-1]) { + i-- + } + return append(res, src[i:]...), nil +} + +// isSpace reports whether the byte is a space character. +// isSpace defines a space as being among the following bytes: ' ', '\t', '\n' and '\r'. +func isSpace(b byte) bool { + return b == ' ' || b == '\t' || b == '\n' || b == '\r' +} diff --git a/vendor/github.com/golangci/gofmt/gofmt/rewrite.go b/vendor/github.com/golangci/gofmt/gofmt/rewrite.go new file mode 100644 index 000000000..73741e0a9 --- /dev/null +++ b/vendor/github.com/golangci/gofmt/gofmt/rewrite.go @@ -0,0 +1,303 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gofmt + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "os" + "reflect" + "strings" + "unicode" + "unicode/utf8" +) + +func initRewrite() { + if *rewriteRule == "" { + rewrite = nil // disable any previous rewrite + return + } + f := strings.Split(*rewriteRule, "->") + if len(f) != 2 { + fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n") + os.Exit(2) + } + pattern := parseExpr(f[0], "pattern") + replace := parseExpr(f[1], "replacement") + rewrite = func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) } +} + +// parseExpr parses s as an expression. +// It might make sense to expand this to allow statement patterns, +// but there are problems with preserving formatting and also +// with what a wildcard for a statement looks like. +func parseExpr(s, what string) ast.Expr { + x, err := parser.ParseExpr(s) + if err != nil { + fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err) + os.Exit(2) + } + return x +} + +// Keep this function for debugging. +/* +func dump(msg string, val reflect.Value) { + fmt.Printf("%s:\n", msg) + ast.Print(fileSet, val.Interface()) + fmt.Println() +} +*/ + +// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file. +func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File { + cmap := ast.NewCommentMap(fileSet, p, p.Comments) + m := make(map[string]reflect.Value) + pat := reflect.ValueOf(pattern) + repl := reflect.ValueOf(replace) + + var rewriteVal func(val reflect.Value) reflect.Value + rewriteVal = func(val reflect.Value) reflect.Value { + // don't bother if val is invalid to start with + if !val.IsValid() { + return reflect.Value{} + } + val = apply(rewriteVal, val) + for k := range m { + delete(m, k) + } + if match(m, pat, val) { + val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos())) + } + return val + } + + r := apply(rewriteVal, reflect.ValueOf(p)).Interface().(*ast.File) + r.Comments = cmap.Filter(r).Comments() // recreate comments list + return r +} + +// set is a wrapper for x.Set(y); it protects the caller from panics if x cannot be changed to y. +func set(x, y reflect.Value) { + // don't bother if x cannot be set or y is invalid + if !x.CanSet() || !y.IsValid() { + return + } + defer func() { + if x := recover(); x != nil { + if s, ok := x.(string); ok && + (strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) { + // x cannot be set to y - ignore this rewrite + return + } + panic(x) + } + }() + x.Set(y) +} + +// Values/types for special cases. +var ( + objectPtrNil = reflect.ValueOf((*ast.Object)(nil)) + scopePtrNil = reflect.ValueOf((*ast.Scope)(nil)) + + identType = reflect.TypeOf((*ast.Ident)(nil)) + objectPtrType = reflect.TypeOf((*ast.Object)(nil)) + positionType = reflect.TypeOf(token.NoPos) + callExprType = reflect.TypeOf((*ast.CallExpr)(nil)) + scopePtrType = reflect.TypeOf((*ast.Scope)(nil)) +) + +// apply replaces each AST field x in val with f(x), returning val. +// To avoid extra conversions, f operates on the reflect.Value form. +func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value { + if !val.IsValid() { + return reflect.Value{} + } + + // *ast.Objects introduce cycles and are likely incorrect after + // rewrite; don't follow them but replace with nil instead + if val.Type() == objectPtrType { + return objectPtrNil + } + + // similarly for scopes: they are likely incorrect after a rewrite; + // replace them with nil + if val.Type() == scopePtrType { + return scopePtrNil + } + + switch v := reflect.Indirect(val); v.Kind() { + case reflect.Slice: + for i := 0; i < v.Len(); i++ { + e := v.Index(i) + set(e, f(e)) + } + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + e := v.Field(i) + set(e, f(e)) + } + case reflect.Interface: + e := v.Elem() + set(v, f(e)) + } + return val +} + +func isWildcard(s string) bool { + rune, size := utf8.DecodeRuneInString(s) + return size == len(s) && unicode.IsLower(rune) +} + +// match reports whether pattern matches val, +// recording wildcard submatches in m. +// If m == nil, match checks whether pattern == val. +func match(m map[string]reflect.Value, pattern, val reflect.Value) bool { + // Wildcard matches any expression. If it appears multiple + // times in the pattern, it must match the same expression + // each time. + if m != nil && pattern.IsValid() && pattern.Type() == identType { + name := pattern.Interface().(*ast.Ident).Name + if isWildcard(name) && val.IsValid() { + // wildcards only match valid (non-nil) expressions. + if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() { + if old, ok := m[name]; ok { + return match(nil, old, val) + } + m[name] = val + return true + } + } + } + + // Otherwise, pattern and val must match recursively. + if !pattern.IsValid() || !val.IsValid() { + return !pattern.IsValid() && !val.IsValid() + } + if pattern.Type() != val.Type() { + return false + } + + // Special cases. + switch pattern.Type() { + case identType: + // For identifiers, only the names need to match + // (and none of the other *ast.Object information). + // This is a common case, handle it all here instead + // of recursing down any further via reflection. + p := pattern.Interface().(*ast.Ident) + v := val.Interface().(*ast.Ident) + return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name + case objectPtrType, positionType: + // object pointers and token positions always match + return true + case callExprType: + // For calls, the Ellipsis fields (token.Position) must + // match since that is how f(x) and f(x...) are different. + // Check them here but fall through for the remaining fields. + p := pattern.Interface().(*ast.CallExpr) + v := val.Interface().(*ast.CallExpr) + if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() { + return false + } + } + + p := reflect.Indirect(pattern) + v := reflect.Indirect(val) + if !p.IsValid() || !v.IsValid() { + return !p.IsValid() && !v.IsValid() + } + + switch p.Kind() { + case reflect.Slice: + if p.Len() != v.Len() { + return false + } + for i := 0; i < p.Len(); i++ { + if !match(m, p.Index(i), v.Index(i)) { + return false + } + } + return true + + case reflect.Struct: + for i := 0; i < p.NumField(); i++ { + if !match(m, p.Field(i), v.Field(i)) { + return false + } + } + return true + + case reflect.Interface: + return match(m, p.Elem(), v.Elem()) + } + + // Handle token integers, etc. + return p.Interface() == v.Interface() +} + +// subst returns a copy of pattern with values from m substituted in place +// of wildcards and pos used as the position of tokens from the pattern. +// if m == nil, subst returns a copy of pattern and doesn't change the line +// number information. +func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value { + if !pattern.IsValid() { + return reflect.Value{} + } + + // Wildcard gets replaced with map value. + if m != nil && pattern.Type() == identType { + name := pattern.Interface().(*ast.Ident).Name + if isWildcard(name) { + if old, ok := m[name]; ok { + return subst(nil, old, reflect.Value{}) + } + } + } + + if pos.IsValid() && pattern.Type() == positionType { + // use new position only if old position was valid in the first place + if old := pattern.Interface().(token.Pos); !old.IsValid() { + return pattern + } + return pos + } + + // Otherwise copy. + switch p := pattern; p.Kind() { + case reflect.Slice: + v := reflect.MakeSlice(p.Type(), p.Len(), p.Len()) + for i := 0; i < p.Len(); i++ { + v.Index(i).Set(subst(m, p.Index(i), pos)) + } + return v + + case reflect.Struct: + v := reflect.New(p.Type()).Elem() + for i := 0; i < p.NumField(); i++ { + v.Field(i).Set(subst(m, p.Field(i), pos)) + } + return v + + case reflect.Ptr: + v := reflect.New(p.Type()).Elem() + if elem := p.Elem(); elem.IsValid() { + v.Set(subst(m, elem, pos).Addr()) + } + return v + + case reflect.Interface: + v := reflect.New(p.Type()).Elem() + if elem := p.Elem(); elem.IsValid() { + v.Set(subst(m, elem, pos)) + } + return v + } + + return pattern +} diff --git a/vendor/github.com/golangci/gofmt/gofmt/simplify.go b/vendor/github.com/golangci/gofmt/gofmt/simplify.go new file mode 100644 index 000000000..2c75495a6 --- /dev/null +++ b/vendor/github.com/golangci/gofmt/gofmt/simplify.go @@ -0,0 +1,165 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gofmt + +import ( + "go/ast" + "go/token" + "reflect" +) + +type simplifier struct{} + +func (s simplifier) Visit(node ast.Node) ast.Visitor { + switch n := node.(type) { + case *ast.CompositeLit: + // array, slice, and map composite literals may be simplified + outer := n + var keyType, eltType ast.Expr + switch typ := outer.Type.(type) { + case *ast.ArrayType: + eltType = typ.Elt + case *ast.MapType: + keyType = typ.Key + eltType = typ.Value + } + + if eltType != nil { + var ktyp reflect.Value + if keyType != nil { + ktyp = reflect.ValueOf(keyType) + } + typ := reflect.ValueOf(eltType) + for i, x := range outer.Elts { + px := &outer.Elts[i] + // look at value of indexed/named elements + if t, ok := x.(*ast.KeyValueExpr); ok { + if keyType != nil { + s.simplifyLiteral(ktyp, keyType, t.Key, &t.Key) + } + x = t.Value + px = &t.Value + } + s.simplifyLiteral(typ, eltType, x, px) + } + // node was simplified - stop walk (there are no subnodes to simplify) + return nil + } + + case *ast.SliceExpr: + // a slice expression of the form: s[a:len(s)] + // can be simplified to: s[a:] + // if s is "simple enough" (for now we only accept identifiers) + // + // Note: This may not be correct because len may have been redeclared in another + // file belonging to the same package. However, this is extremely unlikely + // and so far (April 2016, after years of supporting this rewrite feature) + // has never come up, so let's keep it working as is (see also #15153). + if n.Max != nil { + // - 3-index slices always require the 2nd and 3rd index + break + } + if s, _ := n.X.(*ast.Ident); s != nil && s.Obj != nil { + // the array/slice object is a single, resolved identifier + if call, _ := n.High.(*ast.CallExpr); call != nil && len(call.Args) == 1 && !call.Ellipsis.IsValid() { + // the high expression is a function call with a single argument + if fun, _ := call.Fun.(*ast.Ident); fun != nil && fun.Name == "len" && fun.Obj == nil { + // the function called is "len" and it is not locally defined; and + // because we don't have dot imports, it must be the predefined len() + if arg, _ := call.Args[0].(*ast.Ident); arg != nil && arg.Obj == s.Obj { + // the len argument is the array/slice object + n.High = nil + } + } + } + } + // Note: We could also simplify slice expressions of the form s[0:b] to s[:b] + // but we leave them as is since sometimes we want to be very explicit + // about the lower bound. + // An example where the 0 helps: + // x, y, z := b[0:2], b[2:4], b[4:6] + // An example where it does not: + // x, y := b[:n], b[n:] + + case *ast.RangeStmt: + // - a range of the form: for x, _ = range v {...} + // can be simplified to: for x = range v {...} + // - a range of the form: for _ = range v {...} + // can be simplified to: for range v {...} + if isBlank(n.Value) { + n.Value = nil + } + if isBlank(n.Key) && n.Value == nil { + n.Key = nil + } + } + + return s +} + +func (s simplifier) simplifyLiteral(typ reflect.Value, astType, x ast.Expr, px *ast.Expr) { + ast.Walk(s, x) // simplify x + + // if the element is a composite literal and its literal type + // matches the outer literal's element type exactly, the inner + // literal type may be omitted + if inner, ok := x.(*ast.CompositeLit); ok { + if match(nil, typ, reflect.ValueOf(inner.Type)) { + inner.Type = nil + } + } + // if the outer literal's element type is a pointer type *T + // and the element is & of a composite literal of type T, + // the inner &T may be omitted. + if ptr, ok := astType.(*ast.StarExpr); ok { + if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND { + if inner, ok := addr.X.(*ast.CompositeLit); ok { + if match(nil, reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) { + inner.Type = nil // drop T + *px = inner // drop & + } + } + } + } +} + +func isBlank(x ast.Expr) bool { + ident, ok := x.(*ast.Ident) + return ok && ident.Name == "_" +} + +func simplify(f *ast.File) { + // remove empty declarations such as "const ()", etc + removeEmptyDeclGroups(f) + + var s simplifier + ast.Walk(s, f) +} + +func removeEmptyDeclGroups(f *ast.File) { + i := 0 + for _, d := range f.Decls { + if g, ok := d.(*ast.GenDecl); !ok || !isEmpty(f, g) { + f.Decls[i] = d + i++ + } + } + f.Decls = f.Decls[:i] +} + +func isEmpty(f *ast.File, g *ast.GenDecl) bool { + if g.Doc != nil || g.Specs != nil { + return false + } + + for _, c := range f.Comments { + // if there is a comment in the declaration, it is not considered empty + if g.Pos() <= c.Pos() && c.End() <= g.End() { + return false + } + } + + return true +} diff --git a/vendor/github.com/golangci/gofmt/goimports/LICENSE b/vendor/github.com/golangci/gofmt/goimports/LICENSE new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/vendor/github.com/golangci/gofmt/goimports/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/golangci/gofmt/goimports/goimports.go b/vendor/github.com/golangci/gofmt/goimports/goimports.go new file mode 100644 index 000000000..8878b700d --- /dev/null +++ b/vendor/github.com/golangci/gofmt/goimports/goimports.go @@ -0,0 +1,358 @@ +// 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 goimports + +import ( + "bufio" + "bytes" + "errors" + "flag" + "fmt" + "go/scanner" + "io" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "runtime" + "runtime/pprof" + "strings" + + "golang.org/x/tools/imports" +) + +var ( + // main operation modes + list = flag.Bool("goimports.l", false, "list files whose formatting differs from goimport's") + write = flag.Bool("goimports.w", false, "write result to (source) file instead of stdout") + doDiff = flag.Bool("goimports.d", false, "display diffs instead of rewriting files") + srcdir = flag.String("goimports.srcdir", "", "choose imports as if source code is from `dir`. When operating on a single file, dir may instead be the complete file name.") + verbose bool // verbose logging + + cpuProfile = flag.String("goimports.cpuprofile", "", "CPU profile output") + memProfile = flag.String("goimports.memprofile", "", "memory profile output") + memProfileRate = flag.Int("goimports.memrate", 0, "if > 0, sets runtime.MemProfileRate") + + options = &imports.Options{ + TabWidth: 8, + TabIndent: true, + Comments: true, + Fragment: true, + } + exitCode = 0 +) + +func init() { + flag.BoolVar(&options.AllErrors, "goimports.e", false, "report all errors (not just the first 10 on different lines)") + flag.StringVar(&imports.LocalPrefix, "goimports.local", "", "put imports beginning with this string after 3rd-party packages; comma-separated list") +} + +func report(err error) { + scanner.PrintError(os.Stderr, err) + exitCode = 2 +} + +func usage() { + fmt.Fprintf(os.Stderr, "usage: goimports [flags] [path ...]\n") + flag.PrintDefaults() + os.Exit(2) +} + +func isGoFile(f os.FileInfo) bool { + // ignore non-Go files + name := f.Name() + return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") +} + +// argumentType is which mode goimports was invoked as. +type argumentType int + +const ( + // fromStdin means the user is piping their source into goimports. + fromStdin argumentType = iota + + // singleArg is the common case from editors, when goimports is run on + // a single file. + singleArg + + // multipleArg is when the user ran "goimports file1.go file2.go" + // or ran goimports on a directory tree. + multipleArg +) + +func processFile(filename string, in io.Reader, out io.Writer, argType argumentType) error { + opt := options + if argType == fromStdin { + nopt := *options + nopt.Fragment = true + opt = &nopt + } + + if in == nil { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + in = f + } + + src, err := ioutil.ReadAll(in) + if err != nil { + return err + } + + target := filename + if *srcdir != "" { + // Determine whether the provided -srcdirc is a directory or file + // and then use it to override the target. + // + // See https://github.com/dominikh/go-mode.el/issues/146 + if isFile(*srcdir) { + if argType == multipleArg { + return errors.New("-srcdir value can't be a file when passing multiple arguments or when walking directories") + } + target = *srcdir + } else if argType == singleArg && strings.HasSuffix(*srcdir, ".go") && !isDir(*srcdir) { + // For a file which doesn't exist on disk yet, but might shortly. + // e.g. user in editor opens $DIR/newfile.go and newfile.go doesn't yet exist on disk. + // The goimports on-save hook writes the buffer to a temp file + // first and runs goimports before the actual save to newfile.go. + // The editor's buffer is named "newfile.go" so that is passed to goimports as: + // goimports -srcdir=/gopath/src/pkg/newfile.go /tmp/gofmtXXXXXXXX.go + // and then the editor reloads the result from the tmp file and writes + // it to newfile.go. + target = *srcdir + } else { + // Pretend that file is from *srcdir in order to decide + // visible imports correctly. + target = filepath.Join(*srcdir, filepath.Base(filename)) + } + } + + res, err := imports.Process(target, src, opt) + if err != nil { + return err + } + + if !bytes.Equal(src, res) { + // formatting has changed + if *list { + fmt.Fprintln(out, filename) + } + if *write { + if argType == fromStdin { + // filename is "" + return errors.New("can't use -w on stdin") + } + err = ioutil.WriteFile(filename, res, 0) + if err != nil { + return err + } + } + if *doDiff { + if argType == fromStdin { + filename = "stdin.go" // because .orig looks silly + } + data, err := diff(src, res, filename) + if err != nil { + return fmt.Errorf("computing diff: %s", err) + } + fmt.Printf("diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename)) + out.Write(data) + } + } + + if !*list && !*write && !*doDiff { + _, err = out.Write(res) + } + + return err +} + +func visitFile(path string, f os.FileInfo, err error) error { + if err == nil && isGoFile(f) { + err = processFile(path, nil, os.Stdout, multipleArg) + } + if err != nil { + report(err) + } + return nil +} + +func walkDir(path string) { + filepath.Walk(path, visitFile) +} + +// parseFlags parses command line flags and returns the paths to process. +// It's a var so that custom implementations can replace it in other files. +var parseFlags = func() []string { + flag.BoolVar(&verbose, "v", false, "verbose logging") + + flag.Parse() + return flag.Args() +} + +func bufferedFileWriter(dest string) (w io.Writer, close func()) { + f, err := os.Create(dest) + if err != nil { + log.Fatal(err) + } + bw := bufio.NewWriter(f) + return bw, func() { + if err := bw.Flush(); err != nil { + log.Fatalf("error flushing %v: %v", dest, err) + } + if err := f.Close(); err != nil { + log.Fatal(err) + } + } +} + +func gofmtMain() { + flag.Usage = usage + paths := parseFlags() + + if *cpuProfile != "" { + bw, flush := bufferedFileWriter(*cpuProfile) + pprof.StartCPUProfile(bw) + defer flush() + defer pprof.StopCPUProfile() + } + // doTrace is a conditionally compiled wrapper around runtime/trace. It is + // used to allow goimports to compile under gccgo, which does not support + // runtime/trace. See https://golang.org/issue/15544. + if *memProfileRate > 0 { + runtime.MemProfileRate = *memProfileRate + bw, flush := bufferedFileWriter(*memProfile) + defer func() { + runtime.GC() // materialize all statistics + if err := pprof.WriteHeapProfile(bw); err != nil { + log.Fatal(err) + } + flush() + }() + } + + if verbose { + log.SetFlags(log.LstdFlags | log.Lmicroseconds) + imports.Debug = true + } + if options.TabWidth < 0 { + fmt.Fprintf(os.Stderr, "negative tabwidth %d\n", options.TabWidth) + exitCode = 2 + return + } + + if len(paths) == 0 { + if err := processFile("", os.Stdin, os.Stdout, fromStdin); err != nil { + report(err) + } + return + } + + argType := singleArg + if len(paths) > 1 { + argType = multipleArg + } + + for _, path := range paths { + switch dir, err := os.Stat(path); { + case err != nil: + report(err) + case dir.IsDir(): + walkDir(path) + default: + if err := processFile(path, nil, os.Stdout, argType); err != nil { + report(err) + } + } + } +} + +func writeTempFile(dir, prefix string, data []byte) (string, error) { + file, err := ioutil.TempFile(dir, prefix) + if err != nil { + return "", err + } + _, err = file.Write(data) + if err1 := file.Close(); err == nil { + err = err1 + } + if err != nil { + os.Remove(file.Name()) + return "", err + } + return file.Name(), nil +} + +func diff(b1, b2 []byte, filename string) (data []byte, err error) { + f1, err := writeTempFile("", "gofmt", b1) + if err != nil { + return + } + defer os.Remove(f1) + + f2, err := writeTempFile("", "gofmt", b2) + if err != nil { + return + } + defer os.Remove(f2) + + cmd := "diff" + if runtime.GOOS == "plan9" { + cmd = "/bin/ape/diff" + } + + data, err = exec.Command(cmd, "-u", f1, f2).CombinedOutput() + if len(data) > 0 { + // diff exits with a non-zero status when the files don't match. + // Ignore that failure as long as we get output. + return replaceTempFilename(data, filename) + } + return +} + +// replaceTempFilename replaces temporary filenames in diff with actual one. +// +// --- /tmp/gofmt316145376 2017-02-03 19:13:00.280468375 -0500 +// +++ /tmp/gofmt617882815 2017-02-03 19:13:00.280468375 -0500 +// ... +// -> +// --- path/to/file.go.orig 2017-02-03 19:13:00.280468375 -0500 +// +++ path/to/file.go 2017-02-03 19:13:00.280468375 -0500 +// ... +func replaceTempFilename(diff []byte, filename string) ([]byte, error) { + bs := bytes.SplitN(diff, []byte{'\n'}, 3) + if len(bs) < 3 { + return nil, fmt.Errorf("got unexpected diff for %s", filename) + } + // Preserve timestamps. + var t0, t1 []byte + if i := bytes.LastIndexByte(bs[0], '\t'); i != -1 { + t0 = bs[0][i:] + } + if i := bytes.LastIndexByte(bs[1], '\t'); i != -1 { + t1 = bs[1][i:] + } + // Always print filepath with slash separator. + f := filepath.ToSlash(filename) + bs[0] = []byte(fmt.Sprintf("--- %s%s", f+".orig", t0)) + bs[1] = []byte(fmt.Sprintf("+++ %s%s", f, t1)) + return bytes.Join(bs, []byte{'\n'}), nil +} + +// isFile reports whether name is a file. +func isFile(name string) bool { + fi, err := os.Stat(name) + return err == nil && fi.Mode().IsRegular() +} + +// isDir reports whether name is a directory. +func isDir(name string) bool { + fi, err := os.Stat(name) + return err == nil && fi.IsDir() +} diff --git a/vendor/github.com/golangci/gofmt/goimports/golangci.go b/vendor/github.com/golangci/gofmt/goimports/golangci.go new file mode 100644 index 000000000..e9d013d58 --- /dev/null +++ b/vendor/github.com/golangci/gofmt/goimports/golangci.go @@ -0,0 +1,33 @@ +package goimports + +import ( + "bytes" + "fmt" + "io/ioutil" + + "golang.org/x/tools/imports" +) + +func Run(filename string) ([]byte, error) { + src, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + + res, err := imports.Process(filename, src, options) + if err != nil { + return nil, err + } + + if bytes.Equal(src, res) { + return nil, nil + } + + // formatting has changed + data, err := diff(src, res, filename) + if err != nil { + return nil, fmt.Errorf("error computing diff: %s", err) + } + + return data, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/LICENSE b/vendor/github.com/golangci/golangci-lint/LICENSE new file mode 100644 index 000000000..e72bfddab --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/vendor/github.com/golangci/golangci-lint/cmd/golangci-lint/main.go b/vendor/github.com/golangci/golangci-lint/cmd/golangci-lint/main.go new file mode 100644 index 000000000..282d794b8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/cmd/golangci-lint/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "os" + + "github.com/golangci/golangci-lint/pkg/commands" + "github.com/golangci/golangci-lint/pkg/exitcodes" +) + +var ( + // Populated by goreleaser during build + version = "master" + commit = "?" + date = "" +) + +func main() { + e := commands.NewExecutor(version, commit, date) + + if err := e.Execute(); err != nil { + fmt.Fprintf(os.Stderr, "failed executing command with error %v\n", err) + os.Exit(exitcodes.Failure) + } +} diff --git a/vendor/github.com/golangci/golangci-lint/cmd/golangci-lint/mod_version.go b/vendor/github.com/golangci/golangci-lint/cmd/golangci-lint/mod_version.go new file mode 100644 index 000000000..7b596728e --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/cmd/golangci-lint/mod_version.go @@ -0,0 +1,19 @@ +// +build go1.12 + +package main + +import ( + "fmt" + "runtime/debug" +) + +//nolint:gochecknoinits +func init() { + if info, available := debug.ReadBuildInfo(); available { + if date == "" { + version = info.Main.Version + commit = fmt.Sprintf("(unknown, mod sum: %q)", info.Main.Sum) + date = "(unknown)" + } + } +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/cache/cache.go b/vendor/github.com/golangci/golangci-lint/internal/cache/cache.go new file mode 100644 index 000000000..ae5b7da18 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/cache/cache.go @@ -0,0 +1,544 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cache implements a build artifact cache. +// +// This package is a slightly modified fork of Go's +// cmd/go/internal/cache package. +package cache + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/pkg/errors" + + "github.com/golangci/golangci-lint/internal/renameio" + "github.com/golangci/golangci-lint/internal/robustio" +) + +// An ActionID is a cache action key, the hash of a complete description of a +// repeatable computation (command line, environment variables, +// input file contents, executable contents). +type ActionID [HashSize]byte + +// An OutputID is a cache output key, the hash of an output of a computation. +type OutputID [HashSize]byte + +// A Cache is a package cache, backed by a file system directory tree. +type Cache struct { + dir string + now func() time.Time +} + +// Open opens and returns the cache in the given directory. +// +// It is safe for multiple processes on a single machine to use the +// same cache directory in a local file system simultaneously. +// They will coordinate using operating system file locks and may +// duplicate effort but will not corrupt the cache. +// +// However, it is NOT safe for multiple processes on different machines +// to share a cache directory (for example, if the directory were stored +// in a network file system). File locking is notoriously unreliable in +// network file systems and may not suffice to protect the cache. +// +func Open(dir string) (*Cache, error) { + info, err := os.Stat(dir) + if err != nil { + return nil, err + } + if !info.IsDir() { + return nil, &os.PathError{Op: "open", Path: dir, Err: fmt.Errorf("not a directory")} + } + for i := 0; i < 256; i++ { + name := filepath.Join(dir, fmt.Sprintf("%02x", i)) + if err := os.MkdirAll(name, 0744); err != nil { + return nil, err + } + } + c := &Cache{ + dir: dir, + now: time.Now, + } + return c, nil +} + +// fileName returns the name of the file corresponding to the given id. +func (c *Cache) fileName(id [HashSize]byte, key string) string { + return filepath.Join(c.dir, fmt.Sprintf("%02x", id[0]), fmt.Sprintf("%x", id)+"-"+key) +} + +var errMissing = errors.New("cache entry not found") + +func IsErrMissing(err error) bool { + return err == errMissing +} + +const ( + // action entry file is "v1 \n" + hexSize = HashSize * 2 + entrySize = 2 + 1 + hexSize + 1 + hexSize + 1 + 20 + 1 + 20 + 1 +) + +// verify controls whether to run the cache in verify mode. +// In verify mode, the cache always returns errMissing from Get +// but then double-checks in Put that the data being written +// exactly matches any existing entry. This provides an easy +// way to detect program behavior that would have been different +// had the cache entry been returned from Get. +// +// verify is enabled by setting the environment variable +// GODEBUG=gocacheverify=1. +var verify = false + +// DebugTest is set when GODEBUG=gocachetest=1 is in the environment. +var DebugTest = false + +func init() { initEnv() } + +func initEnv() { + verify = false + debugHash = false + debug := strings.Split(os.Getenv("GODEBUG"), ",") + for _, f := range debug { + if f == "gocacheverify=1" { + verify = true + } + if f == "gocachehash=1" { + debugHash = true + } + if f == "gocachetest=1" { + DebugTest = true + } + } +} + +// Get looks up the action ID in the cache, +// returning the corresponding output ID and file size, if any. +// Note that finding an output ID does not guarantee that the +// saved file for that output ID is still available. +func (c *Cache) Get(id ActionID) (Entry, error) { + if verify { + return Entry{}, errMissing + } + return c.get(id) +} + +type Entry struct { + OutputID OutputID + Size int64 + Time time.Time +} + +// get is Get but does not respect verify mode, so that Put can use it. +func (c *Cache) get(id ActionID) (Entry, error) { + missing := func() (Entry, error) { + return Entry{}, errMissing + } + failed := func(err error) (Entry, error) { + return Entry{}, err + } + fileName := c.fileName(id, "a") + f, err := os.Open(fileName) + if err != nil { + if os.IsNotExist(err) { + return missing() + } + return failed(err) + } + defer f.Close() + entry := make([]byte, entrySize+1) // +1 to detect whether f is too long + if n, readErr := io.ReadFull(f, entry); n != entrySize || readErr != io.ErrUnexpectedEOF { + return failed(fmt.Errorf("read %d/%d bytes from %s with error %s", n, entrySize, fileName, readErr)) + } + if entry[0] != 'v' || entry[1] != '1' || entry[2] != ' ' || entry[3+hexSize] != ' ' || entry[3+hexSize+1+hexSize] != ' ' || entry[3+hexSize+1+hexSize+1+20] != ' ' || entry[entrySize-1] != '\n' { + return failed(fmt.Errorf("bad data in %s", fileName)) + } + eid, entry := entry[3:3+hexSize], entry[3+hexSize:] + eout, entry := entry[1:1+hexSize], entry[1+hexSize:] + esize, entry := entry[1:1+20], entry[1+20:] + etime := entry[1 : 1+20] + var buf [HashSize]byte + if _, err = hex.Decode(buf[:], eid); err != nil || buf != id { + return failed(errors.Wrapf(err, "failed to hex decode eid data in %s", fileName)) + } + if _, err = hex.Decode(buf[:], eout); err != nil { + return failed(errors.Wrapf(err, "failed to hex decode eout data in %s", fileName)) + } + i := 0 + for i < len(esize) && esize[i] == ' ' { + i++ + } + size, err := strconv.ParseInt(string(esize[i:]), 10, 64) + if err != nil || size < 0 { + return failed(fmt.Errorf("failed to parse esize int from %s with error %s", fileName, err)) + } + i = 0 + for i < len(etime) && etime[i] == ' ' { + i++ + } + tm, err := strconv.ParseInt(string(etime[i:]), 10, 64) + if err != nil || tm < 0 { + return failed(fmt.Errorf("failed to parse etime int from %s with error %s", fileName, err)) + } + + if err = c.used(fileName); err != nil { + return failed(errors.Wrapf(err, "failed to mark %s as used", fileName)) + } + + return Entry{buf, size, time.Unix(0, tm)}, nil +} + +// GetFile looks up the action ID in the cache and returns +// the name of the corresponding data file. +func (c *Cache) GetFile(id ActionID) (file string, entry Entry, err error) { + entry, err = c.Get(id) + if err != nil { + return "", Entry{}, err + } + + file, err = c.OutputFile(entry.OutputID) + if err != nil { + return "", Entry{}, err + } + + info, err := os.Stat(file) + if err != nil || info.Size() != entry.Size { + return "", Entry{}, errMissing + } + return file, entry, nil +} + +// GetBytes looks up the action ID in the cache and returns +// the corresponding output bytes. +// GetBytes should only be used for data that can be expected to fit in memory. +func (c *Cache) GetBytes(id ActionID) ([]byte, Entry, error) { + entry, err := c.Get(id) + if err != nil { + return nil, entry, err + } + outputFile, err := c.OutputFile(entry.OutputID) + if err != nil { + return nil, entry, err + } + + data, err := robustio.ReadFile(outputFile) + if err != nil { + return nil, entry, err + } + + if sha256.Sum256(data) != entry.OutputID { + return nil, entry, errMissing + } + return data, entry, nil +} + +// OutputFile returns the name of the cache file storing output with the given OutputID. +func (c *Cache) OutputFile(out OutputID) (string, error) { + file := c.fileName(out, "d") + if err := c.used(file); err != nil { + return "", err + } + return file, nil +} + +// Time constants for cache expiration. +// +// We set the mtime on a cache file on each use, but at most one per mtimeInterval (1 hour), +// to avoid causing many unnecessary inode updates. The mtimes therefore +// roughly reflect "time of last use" but may in fact be older by at most an hour. +// +// We scan the cache for entries to delete at most once per trimInterval (1 day). +// +// When we do scan the cache, we delete entries that have not been used for +// at least trimLimit (5 days). Statistics gathered from a month of usage by +// Go developers found that essentially all reuse of cached entries happened +// within 5 days of the previous reuse. See golang.org/issue/22990. +const ( + mtimeInterval = 1 * time.Hour + trimInterval = 24 * time.Hour + trimLimit = 5 * 24 * time.Hour +) + +// used makes a best-effort attempt to update mtime on file, +// so that mtime reflects cache access time. +// +// Because the reflection only needs to be approximate, +// and to reduce the amount of disk activity caused by using +// cache entries, used only updates the mtime if the current +// mtime is more than an hour old. This heuristic eliminates +// nearly all of the mtime updates that would otherwise happen, +// while still keeping the mtimes useful for cache trimming. +func (c *Cache) used(file string) error { + info, err := os.Stat(file) + if err != nil { + return errors.Wrapf(err, "failed to stat file %s", file) + } + + if c.now().Sub(info.ModTime()) < mtimeInterval { + return nil + } + + if err := os.Chtimes(file, c.now(), c.now()); err != nil { + return errors.Wrapf(err, "failed to change time of file %s", file) + } + + return nil +} + +// Trim removes old cache entries that are likely not to be reused. +func (c *Cache) Trim() { + now := c.now() + + // We maintain in dir/trim.txt the time of the last completed cache trim. + // If the cache has been trimmed recently enough, do nothing. + // This is the common case. + data, _ := renameio.ReadFile(filepath.Join(c.dir, "trim.txt")) + t, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64) + if err == nil && now.Sub(time.Unix(t, 0)) < trimInterval { + return + } + + // Trim each of the 256 subdirectories. + // We subtract an additional mtimeInterval + // to account for the imprecision of our "last used" mtimes. + cutoff := now.Add(-trimLimit - mtimeInterval) + for i := 0; i < 256; i++ { + subdir := filepath.Join(c.dir, fmt.Sprintf("%02x", i)) + c.trimSubdir(subdir, cutoff) + } + + // Ignore errors from here: if we don't write the complete timestamp, the + // cache will appear older than it is, and we'll trim it again next time. + _ = renameio.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())), 0666) +} + +// trimSubdir trims a single cache subdirectory. +func (c *Cache) trimSubdir(subdir string, cutoff time.Time) { + // Read all directory entries from subdir before removing + // any files, in case removing files invalidates the file offset + // in the directory scan. Also, ignore error from f.Readdirnames, + // because we don't care about reporting the error and we still + // want to process any entries found before the error. + f, err := os.Open(subdir) + if err != nil { + return + } + names, _ := f.Readdirnames(-1) + f.Close() + + for _, name := range names { + // Remove only cache entries (xxxx-a and xxxx-d). + if !strings.HasSuffix(name, "-a") && !strings.HasSuffix(name, "-d") { + continue + } + entry := filepath.Join(subdir, name) + info, err := os.Stat(entry) + if err == nil && info.ModTime().Before(cutoff) { + os.Remove(entry) + } + } +} + +// putIndexEntry adds an entry to the cache recording that executing the action +// with the given id produces an output with the given output id (hash) and size. +func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify bool) error { + // Note: We expect that for one reason or another it may happen + // that repeating an action produces a different output hash + // (for example, if the output contains a time stamp or temp dir name). + // While not ideal, this is also not a correctness problem, so we + // don't make a big deal about it. In particular, we leave the action + // cache entries writable specifically so that they can be overwritten. + // + // Setting GODEBUG=gocacheverify=1 does make a big deal: + // in verify mode we are double-checking that the cache entries + // are entirely reproducible. As just noted, this may be unrealistic + // in some cases but the check is also useful for shaking out real bugs. + entry := fmt.Sprintf("v1 %x %x %20d %20d\n", id, out, size, time.Now().UnixNano()) + + if verify && allowVerify { + old, err := c.get(id) + if err == nil && (old.OutputID != out || old.Size != size) { + // panic to show stack trace, so we can see what code is generating this cache entry. + msg := fmt.Sprintf("go: internal cache error: cache verify failed: id=%x changed:<<<\n%s\n>>>\nold: %x %d\nnew: %x %d", id, reverseHash(id), out, size, old.OutputID, old.Size) + panic(msg) + } + } + file := c.fileName(id, "a") + + // Copy file to cache directory. + mode := os.O_WRONLY | os.O_CREATE + f, err := os.OpenFile(file, mode, 0666) + if err != nil { + return err + } + _, err = f.WriteString(entry) + if err == nil { + // Truncate the file only *after* writing it. + // (This should be a no-op, but truncate just in case of previous corruption.) + // + // This differs from ioutil.WriteFile, which truncates to 0 *before* writing + // via os.O_TRUNC. Truncating only after writing ensures that a second write + // of the same content to the same file is idempotent, and does not — even + // temporarily! — undo the effect of the first write. + err = f.Truncate(int64(len(entry))) + } + if closeErr := f.Close(); err == nil { + err = closeErr + } + if err != nil { + // TODO(bcmills): This Remove potentially races with another go command writing to file. + // Can we eliminate it? + os.Remove(file) + return err + } + if err = os.Chtimes(file, c.now(), c.now()); err != nil { // mainly for tests + return errors.Wrapf(err, "failed to change time of file %s", file) + } + + return nil +} + +// Put stores the given output in the cache as the output for the action ID. +// It may read file twice. The content of file must not change between the two passes. +func (c *Cache) Put(id ActionID, file io.ReadSeeker) (OutputID, int64, error) { + return c.put(id, file, true) +} + +// PutNoVerify is like Put but disables the verify check +// when GODEBUG=goverifycache=1 is set. +// It is meant for data that is OK to cache but that we expect to vary slightly from run to run, +// like test output containing times and the like. +func (c *Cache) PutNoVerify(id ActionID, file io.ReadSeeker) (OutputID, int64, error) { + return c.put(id, file, false) +} + +func (c *Cache) put(id ActionID, file io.ReadSeeker, allowVerify bool) (OutputID, int64, error) { + // Compute output ID. + h := sha256.New() + if _, err := file.Seek(0, 0); err != nil { + return OutputID{}, 0, err + } + size, err := io.Copy(h, file) + if err != nil { + return OutputID{}, 0, err + } + var out OutputID + h.Sum(out[:0]) + + // Copy to cached output file (if not already present). + if err := c.copyFile(file, out, size); err != nil { + return out, size, err + } + + // Add to cache index. + return out, size, c.putIndexEntry(id, out, size, allowVerify) +} + +// PutBytes stores the given bytes in the cache as the output for the action ID. +func (c *Cache) PutBytes(id ActionID, data []byte) error { + _, _, err := c.Put(id, bytes.NewReader(data)) + return err +} + +// copyFile copies file into the cache, expecting it to have the given +// output ID and size, if that file is not present already. +func (c *Cache) copyFile(file io.ReadSeeker, out OutputID, size int64) error { + name := c.fileName(out, "d") + info, err := os.Stat(name) + if err == nil && info.Size() == size { + // Check hash. + if f, openErr := os.Open(name); openErr == nil { + h := sha256.New() + if _, copyErr := io.Copy(h, f); copyErr != nil { + return errors.Wrap(copyErr, "failed to copy to sha256") + } + + f.Close() + var out2 OutputID + h.Sum(out2[:0]) + if out == out2 { + return nil + } + } + // Hash did not match. Fall through and rewrite file. + } + + // Copy file to cache directory. + mode := os.O_RDWR | os.O_CREATE + if err == nil && info.Size() > size { // shouldn't happen but fix in case + mode |= os.O_TRUNC + } + f, err := os.OpenFile(name, mode, 0666) + if err != nil { + return err + } + defer f.Close() + if size == 0 { + // File now exists with correct size. + // Only one possible zero-length file, so contents are OK too. + // Early return here makes sure there's a "last byte" for code below. + return nil + } + + // From here on, if any of the I/O writing the file fails, + // we make a best-effort attempt to truncate the file f + // before returning, to avoid leaving bad bytes in the file. + + // Copy file to f, but also into h to double-check hash. + if _, err = file.Seek(0, 0); err != nil { + _ = f.Truncate(0) + return err + } + h := sha256.New() + w := io.MultiWriter(f, h) + if _, err = io.CopyN(w, file, size-1); err != nil { + _ = f.Truncate(0) + return err + } + // Check last byte before writing it; writing it will make the size match + // what other processes expect to find and might cause them to start + // using the file. + buf := make([]byte, 1) + if _, err = file.Read(buf); err != nil { + _ = f.Truncate(0) + return err + } + if n, wErr := h.Write(buf); n != len(buf) { + return fmt.Errorf("wrote to hash %d/%d bytes with error %s", n, len(buf), wErr) + } + + sum := h.Sum(nil) + if !bytes.Equal(sum, out[:]) { + _ = f.Truncate(0) + return fmt.Errorf("file content changed underfoot") + } + + // Commit cache file entry. + if _, err = f.Write(buf); err != nil { + _ = f.Truncate(0) + return err + } + if err = f.Close(); err != nil { + // Data might not have been written, + // but file may look like it is the right size. + // To be extra careful, remove cached file. + os.Remove(name) + return err + } + if err = os.Chtimes(name, c.now(), c.now()); err != nil { // mainly for tests + return errors.Wrapf(err, "failed to change time of file %s", name) + } + + return nil +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/cache/default.go b/vendor/github.com/golangci/golangci-lint/internal/cache/default.go new file mode 100644 index 000000000..e8866cb30 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/cache/default.go @@ -0,0 +1,87 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cache + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "sync" +) + +// Default returns the default cache to use. +func Default() (*Cache, error) { + defaultOnce.Do(initDefaultCache) + return defaultCache, defaultDirErr +} + +var ( + defaultOnce sync.Once + defaultCache *Cache +) + +// cacheREADME is a message stored in a README in the cache directory. +// Because the cache lives outside the normal Go trees, we leave the +// README as a courtesy to explain where it came from. +const cacheREADME = `This directory holds cached build artifacts from golangci-lint. +` + +// initDefaultCache does the work of finding the default cache +// the first time Default is called. +func initDefaultCache() { + dir := DefaultDir() + if err := os.MkdirAll(dir, 0744); err != nil { + log.Fatalf("failed to initialize build cache at %s: %s\n", dir, err) + } + if _, err := os.Stat(filepath.Join(dir, "README")); err != nil { + // Best effort. + if wErr := ioutil.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666); wErr != nil { + log.Fatalf("Failed to write README file to cache dir %s: %s", dir, err) + } + } + + c, err := Open(dir) + if err != nil { + log.Fatalf("failed to initialize build cache at %s: %s\n", dir, err) + } + defaultCache = c +} + +var ( + defaultDirOnce sync.Once + defaultDir string + defaultDirErr error +) + +// DefaultDir returns the effective GOLANGCI_LINT_CACHE setting. +func DefaultDir() string { + // Save the result of the first call to DefaultDir for later use in + // initDefaultCache. cmd/go/main.go explicitly sets GOCACHE so that + // subprocesses will inherit it, but that means initDefaultCache can't + // otherwise distinguish between an explicit "off" and a UserCacheDir error. + + defaultDirOnce.Do(func() { + defaultDir = os.Getenv("GOLANGCI_LINT_CACHE") + if filepath.IsAbs(defaultDir) { + return + } + if defaultDir != "" { + defaultDirErr = fmt.Errorf("GOLANGCI_LINT_CACHE is not an absolute path") + return + } + + // Compute default location. + dir, err := os.UserCacheDir() + if err != nil { + defaultDirErr = fmt.Errorf("GOLANGCI_LINT_CACHE is not defined and %v", err) + return + } + defaultDir = filepath.Join(dir, "golangci-lint") + }) + + return defaultDir +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/cache/hash.go b/vendor/github.com/golangci/golangci-lint/internal/cache/hash.go new file mode 100644 index 000000000..4ce79e325 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/cache/hash.go @@ -0,0 +1,186 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cache + +import ( + "bytes" + "crypto/sha256" + "fmt" + "hash" + "io" + "os" + "sync" +) + +var debugHash = false // set when GODEBUG=gocachehash=1 + +// HashSize is the number of bytes in a hash. +const HashSize = 32 + +// A Hash provides access to the canonical hash function used to index the cache. +// The current implementation uses salted SHA256, but clients must not assume this. +type Hash struct { + h hash.Hash + name string // for debugging + buf *bytes.Buffer // for verify +} + +// hashSalt is a salt string added to the beginning of every hash +// created by NewHash. Using the golangci-lint version makes sure that different +// versions of the command do not address the same cache +// entries, so that a bug in one version does not affect the execution +// of other versions. This salt will result in additional ActionID files +// in the cache, but not additional copies of the large output files, +// which are still addressed by unsalted SHA256. +var hashSalt []byte + +func SetSalt(b []byte) { + hashSalt = b +} + +// Subkey returns an action ID corresponding to mixing a parent +// action ID with a string description of the subkey. +func Subkey(parent ActionID, desc string) (ActionID, error) { + h := sha256.New() + const subkeyPrefix = "subkey:" + if n, err := h.Write([]byte(subkeyPrefix)); n != len(subkeyPrefix) { + return ActionID{}, fmt.Errorf("wrote %d/%d bytes of subkey prefix with error %s", n, len(subkeyPrefix), err) + } + if n, err := h.Write(parent[:]); n != len(parent) { + return ActionID{}, fmt.Errorf("wrote %d/%d bytes of parent with error %s", n, len(parent), err) + } + if n, err := h.Write([]byte(desc)); n != len(desc) { + return ActionID{}, fmt.Errorf("wrote %d/%d bytes of desc with error %s", n, len(desc), err) + } + + var out ActionID + h.Sum(out[:0]) + if debugHash { + fmt.Fprintf(os.Stderr, "HASH subkey %x %q = %x\n", parent, desc, out) + } + if verify { + hashDebug.Lock() + hashDebug.m[out] = fmt.Sprintf("subkey %x %q", parent, desc) + hashDebug.Unlock() + } + return out, nil +} + +// NewHash returns a new Hash. +// The caller is expected to Write data to it and then call Sum. +func NewHash(name string) (*Hash, error) { + h := &Hash{h: sha256.New(), name: name} + if debugHash { + fmt.Fprintf(os.Stderr, "HASH[%s]\n", h.name) + } + if n, err := h.Write(hashSalt); n != len(hashSalt) { + return nil, fmt.Errorf("wrote %d/%d bytes of hash salt with error %s", n, len(hashSalt), err) + } + if verify { + h.buf = new(bytes.Buffer) + } + return h, nil +} + +// Write writes data to the running hash. +func (h *Hash) Write(b []byte) (int, error) { + if debugHash { + fmt.Fprintf(os.Stderr, "HASH[%s]: %q\n", h.name, b) + } + if h.buf != nil { + h.buf.Write(b) + } + return h.h.Write(b) +} + +// Sum returns the hash of the data written previously. +func (h *Hash) Sum() [HashSize]byte { + var out [HashSize]byte + h.h.Sum(out[:0]) + if debugHash { + fmt.Fprintf(os.Stderr, "HASH[%s]: %x\n", h.name, out) + } + if h.buf != nil { + hashDebug.Lock() + if hashDebug.m == nil { + hashDebug.m = make(map[[HashSize]byte]string) + } + hashDebug.m[out] = h.buf.String() + hashDebug.Unlock() + } + return out +} + +// In GODEBUG=gocacheverify=1 mode, +// hashDebug holds the input to every computed hash ID, +// so that we can work backward from the ID involved in a +// cache entry mismatch to a description of what should be there. +var hashDebug struct { + sync.Mutex + m map[[HashSize]byte]string +} + +// reverseHash returns the input used to compute the hash id. +func reverseHash(id [HashSize]byte) string { + hashDebug.Lock() + s := hashDebug.m[id] + hashDebug.Unlock() + return s +} + +var hashFileCache struct { + sync.Mutex + m map[string][HashSize]byte +} + +// FileHash returns the hash of the named file. +// It caches repeated lookups for a given file, +// and the cache entry for a file can be initialized +// using SetFileHash. +// The hash used by FileHash is not the same as +// the hash used by NewHash. +func FileHash(file string) ([HashSize]byte, error) { + hashFileCache.Lock() + out, ok := hashFileCache.m[file] + hashFileCache.Unlock() + + if ok { + return out, nil + } + + h := sha256.New() + f, err := os.Open(file) + if err != nil { + if debugHash { + fmt.Fprintf(os.Stderr, "HASH %s: %v\n", file, err) + } + return [HashSize]byte{}, err + } + _, err = io.Copy(h, f) + f.Close() + if err != nil { + if debugHash { + fmt.Fprintf(os.Stderr, "HASH %s: %v\n", file, err) + } + return [HashSize]byte{}, err + } + h.Sum(out[:0]) + if debugHash { + fmt.Fprintf(os.Stderr, "HASH %s: %x\n", file, out) + } + + SetFileHash(file, out) + return out, nil +} + +// SetFileHash sets the hash returned by FileHash for file. +func SetFileHash(file string, sum [HashSize]byte) { + hashFileCache.Lock() + if hashFileCache.m == nil { + hashFileCache.m = make(map[string][HashSize]byte) + } + hashFileCache.m[file] = sum + hashFileCache.Unlock() +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/errorutil/errors.go b/vendor/github.com/golangci/golangci-lint/internal/errorutil/errors.go new file mode 100644 index 000000000..5cb86d669 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/errorutil/errors.go @@ -0,0 +1,23 @@ +package errorutil + +import ( + "fmt" +) + +// PanicError can be used to not print stacktrace twice +type PanicError struct { + recovered interface{} + stack []byte +} + +func NewPanicError(recovered interface{}, stack []byte) *PanicError { + return &PanicError{recovered: recovered, stack: stack} +} + +func (e PanicError) Error() string { + return fmt.Sprint(e.recovered) +} + +func (e PanicError) Stack() []byte { + return e.stack +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/pkgcache/pkgcache.go b/vendor/github.com/golangci/golangci-lint/internal/pkgcache/pkgcache.go new file mode 100644 index 000000000..86007d042 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/pkgcache/pkgcache.go @@ -0,0 +1,229 @@ +package pkgcache + +import ( + "bytes" + "encoding/gob" + "encoding/hex" + "fmt" + "runtime" + "sort" + "sync" + + "github.com/pkg/errors" + "golang.org/x/tools/go/packages" + + "github.com/golangci/golangci-lint/internal/cache" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/timeutils" +) + +type HashMode int + +const ( + HashModeNeedOnlySelf HashMode = iota + HashModeNeedDirectDeps + HashModeNeedAllDeps +) + +// Cache is a per-package data cache. A cached data is invalidated when +// package or it's dependencies change. +type Cache struct { + lowLevelCache *cache.Cache + pkgHashes sync.Map + sw *timeutils.Stopwatch + log logutils.Log // not used now, but may be needed for future debugging purposes + ioSem chan struct{} // semaphore limiting parallel IO +} + +func NewCache(sw *timeutils.Stopwatch, log logutils.Log) (*Cache, error) { + c, err := cache.Default() + if err != nil { + return nil, err + } + return &Cache{ + lowLevelCache: c, + sw: sw, + log: log, + ioSem: make(chan struct{}, runtime.GOMAXPROCS(-1)), + }, nil +} + +func (c *Cache) Trim() { + c.sw.TrackStage("trim", func() { + c.lowLevelCache.Trim() + }) +} + +func (c *Cache) Put(pkg *packages.Package, mode HashMode, key string, data interface{}) error { + var err error + buf := &bytes.Buffer{} + c.sw.TrackStage("gob", func() { + err = gob.NewEncoder(buf).Encode(data) + }) + if err != nil { + return errors.Wrap(err, "failed to gob encode") + } + + var aID cache.ActionID + + c.sw.TrackStage("key build", func() { + aID, err = c.pkgActionID(pkg, mode) + if err == nil { + subkey, subkeyErr := cache.Subkey(aID, key) + if subkeyErr != nil { + err = errors.Wrap(subkeyErr, "failed to build subkey") + } + aID = subkey + } + }) + if err != nil { + return errors.Wrapf(err, "failed to calculate package %s action id", pkg.Name) + } + c.ioSem <- struct{}{} + c.sw.TrackStage("cache io", func() { + err = c.lowLevelCache.PutBytes(aID, buf.Bytes()) + }) + <-c.ioSem + if err != nil { + return errors.Wrapf(err, "failed to save data to low-level cache by key %s for package %s", key, pkg.Name) + } + + return nil +} + +var ErrMissing = errors.New("missing data") + +func (c *Cache) Get(pkg *packages.Package, mode HashMode, key string, data interface{}) error { + var aID cache.ActionID + var err error + c.sw.TrackStage("key build", func() { + aID, err = c.pkgActionID(pkg, mode) + if err == nil { + subkey, subkeyErr := cache.Subkey(aID, key) + if subkeyErr != nil { + err = errors.Wrap(subkeyErr, "failed to build subkey") + } + aID = subkey + } + }) + if err != nil { + return errors.Wrapf(err, "failed to calculate package %s action id", pkg.Name) + } + + var b []byte + c.ioSem <- struct{}{} + c.sw.TrackStage("cache io", func() { + b, _, err = c.lowLevelCache.GetBytes(aID) + }) + <-c.ioSem + if err != nil { + if cache.IsErrMissing(err) { + return ErrMissing + } + return errors.Wrapf(err, "failed to get data from low-level cache by key %s for package %s", key, pkg.Name) + } + + c.sw.TrackStage("gob", func() { + err = gob.NewDecoder(bytes.NewReader(b)).Decode(data) + }) + if err != nil { + return errors.Wrap(err, "failed to gob decode") + } + + return nil +} + +func (c *Cache) pkgActionID(pkg *packages.Package, mode HashMode) (cache.ActionID, error) { + hash, err := c.packageHash(pkg, mode) + if err != nil { + return cache.ActionID{}, errors.Wrap(err, "failed to get package hash") + } + + key, err := cache.NewHash("action ID") + if err != nil { + return cache.ActionID{}, errors.Wrap(err, "failed to make a hash") + } + fmt.Fprintf(key, "pkgpath %s\n", pkg.PkgPath) + fmt.Fprintf(key, "pkghash %s\n", hash) + + return key.Sum(), nil +} + +// packageHash computes a package's hash. The hash is based on all Go +// files that make up the package, as well as the hashes of imported +// packages. +func (c *Cache) packageHash(pkg *packages.Package, mode HashMode) (string, error) { + type hashResults map[HashMode]string + hashResI, ok := c.pkgHashes.Load(pkg) + if ok { + hashRes := hashResI.(hashResults) + if _, ok := hashRes[mode]; !ok { + return "", fmt.Errorf("no mode %d in hash result", mode) + } + return hashRes[mode], nil + } + + hashRes := hashResults{} + + key, err := cache.NewHash("package hash") + if err != nil { + return "", errors.Wrap(err, "failed to make a hash") + } + + fmt.Fprintf(key, "pkgpath %s\n", pkg.PkgPath) + for _, f := range pkg.CompiledGoFiles { + c.ioSem <- struct{}{} + h, fErr := cache.FileHash(f) + <-c.ioSem + if fErr != nil { + return "", errors.Wrapf(fErr, "failed to calculate file %s hash", f) + } + fmt.Fprintf(key, "file %s %x\n", f, h) + } + curSum := key.Sum() + hashRes[HashModeNeedOnlySelf] = hex.EncodeToString(curSum[:]) + + imps := make([]*packages.Package, 0, len(pkg.Imports)) + for _, imp := range pkg.Imports { + imps = append(imps, imp) + } + sort.Slice(imps, func(i, j int) bool { + return imps[i].PkgPath < imps[j].PkgPath + }) + + calcDepsHash := func(depMode HashMode) error { + for _, dep := range imps { + if dep.PkgPath == "unsafe" { + continue + } + + depHash, depErr := c.packageHash(dep, depMode) + if depErr != nil { + return errors.Wrapf(depErr, "failed to calculate hash for dependency %s with mode %d", dep.Name, depMode) + } + + fmt.Fprintf(key, "import %s %s\n", dep.PkgPath, depHash) + } + return nil + } + + if err := calcDepsHash(HashModeNeedOnlySelf); err != nil { + return "", err + } + + curSum = key.Sum() + hashRes[HashModeNeedDirectDeps] = hex.EncodeToString(curSum[:]) + + if err := calcDepsHash(HashModeNeedAllDeps); err != nil { + return "", err + } + curSum = key.Sum() + hashRes[HashModeNeedAllDeps] = hex.EncodeToString(curSum[:]) + + if _, ok := hashRes[mode]; !ok { + return "", fmt.Errorf("invalid mode %d", mode) + } + + c.pkgHashes.Store(pkg, hashRes) + return hashRes[mode], nil +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/renameio/renameio.go b/vendor/github.com/golangci/golangci-lint/internal/renameio/renameio.go new file mode 100644 index 000000000..fa9d93bf7 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/renameio/renameio.go @@ -0,0 +1,93 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package renameio writes files atomically by renaming temporary files. +package renameio + +import ( + "bytes" + "io" + "math/rand" + "os" + "path/filepath" + "strconv" + + "github.com/golangci/golangci-lint/internal/robustio" +) + +const patternSuffix = ".tmp" + +// Pattern returns a glob pattern that matches the unrenamed temporary files +// created when writing to filename. +func Pattern(filename string) string { + return filepath.Join(filepath.Dir(filename), filepath.Base(filename)+patternSuffix) +} + +// WriteFile is like ioutil.WriteFile, but first writes data to an arbitrary +// file in the same directory as filename, then renames it atomically to the +// final name. +// +// That ensures that the final location, if it exists, is always a complete file. +func WriteFile(filename string, data []byte, perm os.FileMode) (err error) { + return WriteToFile(filename, bytes.NewReader(data), perm) +} + +// WriteToFile is a variant of WriteFile that accepts the data as an io.Reader +// instead of a slice. +func WriteToFile(filename string, data io.Reader, perm os.FileMode) (err error) { + f, err := tempFile(filepath.Dir(filename), filepath.Base(filename), perm) + if err != nil { + return err + } + defer func() { + // Only call os.Remove on f.Name() if we failed to rename it: otherwise, + // some other process may have created a new file with the same name after + // that. + if err != nil { + f.Close() + os.Remove(f.Name()) + } + }() + + if _, err := io.Copy(f, data); err != nil { + return err + } + // Sync the file before renaming it: otherwise, after a crash the reader may + // observe a 0-length file instead of the actual contents. + // See https://golang.org/issue/22397#issuecomment-380831736. + if err := f.Sync(); err != nil { + return err + } + if err := f.Close(); err != nil { + return err + } + + return robustio.Rename(f.Name(), filename) +} + +// tempFile creates a new temporary file with given permission bits. +func tempFile(dir, prefix string, perm os.FileMode) (f *os.File, err error) { + for i := 0; i < 10000; i++ { + name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+patternSuffix) + f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm) + if os.IsExist(err) { + continue + } + break + } + return +} + +// ReadFile is like ioutil.ReadFile, but on Windows retries spurious errors that +// may occur if the file is concurrently replaced. +// +// Errors are classified heuristically and retries are bounded, so even this +// function may occasionally return a spurious error on Windows. +// If so, the error will likely wrap one of: +// - syscall.ERROR_ACCESS_DENIED +// - syscall.ERROR_FILE_NOT_FOUND +// - internal/syscall/windows.ERROR_SHARING_VIOLATION +func ReadFile(filename string) ([]byte, error) { + return robustio.ReadFile(filename) +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio.go b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio.go new file mode 100644 index 000000000..76e47ad1f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio.go @@ -0,0 +1,53 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package robustio wraps I/O functions that are prone to failure on Windows, +// transparently retrying errors up to an arbitrary timeout. +// +// Errors are classified heuristically and retries are bounded, so the functions +// in this package do not completely eliminate spurious errors. However, they do +// significantly reduce the rate of failure in practice. +// +// If so, the error will likely wrap one of: +// The functions in this package do not completely eliminate spurious errors, +// but substantially reduce their rate of occurrence in practice. +package robustio + +// Rename is like os.Rename, but on Windows retries errors that may occur if the +// file is concurrently read or overwritten. +// +// (See golang.org/issue/31247 and golang.org/issue/32188.) +func Rename(oldpath, newpath string) error { + return rename(oldpath, newpath) +} + +// ReadFile is like ioutil.ReadFile, but on Windows retries errors that may +// occur if the file is concurrently replaced. +// +// (See golang.org/issue/31247 and golang.org/issue/32188.) +func ReadFile(filename string) ([]byte, error) { + return readFile(filename) +} + +// RemoveAll is like os.RemoveAll, but on Windows retries errors that may occur +// if an executable file in the directory has recently been executed. +// +// (See golang.org/issue/19491.) +func RemoveAll(path string) error { + return removeAll(path) +} + +// IsEphemeralError reports whether err is one of the errors that the functions +// in this package attempt to mitigate. +// +// Errors considered ephemeral include: +// - syscall.ERROR_ACCESS_DENIED +// - syscall.ERROR_FILE_NOT_FOUND +// - internal/syscall/windows.ERROR_SHARING_VIOLATION +// +// This set may be expanded in the future; programs must not rely on the +// non-ephemerality of any given error. +func IsEphemeralError(err error) bool { + return isEphemeralError(err) +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_darwin.go b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_darwin.go new file mode 100644 index 000000000..1ac0d10d7 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_darwin.go @@ -0,0 +1,29 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package robustio + +import ( + "os" + "syscall" +) + +const errFileNotFound = syscall.ENOENT + +// isEphemeralError returns true if err may be resolved by waiting. +func isEphemeralError(err error) bool { + switch werr := err.(type) { + case *os.PathError: + err = werr.Err + case *os.LinkError: + err = werr.Err + case *os.SyscallError: + err = werr.Err + + } + if errno, ok := err.(syscall.Errno); ok { + return errno == errFileNotFound + } + return false +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_flaky.go b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_flaky.go new file mode 100644 index 000000000..e0bf5b9b3 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_flaky.go @@ -0,0 +1,93 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows darwin + +package robustio + +import ( + "io/ioutil" + "math/rand" + "os" + "syscall" + "time" +) + +const arbitraryTimeout = 500 * time.Millisecond + +const ERROR_SHARING_VIOLATION = 32 + +// retry retries ephemeral errors from f up to an arbitrary timeout +// to work around filesystem flakiness on Windows and Darwin. +func retry(f func() (err error, mayRetry bool)) error { + var ( + bestErr error + lowestErrno syscall.Errno + start time.Time + nextSleep time.Duration = 1 * time.Millisecond + ) + for { + err, mayRetry := f() + if err == nil || !mayRetry { + return err + } + + if errno, ok := err.(syscall.Errno); ok && (lowestErrno == 0 || errno < lowestErrno) { + bestErr = err + lowestErrno = errno + } else if bestErr == nil { + bestErr = err + } + + if start.IsZero() { + start = time.Now() + } else if d := time.Since(start) + nextSleep; d >= arbitraryTimeout { + break + } + time.Sleep(nextSleep) + nextSleep += time.Duration(rand.Int63n(int64(nextSleep))) + } + + return bestErr +} + +// rename is like os.Rename, but retries ephemeral errors. +// +// On windows it wraps os.Rename, which (as of 2019-06-04) uses MoveFileEx with +// MOVEFILE_REPLACE_EXISTING. +// +// Windows also provides a different system call, ReplaceFile, +// that provides similar semantics, but perhaps preserves more metadata. (The +// documentation on the differences between the two is very sparse.) +// +// Empirical error rates with MoveFileEx are lower under modest concurrency, so +// for now we're sticking with what the os package already provides. +func rename(oldpath, newpath string) (err error) { + return retry(func() (err error, mayRetry bool) { + err = os.Rename(oldpath, newpath) + return err, isEphemeralError(err) + }) +} + +// readFile is like ioutil.ReadFile, but retries ephemeral errors. +func readFile(filename string) ([]byte, error) { + var b []byte + err := retry(func() (err error, mayRetry bool) { + b, err = ioutil.ReadFile(filename) + + // Unlike in rename, we do not retry errFileNotFound here: it can occur + // as a spurious error, but the file may also genuinely not exist, so the + // increase in robustness is probably not worth the extra latency. + + return err, isEphemeralError(err) && err != errFileNotFound + }) + return b, err +} + +func removeAll(path string) error { + return retry(func() (err error, mayRetry bool) { + err = os.RemoveAll(path) + return err, isEphemeralError(err) + }) +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_other.go b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_other.go new file mode 100644 index 000000000..a2428856f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_other.go @@ -0,0 +1,28 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !windows,!darwin + +package robustio + +import ( + "io/ioutil" + "os" +) + +func rename(oldpath, newpath string) error { + return os.Rename(oldpath, newpath) +} + +func readFile(filename string) ([]byte, error) { + return ioutil.ReadFile(filename) +} + +func removeAll(path string) error { + return os.RemoveAll(path) +} + +func isEphemeralError(err error) bool { + return false +} diff --git a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_windows.go b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_windows.go new file mode 100644 index 000000000..a35237d44 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_windows.go @@ -0,0 +1,33 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package robustio + +import ( + "os" + "syscall" +) + +const errFileNotFound = syscall.ERROR_FILE_NOT_FOUND + +// isEphemeralError returns true if err may be resolved by waiting. +func isEphemeralError(err error) bool { + switch werr := err.(type) { + case *os.PathError: + err = werr.Err + case *os.LinkError: + err = werr.Err + case *os.SyscallError: + err = werr.Err + } + if errno, ok := err.(syscall.Errno); ok { + switch errno { + case syscall.ERROR_ACCESS_DENIED, + syscall.ERROR_FILE_NOT_FOUND, + ERROR_SHARING_VIOLATION: + return true + } + } + return false +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/cache.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/cache.go new file mode 100644 index 000000000..359e2d63c --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/cache.go @@ -0,0 +1,84 @@ +package commands + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" + + "github.com/golangci/golangci-lint/internal/cache" + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +func (e *Executor) initCache() { + cacheCmd := &cobra.Command{ + Use: "cache", + Short: "Cache control and information", + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 0 { + e.log.Fatalf("Usage: golangci-lint cache") + } + if err := cmd.Help(); err != nil { + e.log.Fatalf("Can't run cache: %s", err) + } + }, + } + e.rootCmd.AddCommand(cacheCmd) + + cacheCmd.AddCommand(&cobra.Command{ + Use: "clean", + Short: "Clean cache", + Run: e.executeCleanCache, + }) + cacheCmd.AddCommand(&cobra.Command{ + Use: "status", + Short: "Show cache status", + Run: e.executeCacheStatus, + }) + + // TODO: add trim command? +} + +func (e *Executor) executeCleanCache(_ *cobra.Command, args []string) { + if len(args) != 0 { + e.log.Fatalf("Usage: golangci-lint cache clean") + } + + cacheDir := cache.DefaultDir() + if err := os.RemoveAll(cacheDir); err != nil { + e.log.Fatalf("Failed to remove dir %s: %s", cacheDir, err) + } + + os.Exit(0) +} + +func (e *Executor) executeCacheStatus(_ *cobra.Command, args []string) { + if len(args) != 0 { + e.log.Fatalf("Usage: golangci-lint cache status") + } + + cacheDir := cache.DefaultDir() + fmt.Fprintf(logutils.StdOut, "Dir: %s\n", cacheDir) + cacheSizeBytes, err := dirSizeBytes(cacheDir) + if err == nil { + fmt.Fprintf(logutils.StdOut, "Size: %s\n", fsutils.PrettifyBytesCount(cacheSizeBytes)) + } + + os.Exit(0) +} + +func dirSizeBytes(path string) (int64, error) { + var size int64 + err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() { + size += info.Size() + } + return err + }) + return size, err +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/completion.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/completion.go new file mode 100644 index 000000000..7d919d197 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/completion.go @@ -0,0 +1,53 @@ +package commands + +import ( + "fmt" + "os" + + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +func (e *Executor) initCompletion() { + completionCmd := &cobra.Command{ + Use: "completion", + Short: "Output completion script", + } + e.rootCmd.AddCommand(completionCmd) + + bashCmd := &cobra.Command{ + Use: "bash", + Short: "Output bash completion script", + RunE: e.executeBashCompletion, + } + completionCmd.AddCommand(bashCmd) + + zshCmd := &cobra.Command{ + Use: "zsh", + Short: "Output zsh completion script", + RunE: e.executeZshCompletion, + } + completionCmd.AddCommand(zshCmd) +} + +func (e *Executor) executeBashCompletion(cmd *cobra.Command, args []string) error { + err := cmd.Root().GenBashCompletion(os.Stdout) + if err != nil { + return errors.Wrap(err, "unable to generate bash completions: %v") + } + + return nil +} + +func (e *Executor) executeZshCompletion(cmd *cobra.Command, args []string) error { + err := cmd.Root().GenZshCompletion(os.Stdout) + if err != nil { + return errors.Wrap(err, "unable to generate zsh completions: %v") + } + // Add extra compdef directive to support sourcing command directly. + // https://github.com/spf13/cobra/issues/881 + // https://github.com/spf13/cobra/pull/887 + fmt.Println("compdef _golangci-lint golangci-lint") + + return nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/config.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/config.go new file mode 100644 index 000000000..4b63e2e52 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/config.go @@ -0,0 +1,66 @@ +package commands + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/golangci/golangci-lint/pkg/exitcodes" + "github.com/golangci/golangci-lint/pkg/fsutils" +) + +func (e *Executor) initConfig() { + cmd := &cobra.Command{ + Use: "config", + Short: "Config", + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 0 { + e.log.Fatalf("Usage: golangci-lint config") + } + if err := cmd.Help(); err != nil { + e.log.Fatalf("Can't run help: %s", err) + } + }, + } + e.rootCmd.AddCommand(cmd) + + pathCmd := &cobra.Command{ + Use: "path", + Short: "Print used config path", + Run: e.executePathCmd, + } + e.initRunConfiguration(pathCmd) // allow --config + cmd.AddCommand(pathCmd) +} + +func (e *Executor) getUsedConfig() string { + usedConfigFile := viper.ConfigFileUsed() + if usedConfigFile == "" { + return "" + } + + prettyUsedConfigFile, err := fsutils.ShortestRelPath(usedConfigFile, "") + if err != nil { + e.log.Warnf("Can't pretty print config file path: %s", err) + return usedConfigFile + } + + return prettyUsedConfigFile +} + +func (e *Executor) executePathCmd(_ *cobra.Command, args []string) { + if len(args) != 0 { + e.log.Fatalf("Usage: golangci-lint config path") + } + + usedConfigFile := e.getUsedConfig() + if usedConfigFile == "" { + e.log.Warnf("No config file detected") + os.Exit(exitcodes.NoConfigFileDetected) + } + + fmt.Println(usedConfigFile) + os.Exit(0) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/executor.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/executor.go new file mode 100644 index 000000000..9581acab2 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/executor.go @@ -0,0 +1,245 @@ +package commands + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/json" + "io" + "os" + "path/filepath" + "strings" + "time" + + "github.com/fatih/color" + "github.com/gofrs/flock" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "github.com/golangci/golangci-lint/internal/cache" + "github.com/golangci/golangci-lint/internal/pkgcache" + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load" + "github.com/golangci/golangci-lint/pkg/goutil" + "github.com/golangci/golangci-lint/pkg/lint" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/report" + "github.com/golangci/golangci-lint/pkg/timeutils" +) + +type Executor struct { + rootCmd *cobra.Command + runCmd *cobra.Command + lintersCmd *cobra.Command + + exitCode int + version, commit, date string + + cfg *config.Config + log logutils.Log + reportData report.Data + DBManager *lintersdb.Manager + EnabledLintersSet *lintersdb.EnabledSet + contextLoader *lint.ContextLoader + goenv *goutil.Env + fileCache *fsutils.FileCache + lineCache *fsutils.LineCache + pkgCache *pkgcache.Cache + debugf logutils.DebugFunc + sw *timeutils.Stopwatch + + loadGuard *load.Guard + flock *flock.Flock +} + +func NewExecutor(version, commit, date string) *Executor { + startedAt := time.Now() + e := &Executor{ + cfg: config.NewDefault(), + version: version, + commit: commit, + date: date, + DBManager: lintersdb.NewManager(nil, nil), + debugf: logutils.Debug("exec"), + } + + e.debugf("Starting execution...") + e.log = report.NewLogWrapper(logutils.NewStderrLog(""), &e.reportData) + + // to setup log level early we need to parse config from command line extra time to + // find `-v` option + commandLineCfg, err := e.getConfigForCommandLine() + if err != nil && err != pflag.ErrHelp { + e.log.Fatalf("Can't get config for command line: %s", err) + } + if commandLineCfg != nil { + logutils.SetupVerboseLog(e.log, commandLineCfg.Run.IsVerbose) + + switch commandLineCfg.Output.Color { + case "always": + color.NoColor = false + case "never": + color.NoColor = true + case "auto": + // nothing + default: + e.log.Fatalf("invalid value %q for --color; must be 'always', 'auto', or 'never'", commandLineCfg.Output.Color) + } + } + + // init of commands must be done before config file reading because + // init sets config with the default values of flags + e.initRoot() + e.initRun() + e.initHelp() + e.initLinters() + e.initConfig() + e.initCompletion() + e.initVersion() + e.initCache() + + // init e.cfg by values from config: flags parse will see these values + // like the default ones. It will overwrite them only if the same option + // is found in command-line: it's ok, command-line has higher priority. + + r := config.NewFileReader(e.cfg, commandLineCfg, e.log.Child("config_reader")) + if err = r.Read(); err != nil { + e.log.Fatalf("Can't read config: %s", err) + } + + // recreate after getting config + e.DBManager = lintersdb.NewManager(e.cfg, e.log).WithCustomLinters() + + e.cfg.LintersSettings.Gocritic.InferEnabledChecks(e.log) + if err = e.cfg.LintersSettings.Gocritic.Validate(e.log); err != nil { + e.log.Fatalf("Invalid gocritic settings: %s", err) + } + + // Slice options must be explicitly set for proper merging of config and command-line options. + fixSlicesFlags(e.runCmd.Flags()) + fixSlicesFlags(e.lintersCmd.Flags()) + + e.EnabledLintersSet = lintersdb.NewEnabledSet(e.DBManager, + lintersdb.NewValidator(e.DBManager), e.log.Child("lintersdb"), e.cfg) + e.goenv = goutil.NewEnv(e.log.Child("goenv")) + e.fileCache = fsutils.NewFileCache() + e.lineCache = fsutils.NewLineCache(e.fileCache) + + e.sw = timeutils.NewStopwatch("pkgcache", e.log.Child("stopwatch")) + e.pkgCache, err = pkgcache.NewCache(e.sw, e.log.Child("pkgcache")) + if err != nil { + e.log.Fatalf("Failed to build packages cache: %s", err) + } + e.loadGuard = load.NewGuard() + e.contextLoader = lint.NewContextLoader(e.cfg, e.log.Child("loader"), e.goenv, + e.lineCache, e.fileCache, e.pkgCache, e.loadGuard) + if err = e.initHashSalt(version); err != nil { + e.log.Fatalf("Failed to init hash salt: %s", err) + } + e.debugf("Initialized executor in %s", time.Since(startedAt)) + return e +} + +func (e *Executor) Execute() error { + return e.rootCmd.Execute() +} + +func (e *Executor) initHashSalt(version string) error { + binSalt, err := computeBinarySalt(version) + if err != nil { + return errors.Wrap(err, "failed to calculate binary salt") + } + + configSalt, err := computeConfigSalt(e.cfg) + if err != nil { + return errors.Wrap(err, "failed to calculate config salt") + } + + var b bytes.Buffer + b.Write(binSalt) + b.Write(configSalt) + cache.SetSalt(b.Bytes()) + return nil +} + +func computeBinarySalt(version string) ([]byte, error) { + if version != "" && version != "(devel)" { + return []byte(version), nil + } + + if logutils.HaveDebugTag("bin_salt") { + return []byte("debug"), nil + } + + p, err := os.Executable() + if err != nil { + return nil, err + } + f, err := os.Open(p) + if err != nil { + return nil, err + } + defer f.Close() + h := sha256.New() + if _, err := io.Copy(h, f); err != nil { + return nil, err + } + return h.Sum(nil), nil +} + +func computeConfigSalt(cfg *config.Config) ([]byte, error) { + // We don't hash all config fields to reduce meaningless cache + // invalidations. At least, it has a huge impact on tests speed. + + lintersSettingsBytes, err := json.Marshal(cfg.LintersSettings) + if err != nil { + return nil, errors.Wrap(err, "failed to json marshal config linter settings") + } + + var configData bytes.Buffer + configData.WriteString("linters-settings=") + configData.Write(lintersSettingsBytes) + configData.WriteString("\nbuild-tags=%s" + strings.Join(cfg.Run.BuildTags, ",")) + + h := sha256.New() + h.Write(configData.Bytes()) //nolint:errcheck + return h.Sum(nil), nil +} + +func (e *Executor) acquireFileLock() bool { + if e.cfg.Run.AllowParallelRunners { + e.debugf("Parallel runners are allowed, no locking") + return true + } + + lockFile := filepath.Join(os.TempDir(), "golangci-lint.lock") + e.debugf("Locking on file %s...", lockFile) + f := flock.New(lockFile) + const totalTimeout = 5 * time.Second + const retryDelay = time.Second + ctx, finish := context.WithTimeout(context.Background(), totalTimeout) + defer finish() + + if ok, _ := f.TryLockContext(ctx, retryDelay); !ok { + return false + } + + e.flock = f + return true +} + +func (e *Executor) releaseFileLock() { + if e.cfg.Run.AllowParallelRunners { + return + } + + if err := e.flock.Unlock(); err != nil { + e.debugf("Failed to unlock on file: %s", err) + } + if err := os.Remove(e.flock.Path()); err != nil { + e.debugf("Failed to remove lock file: %s", err) + } +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/help.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/help.go new file mode 100644 index 000000000..16fef33eb --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/help.go @@ -0,0 +1,84 @@ +package commands + +import ( + "fmt" + "os" + "sort" + "strings" + + "github.com/fatih/color" + "github.com/spf13/cobra" + + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +func (e *Executor) initHelp() { + helpCmd := &cobra.Command{ + Use: "help", + Short: "Help", + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 0 { + e.log.Fatalf("Usage: golangci-lint help") + } + if err := cmd.Help(); err != nil { + e.log.Fatalf("Can't run help: %s", err) + } + }, + } + e.rootCmd.SetHelpCommand(helpCmd) + + lintersHelpCmd := &cobra.Command{ + Use: "linters", + Short: "Help about linters", + Run: e.executeLintersHelp, + } + helpCmd.AddCommand(lintersHelpCmd) +} + +func printLinterConfigs(lcs []*linter.Config) { + sort.Slice(lcs, func(i, j int) bool { + return strings.Compare(lcs[i].Name(), lcs[j].Name()) < 0 + }) + for _, lc := range lcs { + altNamesStr := "" + if len(lc.AlternativeNames) != 0 { + altNamesStr = fmt.Sprintf(" (%s)", strings.Join(lc.AlternativeNames, ", ")) + } + fmt.Fprintf(logutils.StdOut, "%s%s: %s [fast: %t, auto-fix: %t]\n", color.YellowString(lc.Name()), + altNamesStr, lc.Linter.Desc(), !lc.IsSlowLinter(), lc.CanAutoFix) + } +} + +func (e *Executor) executeLintersHelp(_ *cobra.Command, args []string) { + if len(args) != 0 { + e.log.Fatalf("Usage: golangci-lint help linters") + } + + var enabledLCs, disabledLCs []*linter.Config + for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { + if lc.EnabledByDefault { + enabledLCs = append(enabledLCs, lc) + } else { + disabledLCs = append(disabledLCs, lc) + } + } + + color.Green("Enabled by default linters:\n") + printLinterConfigs(enabledLCs) + color.Red("\nDisabled by default linters:\n") + printLinterConfigs(disabledLCs) + + color.Green("\nLinters presets:") + for _, p := range e.DBManager.AllPresets() { + linters := e.DBManager.GetAllLinterConfigsForPreset(p) + linterNames := []string{} + for _, lc := range linters { + linterNames = append(linterNames, lc.Name()) + } + sort.Strings(linterNames) + fmt.Fprintf(logutils.StdOut, "%s: %s\n", color.YellowString(p), strings.Join(linterNames, ", ")) + } + + os.Exit(0) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/linters.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/linters.go new file mode 100644 index 000000000..873dab817 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/linters.go @@ -0,0 +1,51 @@ +package commands + +import ( + "log" + "os" + + "github.com/fatih/color" + "github.com/spf13/cobra" + + "github.com/golangci/golangci-lint/pkg/lint/linter" +) + +func (e *Executor) initLinters() { + e.lintersCmd = &cobra.Command{ + Use: "linters", + Short: "List current linters configuration", + Run: e.executeLinters, + } + e.rootCmd.AddCommand(e.lintersCmd) + e.initRunConfiguration(e.lintersCmd) +} + +func (e *Executor) executeLinters(_ *cobra.Command, args []string) { + if len(args) != 0 { + e.log.Fatalf("Usage: golangci-lint linters") + } + + enabledLintersMap, err := e.EnabledLintersSet.GetEnabledLintersMap() + if err != nil { + log.Fatalf("Can't get enabled linters: %s", err) + } + + color.Green("Enabled by your configuration linters:\n") + enabledLinters := make([]*linter.Config, 0, len(enabledLintersMap)) + for _, linter := range enabledLintersMap { + enabledLinters = append(enabledLinters, linter) + } + printLinterConfigs(enabledLinters) + + var disabledLCs []*linter.Config + for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { + if enabledLintersMap[lc.Name()] == nil { + disabledLCs = append(disabledLCs, lc) + } + } + + color.Red("\nDisabled by your configuration linters:\n") + printLinterConfigs(disabledLCs) + + os.Exit(0) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/root.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/root.go new file mode 100644 index 000000000..f90df9901 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/root.go @@ -0,0 +1,165 @@ +package commands + +import ( + "fmt" + "os" + "runtime" + "runtime/pprof" + "runtime/trace" + "strconv" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +func (e *Executor) persistentPreRun(_ *cobra.Command, _ []string) { + if e.cfg.Run.PrintVersion { + fmt.Fprintf(logutils.StdOut, "golangci-lint has version %s built from %s on %s\n", e.version, e.commit, e.date) + os.Exit(0) + } + + runtime.GOMAXPROCS(e.cfg.Run.Concurrency) + + if e.cfg.Run.CPUProfilePath != "" { + f, err := os.Create(e.cfg.Run.CPUProfilePath) + if err != nil { + e.log.Fatalf("Can't create file %s: %s", e.cfg.Run.CPUProfilePath, err) + } + if err := pprof.StartCPUProfile(f); err != nil { + e.log.Fatalf("Can't start CPU profiling: %s", err) + } + } + + if e.cfg.Run.MemProfilePath != "" { + if rate := os.Getenv("GL_MEMPROFILE_RATE"); rate != "" { + runtime.MemProfileRate, _ = strconv.Atoi(rate) + } + } + + if e.cfg.Run.TracePath != "" { + f, err := os.Create(e.cfg.Run.TracePath) + if err != nil { + e.log.Fatalf("Can't create file %s: %s", e.cfg.Run.TracePath, err) + } + if err = trace.Start(f); err != nil { + e.log.Fatalf("Can't start tracing: %s", err) + } + } +} + +func (e *Executor) persistentPostRun(_ *cobra.Command, _ []string) { + if e.cfg.Run.CPUProfilePath != "" { + pprof.StopCPUProfile() + } + if e.cfg.Run.MemProfilePath != "" { + f, err := os.Create(e.cfg.Run.MemProfilePath) + if err != nil { + e.log.Fatalf("Can't create file %s: %s", e.cfg.Run.MemProfilePath, err) + } + + var ms runtime.MemStats + runtime.ReadMemStats(&ms) + printMemStats(&ms, e.log) + + if err := pprof.WriteHeapProfile(f); err != nil { + e.log.Fatalf("Can't write heap profile: %s", err) + } + f.Close() + } + if e.cfg.Run.TracePath != "" { + trace.Stop() + } + + os.Exit(e.exitCode) +} + +func printMemStats(ms *runtime.MemStats, logger logutils.Log) { + logger.Infof("Mem stats: alloc=%s total_alloc=%s sys=%s "+ + "heap_alloc=%s heap_sys=%s heap_idle=%s heap_released=%s heap_in_use=%s "+ + "stack_in_use=%s stack_sys=%s "+ + "mspan_sys=%s mcache_sys=%s buck_hash_sys=%s gc_sys=%s other_sys=%s "+ + "mallocs_n=%d frees_n=%d heap_objects_n=%d gc_cpu_fraction=%.2f", + formatMemory(ms.Alloc), formatMemory(ms.TotalAlloc), formatMemory(ms.Sys), + formatMemory(ms.HeapAlloc), formatMemory(ms.HeapSys), + formatMemory(ms.HeapIdle), formatMemory(ms.HeapReleased), formatMemory(ms.HeapInuse), + formatMemory(ms.StackInuse), formatMemory(ms.StackSys), + formatMemory(ms.MSpanSys), formatMemory(ms.MCacheSys), formatMemory(ms.BuckHashSys), + formatMemory(ms.GCSys), formatMemory(ms.OtherSys), + ms.Mallocs, ms.Frees, ms.HeapObjects, ms.GCCPUFraction) +} + +func formatMemory(memBytes uint64) string { + const Kb = 1024 + const Mb = Kb * 1024 + + if memBytes < Kb { + return fmt.Sprintf("%db", memBytes) + } + if memBytes < Mb { + return fmt.Sprintf("%dkb", memBytes/Kb) + } + return fmt.Sprintf("%dmb", memBytes/Mb) +} + +func getDefaultConcurrency() int { + if os.Getenv("HELP_RUN") == "1" { + // Make stable concurrency for README help generating builds. + const prettyConcurrency = 8 + return prettyConcurrency + } + + return runtime.NumCPU() +} + +func (e *Executor) initRoot() { + rootCmd := &cobra.Command{ + Use: "golangci-lint", + Short: "golangci-lint is a smart linters runner.", + Long: `Smart, fast linters runner. Run it in cloud for every GitHub pull request on https://golangci.com`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 0 { + e.log.Fatalf("Usage: golangci-lint") + } + if err := cmd.Help(); err != nil { + e.log.Fatalf("Can't run help: %s", err) + } + }, + PersistentPreRun: e.persistentPreRun, + PersistentPostRun: e.persistentPostRun, + } + + initRootFlagSet(rootCmd.PersistentFlags(), e.cfg, e.needVersionOption()) + e.rootCmd = rootCmd +} + +func (e *Executor) needVersionOption() bool { + return e.date != "" +} + +func initRootFlagSet(fs *pflag.FlagSet, cfg *config.Config, needVersionOption bool) { + fs.BoolVarP(&cfg.Run.IsVerbose, "verbose", "v", false, wh("verbose output")) + + var silent bool + fs.BoolVarP(&silent, "silent", "s", false, wh("disables congrats outputs")) + if err := fs.MarkHidden("silent"); err != nil { + panic(err) + } + err := fs.MarkDeprecated("silent", + "now golangci-lint by default is silent: it doesn't print Congrats message") + if err != nil { + panic(err) + } + + fs.StringVar(&cfg.Run.CPUProfilePath, "cpu-profile-path", "", wh("Path to CPU profile output file")) + fs.StringVar(&cfg.Run.MemProfilePath, "mem-profile-path", "", wh("Path to memory profile output file")) + fs.StringVar(&cfg.Run.TracePath, "trace-path", "", wh("Path to trace output file")) + fs.IntVarP(&cfg.Run.Concurrency, "concurrency", "j", getDefaultConcurrency(), wh("Concurrency (default NumCPU)")) + if needVersionOption { + fs.BoolVar(&cfg.Run.PrintVersion, "version", false, wh("Print version")) + } + + fs.StringVar(&cfg.Output.Color, "color", "auto", wh("Use color when printing; can be 'always', 'auto', or 'never'")) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/run.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/run.go new file mode 100644 index 000000000..e4887d587 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/run.go @@ -0,0 +1,534 @@ +package commands + +import ( + "context" + "fmt" + "io/ioutil" + "log" + "os" + "runtime" + "strings" + "time" + + "github.com/fatih/color" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/exitcodes" + "github.com/golangci/golangci-lint/pkg/lint" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/packages" + "github.com/golangci/golangci-lint/pkg/printers" + "github.com/golangci/golangci-lint/pkg/result" + "github.com/golangci/golangci-lint/pkg/result/processors" +) + +func getDefaultIssueExcludeHelp() string { + parts := []string{"Use or not use default excludes:"} + for _, ep := range config.DefaultExcludePatterns { + parts = append(parts, + fmt.Sprintf(" # %s %s: %s", ep.ID, ep.Linter, ep.Why), + fmt.Sprintf(" - %s", color.YellowString(ep.Pattern)), + "", + ) + } + return strings.Join(parts, "\n") +} + +func getDefaultDirectoryExcludeHelp() string { + parts := []string{"Use or not use default excluded directories:"} + for _, dir := range packages.StdExcludeDirRegexps { + parts = append(parts, fmt.Sprintf(" - %s", color.YellowString(dir))) + } + parts = append(parts, "") + return strings.Join(parts, "\n") +} + +const welcomeMessage = "Run this tool in cloud on every github pull " + + "request in https://golangci.com for free (public repos)" + +func wh(text string) string { + return color.GreenString(text) +} + +const defaultTimeout = time.Minute + +//nolint:funlen +func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager, isFinalInit bool) { + hideFlag := func(name string) { + if err := fs.MarkHidden(name); err != nil { + panic(err) + } + + // we run initFlagSet multiple times, but we wouldn't like to see deprecation message multiple times + if isFinalInit { + const deprecateMessage = "flag will be removed soon, please, use .golangci.yml config" + if err := fs.MarkDeprecated(name, deprecateMessage); err != nil { + panic(err) + } + } + } + + // Output config + oc := &cfg.Output + fs.StringVar(&oc.Format, "out-format", + config.OutFormatColoredLineNumber, + wh(fmt.Sprintf("Format of output: %s", strings.Join(config.OutFormats, "|")))) + fs.BoolVar(&oc.PrintIssuedLine, "print-issued-lines", true, wh("Print lines of code with issue")) + fs.BoolVar(&oc.PrintLinterName, "print-linter-name", true, wh("Print linter name in issue line")) + fs.BoolVar(&oc.UniqByLine, "uniq-by-line", true, wh("Make issues output unique by line")) + fs.BoolVar(&oc.PrintWelcomeMessage, "print-welcome", false, wh("Print welcome message")) + hideFlag("print-welcome") // no longer used + + // Run config + rc := &cfg.Run + fs.StringVar(&rc.ModulesDownloadMode, "modules-download-mode", "", + "Modules download mode. If not empty, passed as -mod= to go tools") + fs.IntVar(&rc.ExitCodeIfIssuesFound, "issues-exit-code", + exitcodes.IssuesFound, wh("Exit code when issues were found")) + fs.StringSliceVar(&rc.BuildTags, "build-tags", nil, wh("Build tags")) + + fs.DurationVar(&rc.Timeout, "deadline", defaultTimeout, wh("Deadline for total work")) + if err := fs.MarkHidden("deadline"); err != nil { + panic(err) + } + fs.DurationVar(&rc.Timeout, "timeout", defaultTimeout, wh("Timeout for total work")) + + fs.BoolVar(&rc.AnalyzeTests, "tests", true, wh("Analyze tests (*_test.go)")) + fs.BoolVar(&rc.PrintResourcesUsage, "print-resources-usage", false, + wh("Print avg and max memory usage of golangci-lint and total time")) + fs.StringVarP(&rc.Config, "config", "c", "", wh("Read config from file path `PATH`")) + fs.BoolVar(&rc.NoConfig, "no-config", false, wh("Don't read config")) + fs.StringSliceVar(&rc.SkipDirs, "skip-dirs", nil, wh("Regexps of directories to skip")) + fs.BoolVar(&rc.UseDefaultSkipDirs, "skip-dirs-use-default", true, getDefaultDirectoryExcludeHelp()) + fs.StringSliceVar(&rc.SkipFiles, "skip-files", nil, wh("Regexps of files to skip")) + + const allowParallelDesc = "Allow multiple parallel golangci-lint instances running. " + + "If false (default) - golangci-lint acquires file lock on start." + fs.BoolVar(&rc.AllowParallelRunners, "allow-parallel-runners", false, wh(allowParallelDesc)) + + // Linters settings config + lsc := &cfg.LintersSettings + + // Hide all linters settings flags: they were initially visible, + // but when number of linters started to grow it became obvious that + // we can't fill 90% of flags by linters settings: common flags became hard to find. + // New linters settings should be done only through config file. + fs.BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", + false, "Errcheck: check for ignored type assertion results") + hideFlag("errcheck.check-type-assertions") + fs.BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, + "Errcheck: check for errors assigned to blank identifier: _ = errFunc()") + hideFlag("errcheck.check-blank") + fs.StringVar(&lsc.Errcheck.Exclude, "errcheck.exclude", "", + "Path to a file containing a list of functions to exclude from checking") + hideFlag("errcheck.exclude") + fs.StringVar(&lsc.Errcheck.Ignore, "errcheck.ignore", "fmt:.*", + `Comma-separated list of pairs of the form pkg:regex. The regex is used to ignore names within pkg`) + hideFlag("errcheck.ignore") + + fs.BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false, + "Govet: check for shadowed variables") + hideFlag("govet.check-shadowing") + + fs.Float64Var(&lsc.Golint.MinConfidence, "golint.min-confidence", 0.8, + "Golint: minimum confidence of a problem to print it") + hideFlag("golint.min-confidence") + + fs.BoolVar(&lsc.Gofmt.Simplify, "gofmt.simplify", true, "Gofmt: simplify code") + hideFlag("gofmt.simplify") + + fs.IntVar(&lsc.Gocyclo.MinComplexity, "gocyclo.min-complexity", + 30, "Minimal complexity of function to report it") + hideFlag("gocyclo.min-complexity") + + fs.BoolVar(&lsc.Maligned.SuggestNewOrder, "maligned.suggest-new", false, + "Maligned: print suggested more optimal struct fields ordering") + hideFlag("maligned.suggest-new") + + fs.IntVar(&lsc.Dupl.Threshold, "dupl.threshold", + 150, "Dupl: Minimal threshold to detect copy-paste") + hideFlag("dupl.threshold") + + fs.IntVar(&lsc.Goconst.MinStringLen, "goconst.min-len", + 3, "Goconst: minimum constant string length") + hideFlag("goconst.min-len") + fs.IntVar(&lsc.Goconst.MinOccurrencesCount, "goconst.min-occurrences", + 3, "Goconst: minimum occurrences of constant string count to trigger issue") + hideFlag("goconst.min-occurrences") + + // (@dixonwille) These flag is only used for testing purposes. + fs.StringSliceVar(&lsc.Depguard.Packages, "depguard.packages", nil, + "Depguard: packages to add to the list") + hideFlag("depguard.packages") + + fs.BoolVar(&lsc.Depguard.IncludeGoRoot, "depguard.include-go-root", false, + "Depguard: check list against standard lib") + hideFlag("depguard.include-go-root") + + fs.IntVar(&lsc.Lll.TabWidth, "lll.tab-width", 1, + "Lll: tab width in spaces") + hideFlag("lll.tab-width") + + // Linters config + lc := &cfg.Linters + fs.StringSliceVarP(&lc.Enable, "enable", "E", nil, wh("Enable specific linter")) + fs.StringSliceVarP(&lc.Disable, "disable", "D", nil, wh("Disable specific linter")) + fs.BoolVar(&lc.EnableAll, "enable-all", false, wh("Enable all linters")) + if err := fs.MarkHidden("enable-all"); err != nil { + panic(err) + } + // TODO: run hideFlag("enable-all") to print deprecation message. + + fs.BoolVar(&lc.DisableAll, "disable-all", false, wh("Disable all linters")) + fs.StringSliceVarP(&lc.Presets, "presets", "p", nil, + wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see "+ + "them. This option implies option --disable-all", strings.Join(m.AllPresets(), "|")))) + fs.BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set (first run won't be fast)")) + + // Issues config + ic := &cfg.Issues + fs.StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", nil, wh("Exclude issue by regexp")) + fs.BoolVar(&ic.UseDefaultExcludes, "exclude-use-default", true, getDefaultIssueExcludeHelp()) + fs.BoolVar(&ic.ExcludeCaseSensitive, "exclude-case-sensitive", false, wh("If set to true exclude "+ + "and exclude rules regular expressions are case sensitive")) + + fs.IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50, + wh("Maximum issues count per one linter. Set to 0 to disable")) + fs.IntVar(&ic.MaxSameIssues, "max-same-issues", 3, + wh("Maximum count of issues with the same text. Set to 0 to disable")) + + fs.BoolVarP(&ic.Diff, "new", "n", false, + wh("Show only new issues: if there are unstaged changes or untracked files, only those changes "+ + "are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration "+ + "of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at "+ + "the moment of integration: much better to not allow issues in new code.\nFor CI setups, prefer "+ + "--new-from-rev=HEAD~, as --new can skip linting the current patch if any scripts generate "+ + "unstaged files before golangci-lint runs.")) + fs.StringVar(&ic.DiffFromRevision, "new-from-rev", "", + wh("Show only new issues created after git revision `REV`")) + fs.StringVar(&ic.DiffPatchFilePath, "new-from-patch", "", + wh("Show only new issues created in git patch with file path `PATH`")) + fs.BoolVar(&ic.NeedFix, "fix", false, "Fix found issues (if it's supported by the linter)") +} + +func (e *Executor) initRunConfiguration(cmd *cobra.Command) { + fs := cmd.Flags() + fs.SortFlags = false // sort them as they are defined here + initFlagSet(fs, e.cfg, e.DBManager, true) +} + +func (e *Executor) getConfigForCommandLine() (*config.Config, error) { + // We use another pflag.FlagSet here to not set `changed` flag + // on cmd.Flags() options. Otherwise string slice options will be duplicated. + fs := pflag.NewFlagSet("config flag set", pflag.ContinueOnError) + + var cfg config.Config + // Don't do `fs.AddFlagSet(cmd.Flags())` because it shares flags representations: + // `changed` variable inside string slice vars will be shared. + // Use another config variable here, not e.cfg, to not + // affect main parsing by this parsing of only config option. + initFlagSet(fs, &cfg, e.DBManager, false) + + // Parse max options, even force version option: don't want + // to get access to Executor here: it's error-prone to use + // cfg vs e.cfg. + initRootFlagSet(fs, &cfg, true) + + fs.Usage = func() {} // otherwise help text will be printed twice + if err := fs.Parse(os.Args); err != nil { + if err == pflag.ErrHelp { + return nil, err + } + + return nil, fmt.Errorf("can't parse args: %s", err) + } + + return &cfg, nil +} + +func (e *Executor) initRun() { + e.runCmd = &cobra.Command{ + Use: "run", + Short: welcomeMessage, + Run: e.executeRun, + PreRun: func(_ *cobra.Command, _ []string) { + if ok := e.acquireFileLock(); !ok { + e.log.Fatalf("Parallel golangci-lint is running") + } + }, + PostRun: func(_ *cobra.Command, _ []string) { + e.releaseFileLock() + }, + } + e.rootCmd.AddCommand(e.runCmd) + + e.runCmd.SetOutput(logutils.StdOut) // use custom output to properly color it in Windows terminals + + e.initRunConfiguration(e.runCmd) +} + +func fixSlicesFlags(fs *pflag.FlagSet) { + // It's a dirty hack to set flag.Changed to true for every string slice flag. + // It's necessary to merge config and command-line slices: otherwise command-line + // flags will always overwrite ones from the config. + fs.VisitAll(func(f *pflag.Flag) { + if f.Value.Type() != "stringSlice" { + return + } + + s, err := fs.GetStringSlice(f.Name) + if err != nil { + return + } + + if s == nil { // assume that every string slice flag has nil as the default + return + } + + // calling Set sets Changed to true: next Set calls will append, not overwrite + _ = f.Value.Set(strings.Join(s, ",")) + }) +} + +func (e *Executor) runAnalysis(ctx context.Context, args []string) ([]result.Issue, error) { + e.cfg.Run.Args = args + + lintersToRun, err := e.EnabledLintersSet.GetOptimizedLinters() + if err != nil { + return nil, err + } + + enabledLintersMap, err := e.EnabledLintersSet.GetEnabledLintersMap() + if err != nil { + return nil, err + } + + for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { + isEnabled := enabledLintersMap[lc.Name()] != nil + e.reportData.AddLinter(lc.Name(), isEnabled, lc.EnabledByDefault) + } + + lintCtx, err := e.contextLoader.Load(ctx, lintersToRun) + if err != nil { + return nil, errors.Wrap(err, "context loading failed") + } + lintCtx.Log = e.log.Child("linters context") + + runner, err := lint.NewRunner(e.cfg, e.log.Child("runner"), + e.goenv, e.EnabledLintersSet, e.lineCache, e.DBManager, lintCtx.Packages) + if err != nil { + return nil, err + } + + issues, err := runner.Run(ctx, lintersToRun, lintCtx) + if err != nil { + return nil, err + } + + fixer := processors.NewFixer(e.cfg, e.log, e.fileCache) + return fixer.Process(issues), nil +} + +func (e *Executor) setOutputToDevNull() (savedStdout, savedStderr *os.File) { + savedStdout, savedStderr = os.Stdout, os.Stderr + devNull, err := os.Open(os.DevNull) + if err != nil { + e.log.Warnf("Can't open null device %q: %s", os.DevNull, err) + return + } + + os.Stdout, os.Stderr = devNull, devNull + return +} + +func (e *Executor) setExitCodeIfIssuesFound(issues []result.Issue) { + if len(issues) != 0 { + e.exitCode = e.cfg.Run.ExitCodeIfIssuesFound + } +} + +func (e *Executor) runAndPrint(ctx context.Context, args []string) error { + if err := e.goenv.Discover(ctx); err != nil { + e.log.Warnf("Failed to discover go env: %s", err) + } + + if !logutils.HaveDebugTag("linters_output") { + // Don't allow linters and loader to print anything + log.SetOutput(ioutil.Discard) + savedStdout, savedStderr := e.setOutputToDevNull() + defer func() { + os.Stdout, os.Stderr = savedStdout, savedStderr + }() + } + + issues, err := e.runAnalysis(ctx, args) + if err != nil { + return err // XXX: don't loose type + } + + p, err := e.createPrinter() + if err != nil { + return err + } + + e.setExitCodeIfIssuesFound(issues) + + if err = p.Print(ctx, issues); err != nil { + return fmt.Errorf("can't print %d issues: %s", len(issues), err) + } + + e.fileCache.PrintStats(e.log) + + return nil +} + +func (e *Executor) createPrinter() (printers.Printer, error) { + var p printers.Printer + format := e.cfg.Output.Format + switch format { + case config.OutFormatJSON: + p = printers.NewJSON(&e.reportData) + case config.OutFormatColoredLineNumber, config.OutFormatLineNumber: + p = printers.NewText(e.cfg.Output.PrintIssuedLine, + format == config.OutFormatColoredLineNumber, e.cfg.Output.PrintLinterName, + e.log.Child("text_printer")) + case config.OutFormatTab: + p = printers.NewTab(e.cfg.Output.PrintLinterName, e.log.Child("tab_printer")) + case config.OutFormatCheckstyle: + p = printers.NewCheckstyle() + case config.OutFormatCodeClimate: + p = printers.NewCodeClimate() + case config.OutFormatJunitXML: + p = printers.NewJunitXML() + case config.OutFormatGithubActions: + p = printers.NewGithub() + default: + return nil, fmt.Errorf("unknown output format %s", format) + } + + return p, nil +} + +func (e *Executor) executeRun(_ *cobra.Command, args []string) { + needTrackResources := e.cfg.Run.IsVerbose || e.cfg.Run.PrintResourcesUsage + trackResourcesEndCh := make(chan struct{}) + defer func() { // XXX: this defer must be before ctx.cancel defer + if needTrackResources { // wait until resource tracking finished to print properly + <-trackResourcesEndCh + } + }() + + e.setTimeoutToDeadlineIfOnlyDeadlineIsSet() + ctx, cancel := context.WithTimeout(context.Background(), e.cfg.Run.Timeout) + defer cancel() + + if needTrackResources { + go watchResources(ctx, trackResourcesEndCh, e.log, e.debugf) + } + + if err := e.runAndPrint(ctx, args); err != nil { + e.log.Errorf("Running error: %s", err) + if e.exitCode == exitcodes.Success { + if exitErr, ok := errors.Cause(err).(*exitcodes.ExitError); ok { + e.exitCode = exitErr.Code + } else { + e.exitCode = exitcodes.Failure + } + } + } + + e.setupExitCode(ctx) +} + +// to be removed when deadline is finally decommissioned +func (e *Executor) setTimeoutToDeadlineIfOnlyDeadlineIsSet() { + //lint:ignore SA1019 We want to promoted the deprecated config value when needed + deadlineValue := e.cfg.Run.Deadline // nolint:staticcheck + if deadlineValue != 0 && e.cfg.Run.Timeout == defaultTimeout { + e.cfg.Run.Timeout = deadlineValue + } +} + +func (e *Executor) setupExitCode(ctx context.Context) { + if ctx.Err() != nil { + e.exitCode = exitcodes.Timeout + e.log.Errorf("Timeout exceeded: try increasing it by passing --timeout option") + return + } + + if e.exitCode != exitcodes.Success { + return + } + + needFailOnWarnings := (os.Getenv("GL_TEST_RUN") == "1" || os.Getenv("FAIL_ON_WARNINGS") == "1") + if needFailOnWarnings && len(e.reportData.Warnings) != 0 { + e.exitCode = exitcodes.WarningInTest + return + } + + if e.reportData.Error != "" { + // it's a case e.g. when typecheck linter couldn't parse and error and just logged it + e.exitCode = exitcodes.ErrorWasLogged + return + } +} + +func watchResources(ctx context.Context, done chan struct{}, logger logutils.Log, debugf logutils.DebugFunc) { + startedAt := time.Now() + debugf("Started tracking time") + + var maxRSSMB, totalRSSMB float64 + var iterationsCount int + + const intervalMS = 100 + ticker := time.NewTicker(intervalMS * time.Millisecond) + defer ticker.Stop() + + logEveryRecord := os.Getenv("GL_MEM_LOG_EVERY") == "1" + const MB = 1024 * 1024 + + track := func() { + var m runtime.MemStats + runtime.ReadMemStats(&m) + + if logEveryRecord { + debugf("Stopping memory tracing iteration, printing ...") + printMemStats(&m, logger) + } + + rssMB := float64(m.Sys) / MB + if rssMB > maxRSSMB { + maxRSSMB = rssMB + } + totalRSSMB += rssMB + iterationsCount++ + } + + for { + track() + + stop := false + select { + case <-ctx.Done(): + stop = true + debugf("Stopped resources tracking") + case <-ticker.C: + } + + if stop { + break + } + } + track() + + avgRSSMB := totalRSSMB / float64(iterationsCount) + + logger.Infof("Memory: %d samples, avg is %.1fMB, max is %.1fMB", + iterationsCount, avgRSSMB, maxRSSMB) + logger.Infof("Execution took %s", time.Since(startedAt)) + close(done) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/version.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/version.go new file mode 100644 index 000000000..fdb5aa884 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/version.go @@ -0,0 +1,17 @@ +package commands + +import ( + "github.com/spf13/cobra" +) + +func (e *Executor) initVersion() { + versionCmd := &cobra.Command{ + Use: "version", + Short: "Version", + Run: func(cmd *cobra.Command, _ []string) { + cmd.Printf("golangci-lint has version %s built from %s on %s\n", e.version, e.commit, e.date) + }, + } + + e.rootCmd.AddCommand(versionCmd) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/config/config.go b/vendor/github.com/golangci/golangci-lint/pkg/config/config.go new file mode 100644 index 000000000..89e3559c1 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/config/config.go @@ -0,0 +1,491 @@ +package config + +import ( + "errors" + "fmt" + "regexp" + "time" +) + +const ( + OutFormatJSON = "json" + OutFormatLineNumber = "line-number" + OutFormatColoredLineNumber = "colored-line-number" + OutFormatTab = "tab" + OutFormatCheckstyle = "checkstyle" + OutFormatCodeClimate = "code-climate" + OutFormatJunitXML = "junit-xml" + OutFormatGithubActions = "github-actions" +) + +var OutFormats = []string{ + OutFormatColoredLineNumber, + OutFormatLineNumber, + OutFormatJSON, + OutFormatTab, + OutFormatCheckstyle, + OutFormatCodeClimate, + OutFormatJunitXML, + OutFormatGithubActions, +} + +type ExcludePattern struct { + ID string + Pattern string + Linter string + Why string +} + +var DefaultExcludePatterns = []ExcludePattern{ + { + ID: "EXC0001", + Pattern: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close" + + "|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked", + Linter: "errcheck", + Why: "Almost all programs ignore errors on these functions and in most cases it's ok", + }, + { + ID: "EXC0002", + Pattern: "(comment on exported (method|function|type|const)|" + + "should have( a package)? comment|comment should be of the form)", + Linter: "golint", + Why: "Annoying issue about not having a comment. The rare codebase has such comments", + }, + { + ID: "EXC0003", + Pattern: "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this", + Linter: "golint", + Why: "False positive when tests are defined in package 'test'", + }, + { + ID: "EXC0004", + Pattern: "(possible misuse of unsafe.Pointer|should have signature)", + Linter: "govet", + Why: "Common false positives", + }, + { + ID: "EXC0005", + Pattern: "ineffective break statement. Did you mean to break out of the outer loop", + Linter: "staticcheck", + Why: "Developers tend to write in C-style with an explicit 'break' in a 'switch', so it's ok to ignore", + }, + { + ID: "EXC0006", + Pattern: "Use of unsafe calls should be audited", + Linter: "gosec", + Why: "Too many false-positives on 'unsafe' usage", + }, + { + ID: "EXC0007", + Pattern: "Subprocess launch(ed with variable|ing should be audited)", + Linter: "gosec", + Why: "Too many false-positives for parametrized shell calls", + }, + { + ID: "EXC0008", + Pattern: "(G104|G307)", + Linter: "gosec", + Why: "Duplicated errcheck checks", + }, + { + ID: "EXC0009", + Pattern: "(Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)", + Linter: "gosec", + Why: "Too many issues in popular repos", + }, + { + ID: "EXC0010", + Pattern: "Potential file inclusion via variable", + Linter: "gosec", + Why: "False positive is triggered by 'src, err := ioutil.ReadFile(filename)'", + }, +} + +func GetDefaultExcludePatternsStrings() []string { + return GetExcludePatternsStrings(nil) +} + +func GetExcludePatternsStrings(include []string) []string { + includeMap := make(map[string]bool, len(include)) + for _, inc := range include { + includeMap[inc] = true + } + + var ret []string + for _, p := range DefaultExcludePatterns { + if !includeMap[p.ID] { + ret = append(ret, p.Pattern) + } + } + + return ret +} + +type Run struct { + IsVerbose bool `mapstructure:"verbose"` + Silent bool + CPUProfilePath string + MemProfilePath string + TracePath string + Concurrency int + PrintResourcesUsage bool `mapstructure:"print-resources-usage"` + + Config string + NoConfig bool + + Args []string + + BuildTags []string `mapstructure:"build-tags"` + ModulesDownloadMode string `mapstructure:"modules-download-mode"` + + ExitCodeIfIssuesFound int `mapstructure:"issues-exit-code"` + AnalyzeTests bool `mapstructure:"tests"` + + // Deprecated: Deadline exists for historical compatibility + // and should not be used. To set run timeout use Timeout instead. + Deadline time.Duration + Timeout time.Duration + + PrintVersion bool + SkipFiles []string `mapstructure:"skip-files"` + SkipDirs []string `mapstructure:"skip-dirs"` + UseDefaultSkipDirs bool `mapstructure:"skip-dirs-use-default"` + + AllowParallelRunners bool `mapstructure:"allow-parallel-runners"` +} + +type LintersSettings struct { + Govet GovetSettings + Golint struct { + MinConfidence float64 `mapstructure:"min-confidence"` + } + Gofmt struct { + Simplify bool + } + Goimports struct { + LocalPrefixes string `mapstructure:"local-prefixes"` + } + Gocyclo struct { + MinComplexity int `mapstructure:"min-complexity"` + } + Varcheck struct { + CheckExportedFields bool `mapstructure:"exported-fields"` + } + Structcheck struct { + CheckExportedFields bool `mapstructure:"exported-fields"` + } + Maligned struct { + SuggestNewOrder bool `mapstructure:"suggest-new"` + } + Dupl struct { + Threshold int + } + Goconst struct { + MinStringLen int `mapstructure:"min-len"` + MinOccurrencesCount int `mapstructure:"min-occurrences"` + } + Gomnd struct { + Settings map[string]map[string]interface{} + } + Depguard struct { + ListType string `mapstructure:"list-type"` + Packages []string + IncludeGoRoot bool `mapstructure:"include-go-root"` + PackagesWithErrorMessage map[string]string `mapstructure:"packages-with-error-message"` + } + Misspell struct { + Locale string + IgnoreWords []string `mapstructure:"ignore-words"` + } + Unused struct { + CheckExported bool `mapstructure:"check-exported"` + } + Funlen struct { + Lines int + Statements int + } + Whitespace struct { + MultiIf bool `mapstructure:"multi-if"` + MultiFunc bool `mapstructure:"multi-func"` + } + RowsErrCheck struct { + Packages []string + } + Gomodguard struct { + Allowed struct { + Modules []string `mapstructure:"modules"` + Domains []string `mapstructure:"domains"` + } `mapstructure:"allowed"` + Blocked struct { + Modules []map[string]struct { + Recommendations []string `mapstructure:"recommendations"` + Reason string `mapstructure:"reason"` + } `mapstructure:"modules"` + } `mapstructure:"blocked"` + } + + WSL WSLSettings + Lll LllSettings + Unparam UnparamSettings + Nakedret NakedretSettings + Prealloc PreallocSettings + Errcheck ErrcheckSettings + Gocritic GocriticSettings + Godox GodoxSettings + Dogsled DogsledSettings + Gocognit GocognitSettings + Godot GodotSettings + Testpackage TestpackageSettings + Nestif NestifSettings + NoLintLint NoLintLintSettings + + Custom map[string]CustomLinterSettings +} + +type GovetSettings struct { + CheckShadowing bool `mapstructure:"check-shadowing"` + Settings map[string]map[string]interface{} + + Enable []string + Disable []string + EnableAll bool `mapstructure:"enable-all"` + DisableAll bool `mapstructure:"disable-all"` +} + +func (cfg GovetSettings) Validate() error { + if cfg.EnableAll && cfg.DisableAll { + return errors.New("enable-all and disable-all can't be combined") + } + if cfg.EnableAll && len(cfg.Enable) != 0 { + return errors.New("enable-all and enable can't be combined") + } + if cfg.DisableAll && len(cfg.Disable) != 0 { + return errors.New("disable-all and disable can't be combined") + } + return nil +} + +type ErrcheckSettings struct { + CheckTypeAssertions bool `mapstructure:"check-type-assertions"` + CheckAssignToBlank bool `mapstructure:"check-blank"` + Ignore string `mapstructure:"ignore"` + Exclude string `mapstructure:"exclude"` +} + +type LllSettings struct { + LineLength int `mapstructure:"line-length"` + TabWidth int `mapstructure:"tab-width"` +} + +type UnparamSettings struct { + CheckExported bool `mapstructure:"check-exported"` + Algo string +} + +type NakedretSettings struct { + MaxFuncLines int `mapstructure:"max-func-lines"` +} + +type PreallocSettings struct { + Simple bool + RangeLoops bool `mapstructure:"range-loops"` + ForLoops bool `mapstructure:"for-loops"` +} + +type GodoxSettings struct { + Keywords []string +} + +type DogsledSettings struct { + MaxBlankIdentifiers int `mapstructure:"max-blank-identifiers"` +} + +type GocognitSettings struct { + MinComplexity int `mapstructure:"min-complexity"` +} + +type WSLSettings struct { + StrictAppend bool `mapstructure:"strict-append"` + AllowAssignAndCallCuddle bool `mapstructure:"allow-assign-and-call"` + AllowMultiLineAssignCuddle bool `mapstructure:"allow-multiline-assign"` + AllowCuddleDeclaration bool `mapstructure:"allow-cuddle-declarations"` + AllowTrailingComment bool `mapstructure:"allow-trailing-comment"` + AllowSeparatedLeadingComment bool `mapstructure:"allow-separated-leading-comment"` + ForceCuddleErrCheckAndAssign bool `mapstructure:"force-err-cuddling"` + ForceCaseTrailingWhitespaceLimit int `mapstructure:"force-case-trailing-whitespace"` +} + +type GodotSettings struct { + CheckAll bool `mapstructure:"check-all"` +} + +type NoLintLintSettings struct { + RequireExplanation bool `mapstructure:"require-explanation"` + AllowLeadingSpace bool `mapstructure:"allow-leading-space"` + RequireSpecific bool `mapstructure:"require-specific"` + AllowNoExplanation []string `mapstructure:"allow-no-explanation"` + AllowUnused bool `mapstructure:"allow-unused"` +} + +type TestpackageSettings struct { + SkipRegexp string `mapstructure:"skip-regexp"` +} + +type NestifSettings struct { + MinComplexity int `mapstructure:"min-complexity"` +} + +var defaultLintersSettings = LintersSettings{ + Lll: LllSettings{ + LineLength: 120, + TabWidth: 1, + }, + Unparam: UnparamSettings{ + Algo: "cha", + }, + Nakedret: NakedretSettings{ + MaxFuncLines: 30, + }, + Prealloc: PreallocSettings{ + Simple: true, + RangeLoops: true, + ForLoops: false, + }, + Gocritic: GocriticSettings{ + SettingsPerCheck: map[string]GocriticCheckSettings{}, + }, + Godox: GodoxSettings{ + Keywords: []string{}, + }, + Dogsled: DogsledSettings{ + MaxBlankIdentifiers: 2, + }, + Gocognit: GocognitSettings{ + MinComplexity: 30, + }, + WSL: WSLSettings{ + StrictAppend: true, + AllowAssignAndCallCuddle: true, + AllowMultiLineAssignCuddle: true, + AllowCuddleDeclaration: false, + AllowTrailingComment: false, + AllowSeparatedLeadingComment: false, + ForceCuddleErrCheckAndAssign: false, + ForceCaseTrailingWhitespaceLimit: 0, + }, + NoLintLint: NoLintLintSettings{ + RequireExplanation: false, + AllowLeadingSpace: true, + RequireSpecific: false, + AllowUnused: false, + }, + Testpackage: TestpackageSettings{ + SkipRegexp: `(export|internal)_test\.go`, + }, + Nestif: NestifSettings{ + MinComplexity: 5, + }, +} + +type CustomLinterSettings struct { + Path string + Description string + OriginalURL string `mapstructure:"original-url"` +} + +type Linters struct { + Enable []string + Disable []string + EnableAll bool `mapstructure:"enable-all"` + DisableAll bool `mapstructure:"disable-all"` + Fast bool + + Presets []string +} + +type ExcludeRule struct { + Linters []string + Path string + Text string + Source string +} + +func validateOptionalRegex(value string) error { + if value == "" { + return nil + } + _, err := regexp.Compile(value) + return err +} + +func (e ExcludeRule) Validate() error { + if err := validateOptionalRegex(e.Path); err != nil { + return fmt.Errorf("invalid path regex: %v", err) + } + if err := validateOptionalRegex(e.Text); err != nil { + return fmt.Errorf("invalid text regex: %v", err) + } + if err := validateOptionalRegex(e.Source); err != nil { + return fmt.Errorf("invalid source regex: %v", err) + } + nonBlank := 0 + if len(e.Linters) > 0 { + nonBlank++ + } + if e.Path != "" { + nonBlank++ + } + if e.Text != "" { + nonBlank++ + } + if e.Source != "" { + nonBlank++ + } + const minConditionsCount = 2 + if nonBlank < minConditionsCount { + return errors.New("at least 2 of (text, source, path, linters) should be set") + } + return nil +} + +type Issues struct { + IncludeDefaultExcludes []string `mapstructure:"include"` + ExcludeCaseSensitive bool `mapstructure:"exclude-case-sensitive"` + ExcludePatterns []string `mapstructure:"exclude"` + ExcludeRules []ExcludeRule `mapstructure:"exclude-rules"` + UseDefaultExcludes bool `mapstructure:"exclude-use-default"` + + MaxIssuesPerLinter int `mapstructure:"max-issues-per-linter"` + MaxSameIssues int `mapstructure:"max-same-issues"` + + DiffFromRevision string `mapstructure:"new-from-rev"` + DiffPatchFilePath string `mapstructure:"new-from-patch"` + Diff bool `mapstructure:"new"` + + NeedFix bool `mapstructure:"fix"` +} + +type Config struct { + Run Run + + Output struct { + Format string + Color string + PrintIssuedLine bool `mapstructure:"print-issued-lines"` + PrintLinterName bool `mapstructure:"print-linter-name"` + UniqByLine bool `mapstructure:"uniq-by-line"` + PrintWelcomeMessage bool `mapstructure:"print-welcome"` + } + + LintersSettings LintersSettings `mapstructure:"linters-settings"` + Linters Linters + Issues Issues + + InternalTest bool // Option is used only for testing golangci-lint code, don't use it +} + +func NewDefault() *Config { + return &Config{ + LintersSettings: defaultLintersSettings, + } +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/config/config_gocritic.go b/vendor/github.com/golangci/golangci-lint/pkg/config/config_gocritic.go new file mode 100644 index 000000000..bbfd7bb13 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/config/config_gocritic.go @@ -0,0 +1,367 @@ +package config + +import ( + "fmt" + "sort" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/pkg/errors" + + _ "github.com/go-critic/go-critic/checkers" // this import register checkers + + "github.com/golangci/golangci-lint/pkg/logutils" +) + +const gocriticDebugKey = "gocritic" + +var ( + gocriticDebugf = logutils.Debug(gocriticDebugKey) + isGocriticDebug = logutils.HaveDebugTag(gocriticDebugKey) + allGocriticCheckers = lintpack.GetCheckersInfo() + allGocriticCheckerMap = func() map[string]*lintpack.CheckerInfo { + checkInfoMap := make(map[string]*lintpack.CheckerInfo) + for _, checkInfo := range allGocriticCheckers { + checkInfoMap[checkInfo.Name] = checkInfo + } + return checkInfoMap + }() +) + +type GocriticCheckSettings map[string]interface{} + +type GocriticSettings struct { + EnabledChecks []string `mapstructure:"enabled-checks"` + DisabledChecks []string `mapstructure:"disabled-checks"` + EnabledTags []string `mapstructure:"enabled-tags"` + DisabledTags []string `mapstructure:"disabled-tags"` + SettingsPerCheck map[string]GocriticCheckSettings `mapstructure:"settings"` + + inferredEnabledChecks map[string]bool +} + +func debugChecksListf(checks []string, format string, args ...interface{}) { + if isGocriticDebug { + prefix := fmt.Sprintf(format, args...) + gocriticDebugf(prefix+" checks (%d): %s", len(checks), sprintStrings(checks)) + } +} + +func stringsSliceToSet(ss []string) map[string]bool { + ret := map[string]bool{} + for _, s := range ss { + ret[s] = true + } + + return ret +} + +func buildGocriticTagToCheckersMap() map[string][]string { + tagToCheckers := map[string][]string{} + for _, checker := range allGocriticCheckers { + for _, tag := range checker.Tags { + tagToCheckers[tag] = append(tagToCheckers[tag], checker.Name) + } + } + return tagToCheckers +} + +func gocriticCheckerTagsDebugf() { + if !isGocriticDebug { + return + } + + tagToCheckers := buildGocriticTagToCheckersMap() + + var allTags []string + for tag := range tagToCheckers { + allTags = append(allTags, tag) + } + sort.Strings(allTags) + + gocriticDebugf("All gocritic existing tags and checks:") + for _, tag := range allTags { + debugChecksListf(tagToCheckers[tag], " tag %q", tag) + } +} + +func (s *GocriticSettings) gocriticDisabledCheckersDebugf() { + if !isGocriticDebug { + return + } + + var disabledCheckers []string + for _, checker := range allGocriticCheckers { + if s.inferredEnabledChecks[strings.ToLower(checker.Name)] { + continue + } + + disabledCheckers = append(disabledCheckers, checker.Name) + } + + if len(disabledCheckers) == 0 { + gocriticDebugf("All checks are enabled") + } else { + debugChecksListf(disabledCheckers, "Final not used") + } +} + +func (s *GocriticSettings) InferEnabledChecks(log logutils.Log) { + gocriticCheckerTagsDebugf() + + enabledByDefaultChecks := getDefaultEnabledGocriticCheckersNames() + debugChecksListf(enabledByDefaultChecks, "Enabled by default") + + disabledByDefaultChecks := getDefaultDisabledGocriticCheckersNames() + debugChecksListf(disabledByDefaultChecks, "Disabled by default") + + var enabledChecks []string + + // EnabledTags + if len(s.EnabledTags) != 0 { + tagToCheckers := buildGocriticTagToCheckersMap() + for _, tag := range s.EnabledTags { + enabledChecks = append(enabledChecks, tagToCheckers[tag]...) + } + debugChecksListf(enabledChecks, "Enabled by config tags %s", sprintStrings(s.EnabledTags)) + } + + if !(len(s.EnabledTags) == 0 && len(s.EnabledChecks) != 0) { + // don't use default checks only if we have no enabled tags and enable some checks manually + enabledChecks = append(enabledChecks, enabledByDefaultChecks...) + } + + // DisabledTags + if len(s.DisabledTags) != 0 { + enabledChecks = filterByDisableTags(enabledChecks, s.DisabledTags, log) + } + + // EnabledChecks + if len(s.EnabledChecks) != 0 { + debugChecksListf(s.EnabledChecks, "Enabled by config") + + alreadyEnabledChecksSet := stringsSliceToSet(enabledChecks) + for _, enabledCheck := range s.EnabledChecks { + if alreadyEnabledChecksSet[enabledCheck] { + log.Warnf("No need to enable check %q: it's already enabled", enabledCheck) + continue + } + enabledChecks = append(enabledChecks, enabledCheck) + } + } + + // DisabledChecks + if len(s.DisabledChecks) != 0 { + debugChecksListf(s.DisabledChecks, "Disabled by config") + + enabledChecksSet := stringsSliceToSet(enabledChecks) + for _, disabledCheck := range s.DisabledChecks { + if !enabledChecksSet[disabledCheck] { + log.Warnf("Gocritic check %q was explicitly disabled via config. However, as this check"+ + "is disabled by default, there is no need to explicitly disable it via config.", disabledCheck) + continue + } + delete(enabledChecksSet, disabledCheck) + } + + enabledChecks = nil + for enabledCheck := range enabledChecksSet { + enabledChecks = append(enabledChecks, enabledCheck) + } + } + + s.inferredEnabledChecks = map[string]bool{} + for _, check := range enabledChecks { + s.inferredEnabledChecks[strings.ToLower(check)] = true + } + + debugChecksListf(enabledChecks, "Final used") + s.gocriticDisabledCheckersDebugf() +} + +func validateStringsUniq(ss []string) error { + set := map[string]bool{} + for _, s := range ss { + _, ok := set[s] + if ok { + return fmt.Errorf("%q occurs multiple times in list", s) + } + set[s] = true + } + + return nil +} + +func intersectStringSlice(s1, s2 []string) []string { + s1Map := make(map[string]struct{}) + for _, s := range s1 { + s1Map[s] = struct{}{} + } + + result := make([]string, 0) + for _, s := range s2 { + if _, exists := s1Map[s]; exists { + result = append(result, s) + } + } + + return result +} + +func (s *GocriticSettings) Validate(log logutils.Log) error { + if len(s.EnabledTags) == 0 { + if len(s.EnabledChecks) != 0 && len(s.DisabledChecks) != 0 { + return errors.New("both enabled and disabled check aren't allowed for gocritic") + } + } else { + if err := validateStringsUniq(s.EnabledTags); err != nil { + return errors.Wrap(err, "validate enabled tags") + } + + tagToCheckers := buildGocriticTagToCheckersMap() + for _, tag := range s.EnabledTags { + if _, ok := tagToCheckers[tag]; !ok { + return fmt.Errorf("gocritic [enabled]tag %q doesn't exist", tag) + } + } + } + + if len(s.DisabledTags) > 0 { + tagToCheckers := buildGocriticTagToCheckersMap() + for _, tag := range s.EnabledTags { + if _, ok := tagToCheckers[tag]; !ok { + return fmt.Errorf("gocritic [disabled]tag %q doesn't exist", tag) + } + } + } + + if err := validateStringsUniq(s.EnabledChecks); err != nil { + return errors.Wrap(err, "validate enabled checks") + } + if err := validateStringsUniq(s.DisabledChecks); err != nil { + return errors.Wrap(err, "validate disabled checks") + } + + for checkName := range s.SettingsPerCheck { + if !s.IsCheckEnabled(checkName) { + log.Warnf("Gocritic settings were provided for not enabled check %q", checkName) + } + } + + if err := s.validateCheckerNames(); err != nil { + return errors.Wrap(err, "validation failed") + } + + return nil +} + +func (s *GocriticSettings) IsCheckEnabled(name string) bool { + return s.inferredEnabledChecks[strings.ToLower(name)] +} + +func sprintAllowedCheckerNames(allowedNames map[string]bool) string { + var namesSlice []string + for name := range allowedNames { + namesSlice = append(namesSlice, name) + } + return sprintStrings(namesSlice) +} + +func sprintStrings(ss []string) string { + sort.Strings(ss) + return fmt.Sprint(ss) +} + +func getAllCheckerNames() map[string]bool { + allCheckerNames := map[string]bool{} + for _, checker := range allGocriticCheckers { + allCheckerNames[strings.ToLower(checker.Name)] = true + } + + return allCheckerNames +} + +func isEnabledByDefaultGocriticCheck(info *lintpack.CheckerInfo) bool { + return !info.HasTag("experimental") && + !info.HasTag("opinionated") && + !info.HasTag("performance") +} + +func getDefaultEnabledGocriticCheckersNames() []string { + var enabled []string + for _, info := range allGocriticCheckers { + // get in sync with lintpack behavior in bindDefaultEnabledList + // in https://github.com/go-lintpack/lintpack/blob/master/linter/lintmain/internal/check/check.go#L317 + + enable := isEnabledByDefaultGocriticCheck(info) + if enable { + enabled = append(enabled, info.Name) + } + } + + return enabled +} + +func getDefaultDisabledGocriticCheckersNames() []string { + var disabled []string + for _, info := range allGocriticCheckers { + // get in sync with lintpack behavior in bindDefaultEnabledList + // in https://github.com/go-lintpack/lintpack/blob/master/linter/lintmain/internal/check/check.go#L317 + + enable := isEnabledByDefaultGocriticCheck(info) + if !enable { + disabled = append(disabled, info.Name) + } + } + + return disabled +} + +func (s *GocriticSettings) validateCheckerNames() error { + allowedNames := getAllCheckerNames() + + for _, name := range s.EnabledChecks { + if !allowedNames[strings.ToLower(name)] { + return fmt.Errorf("enabled checker %s doesn't exist, all existing checkers: %s", + name, sprintAllowedCheckerNames(allowedNames)) + } + } + + for _, name := range s.DisabledChecks { + if !allowedNames[strings.ToLower(name)] { + return fmt.Errorf("disabled checker %s doesn't exist, all existing checkers: %s", + name, sprintAllowedCheckerNames(allowedNames)) + } + } + + return nil +} + +func (s *GocriticSettings) GetLowercasedParams() map[string]GocriticCheckSettings { + ret := map[string]GocriticCheckSettings{} + for checker, params := range s.SettingsPerCheck { + ret[strings.ToLower(checker)] = params + } + return ret +} + +func filterByDisableTags(enabledChecks, disableTags []string, log logutils.Log) []string { + enabledChecksSet := stringsSliceToSet(enabledChecks) + for _, enabledCheck := range enabledChecks { + checkInfo, checkInfoExists := allGocriticCheckerMap[enabledCheck] + if !checkInfoExists { + log.Warnf("Gocritic check %q was not exists via filtering disabled tags", enabledCheck) + continue + } + hitTags := intersectStringSlice(checkInfo.Tags, disableTags) + if len(hitTags) != 0 { + delete(enabledChecksSet, enabledCheck) + } + debugChecksListf(enabledChecks, "Disabled by config tags %s", sprintStrings(disableTags)) + } + enabledChecks = nil + for enabledCheck := range enabledChecksSet { + enabledChecks = append(enabledChecks, enabledCheck) + } + return enabledChecks +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/config/reader.go b/vendor/github.com/golangci/golangci-lint/pkg/config/reader.go new file mode 100644 index 000000000..1e355e722 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/config/reader.go @@ -0,0 +1,204 @@ +package config + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strings" + + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/viper" + + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +type FileReader struct { + log logutils.Log + cfg *Config + commandLineCfg *Config +} + +func NewFileReader(toCfg, commandLineCfg *Config, log logutils.Log) *FileReader { + return &FileReader{ + log: log, + cfg: toCfg, + commandLineCfg: commandLineCfg, + } +} + +func (r *FileReader) Read() error { + // XXX: hack with double parsing for 2 purposes: + // 1. to access "config" option here. + // 2. to give config less priority than command line. + + configFile, err := r.parseConfigOption() + if err != nil { + if err == errConfigDisabled { + return nil + } + + return fmt.Errorf("can't parse --config option: %s", err) + } + + if configFile != "" { + viper.SetConfigFile(configFile) + } else { + r.setupConfigFileSearch() + } + + return r.parseConfig() +} + +func (r *FileReader) parseConfig() error { + if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + return nil + } + + return fmt.Errorf("can't read viper config: %s", err) + } + + usedConfigFile := viper.ConfigFileUsed() + if usedConfigFile == "" { + return nil + } + + usedConfigFile, err := fsutils.ShortestRelPath(usedConfigFile, "") + if err != nil { + r.log.Warnf("Can't pretty print config file path: %s", err) + } + r.log.Infof("Used config file %s", usedConfigFile) + + if err := viper.Unmarshal(r.cfg); err != nil { + return fmt.Errorf("can't unmarshal config by viper: %s", err) + } + + if err := r.validateConfig(); err != nil { + return fmt.Errorf("can't validate config: %s", err) + } + + if r.cfg.InternalTest { // just for testing purposes: to detect config file usage + fmt.Fprintln(logutils.StdOut, "test") + os.Exit(0) + } + + return nil +} + +func (r *FileReader) validateConfig() error { + c := r.cfg + if len(c.Run.Args) != 0 { + return errors.New("option run.args in config isn't supported now") + } + + if c.Run.CPUProfilePath != "" { + return errors.New("option run.cpuprofilepath in config isn't allowed") + } + + if c.Run.MemProfilePath != "" { + return errors.New("option run.memprofilepath in config isn't allowed") + } + + if c.Run.TracePath != "" { + return errors.New("option run.tracepath in config isn't allowed") + } + + if c.Run.IsVerbose { + return errors.New("can't set run.verbose option with config: only on command-line") + } + for i, rule := range c.Issues.ExcludeRules { + if err := rule.Validate(); err != nil { + return fmt.Errorf("error in exclude rule #%d: %v", i, err) + } + } + if err := c.LintersSettings.Govet.Validate(); err != nil { + return fmt.Errorf("error in govet config: %v", err) + } + return nil +} + +func getFirstPathArg() string { + args := os.Args + + // skip all args ([golangci-lint, run/linters]) before files/dirs list + for len(args) != 0 { + if args[0] == "run" { + args = args[1:] + break + } + + args = args[1:] + } + + // find first file/dir arg + firstArg := "./..." + for _, arg := range args { + if !strings.HasPrefix(arg, "-") { + firstArg = arg + break + } + } + + return firstArg +} + +func (r *FileReader) setupConfigFileSearch() { + firstArg := getFirstPathArg() + absStartPath, err := filepath.Abs(firstArg) + if err != nil { + r.log.Warnf("Can't make abs path for %q: %s", firstArg, err) + absStartPath = filepath.Clean(firstArg) + } + + // start from it + var curDir string + if fsutils.IsDir(absStartPath) { + curDir = absStartPath + } else { + curDir = filepath.Dir(absStartPath) + } + + // find all dirs from it up to the root + configSearchPaths := []string{"./"} + for { + configSearchPaths = append(configSearchPaths, curDir) + newCurDir := filepath.Dir(curDir) + if curDir == newCurDir || newCurDir == "" { + break + } + curDir = newCurDir + } + + r.log.Infof("Config search paths: %s", configSearchPaths) + viper.SetConfigName(".golangci") + for _, p := range configSearchPaths { + viper.AddConfigPath(p) + } +} + +var errConfigDisabled = errors.New("config is disabled by --no-config") + +func (r *FileReader) parseConfigOption() (string, error) { + cfg := r.commandLineCfg + if cfg == nil { + return "", nil + } + + configFile := cfg.Run.Config + if cfg.Run.NoConfig && configFile != "" { + return "", fmt.Errorf("can't combine option --config and --no-config") + } + + if cfg.Run.NoConfig { + return "", errConfigDisabled + } + + configFile, err := homedir.Expand(configFile) + if err != nil { + return "", fmt.Errorf("failed to expand configuration path") + } + + return configFile, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/exitcodes/exitcodes.go b/vendor/github.com/golangci/golangci-lint/pkg/exitcodes/exitcodes.go new file mode 100644 index 000000000..536f90361 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/exitcodes/exitcodes.go @@ -0,0 +1,34 @@ +package exitcodes + +const ( + Success = 0 + IssuesFound = 1 + WarningInTest = 2 + Failure = 3 + Timeout = 4 + NoGoFiles = 5 + NoConfigFileDetected = 6 + ErrorWasLogged = 7 +) + +type ExitError struct { + Message string + Code int +} + +func (e ExitError) Error() string { + return e.Message +} + +var ( + ErrNoGoFiles = &ExitError{ + Message: "no go files to analyze", + Code: NoGoFiles, + } + ErrFailure = &ExitError{ + Message: "failed to analyze", + Code: Failure, + } +) + +// 1 diff --git a/vendor/github.com/golangci/golangci-lint/pkg/fsutils/filecache.go b/vendor/github.com/golangci/golangci-lint/pkg/fsutils/filecache.go new file mode 100644 index 000000000..2b17a0398 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/fsutils/filecache.go @@ -0,0 +1,67 @@ +package fsutils + +import ( + "fmt" + "io/ioutil" + "sync" + + "github.com/pkg/errors" + + "github.com/golangci/golangci-lint/pkg/logutils" +) + +type FileCache struct { + files sync.Map +} + +func NewFileCache() *FileCache { + return &FileCache{} +} + +func (fc *FileCache) GetFileBytes(filePath string) ([]byte, error) { + cachedBytes, ok := fc.files.Load(filePath) + if ok { + return cachedBytes.([]byte), nil + } + + fileBytes, err := ioutil.ReadFile(filePath) + if err != nil { + return nil, errors.Wrapf(err, "can't read file %s", filePath) + } + + fc.files.Store(filePath, fileBytes) + return fileBytes, nil +} + +func PrettifyBytesCount(n int64) string { + const ( + Multiplexer = 1024 + KiB = 1 * Multiplexer + MiB = KiB * Multiplexer + GiB = MiB * Multiplexer + ) + + if n >= GiB { + return fmt.Sprintf("%.1fGiB", float64(n)/GiB) + } + if n >= MiB { + return fmt.Sprintf("%.1fMiB", float64(n)/MiB) + } + if n >= KiB { + return fmt.Sprintf("%.1fKiB", float64(n)/KiB) + } + return fmt.Sprintf("%dB", n) +} + +func (fc *FileCache) PrintStats(log logutils.Log) { + var size int64 + var mapLen int + fc.files.Range(func(_, fileBytes interface{}) bool { + mapLen++ + size += int64(len(fileBytes.([]byte))) + + return true + }) + + log.Infof("File cache stats: %d entries of total size %s", mapLen, PrettifyBytesCount(size)) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/fsutils/fsutils.go b/vendor/github.com/golangci/golangci-lint/pkg/fsutils/fsutils.go new file mode 100644 index 000000000..a39c105e4 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/fsutils/fsutils.go @@ -0,0 +1,100 @@ +package fsutils + +import ( + "fmt" + "os" + "path/filepath" + "sync" +) + +func IsDir(filename string) bool { + fi, err := os.Stat(filename) + return err == nil && fi.IsDir() +} + +var cachedWd string +var cachedWdError error +var getWdOnce sync.Once +var useCache = true + +func UseWdCache(use bool) { + useCache = use +} + +func Getwd() (string, error) { + if !useCache { // for tests + return os.Getwd() + } + + getWdOnce.Do(func() { + cachedWd, cachedWdError = os.Getwd() + if cachedWdError != nil { + return + } + + evaledWd, err := EvalSymlinks(cachedWd) + if err != nil { + cachedWd, cachedWdError = "", fmt.Errorf("can't eval symlinks on wd %s: %s", cachedWd, err) + return + } + + cachedWd = evaledWd + }) + + return cachedWd, cachedWdError +} + +var evalSymlinkCache sync.Map + +type evalSymlinkRes struct { + path string + err error +} + +func EvalSymlinks(path string) (string, error) { + r, ok := evalSymlinkCache.Load(path) + if ok { + er := r.(evalSymlinkRes) + return er.path, er.err + } + + var er evalSymlinkRes + er.path, er.err = filepath.EvalSymlinks(path) + evalSymlinkCache.Store(path, er) + + return er.path, er.err +} + +func ShortestRelPath(path, wd string) (string, error) { + if wd == "" { // get it if user don't have cached working dir + var err error + wd, err = Getwd() + if err != nil { + return "", fmt.Errorf("can't get working directory: %s", err) + } + } + + evaledPath, err := EvalSymlinks(path) + if err != nil { + return "", fmt.Errorf("can't eval symlinks for path %s: %s", path, err) + } + path = evaledPath + + // make path absolute and then relative to be able to fix this case: + // we are in /test dir, we want to normalize ../test, and have file file.go in this dir; + // it must have normalized path file.go, not ../test/file.go, + var absPath string + if filepath.IsAbs(path) { + absPath = path + } else { + absPath = filepath.Join(wd, path) + } + + relPath, err := filepath.Rel(wd, absPath) + if err != nil { + return "", fmt.Errorf("can't get relative path for path %s and root %s: %s", + absPath, wd, err) + } + + return relPath, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/fsutils/linecache.go b/vendor/github.com/golangci/golangci-lint/pkg/fsutils/linecache.go new file mode 100644 index 000000000..ab408e7d5 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/fsutils/linecache.go @@ -0,0 +1,70 @@ +package fsutils + +import ( + "bytes" + "fmt" + "sync" + + "github.com/pkg/errors" +) + +type fileLinesCache [][]byte + +type LineCache struct { + files sync.Map + fileCache *FileCache +} + +func NewLineCache(fc *FileCache) *LineCache { + return &LineCache{ + fileCache: fc, + } +} + +// GetLine returns a index1-th (1-based index) line from the file on filePath +func (lc *LineCache) GetLine(filePath string, index1 int) (string, error) { + if index1 == 0 { // some linters, e.g. gosec can do it: it really means first line + index1 = 1 + } + + const index1To0Offset = -1 + rawLine, err := lc.getRawLine(filePath, index1+index1To0Offset) + if err != nil { + return "", err + } + + return string(bytes.Trim(rawLine, "\r")), nil +} + +func (lc *LineCache) getRawLine(filePath string, index0 int) ([]byte, error) { + fc, err := lc.getFileCache(filePath) + if err != nil { + return nil, errors.Wrapf(err, "failed to get file %s lines cache", filePath) + } + + if index0 < 0 { + return nil, fmt.Errorf("invalid file line index0 < 0: %d", index0) + } + + if index0 >= len(fc) { + return nil, fmt.Errorf("invalid file line index0 (%d) >= len(fc) (%d)", index0, len(fc)) + } + + return fc[index0], nil +} + +func (lc *LineCache) getFileCache(filePath string) (fileLinesCache, error) { + loadedFc, ok := lc.files.Load(filePath) + if ok { + return loadedFc.(fileLinesCache), nil + } + + fileBytes, err := lc.fileCache.GetFileBytes(filePath) + if err != nil { + return nil, errors.Wrapf(err, "can't get file %s bytes from cache", filePath) + } + + fc := bytes.Split(fileBytes, []byte("\n")) + lc.files.Store(filePath, fileLinesCache(fc)) + return fc, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/asciicheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/asciicheck.go new file mode 100644 index 000000000..7700c33e7 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/asciicheck.go @@ -0,0 +1,19 @@ +package golinters + +import ( + "github.com/tdakkota/asciicheck" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewAsciicheck() *goanalysis.Linter { + return goanalysis.NewLinter( + "asciicheck", + "Simple linter to check that your code does not contain non-ASCII identifiers", + []*analysis.Analyzer{ + asciicheck.NewAnalyzer(), + }, + nil, + ) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/bodyclose.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/bodyclose.go new file mode 100644 index 000000000..0e03813d1 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/bodyclose.go @@ -0,0 +1,21 @@ +package golinters + +import ( + "github.com/timakin/bodyclose/passes/bodyclose" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewBodyclose() *goanalysis.Linter { + analyzers := []*analysis.Analyzer{ + bodyclose.Analyzer, + } + + return goanalysis.NewLinter( + "bodyclose", + "checks whether HTTP response body is closed successfully", + analyzers, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/deadcode.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/deadcode.go new file mode 100644 index 000000000..6ff38909f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/deadcode.go @@ -0,0 +1,52 @@ +package golinters + +import ( + "fmt" + "sync" + + deadcodeAPI "github.com/golangci/go-misc/deadcode" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewDeadcode() *goanalysis.Linter { + const linterName = "deadcode" + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + Run: func(pass *analysis.Pass) (interface{}, error) { + prog := goanalysis.MakeFakeLoaderProgram(pass) + issues, err := deadcodeAPI.Run(prog) + if err != nil { + return nil, err + } + res := make([]goanalysis.Issue, 0, len(issues)) + for _, i := range issues { + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: i.Pos, + Text: fmt.Sprintf("%s is unused", formatCode(i.UnusedIdentName, nil)), + FromLinter: linterName, + }, pass)) + } + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + }, + } + return goanalysis.NewLinter( + linterName, + "Finds unused code", + []*analysis.Analyzer{analyzer}, + nil, + ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/depguard.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/depguard.go new file mode 100644 index 000000000..3bd854811 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/depguard.go @@ -0,0 +1,112 @@ +package golinters + +import ( + "fmt" + "strings" + "sync" + + "github.com/OpenPeeDeeP/depguard" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/loader" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func setDepguardListType(dg *depguard.Depguard, lintCtx *linter.Context) error { + listType := lintCtx.Settings().Depguard.ListType + var found bool + dg.ListType, found = depguard.StringToListType[strings.ToLower(listType)] + if !found { + if listType != "" { + return fmt.Errorf("unsure what list type %s is", listType) + } + dg.ListType = depguard.LTBlacklist + } + + return nil +} + +func setupDepguardPackages(dg *depguard.Depguard, lintCtx *linter.Context) { + if dg.ListType == depguard.LTBlacklist { + // if the list type was a blacklist the packages with error messages should + // be included in the blacklist package list + + noMessagePackages := make(map[string]bool) + for _, pkg := range dg.Packages { + noMessagePackages[pkg] = true + } + + for pkg := range lintCtx.Settings().Depguard.PackagesWithErrorMessage { + if _, ok := noMessagePackages[pkg]; !ok { + dg.Packages = append(dg.Packages, pkg) + } + } + } +} + +func NewDepguard() *goanalysis.Linter { + const linterName = "depguard" + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + linterName, + "Go linter that checks if package imports are in a list of acceptable packages", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + dgSettings := &lintCtx.Settings().Depguard + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + prog := goanalysis.MakeFakeLoaderProgram(pass) + dg := &depguard.Depguard{ + Packages: dgSettings.Packages, + IncludeGoRoot: dgSettings.IncludeGoRoot, + } + if err := setDepguardListType(dg, lintCtx); err != nil { + return nil, err + } + setupDepguardPackages(dg, lintCtx) + + loadConfig := &loader.Config{ + Cwd: "", // fallbacked to os.Getcwd + Build: nil, // fallbacked to build.Default + } + issues, err := dg.Run(loadConfig, prog) + if err != nil { + return nil, err + } + if len(issues) == 0 { + return nil, nil + } + msgSuffix := "is in the blacklist" + if dg.ListType == depguard.LTWhitelist { + msgSuffix = "is not in the whitelist" + } + res := make([]goanalysis.Issue, 0, len(issues)) + for _, i := range issues { + userSuppliedMsgSuffix := dgSettings.PackagesWithErrorMessage[i.PackageName] + if userSuppliedMsgSuffix != "" { + userSuppliedMsgSuffix = ": " + userSuppliedMsgSuffix + } + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: i.Position, + Text: fmt.Sprintf("%s %s%s", formatCode(i.PackageName, lintCtx.Cfg), msgSuffix, userSuppliedMsgSuffix), + FromLinter: linterName, + }, pass)) + } + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/dogsled.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/dogsled.go new file mode 100644 index 000000000..8978ff913 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/dogsled.go @@ -0,0 +1,97 @@ +package golinters + +import ( + "fmt" + "go/ast" + "go/token" + "sync" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const dogsledLinterName = "dogsled" + +func NewDogsled() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: dogsledLinterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + dogsledLinterName, + "Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var pkgIssues []goanalysis.Issue + for _, f := range pass.Files { + v := returnsVisitor{ + maxBlanks: lintCtx.Settings().Dogsled.MaxBlankIdentifiers, + f: pass.Fset, + } + ast.Walk(&v, f) + for i := range v.issues { + pkgIssues = append(pkgIssues, goanalysis.NewIssue(&v.issues[i], pass)) + } + } + + mu.Lock() + resIssues = append(resIssues, pkgIssues...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} + +type returnsVisitor struct { + f *token.FileSet + maxBlanks int + issues []result.Issue +} + +func (v *returnsVisitor) Visit(node ast.Node) ast.Visitor { + funcDecl, ok := node.(*ast.FuncDecl) + if !ok { + return v + } + if funcDecl.Body == nil { + return v + } + + for _, expr := range funcDecl.Body.List { + assgnStmt, ok := expr.(*ast.AssignStmt) + if !ok { + continue + } + + numBlank := 0 + for _, left := range assgnStmt.Lhs { + ident, ok := left.(*ast.Ident) + if !ok { + continue + } + if ident.Name == "_" { + numBlank++ + } + } + + if numBlank > v.maxBlanks { + v.issues = append(v.issues, result.Issue{ + FromLinter: dogsledLinterName, + Text: fmt.Sprintf("declaration has %v blank identifiers", numBlank), + Pos: v.f.Position(assgnStmt.Pos()), + }) + } + } + return v +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/dupl.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/dupl.go new file mode 100644 index 000000000..ed1c4fcbd --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/dupl.go @@ -0,0 +1,83 @@ +package golinters + +import ( + "fmt" + "go/token" + "sync" + + duplAPI "github.com/golangci/dupl" + "github.com/pkg/errors" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const duplLinterName = "dupl" + +func NewDupl() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: duplLinterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + duplLinterName, + "Tool for code clone detection", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var fileNames []string + for _, f := range pass.Files { + pos := pass.Fset.PositionFor(f.Pos(), false) + fileNames = append(fileNames, pos.Filename) + } + + issues, err := duplAPI.Run(fileNames, lintCtx.Settings().Dupl.Threshold) + if err != nil { + return nil, err + } + + if len(issues) == 0 { + return nil, nil + } + + res := make([]goanalysis.Issue, 0, len(issues)) + for _, i := range issues { + toFilename, err := fsutils.ShortestRelPath(i.To.Filename(), "") + if err != nil { + return nil, errors.Wrapf(err, "failed to get shortest rel path for %q", i.To.Filename()) + } + dupl := fmt.Sprintf("%s:%d-%d", toFilename, i.To.LineStart(), i.To.LineEnd()) + text := fmt.Sprintf("%d-%d lines are duplicate of %s", + i.From.LineStart(), i.From.LineEnd(), + formatCode(dupl, lintCtx.Cfg)) + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: token.Position{ + Filename: i.From.Filename(), + Line: i.From.LineStart(), + }, + LineRange: &result.Range{ + From: i.From.LineStart(), + To: i.From.LineEnd(), + }, + Text: text, + FromLinter: duplLinterName, + }, pass)) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/errcheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/errcheck.go new file mode 100644 index 000000000..7df11fc87 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/errcheck.go @@ -0,0 +1,217 @@ +package golinters + +import ( + "bufio" + "fmt" + "os" + "os/user" + "path/filepath" + "regexp" + "strings" + "sync" + + errcheck "github.com/golangci/errcheck/golangci" + "github.com/pkg/errors" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewErrcheck() *goanalysis.Linter { + const linterName = "errcheck" + var mu sync.Mutex + var res []goanalysis.Issue + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + linterName, + "Errcheck is a program for checking for unchecked errors "+ + "in go programs. These unchecked errors can be critical bugs in some cases", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + prog := goanalysis.MakeFakeLoaderProgram(pass) + errCfg, err := genConfig(&lintCtx.Settings().Errcheck) + if err != nil { + return nil, err + } + errcheckIssues, err := errcheck.RunWithConfig(prog, errCfg) + if err != nil { + return nil, err + } + + if len(errcheckIssues) == 0 { + return nil, nil + } + + issues := make([]goanalysis.Issue, 0, len(errcheckIssues)) + for _, i := range errcheckIssues { + var text string + if i.FuncName != "" { + text = fmt.Sprintf("Error return value of %s is not checked", formatCode(i.FuncName, lintCtx.Cfg)) + } else { + text = "Error return value is not checked" + } + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + FromLinter: linterName, + Text: text, + Pos: i.Pos, + }, pass)) + } + mu.Lock() + res = append(res, issues...) + mu.Unlock() + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return res + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} + +// parseIgnoreConfig was taken from errcheck in order to keep the API identical. +// https://github.com/kisielk/errcheck/blob/1787c4bee836470bf45018cfbc783650db3c6501/main.go#L25-L60 +func parseIgnoreConfig(s string) (map[string]*regexp.Regexp, error) { + if s == "" { + return nil, nil + } + + cfg := map[string]*regexp.Regexp{} + + for _, pair := range strings.Split(s, ",") { + colonIndex := strings.Index(pair, ":") + var pkg, re string + if colonIndex == -1 { + pkg = "" + re = pair + } else { + pkg = pair[:colonIndex] + re = pair[colonIndex+1:] + } + regex, err := regexp.Compile(re) + if err != nil { + return nil, err + } + cfg[pkg] = regex + } + + return cfg, nil +} + +func genConfig(errCfg *config.ErrcheckSettings) (*errcheck.Config, error) { + ignoreConfig, err := parseIgnoreConfig(errCfg.Ignore) + if err != nil { + return nil, errors.Wrap(err, "failed to parse 'ignore' directive") + } + + c := &errcheck.Config{ + Ignore: ignoreConfig, + Blank: errCfg.CheckAssignToBlank, + Asserts: errCfg.CheckTypeAssertions, + } + + if errCfg.Exclude != "" { + exclude, err := readExcludeFile(errCfg.Exclude) + if err != nil { + return nil, err + } + c.Exclude = exclude + } + + return c, nil +} + +func getFirstPathArg() string { + args := os.Args + + // skip all args ([golangci-lint, run/linters]) before files/dirs list + for len(args) != 0 { + if args[0] == "run" { + args = args[1:] + break + } + + args = args[1:] + } + + // find first file/dir arg + firstArg := "./..." + for _, arg := range args { + if !strings.HasPrefix(arg, "-") { + firstArg = arg + break + } + } + + return firstArg +} + +func setupConfigFileSearch(name string) []string { + if strings.HasPrefix(name, "~") { + if u, err := user.Current(); err == nil { + name = strings.Replace(name, "~", u.HomeDir, 1) + } + } + + if filepath.IsAbs(name) { + return []string{name} + } + + firstArg := getFirstPathArg() + + absStartPath, err := filepath.Abs(firstArg) + if err != nil { + absStartPath = filepath.Clean(firstArg) + } + + // start from it + var curDir string + if fsutils.IsDir(absStartPath) { + curDir = absStartPath + } else { + curDir = filepath.Dir(absStartPath) + } + + // find all dirs from it up to the root + configSearchPaths := []string{filepath.Join(".", name)} + for { + configSearchPaths = append(configSearchPaths, filepath.Join(curDir, name)) + newCurDir := filepath.Dir(curDir) + if curDir == newCurDir || newCurDir == "" { + break + } + curDir = newCurDir + } + + return configSearchPaths +} + +func readExcludeFile(name string) (map[string]bool, error) { + var err error + var fh *os.File + + for _, path := range setupConfigFileSearch(name) { + if fh, err = os.Open(path); err == nil { + break + } + } + + if fh == nil { + return nil, errors.Wrapf(err, "failed reading exclude file: %s", name) + } + scanner := bufio.NewScanner(fh) + exclude := make(map[string]bool) + for scanner.Scan() { + exclude[scanner.Text()] = true + } + if err := scanner.Err(); err != nil { + return nil, errors.Wrapf(err, "failed scanning file: %s", name) + } + return exclude, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/funlen.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/funlen.go new file mode 100644 index 000000000..29cb6b7ef --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/funlen.go @@ -0,0 +1,64 @@ +package golinters + +import ( + "go/token" + "strings" + "sync" + + "github.com/ultraware/funlen" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const funlenLinterName = "funlen" + +func NewFunlen() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: funlenLinterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + funlenLinterName, + "Tool for detection of long functions", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var issues []funlen.Message + for _, file := range pass.Files { + fileIssues := funlen.Run(file, pass.Fset, lintCtx.Settings().Funlen.Lines, lintCtx.Settings().Funlen.Statements) + issues = append(issues, fileIssues...) + } + + if len(issues) == 0 { + return nil, nil + } + + res := make([]goanalysis.Issue, len(issues)) + for k, i := range issues { + res[k] = goanalysis.NewIssue(&result.Issue{ + Pos: token.Position{ + Filename: i.Pos.Filename, + Line: i.Pos.Line, + }, + Text: strings.TrimRight(i.Message, "\n"), + FromLinter: funlenLinterName, + }, pass) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/adapters.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/adapters.go new file mode 100644 index 000000000..830c4d882 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/adapters.go @@ -0,0 +1,36 @@ +package goanalysis + +import ( + "go/types" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/loader" +) + +func MakeFakeLoaderProgram(pass *analysis.Pass) *loader.Program { + prog := &loader.Program{ + Fset: pass.Fset, + Created: []*loader.PackageInfo{ + { + Pkg: pass.Pkg, + Importable: true, // not used + TransitivelyErrorFree: true, // TODO + + Files: pass.Files, + Errors: nil, + Info: *pass.TypesInfo, + }, + }, + AllPackages: map[*types.Package]*loader.PackageInfo{ + pass.Pkg: { + Pkg: pass.Pkg, + Importable: true, + TransitivelyErrorFree: true, + Files: pass.Files, + Errors: nil, + Info: *pass.TypesInfo, + }, + }, + } + return prog +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/issue.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/issue.go new file mode 100644 index 000000000..f331a3ab9 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/issue.go @@ -0,0 +1,31 @@ +package goanalysis + +import ( + "go/token" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/result" +) + +type Issue struct { + result.Issue + Pass *analysis.Pass +} + +func NewIssue(i *result.Issue, pass *analysis.Pass) Issue { + return Issue{ + Issue: *i, + Pass: pass, + } +} + +type EncodingIssue struct { + FromLinter string + Text string + Pos token.Position + LineRange *result.Range + Replacement *result.Replacement + ExpectNoLint bool + ExpectedNoLintLinter string +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/linter.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/linter.go new file mode 100644 index 000000000..f1cfcca83 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/linter.go @@ -0,0 +1,519 @@ +package goanalysis + +import ( + "context" + "flag" + "fmt" + "runtime" + "sort" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/pkg/errors" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/packages" + + "github.com/golangci/golangci-lint/internal/pkgcache" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" + libpackages "github.com/golangci/golangci-lint/pkg/packages" + "github.com/golangci/golangci-lint/pkg/result" + "github.com/golangci/golangci-lint/pkg/timeutils" +) + +const ( + TheOnlyAnalyzerName = "the_only_name" + TheOnlyanalyzerDoc = "the_only_doc" +) + +type LoadMode int + +const ( + LoadModeNone LoadMode = iota + LoadModeSyntax + LoadModeTypesInfo + LoadModeWholeProgram +) + +var issuesCacheDebugf = logutils.Debug("goanalysis/issues/cache") + +func (loadMode LoadMode) String() string { + switch loadMode { + case LoadModeNone: + return "none" + case LoadModeSyntax: + return "syntax" + case LoadModeTypesInfo: + return "types info" + case LoadModeWholeProgram: + return "whole program" + } + panic(fmt.Sprintf("unknown load mode %d", loadMode)) +} + +type Linter struct { + name, desc string + analyzers []*analysis.Analyzer + cfg map[string]map[string]interface{} + issuesReporter func(*linter.Context) []Issue + contextSetter func(*linter.Context) + loadMode LoadMode + needUseOriginalPackages bool + isTypecheckModeOn bool +} + +func NewLinter(name, desc string, analyzers []*analysis.Analyzer, cfg map[string]map[string]interface{}) *Linter { + return &Linter{name: name, desc: desc, analyzers: analyzers, cfg: cfg} +} + +func (lnt *Linter) UseOriginalPackages() { + lnt.needUseOriginalPackages = true +} + +func (lnt *Linter) SetTypecheckMode() { + lnt.isTypecheckModeOn = true +} + +func (lnt *Linter) LoadMode() LoadMode { + return lnt.loadMode +} + +func (lnt *Linter) WithLoadMode(loadMode LoadMode) *Linter { + lnt.loadMode = loadMode + return lnt +} + +func (lnt *Linter) WithIssuesReporter(r func(*linter.Context) []Issue) *Linter { + lnt.issuesReporter = r + return lnt +} + +func (lnt *Linter) WithContextSetter(cs func(*linter.Context)) *Linter { + lnt.contextSetter = cs + return lnt +} + +func (lnt *Linter) Name() string { + return lnt.name +} + +func (lnt *Linter) Desc() string { + return lnt.desc +} + +func (lnt *Linter) allAnalyzerNames() []string { + var ret []string + for _, a := range lnt.analyzers { + ret = append(ret, a.Name) + } + return ret +} + +func allFlagNames(fs *flag.FlagSet) []string { + var ret []string + fs.VisitAll(func(f *flag.Flag) { + ret = append(ret, f.Name) + }) + return ret +} + +func valueToString(v interface{}) string { + if ss, ok := v.([]string); ok { + return strings.Join(ss, ",") + } + + if is, ok := v.([]interface{}); ok { + var ss []string + for _, i := range is { + ss = append(ss, fmt.Sprint(i)) + } + return valueToString(ss) + } + + return fmt.Sprint(v) +} + +func (lnt *Linter) configureAnalyzer(a *analysis.Analyzer, cfg map[string]interface{}) error { + for k, v := range cfg { + f := a.Flags.Lookup(k) + if f == nil { + validFlagNames := allFlagNames(&a.Flags) + if len(validFlagNames) == 0 { + return fmt.Errorf("analyzer doesn't have settings") + } + + return fmt.Errorf("analyzer doesn't have setting %q, valid settings: %v", + k, validFlagNames) + } + + if err := f.Value.Set(valueToString(v)); err != nil { + return errors.Wrapf(err, "failed to set analyzer setting %q with value %v", k, v) + } + } + + return nil +} + +func (lnt *Linter) configure() error { + analyzersMap := map[string]*analysis.Analyzer{} + for _, a := range lnt.analyzers { + analyzersMap[a.Name] = a + } + + for analyzerName, analyzerSettings := range lnt.cfg { + a := analyzersMap[analyzerName] + if a == nil { + return fmt.Errorf("settings key %q must be valid analyzer name, valid analyzers: %v", + analyzerName, lnt.allAnalyzerNames()) + } + + if err := lnt.configureAnalyzer(a, analyzerSettings); err != nil { + return errors.Wrapf(err, "failed to configure analyzer %s", analyzerName) + } + } + + return nil +} + +func parseError(srcErr packages.Error) (*result.Issue, error) { + pos, err := libpackages.ParseErrorPosition(srcErr.Pos) + if err != nil { + return nil, err + } + + return &result.Issue{ + Pos: *pos, + Text: srcErr.Msg, + FromLinter: "typecheck", + }, nil +} + +func buildIssuesFromErrorsForTypecheckMode(errs []error, lintCtx *linter.Context) ([]result.Issue, error) { + var issues []result.Issue + uniqReportedIssues := map[string]bool{} + for _, err := range errs { + itErr, ok := errors.Cause(err).(*IllTypedError) + if !ok { + return nil, err + } + for _, err := range libpackages.ExtractErrors(itErr.Pkg) { + i, perr := parseError(err) + if perr != nil { // failed to parse + if uniqReportedIssues[err.Msg] { + continue + } + uniqReportedIssues[err.Msg] = true + lintCtx.Log.Errorf("typechecking error: %s", err.Msg) + } else { + i.Pkg = itErr.Pkg // to save to cache later + issues = append(issues, *i) + } + } + } + return issues, nil +} + +func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) string) []result.Issue { + var issues []result.Issue + for i := range diags { + diag := &diags[i] + linterName := linterNameBuilder(diag) + var text string + if diag.Analyzer.Name == linterName { + text = diag.Message + } else { + text = fmt.Sprintf("%s: %s", diag.Analyzer.Name, diag.Message) + } + issues = append(issues, result.Issue{ + FromLinter: linterName, + Text: text, + Pos: diag.Position, + Pkg: diag.Pkg, + }) + } + return issues +} + +func (lnt *Linter) preRun(lintCtx *linter.Context) error { + if err := analysis.Validate(lnt.analyzers); err != nil { + return errors.Wrap(err, "failed to validate analyzers") + } + + if err := lnt.configure(); err != nil { + return errors.Wrap(err, "failed to configure analyzers") + } + + if lnt.contextSetter != nil { + lnt.contextSetter(lintCtx) + } + + return nil +} + +func (lnt *Linter) getName() string { + return lnt.name +} + +func (lnt *Linter) getLinterNameForDiagnostic(*Diagnostic) string { + return lnt.name +} + +func (lnt *Linter) getAnalyzers() []*analysis.Analyzer { + return lnt.analyzers +} + +func (lnt *Linter) useOriginalPackages() bool { + return lnt.needUseOriginalPackages +} + +func (lnt *Linter) isTypecheckMode() bool { + return lnt.isTypecheckModeOn +} + +func (lnt *Linter) reportIssues(lintCtx *linter.Context) []Issue { + if lnt.issuesReporter != nil { + return lnt.issuesReporter(lintCtx) + } + return nil +} + +func (lnt *Linter) getLoadMode() LoadMode { + return lnt.loadMode +} + +type runAnalyzersConfig interface { + getName() string + getLinterNameForDiagnostic(*Diagnostic) string + getAnalyzers() []*analysis.Analyzer + useOriginalPackages() bool + isTypecheckMode() bool + reportIssues(*linter.Context) []Issue + getLoadMode() LoadMode +} + +func getIssuesCacheKey(analyzers []*analysis.Analyzer) string { + return "lint/result:" + analyzersHashID(analyzers) +} + +func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages.Package]bool, + issues []result.Issue, lintCtx *linter.Context, analyzers []*analysis.Analyzer) { + startedAt := time.Now() + perPkgIssues := map[*packages.Package][]result.Issue{} + for ind := range issues { + i := &issues[ind] + perPkgIssues[i.Pkg] = append(perPkgIssues[i.Pkg], *i) + } + + savedIssuesCount := int32(0) + lintResKey := getIssuesCacheKey(analyzers) + + workerCount := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + wg.Add(workerCount) + + pkgCh := make(chan *packages.Package, len(allPkgs)) + for i := 0; i < workerCount; i++ { + go func() { + defer wg.Done() + for pkg := range pkgCh { + pkgIssues := perPkgIssues[pkg] + encodedIssues := make([]EncodingIssue, 0, len(pkgIssues)) + for ind := range pkgIssues { + i := &pkgIssues[ind] + encodedIssues = append(encodedIssues, EncodingIssue{ + FromLinter: i.FromLinter, + Text: i.Text, + Pos: i.Pos, + LineRange: i.LineRange, + Replacement: i.Replacement, + ExpectNoLint: i.ExpectNoLint, + ExpectedNoLintLinter: i.ExpectedNoLintLinter, + }) + } + + atomic.AddInt32(&savedIssuesCount, int32(len(encodedIssues))) + if err := lintCtx.PkgCache.Put(pkg, pkgcache.HashModeNeedAllDeps, lintResKey, encodedIssues); err != nil { + lintCtx.Log.Infof("Failed to save package %s issues (%d) to cache: %s", pkg, len(pkgIssues), err) + } else { + issuesCacheDebugf("Saved package %s issues (%d) to cache", pkg, len(pkgIssues)) + } + } + }() + } + + for _, pkg := range allPkgs { + if pkgsFromCache[pkg] { + continue + } + + pkgCh <- pkg + } + close(pkgCh) + wg.Wait() + + issuesCacheDebugf("Saved %d issues from %d packages to cache in %s", savedIssuesCount, len(allPkgs), time.Since(startedAt)) +} + +//nolint:gocritic +func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context, + analyzers []*analysis.Analyzer) ([]result.Issue, map[*packages.Package]bool) { + startedAt := time.Now() + + lintResKey := getIssuesCacheKey(analyzers) + type cacheRes struct { + issues []result.Issue + loadErr error + } + pkgToCacheRes := make(map[*packages.Package]*cacheRes, len(pkgs)) + for _, pkg := range pkgs { + pkgToCacheRes[pkg] = &cacheRes{} + } + + workerCount := runtime.GOMAXPROCS(-1) + var wg sync.WaitGroup + wg.Add(workerCount) + + pkgCh := make(chan *packages.Package, len(pkgs)) + for i := 0; i < workerCount; i++ { + go func() { + defer wg.Done() + for pkg := range pkgCh { + var pkgIssues []EncodingIssue + err := lintCtx.PkgCache.Get(pkg, pkgcache.HashModeNeedAllDeps, lintResKey, &pkgIssues) + cacheRes := pkgToCacheRes[pkg] + cacheRes.loadErr = err + if err != nil { + continue + } + if len(pkgIssues) == 0 { + continue + } + + issues := make([]result.Issue, 0, len(pkgIssues)) + for _, i := range pkgIssues { + issues = append(issues, result.Issue{ + FromLinter: i.FromLinter, + Text: i.Text, + Pos: i.Pos, + LineRange: i.LineRange, + Replacement: i.Replacement, + Pkg: pkg, + ExpectNoLint: i.ExpectNoLint, + ExpectedNoLintLinter: i.ExpectedNoLintLinter, + }) + } + cacheRes.issues = issues + } + }() + } + + for _, pkg := range pkgs { + pkgCh <- pkg + } + close(pkgCh) + wg.Wait() + + loadedIssuesCount := 0 + var issues []result.Issue + pkgsFromCache := map[*packages.Package]bool{} + for pkg, cacheRes := range pkgToCacheRes { + if cacheRes.loadErr == nil { + loadedIssuesCount += len(cacheRes.issues) + pkgsFromCache[pkg] = true + issues = append(issues, cacheRes.issues...) + issuesCacheDebugf("Loaded package %s issues (%d) from cache", pkg, len(cacheRes.issues)) + } else { + issuesCacheDebugf("Didn't load package %s issues from cache: %s", pkg, cacheRes.loadErr) + } + } + issuesCacheDebugf("Loaded %d issues from cache in %s, analyzing %d/%d packages", + loadedIssuesCount, time.Since(startedAt), len(pkgs)-len(pkgsFromCache), len(pkgs)) + return issues, pkgsFromCache +} + +func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Issue, error) { + log := lintCtx.Log.Child("goanalysis") + sw := timeutils.NewStopwatch("analyzers", log) + + const stagesToPrint = 10 + defer sw.PrintTopStages(stagesToPrint) + + runner := newRunner(cfg.getName(), log, lintCtx.PkgCache, lintCtx.LoadGuard, cfg.getLoadMode(), sw) + + pkgs := lintCtx.Packages + if cfg.useOriginalPackages() { + pkgs = lintCtx.OriginalPackages + } + + issues, pkgsFromCache := loadIssuesFromCache(pkgs, lintCtx, cfg.getAnalyzers()) + var pkgsToAnalyze []*packages.Package + for _, pkg := range pkgs { + if !pkgsFromCache[pkg] { + pkgsToAnalyze = append(pkgsToAnalyze, pkg) + } + } + + diags, errs, passToPkg := runner.run(cfg.getAnalyzers(), pkgsToAnalyze) + + defer func() { + if len(errs) == 0 { + // If we try to save to cache even if we have compilation errors + // we won't see them on repeated runs. + saveIssuesToCache(pkgs, pkgsFromCache, issues, lintCtx, cfg.getAnalyzers()) + } + }() + + buildAllIssues := func() []result.Issue { + var retIssues []result.Issue + reportedIssues := cfg.reportIssues(lintCtx) + for i := range reportedIssues { + issue := &reportedIssues[i].Issue + if issue.Pkg == nil { + issue.Pkg = passToPkg[reportedIssues[i].Pass] + } + retIssues = append(retIssues, *issue) + } + retIssues = append(retIssues, buildIssues(diags, cfg.getLinterNameForDiagnostic)...) + return retIssues + } + + if cfg.isTypecheckMode() { + errIssues, err := buildIssuesFromErrorsForTypecheckMode(errs, lintCtx) + if err != nil { + return nil, err + } + + issues = append(issues, errIssues...) + issues = append(issues, buildAllIssues()...) + + return issues, nil + } + + // Don't print all errs: they can duplicate. + if len(errs) != 0 { + return nil, errs[0] + } + + issues = append(issues, buildAllIssues()...) + return issues, nil +} + +func (lnt *Linter) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) { + if err := lnt.preRun(lintCtx); err != nil { + return nil, err + } + + return runAnalyzers(lnt, lintCtx) +} + +func analyzersHashID(analyzers []*analysis.Analyzer) string { + names := make([]string, 0, len(analyzers)) + for _, a := range analyzers { + names = append(names, a.Name) + } + + sort.Strings(names) + return strings.Join(names, ",") +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load/guard.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load/guard.go new file mode 100644 index 000000000..ab7775cc8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load/guard.go @@ -0,0 +1,30 @@ +package load + +import ( + "sync" + + "golang.org/x/tools/go/packages" +) + +type Guard struct { + loadMutexes map[*packages.Package]*sync.Mutex + mutex sync.Mutex +} + +func NewGuard() *Guard { + return &Guard{ + loadMutexes: map[*packages.Package]*sync.Mutex{}, + } +} + +func (g *Guard) AddMutexForPkg(pkg *packages.Package) { + g.loadMutexes[pkg] = &sync.Mutex{} +} + +func (g *Guard) MutexForPkg(pkg *packages.Package) *sync.Mutex { + return g.loadMutexes[pkg] +} + +func (g *Guard) Mutex() *sync.Mutex { + return &g.mutex +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/metalinter.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/metalinter.go new file mode 100644 index 000000000..5975e2057 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/metalinter.go @@ -0,0 +1,99 @@ +package goanalysis + +import ( + "context" + + "github.com/pkg/errors" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +type MetaLinter struct { + linters []*Linter + analyzerToLinterName map[*analysis.Analyzer]string +} + +func NewMetaLinter(linters []*Linter) *MetaLinter { + ml := &MetaLinter{linters: linters} + ml.analyzerToLinterName = ml.getAnalyzerToLinterNameMapping() + return ml +} + +func (ml MetaLinter) Name() string { + return "goanalysis_metalinter" +} + +func (ml MetaLinter) Desc() string { + return "" +} + +func (ml MetaLinter) isTypecheckMode() bool { + for _, linter := range ml.linters { + if linter.isTypecheckMode() { + return true + } + } + return false +} + +func (ml MetaLinter) getLoadMode() LoadMode { + loadMode := LoadModeNone + for _, linter := range ml.linters { + if linter.loadMode > loadMode { + loadMode = linter.loadMode + } + } + return loadMode +} + +func (ml MetaLinter) getAnalyzers() []*analysis.Analyzer { + var allAnalyzers []*analysis.Analyzer + for _, linter := range ml.linters { + allAnalyzers = append(allAnalyzers, linter.analyzers...) + } + return allAnalyzers +} + +func (ml MetaLinter) getName() string { + return "metalinter" +} + +func (ml MetaLinter) useOriginalPackages() bool { + return false // `unused` can't be run by this metalinter +} + +func (ml MetaLinter) reportIssues(lintCtx *linter.Context) []Issue { + var ret []Issue + for _, lnt := range ml.linters { + if lnt.issuesReporter != nil { + ret = append(ret, lnt.issuesReporter(lintCtx)...) + } + } + return ret +} + +func (ml MetaLinter) getLinterNameForDiagnostic(diag *Diagnostic) string { + return ml.analyzerToLinterName[diag.Analyzer] +} + +func (ml MetaLinter) getAnalyzerToLinterNameMapping() map[*analysis.Analyzer]string { + analyzerToLinterName := map[*analysis.Analyzer]string{} + for _, linter := range ml.linters { + for _, a := range linter.analyzers { + analyzerToLinterName[a] = linter.Name() + } + } + return analyzerToLinterName +} + +func (ml MetaLinter) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) { + for _, linter := range ml.linters { + if err := linter.preRun(lintCtx); err != nil { + return nil, errors.Wrapf(err, "failed to pre-run %s", linter.Name()) + } + } + + return runAnalyzers(ml, lintCtx) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner.go new file mode 100644 index 000000000..d07294245 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner.go @@ -0,0 +1,1363 @@ +// checker is a partial copy of https://github.com/golang/tools/blob/master/go/analysis/internal/checker +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package checker defines the implementation of the checker commands. +// The same code drives the multi-analysis driver, the single-analysis +// driver that is conventionally provided for convenience along with +// each analysis package, and the test driver. +package goanalysis + +import ( + "bytes" + "encoding/gob" + "fmt" + "go/ast" + "go/parser" + "go/scanner" + "go/token" + "go/types" + "os" + "reflect" + "runtime" + "runtime/debug" + "sort" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/pkg/errors" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/gcexportdata" + "golang.org/x/tools/go/packages" + "golang.org/x/tools/go/types/objectpath" + + "github.com/golangci/golangci-lint/internal/errorutil" + "github.com/golangci/golangci-lint/internal/pkgcache" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/timeutils" +) + +var ( + // Debug is a set of single-letter flags: + // + // f show [f]acts as they are created + // p disable [p]arallel execution of analyzers + // s do additional [s]anity checks on fact types and serialization + // t show [t]iming info (NB: use 'p' flag to avoid GC/scheduler noise) + // v show [v]erbose logging + // + + debugf = logutils.Debug("goanalysis") + factsDebugf = logutils.Debug("goanalysis/facts") + factsInheritDebugf = logutils.Debug("goanalysis/facts/inherit") + factsExportDebugf = logutils.Debug("goanalysis/facts") + isFactsExportDebug = logutils.HaveDebugTag("goanalysis/facts/export") + isMemoryDebug = logutils.HaveDebugTag("goanalysis/memory") + + factsCacheDebugf = logutils.Debug("goanalysis/facts/cache") + analyzeDebugf = logutils.Debug("goanalysis/analyze") + + Debug = os.Getenv("GL_GOANALYSIS_DEBUG") + + unsafePkgName = "unsafe" +) + +type Diagnostic struct { + analysis.Diagnostic + Analyzer *analysis.Analyzer + Position token.Position + Pkg *packages.Package +} + +type runner struct { + log logutils.Log + prefix string // ensure unique analyzer names + pkgCache *pkgcache.Cache + loadGuard *load.Guard + loadMode LoadMode + passToPkg map[*analysis.Pass]*packages.Package + passToPkgGuard sync.Mutex + sw *timeutils.Stopwatch +} + +func newRunner(prefix string, logger logutils.Log, pkgCache *pkgcache.Cache, loadGuard *load.Guard, + loadMode LoadMode, sw *timeutils.Stopwatch) *runner { + return &runner{ + prefix: prefix, + log: logger, + pkgCache: pkgCache, + loadGuard: loadGuard, + loadMode: loadMode, + passToPkg: map[*analysis.Pass]*packages.Package{}, + sw: sw, + } +} + +// Run loads the packages specified by args using go/packages, +// then applies the specified analyzers to them. +// Analysis flags must already have been set. +// It provides most of the logic for the main functions of both the +// singlechecker and the multi-analysis commands. +// It returns the appropriate exit code. +func (r *runner) run(analyzers []*analysis.Analyzer, initialPackages []*packages.Package) ([]Diagnostic, + []error, map[*analysis.Pass]*packages.Package) { + debugf("Analyzing %d packages on load mode %s", len(initialPackages), r.loadMode) + defer r.pkgCache.Trim() + + roots := r.analyze(initialPackages, analyzers) + diags, errs := extractDiagnostics(roots) + return diags, errs, r.passToPkg +} + +type actKey struct { + *analysis.Analyzer + *packages.Package +} + +func (r *runner) markAllActions(a *analysis.Analyzer, pkg *packages.Package, markedActions map[actKey]struct{}) { + k := actKey{a, pkg} + if _, ok := markedActions[k]; ok { + return + } + + for _, req := range a.Requires { + r.markAllActions(req, pkg, markedActions) + } + + if len(a.FactTypes) != 0 { + for path := range pkg.Imports { + r.markAllActions(a, pkg.Imports[path], markedActions) + } + } + + markedActions[k] = struct{}{} +} + +func (r *runner) makeAction(a *analysis.Analyzer, pkg *packages.Package, + initialPkgs map[*packages.Package]bool, actions map[actKey]*action, actAlloc *actionAllocator) *action { + k := actKey{a, pkg} + act, ok := actions[k] + if ok { + return act + } + + act = actAlloc.alloc() + act.a = a + act.pkg = pkg + act.r = r + act.isInitialPkg = initialPkgs[pkg] + act.needAnalyzeSource = initialPkgs[pkg] + act.analysisDoneCh = make(chan struct{}) + + depsCount := len(a.Requires) + if len(a.FactTypes) > 0 { + depsCount += len(pkg.Imports) + } + act.deps = make([]*action, 0, depsCount) + + // Add a dependency on each required analyzers. + for _, req := range a.Requires { + act.deps = append(act.deps, r.makeAction(req, pkg, initialPkgs, actions, actAlloc)) + } + + r.buildActionFactDeps(act, a, pkg, initialPkgs, actions, actAlloc) + + actions[k] = act + return act +} + +func (r *runner) buildActionFactDeps(act *action, a *analysis.Analyzer, pkg *packages.Package, + initialPkgs map[*packages.Package]bool, actions map[actKey]*action, actAlloc *actionAllocator) { + // An analysis that consumes/produces facts + // must run on the package's dependencies too. + if len(a.FactTypes) == 0 { + return + } + + act.objectFacts = make(map[objectFactKey]analysis.Fact) + act.packageFacts = make(map[packageFactKey]analysis.Fact) + + paths := make([]string, 0, len(pkg.Imports)) + for path := range pkg.Imports { + paths = append(paths, path) + } + sort.Strings(paths) // for determinism + for _, path := range paths { + dep := r.makeAction(a, pkg.Imports[path], initialPkgs, actions, actAlloc) + act.deps = append(act.deps, dep) + } + + // Need to register fact types for pkgcache proper gob encoding. + for _, f := range a.FactTypes { + gob.Register(f) + } +} + +type actionAllocator struct { + allocatedActions []action + nextFreeIndex int +} + +func newActionAllocator(maxCount int) *actionAllocator { + return &actionAllocator{ + allocatedActions: make([]action, maxCount), + nextFreeIndex: 0, + } +} + +func (actAlloc *actionAllocator) alloc() *action { + if actAlloc.nextFreeIndex == len(actAlloc.allocatedActions) { + panic(fmt.Sprintf("Made too many allocations of actions: %d allowed", len(actAlloc.allocatedActions))) + } + act := &actAlloc.allocatedActions[actAlloc.nextFreeIndex] + actAlloc.nextFreeIndex++ + return act +} + +//nolint:gocritic +func (r *runner) prepareAnalysis(pkgs []*packages.Package, + analyzers []*analysis.Analyzer) (map[*packages.Package]bool, []*action, []*action) { + // Construct the action graph. + + // Each graph node (action) is one unit of analysis. + // Edges express package-to-package (vertical) dependencies, + // and analysis-to-analysis (horizontal) dependencies. + + // This place is memory-intensive: e.g. Istio project has 120k total actions. + // Therefore optimize it carefully. + markedActions := make(map[actKey]struct{}, len(analyzers)*len(pkgs)) + for _, a := range analyzers { + for _, pkg := range pkgs { + r.markAllActions(a, pkg, markedActions) + } + } + totalActionsCount := len(markedActions) + + actions := make(map[actKey]*action, totalActionsCount) + actAlloc := newActionAllocator(totalActionsCount) + + initialPkgs := make(map[*packages.Package]bool, len(pkgs)) + for _, pkg := range pkgs { + initialPkgs[pkg] = true + } + + // Build nodes for initial packages. + roots := make([]*action, 0, len(pkgs)*len(analyzers)) + for _, a := range analyzers { + for _, pkg := range pkgs { + root := r.makeAction(a, pkg, initialPkgs, actions, actAlloc) + root.isroot = true + roots = append(roots, root) + } + } + + allActions := make([]*action, 0, len(actions)) + for _, act := range actions { + allActions = append(allActions, act) + } + + debugf("Built %d actions", len(actions)) + + return initialPkgs, allActions, roots +} + +func (r *runner) analyze(pkgs []*packages.Package, analyzers []*analysis.Analyzer) []*action { + initialPkgs, actions, rootActions := r.prepareAnalysis(pkgs, analyzers) + + actionPerPkg := map[*packages.Package][]*action{} + for _, act := range actions { + actionPerPkg[act.pkg] = append(actionPerPkg[act.pkg], act) + } + + // Fill Imports field. + loadingPackages := map[*packages.Package]*loadingPackage{} + var dfs func(pkg *packages.Package) + dfs = func(pkg *packages.Package) { + if loadingPackages[pkg] != nil { + return + } + + imports := map[string]*loadingPackage{} + for impPath, imp := range pkg.Imports { + dfs(imp) + impLp := loadingPackages[imp] + impLp.dependents++ + imports[impPath] = impLp + } + + loadingPackages[pkg] = &loadingPackage{ + pkg: pkg, + imports: imports, + isInitial: initialPkgs[pkg], + log: r.log, + actions: actionPerPkg[pkg], + loadGuard: r.loadGuard, + dependents: 1, // self dependent + } + } + for _, act := range actions { + dfs(act.pkg) + } + + // Limit memory and IO usage. + gomaxprocs := runtime.GOMAXPROCS(-1) + debugf("Analyzing at most %d packages in parallel", gomaxprocs) + loadSem := make(chan struct{}, gomaxprocs) + + var wg sync.WaitGroup + debugf("There are %d initial and %d total packages", len(initialPkgs), len(loadingPackages)) + for _, lp := range loadingPackages { + if lp.isInitial { + wg.Add(1) + go func(lp *loadingPackage) { + lp.analyzeRecursive(r.loadMode, loadSem) + wg.Done() + }(lp) + } + } + wg.Wait() + + return rootActions +} + +//nolint:nakedret +func extractDiagnostics(roots []*action) (retDiags []Diagnostic, retErrors []error) { + extracted := make(map[*action]bool) + var extract func(*action) + var visitAll func(actions []*action) + visitAll = func(actions []*action) { + for _, act := range actions { + if !extracted[act] { + extracted[act] = true + visitAll(act.deps) + extract(act) + } + } + } + + // De-duplicate diagnostics by position (not token.Pos) to + // avoid double-reporting in source files that belong to + // multiple packages, such as foo and foo.test. + type key struct { + token.Position + *analysis.Analyzer + message string + } + seen := make(map[key]bool) + + extract = func(act *action) { + if act.err != nil { + if pe, ok := act.err.(*errorutil.PanicError); ok { + panic(pe) + } + retErrors = append(retErrors, errors.Wrap(act.err, act.a.Name)) + return + } + + if act.isroot { + for _, diag := range act.diagnostics { + // We don't display a.Name/f.Category + // as most users don't care. + + posn := act.pkg.Fset.Position(diag.Pos) + k := key{posn, act.a, diag.Message} + if seen[k] { + continue // duplicate + } + seen[k] = true + + retDiag := Diagnostic{ + Diagnostic: diag, + Analyzer: act.a, + Position: posn, + Pkg: act.pkg, + } + retDiags = append(retDiags, retDiag) + } + } + } + visitAll(roots) + return +} + +// An action represents one unit of analysis work: the application of +// one analysis to one package. Actions form a DAG, both within a +// package (as different analyzers are applied, either in sequence or +// parallel), and across packages (as dependencies are analyzed). +type action struct { + a *analysis.Analyzer + pkg *packages.Package + pass *analysis.Pass + deps []*action + objectFacts map[objectFactKey]analysis.Fact + packageFacts map[packageFactKey]analysis.Fact + result interface{} + diagnostics []analysis.Diagnostic + err error + r *runner + analysisDoneCh chan struct{} + loadCachedFactsDone bool + loadCachedFactsOk bool + isroot bool + isInitialPkg bool + needAnalyzeSource bool +} + +type objectFactKey struct { + obj types.Object + typ reflect.Type +} + +type packageFactKey struct { + pkg *types.Package + typ reflect.Type +} + +func (act *action) String() string { + return fmt.Sprintf("%s@%s", act.a, act.pkg) +} + +func (act *action) loadCachedFacts() bool { + if act.loadCachedFactsDone { // can't be set in parallel + return act.loadCachedFactsOk + } + + res := func() bool { + if act.isInitialPkg { + return true // load cached facts only for non-initial packages + } + + if len(act.a.FactTypes) == 0 { + return true // no need to load facts + } + + return act.loadPersistedFacts() + }() + act.loadCachedFactsDone = true + act.loadCachedFactsOk = res + return res +} + +func (act *action) waitUntilDependingAnalyzersWorked() { + for _, dep := range act.deps { + if dep.pkg == act.pkg { + <-dep.analysisDoneCh + } + } +} + +type IllTypedError struct { + Pkg *packages.Package +} + +func (e *IllTypedError) Error() string { + return fmt.Sprintf("errors in package: %v", e.Pkg.Errors) +} + +type FailedPrerequisitesError struct { + errors map[string][]string +} + +func (f FailedPrerequisitesError) NotEmpty() bool { + return len(f.errors) > 0 +} + +func (f *FailedPrerequisitesError) Consume(name string, err error) { + if f.errors == nil { + f.errors = map[string][]string{} + } + k := fmt.Sprintf("%v", err) + f.errors[k] = append(f.errors[k], name) +} + +type groupedPrerequisiteErr struct { + names []string + err string +} + +func (g groupedPrerequisiteErr) String() string { + if len(g.names) == 1 { + return fmt.Sprintf("%s: %s", g.names[0], g.err) + } + return fmt.Sprintf("(%s): %s", strings.Join(g.names, ", "), g.err) +} + +func (f FailedPrerequisitesError) Error() string { + var errs []string + for err := range f.errors { + errs = append(errs, err) + } + var groups []groupedPrerequisiteErr + for _, err := range errs { + groups = append(groups, groupedPrerequisiteErr{ + err: err, + names: f.errors[err], + }) + } + return fmt.Sprintf("failed prerequisites: %s", groups) +} + +func (act *action) analyzeSafe() { + defer func() { + if p := recover(); p != nil { + act.err = errorutil.NewPanicError(fmt.Sprintf("%s: package %q (isInitialPkg: %t, needAnalyzeSource: %t): %s", + act.a.Name, act.pkg.Name, act.isInitialPkg, act.needAnalyzeSource, p), debug.Stack()) + } + }() + act.r.sw.TrackStage(act.a.Name, func() { + act.analyze() + }) +} + +func (act *action) analyze() { + defer close(act.analysisDoneCh) // unblock actions depending on this action + + if !act.needAnalyzeSource { + return + } + + defer func(now time.Time) { + analyzeDebugf("go/analysis: %s: %s: analyzed package %q in %s", act.r.prefix, act.a.Name, act.pkg.Name, time.Since(now)) + }(time.Now()) + + // Report an error if any dependency failures. + var depErr FailedPrerequisitesError + for _, dep := range act.deps { + if dep.err == nil { + continue + } + depErr.Consume(dep.String(), dep.err) + } + if depErr.NotEmpty() { + act.err = depErr + return + } + + // Plumb the output values of the dependencies + // into the inputs of this action. Also facts. + inputs := make(map[*analysis.Analyzer]interface{}) + startedAt := time.Now() + for _, dep := range act.deps { + if dep.pkg == act.pkg { + // Same package, different analysis (horizontal edge): + // in-memory outputs of prerequisite analyzers + // become inputs to this analysis pass. + inputs[dep.a] = dep.result + } else if dep.a == act.a { // (always true) + // Same analysis, different package (vertical edge): + // serialized facts produced by prerequisite analysis + // become available to this analysis pass. + inheritFacts(act, dep) + } + } + factsDebugf("%s: Inherited facts in %s", act, time.Since(startedAt)) + + // Run the analysis. + pass := &analysis.Pass{ + Analyzer: act.a, + Fset: act.pkg.Fset, + Files: act.pkg.Syntax, + OtherFiles: act.pkg.OtherFiles, + Pkg: act.pkg.Types, + TypesInfo: act.pkg.TypesInfo, + TypesSizes: act.pkg.TypesSizes, + ResultOf: inputs, + Report: func(d analysis.Diagnostic) { act.diagnostics = append(act.diagnostics, d) }, + ImportObjectFact: act.importObjectFact, + ExportObjectFact: act.exportObjectFact, + ImportPackageFact: act.importPackageFact, + ExportPackageFact: act.exportPackageFact, + AllObjectFacts: act.allObjectFacts, + AllPackageFacts: act.allPackageFacts, + } + act.pass = pass + act.r.passToPkgGuard.Lock() + act.r.passToPkg[pass] = act.pkg + act.r.passToPkgGuard.Unlock() + + var err error + if act.pkg.IllTyped { + // It looks like there should be !pass.Analyzer.RunDespiteErrors + // but govet's cgocall crashes on it. Govet itself contains !pass.Analyzer.RunDespiteErrors condition here + // but it exit before it if packages.Load have failed. + err = errors.Wrap(&IllTypedError{Pkg: act.pkg}, "analysis skipped") + } else { + startedAt = time.Now() + act.result, err = pass.Analyzer.Run(pass) + analyzedIn := time.Since(startedAt) + if analyzedIn > time.Millisecond*10 { + debugf("%s: run analyzer in %s", act, analyzedIn) + } + } + act.err = err + + // disallow calls after Run + pass.ExportObjectFact = nil + pass.ExportPackageFact = nil + + if err := act.persistFactsToCache(); err != nil { + act.r.log.Warnf("Failed to persist facts to cache: %s", err) + } +} + +// inheritFacts populates act.facts with +// those it obtains from its dependency, dep. +func inheritFacts(act, dep *action) { + serialize := false + + for key, fact := range dep.objectFacts { + // Filter out facts related to objects + // that are irrelevant downstream + // (equivalently: not in the compiler export data). + if !exportedFrom(key.obj, dep.pkg.Types) { + factsInheritDebugf("%v: discarding %T fact from %s for %s: %s", act, fact, dep, key.obj, fact) + continue + } + + // Optionally serialize/deserialize fact + // to verify that it works across address spaces. + if serialize { + var err error + fact, err = codeFact(fact) + if err != nil { + act.r.log.Panicf("internal error: encoding of %T fact failed in %v", fact, act) + } + } + + factsInheritDebugf("%v: inherited %T fact for %s: %s", act, fact, key.obj, fact) + act.objectFacts[key] = fact + } + + for key, fact := range dep.packageFacts { + // TODO: filter out facts that belong to + // packages not mentioned in the export data + // to prevent side channels. + + // Optionally serialize/deserialize fact + // to verify that it works across address spaces + // and is deterministic. + if serialize { + var err error + fact, err = codeFact(fact) + if err != nil { + act.r.log.Panicf("internal error: encoding of %T fact failed in %v", fact, act) + } + } + + factsInheritDebugf("%v: inherited %T fact for %s: %s", act, fact, key.pkg.Path(), fact) + act.packageFacts[key] = fact + } +} + +// codeFact encodes then decodes a fact, +// just to exercise that logic. +func codeFact(fact analysis.Fact) (analysis.Fact, error) { + // We encode facts one at a time. + // A real modular driver would emit all facts + // into one encoder to improve gob efficiency. + var buf bytes.Buffer + if err := gob.NewEncoder(&buf).Encode(fact); err != nil { + return nil, err + } + + // Encode it twice and assert that we get the same bits. + // This helps detect nondeterministic Gob encoding (e.g. of maps). + var buf2 bytes.Buffer + if err := gob.NewEncoder(&buf2).Encode(fact); err != nil { + return nil, err + } + if !bytes.Equal(buf.Bytes(), buf2.Bytes()) { + return nil, fmt.Errorf("encoding of %T fact is nondeterministic", fact) + } + + newFact := reflect.New(reflect.TypeOf(fact).Elem()).Interface().(analysis.Fact) + if err := gob.NewDecoder(&buf).Decode(newFact); err != nil { + return nil, err + } + return newFact, nil +} + +// exportedFrom reports whether obj may be visible to a package that imports pkg. +// This includes not just the exported members of pkg, but also unexported +// constants, types, fields, and methods, perhaps belonging to oether packages, +// that find there way into the API. +// This is an overapproximation of the more accurate approach used by +// gc export data, which walks the type graph, but it's much simpler. +// +// TODO(adonovan): do more accurate filtering by walking the type graph. +func exportedFrom(obj types.Object, pkg *types.Package) bool { + switch obj := obj.(type) { + case *types.Func: + return obj.Exported() && obj.Pkg() == pkg || + obj.Type().(*types.Signature).Recv() != nil + case *types.Var: + return obj.Exported() && obj.Pkg() == pkg || + obj.IsField() + case *types.TypeName, *types.Const: + return true + } + return false // Nil, Builtin, Label, or PkgName +} + +// importObjectFact implements Pass.ImportObjectFact. +// Given a non-nil pointer ptr of type *T, where *T satisfies Fact, +// importObjectFact copies the fact value to *ptr. +func (act *action) importObjectFact(obj types.Object, ptr analysis.Fact) bool { + if obj == nil { + panic("nil object") + } + key := objectFactKey{obj, act.factType(ptr)} + if v, ok := act.objectFacts[key]; ok { + reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem()) + return true + } + return false +} + +// exportObjectFact implements Pass.ExportObjectFact. +func (act *action) exportObjectFact(obj types.Object, fact analysis.Fact) { + if obj.Pkg() != act.pkg.Types { + act.r.log.Panicf("internal error: in analysis %s of package %s: Fact.Set(%s, %T): can't set facts on objects belonging another package", + act.a, act.pkg, obj, fact) + } + + key := objectFactKey{obj, act.factType(fact)} + act.objectFacts[key] = fact // clobber any existing entry + if isFactsExportDebug { + objstr := types.ObjectString(obj, (*types.Package).Name) + factsExportDebugf("%s: object %s has fact %s\n", + act.pkg.Fset.Position(obj.Pos()), objstr, fact) + } +} + +func (act *action) allObjectFacts() []analysis.ObjectFact { + out := make([]analysis.ObjectFact, 0, len(act.objectFacts)) + for key, fact := range act.objectFacts { + out = append(out, analysis.ObjectFact{ + Object: key.obj, + Fact: fact, + }) + } + return out +} + +// importPackageFact implements Pass.ImportPackageFact. +// Given a non-nil pointer ptr of type *T, where *T satisfies Fact, +// fact copies the fact value to *ptr. +func (act *action) importPackageFact(pkg *types.Package, ptr analysis.Fact) bool { + if pkg == nil { + panic("nil package") + } + key := packageFactKey{pkg, act.factType(ptr)} + if v, ok := act.packageFacts[key]; ok { + reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem()) + return true + } + return false +} + +// exportPackageFact implements Pass.ExportPackageFact. +func (act *action) exportPackageFact(fact analysis.Fact) { + key := packageFactKey{act.pass.Pkg, act.factType(fact)} + act.packageFacts[key] = fact // clobber any existing entry + factsDebugf("%s: package %s has fact %s\n", + act.pkg.Fset.Position(act.pass.Files[0].Pos()), act.pass.Pkg.Path(), fact) +} + +func (act *action) allPackageFacts() []analysis.PackageFact { + out := make([]analysis.PackageFact, 0, len(act.packageFacts)) + for key, fact := range act.packageFacts { + out = append(out, analysis.PackageFact{ + Package: key.pkg, + Fact: fact, + }) + } + return out +} + +func (act *action) factType(fact analysis.Fact) reflect.Type { + t := reflect.TypeOf(fact) + if t.Kind() != reflect.Ptr { + act.r.log.Fatalf("invalid Fact type: got %T, want pointer", t) + } + return t +} + +type Fact struct { + Path string // non-empty only for object facts + Fact analysis.Fact +} + +func (act *action) persistFactsToCache() error { + analyzer := act.a + if len(analyzer.FactTypes) == 0 { + return nil + } + + // Merge new facts into the package and persist them. + var facts []Fact + for key, fact := range act.packageFacts { + if key.pkg != act.pkg.Types { + // The fact is from inherited facts from another package + continue + } + facts = append(facts, Fact{ + Path: "", + Fact: fact, + }) + } + for key, fact := range act.objectFacts { + obj := key.obj + if obj.Pkg() != act.pkg.Types { + // The fact is from inherited facts from another package + continue + } + + path, err := objectpath.For(obj) + if err != nil { + // The object is not globally addressable + continue + } + + facts = append(facts, Fact{ + Path: string(path), + Fact: fact, + }) + } + + factsCacheDebugf("Caching %d facts for package %q and analyzer %s", len(facts), act.pkg.Name, act.a.Name) + + key := fmt.Sprintf("%s/facts", analyzer.Name) + return act.r.pkgCache.Put(act.pkg, pkgcache.HashModeNeedAllDeps, key, facts) +} + +func (act *action) loadPersistedFacts() bool { + var facts []Fact + key := fmt.Sprintf("%s/facts", act.a.Name) + if err := act.r.pkgCache.Get(act.pkg, pkgcache.HashModeNeedAllDeps, key, &facts); err != nil { + if err != pkgcache.ErrMissing { + act.r.log.Warnf("Failed to get persisted facts: %s", err) + } + + factsCacheDebugf("No cached facts for package %q and analyzer %s", act.pkg.Name, act.a.Name) + return false + } + + factsCacheDebugf("Loaded %d cached facts for package %q and analyzer %s", len(facts), act.pkg.Name, act.a.Name) + + for _, f := range facts { + if f.Path == "" { // this is a package fact + key := packageFactKey{act.pkg.Types, act.factType(f.Fact)} + act.packageFacts[key] = f.Fact + continue + } + obj, err := objectpath.Object(act.pkg.Types, objectpath.Path(f.Path)) + if err != nil { + // Be lenient about these errors. For example, when + // analyzing io/ioutil from source, we may get a fact + // for methods on the devNull type, and objectpath + // will happily create a path for them. However, when + // we later load io/ioutil from export data, the path + // no longer resolves. + // + // If an exported type embeds the unexported type, + // then (part of) the unexported type will become part + // of the type information and our path will resolve + // again. + continue + } + factKey := objectFactKey{obj, act.factType(f.Fact)} + act.objectFacts[factKey] = f.Fact + } + + return true +} + +type loadingPackage struct { + pkg *packages.Package + imports map[string]*loadingPackage + isInitial bool + log logutils.Log + actions []*action // all actions with this package + loadGuard *load.Guard + dependents int32 // number of depending on it packages + analyzeOnce sync.Once + decUseMutex sync.Mutex +} + +func (lp *loadingPackage) String() string { + return fmt.Sprintf("%s@%s", lp.pkg.PkgPath, lp.pkg.Name) +} + +func sizeOfValueTreeBytes(v interface{}) int { + return sizeOfReflectValueTreeBytes(reflect.ValueOf(v), map[uintptr]struct{}{}) +} + +func sizeOfReflectValueTreeBytes(rv reflect.Value, visitedPtrs map[uintptr]struct{}) int { + switch rv.Kind() { + case reflect.Ptr: + ptrSize := int(rv.Type().Size()) + if rv.IsNil() { + return ptrSize + } + ptr := rv.Pointer() + if _, ok := visitedPtrs[ptr]; ok { + return 0 + } + visitedPtrs[ptr] = struct{}{} + return ptrSize + sizeOfReflectValueTreeBytes(rv.Elem(), visitedPtrs) + case reflect.Interface: + if rv.IsNil() { + return 0 + } + return sizeOfReflectValueTreeBytes(rv.Elem(), visitedPtrs) + case reflect.Struct: + ret := 0 + for i := 0; i < rv.NumField(); i++ { + ret += sizeOfReflectValueTreeBytes(rv.Field(i), visitedPtrs) + } + return ret + case reflect.Slice, reflect.Array, reflect.Chan: + return int(rv.Type().Size()) + rv.Cap()*int(rv.Type().Elem().Size()) + case reflect.Map: + ret := 0 + for _, key := range rv.MapKeys() { + mv := rv.MapIndex(key) + ret += sizeOfReflectValueTreeBytes(key, visitedPtrs) + ret += sizeOfReflectValueTreeBytes(mv, visitedPtrs) + } + return ret + case reflect.String: + return rv.Len() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Uintptr, reflect.Bool, reflect.Float32, reflect.Float64, reflect.UnsafePointer: + return int(rv.Type().Size()) + case reflect.Invalid: + return 0 + default: + panic("unknown rv of type " + fmt.Sprint(rv)) + } +} + +func (lp *loadingPackage) decUse(canClearTypes bool) { + lp.decUseMutex.Lock() + defer lp.decUseMutex.Unlock() + + for _, act := range lp.actions { + pass := act.pass + if pass == nil { + continue + } + + pass.Files = nil + pass.TypesInfo = nil + pass.TypesSizes = nil + pass.ResultOf = nil + pass.Pkg = nil + pass.OtherFiles = nil + pass.AllObjectFacts = nil + pass.AllPackageFacts = nil + pass.ImportObjectFact = nil + pass.ExportObjectFact = nil + pass.ImportPackageFact = nil + pass.ExportPackageFact = nil + act.pass = nil + act.deps = nil + if act.result != nil { + if isMemoryDebug { + debugf("%s: decUse: nilling act result of size %d bytes", act, sizeOfValueTreeBytes(act.result)) + } + act.result = nil + } + } + + lp.pkg.Syntax = nil + lp.pkg.TypesInfo = nil + lp.pkg.TypesSizes = nil + + // Can't set lp.pkg.Imports to nil because of loadFromExportData.visit. + + dependents := atomic.AddInt32(&lp.dependents, -1) + if dependents != 0 { + return + } + + if canClearTypes { + // canClearTypes is set to true if we can discard type + // information after the package and its dependents have been + // processed. This is the case when no whole program checkers (unused) are + // being run. + lp.pkg.Types = nil + } + lp.pkg = nil + + for _, imp := range lp.imports { + imp.decUse(canClearTypes) + } + lp.imports = nil + + for _, act := range lp.actions { + if !lp.isInitial { + act.pkg = nil + } + act.packageFacts = nil + act.objectFacts = nil + } + lp.actions = nil +} + +func (lp *loadingPackage) analyzeRecursive(loadMode LoadMode, loadSem chan struct{}) { + lp.analyzeOnce.Do(func() { + // Load the direct dependencies, in parallel. + var wg sync.WaitGroup + wg.Add(len(lp.imports)) + for _, imp := range lp.imports { + go func(imp *loadingPackage) { + imp.analyzeRecursive(loadMode, loadSem) + wg.Done() + }(imp) + } + wg.Wait() + lp.analyze(loadMode, loadSem) + }) +} + +func (lp *loadingPackage) analyze(loadMode LoadMode, loadSem chan struct{}) { + loadSem <- struct{}{} + defer func() { + <-loadSem + }() + + // Save memory on unused more fields. + defer lp.decUse(loadMode < LoadModeWholeProgram) + + if err := lp.loadWithFacts(loadMode); err != nil { + werr := errors.Wrapf(err, "failed to load package %s", lp.pkg.Name) + // Don't need to write error to errCh, it will be extracted and reported on another layer. + // Unblock depending actions and propagate error. + for _, act := range lp.actions { + close(act.analysisDoneCh) + act.err = werr + } + return + } + + var actsWg sync.WaitGroup + actsWg.Add(len(lp.actions)) + for _, act := range lp.actions { + go func(act *action) { + defer actsWg.Done() + + act.waitUntilDependingAnalyzersWorked() + + act.analyzeSafe() + }(act) + } + actsWg.Wait() +} + +func (lp *loadingPackage) loadFromSource(loadMode LoadMode) error { + pkg := lp.pkg + + // Many packages have few files, much fewer than there + // are CPU cores. Additionally, parsing each individual file is + // very fast. A naive parallel implementation of this loop won't + // be faster, and tends to be slower due to extra scheduling, + // bookkeeping and potentially false sharing of cache lines. + pkg.Syntax = make([]*ast.File, 0, len(pkg.CompiledGoFiles)) + for _, file := range pkg.CompiledGoFiles { + f, err := parser.ParseFile(pkg.Fset, file, nil, parser.ParseComments) + if err != nil { + pkg.Errors = append(pkg.Errors, lp.convertError(err)...) + continue + } + pkg.Syntax = append(pkg.Syntax, f) + } + if len(pkg.Errors) != 0 { + pkg.IllTyped = true + return nil + } + + if loadMode == LoadModeSyntax { + return nil + } + + // Call NewPackage directly with explicit name. + // This avoids skew between golist and go/types when the files' + // package declarations are inconsistent. + // Subtle: we populate all Types fields with an empty Package + // before loading export data so that export data processing + // never has to create a types.Package for an indirect dependency, + // which would then require that such created packages be explicitly + // inserted back into the Import graph as a final step after export data loading. + pkg.Types = types.NewPackage(pkg.PkgPath, pkg.Name) + + pkg.IllTyped = true + + pkg.TypesInfo = &types.Info{ + Types: make(map[ast.Expr]types.TypeAndValue), + Defs: make(map[*ast.Ident]types.Object), + Uses: make(map[*ast.Ident]types.Object), + Implicits: make(map[ast.Node]types.Object), + Scopes: make(map[ast.Node]*types.Scope), + Selections: make(map[*ast.SelectorExpr]*types.Selection), + } + + importer := func(path string) (*types.Package, error) { + if path == unsafePkgName { + return types.Unsafe, nil + } + if path == "C" { + // go/packages doesn't tell us that cgo preprocessing + // failed. When we subsequently try to parse the package, + // we'll encounter the raw C import. + return nil, errors.New("cgo preprocessing failed") + } + imp := pkg.Imports[path] + if imp == nil { + return nil, nil + } + if len(imp.Errors) > 0 { + return nil, imp.Errors[0] + } + return imp.Types, nil + } + tc := &types.Config{ + Importer: importerFunc(importer), + Error: func(err error) { + pkg.Errors = append(pkg.Errors, lp.convertError(err)...) + }, + } + _ = types.NewChecker(tc, pkg.Fset, pkg.Types, pkg.TypesInfo).Files(pkg.Syntax) + // Don't handle error here: errors are adding by tc.Error function. + + illTyped := len(pkg.Errors) != 0 + if !illTyped { + for _, imp := range lp.imports { + if imp.pkg.IllTyped { + illTyped = true + break + } + } + } + pkg.IllTyped = illTyped + return nil +} + +func (lp *loadingPackage) loadFromExportData() error { + pkg := lp.pkg + + // Call NewPackage directly with explicit name. + // This avoids skew between golist and go/types when the files' + // package declarations are inconsistent. + // Subtle: we populate all Types fields with an empty Package + // before loading export data so that export data processing + // never has to create a types.Package for an indirect dependency, + // which would then require that such created packages be explicitly + // inserted back into the Import graph as a final step after export data loading. + pkg.Types = types.NewPackage(pkg.PkgPath, pkg.Name) + + pkg.IllTyped = true + for path, pkg := range pkg.Imports { + if pkg.Types == nil { + return fmt.Errorf("dependency %q hasn't been loaded yet", path) + } + } + if pkg.ExportFile == "" { + return fmt.Errorf("no export data for %q", pkg.ID) + } + f, err := os.Open(pkg.ExportFile) + if err != nil { + return err + } + defer f.Close() + + r, err := gcexportdata.NewReader(f) + if err != nil { + return err + } + + view := make(map[string]*types.Package) // view seen by gcexportdata + seen := make(map[*packages.Package]bool) // all visited packages + var visit func(pkgs map[string]*packages.Package) + visit = func(pkgs map[string]*packages.Package) { + for _, pkg := range pkgs { + if !seen[pkg] { + seen[pkg] = true + view[pkg.PkgPath] = pkg.Types + visit(pkg.Imports) + } + } + } + visit(pkg.Imports) + tpkg, err := gcexportdata.Read(r, pkg.Fset, view, pkg.PkgPath) + if err != nil { + return err + } + pkg.Types = tpkg + pkg.IllTyped = false + return nil +} + +func (act *action) markDepsForAnalyzingSource() { + // Horizontal deps (analyzer.Requires) must be loaded from source and analyzed before analyzing + // this action. + for _, dep := range act.deps { + if dep.pkg == act.pkg { + // Analyze source only for horizontal dependencies, e.g. from "buildssa". + dep.needAnalyzeSource = true // can't be set in parallel + } + } +} + +func (lp *loadingPackage) loadWithFacts(loadMode LoadMode) error { + pkg := lp.pkg + + if pkg.PkgPath == unsafePkgName { + // Fill in the blanks to avoid surprises. + pkg.Syntax = []*ast.File{} + if loadMode >= LoadModeTypesInfo { + pkg.Types = types.Unsafe + pkg.TypesInfo = new(types.Info) + } + return nil + } + + if pkg.TypesInfo != nil { + // Already loaded package, e.g. because another not go/analysis linter required types for deps. + // Try load cached facts for it. + + for _, act := range lp.actions { + if !act.loadCachedFacts() { + // Cached facts loading failed: analyze later the action from source. + act.needAnalyzeSource = true + factsCacheDebugf("Loading of facts for already loaded %s failed, analyze it from source later", act) + act.markDepsForAnalyzingSource() + } + } + return nil + } + + if lp.isInitial { + // No need to load cached facts: the package will be analyzed from source + // because it's the initial. + return lp.loadFromSource(loadMode) + } + + return lp.loadImportedPackageWithFacts(loadMode) +} + +func (lp *loadingPackage) loadImportedPackageWithFacts(loadMode LoadMode) error { + pkg := lp.pkg + + // Load package from export data + if loadMode >= LoadModeTypesInfo { + if err := lp.loadFromExportData(); err != nil { + // We asked Go to give us up to date export data, yet + // we can't load it. There must be something wrong. + // + // Attempt loading from source. This should fail (because + // otherwise there would be export data); we just want to + // get the compile errors. If loading from source succeeds + // we discard the result, anyway. Otherwise we'll fail + // when trying to reload from export data later. + + // Otherwise it panics because uses already existing (from exported data) types. + pkg.Types = types.NewPackage(pkg.PkgPath, pkg.Name) + if srcErr := lp.loadFromSource(loadMode); srcErr != nil { + return srcErr + } + // Make sure this package can't be imported successfully + pkg.Errors = append(pkg.Errors, packages.Error{ + Pos: "-", + Msg: fmt.Sprintf("could not load export data: %s", err), + Kind: packages.ParseError, + }) + return errors.Wrap(err, "could not load export data") + } + } + + needLoadFromSource := false + for _, act := range lp.actions { + if act.loadCachedFacts() { + continue + } + + // Cached facts loading failed: analyze later the action from source. + factsCacheDebugf("Loading of facts for %s failed, analyze it from source later", act) + act.needAnalyzeSource = true // can't be set in parallel + needLoadFromSource = true + + act.markDepsForAnalyzingSource() + } + + if needLoadFromSource { + // Cached facts loading failed: analyze later the action from source. To perform + // the analysis we need to load the package from source code. + + // Otherwise it panics because uses already existing (from exported data) types. + if loadMode >= LoadModeTypesInfo { + pkg.Types = types.NewPackage(pkg.PkgPath, pkg.Name) + } + return lp.loadFromSource(loadMode) + } + + return nil +} + +func (lp *loadingPackage) convertError(err error) []packages.Error { + var errs []packages.Error + // taken from go/packages + switch err := err.(type) { + case packages.Error: + // from driver + errs = append(errs, err) + + case *os.PathError: + // from parser + errs = append(errs, packages.Error{ + Pos: err.Path + ":1", + Msg: err.Err.Error(), + Kind: packages.ParseError, + }) + + case scanner.ErrorList: + // from parser + for _, err := range err { + errs = append(errs, packages.Error{ + Pos: err.Pos.String(), + Msg: err.Msg, + Kind: packages.ParseError, + }) + } + + case types.Error: + // from type checker + errs = append(errs, packages.Error{ + Pos: err.Fset.Position(err.Pos).String(), + Msg: err.Msg, + Kind: packages.TypeError, + }) + + default: + // unexpected impoverished error from parser? + errs = append(errs, packages.Error{ + Pos: "-", + Msg: err.Error(), + Kind: packages.UnknownError, + }) + + // If you see this error message, please file a bug. + lp.log.Warnf("Internal error: error %q (%T) without position", err, err) + } + return errs +} + +type importerFunc func(path string) (*types.Package, error) + +func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gochecknoglobals.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gochecknoglobals.go new file mode 100644 index 000000000..f2166416b --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gochecknoglobals.go @@ -0,0 +1,100 @@ +package golinters + +import ( + "fmt" + "go/ast" + "go/token" + "strings" + "sync" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const gochecknoglobalsName = "gochecknoglobals" + +//nolint:dupl +func NewGochecknoglobals() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: gochecknoglobalsName, + Doc: goanalysis.TheOnlyanalyzerDoc, + Run: func(pass *analysis.Pass) (interface{}, error) { + var res []goanalysis.Issue + for _, file := range pass.Files { + fileIssues := checkFileForGlobals(file, pass.Fset) + for i := range fileIssues { + res = append(res, goanalysis.NewIssue(&fileIssues[i], pass)) + } + } + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + }, + } + return goanalysis.NewLinter( + gochecknoglobalsName, + "Checks that no globals are present in Go code", + []*analysis.Analyzer{analyzer}, + nil, + ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} + +func checkFileForGlobals(f *ast.File, fset *token.FileSet) []result.Issue { + var res []result.Issue + for _, decl := range f.Decls { + genDecl, ok := decl.(*ast.GenDecl) + if !ok { + continue + } + if genDecl.Tok != token.VAR { + continue + } + + for _, spec := range genDecl.Specs { + valueSpec := spec.(*ast.ValueSpec) + for _, vn := range valueSpec.Names { + if isWhitelisted(vn) { + continue + } + + res = append(res, result.Issue{ + Pos: fset.Position(vn.Pos()), + Text: fmt.Sprintf("%s is a global variable", formatCode(vn.Name, nil)), + FromLinter: gochecknoglobalsName, + }) + } + } + } + + return res +} + +func isWhitelisted(i *ast.Ident) bool { + return i.Name == "_" || i.Name == "version" || looksLikeError(i) +} + +// looksLikeError returns true if the AST identifier starts +// with 'err' or 'Err', or false otherwise. +// +// TODO: https://github.com/leighmcculloch/gochecknoglobals/issues/5 +func looksLikeError(i *ast.Ident) bool { + prefix := "err" + if i.IsExported() { + prefix = "Err" + } + return strings.HasPrefix(i.Name, prefix) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gochecknoinits.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gochecknoinits.go new file mode 100644 index 000000000..18465b130 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gochecknoinits.go @@ -0,0 +1,74 @@ +package golinters + +import ( + "fmt" + "go/ast" + "go/token" + "sync" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const gochecknoinitsName = "gochecknoinits" + +//nolint:dupl +func NewGochecknoinits() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: gochecknoinitsName, + Doc: goanalysis.TheOnlyanalyzerDoc, + Run: func(pass *analysis.Pass) (interface{}, error) { + var res []goanalysis.Issue + for _, file := range pass.Files { + fileIssues := checkFileForInits(file, pass.Fset) + for i := range fileIssues { + res = append(res, goanalysis.NewIssue(&fileIssues[i], pass)) + } + } + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + }, + } + return goanalysis.NewLinter( + gochecknoinitsName, + "Checks that no init functions are present in Go code", + []*analysis.Analyzer{analyzer}, + nil, + ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} + +func checkFileForInits(f *ast.File, fset *token.FileSet) []result.Issue { + var res []result.Issue + for _, decl := range f.Decls { + funcDecl, ok := decl.(*ast.FuncDecl) + if !ok { + continue + } + + name := funcDecl.Name.Name + if name == "init" && funcDecl.Recv.NumFields() == 0 { + res = append(res, result.Issue{ + Pos: fset.Position(funcDecl.Pos()), + Text: fmt.Sprintf("don't use %s function", formatCode(name, nil)), + FromLinter: gochecknoinitsName, + }) + } + } + + return res +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocognit.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocognit.go new file mode 100644 index 000000000..78afff86c --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocognit.go @@ -0,0 +1,69 @@ +// nolint:dupl +package golinters + +import ( + "fmt" + "sort" + "sync" + + "github.com/uudashr/gocognit" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const gocognitName = "gocognit" + +func NewGocognit() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: goanalysis.TheOnlyAnalyzerName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + gocognitName, + "Computes and checks the cognitive complexity of functions", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var stats []gocognit.Stat + for _, f := range pass.Files { + stats = gocognit.ComplexityStats(f, pass.Fset, stats) + } + if len(stats) == 0 { + return nil, nil + } + + sort.SliceStable(stats, func(i, j int) bool { + return stats[i].Complexity > stats[j].Complexity + }) + + res := make([]goanalysis.Issue, 0, len(stats)) + for _, s := range stats { + if s.Complexity <= lintCtx.Settings().Gocognit.MinComplexity { + break // Break as the stats is already sorted from greatest to least + } + + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: s.Pos, + Text: fmt.Sprintf("cognitive complexity %d of func %s is high (> %d)", + s.Complexity, formatCode(s.FuncName, lintCtx.Cfg), lintCtx.Settings().Gocognit.MinComplexity), + FromLinter: gocognitName, + }, pass)) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goconst.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goconst.go new file mode 100644 index 000000000..8e91feef8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goconst.go @@ -0,0 +1,81 @@ +package golinters + +import ( + "fmt" + "sync" + + goconstAPI "github.com/golangci/goconst" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const goconstName = "goconst" + +func NewGoconst() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: goconstName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + goconstName, + "Finds repeated strings that could be replaced by a constant", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + issues, err := checkConstants(pass, lintCtx) + if err != nil || len(issues) == 0 { + return nil, err + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} + +func checkConstants(pass *analysis.Pass, lintCtx *linter.Context) ([]goanalysis.Issue, error) { + cfg := goconstAPI.Config{ + MatchWithConstants: true, + MinStringLength: lintCtx.Settings().Goconst.MinStringLen, + MinOccurrences: lintCtx.Settings().Goconst.MinOccurrencesCount, + } + + goconstIssues, err := goconstAPI.Run(pass.Files, pass.Fset, &cfg) + if err != nil { + return nil, err + } + + if len(goconstIssues) == 0 { + return nil, nil + } + + res := make([]goanalysis.Issue, 0, len(goconstIssues)) + for _, i := range goconstIssues { + textBegin := fmt.Sprintf("string %s has %d occurrences", formatCode(i.Str, lintCtx.Cfg), i.OccurencesCount) + var textEnd string + if i.MatchingConst == "" { + textEnd = ", make it a constant" + } else { + textEnd = fmt.Sprintf(", but such constant %s already exists", formatCode(i.MatchingConst, lintCtx.Cfg)) + } + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: i.Pos, + Text: textBegin + textEnd, + FromLinter: goconstName, + }, pass)) + } + + return res, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocritic.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocritic.go new file mode 100644 index 000000000..fb2925209 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocritic.go @@ -0,0 +1,162 @@ +package golinters + +import ( + "fmt" + "go/ast" + "go/types" + "path/filepath" + "runtime" + "sort" + "strings" + "sync" + + "github.com/go-lintpack/lintpack" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const gocriticName = "gocritic" + +func NewGocritic() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + sizes := types.SizesFor("gc", runtime.GOARCH) + + analyzer := &analysis.Analyzer{ + Name: gocriticName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + gocriticName, + "The most opinionated Go source code linter", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + lintpackCtx := lintpack.NewContext(pass.Fset, sizes) + enabledCheckers, err := buildEnabledCheckers(lintCtx, lintpackCtx) + if err != nil { + return nil, err + } + + lintpackCtx.SetPackageInfo(pass.TypesInfo, pass.Pkg) + var res []goanalysis.Issue + pkgIssues := runGocriticOnPackage(lintpackCtx, enabledCheckers, pass.Files) + for i := range pkgIssues { + res = append(res, goanalysis.NewIssue(&pkgIssues[i], pass)) + } + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} + +func normalizeCheckerInfoParams(info *lintpack.CheckerInfo) lintpack.CheckerParams { + // lowercase info param keys here because golangci-lint's config parser lowercases all strings + ret := lintpack.CheckerParams{} + for k, v := range info.Params { + ret[strings.ToLower(k)] = v + } + + return ret +} + +func configureCheckerInfo(info *lintpack.CheckerInfo, allParams map[string]config.GocriticCheckSettings) error { + params := allParams[strings.ToLower(info.Name)] + if params == nil { // no config for this checker + return nil + } + + infoParams := normalizeCheckerInfoParams(info) + for k, p := range params { + v, ok := infoParams[k] + if ok { + v.Value = p + continue + } + + // param `k` isn't supported + if len(info.Params) == 0 { + return fmt.Errorf("checker %s config param %s doesn't exist: checker doesn't have params", + info.Name, k) + } + + var supportedKeys []string + for sk := range info.Params { + supportedKeys = append(supportedKeys, sk) + } + sort.Strings(supportedKeys) + + return fmt.Errorf("checker %s config param %s doesn't exist, all existing: %s", + info.Name, k, supportedKeys) + } + + return nil +} + +func buildEnabledCheckers(lintCtx *linter.Context, lintpackCtx *lintpack.Context) ([]*lintpack.Checker, error) { + s := lintCtx.Settings().Gocritic + allParams := s.GetLowercasedParams() + + var enabledCheckers []*lintpack.Checker + for _, info := range lintpack.GetCheckersInfo() { + if !s.IsCheckEnabled(info.Name) { + continue + } + + if err := configureCheckerInfo(info, allParams); err != nil { + return nil, err + } + + c := lintpack.NewChecker(lintpackCtx, info) + enabledCheckers = append(enabledCheckers, c) + } + + return enabledCheckers, nil +} + +func runGocriticOnPackage(lintpackCtx *lintpack.Context, checkers []*lintpack.Checker, + files []*ast.File) []result.Issue { + var res []result.Issue + for _, f := range files { + filename := filepath.Base(lintpackCtx.FileSet.Position(f.Pos()).Filename) + lintpackCtx.SetFileInfo(filename, f) + + issues := runGocriticOnFile(lintpackCtx, f, checkers) + res = append(res, issues...) + } + return res +} + +func runGocriticOnFile(ctx *lintpack.Context, f *ast.File, checkers []*lintpack.Checker) []result.Issue { + var res []result.Issue + + for _, c := range checkers { + // All checkers are expected to use *lint.Context + // as read-only structure, so no copying is required. + for _, warn := range c.Check(f) { + pos := ctx.FileSet.Position(warn.Node.Pos()) + res = append(res, result.Issue{ + Pos: pos, + Text: fmt.Sprintf("%s: %s", c.Info.Name, warn.Text), + FromLinter: gocriticName, + }) + } + } + + return res +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocyclo.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocyclo.go new file mode 100644 index 000000000..55f13fcfe --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocyclo.go @@ -0,0 +1,69 @@ +// nolint:dupl +package golinters + +import ( + "fmt" + "sort" + "sync" + + gocycloAPI "github.com/golangci/gocyclo/pkg/gocyclo" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const gocycloName = "gocyclo" + +func NewGocyclo() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: gocycloName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + gocycloName, + "Computes and checks the cyclomatic complexity of functions", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var stats []gocycloAPI.Stat + for _, f := range pass.Files { + stats = gocycloAPI.BuildStats(f, pass.Fset, stats) + } + if len(stats) == 0 { + return nil, nil + } + + sort.SliceStable(stats, func(i, j int) bool { + return stats[i].Complexity > stats[j].Complexity + }) + + res := make([]goanalysis.Issue, 0, len(stats)) + for _, s := range stats { + if s.Complexity <= lintCtx.Settings().Gocyclo.MinComplexity { + break // Break as the stats is already sorted from greatest to least + } + + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: s.Pos, + Text: fmt.Sprintf("cyclomatic complexity %d of func %s is high (> %d)", + s.Complexity, formatCode(s.FuncName, lintCtx.Cfg), lintCtx.Settings().Gocyclo.MinComplexity), + FromLinter: gocycloName, + }, pass)) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/godot.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/godot.go new file mode 100644 index 000000000..7e5b233a6 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/godot.go @@ -0,0 +1,63 @@ +package golinters + +import ( + "sync" + + "github.com/tetafro/godot" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const godotName = "godot" + +func NewGodot() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: godotName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + godotName, + "Check if comments end in a period", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + cfg := lintCtx.Cfg.LintersSettings.Godot + settings := godot.Settings{CheckAll: cfg.CheckAll} + + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var issues []godot.Message + for _, file := range pass.Files { + issues = append(issues, godot.Run(file, pass.Fset, settings)...) + } + + if len(issues) == 0 { + return nil, nil + } + + res := make([]goanalysis.Issue, len(issues)) + for k, i := range issues { + issue := result.Issue{ + Pos: i.Pos, + Text: i.Message, + FromLinter: godotName, + } + + res[k] = goanalysis.NewIssue(&issue, pass) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/godox.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/godox.go new file mode 100644 index 000000000..2a4dd9faf --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/godox.go @@ -0,0 +1,63 @@ +package golinters + +import ( + "go/token" + "strings" + "sync" + + "github.com/matoous/godox" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const godoxName = "godox" + +func NewGodox() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: godoxName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + godoxName, + "Tool for detection of FIXME, TODO and other comment keywords", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var issues []godox.Message + for _, file := range pass.Files { + issues = append(issues, godox.Run(file, pass.Fset, lintCtx.Settings().Godox.Keywords...)...) + } + + if len(issues) == 0 { + return nil, nil + } + + res := make([]goanalysis.Issue, len(issues)) + for k, i := range issues { + res[k] = goanalysis.NewIssue(&result.Issue{ + Pos: token.Position{ + Filename: i.Pos.Filename, + Line: i.Pos.Line, + }, + Text: strings.TrimRight(i.Message, "\n"), + FromLinter: godoxName, + }, pass) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goerr113.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goerr113.go new file mode 100644 index 000000000..0c10005a0 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goerr113.go @@ -0,0 +1,19 @@ +package golinters + +import ( + "github.com/Djarvur/go-err113" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewGoerr113() *goanalysis.Linter { + return goanalysis.NewLinter( + "goerr113", + "Golang linter to check the errors handling expressions", + []*analysis.Analyzer{ + err113.NewAnalyzer(), + }, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofmt.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofmt.go new file mode 100644 index 000000000..a7bd88a73 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofmt.go @@ -0,0 +1,72 @@ +package golinters + +import ( + "sync" + + gofmtAPI "github.com/golangci/gofmt/gofmt" + "github.com/pkg/errors" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" +) + +const gofmtName = "gofmt" + +func NewGofmt() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: gofmtName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + gofmtName, + "Gofmt checks whether code was gofmt-ed. By default "+ + "this tool runs with -s option to check for code simplification", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var fileNames []string + for _, f := range pass.Files { + pos := pass.Fset.PositionFor(f.Pos(), false) + fileNames = append(fileNames, pos.Filename) + } + + var issues []goanalysis.Issue + + for _, f := range fileNames { + diff, err := gofmtAPI.Run(f, lintCtx.Settings().Gofmt.Simplify) + if err != nil { // TODO: skip + return nil, err + } + if diff == nil { + continue + } + + is, err := extractIssuesFromPatch(string(diff), lintCtx.Log, lintCtx, false) + if err != nil { + return nil, errors.Wrapf(err, "can't extract issues from gofmt diff output %q", string(diff)) + } + + for i := range is { + issues = append(issues, goanalysis.NewIssue(&is[i], pass)) + } + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofmt_common.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofmt_common.go new file mode 100644 index 000000000..fb1e3f662 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofmt_common.go @@ -0,0 +1,269 @@ +package golinters + +import ( + "bytes" + "fmt" + "go/token" + "strings" + + "github.com/pkg/errors" + diffpkg "github.com/sourcegraph/go-diff/diff" + + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type Change struct { + LineRange result.Range + Replacement result.Replacement +} + +type diffLineType string + +const ( + diffLineAdded diffLineType = "added" + diffLineOriginal diffLineType = "original" + diffLineDeleted diffLineType = "deleted" +) + +type diffLine struct { + originalNumber int // 1-based original line number + typ diffLineType + data string // "+" or "-" stripped line +} + +type hunkChangesParser struct { + // needed because we merge currently added lines with the last original line + lastOriginalLine *diffLine + + // if the first line of diff is an adding we save all additions to replacementLinesToPrepend + replacementLinesToPrepend []string + + log logutils.Log + + lines []diffLine + + ret []Change +} + +func (p *hunkChangesParser) parseDiffLines(h *diffpkg.Hunk) { + lines := bytes.Split(h.Body, []byte{'\n'}) + currentOriginalLineNumer := int(h.OrigStartLine) + var ret []diffLine + + for i, line := range lines { + dl := diffLine{ + originalNumber: currentOriginalLineNumer, + } + + lineStr := string(line) + + if strings.HasPrefix(lineStr, "-") { + dl.typ = diffLineDeleted + dl.data = strings.TrimPrefix(lineStr, "-") + currentOriginalLineNumer++ + } else if strings.HasPrefix(lineStr, "+") { + dl.typ = diffLineAdded + dl.data = strings.TrimPrefix(lineStr, "+") + } else { + if i == len(lines)-1 && lineStr == "" { + // handle last \n: don't add an empty original line + break + } + + dl.typ = diffLineOriginal + dl.data = strings.TrimPrefix(lineStr, " ") + currentOriginalLineNumer++ + } + + ret = append(ret, dl) + } + + p.lines = ret +} + +func (p *hunkChangesParser) handleOriginalLine(line diffLine, i *int) { + if len(p.replacementLinesToPrepend) == 0 { + p.lastOriginalLine = &line + *i++ + return + } + + // check following added lines for the case: + // + added line 1 + // original line + // + added line 2 + + *i++ + var followingAddedLines []string + for ; *i < len(p.lines) && p.lines[*i].typ == diffLineAdded; *i++ { + followingAddedLines = append(followingAddedLines, p.lines[*i].data) + } + + p.ret = append(p.ret, Change{ + LineRange: result.Range{ + From: line.originalNumber, + To: line.originalNumber, + }, + Replacement: result.Replacement{ + NewLines: append(p.replacementLinesToPrepend, append([]string{line.data}, followingAddedLines...)...), + }, + }) + p.replacementLinesToPrepend = nil + p.lastOriginalLine = &line +} + +func (p *hunkChangesParser) handleDeletedLines(deletedLines []diffLine, addedLines []string) { + change := Change{ + LineRange: result.Range{ + From: deletedLines[0].originalNumber, + To: deletedLines[len(deletedLines)-1].originalNumber, + }, + } + + if len(addedLines) != 0 { + //nolint:gocritic + change.Replacement.NewLines = append(p.replacementLinesToPrepend, addedLines...) + if len(p.replacementLinesToPrepend) != 0 { + p.replacementLinesToPrepend = nil + } + + p.ret = append(p.ret, change) + return + } + + // delete-only change with possible prepending + if len(p.replacementLinesToPrepend) != 0 { + change.Replacement.NewLines = p.replacementLinesToPrepend + p.replacementLinesToPrepend = nil + } else { + change.Replacement.NeedOnlyDelete = true + } + + p.ret = append(p.ret, change) +} + +func (p *hunkChangesParser) handleAddedOnlyLines(addedLines []string) { + if p.lastOriginalLine == nil { + // the first line is added; the diff looks like: + // 1. + ... + // 2. - ... + // or + // 1. + ... + // 2. ... + + p.replacementLinesToPrepend = addedLines + return + } + + // add-only change merged into the last original line with possible prepending + p.ret = append(p.ret, Change{ + LineRange: result.Range{ + From: p.lastOriginalLine.originalNumber, + To: p.lastOriginalLine.originalNumber, + }, + Replacement: result.Replacement{ + NewLines: append(p.replacementLinesToPrepend, append([]string{p.lastOriginalLine.data}, addedLines...)...), + }, + }) + p.replacementLinesToPrepend = nil +} + +func (p *hunkChangesParser) parse(h *diffpkg.Hunk) []Change { + p.parseDiffLines(h) + + for i := 0; i < len(p.lines); { + line := p.lines[i] + if line.typ == diffLineOriginal { + p.handleOriginalLine(line, &i) //nolint:scopelint + continue + } + + var deletedLines []diffLine + for ; i < len(p.lines) && p.lines[i].typ == diffLineDeleted; i++ { + deletedLines = append(deletedLines, p.lines[i]) + } + + var addedLines []string + for ; i < len(p.lines) && p.lines[i].typ == diffLineAdded; i++ { + addedLines = append(addedLines, p.lines[i].data) + } + + if len(deletedLines) != 0 { + p.handleDeletedLines(deletedLines, addedLines) + continue + } + + // no deletions, only additions + p.handleAddedOnlyLines(addedLines) + } + + if len(p.replacementLinesToPrepend) != 0 { + p.log.Infof("The diff contains only additions: no original or deleted lines: %#v", p.lines) + return nil + } + + return p.ret +} + +func extractIssuesFromPatch(patch string, log logutils.Log, lintCtx *linter.Context, isGoimports bool) ([]result.Issue, error) { + diffs, err := diffpkg.ParseMultiFileDiff([]byte(patch)) + if err != nil { + return nil, errors.Wrap(err, "can't parse patch") + } + + if len(diffs) == 0 { + return nil, fmt.Errorf("got no diffs from patch parser: %v", diffs) + } + + issues := []result.Issue{} + for _, d := range diffs { + if len(d.Hunks) == 0 { + log.Warnf("Got no hunks in diff %+v", d) + continue + } + + for _, hunk := range d.Hunks { + var text string + if isGoimports { + text = "File is not `goimports`-ed" + if lintCtx.Settings().Goimports.LocalPrefixes != "" { + text += " with -local " + lintCtx.Settings().Goimports.LocalPrefixes + } + } else { + text = "File is not `gofmt`-ed" + if lintCtx.Settings().Gofmt.Simplify { + text += " with `-s`" + } + } + p := hunkChangesParser{ + log: log, + } + changes := p.parse(hunk) + for _, change := range changes { + change := change // fix scope + linterName := gofmtName + if isGoimports { + linterName = goimportsName + } + i := result.Issue{ + FromLinter: linterName, + Pos: token.Position{ + Filename: d.NewName, + Line: change.LineRange.From, + }, + Text: text, + Replacement: &change.Replacement, + } + if change.LineRange.From != change.LineRange.To { + i.LineRange = &change.LineRange + } + + issues = append(issues, i) + } + } + } + + return issues, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goimports.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goimports.go new file mode 100644 index 000000000..97767db8b --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goimports.go @@ -0,0 +1,73 @@ +package golinters + +import ( + "sync" + + goimportsAPI "github.com/golangci/gofmt/goimports" + "github.com/pkg/errors" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/imports" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" +) + +const goimportsName = "goimports" + +func NewGoimports() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: goimportsName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + goimportsName, + "Goimports does everything that gofmt does. Additionally it checks unused imports", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + imports.LocalPrefix = lintCtx.Settings().Goimports.LocalPrefixes + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var fileNames []string + for _, f := range pass.Files { + pos := pass.Fset.PositionFor(f.Pos(), false) + fileNames = append(fileNames, pos.Filename) + } + + var issues []goanalysis.Issue + + for _, f := range fileNames { + diff, err := goimportsAPI.Run(f) + if err != nil { // TODO: skip + return nil, err + } + if diff == nil { + continue + } + + is, err := extractIssuesFromPatch(string(diff), lintCtx.Log, lintCtx, true) + if err != nil { + return nil, errors.Wrapf(err, "can't extract issues from gofmt diff output %q", string(diff)) + } + + for i := range is { + issues = append(issues, goanalysis.NewIssue(&is[i], pass)) + } + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/golint.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/golint.go new file mode 100644 index 000000000..3b1b1b66f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/golint.go @@ -0,0 +1,78 @@ +package golinters + +import ( + "fmt" + "go/ast" + "go/token" + "go/types" + "sync" + + lintAPI "github.com/golangci/lint-1" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func golintProcessPkg(minConfidence float64, files []*ast.File, fset *token.FileSet, + typesPkg *types.Package, typesInfo *types.Info) ([]result.Issue, error) { + l := new(lintAPI.Linter) + ps, err := l.LintPkg(files, fset, typesPkg, typesInfo) + if err != nil { + return nil, fmt.Errorf("can't lint %d files: %s", len(files), err) + } + + if len(ps) == 0 { + return nil, nil + } + + issues := make([]result.Issue, 0, len(ps)) // This is worst case + for idx := range ps { + if ps[idx].Confidence >= minConfidence { + issues = append(issues, result.Issue{ + Pos: ps[idx].Position, + Text: ps[idx].Text, + FromLinter: golintName, + }) + // TODO: use p.Link and p.Category + } + } + + return issues, nil +} + +const golintName = "golint" + +func NewGolint() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: golintName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + golintName, + "Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + res, err := golintProcessPkg(lintCtx.Settings().Golint.MinConfidence, pass.Files, pass.Fset, pass.Pkg, pass.TypesInfo) + if err != nil || len(res) == 0 { + return nil, err + } + + mu.Lock() + for i := range res { + resIssues = append(resIssues, goanalysis.NewIssue(&res[i], pass)) + } + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gomnd.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gomnd.go new file mode 100644 index 000000000..0a64f88f8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gomnd.go @@ -0,0 +1,27 @@ +package golinters + +import ( + mnd "github.com/tommy-muehle/go-mnd" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewGoMND(cfg *config.Config) *goanalysis.Linter { + analyzers := []*analysis.Analyzer{ + mnd.Analyzer, + } + + var linterCfg map[string]map[string]interface{} + if cfg != nil { + linterCfg = cfg.LintersSettings.Gomnd.Settings + } + + return goanalysis.NewLinter( + "gomnd", + "An analyzer to detect magic numbers.", + analyzers, + linterCfg, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gomodguard.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gomodguard.go new file mode 100644 index 000000000..5b1406313 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gomodguard.go @@ -0,0 +1,88 @@ +package golinters + +import ( + "log" + "os" + "sync" + + "github.com/ryancurrah/gomodguard" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const ( + gomodguardName = "gomodguard" +) + +// NewGomodguard returns a new Gomodguard linter. +func NewGomodguard() *goanalysis.Linter { + var ( + issues []goanalysis.Issue + mu = sync.Mutex{} + analyzer = &analysis.Analyzer{ + Name: goanalysis.TheOnlyAnalyzerName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + ) + + return goanalysis.NewLinter( + gomodguardName, + "Allow and block list linter for direct Go module dependencies.", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var ( + files = []string{} + linterCfg = lintCtx.Cfg.LintersSettings.Gomodguard + processorCfg = gomodguard.Configuration{} + ) + processorCfg.Allowed.Modules = linterCfg.Allowed.Modules + processorCfg.Allowed.Domains = linterCfg.Allowed.Domains + for n := range linterCfg.Blocked.Modules { + for k, v := range linterCfg.Blocked.Modules[n] { + m := gomodguard.BlockedModule{k: gomodguard.Recommendations{ + Recommendations: v.Recommendations, + Reason: v.Reason, + }} + processorCfg.Blocked.Modules = append(processorCfg.Blocked.Modules, m) + break + } + } + + for _, file := range pass.Files { + files = append(files, pass.Fset.PositionFor(file.Pos(), false).Filename) + } + + processor, err := gomodguard.NewProcessor(processorCfg, log.New(os.Stderr, "", 0)) + if err != nil { + lintCtx.Log.Warnf("running gomodguard failed: %s: if you are not using go modules "+ + "it is suggested to disable this linter", err) + return nil, nil + } + + gomodguardErrors := processor.ProcessFiles(files) + if len(gomodguardErrors) == 0 { + return nil, nil + } + + mu.Lock() + defer mu.Unlock() + + for _, err := range gomodguardErrors { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + FromLinter: gomodguardName, + Pos: err.Position, + Text: err.Reason, + }, pass)) + } + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return issues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goprintffuncname.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goprintffuncname.go new file mode 100644 index 000000000..c5516dc7f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goprintffuncname.go @@ -0,0 +1,17 @@ +package golinters + +import ( + "github.com/jirfag/go-printf-func-name/pkg/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewGoPrintfFuncName() *goanalysis.Linter { + return goanalysis.NewLinter( + "goprintffuncname", + "Checks that printf-like functions are named with `f` at the end", + []*analysis.Analyzer{analyzer.Analyzer}, + nil, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosec.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosec.go new file mode 100644 index 000000000..08b3e660f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosec.go @@ -0,0 +1,97 @@ +package golinters + +import ( + "fmt" + "go/token" + "io/ioutil" + "log" + "strconv" + "sync" + + "github.com/securego/gosec/v2" + "github.com/securego/gosec/v2/rules" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/packages" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const gosecName = "gosec" + +func NewGosec() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + gasConfig := gosec.NewConfig() + enabledRules := rules.Generate() + logger := log.New(ioutil.Discard, "", 0) + + analyzer := &analysis.Analyzer{ + Name: gosecName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + gosecName, + "Inspects source code for security problems", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + gosecAnalyzer := gosec.NewAnalyzer(gasConfig, true, logger) + gosecAnalyzer.LoadRules(enabledRules.Builders()) + pkg := &packages.Package{ + Fset: pass.Fset, + Syntax: pass.Files, + Types: pass.Pkg, + TypesInfo: pass.TypesInfo, + } + gosecAnalyzer.Check(pkg) + issues, _, _ := gosecAnalyzer.Report() + if len(issues) == 0 { + return nil, nil + } + + res := make([]goanalysis.Issue, 0, len(issues)) + for _, i := range issues { + text := fmt.Sprintf("%s: %s", i.RuleID, i.What) // TODO: use severity and confidence + var r *result.Range + line, err := strconv.Atoi(i.Line) + if err != nil { + r = &result.Range{} + if n, rerr := fmt.Sscanf(i.Line, "%d-%d", &r.From, &r.To); rerr != nil || n != 2 { + lintCtx.Log.Warnf("Can't convert gosec line number %q of %v to int: %s", i.Line, i, err) + continue + } + line = r.From + } + + column, err := strconv.Atoi(i.Col) + if err != nil { + lintCtx.Log.Warnf("Can't convert gosec column number %q of %v to int: %s", i.Col, i, err) + continue + } + + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: token.Position{ + Filename: i.File, + Line: line, + Column: column, + }, + Text: text, + LineRange: r, + FromLinter: gosecName, + }, pass)) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosimple.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosimple.go new file mode 100644 index 000000000..788fc8c63 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosimple.go @@ -0,0 +1,19 @@ +package golinters + +import ( + "honnef.co/go/tools/simple" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewGosimple() *goanalysis.Linter { + analyzers := analyzersMapToSlice(simple.Analyzers) + setAnalyzersGoVersion(analyzers) + + return goanalysis.NewLinter( + "gosimple", + "Linter for Go source code that specializes in simplifying a code", + analyzers, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/govet.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/govet.go new file mode 100644 index 000000000..7ea1f094e --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/govet.go @@ -0,0 +1,165 @@ +package golinters + +import ( + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/asmdecl" + "golang.org/x/tools/go/analysis/passes/assign" + "golang.org/x/tools/go/analysis/passes/atomic" + "golang.org/x/tools/go/analysis/passes/atomicalign" + "golang.org/x/tools/go/analysis/passes/bools" + _ "golang.org/x/tools/go/analysis/passes/buildssa" // unused, internal analyzer + "golang.org/x/tools/go/analysis/passes/buildtag" + "golang.org/x/tools/go/analysis/passes/cgocall" + "golang.org/x/tools/go/analysis/passes/composite" + "golang.org/x/tools/go/analysis/passes/copylock" + _ "golang.org/x/tools/go/analysis/passes/ctrlflow" // unused, internal analyzer + "golang.org/x/tools/go/analysis/passes/deepequalerrors" + "golang.org/x/tools/go/analysis/passes/errorsas" + "golang.org/x/tools/go/analysis/passes/findcall" + "golang.org/x/tools/go/analysis/passes/httpresponse" + _ "golang.org/x/tools/go/analysis/passes/inspect" // unused internal analyzer + "golang.org/x/tools/go/analysis/passes/loopclosure" + "golang.org/x/tools/go/analysis/passes/lostcancel" + "golang.org/x/tools/go/analysis/passes/nilfunc" + "golang.org/x/tools/go/analysis/passes/nilness" + _ "golang.org/x/tools/go/analysis/passes/pkgfact" // unused, internal analyzer + "golang.org/x/tools/go/analysis/passes/printf" + "golang.org/x/tools/go/analysis/passes/shadow" + "golang.org/x/tools/go/analysis/passes/shift" + "golang.org/x/tools/go/analysis/passes/sortslice" + "golang.org/x/tools/go/analysis/passes/stdmethods" + "golang.org/x/tools/go/analysis/passes/structtag" + "golang.org/x/tools/go/analysis/passes/testinggoroutine" + "golang.org/x/tools/go/analysis/passes/tests" + "golang.org/x/tools/go/analysis/passes/unmarshal" + "golang.org/x/tools/go/analysis/passes/unreachable" + "golang.org/x/tools/go/analysis/passes/unsafeptr" + "golang.org/x/tools/go/analysis/passes/unusedresult" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +var ( + allAnalyzers = []*analysis.Analyzer{ + asmdecl.Analyzer, + assign.Analyzer, + atomic.Analyzer, + atomicalign.Analyzer, + bools.Analyzer, + buildtag.Analyzer, + cgocall.Analyzer, + composite.Analyzer, + copylock.Analyzer, + deepequalerrors.Analyzer, + errorsas.Analyzer, + findcall.Analyzer, + httpresponse.Analyzer, + loopclosure.Analyzer, + lostcancel.Analyzer, + nilfunc.Analyzer, + nilness.Analyzer, + printf.Analyzer, + shadow.Analyzer, + shift.Analyzer, + sortslice.Analyzer, + stdmethods.Analyzer, + structtag.Analyzer, + testinggoroutine.Analyzer, + tests.Analyzer, + unmarshal.Analyzer, + unreachable.Analyzer, + unsafeptr.Analyzer, + unusedresult.Analyzer, + } + + defaultAnalyzers = []*analysis.Analyzer{ + asmdecl.Analyzer, + assign.Analyzer, + atomic.Analyzer, + bools.Analyzer, + buildtag.Analyzer, + cgocall.Analyzer, + composite.Analyzer, + copylock.Analyzer, + errorsas.Analyzer, + httpresponse.Analyzer, + loopclosure.Analyzer, + lostcancel.Analyzer, + nilfunc.Analyzer, + printf.Analyzer, + shift.Analyzer, + stdmethods.Analyzer, + structtag.Analyzer, + tests.Analyzer, + unmarshal.Analyzer, + unreachable.Analyzer, + unsafeptr.Analyzer, + unusedresult.Analyzer, + } +) + +func isAnalyzerEnabled(name string, cfg *config.GovetSettings, defaultAnalyzers []*analysis.Analyzer) bool { + if cfg.EnableAll { + for _, n := range cfg.Disable { + if n == name { + return false + } + } + return true + } + // Raw for loops should be OK on small slice lengths. + for _, n := range cfg.Enable { + if n == name { + return true + } + } + for _, n := range cfg.Disable { + if n == name { + return false + } + } + if cfg.DisableAll { + return false + } + for _, a := range defaultAnalyzers { + if a.Name == name { + return true + } + } + return false +} + +func analyzersFromConfig(cfg *config.GovetSettings) []*analysis.Analyzer { + if cfg == nil { + return defaultAnalyzers + } + + if cfg.CheckShadowing { + // Keeping for backward compatibility. + cfg.Enable = append(cfg.Enable, shadow.Analyzer.Name) + } + + var enabledAnalyzers []*analysis.Analyzer + for _, a := range allAnalyzers { + if isAnalyzerEnabled(a.Name, cfg, defaultAnalyzers) { + enabledAnalyzers = append(enabledAnalyzers, a) + } + } + + return enabledAnalyzers +} + +func NewGovet(cfg *config.GovetSettings) *goanalysis.Linter { + var settings map[string]map[string]interface{} + if cfg != nil { + settings = cfg.Settings + } + return goanalysis.NewLinter( + "govet", + "Vet examines Go source code and reports suspicious constructs, "+ + "such as Printf calls whose arguments do not align with the format string", + analyzersFromConfig(cfg), + settings, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/ineffassign.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/ineffassign.go new file mode 100644 index 000000000..93c1fb11b --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/ineffassign.go @@ -0,0 +1,61 @@ +package golinters + +import ( + "fmt" + "sync" + + "github.com/golangci/ineffassign" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const ineffassignName = "ineffassign" + +func NewIneffassign() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: ineffassignName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + ineffassignName, + "Detects when assignments to existing variables are not used", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var fileNames []string + for _, f := range pass.Files { + pos := pass.Fset.PositionFor(f.Pos(), false) + fileNames = append(fileNames, pos.Filename) + } + + issues := ineffassign.Run(fileNames) + if len(issues) == 0 { + return nil, nil + } + + res := make([]goanalysis.Issue, 0, len(issues)) + for _, i := range issues { + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: i.Pos, + Text: fmt.Sprintf("ineffectual assignment to %s", formatCode(i.IdentName, lintCtx.Cfg)), + FromLinter: ineffassignName, + }, pass)) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/interfacer.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/interfacer.go new file mode 100644 index 000000000..1edbe894c --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/interfacer.go @@ -0,0 +1,67 @@ +package golinters + +import ( + "sync" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/buildssa" + "mvdan.cc/interfacer/check" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const interfacerName = "interfacer" + +func NewInterfacer() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: interfacerName, + Doc: goanalysis.TheOnlyanalyzerDoc, + Requires: []*analysis.Analyzer{buildssa.Analyzer}, + } + return goanalysis.NewLinter( + interfacerName, + "Linter that suggests narrower interface types", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + ssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA) + ssaPkg := ssa.Pkg + c := &check.Checker{} + prog := goanalysis.MakeFakeLoaderProgram(pass) + c.Program(prog) + c.ProgramSSA(ssaPkg.Prog) + + issues, err := c.Check() + if err != nil { + return nil, err + } + if len(issues) == 0 { + return nil, nil + } + + res := make([]goanalysis.Issue, 0, len(issues)) + for _, i := range issues { + pos := pass.Fset.Position(i.Pos()) + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: pos, + Text: i.Message(), + FromLinter: interfacerName, + }, pass)) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/lll.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/lll.go new file mode 100644 index 000000000..5f26e91dd --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/lll.go @@ -0,0 +1,124 @@ +package golinters + +import ( + "bufio" + "fmt" + "go/token" + "os" + "strings" + "sync" + "unicode/utf8" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func getLLLIssuesForFile(filename string, maxLineLen int, tabSpaces string) ([]result.Issue, error) { + var res []result.Issue + + f, err := os.Open(filename) + if err != nil { + return nil, fmt.Errorf("can't open file %s: %s", filename, err) + } + defer f.Close() + + lineNumber := 1 + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + line = strings.Replace(line, "\t", tabSpaces, -1) + lineLen := utf8.RuneCountInString(line) + if lineLen > maxLineLen { + res = append(res, result.Issue{ + Pos: token.Position{ + Filename: filename, + Line: lineNumber, + }, + Text: fmt.Sprintf("line is %d characters", lineLen), + FromLinter: lllName, + }) + } + lineNumber++ + } + + if err := scanner.Err(); err != nil { + if err == bufio.ErrTooLong && maxLineLen < bufio.MaxScanTokenSize { + // scanner.Scan() might fail if the line is longer than bufio.MaxScanTokenSize + // In the case where the specified maxLineLen is smaller than bufio.MaxScanTokenSize + // we can return this line as a long line instead of returning an error. + // The reason for this change is that this case might happen with autogenerated files + // The go-bindata tool for instance might generate a file with a very long line. + // In this case, as it's a auto generated file, the warning returned by lll will + // be ignored. + // But if we return a linter error here, and this error happens for an autogenerated + // file the error will be discarded (fine), but all the subsequent errors for lll will + // be discarded for other files and we'll miss legit error. + res = append(res, result.Issue{ + Pos: token.Position{ + Filename: filename, + Line: lineNumber, + Column: 1, + }, + Text: fmt.Sprintf("line is more than %d characters", bufio.MaxScanTokenSize), + FromLinter: lllName, + }) + } else { + return nil, fmt.Errorf("can't scan file %s: %s", filename, err) + } + } + + return res, nil +} + +const lllName = "lll" + +func NewLLL() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: lllName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + lllName, + "Reports long lines", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var fileNames []string + for _, f := range pass.Files { + pos := pass.Fset.PositionFor(f.Pos(), false) + fileNames = append(fileNames, pos.Filename) + } + + var res []goanalysis.Issue + spaces := strings.Repeat(" ", lintCtx.Settings().Lll.TabWidth) + for _, f := range fileNames { + issues, err := getLLLIssuesForFile(f, lintCtx.Settings().Lll.LineLength, spaces) + if err != nil { + return nil, err + } + for i := range issues { + res = append(res, goanalysis.NewIssue(&issues[i], pass)) + } + } + + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/maligned.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/maligned.go new file mode 100644 index 000000000..22422b8c6 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/maligned.go @@ -0,0 +1,58 @@ +package golinters + +import ( + "fmt" + "sync" + + malignedAPI "github.com/golangci/maligned" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewMaligned() *goanalysis.Linter { + const linterName = "maligned" + var mu sync.Mutex + var res []goanalysis.Issue + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + linterName, + "Tool to detect Go structs that would take less memory if their fields were sorted", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + prog := goanalysis.MakeFakeLoaderProgram(pass) + + malignedIssues := malignedAPI.Run(prog) + if len(malignedIssues) == 0 { + return nil, nil + } + + issues := make([]goanalysis.Issue, 0, len(malignedIssues)) + for _, i := range malignedIssues { + text := fmt.Sprintf("struct of size %d bytes could be of size %d bytes", i.OldSize, i.NewSize) + if lintCtx.Settings().Maligned.SuggestNewOrder { + text += fmt.Sprintf(":\n%s", formatCodeBlock(i.NewStructDef, lintCtx.Cfg)) + } + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + Pos: i.Pos, + Text: text, + FromLinter: linterName, + }, pass)) + } + + mu.Lock() + res = append(res, issues...) + mu.Unlock() + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return res + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/megacheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/megacheck.go new file mode 100644 index 000000000..85621f6fb --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/megacheck.go @@ -0,0 +1,30 @@ +package golinters + +import ( + "fmt" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/logutils" +) + +var debugf = logutils.Debug("megacheck") + +func analyzersMapToSlice(m map[string]*analysis.Analyzer) []*analysis.Analyzer { + var ret []*analysis.Analyzer + for _, v := range m { + ret = append(ret, v) + } + return ret +} + +func setAnalyzersGoVersion(analyzers []*analysis.Analyzer) { + const goVersion = 13 // TODO + for _, a := range analyzers { + if v := a.Flags.Lookup("go"); v != nil { + if err := v.Value.Set(fmt.Sprintf("1.%d", goVersion)); err != nil { + debugf("Failed to set go version: %s", err) + } + } + } +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/misspell.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/misspell.go new file mode 100644 index 000000000..80ecf9bb6 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/misspell.go @@ -0,0 +1,132 @@ +package golinters + +import ( + "fmt" + "go/token" + "strings" + "sync" + + "github.com/golangci/misspell" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func runMisspellOnFile(fileName string, r *misspell.Replacer, lintCtx *linter.Context) ([]result.Issue, error) { + var res []result.Issue + fileContent, err := lintCtx.FileCache.GetFileBytes(fileName) + if err != nil { + return nil, fmt.Errorf("can't get file %s contents: %s", fileName, err) + } + + // use r.Replace, not r.ReplaceGo because r.ReplaceGo doesn't find + // issues inside strings: it searches only inside comments. r.Replace + // searches all words: it treats input as a plain text. A standalone misspell + // tool uses r.Replace by default. + _, diffs := r.Replace(string(fileContent)) + for _, diff := range diffs { + text := fmt.Sprintf("`%s` is a misspelling of `%s`", diff.Original, diff.Corrected) + pos := token.Position{ + Filename: fileName, + Line: diff.Line, + Column: diff.Column + 1, + } + replacement := &result.Replacement{ + Inline: &result.InlineFix{ + StartCol: diff.Column, + Length: len(diff.Original), + NewString: diff.Corrected, + }, + } + + res = append(res, result.Issue{ + Pos: pos, + Text: text, + FromLinter: misspellName, + Replacement: replacement, + }) + } + + return res, nil +} + +const misspellName = "misspell" + +func NewMisspell() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + var ruleErr error + + analyzer := &analysis.Analyzer{ + Name: misspellName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + misspellName, + "Finds commonly misspelled English words in comments", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + r := misspell.Replacer{ + Replacements: misspell.DictMain, + } + + // Figure out regional variations + settings := lintCtx.Settings().Misspell + locale := settings.Locale + switch strings.ToUpper(locale) { + case "": + // nothing + case "US": + r.AddRuleList(misspell.DictAmerican) + case "UK", "GB": + r.AddRuleList(misspell.DictBritish) + case "NZ", "AU", "CA": + ruleErr = fmt.Errorf("unknown locale: %q", locale) + } + + if ruleErr == nil { + if len(settings.IgnoreWords) != 0 { + r.RemoveRule(settings.IgnoreWords) + } + + r.Compile() + } + + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + if ruleErr != nil { + return nil, ruleErr + } + + var fileNames []string + for _, f := range pass.Files { + pos := pass.Fset.PositionFor(f.Pos(), false) + fileNames = append(fileNames, pos.Filename) + } + + var res []goanalysis.Issue + for _, f := range fileNames { + issues, err := runMisspellOnFile(f, &r, lintCtx) + if err != nil { + return nil, err + } + for i := range issues { + res = append(res, goanalysis.NewIssue(&issues[i], pass)) + } + } + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/nakedret.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nakedret.go new file mode 100644 index 000000000..86735a51a --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nakedret.go @@ -0,0 +1,123 @@ +package golinters + +import ( + "fmt" + "go/ast" + "go/token" + "sync" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +type nakedretVisitor struct { + maxLength int + f *token.FileSet + issues []result.Issue +} + +func (v *nakedretVisitor) processFuncDecl(funcDecl *ast.FuncDecl) { + file := v.f.File(funcDecl.Pos()) + functionLineLength := file.Position(funcDecl.End()).Line - file.Position(funcDecl.Pos()).Line + + // Scan the body for usage of the named returns + for _, stmt := range funcDecl.Body.List { + s, ok := stmt.(*ast.ReturnStmt) + if !ok { + continue + } + + if len(s.Results) != 0 { + continue + } + + file := v.f.File(s.Pos()) + if file == nil || functionLineLength <= v.maxLength { + continue + } + if funcDecl.Name == nil { + continue + } + + v.issues = append(v.issues, result.Issue{ + FromLinter: nakedretName, + Text: fmt.Sprintf("naked return in func `%s` with %d lines of code", + funcDecl.Name.Name, functionLineLength), + Pos: v.f.Position(s.Pos()), + }) + } +} + +func (v *nakedretVisitor) Visit(node ast.Node) ast.Visitor { + funcDecl, ok := node.(*ast.FuncDecl) + if !ok { + return v + } + + var namedReturns []*ast.Ident + + // We've found a function + if funcDecl.Type != nil && funcDecl.Type.Results != nil { + for _, field := range funcDecl.Type.Results.List { + for _, ident := range field.Names { + if ident != nil { + namedReturns = append(namedReturns, ident) + } + } + } + } + + if len(namedReturns) == 0 || funcDecl.Body == nil { + return v + } + + v.processFuncDecl(funcDecl) + return v +} + +const nakedretName = "nakedret" + +func NewNakedret() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: nakedretName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + nakedretName, + "Finds naked returns in functions greater than a specified function length", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var res []goanalysis.Issue + for _, file := range pass.Files { + v := nakedretVisitor{ + maxLength: lintCtx.Settings().Nakedret.MaxFuncLines, + f: pass.Fset, + } + ast.Walk(&v, file) + for i := range v.issues { + res = append(res, goanalysis.NewIssue(&v.issues[i], pass)) + } + } + + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/nestif.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nestif.go new file mode 100644 index 000000000..0998a8ce2 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nestif.go @@ -0,0 +1,65 @@ +package golinters + +import ( + "sort" + "sync" + + "github.com/nakabonne/nestif" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const nestifName = "nestif" + +func NewNestif() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: goanalysis.TheOnlyAnalyzerName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + nestifName, + "Reports deeply nested if statements", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + checker := &nestif.Checker{ + MinComplexity: lintCtx.Settings().Nestif.MinComplexity, + } + var issues []nestif.Issue + for _, f := range pass.Files { + issues = append(issues, checker.Check(f, pass.Fset)...) + } + if len(issues) == 0 { + return nil, nil + } + + sort.SliceStable(issues, func(i, j int) bool { + return issues[i].Complexity > issues[j].Complexity + }) + + res := make([]goanalysis.Issue, 0, len(issues)) + for _, i := range issues { + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: i.Pos, + Text: i.Message, + FromLinter: nestifName, + }, pass)) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint.go new file mode 100644 index 000000000..d98b50cf8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint.go @@ -0,0 +1,92 @@ +package golinters + +import ( + "fmt" + "go/ast" + "sync" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/golinters/nolintlint" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const NolintlintName = "nolintlint" + +func NewNoLintLint() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: NolintlintName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + NolintlintName, + "Reports ill-formed or insufficient nolint directives", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var needs nolintlint.Needs + settings := lintCtx.Settings().NoLintLint + if settings.RequireExplanation { + needs |= nolintlint.NeedsExplanation + } + if !settings.AllowLeadingSpace { + needs |= nolintlint.NeedsMachineOnly + } + if settings.RequireSpecific { + needs |= nolintlint.NeedsSpecific + } + if !settings.AllowUnused { + needs |= nolintlint.NeedsUnused + } + + lnt, err := nolintlint.NewLinter(needs, settings.AllowNoExplanation) + if err != nil { + return nil, err + } + + nodes := make([]ast.Node, 0, len(pass.Files)) + for _, n := range pass.Files { + nodes = append(nodes, n) + } + issues, err := lnt.Run(pass.Fset, nodes...) + if err != nil { + return nil, fmt.Errorf("linter failed to run: %s", err) + } + var res []goanalysis.Issue + for _, i := range issues { + expectNoLint := false + var expectedNolintLinter string + if ii, ok := i.(nolintlint.UnusedCandidate); ok { + expectedNolintLinter = ii.ExpectedLinter + expectNoLint = true + } + issue := &result.Issue{ + FromLinter: NolintlintName, + Text: i.Details(), + Pos: i.Position(), + ExpectNoLint: expectNoLint, + ExpectedNoLintLinter: expectedNolintLinter, + } + res = append(res, goanalysis.NewIssue(issue, pass)) + } + + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint/README.md b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint/README.md new file mode 100644 index 000000000..3d440d5a5 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint/README.md @@ -0,0 +1,31 @@ +# nolintlint + +nolintlint is a Go static analysis tool to find ill-formed or insufficiently explained `// nolint` directives for golangci +(or any other linter, using th ) + +## Purpose + +To ensure that lint exceptions have explanations. Consider the case below: + +```Go +import "crypto/md5" //nolint + +func hash(data []byte) []byte { + return md5.New().Sum(data) //nolint +} +``` + +In the above case, nolint directives are present but the user has no idea why this is being done or which linter +is being suppressed (in this case, gosec recommends against use of md5). `nolintlint` can require that the code provide an explanation, which might look as follows: + +```Go +import "crypto/md5" //nolint:gosec // this is not used in a secure application + +func hash(data []byte) []byte { + return md5.New().Sum(data) //nolint:gosec // this result is not used in a secure application +} +``` + +`nolintlint` can also identify cases where you may have written `// nolint`. Finally `nolintlint`, can also enforce that you +use the machine-readable nolint directive format `//nolint` and that you mention what linter is being suppressed, as shown above when we write `//nolint:gosec`. + diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint/nolintlint.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint/nolintlint.go new file mode 100644 index 000000000..6da31c60f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nolintlint/nolintlint.go @@ -0,0 +1,239 @@ +// nolintlint provides a linter to ensure that all //nolint directives are followed by explanations +package nolintlint + +import ( + "fmt" + "go/ast" + "go/token" + "regexp" + "strings" + "unicode" +) + +type BaseIssue struct { + fullDirective string + directiveWithOptionalLeadingSpace string + position token.Position +} + +func (b BaseIssue) Position() token.Position { + return b.position +} + +type ExtraLeadingSpace struct { + BaseIssue +} + +func (i ExtraLeadingSpace) Details() string { + return fmt.Sprintf("directive `%s` should not have more than one leading space", i.fullDirective) +} + +func (i ExtraLeadingSpace) String() string { return toString(i) } + +type NotMachine struct { + BaseIssue +} + +func (i NotMachine) Details() string { + expected := i.fullDirective[:2] + strings.TrimLeftFunc(i.fullDirective[2:], unicode.IsSpace) + return fmt.Sprintf("directive `%s` should be written without leading space as `%s`", + i.fullDirective, expected) +} + +func (i NotMachine) String() string { return toString(i) } + +type NotSpecific struct { + BaseIssue +} + +func (i NotSpecific) Details() string { + return fmt.Sprintf("directive `%s` should mention specific linter such as `//%s:my-linter`", + i.fullDirective, i.directiveWithOptionalLeadingSpace) +} + +func (i NotSpecific) String() string { return toString(i) } + +type ParseError struct { + BaseIssue +} + +func (i ParseError) Details() string { + return fmt.Sprintf("directive `%s` should match `//%s[:] [// ]`", + i.fullDirective, + i.directiveWithOptionalLeadingSpace) +} + +func (i ParseError) String() string { return toString(i) } + +type NoExplanation struct { + BaseIssue + fullDirectiveWithoutExplanation string +} + +func (i NoExplanation) Details() string { + return fmt.Sprintf("directive `%s` should provide explanation such as `%s // this is why`", + i.fullDirective, i.fullDirectiveWithoutExplanation) +} + +func (i NoExplanation) String() string { return toString(i) } + +type UnusedCandidate struct { + BaseIssue + ExpectedLinter string +} + +func (i UnusedCandidate) Details() string { + details := fmt.Sprintf("directive `%s` is unused", i.fullDirective) + if i.ExpectedLinter != "" { + details += fmt.Sprintf(" for linter %s", i.ExpectedLinter) + } + return details +} + +func (i UnusedCandidate) String() string { return toString(i) } + +func toString(i Issue) string { + return fmt.Sprintf("%s at %s", i.Details(), i.Position()) +} + +type Issue interface { + Details() string + Position() token.Position + String() string +} + +type Needs uint + +const ( + NeedsMachineOnly Needs = 1 << iota + NeedsSpecific + NeedsExplanation + NeedsUnused + NeedsAll = NeedsMachineOnly | NeedsSpecific | NeedsExplanation +) + +// matches lines starting with the nolint directive +var directiveOnlyPattern = regexp.MustCompile(`^\s*(nolint)(:\s*[\w-]+\s*(?:,\s*[\w-]+\s*)*)?\b`) + +// matches a complete nolint directive +var fullDirectivePattern = regexp.MustCompile(`^//\s*nolint(:\s*[\w-]+\s*(?:,\s*[\w-]+\s*)*)?\s*(//.*)?\s*\n?$`) + +type Linter struct { + excludes []string // lists individual linters that don't require explanations + needs Needs // indicates which linter checks to perform + excludeByLinter map[string]bool +} + +// NewLinter creates a linter that enforces that the provided directives fulfill the provided requirements +func NewLinter(needs Needs, excludes []string) (*Linter, error) { + excludeByName := make(map[string]bool) + for _, e := range excludes { + excludeByName[e] = true + } + + return &Linter{ + needs: needs, + excludeByLinter: excludeByName, + }, nil +} + +var leadingSpacePattern = regexp.MustCompile(`^//(\s*)`) +var trailingBlankExplanation = regexp.MustCompile(`\s*(//\s*)?$`) + +func (l Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) { + var issues []Issue + for _, node := range nodes { + if file, ok := node.(*ast.File); ok { + for _, c := range file.Comments { + text := c.Text() + matches := directiveOnlyPattern.FindStringSubmatch(text) + if len(matches) == 0 { + continue + } + directive := matches[1] + + // check for a space between the "//" and the directive + leadingSpaceMatches := leadingSpacePattern.FindStringSubmatch(c.List[0].Text) // c.Text() doesn't have all leading space + if len(leadingSpaceMatches) == 0 { + continue + } + leadingSpace := leadingSpaceMatches[1] + + directiveWithOptionalLeadingSpace := directive + if len(leadingSpace) > 0 { + directiveWithOptionalLeadingSpace = " " + directive + } + + base := BaseIssue{ + fullDirective: c.List[0].Text, + directiveWithOptionalLeadingSpace: directiveWithOptionalLeadingSpace, + position: fset.Position(c.Pos()), + } + + // check for, report and eliminate leading spaces so we can check for other issues + if leadingSpace != "" && leadingSpace != " " { + issues = append(issues, ExtraLeadingSpace{ + BaseIssue: base, + }) + } + + if (l.needs&NeedsMachineOnly) != 0 && strings.HasPrefix(directiveWithOptionalLeadingSpace, " ") { + issues = append(issues, NotMachine{BaseIssue: base}) + } + + fullMatches := fullDirectivePattern.FindStringSubmatch(c.List[0].Text) + if len(fullMatches) == 0 { + issues = append(issues, ParseError{BaseIssue: base}) + continue + } + lintersText, explanation := fullMatches[1], fullMatches[2] + var linters []string + if len(lintersText) > 0 { + lls := strings.Split(lintersText[1:], ",") + linters = make([]string, 0, len(lls)) + for _, ll := range lls { + ll = strings.TrimSpace(ll) + if ll != "" { + linters = append(linters, ll) + } + } + } + if (l.needs & NeedsSpecific) != 0 { + if len(linters) == 0 { + issues = append(issues, NotSpecific{BaseIssue: base}) + } + } + + // when detecting unused directives, we send all the directives through and filter them out in the nolint processor + if l.needs&NeedsUnused != 0 { + if len(linters) == 0 { + issues = append(issues, UnusedCandidate{BaseIssue: base}) + } else { + for _, linter := range linters { + issues = append(issues, UnusedCandidate{BaseIssue: base, ExpectedLinter: linter}) + } + } + } + + if (l.needs&NeedsExplanation) != 0 && (explanation == "" || strings.TrimSpace(explanation) == "//") { + needsExplanation := len(linters) == 0 // if no linters are mentioned, we must have explanation + // otherwise, check if we are excluding all of the mentioned linters + for _, ll := range linters { + if !l.excludeByLinter[ll] { // if a linter does require explanation + needsExplanation = true + break + } + } + if needsExplanation { + fullDirectiveWithoutExplanation := trailingBlankExplanation.ReplaceAllString(c.List[0].Text, "") + issues = append(issues, NoExplanation{ + BaseIssue: base, + fullDirectiveWithoutExplanation: fullDirectiveWithoutExplanation, + }) + } + } + } + } + } + return issues, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/prealloc.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/prealloc.go new file mode 100644 index 000000000..534a69253 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/prealloc.go @@ -0,0 +1,57 @@ +package golinters + +import ( + "fmt" + "sync" + + "github.com/golangci/prealloc" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const preallocName = "prealloc" + +func NewPrealloc() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: preallocName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + preallocName, + "Finds slice declarations that could potentially be preallocated", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + s := &lintCtx.Settings().Prealloc + + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var res []goanalysis.Issue + hints := prealloc.Check(pass.Files, s.Simple, s.RangeLoops, s.ForLoops) + for _, hint := range hints { + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: pass.Fset.Position(hint.Pos), + Text: fmt.Sprintf("Consider preallocating %s", formatCode(hint.DeclaredSliceName, lintCtx.Cfg)), + FromLinter: preallocName, + }, pass)) + } + + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/rowerrcheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/rowerrcheck.go new file mode 100644 index 000000000..d4c89d382 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/rowerrcheck.go @@ -0,0 +1,23 @@ +package golinters + +import ( + "github.com/jingyugao/rowserrcheck/passes/rowserr" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" +) + +func NewRowsErrCheck() *goanalysis.Linter { + analyzer := rowserr.NewAnalyzer() + return goanalysis.NewLinter( + "rowserrcheck", + "checks whether Err of rows is checked successfully", + []*analysis.Analyzer{analyzer}, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo). + WithContextSetter(func(lintCtx *linter.Context) { + pkgs := lintCtx.Settings().RowsErrCheck.Packages + analyzer.Run = rowserr.NewRun(pkgs...) + }) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/scopelint.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/scopelint.go new file mode 100644 index 000000000..258912e0b --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/scopelint.go @@ -0,0 +1,178 @@ +package golinters + +import ( + "fmt" + "go/ast" + "go/token" + "sync" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const scopelintName = "scopelint" + +func NewScopelint() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: scopelintName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + scopelintName, + "Scopelint checks for unpinned variables in go programs", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var res []result.Issue + for _, file := range pass.Files { + n := Node{ + fset: pass.Fset, + DangerObjects: map[*ast.Object]int{}, + UnsafeObjects: map[*ast.Object]int{}, + SkipFuncs: map[*ast.FuncLit]int{}, + issues: &res, + } + ast.Walk(&n, file) + } + + if len(res) == 0 { + return nil, nil + } + + mu.Lock() + for i := range res { + resIssues = append(resIssues, goanalysis.NewIssue(&res[i], pass)) + } + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} + +// The code below is copy-pasted from https://github.com/kyoh86/scopelint 92cbe2cc9276abda0e309f52cc9e309d407f174e + +// Node represents a Node being linted. +type Node struct { + fset *token.FileSet + DangerObjects map[*ast.Object]int + UnsafeObjects map[*ast.Object]int + SkipFuncs map[*ast.FuncLit]int + issues *[]result.Issue +} + +// Visit method is invoked for each node encountered by Walk. +// If the result visitor w is not nil, Walk visits each of the children +// of node with the visitor w, followed by a call of w.Visit(nil). +//nolint:gocyclo,gocritic +func (f *Node) Visit(node ast.Node) ast.Visitor { + switch typedNode := node.(type) { + case *ast.ForStmt: + switch init := typedNode.Init.(type) { + case *ast.AssignStmt: + for _, lh := range init.Lhs { + switch tlh := lh.(type) { + case *ast.Ident: + f.UnsafeObjects[tlh.Obj] = 0 + } + } + } + + case *ast.RangeStmt: + // Memory variables declared in range statement + switch k := typedNode.Key.(type) { + case *ast.Ident: + f.UnsafeObjects[k.Obj] = 0 + } + switch v := typedNode.Value.(type) { + case *ast.Ident: + f.UnsafeObjects[v.Obj] = 0 + } + + case *ast.UnaryExpr: + if typedNode.Op == token.AND { + switch ident := typedNode.X.(type) { + case *ast.Ident: + if _, unsafe := f.UnsafeObjects[ident.Obj]; unsafe { + f.errorf(ident, "Using a reference for the variable on range scope %s", formatCode(ident.Name, nil)) + } + } + } + + case *ast.Ident: + if _, obj := f.DangerObjects[typedNode.Obj]; obj { + // It is the naked variable in scope of range statement. + f.errorf(node, "Using the variable on range scope %s in function literal", formatCode(typedNode.Name, nil)) + break + } + + case *ast.CallExpr: + // Ignore func literals that'll be called immediately. + switch funcLit := typedNode.Fun.(type) { + case *ast.FuncLit: + f.SkipFuncs[funcLit] = 0 + } + + case *ast.FuncLit: + if _, skip := f.SkipFuncs[typedNode]; !skip { + dangers := map[*ast.Object]int{} + for d := range f.DangerObjects { + dangers[d] = 0 + } + for u := range f.UnsafeObjects { + dangers[u] = 0 + f.UnsafeObjects[u]++ + } + return &Node{ + fset: f.fset, + DangerObjects: dangers, + UnsafeObjects: f.UnsafeObjects, + SkipFuncs: f.SkipFuncs, + issues: f.issues, + } + } + + case *ast.ReturnStmt: + unsafe := map[*ast.Object]int{} + for u := range f.UnsafeObjects { + if f.UnsafeObjects[u] == 0 { + continue + } + unsafe[u] = f.UnsafeObjects[u] + } + return &Node{ + fset: f.fset, + DangerObjects: f.DangerObjects, + UnsafeObjects: unsafe, + SkipFuncs: f.SkipFuncs, + issues: f.issues, + } + } + return f +} + +// The variadic arguments may start with link and category types, +// and must end with a format string and any arguments. +// It returns the new Problem. +//nolint:interfacer +func (f *Node) errorf(n ast.Node, format string, args ...interface{}) { + pos := f.fset.Position(n.Pos()) + f.errorAtf(pos, format, args...) +} + +func (f *Node) errorAtf(pos token.Position, format string, args ...interface{}) { + *f.issues = append(*f.issues, result.Issue{ + Pos: pos, + Text: fmt.Sprintf(format, args...), + FromLinter: scopelintName, + }) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/staticcheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/staticcheck.go new file mode 100644 index 000000000..33aa921e6 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/staticcheck.go @@ -0,0 +1,19 @@ +package golinters + +import ( + "honnef.co/go/tools/staticcheck" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewStaticcheck() *goanalysis.Linter { + analyzers := analyzersMapToSlice(staticcheck.Analyzers) + setAnalyzersGoVersion(analyzers) + + return goanalysis.NewLinter( + "staticcheck", + "Staticcheck is a go vet on steroids, applying a ton of static analysis checks", + analyzers, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/structcheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/structcheck.go new file mode 100644 index 000000000..7c16f8ec3 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/structcheck.go @@ -0,0 +1,55 @@ +package golinters // nolint:dupl + +import ( + "fmt" + "sync" + + structcheckAPI "github.com/golangci/check/cmd/structcheck" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewStructcheck() *goanalysis.Linter { + const linterName = "structcheck" + var mu sync.Mutex + var res []goanalysis.Issue + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + linterName, + "Finds unused struct fields", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + checkExported := lintCtx.Settings().Structcheck.CheckExportedFields + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + prog := goanalysis.MakeFakeLoaderProgram(pass) + + structcheckIssues := structcheckAPI.Run(prog, checkExported) + if len(structcheckIssues) == 0 { + return nil, nil + } + + issues := make([]goanalysis.Issue, 0, len(structcheckIssues)) + for _, i := range structcheckIssues { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + Pos: i.Pos, + Text: fmt.Sprintf("%s is unused", formatCode(i.FieldName, lintCtx.Cfg)), + FromLinter: linterName, + }, pass)) + } + + mu.Lock() + res = append(res, issues...) + mu.Unlock() + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return res + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/stylecheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/stylecheck.go new file mode 100644 index 000000000..5a076951a --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/stylecheck.go @@ -0,0 +1,19 @@ +package golinters + +import ( + "honnef.co/go/tools/stylecheck" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewStylecheck() *goanalysis.Linter { + analyzers := analyzersMapToSlice(stylecheck.Analyzers) + setAnalyzersGoVersion(analyzers) + + return goanalysis.NewLinter( + "stylecheck", + "Stylecheck is a replacement for golint", + analyzers, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/testpackage.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/testpackage.go new file mode 100644 index 000000000..1248e78fd --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/testpackage.go @@ -0,0 +1,23 @@ +package golinters + +import ( + "github.com/maratori/testpackage/pkg/testpackage" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewTestpackage(cfg *config.TestpackageSettings) *goanalysis.Linter { + var a = testpackage.NewAnalyzer() + var settings map[string]map[string]interface{} + if cfg != nil { + settings = map[string]map[string]interface{}{ + a.Name: { + testpackage.SkipRegexpFlagName: cfg.SkipRegexp, + }, + } + } + return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, settings). + WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/typecheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/typecheck.go new file mode 100644 index 000000000..436530a8d --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/typecheck.go @@ -0,0 +1,26 @@ +package golinters + +import ( + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewTypecheck() *goanalysis.Linter { + const linterName = "typecheck" + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + Run: func(pass *analysis.Pass) (interface{}, error) { + return nil, nil + }, + } + linter := goanalysis.NewLinter( + linterName, + "Like the front-end of a Go compiler, parses and type-checks Go code", + []*analysis.Analyzer{analyzer}, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) + linter.SetTypecheckMode() + return linter +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/unconvert.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/unconvert.go new file mode 100644 index 000000000..456f6836c --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/unconvert.go @@ -0,0 +1,53 @@ +package golinters + +import ( + "sync" + + unconvertAPI "github.com/golangci/unconvert" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewUnconvert() *goanalysis.Linter { + const linterName = "unconvert" + var mu sync.Mutex + var res []goanalysis.Issue + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + linterName, + "Remove unnecessary type conversions", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + prog := goanalysis.MakeFakeLoaderProgram(pass) + + positions := unconvertAPI.Run(prog) + if len(positions) == 0 { + return nil, nil + } + + issues := make([]goanalysis.Issue, 0, len(positions)) + for _, pos := range positions { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + Pos: pos, + Text: "unnecessary conversion", + FromLinter: linterName, + }, pass)) + } + + mu.Lock() + res = append(res, issues...) + mu.Unlock() + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return res + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/unparam.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/unparam.go new file mode 100644 index 000000000..fabb6b527 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/unparam.go @@ -0,0 +1,77 @@ +package golinters + +import ( + "sync" + + "golang.org/x/tools/go/packages" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/buildssa" + "mvdan.cc/unparam/check" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewUnparam() *goanalysis.Linter { + const linterName = "unparam" + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + Requires: []*analysis.Analyzer{buildssa.Analyzer}, + } + return goanalysis.NewLinter( + linterName, + "Reports unused function parameters", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + us := &lintCtx.Settings().Unparam + if us.Algo != "cha" { + lintCtx.Log.Warnf("`linters-settings.unparam.algo` isn't supported by the newest `unparam`") + } + + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + ssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA) + ssaPkg := ssa.Pkg + + pkg := &packages.Package{ + Fset: pass.Fset, + Syntax: pass.Files, + Types: pass.Pkg, + TypesInfo: pass.TypesInfo, + } + + c := &check.Checker{} + c.CheckExportedFuncs(us.CheckExported) + c.Packages([]*packages.Package{pkg}) + c.ProgramSSA(ssaPkg.Prog) + + unparamIssues, err := c.Check() + if err != nil { + return nil, err + } + + var res []goanalysis.Issue + for _, i := range unparamIssues { + res = append(res, goanalysis.NewIssue(&result.Issue{ + Pos: pass.Fset.Position(i.Pos()), + Text: i.Message(), + FromLinter: linterName, + }, pass)) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/unused.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/unused.go new file mode 100644 index 000000000..bbe1e4b69 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/unused.go @@ -0,0 +1,65 @@ +package golinters + +import ( + "go/types" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/packages" + "honnef.co/go/tools/unused" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewUnused() *goanalysis.Linter { + u := unused.NewChecker(false) + analyzers := []*analysis.Analyzer{u.Analyzer()} + setAnalyzersGoVersion(analyzers) + + const name = "unused" + lnt := goanalysis.NewLinter( + name, + "Checks Go code for unused constants, variables, functions and types", + analyzers, + nil, + ).WithIssuesReporter(func(lintCtx *linter.Context) []goanalysis.Issue { + typesToPkg := map[*types.Package]*packages.Package{} + for _, pkg := range lintCtx.OriginalPackages { + typesToPkg[pkg.Types] = pkg + } + + var issues []goanalysis.Issue + for _, ur := range u.Result() { + p := u.ProblemObject(lintCtx.Packages[0].Fset, ur) + pkg := typesToPkg[ur.Pkg()] + i := &result.Issue{ + FromLinter: name, + Text: p.Message, + Pos: p.Pos, + Pkg: pkg, + LineRange: &result.Range{ + From: p.Pos.Line, + To: p.End.Line, + }, + } + // See https://github.com/golangci/golangci-lint/issues/1048 + // If range is invalid, this will break `--fix` mode. + if i.LineRange.To >= i.LineRange.From { + i.Replacement = &result.Replacement{ + // Suggest deleting unused stuff. + NeedOnlyDelete: true, + } + } + issues = append(issues, goanalysis.NewIssue(i, nil)) + } + return issues + }).WithContextSetter(func(lintCtx *linter.Context) { + if lintCtx.Settings().Unused.CheckExported { + lintCtx.Log.Infof("Using whole program analysis for unused, it can be memory-heavy") + u.WholeProgram = true + } + }).WithLoadMode(goanalysis.LoadModeWholeProgram) + lnt.UseOriginalPackages() + return lnt +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/util.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/util.go new file mode 100644 index 000000000..1940f30e3 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/util.go @@ -0,0 +1,24 @@ +package golinters + +import ( + "fmt" + "strings" + + "github.com/golangci/golangci-lint/pkg/config" +) + +func formatCode(code string, _ *config.Config) string { + if strings.Contains(code, "`") { + return code // TODO: properly escape or remove + } + + return fmt.Sprintf("`%s`", code) +} + +func formatCodeBlock(code string, _ *config.Config) string { + if strings.Contains(code, "`") { + return code // TODO: properly escape or remove + } + + return fmt.Sprintf("```\n%s\n```", code) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/varcheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/varcheck.go new file mode 100644 index 000000000..dcf2e7de8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/varcheck.go @@ -0,0 +1,55 @@ +package golinters // nolint:dupl + +import ( + "fmt" + "sync" + + varcheckAPI "github.com/golangci/check/cmd/varcheck" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewVarcheck() *goanalysis.Linter { + const linterName = "varcheck" + var mu sync.Mutex + var res []goanalysis.Issue + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + linterName, + "Finds unused global variables and constants", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + checkExported := lintCtx.Settings().Varcheck.CheckExportedFields + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + prog := goanalysis.MakeFakeLoaderProgram(pass) + + varcheckIssues := varcheckAPI.Run(prog, checkExported) + if len(varcheckIssues) == 0 { + return nil, nil + } + + issues := make([]goanalysis.Issue, 0, len(varcheckIssues)) + for _, i := range varcheckIssues { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + Pos: i.Pos, + Text: fmt.Sprintf("%s is unused", formatCode(i.VarName, lintCtx.Cfg)), + FromLinter: linterName, + }, pass)) + } + + mu.Lock() + res = append(res, issues...) + mu.Unlock() + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return res + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/whitespace.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/whitespace.go new file mode 100644 index 000000000..d475465a2 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/whitespace.go @@ -0,0 +1,85 @@ +package golinters + +import ( + "go/token" + "sync" + + "github.com/pkg/errors" + "github.com/ultraware/whitespace" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewWhitespace() *goanalysis.Linter { + const linterName = "whitespace" + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: linterName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + return goanalysis.NewLinter( + linterName, + "Tool for detection of leading and trailing whitespace", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + cfg := lintCtx.Cfg.LintersSettings.Whitespace + settings := whitespace.Settings{MultiIf: cfg.MultiIf, MultiFunc: cfg.MultiFunc} + + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var issues []whitespace.Message + for _, file := range pass.Files { + issues = append(issues, whitespace.Run(file, pass.Fset, settings)...) + } + + if len(issues) == 0 { + return nil, nil + } + + res := make([]goanalysis.Issue, len(issues)) + for k, i := range issues { + issue := result.Issue{ + Pos: token.Position{ + Filename: i.Pos.Filename, + Line: i.Pos.Line, + }, + LineRange: &result.Range{From: i.Pos.Line, To: i.Pos.Line}, + Text: i.Message, + FromLinter: linterName, + Replacement: &result.Replacement{}, + } + + bracketLine, err := lintCtx.LineCache.GetLine(issue.Pos.Filename, issue.Pos.Line) + if err != nil { + return nil, errors.Wrapf(err, "failed to get line %s:%d", issue.Pos.Filename, issue.Pos.Line) + } + + switch i.Type { + case whitespace.MessageTypeLeading: + issue.LineRange.To++ // cover two lines by the issue: opening bracket "{" (issue.Pos.Line) and following empty line + case whitespace.MessageTypeTrailing: + issue.LineRange.From-- // cover two lines by the issue: closing bracket "}" (issue.Pos.Line) and preceding empty line + issue.Pos.Line-- // set in sync with LineRange.From to not break fixer and other code features + case whitespace.MessageTypeAddAfter: + bracketLine += "\n" + } + issue.Replacement.NewLines = []string{bracketLine} + + res[k] = goanalysis.NewIssue(&issue, pass) + } + + mu.Lock() + resIssues = append(resIssues, res...) + mu.Unlock() + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/wsl.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/wsl.go new file mode 100644 index 000000000..ca659ac4e --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/wsl.go @@ -0,0 +1,81 @@ +package golinters + +import ( + "sync" + + "github.com/bombsimon/wsl/v3" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const ( + name = "wsl" +) + +// NewWSL returns a new WSL linter. +func NewWSL() *goanalysis.Linter { + var ( + issues []goanalysis.Issue + mu = sync.Mutex{} + analyzer = &analysis.Analyzer{ + Name: goanalysis.TheOnlyAnalyzerName, + Doc: goanalysis.TheOnlyanalyzerDoc, + } + ) + + return goanalysis.NewLinter( + name, + "Whitespace Linter - Forces you to use empty lines!", + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + var ( + files = []string{} + linterCfg = lintCtx.Cfg.LintersSettings.WSL + processorCfg = wsl.Configuration{ + StrictAppend: linterCfg.StrictAppend, + AllowAssignAndCallCuddle: linterCfg.AllowAssignAndCallCuddle, + AllowMultiLineAssignCuddle: linterCfg.AllowMultiLineAssignCuddle, + AllowCuddleDeclaration: linterCfg.AllowCuddleDeclaration, + AllowTrailingComment: linterCfg.AllowTrailingComment, + AllowSeparatedLeadingComment: linterCfg.AllowSeparatedLeadingComment, + ForceCuddleErrCheckAndAssign: linterCfg.ForceCuddleErrCheckAndAssign, + ForceCaseTrailingWhitespaceLimit: linterCfg.ForceCaseTrailingWhitespaceLimit, + AllowCuddleWithCalls: []string{"Lock", "RLock"}, + AllowCuddleWithRHS: []string{"Unlock", "RUnlock"}, + ErrorVariableNames: []string{"err"}, + } + ) + + for _, file := range pass.Files { + files = append(files, pass.Fset.PositionFor(file.Pos(), false).Filename) + } + + wslErrors, _ := wsl.NewProcessorWithConfig(processorCfg). + ProcessFiles(files) + + if len(wslErrors) == 0 { + return nil, nil + } + + mu.Lock() + defer mu.Unlock() + + for _, err := range wslErrors { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + FromLinter: name, + Pos: err.Position, + Text: err.Reason, + }, pass)) + } + + return nil, nil + } + }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return issues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/goutil/env.go b/vendor/github.com/golangci/golangci-lint/pkg/goutil/env.go new file mode 100644 index 000000000..1c05b9805 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/goutil/env.go @@ -0,0 +1,61 @@ +package goutil + +import ( + "context" + "encoding/json" + "os" + "os/exec" + "strings" + "time" + + "github.com/pkg/errors" + + "github.com/golangci/golangci-lint/pkg/logutils" +) + +type EnvKey string + +const ( + EnvGoCache EnvKey = "GOCACHE" + EnvGoRoot EnvKey = "GOROOT" +) + +type Env struct { + vars map[string]string + log logutils.Log + debugf logutils.DebugFunc +} + +func NewEnv(log logutils.Log) *Env { + return &Env{ + vars: map[string]string{}, + log: log, + debugf: logutils.Debug("env"), + } +} + +func (e *Env) Discover(ctx context.Context) error { + startedAt := time.Now() + args := []string{"env", "-json"} + args = append(args, string(EnvGoCache), string(EnvGoRoot)) + out, err := exec.CommandContext(ctx, "go", args...).Output() + if err != nil { + return errors.Wrap(err, "failed to run 'go env'") + } + + if err = json.Unmarshal(out, &e.vars); err != nil { + return errors.Wrapf(err, "failed to parse 'go %s' json", strings.Join(args, " ")) + } + + e.debugf("Read go env for %s: %#v", time.Since(startedAt), e.vars) + return nil +} + +func (e Env) Get(k EnvKey) string { + envValue := os.Getenv(string(k)) + if envValue != "" { + return envValue + } + + return e.vars[string(k)] +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/linter/config.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/linter/config.go new file mode 100644 index 000000000..4ec835254 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/linter/config.go @@ -0,0 +1,89 @@ +package linter + +import ( + "golang.org/x/tools/go/packages" +) + +const ( + PresetFormatting = "format" + PresetComplexity = "complexity" + PresetStyle = "style" + PresetBugs = "bugs" + PresetUnused = "unused" + PresetPerformance = "performance" +) + +type Config struct { + Linter Linter + EnabledByDefault bool + + LoadMode packages.LoadMode + + InPresets []string + AlternativeNames []string + + OriginalURL string // URL of original (not forked) repo, needed for autogenerated README + CanAutoFix bool + IsSlow bool + DoesChangeTypes bool +} + +func (lc *Config) ConsiderSlow() *Config { + lc.IsSlow = true + return lc +} + +func (lc *Config) IsSlowLinter() bool { + return lc.IsSlow || (lc.LoadMode&packages.NeedTypesInfo != 0 && lc.LoadMode&packages.NeedDeps != 0) +} + +func (lc *Config) WithLoadFiles() *Config { + lc.LoadMode |= packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles + return lc +} + +func (lc *Config) WithLoadForGoAnalysis() *Config { + lc = lc.WithLoadFiles() + lc.LoadMode |= packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | packages.NeedTypesSizes + return lc +} + +func (lc *Config) WithPresets(presets ...string) *Config { + lc.InPresets = presets + return lc +} + +func (lc *Config) WithURL(url string) *Config { + lc.OriginalURL = url + return lc +} + +func (lc *Config) WithAlternativeNames(names ...string) *Config { + lc.AlternativeNames = names + return lc +} + +func (lc *Config) WithAutoFix() *Config { + lc.CanAutoFix = true + return lc +} + +func (lc *Config) WithChangeTypes() *Config { + lc.DoesChangeTypes = true + return lc +} + +func (lc *Config) AllNames() []string { + return append([]string{lc.Name()}, lc.AlternativeNames...) +} + +func (lc *Config) Name() string { + return lc.Linter.Name() +} + +func NewConfig(linter Linter) *Config { + lc := &Config{ + Linter: linter, + } + return lc.WithLoadFiles() +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/linter/context.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/linter/context.go new file mode 100644 index 000000000..a9f9d7d7f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/linter/context.go @@ -0,0 +1,49 @@ +package linter + +import ( + "go/ast" + + "golang.org/x/tools/go/packages" + + "github.com/golangci/golangci-lint/internal/pkgcache" + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +type Context struct { + // Packages are deduplicated (test and normal packages) packages + Packages []*packages.Package + + // OriginalPackages aren't deduplicated: they contain both normal and test + // version for each of packages + OriginalPackages []*packages.Package + + Cfg *config.Config + FileCache *fsutils.FileCache + LineCache *fsutils.LineCache + Log logutils.Log + + PkgCache *pkgcache.Cache + LoadGuard *load.Guard +} + +func (c *Context) Settings() *config.LintersSettings { + return &c.Cfg.LintersSettings +} + +func (c *Context) ClearTypesInPackages() { + for _, p := range c.Packages { + clearTypes(p) + } + for _, p := range c.OriginalPackages { + clearTypes(p) + } +} + +func clearTypes(p *packages.Package) { + p.Types = nil + p.TypesInfo = nil + p.Syntax = []*ast.File{} +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/linter/linter.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/linter/linter.go new file mode 100644 index 000000000..cfe9ec020 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/linter/linter.go @@ -0,0 +1,13 @@ +package linter + +import ( + "context" + + "github.com/golangci/golangci-lint/pkg/result" +) + +type Linter interface { + Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) + Name() string + Desc() string +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/enabled_set.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/enabled_set.go new file mode 100644 index 000000000..eced95f65 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/enabled_set.go @@ -0,0 +1,187 @@ +package lintersdb + +import ( + "os" + "sort" + "strings" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +type EnabledSet struct { + m *Manager + v *Validator + log logutils.Log + cfg *config.Config + debugf logutils.DebugFunc +} + +func NewEnabledSet(m *Manager, v *Validator, log logutils.Log, cfg *config.Config) *EnabledSet { + return &EnabledSet{ + m: m, + v: v, + log: log, + cfg: cfg, + debugf: logutils.Debug("enabled_linters"), + } +} + +func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []*linter.Config) map[string]*linter.Config { + es.debugf("Linters config: %#v", lcfg) + resultLintersSet := map[string]*linter.Config{} + switch { + case len(lcfg.Presets) != 0: + break // imply --disable-all + case lcfg.EnableAll: + resultLintersSet = linterConfigsToMap(es.m.GetAllSupportedLinterConfigs()) + case lcfg.DisableAll: + break + default: + resultLintersSet = linterConfigsToMap(enabledByDefaultLinters) + } + + // --presets can only add linters to default set + for _, p := range lcfg.Presets { + for _, lc := range es.m.GetAllLinterConfigsForPreset(p) { + lc := lc + resultLintersSet[lc.Name()] = lc + } + } + + // --fast removes slow linters from current set. + // It should be after --presets to be able to run only fast linters in preset. + // It should be before --enable and --disable to be able to enable or disable specific linter. + if lcfg.Fast { + for name, lc := range resultLintersSet { + if lc.IsSlowLinter() { + delete(resultLintersSet, name) + } + } + } + + for _, name := range lcfg.Enable { + for _, lc := range es.m.GetLinterConfigs(name) { + // it's important to use lc.Name() nor name because name can be alias + resultLintersSet[lc.Name()] = lc + } + } + + for _, name := range lcfg.Disable { + for _, lc := range es.m.GetLinterConfigs(name) { + // it's important to use lc.Name() nor name because name can be alias + delete(resultLintersSet, lc.Name()) + } + } + + return resultLintersSet +} + +func (es EnabledSet) GetEnabledLintersMap() (map[string]*linter.Config, error) { + if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil { + return nil, err + } + + enabledLinters := es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters()) + if os.Getenv("GL_TEST_RUN") == "1" { + es.verbosePrintLintersStatus(enabledLinters) + } + return enabledLinters, nil +} + +// GetOptimizedLinters returns enabled linters after optimization (merging) of multiple linters +// into a fewer number of linters. E.g. some go/analysis linters can be optimized into +// one metalinter for data reuse and speed up. +func (es EnabledSet) GetOptimizedLinters() ([]*linter.Config, error) { + if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil { + return nil, err + } + + resultLintersSet := es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters()) + es.verbosePrintLintersStatus(resultLintersSet) + es.combineGoAnalysisLinters(resultLintersSet) + + var resultLinters []*linter.Config + for _, lc := range resultLintersSet { + resultLinters = append(resultLinters, lc) + } + + // Make order of execution of linters (go/analysis metalinter and unused) stable. + sort.Slice(resultLinters, func(i, j int) bool { + a, b := resultLinters[i], resultLinters[j] + if a.DoesChangeTypes != b.DoesChangeTypes { + return b.DoesChangeTypes // move type-changing linters to the end to optimize speed + } + return strings.Compare(a.Name(), b.Name()) < 0 + }) + + return resultLinters, nil +} + +func (es EnabledSet) combineGoAnalysisLinters(linters map[string]*linter.Config) { + var goanalysisLinters []*goanalysis.Linter + goanalysisPresets := map[string]bool{} + for _, linter := range linters { + lnt, ok := linter.Linter.(*goanalysis.Linter) + if !ok { + continue + } + if lnt.LoadMode() == goanalysis.LoadModeWholeProgram { + // It's ineffective by CPU and memory to run whole-program and incremental analyzers at once. + continue + } + goanalysisLinters = append(goanalysisLinters, lnt) + for _, p := range linter.InPresets { + goanalysisPresets[p] = true + } + } + + if len(goanalysisLinters) <= 1 { + es.debugf("Didn't combine go/analysis linters: got only %d linters", len(goanalysisLinters)) + return + } + + for _, lnt := range goanalysisLinters { + delete(linters, lnt.Name()) + } + + // Make order of execution of go/analysis analyzers stable. + sort.Slice(goanalysisLinters, func(i, j int) bool { + return strings.Compare(goanalysisLinters[i].Name(), goanalysisLinters[j].Name()) <= 0 + }) + ml := goanalysis.NewMetaLinter(goanalysisLinters) + + var presets []string + for p := range goanalysisPresets { + presets = append(presets, p) + } + + mlConfig := &linter.Config{ + Linter: ml, + EnabledByDefault: false, + InPresets: presets, + AlternativeNames: nil, + OriginalURL: "", + } + + mlConfig = mlConfig.WithLoadForGoAnalysis() + + linters[ml.Name()] = mlConfig + es.debugf("Combined %d go/analysis linters into one metalinter", len(goanalysisLinters)) +} + +func (es EnabledSet) verbosePrintLintersStatus(lcs map[string]*linter.Config) { + var linterNames []string + for _, lc := range lcs { + linterNames = append(linterNames, lc.Name()) + } + sort.StringSlice(linterNames).Sort() + es.log.Infof("Active %d linters: %s", len(linterNames), linterNames) + + if len(es.cfg.Linters.Presets) != 0 { + sort.StringSlice(es.cfg.Linters.Presets).Sort() + es.log.Infof("Active presets: %s", es.cfg.Linters.Presets) + } +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/manager.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/manager.go new file mode 100644 index 000000000..1ec78de28 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/manager.go @@ -0,0 +1,374 @@ +package lintersdb + +import ( + "fmt" + "os" + "plugin" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/report" +) + +type Manager struct { + nameToLCs map[string][]*linter.Config + cfg *config.Config + log logutils.Log +} + +func NewManager(cfg *config.Config, log logutils.Log) *Manager { + m := &Manager{cfg: cfg, log: log} + nameToLCs := make(map[string][]*linter.Config) + for _, lc := range m.GetAllSupportedLinterConfigs() { + for _, name := range lc.AllNames() { + nameToLCs[name] = append(nameToLCs[name], lc) + } + } + + m.nameToLCs = nameToLCs + return m +} + +func (m *Manager) WithCustomLinters() *Manager { + if m.log == nil { + m.log = report.NewLogWrapper(logutils.NewStderrLog(""), &report.Data{}) + } + if m.cfg != nil { + for name, settings := range m.cfg.LintersSettings.Custom { + lc, err := m.loadCustomLinterConfig(name, settings) + + if err != nil { + m.log.Errorf("Unable to load custom analyzer %s:%s, %v", + name, + settings.Path, + err) + } else { + m.nameToLCs[name] = append(m.nameToLCs[name], lc) + } + } + } + return m +} + +func (Manager) AllPresets() []string { + return []string{linter.PresetBugs, linter.PresetComplexity, linter.PresetFormatting, + linter.PresetPerformance, linter.PresetStyle, linter.PresetUnused} +} + +func (m Manager) allPresetsSet() map[string]bool { + ret := map[string]bool{} + for _, p := range m.AllPresets() { + ret[p] = true + } + return ret +} + +func (m Manager) GetLinterConfigs(name string) []*linter.Config { + return m.nameToLCs[name] +} + +func enableLinterConfigs(lcs []*linter.Config, isEnabled func(lc *linter.Config) bool) []*linter.Config { + var ret []*linter.Config + for _, lc := range lcs { + lc := lc + lc.EnabledByDefault = isEnabled(lc) + ret = append(ret, lc) + } + + return ret +} + +//nolint:funlen +func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { + var govetCfg *config.GovetSettings + var testpackageCfg *config.TestpackageSettings + if m.cfg != nil { + govetCfg = &m.cfg.LintersSettings.Govet + testpackageCfg = &m.cfg.LintersSettings.Testpackage + } + const megacheckName = "megacheck" + lcs := []*linter.Config{ + linter.NewConfig(golinters.NewGovet(govetCfg)). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithAlternativeNames("vet", "vetshadow"). + WithURL("https://golang.org/cmd/vet/"), + linter.NewConfig(golinters.NewBodyclose()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetPerformance, linter.PresetBugs). + WithURL("https://github.com/timakin/bodyclose"), + linter.NewConfig(golinters.NewErrcheck()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/kisielk/errcheck"), + linter.NewConfig(golinters.NewGolint()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/golang/lint"), + linter.NewConfig(golinters.NewRowsErrCheck()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetPerformance, linter.PresetBugs). + WithURL("https://github.com/jingyugao/rowserrcheck"), + + linter.NewConfig(golinters.NewStaticcheck()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithAlternativeNames(megacheckName). + WithURL("https://staticcheck.io/"), + linter.NewConfig(golinters.NewUnused()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetUnused). + WithAlternativeNames(megacheckName). + ConsiderSlow(). + WithChangeTypes(). + WithURL("https://github.com/dominikh/go-tools/tree/master/unused"), + linter.NewConfig(golinters.NewGosimple()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithAlternativeNames(megacheckName). + WithURL("https://github.com/dominikh/go-tools/tree/master/simple"), + linter.NewConfig(golinters.NewStylecheck()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/dominikh/go-tools/tree/master/stylecheck"), + + linter.NewConfig(golinters.NewGosec()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/securego/gosec"). + WithAlternativeNames("gas"), + linter.NewConfig(golinters.NewStructcheck()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetUnused). + WithURL("https://github.com/opennota/check"), + linter.NewConfig(golinters.NewVarcheck()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetUnused). + WithURL("https://github.com/opennota/check"), + linter.NewConfig(golinters.NewInterfacer()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/mvdan/interfacer"), + linter.NewConfig(golinters.NewUnconvert()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/mdempsky/unconvert"), + linter.NewConfig(golinters.NewIneffassign()). + WithPresets(linter.PresetUnused). + WithURL("https://github.com/gordonklaus/ineffassign"), + linter.NewConfig(golinters.NewDupl()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/mibk/dupl"), + linter.NewConfig(golinters.NewGoconst()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/jgautheron/goconst"), + linter.NewConfig(golinters.NewDeadcode()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetUnused). + WithURL("https://github.com/remyoudompheng/go-misc/tree/master/deadcode"), + linter.NewConfig(golinters.NewGocyclo()). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/alecthomas/gocyclo"), + linter.NewConfig(golinters.NewGocognit()). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/uudashr/gocognit"), + linter.NewConfig(golinters.NewTypecheck()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithURL(""), + linter.NewConfig(golinters.NewAsciicheck()). + WithPresets(linter.PresetBugs, linter.PresetStyle). + WithURL("https://github.com/tdakkota/asciicheck"), + + linter.NewConfig(golinters.NewGofmt()). + WithPresets(linter.PresetFormatting). + WithAutoFix(). + WithURL("https://golang.org/cmd/gofmt/"), + linter.NewConfig(golinters.NewGoimports()). + WithPresets(linter.PresetFormatting). + WithAutoFix(). + WithURL("https://godoc.org/golang.org/x/tools/cmd/goimports"), + linter.NewConfig(golinters.NewMaligned()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetPerformance). + WithURL("https://github.com/mdempsky/maligned"), + linter.NewConfig(golinters.NewDepguard()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/OpenPeeDeeP/depguard"), + linter.NewConfig(golinters.NewMisspell()). + WithPresets(linter.PresetStyle). + WithAutoFix(). + WithURL("https://github.com/client9/misspell"), + linter.NewConfig(golinters.NewLLL()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/walle/lll"), + linter.NewConfig(golinters.NewUnparam()). + WithPresets(linter.PresetUnused). + WithLoadForGoAnalysis(). + WithURL("https://github.com/mvdan/unparam"), + linter.NewConfig(golinters.NewDogsled()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/alexkohler/dogsled"), + linter.NewConfig(golinters.NewNakedret()). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/alexkohler/nakedret"), + linter.NewConfig(golinters.NewPrealloc()). + WithPresets(linter.PresetPerformance). + WithURL("https://github.com/alexkohler/prealloc"), + linter.NewConfig(golinters.NewScopelint()). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/kyoh86/scopelint"), + linter.NewConfig(golinters.NewGocritic()). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/go-critic/go-critic"), + linter.NewConfig(golinters.NewGochecknoinits()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/leighmcculloch/gochecknoinits"), + linter.NewConfig(golinters.NewGochecknoglobals()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/leighmcculloch/gochecknoglobals"), + linter.NewConfig(golinters.NewGodox()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/matoous/godox"), + linter.NewConfig(golinters.NewFunlen()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/ultraware/funlen"), + linter.NewConfig(golinters.NewWhitespace()). + WithPresets(linter.PresetStyle). + WithAutoFix(). + WithURL("https://github.com/ultraware/whitespace"), + linter.NewConfig(golinters.NewWSL()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/bombsimon/wsl"), + linter.NewConfig(golinters.NewGoPrintfFuncName()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/jirfag/go-printf-func-name"), + linter.NewConfig(golinters.NewGoMND(m.cfg)). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/tommy-muehle/go-mnd"), + linter.NewConfig(golinters.NewGoerr113()). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/Djarvur/go-err113"), + linter.NewConfig(golinters.NewGomodguard()). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/ryancurrah/gomodguard"), + linter.NewConfig(golinters.NewGodot()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/tetafro/godot"), + linter.NewConfig(golinters.NewTestpackage(testpackageCfg)). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/maratori/testpackage"), + linter.NewConfig(golinters.NewNestif()). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/nakabonne/nestif"), + // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives + linter.NewConfig(golinters.NewNoLintLint()). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/golangci-lint/pkg/golinters/nolintlint"), + } + + isLocalRun := os.Getenv("GOLANGCI_COM_RUN") == "" + enabledByDefault := map[string]bool{ + golinters.NewGovet(nil).Name(): true, + golinters.NewErrcheck().Name(): true, + golinters.NewStaticcheck().Name(): true, + golinters.NewUnused().Name(): true, + golinters.NewGosimple().Name(): true, + golinters.NewStructcheck().Name(): true, + golinters.NewVarcheck().Name(): true, + golinters.NewIneffassign().Name(): true, + golinters.NewDeadcode().Name(): true, + + // don't typecheck for golangci.com: too many troubles + golinters.NewTypecheck().Name(): isLocalRun, + } + return enableLinterConfigs(lcs, func(lc *linter.Config) bool { + return enabledByDefault[lc.Name()] + }) +} + +func (m Manager) GetAllEnabledByDefaultLinters() []*linter.Config { + var ret []*linter.Config + for _, lc := range m.GetAllSupportedLinterConfigs() { + if lc.EnabledByDefault { + ret = append(ret, lc) + } + } + + return ret +} + +func linterConfigsToMap(lcs []*linter.Config) map[string]*linter.Config { + ret := map[string]*linter.Config{} + for _, lc := range lcs { + lc := lc // local copy + ret[lc.Name()] = lc + } + + return ret +} + +func (m Manager) GetAllLinterConfigsForPreset(p string) []*linter.Config { + var ret []*linter.Config + for _, lc := range m.GetAllSupportedLinterConfigs() { + for _, ip := range lc.InPresets { + if p == ip { + ret = append(ret, lc) + break + } + } + } + + return ret +} + +func (m Manager) loadCustomLinterConfig(name string, settings config.CustomLinterSettings) (*linter.Config, error) { + analyzer, err := m.getAnalyzerPlugin(settings.Path) + if err != nil { + return nil, err + } + m.log.Infof("Loaded %s: %s", settings.Path, name) + customLinter := goanalysis.NewLinter( + name, + settings.Description, + analyzer.GetAnalyzers(), + nil).WithLoadMode(goanalysis.LoadModeTypesInfo) + linterConfig := linter.NewConfig(customLinter) + linterConfig.EnabledByDefault = true + linterConfig.IsSlow = false + linterConfig.WithURL(settings.OriginalURL) + return linterConfig, nil +} + +type AnalyzerPlugin interface { + GetAnalyzers() []*analysis.Analyzer +} + +func (m Manager) getAnalyzerPlugin(path string) (AnalyzerPlugin, error) { + plug, err := plugin.Open(path) + if err != nil { + return nil, err + } + + symbol, err := plug.Lookup("AnalyzerPlugin") + if err != nil { + return nil, err + } + + analyzerPlugin, ok := symbol.(AnalyzerPlugin) + if !ok { + return nil, fmt.Errorf("plugin %s does not abide by 'AnalyzerPlugin' interface", path) + } + + return analyzerPlugin, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/validator.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/validator.go new file mode 100644 index 000000000..d7e3699c8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/validator.go @@ -0,0 +1,99 @@ +package lintersdb + +import ( + "fmt" + "strings" + + "github.com/golangci/golangci-lint/pkg/config" +) + +type Validator struct { + m *Manager +} + +func NewValidator(m *Manager) *Validator { + return &Validator{ + m: m, + } +} + +func (v Validator) validateLintersNames(cfg *config.Linters) error { + allNames := append([]string{}, cfg.Enable...) + allNames = append(allNames, cfg.Disable...) + for _, name := range allNames { + if v.m.GetLinterConfigs(name) == nil { + return fmt.Errorf("no such linter %q", name) + } + } + + return nil +} + +func (v Validator) validatePresets(cfg *config.Linters) error { + allPresets := v.m.allPresetsSet() + for _, p := range cfg.Presets { + if !allPresets[p] { + return fmt.Errorf("no such preset %q: only next presets exist: (%s)", + p, strings.Join(v.m.AllPresets(), "|")) + } + } + + if len(cfg.Presets) != 0 && cfg.EnableAll { + return fmt.Errorf("--presets is incompatible with --enable-all") + } + + return nil +} + +func (v Validator) validateAllDisableEnableOptions(cfg *config.Linters) error { + if cfg.EnableAll && cfg.DisableAll { + return fmt.Errorf("--enable-all and --disable-all options must not be combined") + } + + if cfg.DisableAll { + if len(cfg.Enable) == 0 && len(cfg.Presets) == 0 { + return fmt.Errorf("all linters were disabled, but no one linter was enabled: must enable at least one") + } + + if len(cfg.Disable) != 0 { + return fmt.Errorf("can't combine options --disable-all and --disable %s", cfg.Disable[0]) + } + } + + if cfg.EnableAll && len(cfg.Enable) != 0 && !cfg.Fast { + return fmt.Errorf("can't combine options --enable-all and --enable %s", cfg.Enable[0]) + } + + return nil +} + +func (v Validator) validateDisabledAndEnabledAtOneMoment(cfg *config.Linters) error { + enabledLintersSet := map[string]bool{} + for _, name := range cfg.Enable { + enabledLintersSet[name] = true + } + + for _, name := range cfg.Disable { + if enabledLintersSet[name] { + return fmt.Errorf("linter %q can't be disabled and enabled at one moment", name) + } + } + + return nil +} + +func (v Validator) validateEnabledDisabledLintersConfig(cfg *config.Linters) error { + validators := []func(cfg *config.Linters) error{ + v.validateLintersNames, + v.validatePresets, + v.validateAllDisableEnableOptions, + v.validateDisabledAndEnabledAtOneMoment, + } + for _, v := range validators { + if err := v(cfg); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/load.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/load.go new file mode 100644 index 000000000..e2928a57a --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/load.go @@ -0,0 +1,308 @@ +package lint + +import ( + "context" + "fmt" + "go/build" + "go/token" + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "github.com/pkg/errors" + "golang.org/x/tools/go/packages" + + "github.com/golangci/golangci-lint/internal/pkgcache" + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/exitcodes" + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load" + "github.com/golangci/golangci-lint/pkg/goutil" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +type ContextLoader struct { + cfg *config.Config + log logutils.Log + debugf logutils.DebugFunc + goenv *goutil.Env + pkgTestIDRe *regexp.Regexp + lineCache *fsutils.LineCache + fileCache *fsutils.FileCache + pkgCache *pkgcache.Cache + loadGuard *load.Guard +} + +func NewContextLoader(cfg *config.Config, log logutils.Log, goenv *goutil.Env, + lineCache *fsutils.LineCache, fileCache *fsutils.FileCache, pkgCache *pkgcache.Cache, loadGuard *load.Guard) *ContextLoader { + return &ContextLoader{ + cfg: cfg, + log: log, + debugf: logutils.Debug("loader"), + goenv: goenv, + pkgTestIDRe: regexp.MustCompile(`^(.*) \[(.*)\.test\]`), + lineCache: lineCache, + fileCache: fileCache, + pkgCache: pkgCache, + loadGuard: loadGuard, + } +} + +func (cl *ContextLoader) prepareBuildContext() { + // Set GOROOT to have working cross-compilation: cross-compiled binaries + // have invalid GOROOT. XXX: can't use runtime.GOROOT(). + goroot := cl.goenv.Get(goutil.EnvGoRoot) + if goroot == "" { + return + } + + os.Setenv("GOROOT", goroot) + build.Default.GOROOT = goroot + build.Default.BuildTags = cl.cfg.Run.BuildTags +} + +func (cl *ContextLoader) findLoadMode(linters []*linter.Config) packages.LoadMode { + loadMode := packages.LoadMode(0) + for _, lc := range linters { + loadMode |= lc.LoadMode + } + + return loadMode +} + +func (cl *ContextLoader) buildArgs() []string { + args := cl.cfg.Run.Args + if len(args) == 0 { + return []string{"./..."} + } + + var retArgs []string + for _, arg := range args { + if strings.HasPrefix(arg, ".") || filepath.IsAbs(arg) { + retArgs = append(retArgs, arg) + } else { + // go/packages doesn't work well if we don't have prefix ./ for local packages + retArgs = append(retArgs, fmt.Sprintf(".%c%s", filepath.Separator, arg)) + } + } + + return retArgs +} + +func (cl *ContextLoader) makeBuildFlags() ([]string, error) { + var buildFlags []string + + if len(cl.cfg.Run.BuildTags) != 0 { + // go help build + buildFlags = append(buildFlags, "-tags", strings.Join(cl.cfg.Run.BuildTags, " ")) + cl.log.Infof("Using build tags: %v", cl.cfg.Run.BuildTags) + } + + mod := cl.cfg.Run.ModulesDownloadMode + if mod != "" { + // go help modules + allowedMods := []string{"release", "readonly", "vendor"} + var ok bool + for _, am := range allowedMods { + if am == mod { + ok = true + break + } + } + if !ok { + return nil, fmt.Errorf("invalid modules download path %s, only (%s) allowed", mod, strings.Join(allowedMods, "|")) + } + + buildFlags = append(buildFlags, fmt.Sprintf("-mod=%s", cl.cfg.Run.ModulesDownloadMode)) + } + + return buildFlags, nil +} + +func stringifyLoadMode(mode packages.LoadMode) string { + m := map[packages.LoadMode]string{ + packages.NeedCompiledGoFiles: "compiled_files", + packages.NeedDeps: "deps", + packages.NeedExportsFile: "exports_file", + packages.NeedFiles: "files", + packages.NeedImports: "imports", + packages.NeedName: "name", + packages.NeedSyntax: "syntax", + packages.NeedTypes: "types", + packages.NeedTypesInfo: "types_info", + packages.NeedTypesSizes: "types_sizes", + } + + var flags []string + for flag, flagStr := range m { + if mode&flag != 0 { + flags = append(flags, flagStr) + } + } + + return fmt.Sprintf("%d (%s)", mode, strings.Join(flags, "|")) +} + +func (cl *ContextLoader) debugPrintLoadedPackages(pkgs []*packages.Package) { + cl.debugf("loaded %d pkgs", len(pkgs)) + for i, pkg := range pkgs { + var syntaxFiles []string + for _, sf := range pkg.Syntax { + syntaxFiles = append(syntaxFiles, pkg.Fset.Position(sf.Pos()).Filename) + } + cl.debugf("Loaded pkg #%d: ID=%s GoFiles=%s CompiledGoFiles=%s Syntax=%s", + i, pkg.ID, pkg.GoFiles, pkg.CompiledGoFiles, syntaxFiles) + } +} + +func (cl *ContextLoader) parseLoadedPackagesErrors(pkgs []*packages.Package) error { + for _, pkg := range pkgs { + for _, err := range pkg.Errors { + if strings.Contains(err.Msg, "no Go files") { + return errors.Wrapf(exitcodes.ErrNoGoFiles, "package %s", pkg.PkgPath) + } + if strings.Contains(err.Msg, "cannot find package") { + // when analyzing not existing directory + return errors.Wrap(exitcodes.ErrFailure, err.Msg) + } + } + } + + return nil +} + +func (cl *ContextLoader) loadPackages(ctx context.Context, loadMode packages.LoadMode) ([]*packages.Package, error) { + defer func(startedAt time.Time) { + cl.log.Infof("Go packages loading at mode %s took %s", stringifyLoadMode(loadMode), time.Since(startedAt)) + }(time.Now()) + + cl.prepareBuildContext() + + buildFlags, err := cl.makeBuildFlags() + if err != nil { + return nil, errors.Wrap(err, "failed to make build flags for go list") + } + + conf := &packages.Config{ + Mode: loadMode, + Tests: cl.cfg.Run.AnalyzeTests, + Context: ctx, + BuildFlags: buildFlags, + Logf: cl.debugf, + //TODO: use fset, parsefile, overlay + } + + args := cl.buildArgs() + cl.debugf("Built loader args are %s", args) + pkgs, err := packages.Load(conf, args...) + if err != nil { + return nil, errors.Wrap(err, "failed to load program with go/packages") + } + + if loadMode&packages.NeedSyntax == 0 { + // Needed e.g. for go/analysis loading. + fset := token.NewFileSet() + packages.Visit(pkgs, nil, func(pkg *packages.Package) { + pkg.Fset = fset + cl.loadGuard.AddMutexForPkg(pkg) + }) + } + + cl.debugPrintLoadedPackages(pkgs) + + if err := cl.parseLoadedPackagesErrors(pkgs); err != nil { + return nil, err + } + + return cl.filterTestMainPackages(pkgs), nil +} + +func (cl *ContextLoader) tryParseTestPackage(pkg *packages.Package) (name string, isTest bool) { + matches := cl.pkgTestIDRe.FindStringSubmatch(pkg.ID) + if matches == nil { + return "", false + } + + return matches[1], true +} + +func (cl *ContextLoader) filterTestMainPackages(pkgs []*packages.Package) []*packages.Package { + var retPkgs []*packages.Package + for _, pkg := range pkgs { + if pkg.Name == "main" && strings.HasSuffix(pkg.PkgPath, ".test") { + // it's an implicit testmain package + cl.debugf("skip pkg ID=%s", pkg.ID) + continue + } + + retPkgs = append(retPkgs, pkg) + } + + return retPkgs +} + +func (cl *ContextLoader) filterDuplicatePackages(pkgs []*packages.Package) []*packages.Package { + packagesWithTests := map[string]bool{} + for _, pkg := range pkgs { + name, isTest := cl.tryParseTestPackage(pkg) + if !isTest { + continue + } + packagesWithTests[name] = true + } + + cl.debugf("package with tests: %#v", packagesWithTests) + + var retPkgs []*packages.Package + for _, pkg := range pkgs { + _, isTest := cl.tryParseTestPackage(pkg) + if !isTest && packagesWithTests[pkg.PkgPath] { + // If tests loading is enabled, + // for package with files a.go and a_test.go go/packages loads two packages: + // 1. ID=".../a" GoFiles=[a.go] + // 2. ID=".../a [.../a.test]" GoFiles=[a.go a_test.go] + // We need only the second package, otherwise we can get warnings about unused variables/fields/functions + // in a.go if they are used only in a_test.go. + cl.debugf("skip pkg ID=%s because we load it with test package", pkg.ID) + continue + } + + retPkgs = append(retPkgs, pkg) + } + + return retPkgs +} + +func (cl *ContextLoader) Load(ctx context.Context, linters []*linter.Config) (*linter.Context, error) { + loadMode := cl.findLoadMode(linters) + pkgs, err := cl.loadPackages(ctx, loadMode) + if err != nil { + return nil, err + } + + deduplicatedPkgs := cl.filterDuplicatePackages(pkgs) + + if len(deduplicatedPkgs) == 0 { + return nil, exitcodes.ErrNoGoFiles + } + + ret := &linter.Context{ + Packages: deduplicatedPkgs, + + // At least `unused` linters works properly only on original (not deduplicated) packages, + // see https://github.com/golangci/golangci-lint/pull/585. + OriginalPackages: pkgs, + + Cfg: cl.cfg, + Log: cl.log, + FileCache: cl.fileCache, + LineCache: cl.lineCache, + PkgCache: cl.pkgCache, + LoadGuard: cl.loadGuard, + } + + return ret, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/runner.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/runner.go new file mode 100644 index 000000000..05dc51ba9 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/runner.go @@ -0,0 +1,256 @@ +package lint + +import ( + "context" + "fmt" + "os" + "runtime/debug" + "strings" + + "github.com/pkg/errors" + + "github.com/golangci/golangci-lint/internal/errorutil" + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/goutil" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/packages" + "github.com/golangci/golangci-lint/pkg/result" + "github.com/golangci/golangci-lint/pkg/result/processors" + "github.com/golangci/golangci-lint/pkg/timeutils" + + gopackages "golang.org/x/tools/go/packages" +) + +type Runner struct { + Processors []processors.Processor + Log logutils.Log +} + +func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, es *lintersdb.EnabledSet, + lineCache *fsutils.LineCache, dbManager *lintersdb.Manager, pkgs []*gopackages.Package) (*Runner, error) { + icfg := cfg.Issues + excludePatterns := icfg.ExcludePatterns + if icfg.UseDefaultExcludes { + excludePatterns = append(excludePatterns, config.GetExcludePatternsStrings(icfg.IncludeDefaultExcludes)...) + } + + var excludeTotalPattern string + if len(excludePatterns) != 0 { + excludeTotalPattern = fmt.Sprintf("(%s)", strings.Join(excludePatterns, "|")) + } + + var excludeProcessor processors.Processor + if cfg.Issues.ExcludeCaseSensitive { + excludeProcessor = processors.NewExcludeCaseSensitive(excludeTotalPattern) + } else { + excludeProcessor = processors.NewExclude(excludeTotalPattern) + } + + skipFilesProcessor, err := processors.NewSkipFiles(cfg.Run.SkipFiles) + if err != nil { + return nil, err + } + + skipDirs := cfg.Run.SkipDirs + if cfg.Run.UseDefaultSkipDirs { + skipDirs = append(skipDirs, packages.StdExcludeDirRegexps...) + } + skipDirsProcessor, err := processors.NewSkipDirs(skipDirs, log.Child("skip dirs"), cfg.Run.Args) + if err != nil { + return nil, err + } + + var excludeRules []processors.ExcludeRule + for _, r := range icfg.ExcludeRules { + excludeRules = append(excludeRules, processors.ExcludeRule{ + Text: r.Text, + Source: r.Source, + Path: r.Path, + Linters: r.Linters, + }) + } + var excludeRulesProcessor processors.Processor + if cfg.Issues.ExcludeCaseSensitive { + excludeRulesProcessor = processors.NewExcludeRulesCaseSensitive(excludeRules, lineCache, log.Child("exclude_rules")) + } else { + excludeRulesProcessor = processors.NewExcludeRules(excludeRules, lineCache, log.Child("exclude_rules")) + } + + enabledLinters, err := es.GetEnabledLintersMap() + if err != nil { + return nil, errors.Wrap(err, "failed to get enabled linters") + } + + return &Runner{ + Processors: []processors.Processor{ + processors.NewCgo(goenv), + + // Must go after Cgo. + processors.NewFilenameUnadjuster(pkgs, log.Child("filename_unadjuster")), + + // Must be before diff, nolint and exclude autogenerated processor at least. + processors.NewPathPrettifier(), + skipFilesProcessor, + skipDirsProcessor, // must be after path prettifier + + processors.NewAutogeneratedExclude(), + + // Must be before exclude because users see already marked output and configure excluding by it. + processors.NewIdentifierMarker(), + + excludeProcessor, + excludeRulesProcessor, + processors.NewNolint(log.Child("nolint"), dbManager, enabledLinters), + + processors.NewUniqByLine(cfg), + processors.NewDiff(icfg.Diff, icfg.DiffFromRevision, icfg.DiffPatchFilePath), + processors.NewMaxPerFileFromLinter(cfg), + processors.NewMaxSameIssues(icfg.MaxSameIssues, log.Child("max_same_issues"), cfg), + processors.NewMaxFromLinter(icfg.MaxIssuesPerLinter, log.Child("max_from_linter"), cfg), + processors.NewSourceCode(lineCache, log.Child("source_code")), + processors.NewPathShortener(), + }, + Log: log, + }, nil +} + +func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, + lc *linter.Config) (ret []result.Issue, err error) { + defer func() { + if panicData := recover(); panicData != nil { + if pe, ok := panicData.(*errorutil.PanicError); ok { + // Don't print stacktrace from goroutines twice + lintCtx.Log.Warnf("Panic: %s: %s", pe, pe.Stack()) + } else { + err = fmt.Errorf("panic occurred: %s", panicData) + r.Log.Warnf("Panic stack trace: %s", debug.Stack()) + } + } + }() + + issues, err := lc.Linter.Run(ctx, lintCtx) + + if lc.DoesChangeTypes { + // Packages in lintCtx might be dirty due to the last analysis, + // which affects to the next analysis. + // To avoid this issue, we clear type information from the packages. + // See https://github.com/golangci/golangci-lint/pull/944. + // Currently DoesChangeTypes is true only for `unused`. + lintCtx.ClearTypesInPackages() + } + + if err != nil { + return nil, err + } + + for i := range issues { + if issues[i].FromLinter == "" { + issues[i].FromLinter = lc.Name() + } + } + + return issues, nil +} + +type processorStat struct { + inCount int + outCount int +} + +func (r Runner) processLintResults(inIssues []result.Issue) []result.Issue { + sw := timeutils.NewStopwatch("processing", r.Log) + + var issuesBefore, issuesAfter int + statPerProcessor := map[string]processorStat{} + + var outIssues []result.Issue + if len(inIssues) != 0 { + issuesBefore += len(inIssues) + outIssues = r.processIssues(inIssues, sw, statPerProcessor) + issuesAfter += len(outIssues) + } + + // finalize processors: logging, clearing, no heavy work here + + for _, p := range r.Processors { + p := p + sw.TrackStage(p.Name(), func() { + p.Finish() + }) + } + + if issuesBefore != issuesAfter { + r.Log.Infof("Issues before processing: %d, after processing: %d", issuesBefore, issuesAfter) + } + r.printPerProcessorStat(statPerProcessor) + sw.PrintStages() + + return outIssues +} + +func (r Runner) printPerProcessorStat(stat map[string]processorStat) { + parts := make([]string, 0, len(stat)) + for name, ps := range stat { + if ps.inCount != 0 { + parts = append(parts, fmt.Sprintf("%s: %d/%d", name, ps.outCount, ps.inCount)) + } + } + if len(parts) != 0 { + r.Log.Infof("Processors filtering stat (out/in): %s", strings.Join(parts, ", ")) + } +} + +func (r Runner) Run(ctx context.Context, linters []*linter.Config, lintCtx *linter.Context) ([]result.Issue, error) { + sw := timeutils.NewStopwatch("linters", r.Log) + defer sw.Print() + + var issues []result.Issue + var runErr error + for _, lc := range linters { + lc := lc + sw.TrackStage(lc.Name(), func() { + linterIssues, err := r.runLinterSafe(ctx, lintCtx, lc) + if err != nil { + r.Log.Warnf("Can't run linter %s: %s", lc.Linter.Name(), err) + if os.Getenv("GOLANGCI_COM_RUN") == "" { + // Don't stop all linters on one linter failure for golangci.com. + runErr = err + } + return + } + issues = append(issues, linterIssues...) + }) + } + + return r.processLintResults(issues), runErr +} + +func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, statPerProcessor map[string]processorStat) []result.Issue { + for _, p := range r.Processors { + var newIssues []result.Issue + var err error + p := p + sw.TrackStage(p.Name(), func() { + newIssues, err = p.Process(issues) + }) + + if err != nil { + r.Log.Warnf("Can't process result by %s processor: %s", p.Name(), err) + } else { + stat := statPerProcessor[p.Name()] + stat.inCount += len(issues) + stat.outCount += len(newIssues) + statPerProcessor[p.Name()] = stat + issues = newIssues + } + + if issues == nil { + issues = []result.Issue{} + } + } + + return issues +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/logutils/log.go b/vendor/github.com/golangci/golangci-lint/pkg/logutils/log.go new file mode 100644 index 000000000..b955417a8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/logutils/log.go @@ -0,0 +1,31 @@ +package logutils + +type Log interface { + Fatalf(format string, args ...interface{}) + Panicf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) + Warnf(format string, args ...interface{}) + Infof(format string, args ...interface{}) + + Child(name string) Log + SetLevel(level LogLevel) +} + +type LogLevel int + +const ( + // Debug messages, write to debug logs only by logutils.Debug. + LogLevelDebug LogLevel = 0 + + // Information messages, don't write too much messages, + // only useful ones: they are shown when running with -v. + LogLevelInfo LogLevel = 1 + + // Hidden errors: non critical errors: work can be continued, no need to fail whole program; + // tests will crash if any warning occurred. + LogLevelWarn LogLevel = 2 + + // Only not hidden from user errors: whole program failing, usually + // error logging happens in 1-2 places: in the "main" function. + LogLevelError LogLevel = 3 +) diff --git a/vendor/github.com/golangci/golangci-lint/pkg/logutils/logutils.go b/vendor/github.com/golangci/golangci-lint/pkg/logutils/logutils.go new file mode 100644 index 000000000..93c9873d9 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/logutils/logutils.go @@ -0,0 +1,49 @@ +package logutils + +import ( + "os" + "strings" +) + +func getEnabledDebugs() map[string]bool { + ret := map[string]bool{} + debugVar := os.Getenv("GL_DEBUG") + if debugVar == "" { + return ret + } + + for _, tag := range strings.Split(debugVar, ",") { + ret[tag] = true + } + + return ret +} + +var enabledDebugs = getEnabledDebugs() + +type DebugFunc func(format string, args ...interface{}) + +func nopDebugf(format string, args ...interface{}) {} + +func Debug(tag string) DebugFunc { + if !enabledDebugs[tag] { + return nopDebugf + } + + logger := NewStderrLog(tag) + logger.SetLevel(LogLevelDebug) + + return func(format string, args ...interface{}) { + logger.Debugf(format, args...) + } +} + +func HaveDebugTag(tag string) bool { + return enabledDebugs[tag] +} + +func SetupVerboseLog(log Log, isVerbose bool) { + if isVerbose { + log.SetLevel(LogLevelInfo) + } +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/logutils/mock.go b/vendor/github.com/golangci/golangci-lint/pkg/logutils/mock.go new file mode 100644 index 000000000..e897ce1ed --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/logutils/mock.go @@ -0,0 +1,47 @@ +package logutils + +import ( + "github.com/stretchr/testify/mock" +) + +type MockLog struct { + mock.Mock +} + +func NewMockLog() *MockLog { + return &MockLog{} +} + +func (m *MockLog) Fatalf(format string, args ...interface{}) { + mArgs := []interface{}{format} + m.Called(append(mArgs, args...)...) +} + +func (m *MockLog) Panicf(format string, args ...interface{}) { + mArgs := []interface{}{format} + m.Called(append(mArgs, args...)...) +} + +func (m *MockLog) Errorf(format string, args ...interface{}) { + mArgs := []interface{}{format} + m.Called(append(mArgs, args...)...) +} + +func (m *MockLog) Warnf(format string, args ...interface{}) { + mArgs := []interface{}{format} + m.Called(append(mArgs, args...)...) +} + +func (m *MockLog) Infof(format string, args ...interface{}) { + mArgs := []interface{}{format} + m.Called(append(mArgs, args...)...) +} + +func (m *MockLog) Child(name string) Log { + m.Called(name) + return m +} + +func (m *MockLog) SetLevel(level LogLevel) { + m.Called(level) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/logutils/out.go b/vendor/github.com/golangci/golangci-lint/pkg/logutils/out.go new file mode 100644 index 000000000..67c70dc8f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/logutils/out.go @@ -0,0 +1,9 @@ +package logutils + +import ( + "github.com/fatih/color" + colorable "github.com/mattn/go-colorable" +) + +var StdOut = color.Output // https://github.com/golangci/golangci-lint/issues/14 +var StdErr = colorable.NewColorableStderr() diff --git a/vendor/github.com/golangci/golangci-lint/pkg/logutils/stderr_log.go b/vendor/github.com/golangci/golangci-lint/pkg/logutils/stderr_log.go new file mode 100644 index 000000000..b4697ee4c --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/logutils/stderr_log.go @@ -0,0 +1,121 @@ +package logutils + +import ( + "fmt" + "os" + "time" + + "github.com/sirupsen/logrus" //nolint:depguard + + "github.com/golangci/golangci-lint/pkg/exitcodes" +) + +type StderrLog struct { + name string + logger *logrus.Logger + level LogLevel +} + +var _ Log = NewStderrLog("") + +func NewStderrLog(name string) *StderrLog { + sl := &StderrLog{ + name: name, + logger: logrus.New(), + level: LogLevelWarn, + } + + switch os.Getenv("LOG_LEVEL") { + case "error", "err": + sl.logger.SetLevel(logrus.ErrorLevel) + case "warning", "warn": + sl.logger.SetLevel(logrus.WarnLevel) + case "info": + sl.logger.SetLevel(logrus.InfoLevel) + default: + sl.logger.SetLevel(logrus.DebugLevel) + } + + sl.logger.Out = StdErr + formatter := &logrus.TextFormatter{ + DisableTimestamp: true, // `INFO[0007] msg` -> `INFO msg` + } + if os.Getenv("LOG_TIMESTAMP") == "1" { + formatter.DisableTimestamp = false + formatter.FullTimestamp = true + formatter.TimestampFormat = time.StampMilli + } + sl.logger.Formatter = formatter + + return sl +} + +func (sl StderrLog) prefix() string { + prefix := "" + if sl.name != "" { + prefix = fmt.Sprintf("[%s] ", sl.name) + } + + return prefix +} + +func (sl StderrLog) Fatalf(format string, args ...interface{}) { + sl.logger.Errorf("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) + os.Exit(exitcodes.Failure) +} + +func (sl StderrLog) Panicf(format string, args ...interface{}) { + v := fmt.Sprintf("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) + panic(v) +} + +func (sl StderrLog) Errorf(format string, args ...interface{}) { + if sl.level > LogLevelError { + return + } + + sl.logger.Errorf("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) + // don't call exitIfTest() because the idea is to + // crash on hidden errors (warnings); but Errorf MUST NOT be + // called on hidden errors, see log levels comments. +} + +func (sl StderrLog) Warnf(format string, args ...interface{}) { + if sl.level > LogLevelWarn { + return + } + + sl.logger.Warnf("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) +} + +func (sl StderrLog) Infof(format string, args ...interface{}) { + if sl.level > LogLevelInfo { + return + } + + sl.logger.Infof("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) +} + +func (sl StderrLog) Debugf(format string, args ...interface{}) { + if sl.level > LogLevelDebug { + return + } + + sl.logger.Debugf("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) +} + +func (sl StderrLog) Child(name string) Log { + prefix := "" + if sl.name != "" { + prefix = sl.name + "/" + } + + child := sl + child.name = prefix + name + + return &child +} + +func (sl *StderrLog) SetLevel(level LogLevel) { + sl.level = level +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/packages/errors.go b/vendor/github.com/golangci/golangci-lint/pkg/packages/errors.go new file mode 100644 index 000000000..c620573b9 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/packages/errors.go @@ -0,0 +1,39 @@ +package packages + +import ( + "fmt" + "go/token" + "strconv" + "strings" + + "github.com/pkg/errors" +) + +//nolint:gomnd +func ParseErrorPosition(pos string) (*token.Position, error) { + // file:line(:colon) + parts := strings.Split(pos, ":") + if len(parts) == 1 { + return nil, errors.New("no colons") + } + + file := parts[0] + line, err := strconv.Atoi(parts[1]) + if err != nil { + return nil, fmt.Errorf("can't parse line number %q: %s", parts[1], err) + } + + var column int + if len(parts) == 3 { // no column + column, err = strconv.Atoi(parts[2]) + if err != nil { + return nil, errors.Wrapf(err, "failed to parse column from %q", parts[2]) + } + } + + return &token.Position{ + Filename: file, + Line: line, + Column: column, + }, nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/packages/skip.go b/vendor/github.com/golangci/golangci-lint/pkg/packages/skip.go new file mode 100644 index 000000000..cdd327f5d --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/packages/skip.go @@ -0,0 +1,25 @@ +package packages + +import ( + "fmt" + "path/filepath" + "regexp" +) + +func pathElemReImpl(e string, sep rune) string { + escapedSep := regexp.QuoteMeta(string(sep)) // needed for windows sep '\\' + return fmt.Sprintf(`(^|%s)%s($|%s)`, escapedSep, e, escapedSep) +} + +func pathElemRe(e string) string { + return pathElemReImpl(e, filepath.Separator) +} + +var StdExcludeDirRegexps = []string{ + pathElemRe("vendor"), + pathElemRe("third_party"), + pathElemRe("testdata"), + pathElemRe("examples"), + pathElemRe("Godeps"), + pathElemRe("builtin"), +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/packages/util.go b/vendor/github.com/golangci/golangci-lint/pkg/packages/util.go new file mode 100644 index 000000000..3c8642afa --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/packages/util.go @@ -0,0 +1,71 @@ +package packages + +import ( + "fmt" + + "golang.org/x/tools/go/packages" +) + +func ExtractErrors(pkg *packages.Package) []packages.Error { + errors := extractErrorsImpl(pkg, map[*packages.Package]bool{}) + if len(errors) == 0 { + return errors + } + + seenErrors := map[string]bool{} + var uniqErrors []packages.Error + for _, err := range errors { + if seenErrors[err.Msg] { + continue + } + seenErrors[err.Msg] = true + uniqErrors = append(uniqErrors, err) + } + + if len(pkg.GoFiles) != 0 { + // errors were extracted from deps and have at leat one file in package + for i := range uniqErrors { + _, parseErr := ParseErrorPosition(uniqErrors[i].Pos) + if parseErr != nil { + // change pos to local file to properly process it by processors (properly read line etc) + uniqErrors[i].Msg = fmt.Sprintf("%s: %s", uniqErrors[i].Pos, uniqErrors[i].Msg) + uniqErrors[i].Pos = fmt.Sprintf("%s:1", pkg.GoFiles[0]) + } + } + + // some errors like "code in directory expects import" don't have Pos, set it here + for i := range uniqErrors { + err := &uniqErrors[i] + if err.Pos == "" { + err.Pos = fmt.Sprintf("%s:1", pkg.GoFiles[0]) + } + } + } + + return uniqErrors +} + +func extractErrorsImpl(pkg *packages.Package, seenPackages map[*packages.Package]bool) []packages.Error { + if seenPackages[pkg] { + return nil + } + seenPackages[pkg] = true + + if !pkg.IllTyped { // otherwise it may take hours to traverse all deps many times + return nil + } + + if len(pkg.Errors) != 0 { + return pkg.Errors + } + + var errors []packages.Error + for _, iPkg := range pkg.Imports { + iPkgErrors := extractErrorsImpl(iPkg, seenPackages) + if iPkgErrors != nil { + errors = append(errors, iPkgErrors...) + } + } + + return errors +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/checkstyle.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/checkstyle.go new file mode 100644 index 000000000..f36bc108a --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/checkstyle.go @@ -0,0 +1,80 @@ +package printers + +import ( + "context" + "encoding/xml" + "fmt" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type checkstyleOutput struct { + XMLName xml.Name `xml:"checkstyle"` + Version string `xml:"version,attr"` + Files []*checkstyleFile `xml:"file"` +} + +type checkstyleFile struct { + Name string `xml:"name,attr"` + Errors []*checkstyleError `xml:"error"` +} + +type checkstyleError struct { + Column int `xml:"column,attr"` + Line int `xml:"line,attr"` + Message string `xml:"message,attr"` + Severity string `xml:"severity,attr"` + Source string `xml:"source,attr"` +} + +const defaultSeverity = "error" + +type Checkstyle struct{} + +func NewCheckstyle() *Checkstyle { + return &Checkstyle{} +} + +func (Checkstyle) Print(ctx context.Context, issues []result.Issue) error { + out := checkstyleOutput{ + Version: "5.0", + } + + files := map[string]*checkstyleFile{} + + for i := range issues { + issue := &issues[i] + file, ok := files[issue.FilePath()] + if !ok { + file = &checkstyleFile{ + Name: issue.FilePath(), + } + + files[issue.FilePath()] = file + } + + newError := &checkstyleError{ + Column: issue.Column(), + Line: issue.Line(), + Message: issue.Text, + Source: issue.FromLinter, + Severity: defaultSeverity, + } + + file.Errors = append(file.Errors, newError) + } + + out.Files = make([]*checkstyleFile, 0, len(files)) + for _, file := range files { + out.Files = append(out.Files, file) + } + + data, err := xml.Marshal(&out) + if err != nil { + return err + } + + fmt.Fprintf(logutils.StdOut, "%s%s\n", xml.Header, data) + return nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/codeclimate.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/codeclimate.go new file mode 100644 index 000000000..5d45c4eb3 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/codeclimate.go @@ -0,0 +1,62 @@ +package printers + +import ( + "context" + "crypto/md5" //nolint:gosec + "encoding/json" + "fmt" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +// CodeClimateIssue is a subset of the Code Climate spec - https://github.com/codeclimate/spec/blob/master/SPEC.md#data-types +// It is just enough to support GitLab CI Code Quality - https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html +type CodeClimateIssue struct { + Description string `json:"description"` + Fingerprint string `json:"fingerprint"` + Location struct { + Path string `json:"path"` + Lines struct { + Begin int `json:"begin"` + } `json:"lines"` + } `json:"location"` +} + +type CodeClimate struct { +} + +func NewCodeClimate() *CodeClimate { + return &CodeClimate{} +} + +func (p CodeClimate) Print(ctx context.Context, issues []result.Issue) error { + allIssues := []CodeClimateIssue{} + for ind := range issues { + i := &issues[ind] + var issue CodeClimateIssue + issue.Description = i.FromLinter + ": " + i.Text + issue.Location.Path = i.Pos.Filename + issue.Location.Lines.Begin = i.Pos.Line + + // Need a checksum of the issue, so we use MD5 of the filename, text, and first line of source if there is any + var firstLine string + if len(i.SourceLines) > 0 { + firstLine = i.SourceLines[0] + } + + hash := md5.New() //nolint:gosec + _, _ = hash.Write([]byte(i.Pos.Filename + i.Text + firstLine)) + issue.Fingerprint = fmt.Sprintf("%X", hash.Sum(nil)) + + allIssues = append(allIssues, issue) + } + + outputJSON, err := json.Marshal(allIssues) + if err != nil { + return err + } + + fmt.Fprint(logutils.StdOut, string(outputJSON)) + return nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/github.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/github.go new file mode 100644 index 000000000..fa11a2839 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/github.go @@ -0,0 +1,39 @@ +package printers + +import ( + "context" + "fmt" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type github struct { +} + +// Github output format outputs issues according to Github actions format: +// https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message +func NewGithub() Printer { + return &github{} +} + +// print each line as: ::error file=app.js,line=10,col=15::Something went wrong +func formatIssueAsGithub(issue *result.Issue) string { + ret := fmt.Sprintf("::error file=%s,line=%d", issue.FilePath(), issue.Line()) + if issue.Pos.Column != 0 { + ret += fmt.Sprintf(",col=%d", issue.Pos.Column) + } + + ret += fmt.Sprintf("::%s (%s)", issue.Text, issue.FromLinter) + return ret +} + +func (g *github) Print(_ context.Context, issues []result.Issue) error { + for ind := range issues { + _, err := fmt.Fprintln(logutils.StdOut, formatIssueAsGithub(&issues[ind])) + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/json.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/json.go new file mode 100644 index 000000000..6ffa996fb --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/json.go @@ -0,0 +1,41 @@ +package printers + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/report" + "github.com/golangci/golangci-lint/pkg/result" +) + +type JSON struct { + rd *report.Data +} + +func NewJSON(rd *report.Data) *JSON { + return &JSON{ + rd: rd, + } +} + +type JSONResult struct { + Issues []result.Issue + Report *report.Data +} + +func (p JSON) Print(ctx context.Context, issues []result.Issue) error { + res := JSONResult{ + Issues: issues, + Report: p.rd, + } + + outputJSON, err := json.Marshal(res) + if err != nil { + return err + } + + fmt.Fprint(logutils.StdOut, string(outputJSON)) + return nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/junitxml.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/junitxml.go new file mode 100644 index 000000000..9277cd66f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/junitxml.go @@ -0,0 +1,79 @@ +package printers + +import ( + "context" + "encoding/xml" + "strings" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type testSuitesXML struct { + XMLName xml.Name `xml:"testsuites"` + TestSuites []testSuiteXML +} + +type testSuiteXML struct { + XMLName xml.Name `xml:"testsuite"` + Suite string `xml:"name,attr"` + Tests int `xml:"tests,attr"` + Errors int `xml:"errors,attr"` + Failures int `xml:"failures,attr"` + TestCases []testCaseXML `xml:"testcase"` +} + +type testCaseXML struct { + Name string `xml:"name,attr"` + ClassName string `xml:"classname,attr"` + Failure failureXML `xml:"failure"` +} + +type failureXML struct { + Message string `xml:"message,attr"` + Content string `xml:",cdata"` +} + +type JunitXML struct { +} + +func NewJunitXML() *JunitXML { + return &JunitXML{} +} + +func (JunitXML) Print(ctx context.Context, issues []result.Issue) error { + suites := make(map[string]testSuiteXML) // use a map to group by file + + for ind := range issues { + i := &issues[ind] + suiteName := i.FilePath() + testSuite := suites[suiteName] + testSuite.Suite = i.FilePath() + testSuite.Tests++ + testSuite.Failures++ + + tc := testCaseXML{ + Name: i.FromLinter, + ClassName: i.Pos.String(), + Failure: failureXML{ + Message: i.Text, + Content: strings.Join(i.SourceLines, "\n"), + }, + } + + testSuite.TestCases = append(testSuite.TestCases, tc) + suites[suiteName] = testSuite + } + + var res testSuitesXML + for _, val := range suites { + res.TestSuites = append(res.TestSuites, val) + } + + enc := xml.NewEncoder(logutils.StdOut) + enc.Indent("", " ") + if err := enc.Encode(res); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/printer.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/printer.go new file mode 100644 index 000000000..bfafb88e2 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/printer.go @@ -0,0 +1,11 @@ +package printers + +import ( + "context" + + "github.com/golangci/golangci-lint/pkg/result" +) + +type Printer interface { + Print(ctx context.Context, issues []result.Issue) error +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/tab.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/tab.go new file mode 100644 index 000000000..d3cdce673 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/tab.go @@ -0,0 +1,58 @@ +package printers + +import ( + "context" + "fmt" + "io" + "text/tabwriter" + + "github.com/fatih/color" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type Tab struct { + printLinterName bool + log logutils.Log +} + +func NewTab(printLinterName bool, log logutils.Log) *Tab { + return &Tab{ + printLinterName: printLinterName, + log: log, + } +} + +func (p Tab) SprintfColored(ca color.Attribute, format string, args ...interface{}) string { + c := color.New(ca) + return c.Sprintf(format, args...) +} + +func (p *Tab) Print(ctx context.Context, issues []result.Issue) error { + w := tabwriter.NewWriter(logutils.StdOut, 0, 0, 2, ' ', 0) + + for i := range issues { + p.printIssue(&issues[i], w) + } + + if err := w.Flush(); err != nil { + p.log.Warnf("Can't flush tab writer: %s", err) + } + + return nil +} + +func (p Tab) printIssue(i *result.Issue, w io.Writer) { + text := p.SprintfColored(color.FgRed, "%s", i.Text) + if p.printLinterName { + text = fmt.Sprintf("%s\t%s", i.FromLinter, text) + } + + pos := p.SprintfColored(color.Bold, "%s:%d", i.FilePath(), i.Line()) + if i.Pos.Column != 0 { + pos += fmt.Sprintf(":%d", i.Pos.Column) + } + + fmt.Fprintf(w, "%s\t%s\n", pos, text) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/text.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/text.go new file mode 100644 index 000000000..283499205 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/text.go @@ -0,0 +1,90 @@ +package printers + +import ( + "context" + "fmt" + + "github.com/fatih/color" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type Text struct { + printIssuedLine bool + useColors bool + printLinterName bool + + log logutils.Log +} + +func NewText(printIssuedLine, useColors, printLinterName bool, log logutils.Log) *Text { + return &Text{ + printIssuedLine: printIssuedLine, + useColors: useColors, + printLinterName: printLinterName, + log: log, + } +} + +func (p Text) SprintfColored(ca color.Attribute, format string, args ...interface{}) string { + if !p.useColors { + return fmt.Sprintf(format, args...) + } + + c := color.New(ca) + return c.Sprintf(format, args...) +} + +func (p *Text) Print(ctx context.Context, issues []result.Issue) error { + for i := range issues { + p.printIssue(&issues[i]) + + if !p.printIssuedLine { + continue + } + + p.printSourceCode(&issues[i]) + p.printUnderLinePointer(&issues[i]) + } + + return nil +} + +func (p Text) printIssue(i *result.Issue) { + text := p.SprintfColored(color.FgRed, "%s", i.Text) + if p.printLinterName { + text += fmt.Sprintf(" (%s)", i.FromLinter) + } + pos := p.SprintfColored(color.Bold, "%s:%d", i.FilePath(), i.Line()) + if i.Pos.Column != 0 { + pos += fmt.Sprintf(":%d", i.Pos.Column) + } + fmt.Fprintf(logutils.StdOut, "%s: %s\n", pos, text) +} + +func (p Text) printSourceCode(i *result.Issue) { + for _, line := range i.SourceLines { + fmt.Fprintln(logutils.StdOut, line) + } +} + +func (p Text) printUnderLinePointer(i *result.Issue) { + // if column == 0 it means column is unknown (e.g. for gosec) + if len(i.SourceLines) != 1 || i.Pos.Column == 0 { + return + } + + col0 := i.Pos.Column - 1 + line := i.SourceLines[0] + prefixRunes := make([]rune, 0, len(line)) + for j := 0; j < len(line) && j < col0; j++ { + if line[j] == '\t' { + prefixRunes = append(prefixRunes, '\t') + } else { + prefixRunes = append(prefixRunes, ' ') + } + } + + fmt.Fprintf(logutils.StdOut, "%s%s\n", string(prefixRunes), p.SprintfColored(color.FgYellow, "^")) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/report/data.go b/vendor/github.com/golangci/golangci-lint/pkg/report/data.go new file mode 100644 index 000000000..f083fa9f5 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/report/data.go @@ -0,0 +1,26 @@ +package report + +type Warning struct { + Tag string `json:",omitempty"` + Text string +} + +type LinterData struct { + Name string + Enabled bool `json:",omitempty"` + EnabledByDefault bool `json:",omitempty"` +} + +type Data struct { + Warnings []Warning `json:",omitempty"` + Linters []LinterData `json:",omitempty"` + Error string `json:",omitempty"` +} + +func (d *Data) AddLinter(name string, enabled, enabledByDefault bool) { + d.Linters = append(d.Linters, LinterData{ + Name: name, + Enabled: enabled, + EnabledByDefault: enabledByDefault, + }) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/report/log.go b/vendor/github.com/golangci/golangci-lint/pkg/report/log.go new file mode 100644 index 000000000..45ab6cae8 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/report/log.go @@ -0,0 +1,64 @@ +package report + +import ( + "fmt" + "strings" + + "github.com/golangci/golangci-lint/pkg/logutils" +) + +type LogWrapper struct { + rd *Data + tags []string + origLog logutils.Log +} + +func NewLogWrapper(log logutils.Log, reportData *Data) *LogWrapper { + return &LogWrapper{ + rd: reportData, + origLog: log, + } +} + +func (lw LogWrapper) Fatalf(format string, args ...interface{}) { + lw.origLog.Fatalf(format, args...) +} + +func (lw LogWrapper) Panicf(format string, args ...interface{}) { + lw.origLog.Panicf(format, args...) +} + +func (lw LogWrapper) Errorf(format string, args ...interface{}) { + lw.origLog.Errorf(format, args...) + lw.rd.Error = fmt.Sprintf(format, args...) +} + +func (lw LogWrapper) Warnf(format string, args ...interface{}) { + lw.origLog.Warnf(format, args...) + w := Warning{ + Tag: strings.Join(lw.tags, "/"), + Text: fmt.Sprintf(format, args...), + } + + lw.rd.Warnings = append(lw.rd.Warnings, w) +} + +func (lw LogWrapper) Infof(format string, args ...interface{}) { + lw.origLog.Infof(format, args...) +} + +func (lw LogWrapper) Child(name string) logutils.Log { + c := lw + c.origLog = lw.origLog.Child(name) + c.tags = append([]string{}, lw.tags...) + c.tags = append(c.tags, name) + return c +} + +func (lw LogWrapper) SetLevel(level logutils.LogLevel) { + lw.origLog.SetLevel(level) +} + +func (lw LogWrapper) GoString() string { + return fmt.Sprintf("lw: %+v, orig log: %#v", lw, lw.origLog) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/issue.go b/vendor/github.com/golangci/golangci-lint/pkg/result/issue.go new file mode 100644 index 000000000..16d9a8a8c --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/issue.go @@ -0,0 +1,78 @@ +package result + +import ( + "go/token" + + "golang.org/x/tools/go/packages" +) + +type Range struct { + From, To int +} + +type Replacement struct { + NeedOnlyDelete bool // need to delete all lines of the issue without replacement with new lines + NewLines []string // is NeedDelete is false it's the replacement lines + Inline *InlineFix +} + +type InlineFix struct { + StartCol int // zero-based + Length int // length of chunk to be replaced + NewString string +} + +type Issue struct { + FromLinter string + Text string + + // Source lines of a code with the issue to show + SourceLines []string + + // If we know how to fix the issue we can provide replacement lines + Replacement *Replacement + + // Pkg is needed for proper caching of linting results + Pkg *packages.Package `json:"-"` + + LineRange *Range `json:",omitempty"` + + Pos token.Position + + // HunkPos is used only when golangci-lint is run over a diff + HunkPos int `json:",omitempty"` + + // If we are expecting a nolint (because this is from nolintlint), record the expected linter + ExpectNoLint bool + ExpectedNoLintLinter string +} + +func (i *Issue) FilePath() string { + return i.Pos.Filename +} + +func (i *Issue) Line() int { + return i.Pos.Line +} + +func (i *Issue) Column() int { + return i.Pos.Column +} + +func (i *Issue) GetLineRange() Range { + if i.LineRange == nil { + return Range{ + From: i.Line(), + To: i.Line(), + } + } + + if i.LineRange.From == 0 { + return Range{ + From: i.Line(), + To: i.Line(), + } + } + + return *i.LineRange +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/autogenerated_exclude.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/autogenerated_exclude.go new file mode 100644 index 000000000..249ba9d44 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/autogenerated_exclude.go @@ -0,0 +1,152 @@ +package processors + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/pkg/errors" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +var autogenDebugf = logutils.Debug("autogen_exclude") + +type ageFileSummary struct { + isGenerated bool +} + +type ageFileSummaryCache map[string]*ageFileSummary + +type AutogeneratedExclude struct { + fileSummaryCache ageFileSummaryCache +} + +func NewAutogeneratedExclude() *AutogeneratedExclude { + return &AutogeneratedExclude{ + fileSummaryCache: ageFileSummaryCache{}, + } +} + +var _ Processor = &AutogeneratedExclude{} + +func (p AutogeneratedExclude) Name() string { + return "autogenerated_exclude" +} + +func (p *AutogeneratedExclude) Process(issues []result.Issue) ([]result.Issue, error) { + return filterIssuesErr(issues, p.shouldPassIssue) +} + +func isSpecialAutogeneratedFile(filePath string) bool { + fileName := filepath.Base(filePath) + // fake files to which //line points to for goyacc generated files + return fileName == "yacctab" || fileName == "yaccpar" || fileName == "NONE" +} + +func (p *AutogeneratedExclude) shouldPassIssue(i *result.Issue) (bool, error) { + if i.FromLinter == "typecheck" { + // don't hide typechecking errors in generated files: users expect to see why the project isn't compiling + return true, nil + } + + if isSpecialAutogeneratedFile(i.FilePath()) { + return false, nil + } + + fs, err := p.getOrCreateFileSummary(i) + if err != nil { + return false, err + } + + // don't report issues for autogenerated files + return !fs.isGenerated, nil +} + +// isGenerated reports whether the source file is generated code. +// Using a bit laxer rules than https://golang.org/s/generatedcode to +// match more generated code. See #48 and #72. +func isGeneratedFileByComment(doc string) bool { + const ( + genCodeGenerated = "code generated" + genDoNotEdit = "do not edit" + genAutoFile = "autogenerated file" // easyjson + ) + + markers := []string{genCodeGenerated, genDoNotEdit, genAutoFile} + doc = strings.ToLower(doc) + for _, marker := range markers { + if strings.Contains(doc, marker) { + autogenDebugf("doc contains marker %q: file is generated", marker) + return true + } + } + + autogenDebugf("doc of len %d doesn't contain any of markers: %s", len(doc), markers) + return false +} + +func (p *AutogeneratedExclude) getOrCreateFileSummary(i *result.Issue) (*ageFileSummary, error) { + fs := p.fileSummaryCache[i.FilePath()] + if fs != nil { + return fs, nil + } + + fs = &ageFileSummary{} + p.fileSummaryCache[i.FilePath()] = fs + + if i.FilePath() == "" { + return nil, fmt.Errorf("no file path for issue") + } + + doc, err := getDoc(i.FilePath()) + if err != nil { + return nil, errors.Wrapf(err, "failed to get doc of file %s", i.FilePath()) + } + + fs.isGenerated = isGeneratedFileByComment(doc) + autogenDebugf("file %q is generated: %t", i.FilePath(), fs.isGenerated) + return fs, nil +} + +func getDoc(filePath string) (string, error) { + file, err := os.Open(filePath) + if err != nil { + return "", errors.Wrap(err, "failed to open file") + } + defer file.Close() + + scanner := bufio.NewScanner(file) + + // Issue 954: Some lines can be very long, e.g. auto-generated + // embedded resources. Reported on file of 86.2KB. + const ( + maxSize = 10 * 1024 * 1024 // 10MB should be enough + initialSize = 4096 // same as startBufSize in bufio + ) + scanner.Buffer(make([]byte, initialSize), maxSize) + + var docLines []string + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if strings.HasPrefix(line, "//") { + text := strings.TrimSpace(strings.TrimPrefix(line, "//")) + docLines = append(docLines, text) + } else if line == "" || strings.HasPrefix(line, "package") { + // go to next line + } else { + break + } + } + + if err := scanner.Err(); err != nil { + return "", errors.Wrap(err, "failed to scan file") + } + + return strings.Join(docLines, "\n"), nil +} + +func (p AutogeneratedExclude) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/cgo.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/cgo.go new file mode 100644 index 000000000..c8793871a --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/cgo.go @@ -0,0 +1,58 @@ +package processors + +import ( + "path/filepath" + "strings" + + "github.com/pkg/errors" + + "github.com/golangci/golangci-lint/pkg/goutil" + "github.com/golangci/golangci-lint/pkg/result" +) + +type Cgo struct { + goCacheDir string +} + +var _ Processor = Cgo{} + +func NewCgo(goenv *goutil.Env) *Cgo { + return &Cgo{ + goCacheDir: goenv.Get(goutil.EnvGoCache), + } +} + +func (p Cgo) Name() string { + return "cgo" +} + +func (p Cgo) Process(issues []result.Issue) ([]result.Issue, error) { + return filterIssuesErr(issues, func(i *result.Issue) (bool, error) { + // some linters (.e.g gosec, deadcode) return incorrect filepaths for cgo issues, + // also cgo files have strange issues looking like false positives. + + // cache dir contains all preprocessed files including cgo files + + issueFilePath := i.FilePath() + if !filepath.IsAbs(i.FilePath()) { + absPath, err := filepath.Abs(i.FilePath()) + if err != nil { + return false, errors.Wrapf(err, "failed to build abs path for %q", i.FilePath()) + } + issueFilePath = absPath + } + + if p.goCacheDir != "" && strings.HasPrefix(issueFilePath, p.goCacheDir) { + return false, nil + } + + if filepath.Base(i.FilePath()) == "_cgo_gotypes.go" { + // skip cgo warning for go1.10 + return false, nil + } + + return true, nil + }) +} + +func (Cgo) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/diff.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/diff.go new file mode 100644 index 000000000..fc4aba4b9 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/diff.go @@ -0,0 +1,74 @@ +package processors + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "strings" + + "github.com/golangci/revgrep" + + "github.com/golangci/golangci-lint/pkg/result" +) + +type Diff struct { + onlyNew bool + fromRev string + patchFilePath string + patch string +} + +var _ Processor = Diff{} + +func NewDiff(onlyNew bool, fromRev, patchFilePath string) *Diff { + return &Diff{ + onlyNew: onlyNew, + fromRev: fromRev, + patchFilePath: patchFilePath, + patch: os.Getenv("GOLANGCI_DIFF_PROCESSOR_PATCH"), + } +} + +func (p Diff) Name() string { + return "diff" +} + +func (p Diff) Process(issues []result.Issue) ([]result.Issue, error) { + if !p.onlyNew && p.fromRev == "" && p.patchFilePath == "" && p.patch == "" { // no need to work + return issues, nil + } + + var patchReader io.Reader + if p.patchFilePath != "" { + patch, err := ioutil.ReadFile(p.patchFilePath) + if err != nil { + return nil, fmt.Errorf("can't read from patch file %s: %s", p.patchFilePath, err) + } + patchReader = bytes.NewReader(patch) + } else if p.patch != "" { + patchReader = strings.NewReader(p.patch) + } + + c := revgrep.Checker{ + Patch: patchReader, + RevisionFrom: p.fromRev, + } + if err := c.Prepare(); err != nil { + return nil, fmt.Errorf("can't prepare diff by revgrep: %s", err) + } + + return transformIssues(issues, func(i *result.Issue) *result.Issue { + hunkPos, isNew := c.IsNewIssue(i) + if !isNew { + return nil + } + + newI := *i + newI.HunkPos = hunkPos + return &newI + }), nil +} + +func (Diff) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/exclude.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/exclude.go new file mode 100644 index 000000000..92959a328 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/exclude.go @@ -0,0 +1,59 @@ +package processors + +import ( + "regexp" + + "github.com/golangci/golangci-lint/pkg/result" +) + +type Exclude struct { + pattern *regexp.Regexp +} + +var _ Processor = Exclude{} + +func NewExclude(pattern string) *Exclude { + var patternRe *regexp.Regexp + if pattern != "" { + patternRe = regexp.MustCompile("(?i)" + pattern) + } + return &Exclude{ + pattern: patternRe, + } +} + +func (p Exclude) Name() string { + return "exclude" +} + +func (p Exclude) Process(issues []result.Issue) ([]result.Issue, error) { + if p.pattern == nil { + return issues, nil + } + + return filterIssues(issues, func(i *result.Issue) bool { + return !p.pattern.MatchString(i.Text) + }), nil +} + +func (p Exclude) Finish() {} + +type ExcludeCaseSensitive struct { + *Exclude +} + +var _ Processor = ExcludeCaseSensitive{} + +func NewExcludeCaseSensitive(pattern string) *ExcludeCaseSensitive { + var patternRe *regexp.Regexp + if pattern != "" { + patternRe = regexp.MustCompile(pattern) + } + return &ExcludeCaseSensitive{ + &Exclude{pattern: patternRe}, + } +} + +func (p ExcludeCaseSensitive) Name() string { + return "exclude-case-sensitive" +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/exclude_rules.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/exclude_rules.go new file mode 100644 index 000000000..b926af5b1 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/exclude_rules.go @@ -0,0 +1,143 @@ +package processors + +import ( + "regexp" + + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type excludeRule struct { + text *regexp.Regexp + source *regexp.Regexp + path *regexp.Regexp + linters []string +} + +func (r *excludeRule) isEmpty() bool { + return r.text == nil && r.path == nil && len(r.linters) == 0 +} + +type ExcludeRule struct { + Text string + Source string + Path string + Linters []string +} + +type ExcludeRules struct { + rules []excludeRule + lineCache *fsutils.LineCache + log logutils.Log +} + +func NewExcludeRules(rules []ExcludeRule, lineCache *fsutils.LineCache, log logutils.Log) *ExcludeRules { + r := &ExcludeRules{ + lineCache: lineCache, + log: log, + } + r.rules = createRules(rules, "(?i)") + + return r +} + +func createRules(rules []ExcludeRule, prefix string) []excludeRule { + parsedRules := make([]excludeRule, 0, len(rules)) + for _, rule := range rules { + parsedRule := excludeRule{ + linters: rule.Linters, + } + if rule.Text != "" { + parsedRule.text = regexp.MustCompile(prefix + rule.Text) + } + if rule.Source != "" { + parsedRule.source = regexp.MustCompile(prefix + rule.Source) + } + if rule.Path != "" { + parsedRule.path = regexp.MustCompile(rule.Path) + } + parsedRules = append(parsedRules, parsedRule) + } + return parsedRules +} + +func (p ExcludeRules) Process(issues []result.Issue) ([]result.Issue, error) { + if len(p.rules) == 0 { + return issues, nil + } + return filterIssues(issues, func(i *result.Issue) bool { + for _, rule := range p.rules { + rule := rule + if p.match(i, &rule) { + return false + } + } + return true + }), nil +} + +func (p ExcludeRules) matchLinter(i *result.Issue, r *excludeRule) bool { + for _, linter := range r.linters { + if linter == i.FromLinter { + return true + } + } + + return false +} + +func (p ExcludeRules) matchSource(i *result.Issue, r *excludeRule) bool { //nolint:interfacer + sourceLine, err := p.lineCache.GetLine(i.FilePath(), i.Line()) + if err != nil { + p.log.Warnf("Failed to get line %s:%d from line cache: %s", i.FilePath(), i.Line(), err) + return false // can't properly match + } + + return r.source.MatchString(sourceLine) +} + +func (p ExcludeRules) match(i *result.Issue, r *excludeRule) bool { + if r.isEmpty() { + return false + } + if r.text != nil && !r.text.MatchString(i.Text) { + return false + } + if r.path != nil && !r.path.MatchString(i.FilePath()) { + return false + } + if len(r.linters) != 0 && !p.matchLinter(i, r) { + return false + } + + // the most heavyweight checking last + if r.source != nil && !p.matchSource(i, r) { + return false + } + + return true +} + +func (ExcludeRules) Name() string { return "exclude-rules" } +func (ExcludeRules) Finish() {} + +var _ Processor = ExcludeRules{} + +type ExcludeRulesCaseSensitive struct { + *ExcludeRules +} + +func NewExcludeRulesCaseSensitive(rules []ExcludeRule, lineCache *fsutils.LineCache, log logutils.Log) *ExcludeRulesCaseSensitive { + r := &ExcludeRules{ + lineCache: lineCache, + log: log, + } + r.rules = createRules(rules, "") + + return &ExcludeRulesCaseSensitive{r} +} + +func (ExcludeRulesCaseSensitive) Name() string { return "exclude-rules-case-sensitive" } + +var _ Processor = ExcludeCaseSensitive{} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/filename_unadjuster.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/filename_unadjuster.go new file mode 100644 index 000000000..5e692ceba --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/filename_unadjuster.go @@ -0,0 +1,123 @@ +package processors + +import ( + "go/parser" + "go/token" + "path/filepath" + "strings" + "sync" + "time" + + "golang.org/x/tools/go/packages" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type posMapper func(pos token.Position) token.Position + +// FilenameUnadjuster is needed because a lot of linters use fset.Position(f.Pos()) +// to get filename. And they return adjusted filename (e.g. *.qtpl) for an issue. We need +// restore real .go filename to properly output it, parse it, etc. +type FilenameUnadjuster struct { + m map[string]posMapper // map from adjusted filename to position mapper: adjusted -> unadjusted position + log logutils.Log + loggedUnadjustments map[string]bool +} + +var _ Processor = &FilenameUnadjuster{} + +func processUnadjusterPkg(m map[string]posMapper, pkg *packages.Package, log logutils.Log) { + fset := token.NewFileSet() // it's more memory efficient to not store all in one fset + + for _, filename := range pkg.CompiledGoFiles { + // It's important to call func here to run GC + processUnadjusterFile(filename, m, log, fset) + } +} + +func processUnadjusterFile(filename string, m map[string]posMapper, log logutils.Log, fset *token.FileSet) { + syntax, err := parser.ParseFile(fset, filename, nil, parser.ParseComments) + if err != nil { + // Error will be reported by typecheck + return + } + + adjustedFilename := fset.PositionFor(syntax.Pos(), true).Filename + if adjustedFilename == "" { + return + } + + unadjustedFilename := fset.PositionFor(syntax.Pos(), false).Filename + if unadjustedFilename == "" || unadjustedFilename == adjustedFilename { + return + } + + if !strings.HasSuffix(unadjustedFilename, ".go") { + return // file.go -> /caches/cgo-xxx + } + + m[adjustedFilename] = func(adjustedPos token.Position) token.Position { + tokenFile := fset.File(syntax.Pos()) + if tokenFile == nil { + log.Warnf("Failed to get token file for %s", adjustedFilename) + return adjustedPos + } + return fset.PositionFor(tokenFile.Pos(adjustedPos.Offset), false) + } +} + +func NewFilenameUnadjuster(pkgs []*packages.Package, log logutils.Log) *FilenameUnadjuster { + m := map[string]posMapper{} + startedAt := time.Now() + var wg sync.WaitGroup + wg.Add(len(pkgs)) + for _, pkg := range pkgs { + go func(pkg *packages.Package) { + // It's important to call func here to run GC + processUnadjusterPkg(m, pkg, log) + wg.Done() + }(pkg) + } + wg.Wait() + log.Infof("Pre-built %d adjustments in %s", len(m), time.Since(startedAt)) + + return &FilenameUnadjuster{ + m: m, + log: log, + loggedUnadjustments: map[string]bool{}, + } +} + +func (p FilenameUnadjuster) Name() string { + return "filename_unadjuster" +} + +func (p *FilenameUnadjuster) Process(issues []result.Issue) ([]result.Issue, error) { + return transformIssues(issues, func(i *result.Issue) *result.Issue { + issueFilePath := i.FilePath() + if !filepath.IsAbs(i.FilePath()) { + absPath, err := filepath.Abs(i.FilePath()) + if err != nil { + p.log.Warnf("failed to build abs path for %q: %s", i.FilePath(), err) + return i + } + issueFilePath = absPath + } + + mapper := p.m[issueFilePath] + if mapper == nil { + return i + } + + newI := *i + newI.Pos = mapper(i.Pos) + if !p.loggedUnadjustments[i.Pos.Filename] { + p.log.Infof("Unadjusted from %v to %v", i.Pos, newI.Pos) + p.loggedUnadjustments[i.Pos.Filename] = true + } + return &newI + }), nil +} + +func (FilenameUnadjuster) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/fixer.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/fixer.go new file mode 100644 index 000000000..75fdc93f1 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/fixer.go @@ -0,0 +1,248 @@ +package processors + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/pkg/errors" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" + "github.com/golangci/golangci-lint/pkg/timeutils" +) + +type Fixer struct { + cfg *config.Config + log logutils.Log + fileCache *fsutils.FileCache + sw *timeutils.Stopwatch +} + +func NewFixer(cfg *config.Config, log logutils.Log, fileCache *fsutils.FileCache) *Fixer { + return &Fixer{ + cfg: cfg, + log: log, + fileCache: fileCache, + sw: timeutils.NewStopwatch("fixer", log), + } +} + +func (f Fixer) printStat() { + f.sw.PrintStages() +} + +func (f Fixer) Process(issues []result.Issue) []result.Issue { + if !f.cfg.Issues.NeedFix { + return issues + } + + outIssues := make([]result.Issue, 0, len(issues)) + issuesToFixPerFile := map[string][]result.Issue{} + for i := range issues { + issue := &issues[i] + if issue.Replacement == nil { + outIssues = append(outIssues, *issue) + continue + } + + issuesToFixPerFile[issue.FilePath()] = append(issuesToFixPerFile[issue.FilePath()], *issue) + } + + for file, issuesToFix := range issuesToFixPerFile { + var err error + f.sw.TrackStage("all", func() { + err = f.fixIssuesInFile(file, issuesToFix) //nolint:scopelint + }) + if err != nil { + f.log.Errorf("Failed to fix issues in file %s: %s", file, err) + + // show issues only if can't fix them + outIssues = append(outIssues, issuesToFix...) + } + } + + f.printStat() + return outIssues +} + +func (f Fixer) fixIssuesInFile(filePath string, issues []result.Issue) error { + // TODO: don't read the whole file into memory: read line by line; + // can't just use bufio.scanner: it has a line length limit + origFileData, err := f.fileCache.GetFileBytes(filePath) + if err != nil { + return errors.Wrapf(err, "failed to get file bytes for %s", filePath) + } + origFileLines := bytes.Split(origFileData, []byte("\n")) + + tmpFileName := filepath.Join(filepath.Dir(filePath), fmt.Sprintf(".%s.golangci_fix", filepath.Base(filePath))) + tmpOutFile, err := os.Create(tmpFileName) + if err != nil { + return errors.Wrapf(err, "failed to make file %s", tmpFileName) + } + + // merge multiple issues per line into one issue + issuesPerLine := map[int][]result.Issue{} + for i := range issues { + issue := &issues[i] + issuesPerLine[issue.Line()] = append(issuesPerLine[issue.Line()], *issue) + } + + issues = issues[:0] // reuse the same memory + for line, lineIssues := range issuesPerLine { + if mergedIssue := f.mergeLineIssues(line, lineIssues, origFileLines); mergedIssue != nil { + issues = append(issues, *mergedIssue) + } + } + + issues = f.findNotIntersectingIssues(issues) + + if err = f.writeFixedFile(origFileLines, issues, tmpOutFile); err != nil { + tmpOutFile.Close() + os.Remove(tmpOutFile.Name()) + return err + } + + tmpOutFile.Close() + if err = os.Rename(tmpOutFile.Name(), filePath); err != nil { + os.Remove(tmpOutFile.Name()) + return errors.Wrapf(err, "failed to rename %s -> %s", tmpOutFile.Name(), filePath) + } + + return nil +} + +func (f Fixer) mergeLineIssues(lineNum int, lineIssues []result.Issue, origFileLines [][]byte) *result.Issue { + origLine := origFileLines[lineNum-1] // lineNum is 1-based + + if len(lineIssues) == 1 && lineIssues[0].Replacement.Inline == nil { + return &lineIssues[0] + } + + // check issues first + for ind := range lineIssues { + i := &lineIssues[ind] + if i.LineRange != nil { + f.log.Infof("Line %d has multiple issues but at least one of them is ranged: %#v", lineNum, lineIssues) + return &lineIssues[0] + } + + r := i.Replacement + if r.Inline == nil || len(r.NewLines) != 0 || r.NeedOnlyDelete { + f.log.Infof("Line %d has multiple issues but at least one of them isn't inline: %#v", lineNum, lineIssues) + return &lineIssues[0] + } + + if r.Inline.StartCol < 0 || r.Inline.Length <= 0 || r.Inline.StartCol+r.Inline.Length > len(origLine) { + f.log.Warnf("Line %d (%q) has invalid inline fix: %#v, %#v", lineNum, origLine, i, r.Inline) + return nil + } + } + + return f.applyInlineFixes(lineIssues, origLine, lineNum) +} + +func (f Fixer) applyInlineFixes(lineIssues []result.Issue, origLine []byte, lineNum int) *result.Issue { + sort.Slice(lineIssues, func(i, j int) bool { + return lineIssues[i].Replacement.Inline.StartCol < lineIssues[j].Replacement.Inline.StartCol + }) + + var newLineBuf bytes.Buffer + newLineBuf.Grow(len(origLine)) + + //nolint:misspell + // example: origLine="it's becouse of them", StartCol=5, Length=7, NewString="because" + + curOrigLinePos := 0 + for i := range lineIssues { + fix := lineIssues[i].Replacement.Inline + if fix.StartCol < curOrigLinePos { + f.log.Warnf("Line %d has multiple intersecting issues: %#v", lineNum, lineIssues) + return nil + } + + if curOrigLinePos != fix.StartCol { + newLineBuf.Write(origLine[curOrigLinePos:fix.StartCol]) + } + newLineBuf.WriteString(fix.NewString) + curOrigLinePos = fix.StartCol + fix.Length + } + if curOrigLinePos != len(origLine) { + newLineBuf.Write(origLine[curOrigLinePos:]) + } + + mergedIssue := lineIssues[0] // use text from the first issue (it's not really used) + mergedIssue.Replacement = &result.Replacement{ + NewLines: []string{newLineBuf.String()}, + } + return &mergedIssue +} + +func (f Fixer) findNotIntersectingIssues(issues []result.Issue) []result.Issue { + sort.SliceStable(issues, func(i, j int) bool { + a, b := issues[i], issues[j] + return a.Line() < b.Line() + }) + + var ret []result.Issue + var currentEnd int + for i := range issues { + issue := &issues[i] + rng := issue.GetLineRange() + if rng.From <= currentEnd { + f.log.Infof("Skip issue %#v: intersects with end %d", issue, currentEnd) + continue // skip intersecting issue + } + f.log.Infof("Fix issue %#v with range %v", issue, issue.GetLineRange()) + ret = append(ret, *issue) + currentEnd = rng.To + } + + return ret +} + +func (f Fixer) writeFixedFile(origFileLines [][]byte, issues []result.Issue, tmpOutFile *os.File) error { + // issues aren't intersecting + + nextIssueIndex := 0 + for i := 0; i < len(origFileLines); i++ { + var outLine string + var nextIssue *result.Issue + if nextIssueIndex != len(issues) { + nextIssue = &issues[nextIssueIndex] + } + + origFileLineNumber := i + 1 + if nextIssue == nil || origFileLineNumber != nextIssue.GetLineRange().From { + outLine = string(origFileLines[i]) + } else { + nextIssueIndex++ + rng := nextIssue.GetLineRange() + if rng.From > rng.To { + // Maybe better decision is to skip such issues, re-evaluate if regressed. + f.log.Warnf("[fixer]: issue line range is probably invalid, fix can be incorrect (from=%d, to=%d, linter=%s)", + rng.From, rng.To, nextIssue.FromLinter, + ) + } + i += rng.To - rng.From + if nextIssue.Replacement.NeedOnlyDelete { + continue + } + outLine = strings.Join(nextIssue.Replacement.NewLines, "\n") + } + + if i < len(origFileLines)-1 { + outLine += "\n" + } + if _, err := tmpOutFile.WriteString(outLine); err != nil { + return errors.Wrap(err, "failed to write output line") + } + } + + return nil +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/identifier_marker.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/identifier_marker.go new file mode 100644 index 000000000..5cc4e56ba --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/identifier_marker.go @@ -0,0 +1,125 @@ +package processors + +import ( + "regexp" + + "github.com/golangci/golangci-lint/pkg/result" +) + +type replacePattern struct { + re string + repl string +} + +type replaceRegexp struct { + re *regexp.Regexp + repl string +} + +var replacePatterns = []replacePattern{ + // unparam + {`^(\S+) - (\S+) is unused$`, "`${1}` - `${2}` is unused"}, + {`^(\S+) - (\S+) always receives (\S+) \((.*)\)$`, "`${1}` - `${2}` always receives `${3}` (`${4}`)"}, + {`^(\S+) - (\S+) always receives (.*)$`, "`${1}` - `${2}` always receives `${3}`"}, + {`^(\S+) - result (\S+) is always (\S+)`, "`${1}` - result `${2}` is always `${3}`"}, + + // interfacer + {`^(\S+) can be (\S+)$`, "`${1}` can be `${2}`"}, + + // govet + {`^printf: (\S+) arg list ends with redundant newline$`, "printf: `${1}` arg list ends with redundant newline"}, + {`^composites: (\S+) composite literal uses unkeyed fields$`, "composites: `${1}` composite literal uses unkeyed fields"}, + + // gosec + {`^(\S+): Blacklisted import (\S+): weak cryptographic primitive$`, + "${1}: Blacklisted import `${2}`: weak cryptographic primitive"}, + {`^TLS InsecureSkipVerify set true.$`, "TLS `InsecureSkipVerify` set true."}, + + // gosimple + {`should replace loop with (.*)$`, "should replace loop with `${1}`"}, + {`should use a simple channel send/receive instead of select with a single case`, + "should use a simple channel send/receive instead of `select` with a single case"}, + {`should omit comparison to bool constant, can be simplified to (.+)$`, + "should omit comparison to bool constant, can be simplified to `${1}`"}, + {`should write (.+) instead of (.+)$`, "should write `${1}` instead of `${2}`"}, + {`redundant return statement$`, "redundant `return` statement"}, + {`should replace this if statement with an unconditional strings.TrimPrefix`, + "should replace this `if` statement with an unconditional `strings.TrimPrefix`"}, + + // staticcheck + {`this value of (\S+) is never used$`, "this value of `${1}` is never used"}, + {`should use time.Since instead of time.Now\(\).Sub$`, + "should use `time.Since` instead of `time.Now().Sub`"}, + {`should check returned error before deferring response.Close\(\)$`, + "should check returned error before deferring `response.Close()`"}, + {`no value of type uint is less than 0$`, "no value of type `uint` is less than `0`"}, + + // unused + {`(func|const|field|type|var) (\S+) is unused$`, "${1} `${2}` is unused"}, + + // typecheck + {`^unknown field (\S+) in struct literal$`, "unknown field `${1}` in struct literal"}, + {`^invalid operation: (\S+) \(variable of type (\S+)\) has no field or method (\S+)$`, + "invalid operation: `${1}` (variable of type `${2}`) has no field or method `${3}`"}, + {`^undeclared name: (\S+)$`, "undeclared name: `${1}`"}, + {`^cannot use addr \(variable of type (\S+)\) as (\S+) value in argument to (\S+)$`, + "cannot use addr (variable of type `${1}`) as `${2}` value in argument to `${3}`"}, + {`^other declaration of (\S+)$`, "other declaration of `${1}`"}, + {`^(\S+) redeclared in this block$`, "`${1}` redeclared in this block"}, + + // golint + {`^exported (type|method|function|var|const) (\S+) should have comment or be unexported$`, + "exported ${1} `${2}` should have comment or be unexported"}, + {`^comment on exported (type|method|function|var|const) (\S+) should be of the form "(\S+) ..."$`, + "comment on exported ${1} `${2}` should be of the form `${3} ...`"}, + {`^should replace (.+) with (.+)$`, "should replace `${1}` with `${2}`"}, + {`^if block ends with a return statement, so drop this else and outdent its block$`, + "`if` block ends with a `return` statement, so drop this `else` and outdent its block"}, + {`^(struct field|var|range var|const|type|(?:func|method|interface method) (?:parameter|result)) (\S+) should be (\S+)$`, + "${1} `${2}` should be `${3}`"}, + {`^don't use underscores in Go names; var (\S+) should be (\S+)$`, + "don't use underscores in Go names; var `${1}` should be `${2}`"}, +} + +type IdentifierMarker struct { + replaceRegexps []replaceRegexp +} + +func NewIdentifierMarker() *IdentifierMarker { + var replaceRegexps []replaceRegexp + for _, p := range replacePatterns { + r := replaceRegexp{ + re: regexp.MustCompile(p.re), + repl: p.repl, + } + replaceRegexps = append(replaceRegexps, r) + } + + return &IdentifierMarker{ + replaceRegexps: replaceRegexps, + } +} + +func (im IdentifierMarker) Process(issues []result.Issue) ([]result.Issue, error) { + return transformIssues(issues, func(i *result.Issue) *result.Issue { + iCopy := *i + iCopy.Text = im.markIdentifiers(iCopy.Text) + return &iCopy + }), nil +} + +func (im IdentifierMarker) markIdentifiers(s string) string { + for _, rr := range im.replaceRegexps { + rs := rr.re.ReplaceAllString(s, rr.repl) + if rs != s { + return rs + } + } + + return s +} + +func (im IdentifierMarker) Name() string { + return "identifier_marker" +} +func (im IdentifierMarker) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_from_linter.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_from_linter.go new file mode 100644 index 000000000..c58666c56 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_from_linter.go @@ -0,0 +1,54 @@ +package processors + +import ( + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type MaxFromLinter struct { + lc linterToCountMap + limit int + log logutils.Log + cfg *config.Config +} + +var _ Processor = &MaxFromLinter{} + +func NewMaxFromLinter(limit int, log logutils.Log, cfg *config.Config) *MaxFromLinter { + return &MaxFromLinter{ + lc: linterToCountMap{}, + limit: limit, + log: log, + cfg: cfg, + } +} + +func (p MaxFromLinter) Name() string { + return "max_from_linter" +} + +func (p *MaxFromLinter) Process(issues []result.Issue) ([]result.Issue, error) { + if p.limit <= 0 { // no limit + return issues, nil + } + + return filterIssues(issues, func(i *result.Issue) bool { + if i.Replacement != nil && p.cfg.Issues.NeedFix { + // we need to fix all issues at once => we need to return all of them + return true + } + + p.lc[i.FromLinter]++ // always inc for stat + return p.lc[i.FromLinter] <= p.limit + }), nil +} + +func (p MaxFromLinter) Finish() { + walkStringToIntMapSortedByValue(p.lc, func(linter string, count int) { + if count > p.limit { + p.log.Infof("%d/%d issues from linter %s were hidden, use --max-issues-per-linter", + count-p.limit, count, linter) + } + }) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_per_file_from_linter.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_per_file_from_linter.go new file mode 100644 index 000000000..e83c569ef --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_per_file_from_linter.go @@ -0,0 +1,60 @@ +package processors + +import ( + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/result" +) + +type linterToCountMap map[string]int +type fileToLinterToCountMap map[string]linterToCountMap + +type MaxPerFileFromLinter struct { + flc fileToLinterToCountMap + maxPerFileFromLinterConfig map[string]int +} + +var _ Processor = &MaxPerFileFromLinter{} + +func NewMaxPerFileFromLinter(cfg *config.Config) *MaxPerFileFromLinter { + maxPerFileFromLinterConfig := map[string]int{ + "typecheck": 3, + } + if !cfg.Issues.NeedFix { + // if we don't fix we do this limiting to not annoy user; + // otherwise we need to fix all issues in the file at once + maxPerFileFromLinterConfig["gofmt"] = 1 + maxPerFileFromLinterConfig["goimports"] = 1 + } + + return &MaxPerFileFromLinter{ + flc: fileToLinterToCountMap{}, + maxPerFileFromLinterConfig: maxPerFileFromLinterConfig, + } +} + +func (p MaxPerFileFromLinter) Name() string { + return "max_per_file_from_linter" +} + +func (p *MaxPerFileFromLinter) Process(issues []result.Issue) ([]result.Issue, error) { + return filterIssues(issues, func(i *result.Issue) bool { + limit := p.maxPerFileFromLinterConfig[i.FromLinter] + if limit == 0 { + return true + } + + lm := p.flc[i.FilePath()] + if lm == nil { + p.flc[i.FilePath()] = linterToCountMap{} + } + count := p.flc[i.FilePath()][i.FromLinter] + if count >= limit { + return false + } + + p.flc[i.FilePath()][i.FromLinter]++ + return true + }), nil +} + +func (p MaxPerFileFromLinter) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_same_issues.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_same_issues.go new file mode 100644 index 000000000..84fdf0c05 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/max_same_issues.go @@ -0,0 +1,81 @@ +package processors + +import ( + "sort" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type textToCountMap map[string]int + +type MaxSameIssues struct { + tc textToCountMap + limit int + log logutils.Log + cfg *config.Config +} + +var _ Processor = &MaxSameIssues{} + +func NewMaxSameIssues(limit int, log logutils.Log, cfg *config.Config) *MaxSameIssues { + return &MaxSameIssues{ + tc: textToCountMap{}, + limit: limit, + log: log, + cfg: cfg, + } +} + +func (MaxSameIssues) Name() string { + return "max_same_issues" +} + +func (p *MaxSameIssues) Process(issues []result.Issue) ([]result.Issue, error) { + if p.limit <= 0 { // no limit + return issues, nil + } + + return filterIssues(issues, func(i *result.Issue) bool { + if i.Replacement != nil && p.cfg.Issues.NeedFix { + // we need to fix all issues at once => we need to return all of them + return true + } + + p.tc[i.Text]++ // always inc for stat + return p.tc[i.Text] <= p.limit + }), nil +} + +func (p MaxSameIssues) Finish() { + walkStringToIntMapSortedByValue(p.tc, func(text string, count int) { + if count > p.limit { + p.log.Infof("%d/%d issues with text %q were hidden, use --max-same-issues", + count-p.limit, count, text) + } + }) +} + +type kv struct { + Key string + Value int +} + +func walkStringToIntMapSortedByValue(m map[string]int, walk func(k string, v int)) { + var ss []kv + for k, v := range m { + ss = append(ss, kv{ + Key: k, + Value: v, + }) + } + + sort.Slice(ss, func(i, j int) bool { + return ss[i].Value > ss[j].Value + }) + + for _, kv := range ss { + walk(kv.Key, kv.Value) + } +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/nolint.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/nolint.go new file mode 100644 index 000000000..cda101784 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/nolint.go @@ -0,0 +1,304 @@ +package processors + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "sort" + "strings" + + "github.com/golangci/golangci-lint/pkg/golinters" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +var nolintDebugf = logutils.Debug("nolint") + +type ignoredRange struct { + linters []string + matchedIssueFromLinter map[string]bool + result.Range + col int +} + +func (i *ignoredRange) doesMatch(issue *result.Issue) bool { + if issue.Line() < i.From || issue.Line() > i.To { + return false + } + + // handle possible unused nolint directives + // nolintlint generates potential issues for every nolint directive and they are filtered out here + if issue.ExpectNoLint { + if issue.ExpectedNoLintLinter != "" { + return i.matchedIssueFromLinter[issue.ExpectedNoLintLinter] + } + return len(i.matchedIssueFromLinter) > 0 + } + + if len(i.linters) == 0 { + return true + } + + for _, linterName := range i.linters { + if linterName == issue.FromLinter { + return true + } + } + + return false +} + +type fileData struct { + ignoredRanges []ignoredRange +} + +type filesCache map[string]*fileData + +type Nolint struct { + cache filesCache + dbManager *lintersdb.Manager + enabledLinters map[string]*linter.Config + log logutils.Log + + unknownLintersSet map[string]bool +} + +func NewNolint(log logutils.Log, dbManager *lintersdb.Manager, enabledLinters map[string]*linter.Config) *Nolint { + return &Nolint{ + cache: filesCache{}, + dbManager: dbManager, + enabledLinters: enabledLinters, + log: log, + unknownLintersSet: map[string]bool{}, + } +} + +var _ Processor = &Nolint{} + +func (p Nolint) Name() string { + return "nolint" +} + +func (p *Nolint) Process(issues []result.Issue) ([]result.Issue, error) { + // put nolintlint issues last because we process other issues first to determine which nolint directives are unused + sort.Stable(sortWithNolintlintLast(issues)) + return filterIssuesErr(issues, p.shouldPassIssue) +} + +func (p *Nolint) getOrCreateFileData(i *result.Issue) (*fileData, error) { + fd := p.cache[i.FilePath()] + if fd != nil { + return fd, nil + } + + fd = &fileData{} + p.cache[i.FilePath()] = fd + + if i.FilePath() == "" { + return nil, fmt.Errorf("no file path for issue") + } + + // TODO: migrate this parsing to go/analysis facts + // or cache them somehow per file. + + // Don't use cached AST because they consume a lot of memory on large projects. + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, i.FilePath(), nil, parser.ParseComments) + if err != nil { + // Don't report error because it's already must be reporter by typecheck or go/analysis. + return fd, nil + } + + fd.ignoredRanges = p.buildIgnoredRangesForFile(f, fset, i.FilePath()) + nolintDebugf("file %s: built nolint ranges are %+v", i.FilePath(), fd.ignoredRanges) + return fd, nil +} + +func (p *Nolint) buildIgnoredRangesForFile(f *ast.File, fset *token.FileSet, filePath string) []ignoredRange { + inlineRanges := p.extractFileCommentsInlineRanges(fset, f.Comments...) + nolintDebugf("file %s: inline nolint ranges are %+v", filePath, inlineRanges) + + if len(inlineRanges) == 0 { + return nil + } + + e := rangeExpander{ + fset: fset, + inlineRanges: inlineRanges, + } + + ast.Walk(&e, f) + + // TODO: merge all ranges: there are repeated ranges + allRanges := append([]ignoredRange{}, inlineRanges...) + allRanges = append(allRanges, e.expandedRanges...) + + return allRanges +} + +func (p *Nolint) shouldPassIssue(i *result.Issue) (bool, error) { + nolintDebugf("got issue: %v", *i) + if i.FromLinter == golinters.NolintlintName { + // always pass nolintlint issues except ones trying find unused nolint directives + if !i.ExpectNoLint { + return true, nil + } + if i.ExpectedNoLintLinter != "" { + // don't expect disabled linters to cover their nolint statements + nolintDebugf("enabled linters: %v", p.enabledLinters) + if p.enabledLinters[i.ExpectedNoLintLinter] == nil { + return false, nil + } + nolintDebugf("checking that lint issue was used for %s: %v", i.ExpectedNoLintLinter, i) + } + } + + fd, err := p.getOrCreateFileData(i) + if err != nil { + return false, err + } + + for _, ir := range fd.ignoredRanges { + if ir.doesMatch(i) { + ir.matchedIssueFromLinter[i.FromLinter] = true + return false, nil + } + } + + return true, nil +} + +type rangeExpander struct { + fset *token.FileSet + inlineRanges []ignoredRange + expandedRanges []ignoredRange +} + +func (e *rangeExpander) Visit(node ast.Node) ast.Visitor { + if node == nil { + return e + } + + nodeStartPos := e.fset.Position(node.Pos()) + nodeStartLine := nodeStartPos.Line + nodeEndLine := e.fset.Position(node.End()).Line + + var foundRange *ignoredRange + for _, r := range e.inlineRanges { + if r.To == nodeStartLine-1 && nodeStartPos.Column == r.col { + r := r + foundRange = &r + break + } + } + if foundRange == nil { + return e + } + + expandedRange := *foundRange + if expandedRange.To < nodeEndLine { + expandedRange.To = nodeEndLine + } + nolintDebugf("found range is %v for node %#v [%d;%d], expanded range is %v", + *foundRange, node, nodeStartLine, nodeEndLine, expandedRange) + e.expandedRanges = append(e.expandedRanges, expandedRange) + + return e +} + +func (p *Nolint) extractFileCommentsInlineRanges(fset *token.FileSet, comments ...*ast.CommentGroup) []ignoredRange { + var ret []ignoredRange + for _, g := range comments { + for _, c := range g.List { + ir := p.extractInlineRangeFromComment(c.Text, g, fset) + if ir != nil { + ret = append(ret, *ir) + } + } + } + + return ret +} + +func (p *Nolint) extractInlineRangeFromComment(text string, g ast.Node, fset *token.FileSet) *ignoredRange { + text = strings.TrimLeft(text, "/ ") + if !strings.HasPrefix(text, "nolint") { + return nil + } + + buildRange := func(linters []string) *ignoredRange { + pos := fset.Position(g.Pos()) + return &ignoredRange{ + Range: result.Range{ + From: pos.Line, + To: fset.Position(g.End()).Line, + }, + col: pos.Column, + linters: linters, + matchedIssueFromLinter: make(map[string]bool), + } + } + + if !strings.HasPrefix(text, "nolint:") { + return buildRange(nil) // ignore all linters + } + + // ignore specific linters + var linters []string + text = strings.Split(text, "//")[0] // allow another comment after this comment + linterItems := strings.Split(strings.TrimPrefix(text, "nolint:"), ",") + var gotUnknownLinters bool + for _, linter := range linterItems { + linterName := strings.ToLower(strings.TrimSpace(linter)) + + lcs := p.dbManager.GetLinterConfigs(linterName) + if lcs == nil { + p.unknownLintersSet[linterName] = true + gotUnknownLinters = true + continue + } + + for _, lc := range lcs { + linters = append(linters, lc.Name()) // normalize name to work with aliases + } + } + + if gotUnknownLinters { + return buildRange(nil) // ignore all linters to not annoy user + } + + nolintDebugf("%d: linters are %s", fset.Position(g.Pos()).Line, linters) + return buildRange(linters) +} + +func (p Nolint) Finish() { + if len(p.unknownLintersSet) == 0 { + return + } + + unknownLinters := []string{} + for name := range p.unknownLintersSet { + unknownLinters = append(unknownLinters, name) + } + sort.Strings(unknownLinters) + + p.log.Warnf("Found unknown linters in //nolint directives: %s", strings.Join(unknownLinters, ", ")) +} + +// put nolintlint last +type sortWithNolintlintLast []result.Issue + +func (issues sortWithNolintlintLast) Len() int { + return len(issues) +} + +func (issues sortWithNolintlintLast) Less(i, j int) bool { + return issues[i].FromLinter != golinters.NolintlintName && issues[j].FromLinter == golinters.NolintlintName +} + +func (issues sortWithNolintlintLast) Swap(i, j int) { + issues[j], issues[i] = issues[i], issues[j] +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/path_prettifier.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/path_prettifier.go new file mode 100644 index 000000000..3a140999c --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/path_prettifier.go @@ -0,0 +1,48 @@ +package processors + +import ( + "fmt" + "path/filepath" + + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type PathPrettifier struct { + root string +} + +var _ Processor = PathPrettifier{} + +func NewPathPrettifier() *PathPrettifier { + root, err := fsutils.Getwd() + if err != nil { + panic(fmt.Sprintf("Can't get working dir: %s", err)) + } + return &PathPrettifier{ + root: root, + } +} + +func (p PathPrettifier) Name() string { + return "path_prettifier" +} + +func (p PathPrettifier) Process(issues []result.Issue) ([]result.Issue, error) { + return transformIssues(issues, func(i *result.Issue) *result.Issue { + if !filepath.IsAbs(i.FilePath()) { + return i + } + + rel, err := fsutils.ShortestRelPath(i.FilePath(), "") + if err != nil { + return i + } + + newI := i + newI.Pos.Filename = rel + return newI + }), nil +} + +func (p PathPrettifier) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/path_shortener.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/path_shortener.go new file mode 100644 index 000000000..484f7f1f1 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/path_shortener.go @@ -0,0 +1,40 @@ +package processors + +import ( + "fmt" + "strings" + + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type PathShortener struct { + wd string +} + +var _ Processor = PathShortener{} + +func NewPathShortener() *PathShortener { + wd, err := fsutils.Getwd() + if err != nil { + panic(fmt.Sprintf("Can't get working dir: %s", err)) + } + return &PathShortener{ + wd: wd, + } +} + +func (p PathShortener) Name() string { + return "path_shortener" +} + +func (p PathShortener) Process(issues []result.Issue) ([]result.Issue, error) { + return transformIssues(issues, func(i *result.Issue) *result.Issue { + newI := i + newI.Text = strings.Replace(newI.Text, p.wd+"/", "", -1) + newI.Text = strings.Replace(newI.Text, p.wd, "", -1) + return newI + }), nil +} + +func (p PathShortener) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/processor.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/processor.go new file mode 100644 index 000000000..1a7a40434 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/processor.go @@ -0,0 +1,11 @@ +package processors + +import ( + "github.com/golangci/golangci-lint/pkg/result" +) + +type Processor interface { + Process(issues []result.Issue) ([]result.Issue, error) + Name() string + Finish() +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/skip_dirs.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/skip_dirs.go new file mode 100644 index 000000000..6488c109e --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/skip_dirs.go @@ -0,0 +1,143 @@ +package processors + +import ( + "path/filepath" + "regexp" + "strings" + + "github.com/pkg/errors" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type skipStat struct { + pattern string + count int +} + +type SkipDirs struct { + patterns []*regexp.Regexp + log logutils.Log + skippedDirs map[string]*skipStat + absArgsDirs []string + skippedDirsCache map[string]bool +} + +var _ Processor = SkipFiles{} + +const goFileSuffix = ".go" + +func NewSkipDirs(patterns []string, log logutils.Log, runArgs []string) (*SkipDirs, error) { + var patternsRe []*regexp.Regexp + for _, p := range patterns { + p = normalizePathInRegex(p) + patternRe, err := regexp.Compile(p) + if err != nil { + return nil, errors.Wrapf(err, "can't compile regexp %q", p) + } + patternsRe = append(patternsRe, patternRe) + } + + if len(runArgs) == 0 { + runArgs = append(runArgs, "./...") + } + var absArgsDirs []string + for _, arg := range runArgs { + base := filepath.Base(arg) + if base == "..." || strings.HasSuffix(base, goFileSuffix) { + arg = filepath.Dir(arg) + } + + absArg, err := filepath.Abs(arg) + if err != nil { + return nil, errors.Wrapf(err, "failed to abs-ify arg %q", arg) + } + absArgsDirs = append(absArgsDirs, absArg) + } + + return &SkipDirs{ + patterns: patternsRe, + log: log, + skippedDirs: map[string]*skipStat{}, + absArgsDirs: absArgsDirs, + skippedDirsCache: map[string]bool{}, + }, nil +} + +func (p *SkipDirs) Name() string { + return "skip_dirs" +} + +func (p *SkipDirs) Process(issues []result.Issue) ([]result.Issue, error) { + if len(p.patterns) == 0 { + return issues, nil + } + + return filterIssues(issues, p.shouldPassIssue), nil +} + +func (p *SkipDirs) shouldPassIssue(i *result.Issue) bool { + if filepath.IsAbs(i.FilePath()) { + if !isSpecialAutogeneratedFile(i.FilePath()) { + p.log.Warnf("Got abs path %s in skip dirs processor, it should be relative", i.FilePath()) + } + return true + } + + issueRelDir := filepath.Dir(i.FilePath()) + + if toPass, ok := p.skippedDirsCache[issueRelDir]; ok { + if !toPass { + p.skippedDirs[issueRelDir].count++ + } + return toPass + } + + issueAbsDir, err := filepath.Abs(issueRelDir) + if err != nil { + p.log.Warnf("Can't abs-ify path %q: %s", issueRelDir, err) + return true + } + + toPass := p.shouldPassIssueDirs(issueRelDir, issueAbsDir) + p.skippedDirsCache[issueRelDir] = toPass + return toPass +} + +func (p *SkipDirs) shouldPassIssueDirs(issueRelDir, issueAbsDir string) bool { + for _, absArgDir := range p.absArgsDirs { + if absArgDir == issueAbsDir { + // we must not skip issues if they are from explicitly set dirs + // even if they match skip patterns + return true + } + } + + // We use issueRelDir for matching: it's the relative to the current + // work dir path of directory of source file with the issue. It can lead + // to unexpected behavior if we're analyzing files out of current work dir. + // The alternative solution is to find relative to args path, but it has + // disadvantages (https://github.com/golangci/golangci-lint/pull/313). + + for _, pattern := range p.patterns { + if pattern.MatchString(issueRelDir) { + ps := pattern.String() + if p.skippedDirs[issueRelDir] == nil { + p.skippedDirs[issueRelDir] = &skipStat{ + pattern: ps, + } + } + p.skippedDirs[issueRelDir].count++ + return false + } + } + + return true +} + +func (p *SkipDirs) Finish() { + for dir, stat := range p.skippedDirs { + p.log.Infof("Skipped %d issues from dir %s by pattern %s", stat.count, dir, stat.pattern) + } +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/skip_files.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/skip_files.go new file mode 100644 index 000000000..522b07e4f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/skip_files.go @@ -0,0 +1,52 @@ +package processors + +import ( + "fmt" + "regexp" + + "github.com/golangci/golangci-lint/pkg/result" +) + +type SkipFiles struct { + patterns []*regexp.Regexp +} + +var _ Processor = SkipFiles{} + +func NewSkipFiles(patterns []string) (*SkipFiles, error) { + var patternsRe []*regexp.Regexp + for _, p := range patterns { + p = normalizePathInRegex(p) + patternRe, err := regexp.Compile(p) + if err != nil { + return nil, fmt.Errorf("can't compile regexp %q: %s", p, err) + } + patternsRe = append(patternsRe, patternRe) + } + + return &SkipFiles{ + patterns: patternsRe, + }, nil +} + +func (p SkipFiles) Name() string { + return "skip_files" +} + +func (p SkipFiles) Process(issues []result.Issue) ([]result.Issue, error) { + if len(p.patterns) == 0 { + return issues, nil + } + + return filterIssues(issues, func(i *result.Issue) bool { + for _, p := range p.patterns { + if p.MatchString(i.FilePath()) { + return false + } + } + + return true + }), nil +} + +func (p SkipFiles) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/source_code.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/source_code.go new file mode 100644 index 000000000..cfd73cb98 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/source_code.go @@ -0,0 +1,47 @@ +package processors + +import ( + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +type SourceCode struct { + lineCache *fsutils.LineCache + log logutils.Log +} + +var _ Processor = SourceCode{} + +func NewSourceCode(lc *fsutils.LineCache, log logutils.Log) *SourceCode { + return &SourceCode{ + lineCache: lc, + log: log, + } +} + +func (p SourceCode) Name() string { + return "source_code" +} + +func (p SourceCode) Process(issues []result.Issue) ([]result.Issue, error) { + return transformIssues(issues, func(i *result.Issue) *result.Issue { + newI := *i + + lineRange := i.GetLineRange() + for lineNumber := lineRange.From; lineNumber <= lineRange.To; lineNumber++ { + line, err := p.lineCache.GetLine(i.FilePath(), lineNumber) + if err != nil { + p.log.Warnf("Failed to get line %d for file %s: %s", + lineNumber, i.FilePath(), err) + return i + } + + newI.SourceLines = append(newI.SourceLines, line) + } + + return &newI + }), nil +} + +func (p SourceCode) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/uniq_by_line.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/uniq_by_line.go new file mode 100644 index 000000000..17167dde5 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/uniq_by_line.go @@ -0,0 +1,58 @@ +package processors + +import ( + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/result" +) + +type lineToCount map[int]int +type fileToLineToCount map[string]lineToCount + +type UniqByLine struct { + flc fileToLineToCount + cfg *config.Config +} + +func NewUniqByLine(cfg *config.Config) *UniqByLine { + return &UniqByLine{ + flc: fileToLineToCount{}, + cfg: cfg, + } +} + +var _ Processor = &UniqByLine{} + +func (p UniqByLine) Name() string { + return "uniq_by_line" +} + +func (p *UniqByLine) Process(issues []result.Issue) ([]result.Issue, error) { + if !p.cfg.Output.UniqByLine { + return issues, nil + } + + return filterIssues(issues, func(i *result.Issue) bool { + if i.Replacement != nil && p.cfg.Issues.NeedFix { + // if issue will be auto-fixed we shouldn't collapse issues: + // e.g. one line can contain 2 misspellings, they will be in 2 issues and misspell should fix both of them. + return true + } + + lc := p.flc[i.FilePath()] + if lc == nil { + lc = lineToCount{} + p.flc[i.FilePath()] = lc + } + + const limit = 1 + count := lc[i.Line()] + if count == limit { + return false + } + + lc[i.Line()]++ + return true + }), nil +} + +func (p UniqByLine) Finish() {} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/utils.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/utils.go new file mode 100644 index 000000000..7108fd3b3 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/utils.go @@ -0,0 +1,62 @@ +package processors + +import ( + "path/filepath" + "regexp" + "strings" + + "github.com/pkg/errors" + + "github.com/golangci/golangci-lint/pkg/result" +) + +func filterIssues(issues []result.Issue, filter func(i *result.Issue) bool) []result.Issue { + retIssues := make([]result.Issue, 0, len(issues)) + for i := range issues { + if filter(&issues[i]) { + retIssues = append(retIssues, issues[i]) + } + } + + return retIssues +} + +func filterIssuesErr(issues []result.Issue, filter func(i *result.Issue) (bool, error)) ([]result.Issue, error) { + retIssues := make([]result.Issue, 0, len(issues)) + for i := range issues { + ok, err := filter(&issues[i]) + if err != nil { + return nil, errors.Wrapf(err, "can't filter issue %#v", issues[i]) + } + + if ok { + retIssues = append(retIssues, issues[i]) + } + } + + return retIssues, nil +} + +func transformIssues(issues []result.Issue, transform func(i *result.Issue) *result.Issue) []result.Issue { + retIssues := make([]result.Issue, 0, len(issues)) + for i := range issues { + newI := transform(&issues[i]) + if newI != nil { + retIssues = append(retIssues, *newI) + } + } + + return retIssues +} + +var separatorToReplace = regexp.QuoteMeta(string(filepath.Separator)) + +func normalizePathInRegex(path string) string { + if filepath.Separator == '/' { + return path + } + + // This replacing should be safe because "/" are disallowed in Windows + // https://docs.microsoft.com/ru-ru/windows/win32/fileio/naming-a-file + return strings.ReplaceAll(path, "/", separatorToReplace) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go b/vendor/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go new file mode 100644 index 000000000..9628bd80f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go @@ -0,0 +1,116 @@ +package timeutils + +import ( + "fmt" + "sort" + "strings" + "sync" + "time" + + "github.com/golangci/golangci-lint/pkg/logutils" +) + +const noStagesText = "no stages" + +type Stopwatch struct { + name string + startedAt time.Time + stages map[string]time.Duration + log logutils.Log + + sync.Mutex +} + +func NewStopwatch(name string, log logutils.Log) *Stopwatch { + return &Stopwatch{ + name: name, + startedAt: time.Now(), + stages: map[string]time.Duration{}, + log: log, + } +} + +type stageDuration struct { + name string + d time.Duration +} + +func (s *Stopwatch) stageDurationsSorted() []stageDuration { + stageDurations := []stageDuration{} + for n, d := range s.stages { + stageDurations = append(stageDurations, stageDuration{ + name: n, + d: d, + }) + } + sort.Slice(stageDurations, func(i, j int) bool { + return stageDurations[i].d > stageDurations[j].d + }) + return stageDurations +} + +func (s *Stopwatch) sprintStages() string { + if len(s.stages) == 0 { + return noStagesText + } + + stageDurations := s.stageDurationsSorted() + + stagesStrings := []string{} + for _, s := range stageDurations { + stagesStrings = append(stagesStrings, fmt.Sprintf("%s: %s", s.name, s.d)) + } + + return fmt.Sprintf("stages: %s", strings.Join(stagesStrings, ", ")) +} + +func (s *Stopwatch) sprintTopStages(n int) string { + if len(s.stages) == 0 { + return noStagesText + } + + stageDurations := s.stageDurationsSorted() + + stagesStrings := []string{} + for i := 0; i < len(stageDurations) && i < n; i++ { + s := stageDurations[i] + stagesStrings = append(stagesStrings, fmt.Sprintf("%s: %s", s.name, s.d)) + } + + return fmt.Sprintf("top %d stages: %s", n, strings.Join(stagesStrings, ", ")) +} + +func (s *Stopwatch) Print() { + p := fmt.Sprintf("%s took %s", s.name, time.Since(s.startedAt)) + if len(s.stages) == 0 { + s.log.Infof("%s", p) + return + } + + s.log.Infof("%s with %s", p, s.sprintStages()) +} + +func (s *Stopwatch) PrintStages() { + var stagesDuration time.Duration + for _, s := range s.stages { + stagesDuration += s + } + s.log.Infof("%s took %s with %s", s.name, stagesDuration, s.sprintStages()) +} + +func (s *Stopwatch) PrintTopStages(n int) { + var stagesDuration time.Duration + for _, s := range s.stages { + stagesDuration += s + } + s.log.Infof("%s took %s with %s", s.name, stagesDuration, s.sprintTopStages(n)) +} + +func (s *Stopwatch) TrackStage(name string, f func()) { + startedAt := time.Now() + f() + + s.Lock() + s.stages[name] += time.Since(startedAt) + s.Unlock() +} diff --git a/vendor/github.com/golangci/ineffassign/.gitignore b/vendor/github.com/golangci/ineffassign/.gitignore new file mode 100644 index 000000000..c4feb4ff0 --- /dev/null +++ b/vendor/github.com/golangci/ineffassign/.gitignore @@ -0,0 +1,30 @@ +ineffassign + +# Created by https://www.gitignore.io/api/go + +### Go ### +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + diff --git a/vendor/github.com/golangci/ineffassign/LICENSE b/vendor/github.com/golangci/ineffassign/LICENSE new file mode 100644 index 000000000..9e3d9bcc0 --- /dev/null +++ b/vendor/github.com/golangci/ineffassign/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Gordon Klaus and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/golangci/ineffassign/README.md b/vendor/github.com/golangci/ineffassign/README.md new file mode 100644 index 000000000..6dcb9f0cc --- /dev/null +++ b/vendor/github.com/golangci/ineffassign/README.md @@ -0,0 +1,4 @@ +# ineffassign +Detect ineffectual assignments in Go code. + +This tool misses some cases because does not consider any type information in its analysis. (For example, assignments to struct fields are never marked as ineffectual.) It should, however, never give any false positives. diff --git a/vendor/github.com/golangci/ineffassign/bugs b/vendor/github.com/golangci/ineffassign/bugs new file mode 100644 index 000000000..468177e0a --- /dev/null +++ b/vendor/github.com/golangci/ineffassign/bugs @@ -0,0 +1,7 @@ +cmd/compile/internal/big/floatconv.go:367:2 m +cmd/cover/cover_test.go:62:2 err +cmd/pprof/internal/profile/profile.go:131:10 err +math/big/ftoa.go:285:2 m +net/file_unix.go:66:7 err +golang.org/x/mobile/app/android.go:175:2 queue +golang.org/x/net/icmp/listen_posix.go:83:6 err diff --git a/vendor/github.com/golangci/ineffassign/ineffassign.go b/vendor/github.com/golangci/ineffassign/ineffassign.go new file mode 100644 index 000000000..5cda3982d --- /dev/null +++ b/vendor/github.com/golangci/ineffassign/ineffassign.go @@ -0,0 +1,620 @@ +package ineffassign + +import ( + "flag" + "fmt" + "go/ast" + "go/parser" + "go/token" + "os" + "path/filepath" + "sort" + "strings" +) + +const invalidArgumentExitCode = 3 + +var dontRecurseFlag = flag.Bool("ineffassign.n", false, "don't recursively check paths") + +type Issue struct { + Pos token.Position + IdentName string +} + +func Run(files []string) []Issue { + var issues []Issue + for _, path := range files { + fset, _, ineff := checkPath(path) + for _, id := range ineff { + issues = append(issues, Issue{ + Pos: fset.Position(id.Pos()), + IdentName: id.Name, + }) + } + } + + return issues +} + +func walkPath(root string) bool { + lintFailed := false + filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { + if err != nil { + fmt.Printf("Error during filesystem walk: %v\n", err) + return nil + } + if fi.IsDir() { + if path != root && (*dontRecurseFlag || + filepath.Base(path) == "testdata" || + filepath.Base(path) == "vendor") { + return filepath.SkipDir + } + return nil + } + if !strings.HasSuffix(path, ".go") { + return nil + } + fset, _, ineff := checkPath(path) + for _, id := range ineff { + fmt.Printf("%s: ineffectual assignment to %s\n", fset.Position(id.Pos()), id.Name) + lintFailed = true + } + return nil + }) + return lintFailed +} + +func checkPath(path string) (*token.FileSet, []*ast.CommentGroup, []*ast.Ident) { + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, path, nil, parser.ParseComments) + if err != nil { + return nil, nil, nil + } + + bld := &builder{vars: map[*ast.Object]*variable{}} + bld.walk(f) + + chk := &checker{vars: bld.vars, seen: map[*block]bool{}} + for _, b := range bld.roots { + chk.check(b) + } + sort.Sort(chk.ineff) + + return fset, f.Comments, chk.ineff +} + +type builder struct { + roots []*block + block *block + vars map[*ast.Object]*variable + results []*ast.FieldList + breaks branchStack + continues branchStack + gotos branchStack + labelStmt *ast.LabeledStmt +} + +type block struct { + children []*block + ops map[*ast.Object][]operation +} + +func (b *block) addChild(c *block) { + b.children = append(b.children, c) +} + +type operation struct { + id *ast.Ident + assign bool +} + +type variable struct { + fundept int + escapes bool +} + +func (bld *builder) walk(n ast.Node) { + if n != nil { + ast.Walk(bld, n) + } +} + +func (bld *builder) Visit(n ast.Node) ast.Visitor { + switch n := n.(type) { + case *ast.FuncDecl: + if n.Body != nil { + bld.fun(n.Type, n.Body) + } + case *ast.FuncLit: + bld.fun(n.Type, n.Body) + case *ast.IfStmt: + bld.walk(n.Init) + bld.walk(n.Cond) + b0 := bld.block + bld.newBlock(b0) + bld.walk(n.Body) + b1 := bld.block + if n.Else != nil { + bld.newBlock(b0) + bld.walk(n.Else) + b0 = bld.block + } + bld.newBlock(b0, b1) + case *ast.ForStmt: + lbl := bld.stmtLabel(n) + brek := bld.breaks.push(lbl) + continu := bld.continues.push(lbl) + bld.walk(n.Init) + start := bld.newBlock(bld.block) + bld.walk(n.Cond) + cond := bld.block + bld.newBlock(cond) + bld.walk(n.Body) + continu.setDestination(bld.newBlock(bld.block)) + bld.walk(n.Post) + bld.block.addChild(start) + brek.setDestination(bld.newBlock(cond)) + bld.breaks.pop() + bld.continues.pop() + case *ast.RangeStmt: + lbl := bld.stmtLabel(n) + brek := bld.breaks.push(lbl) + continu := bld.continues.push(lbl) + bld.walk(n.X) + pre := bld.newBlock(bld.block) + start := bld.newBlock(pre) + if n.Key != nil { + lhs := []ast.Expr{n.Key} + if n.Value != nil { + lhs = append(lhs, n.Value) + } + bld.walk(&ast.AssignStmt{Lhs: lhs, Tok: n.Tok, TokPos: n.TokPos, Rhs: []ast.Expr{&ast.Ident{NamePos: n.X.End()}}}) + } + bld.walk(n.Body) + bld.block.addChild(start) + continu.setDestination(pre) + brek.setDestination(bld.newBlock(pre, bld.block)) + bld.breaks.pop() + bld.continues.pop() + case *ast.SwitchStmt: + bld.walk(n.Init) + bld.walk(n.Tag) + bld.swtch(n, n.Body.List) + case *ast.TypeSwitchStmt: + bld.walk(n.Init) + bld.walk(n.Assign) + bld.swtch(n, n.Body.List) + case *ast.SelectStmt: + brek := bld.breaks.push(bld.stmtLabel(n)) + for _, c := range n.Body.List { + c := c.(*ast.CommClause).Comm + if s, ok := c.(*ast.AssignStmt); ok { + bld.walk(s.Rhs[0]) + } else { + bld.walk(c) + } + } + b0 := bld.block + exits := make([]*block, len(n.Body.List)) + dfault := false + for i, c := range n.Body.List { + c := c.(*ast.CommClause) + bld.newBlock(b0) + bld.walk(c) + exits[i] = bld.block + dfault = dfault || c.Comm == nil + } + if !dfault { + exits = append(exits, b0) + } + brek.setDestination(bld.newBlock(exits...)) + bld.breaks.pop() + case *ast.LabeledStmt: + bld.gotos.get(n.Label).setDestination(bld.newBlock(bld.block)) + bld.labelStmt = n + bld.walk(n.Stmt) + case *ast.BranchStmt: + switch n.Tok { + case token.BREAK: + bld.breaks.get(n.Label).addSource(bld.block) + bld.newBlock() + case token.CONTINUE: + bld.continues.get(n.Label).addSource(bld.block) + bld.newBlock() + case token.GOTO: + bld.gotos.get(n.Label).addSource(bld.block) + bld.newBlock() + } + + case *ast.AssignStmt: + if n.Tok == token.QUO_ASSIGN || n.Tok == token.REM_ASSIGN { + bld.maybePanic() + } + + for _, x := range n.Rhs { + bld.walk(x) + } + for i, x := range n.Lhs { + if id, ok := ident(x); ok { + if n.Tok >= token.ADD_ASSIGN && n.Tok <= token.AND_NOT_ASSIGN { + bld.use(id) + } + // Don't treat explicit initialization to zero as assignment; it is often used as shorthand for a bare declaration. + if n.Tok == token.DEFINE && i < len(n.Rhs) && isZeroInitializer(n.Rhs[i]) { + bld.use(id) + } else { + bld.assign(id) + } + } else { + bld.walk(x) + } + } + case *ast.GenDecl: + if n.Tok == token.VAR { + for _, s := range n.Specs { + s := s.(*ast.ValueSpec) + for _, x := range s.Values { + bld.walk(x) + } + for _, id := range s.Names { + if len(s.Values) > 0 { + bld.assign(id) + } else { + bld.use(id) + } + } + } + } + case *ast.IncDecStmt: + if id, ok := ident(n.X); ok { + bld.use(id) + bld.assign(id) + } else { + bld.walk(n.X) + } + case *ast.Ident: + bld.use(n) + case *ast.ReturnStmt: + for _, x := range n.Results { + bld.walk(x) + } + if res := bld.results[len(bld.results)-1]; res != nil { + for _, f := range res.List { + for _, id := range f.Names { + if n.Results != nil { + bld.assign(id) + } + bld.use(id) + } + } + } + bld.newBlock() + case *ast.SendStmt: + bld.maybePanic() + return bld + + case *ast.BinaryExpr: + if n.Op == token.EQL || n.Op == token.QUO || n.Op == token.REM { + bld.maybePanic() + } + return bld + case *ast.CallExpr: + bld.maybePanic() + return bld + case *ast.IndexExpr: + bld.maybePanic() + return bld + case *ast.UnaryExpr: + id, ok := ident(n.X) + if ix, isIx := n.X.(*ast.IndexExpr); isIx { + // We don't care about indexing into slices, but without type information we can do no better. + id, ok = ident(ix.X) + } + if ok && n.Op == token.AND { + if v, ok := bld.vars[id.Obj]; ok { + v.escapes = true + } + } + return bld + case *ast.SelectorExpr: + bld.maybePanic() + // A method call (possibly delayed via a method value) might implicitly take + // the address of its receiver, causing it to escape. + // We can't do any better here without knowing the variable's type. + if id, ok := ident(n.X); ok { + if v, ok := bld.vars[id.Obj]; ok { + v.escapes = true + } + } + return bld + case *ast.SliceExpr: + bld.maybePanic() + // We don't care about slicing into slices, but without type information we can do no better. + if id, ok := ident(n.X); ok { + if v, ok := bld.vars[id.Obj]; ok { + v.escapes = true + } + } + return bld + case *ast.StarExpr: + bld.maybePanic() + return bld + case *ast.TypeAssertExpr: + bld.maybePanic() + return bld + + default: + return bld + } + return nil +} + +func isZeroInitializer(x ast.Expr) bool { + // Assume that a call expression of a single argument is a conversion expression. We can't do better without type information. + if c, ok := x.(*ast.CallExpr); ok { + switch c.Fun.(type) { + case *ast.Ident, *ast.SelectorExpr: + default: + return false + } + if len(c.Args) != 1 { + return false + } + x = c.Args[0] + } + + switch x := x.(type) { + case *ast.BasicLit: + switch x.Value { + case "0", "0.0", "0.", ".0", `""`: + return true + } + case *ast.Ident: + return x.Name == "false" && x.Obj == nil + } + + return false +} + +func (bld *builder) fun(typ *ast.FuncType, body *ast.BlockStmt) { + for _, v := range bld.vars { + v.fundept++ + } + bld.results = append(bld.results, typ.Results) + + b := bld.block + bld.newBlock() + bld.roots = append(bld.roots, bld.block) + bld.walk(typ) + bld.walk(body) + bld.block = b + + bld.results = bld.results[:len(bld.results)-1] + for _, v := range bld.vars { + v.fundept-- + } +} + +func (bld *builder) swtch(stmt ast.Stmt, cases []ast.Stmt) { + brek := bld.breaks.push(bld.stmtLabel(stmt)) + b0 := bld.block + list := b0 + exits := make([]*block, 0, len(cases)+1) + var dfault, fallthru *block + for _, c := range cases { + c := c.(*ast.CaseClause) + + if c.List != nil { + list = bld.newBlock(list) + for _, x := range c.List { + bld.walk(x) + } + } + + parents := []*block{} + if c.List != nil { + parents = append(parents, list) + } + if fallthru != nil { + parents = append(parents, fallthru) + fallthru = nil + } + bld.newBlock(parents...) + if c.List == nil { + dfault = bld.block + } + for _, s := range c.Body { + bld.walk(s) + if s, ok := s.(*ast.BranchStmt); ok && s.Tok == token.FALLTHROUGH { + fallthru = bld.block + } + } + + if fallthru == nil { + exits = append(exits, bld.block) + } + } + if dfault != nil { + list.addChild(dfault) + } else { + exits = append(exits, b0) + } + brek.setDestination(bld.newBlock(exits...)) + bld.breaks.pop() +} + +// An operation that might panic marks named function results as used. +func (bld *builder) maybePanic() { + if len(bld.results) == 0 { + return + } + res := bld.results[len(bld.results)-1] + if res == nil { + return + } + for _, f := range res.List { + for _, id := range f.Names { + bld.use(id) + } + } +} + +func (bld *builder) newBlock(parents ...*block) *block { + bld.block = &block{ops: map[*ast.Object][]operation{}} + for _, b := range parents { + b.addChild(bld.block) + } + return bld.block +} + +func (bld *builder) stmtLabel(s ast.Stmt) *ast.Object { + if ls := bld.labelStmt; ls != nil && ls.Stmt == s { + return ls.Label.Obj + } + return nil +} + +func (bld *builder) assign(id *ast.Ident) { + bld.newOp(id, true) +} + +func (bld *builder) use(id *ast.Ident) { + bld.newOp(id, false) +} + +func (bld *builder) newOp(id *ast.Ident, assign bool) { + if id.Name == "_" || id.Obj == nil { + return + } + + v, ok := bld.vars[id.Obj] + if !ok { + v = &variable{} + bld.vars[id.Obj] = v + } + v.escapes = v.escapes || v.fundept > 0 || bld.block == nil + + if b := bld.block; b != nil { + b.ops[id.Obj] = append(b.ops[id.Obj], operation{id, assign}) + } +} + +type branchStack []*branch + +type branch struct { + label *ast.Object + srcs []*block + dst *block +} + +func (s *branchStack) push(lbl *ast.Object) *branch { + br := &branch{label: lbl} + *s = append(*s, br) + return br +} + +func (s *branchStack) get(lbl *ast.Ident) *branch { + for i := len(*s) - 1; i >= 0; i-- { + if br := (*s)[i]; lbl == nil || br.label == lbl.Obj { + return br + } + } + + // Guard against invalid code (break/continue outside of loop). + if lbl == nil { + return &branch{} + } + + return s.push(lbl.Obj) +} + +func (br *branch) addSource(src *block) { + br.srcs = append(br.srcs, src) + if br.dst != nil { + src.addChild(br.dst) + } +} + +func (br *branch) setDestination(dst *block) { + br.dst = dst + for _, src := range br.srcs { + src.addChild(dst) + } +} + +func (s *branchStack) pop() { + *s = (*s)[:len(*s)-1] +} + +func ident(x ast.Expr) (*ast.Ident, bool) { + if p, ok := x.(*ast.ParenExpr); ok { + return ident(p.X) + } + id, ok := x.(*ast.Ident) + return id, ok +} + +type checker struct { + vars map[*ast.Object]*variable + seen map[*block]bool + ineff idents +} + +func (chk *checker) check(b *block) { + if chk.seen[b] { + return + } + chk.seen[b] = true + + for obj, ops := range b.ops { + if chk.vars[obj].escapes { + continue + } + ops: + for i, op := range ops { + if !op.assign { + continue + } + if i+1 < len(ops) { + if ops[i+1].assign { + chk.ineff = append(chk.ineff, op.id) + } + continue + } + seen := map[*block]bool{} + for _, b := range b.children { + if used(obj, b, seen) { + continue ops + } + } + chk.ineff = append(chk.ineff, op.id) + } + } + + for _, b := range b.children { + chk.check(b) + } +} + +func used(obj *ast.Object, b *block, seen map[*block]bool) bool { + if seen[b] { + return false + } + seen[b] = true + + if ops := b.ops[obj]; len(ops) > 0 { + return !ops[0].assign + } + for _, b := range b.children { + if used(obj, b, seen) { + return true + } + } + return false +} + +type idents []*ast.Ident + +func (ids idents) Len() int { return len(ids) } +func (ids idents) Less(i, j int) bool { return ids[i].Pos() < ids[j].Pos() } +func (ids idents) Swap(i, j int) { ids[i], ids[j] = ids[j], ids[i] } diff --git a/vendor/github.com/golangci/ineffassign/list b/vendor/github.com/golangci/ineffassign/list new file mode 100644 index 000000000..7e6b1e75a --- /dev/null +++ b/vendor/github.com/golangci/ineffassign/list @@ -0,0 +1,25 @@ +/Users/gordon/go/src/code.google.com/p/freetype-go/freetype/truetype/truetype.go:493:5: offset assigned and not used +/Users/gordon/go/src/code.google.com/p/freetype-go/freetype/truetype/truetype.go:289:11: offset assigned and not used +/Users/gordon/go/src/code.google.com/p/freetype-go/freetype/truetype/truetype_test.go:224:2: prefix assigned and not used +/Users/gordon/go/src/code.google.com/p/freetype-go/freetype/truetype/truetype_test.go:239:3: s assigned and not used +/Users/gordon/go/src/github.com/gordonklaus/flux/go/types/resolver.go:372:2: seenPkgs assigned and not used +/Users/gordon/go/src/github.com/gopherjs/gopherjs/compiler/package.go:195:7: recvType assigned and not used +/Users/gordon/go/src/golang.org/x/crypto/ocsp/ocsp.go:340:2: rest assigned and not used +/Users/gordon/go/src/golang.org/x/crypto/openpgp/packet/opaque_test.go:35:6: err assigned and not used +/Users/gordon/go/src/golang.org/x/crypto/otr/otr.go:641:6: in assigned and not used +/Users/gordon/go/src/golang.org/x/crypto/otr/otr_test.go:198:17: err assigned and not used +/Users/gordon/go/src/golang.org/x/crypto/ssh/benchmark_test.go:94:17: err assigned and not used +/Users/gordon/go/src/golang.org/x/mobile/app/android.go:175:2: queue assigned and not used +/Users/gordon/go/src/golang.org/x/mobile/cmd/gomobile/bind.go:411:2: w assigned and not used +/Users/gordon/go/src/golang.org/x/mobile/cmd/gomobile/build.go:231:8: err assigned and not used +/Users/gordon/go/src/golang.org/x/net/icmp/listen_posix.go:83:6: err assigned and not used +/Users/gordon/go/src/golang.org/x/net/ipv4/control_unix.go:99:5: b assigned and not used +/Users/gordon/go/src/golang.org/x/net/ipv4/control_unix.go:148:4: b assigned and not used +/Users/gordon/go/src/golang.org/x/net/ipv6/control_unix.go:90:4: b assigned and not used +/Users/gordon/go/src/golang.org/x/net/ipv6/control_unix.go:162:4: b assigned and not used +/Users/gordon/go/src/golang.org/x/net/websocket/hybi.go:298:3: n assigned and not used +/Users/gordon/go/src/golang.org/x/tools/cmd/callgraph/main.go:164:2: args assigned and not used +/Users/gordon/go/src/golang.org/x/tools/cmd/cover/cover_test.go:52:2: err assigned and not used +/Users/gordon/go/src/golang.org/x/tools/go/gcimporter/exportdata.go:74:13: size assigned and not used +/Users/gordon/go/src/golang.org/x/tools/oracle/oracle.go:268:2: iprog assigned and not used +/Users/gordon/go/src/golang.org/x/tools/oracle/oracle_test.go:299:2: iprog assigned and not used diff --git a/vendor/github.com/golangci/ineffassign/liststd b/vendor/github.com/golangci/ineffassign/liststd new file mode 100644 index 000000000..591d026e4 --- /dev/null +++ b/vendor/github.com/golangci/ineffassign/liststd @@ -0,0 +1,131 @@ +/usr/local/go/src/bufio/scan.go:388:6: ineffectual assignment to width +/usr/local/go/src/bufio/scan.go:396:6: ineffectual assignment to width +/usr/local/go/src/bytes/buffer_test.go:141:6: ineffectual assignment to err +/usr/local/go/src/bytes/buffer_test.go:164:3: ineffectual assignment to c +/usr/local/go/src/cmd/cgo/out.go:799:3: ineffectual assignment to gccResult +/usr/local/go/src/cmd/compile/internal/big/ratconv.go:170:4: ineffectual assignment to err +/usr/local/go/src/cmd/compile/internal/gc/bimport.go:330:2: ineffectual assignment to file +/usr/local/go/src/cmd/compile/internal/gc/cgen.go:3332:3: ineffectual assignment to max +/usr/local/go/src/cmd/compile/internal/gc/export.go:379:2: ineffectual assignment to size +/usr/local/go/src/cmd/compile/internal/gc/global_test.go:51:2: ineffectual assignment to out +/usr/local/go/src/cmd/compile/internal/gc/lex.go:281:4: ineffectual assignment to c1 +/usr/local/go/src/cmd/compile/internal/gc/reg.go:1373:2: ineffectual assignment to firstf +/usr/local/go/src/cmd/compile/internal/gc/reg.go:1381:3: ineffectual assignment to firstf +/usr/local/go/src/cmd/compile/internal/s390x/peep.go:1048:3: ineffectual assignment to size +/usr/local/go/src/cmd/compile/internal/s390x/peep.go:1139:3: ineffectual assignment to size +/usr/local/go/src/cmd/compile/internal/ssa/loopbce.go:44:3: ineffectual assignment to entry +/usr/local/go/src/cmd/cover/html.go:64:8: ineffectual assignment to err +/usr/local/go/src/cmd/cover/html.go:66:8: ineffectual assignment to err +/usr/local/go/src/cmd/go/build.go:3355:3: ineffectual assignment to cgoLDFLAGS +/usr/local/go/src/cmd/internal/goobj/read.go:532:3: ineffectual assignment to data +/usr/local/go/src/cmd/internal/obj/arm64/obj7.go:600:2: ineffectual assignment to aoffset +/usr/local/go/src/cmd/internal/obj/mips/asm0.go:1049:3: ineffectual assignment to v +/usr/local/go/src/cmd/internal/obj/mips/asm0.go:1101:3: ineffectual assignment to v +/usr/local/go/src/cmd/internal/obj/s390x/objz.go:609:3: ineffectual assignment to pLast +/usr/local/go/src/cmd/internal/pprof/profile/encode.go:279:12: ineffectual assignment to err +/usr/local/go/src/cmd/link/internal/ld/dwarf.go:1426:2: ineffectual assignment to unitstart +/usr/local/go/src/cmd/link/internal/ld/dwarf.go:1427:2: ineffectual assignment to headerstart +/usr/local/go/src/cmd/link/internal/ld/dwarf.go:1428:2: ineffectual assignment to headerend +/usr/local/go/src/cmd/link/internal/ld/elf.go:2272:3: ineffectual assignment to resoff +/usr/local/go/src/cmd/vet/print.go:227:9: ineffectual assignment to w +/usr/local/go/src/cmd/yacc/yacc.go:770:2: ineffectual assignment to val +/usr/local/go/src/cmd/yacc/yacc.go:3127:2: ineffectual assignment to i +/usr/local/go/src/compress/bzip2/huffman.go:114:4: ineffectual assignment to length +/usr/local/go/src/compress/flate/reader_test.go:53:3: ineffectual assignment to buf0 +/usr/local/go/src/compress/flate/writer_test.go:29:3: ineffectual assignment to buf0 +/usr/local/go/src/compress/gzip/gzip_test.go:211:5: ineffectual assignment to err +/usr/local/go/src/compress/lzw/reader_test.go:148:4: ineffectual assignment to buf0 +/usr/local/go/src/compress/lzw/writer_test.go:146:3: ineffectual assignment to buf0 +/usr/local/go/src/container/list/list_test.go:286:2: ineffectual assignment to e1 +/usr/local/go/src/container/list/list_test.go:286:6: ineffectual assignment to e2 +/usr/local/go/src/container/list/list_test.go:286:10: ineffectual assignment to e3 +/usr/local/go/src/container/list/list_test.go:286:14: ineffectual assignment to e4 +/usr/local/go/src/crypto/elliptic/p224.go:722:10: ineffectual assignment to bytes +/usr/local/go/src/crypto/tls/handshake_messages.go:289:3: ineffectual assignment to z +/usr/local/go/src/crypto/x509/verify.go:110:5: ineffectual assignment to certName +/usr/local/go/src/database/sql/sql_test.go:1705:4: ineffectual assignment to numOpen +/usr/local/go/src/database/sql/sql_test.go:1839:5: ineffectual assignment to err +/usr/local/go/src/debug/dwarf/type.go:540:5: ineffectual assignment to haveBitOffset +/usr/local/go/src/debug/elf/file.go:1014:3: ineffectual assignment to suffix +/usr/local/go/src/debug/gosym/pclntab_test.go:256:2: ineffectual assignment to off +/usr/local/go/src/debug/pe/file_test.go:309:2: ineffectual assignment to err +/usr/local/go/src/encoding/base32/base32_test.go:120:4: ineffectual assignment to count +/usr/local/go/src/encoding/base64/base64_test.go:174:4: ineffectual assignment to count +/usr/local/go/src/encoding/gob/decgen.go:187:6: ineffectual assignment to err +/usr/local/go/src/encoding/gob/encgen.go:166:6: ineffectual assignment to err +/usr/local/go/src/encoding/json/encode.go:1071:2: ineffectual assignment to count +/usr/local/go/src/encoding/json/encode.go:1169:6: ineffectual assignment to advance +/usr/local/go/src/encoding/xml/xml.go:1030:6: ineffectual assignment to ok +/usr/local/go/src/fmt/print.go:936:2: ineffectual assignment to afterIndex +/usr/local/go/src/fmt/print.go:1051:15: ineffectual assignment to afterIndex +/usr/local/go/src/go/ast/filter.go:84:3: ineffectual assignment to keepField +/usr/local/go/src/go/internal/gcimporter/bimport.go:215:2: ineffectual assignment to file +/usr/local/go/src/go/printer/nodes.go:439:4: ineffectual assignment to extraTabs +/usr/local/go/src/go/printer/printer_test.go:155:8: ineffectual assignment to err +/usr/local/go/src/go/types/conversions.go:49:2: ineffectual assignment to final +/usr/local/go/src/html/template/css.go:160:2: ineffectual assignment to r +/usr/local/go/src/html/template/css.go:160:5: ineffectual assignment to w +/usr/local/go/src/html/template/html.go:141:2: ineffectual assignment to r +/usr/local/go/src/html/template/html.go:141:5: ineffectual assignment to w +/usr/local/go/src/html/template/js.go:249:2: ineffectual assignment to r +/usr/local/go/src/html/template/js.go:249:5: ineffectual assignment to w +/usr/local/go/src/image/decode_test.go:125:9: ineffectual assignment to err +/usr/local/go/src/image/png/reader.go:689:2: ineffectual assignment to n +/usr/local/go/src/image/png/writer.go:269:3: ineffectual assignment to best +/usr/local/go/src/io/io_test.go:245:2: ineffectual assignment to n +/usr/local/go/src/io/ioutil/ioutil.go:149:2: ineffectual assignment to readSize +/usr/local/go/src/io/ioutil/ioutil_test.go:24:2: ineffectual assignment to contents +/usr/local/go/src/log/syslog/syslog_test.go:236:5: ineffectual assignment to err +/usr/local/go/src/log/syslog/syslog_test.go:240:5: ineffectual assignment to err +/usr/local/go/src/math/big/ratconv.go:176:4: ineffectual assignment to err +/usr/local/go/src/mime/multipart/multipart_test.go:408:2: ineffectual assignment to p +/usr/local/go/src/net/dial_test.go:381:6: ineffectual assignment to err +/usr/local/go/src/net/dnsname_test.go:36:6: ineffectual assignment to char63 +/usr/local/go/src/net/dnsname_test.go:37:6: ineffectual assignment to char64 +/usr/local/go/src/net/fd_plan9.go:64:4: ineffectual assignment to err +/usr/local/go/src/net/fd_windows.go:166:3: ineffectual assignment to err +/usr/local/go/src/net/http/fs.go:413:5: ineffectual assignment to name +/usr/local/go/src/net/http/h2_bundle.go:6249:4: ineffectual assignment to n +/usr/local/go/src/net/http/request_test.go:155:13: ineffectual assignment to err +/usr/local/go/src/net/http/serve_test.go:4053:13: ineffectual assignment to err +/usr/local/go/src/net/http/transport_test.go:729:8: ineffectual assignment to err +/usr/local/go/src/net/http/transport_test.go:2345:3: ineffectual assignment to slurp +/usr/local/go/src/net/parse.go:27:2: ineffectual assignment to i +/usr/local/go/src/net/rpc/server.go:270:3: ineffectual assignment to str +/usr/local/go/src/net/udpsock_plan9.go:80:16: ineffectual assignment to i +/usr/local/go/src/os/env_test.go:109:2: ineffectual assignment to value +/usr/local/go/src/os/os_test.go:1080:5: ineffectual assignment to err +/usr/local/go/src/os/path_test.go:122:2: ineffectual assignment to testit +/usr/local/go/src/reflect/type.go:2379:3: ineffectual assignment to name +/usr/local/go/src/regexp/exec.go:123:2: ineffectual assignment to r +/usr/local/go/src/regexp/exec.go:124:2: ineffectual assignment to width +/usr/local/go/src/regexp/exec.go:321:2: ineffectual assignment to r +/usr/local/go/src/regexp/exec.go:322:2: ineffectual assignment to width +/usr/local/go/src/regexp/onepass.go:338:15: ineffectual assignment to matchArg +/usr/local/go/src/regexp/syntax/parse.go:577:2: ineffectual assignment to start +/usr/local/go/src/runtime/lfstack_test.go:48:2: ineffectual assignment to nodes +/usr/local/go/src/runtime/mbitmap.go:1458:3: ineffectual assignment to i +/usr/local/go/src/runtime/mfinal_test.go:60:4: ineffectual assignment to v +/usr/local/go/src/runtime/mfinal_test.go:98:3: ineffectual assignment to v +/usr/local/go/src/runtime/mgcmark.go:414:2: ineffectual assignment to stolen +/usr/local/go/src/runtime/mgcsweep.go:188:2: ineffectual assignment to nfree +/usr/local/go/src/runtime/os_plan9.go:307:2: ineffectual assignment to n +/usr/local/go/src/runtime/pprof/pprof.go:465:5: ineffectual assignment to ok +/usr/local/go/src/runtime/pprof/pprof.go:608:5: ineffectual assignment to ok +/usr/local/go/src/runtime/pprof/pprof.go:751:5: ineffectual assignment to ok +/usr/local/go/src/runtime/proc.go:4227:3: ineffectual assignment to xname +/usr/local/go/src/runtime/runtime1.go:360:3: ineffectual assignment to field +/usr/local/go/src/runtime/runtime_mmap_test.go:25:2: ineffectual assignment to p +/usr/local/go/src/runtime/softfloat64.go:228:3: ineffectual assignment to f +/usr/local/go/src/runtime/softfloat64.go:228:6: ineffectual assignment to g +/usr/local/go/src/runtime/stack_test.go:106:4: ineffectual assignment to s +/usr/local/go/src/strconv/quote.go:23:6: ineffectual assignment to width +/usr/local/go/src/sync/atomic/atomic_test.go:1122:2: ineffectual assignment to new +/usr/local/go/src/sync/atomic/atomic_test.go:1150:2: ineffectual assignment to new +/usr/local/go/src/syscall/dir_plan9.go:88:2: ineffectual assignment to b +/usr/local/go/src/syscall/dir_plan9.go:131:13: ineffectual assignment to b +/usr/local/go/src/syscall/exec_plan9.go:281:2: ineffectual assignment to r1 +/usr/local/go/src/syscall/mksyscall_windows.go:310:2: ineffectual assignment to s +/usr/local/go/src/syscall/syscall_bsd_test.go:23:2: ineffectual assignment to n +/usr/local/go/src/syscall/syscall_unix_test.go:187:17: ineffectual assignment to err +/usr/local/go/src/text/template/multi_test.go:249:9: ineffectual assignment to err diff --git a/vendor/github.com/golangci/lint-1/.travis.yml b/vendor/github.com/golangci/lint-1/.travis.yml new file mode 100644 index 000000000..bc2f4b311 --- /dev/null +++ b/vendor/github.com/golangci/lint-1/.travis.yml @@ -0,0 +1,19 @@ +sudo: false +language: go +go: + - 1.10.x + - 1.11.x + - master + +go_import_path: github.com/golangci/lint-1 + +install: + - go get -t -v ./... + +script: + - go test -v -race ./... + +matrix: + allow_failures: + - go: master + fast_finish: true diff --git a/vendor/github.com/golangci/lint-1/CONTRIBUTING.md b/vendor/github.com/golangci/lint-1/CONTRIBUTING.md new file mode 100644 index 000000000..2e39a1c67 --- /dev/null +++ b/vendor/github.com/golangci/lint-1/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contributing to Golint + +## Before filing an issue: + +### Are you having trouble building golint? + +Check you have the latest version of its dependencies. Run +``` +go get -u github.com/golangci/lint-1/golint +``` +If you still have problems, consider searching for existing issues before filing a new issue. + +## Before sending a pull request: + +Have you understood the purpose of golint? Make sure to carefully read `README`. diff --git a/vendor/github.com/golangci/lint-1/LICENSE b/vendor/github.com/golangci/lint-1/LICENSE new file mode 100644 index 000000000..65d761bc9 --- /dev/null +++ b/vendor/github.com/golangci/lint-1/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/golangci/lint-1/README.md b/vendor/github.com/golangci/lint-1/README.md new file mode 100644 index 000000000..2de6ee835 --- /dev/null +++ b/vendor/github.com/golangci/lint-1/README.md @@ -0,0 +1,88 @@ +Golint is a linter for Go source code. + +[![Build Status](https://travis-ci.org/golang/lint.svg?branch=master)](https://travis-ci.org/golang/lint) + +## Installation + +Golint requires a +[supported release of Go](https://golang.org/doc/devel/release.html#policy). + + go get -u github.com/golangci/lint-1/golint + +To find out where `golint` was installed you can run `go list -f {{.Target}} github.com/golangci/lint-1/golint`. For `golint` to be used globally add that directory to the `$PATH` environment setting. + +## Usage + +Invoke `golint` with one or more filenames, directories, or packages named +by its import path. Golint uses the same +[import path syntax](https://golang.org/cmd/go/#hdr-Import_path_syntax) as +the `go` command and therefore +also supports relative import paths like `./...`. Additionally the `...` +wildcard can be used as suffix on relative and absolute file paths to recurse +into them. + +The output of this tool is a list of suggestions in Vim quickfix format, +which is accepted by lots of different editors. + +## Purpose + +Golint differs from gofmt. Gofmt reformats Go source code, whereas +golint prints out style mistakes. + +Golint differs from govet. Govet is concerned with correctness, whereas +golint is concerned with coding style. Golint is in use at Google, and it +seeks to match the accepted style of the open source Go project. + +The suggestions made by golint are exactly that: suggestions. +Golint is not perfect, and has both false positives and false negatives. +Do not treat its output as a gold standard. We will not be adding pragmas +or other knobs to suppress specific warnings, so do not expect or require +code to be completely "lint-free". +In short, this tool is not, and will never be, trustworthy enough for its +suggestions to be enforced automatically, for example as part of a build process. +Golint makes suggestions for many of the mechanically checkable items listed in +[Effective Go](https://golang.org/doc/effective_go.html) and the +[CodeReviewComments wiki page](https://golang.org/wiki/CodeReviewComments). + +## Scope + +Golint is meant to carry out the stylistic conventions put forth in +[Effective Go](https://golang.org/doc/effective_go.html) and +[CodeReviewComments](https://golang.org/wiki/CodeReviewComments). +Changes that are not aligned with those documents will not be considered. + +## Contributions + +Contributions to this project are welcome provided they are [in scope](#scope), +though please send mail before starting work on anything major. +Contributors retain their copyright, so we need you to fill out +[a short form](https://developers.google.com/open-source/cla/individual) +before we can accept your contribution. + +## Vim + +Add this to your ~/.vimrc: + + set rtp+=$GOPATH/src/github.com/golangci/lint-1/misc/vim + +If you have multiple entries in your GOPATH, replace `$GOPATH` with the right value. + +Running `:Lint` will run golint on the current file and populate the quickfix list. + +Optionally, add this to your `~/.vimrc` to automatically run `golint` on `:w` + + autocmd BufWritePost,FileWritePost *.go execute 'Lint' | cwindow + + +## Emacs + +Add this to your `.emacs` file: + + (add-to-list 'load-path (concat (getenv "GOPATH") "/src/github.com/golang/lint/misc/emacs")) + (require 'golint) + +If you have multiple entries in your GOPATH, replace `$GOPATH` with the right value. + +Running M-x golint will run golint on the current file. + +For more usage, see [Compilation-Mode](http://www.gnu.org/software/emacs/manual/html_node/emacs/Compilation-Mode.html). diff --git a/vendor/github.com/golangci/lint-1/go.mod b/vendor/github.com/golangci/lint-1/go.mod new file mode 100644 index 000000000..fafbd340b --- /dev/null +++ b/vendor/github.com/golangci/lint-1/go.mod @@ -0,0 +1,3 @@ +module github.com/golangci/lint-1 + +require golang.org/x/tools v0.0.0-20190311212946-11955173bddd diff --git a/vendor/github.com/golangci/lint-1/go.sum b/vendor/github.com/golangci/lint-1/go.sum new file mode 100644 index 000000000..7d0e2e618 --- /dev/null +++ b/vendor/github.com/golangci/lint-1/go.sum @@ -0,0 +1,6 @@ +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= diff --git a/vendor/github.com/golangci/lint-1/lint.go b/vendor/github.com/golangci/lint-1/lint.go new file mode 100644 index 000000000..886c85bf0 --- /dev/null +++ b/vendor/github.com/golangci/lint-1/lint.go @@ -0,0 +1,1655 @@ +// Copyright (c) 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 or at +// https://developers.google.com/open-source/licenses/bsd. + +// Package lint contains a linter for Go source code. +package lint // import "github.com/golangci/lint-1" + +import ( + "bufio" + "bytes" + "fmt" + "go/ast" + "go/parser" + "go/printer" + "go/token" + "go/types" + "io/ioutil" + "regexp" + "sort" + "strconv" + "strings" + "unicode" + "unicode/utf8" + + "golang.org/x/tools/go/ast/astutil" + "golang.org/x/tools/go/gcexportdata" +) + +const styleGuideBase = "https://golang.org/wiki/CodeReviewComments" + +// A Linter lints Go source code. +type Linter struct { +} + +// Problem represents a problem in some source code. +type Problem struct { + Position token.Position // position in source file + Text string // the prose that describes the problem + Link string // (optional) the link to the style guide for the problem + Confidence float64 // a value in (0,1] estimating the confidence in this problem's correctness + LineText string // the source line + Category string // a short name for the general category of the problem + + // If the problem has a suggested fix (the minority case), + // ReplacementLine is a full replacement for the relevant line of the source file. + ReplacementLine string +} + +func (p *Problem) String() string { + if p.Link != "" { + return p.Text + "\n\n" + p.Link + } + return p.Text +} + +type byPosition []Problem + +func (p byPosition) Len() int { return len(p) } +func (p byPosition) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p byPosition) Less(i, j int) bool { + pi, pj := p[i].Position, p[j].Position + + if pi.Filename != pj.Filename { + return pi.Filename < pj.Filename + } + if pi.Line != pj.Line { + return pi.Line < pj.Line + } + if pi.Column != pj.Column { + return pi.Column < pj.Column + } + + return p[i].Text < p[j].Text +} + +// Lint lints src. +func (l *Linter) Lint(filename string, src []byte) ([]Problem, error) { + return l.LintFiles(map[string][]byte{filename: src}) +} + +// LintFiles lints a set of files of a single package. +// The argument is a map of filename to source. +func (l *Linter) LintFiles(files map[string][]byte) ([]Problem, error) { + pkg := &pkg{ + fset: token.NewFileSet(), + files: make(map[string]*file), + } + var pkgName string + for filename, src := range files { + if isGenerated(src) { + continue // See issue #239 + } + f, err := parser.ParseFile(pkg.fset, filename, src, parser.ParseComments) + if err != nil { + return nil, err + } + if pkgName == "" { + pkgName = f.Name.Name + } else if f.Name.Name != pkgName { + return nil, fmt.Errorf("%s is in package %s, not %s", filename, f.Name.Name, pkgName) + } + pkg.files[filename] = &file{ + pkg: pkg, + f: f, + fset: pkg.fset, + src: src, + filename: filename, + } + } + if len(pkg.files) == 0 { + return nil, nil + } + return pkg.lint(), nil +} + +// LintFiles lints a set of files of a single package. +// The argument is a map of filename to source. +func (l *Linter) LintPkg(files []*ast.File, fset *token.FileSet, typesPkg *types.Package, typesInfo *types.Info) ([]Problem, error) { + pkg := &pkg{ + fset: fset, + files: make(map[string]*file), + typesPkg: typesPkg, + typesInfo: typesInfo, + } + var pkgName string + for _, f := range files { + // use PositionFor, not Position because of //line directives: + // this filename will be used for source lines extraction. + filename := fset.PositionFor(f.Pos(), false).Filename + if filename == "" { + return nil, fmt.Errorf("no file name for file %+v", f) + } + + if pkgName == "" { + pkgName = f.Name.Name + } else if f.Name.Name != pkgName { + return nil, fmt.Errorf("%s is in package %s, not %s", filename, f.Name.Name, pkgName) + } + + // TODO: reuse golangci-lint lines cache + src, err := ioutil.ReadFile(filename) + if err != nil { + return nil, fmt.Errorf("can't read file %s: %s", filename, err) + } + + pkg.files[filename] = &file{ + pkg: pkg, + f: f, + fset: pkg.fset, + src: src, + filename: filename, + } + } + if len(pkg.files) == 0 { + return nil, nil + } + return pkg.lint(), nil +} + +var ( + genHdr = []byte("// Code generated ") + genFtr = []byte(" DO NOT EDIT.") +) + +// isGenerated reports whether the source file is generated code +// according the rules from https://golang.org/s/generatedcode. +func isGenerated(src []byte) bool { + sc := bufio.NewScanner(bytes.NewReader(src)) + for sc.Scan() { + b := sc.Bytes() + if bytes.HasPrefix(b, genHdr) && bytes.HasSuffix(b, genFtr) && len(b) >= len(genHdr)+len(genFtr) { + return true + } + } + return false +} + +// pkg represents a package being linted. +type pkg struct { + fset *token.FileSet + files map[string]*file + + typesPkg *types.Package + typesInfo *types.Info + + // sortable is the set of types in the package that implement sort.Interface. + sortable map[string]bool + // main is whether this is a "main" package. + main bool + + problems []Problem +} + +func (p *pkg) lint() []Problem { + p.scanSortable() + p.main = p.isMain() + + for _, f := range p.files { + f.lint() + } + + sort.Sort(byPosition(p.problems)) + + return p.problems +} + +// file represents a file being linted. +type file struct { + pkg *pkg + f *ast.File + fset *token.FileSet + src []byte + filename string +} + +func (f *file) isTest() bool { return strings.HasSuffix(f.filename, "_test.go") } + +func (f *file) lint() { + f.lintPackageComment() + f.lintImports() + f.lintBlankImports() + f.lintExported() + f.lintNames() + f.lintElses() + f.lintRanges() + f.lintErrorf() + f.lintErrors() + f.lintErrorStrings() + f.lintReceiverNames() + f.lintIncDec() + f.lintErrorReturn() + f.lintUnexportedReturn() + f.lintTimeNames() + f.lintContextKeyTypes() + f.lintContextArgs() +} + +type link string +type category string + +// The variadic arguments may start with link and category types, +// and must end with a format string and any arguments. +// It returns the new Problem. +func (f *file) errorf(n ast.Node, confidence float64, args ...interface{}) *Problem { + pos := f.fset.Position(n.Pos()) + if pos.Filename == "" { + pos.Filename = f.filename + } + return f.pkg.errorfAt(pos, confidence, args...) +} + +func (p *pkg) errorfAt(pos token.Position, confidence float64, args ...interface{}) *Problem { + problem := Problem{ + Position: pos, + Confidence: confidence, + } + if pos.Filename != "" { + // The file might not exist in our mapping if a //line directive was encountered. + if f, ok := p.files[pos.Filename]; ok { + problem.LineText = srcLine(f.src, pos) + } + } + +argLoop: + for len(args) > 1 { // always leave at least the format string in args + switch v := args[0].(type) { + case link: + problem.Link = string(v) + case category: + problem.Category = string(v) + default: + break argLoop + } + args = args[1:] + } + + problem.Text = fmt.Sprintf(args[0].(string), args[1:]...) + + p.problems = append(p.problems, problem) + return &p.problems[len(p.problems)-1] +} + +var newImporter = func(fset *token.FileSet) types.ImporterFrom { + return gcexportdata.NewImporter(fset, make(map[string]*types.Package)) +} + +func (p *pkg) typeCheck() error { + config := &types.Config{ + // By setting a no-op error reporter, the type checker does as much work as possible. + Error: func(error) {}, + Importer: newImporter(p.fset), + } + info := &types.Info{ + Types: make(map[ast.Expr]types.TypeAndValue), + Defs: make(map[*ast.Ident]types.Object), + Uses: make(map[*ast.Ident]types.Object), + Scopes: make(map[ast.Node]*types.Scope), + } + var anyFile *file + var astFiles []*ast.File + for _, f := range p.files { + anyFile = f + astFiles = append(astFiles, f.f) + } + pkg, err := config.Check(anyFile.f.Name.Name, p.fset, astFiles, info) + // Remember the typechecking info, even if config.Check failed, + // since we will get partial information. + p.typesPkg = pkg + p.typesInfo = info + return err +} + +func (p *pkg) typeOf(expr ast.Expr) types.Type { + if p.typesInfo == nil { + return nil + } + return p.typesInfo.TypeOf(expr) +} + +func (p *pkg) isNamedType(typ types.Type, importPath, name string) bool { + n, ok := typ.(*types.Named) + if !ok { + return false + } + tn := n.Obj() + return tn != nil && tn.Pkg() != nil && tn.Pkg().Path() == importPath && tn.Name() == name +} + +// scopeOf returns the tightest scope encompassing id. +func (p *pkg) scopeOf(id *ast.Ident) *types.Scope { + var scope *types.Scope + if obj := p.typesInfo.ObjectOf(id); obj != nil { + scope = obj.Parent() + } + if scope == p.typesPkg.Scope() { + // We were given a top-level identifier. + // Use the file-level scope instead of the package-level scope. + pos := id.Pos() + for _, f := range p.files { + if f.f.Pos() <= pos && pos < f.f.End() { + scope = p.typesInfo.Scopes[f.f] + break + } + } + } + return scope +} + +func (p *pkg) scanSortable() { + p.sortable = make(map[string]bool) + + // bitfield for which methods exist on each type. + const ( + Len = 1 << iota + Less + Swap + ) + nmap := map[string]int{"Len": Len, "Less": Less, "Swap": Swap} + has := make(map[string]int) + for _, f := range p.files { + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok || fn.Recv == nil || len(fn.Recv.List) == 0 { + return true + } + // TODO(dsymonds): We could check the signature to be more precise. + recv := receiverType(fn) + if i, ok := nmap[fn.Name.Name]; ok { + has[recv] |= i + } + return false + }) + } + for typ, ms := range has { + if ms == Len|Less|Swap { + p.sortable[typ] = true + } + } +} + +func (p *pkg) isMain() bool { + for _, f := range p.files { + if f.isMain() { + return true + } + } + return false +} + +func (f *file) isMain() bool { + if f.f.Name.Name == "main" { + return true + } + return false +} + +// lintPackageComment checks package comments. It complains if +// there is no package comment, or if it is not of the right form. +// This has a notable false positive in that a package comment +// could rightfully appear in a different file of the same package, +// but that's not easy to fix since this linter is file-oriented. +func (f *file) lintPackageComment() { + if f.isTest() { + return + } + + const ref = styleGuideBase + "#package-comments" + prefix := "Package " + f.f.Name.Name + " " + + // Look for a detached package comment. + // First, scan for the last comment that occurs before the "package" keyword. + var lastCG *ast.CommentGroup + for _, cg := range f.f.Comments { + if cg.Pos() > f.f.Package { + // Gone past "package" keyword. + break + } + lastCG = cg + } + if lastCG != nil && strings.HasPrefix(lastCG.Text(), prefix) { + endPos := f.fset.Position(lastCG.End()) + pkgPos := f.fset.Position(f.f.Package) + if endPos.Line+1 < pkgPos.Line { + // There isn't a great place to anchor this error; + // the start of the blank lines between the doc and the package statement + // is at least pointing at the location of the problem. + pos := token.Position{ + Filename: endPos.Filename, + // Offset not set; it is non-trivial, and doesn't appear to be needed. + Line: endPos.Line + 1, + Column: 1, + } + f.pkg.errorfAt(pos, 0.9, link(ref), category("comments"), "package comment is detached; there should be no blank lines between it and the package statement") + return + } + } + + if f.f.Doc == nil { + f.errorf(f.f, 0.2, link(ref), category("comments"), "should have a package comment, unless it's in another file for this package") + return + } + s := f.f.Doc.Text() + if ts := strings.TrimLeft(s, " \t"); ts != s { + f.errorf(f.f.Doc, 1, link(ref), category("comments"), "package comment should not have leading space") + s = ts + } + // Only non-main packages need to keep to this form. + if !f.pkg.main && !strings.HasPrefix(s, prefix) { + f.errorf(f.f.Doc, 1, link(ref), category("comments"), `package comment should be of the form "%s..."`, prefix) + } +} + +func (f *file) isCgo() bool { + if f.src == nil { + return false + } + newLinePos := bytes.Index(f.src, []byte("\n")) + if newLinePos < 0 { + return false + } + firstLine := string(f.src[:newLinePos]) + + // files using cgo have implicitly added comment "Created by cgo - DO NOT EDIT" for go <= 1.10 + // and "Code generated by cmd/cgo" for go >= 1.11 + return strings.Contains(firstLine, "Created by cgo") || strings.Contains(firstLine, "Code generated by cmd/cgo") +} + +// lintBlankImports complains if a non-main package has blank imports that are +// not documented. +func (f *file) lintBlankImports() { + // In package main and in tests, we don't complain about blank imports. + if f.pkg.main || f.isTest() || f.isCgo() { + return + } + + // The first element of each contiguous group of blank imports should have + // an explanatory comment of some kind. + for i, imp := range f.f.Imports { + pos := f.fset.Position(imp.Pos()) + + if !isBlank(imp.Name) { + continue // Ignore non-blank imports. + } + if i > 0 { + prev := f.f.Imports[i-1] + prevPos := f.fset.Position(prev.Pos()) + if isBlank(prev.Name) && prevPos.Line+1 == pos.Line { + continue // A subsequent blank in a group. + } + } + + // This is the first blank import of a group. + if imp.Doc == nil && imp.Comment == nil { + ref := "" + f.errorf(imp, 1, link(ref), category("imports"), "a blank import should be only in a main or test package, or have a comment justifying it") + } + } +} + +// lintImports examines import blocks. +func (f *file) lintImports() { + for i, is := range f.f.Imports { + _ = i + if is.Name != nil && is.Name.Name == "." && !f.isTest() { + f.errorf(is, 1, link(styleGuideBase+"#import-dot"), category("imports"), "should not use dot imports") + } + + } +} + +const docCommentsLink = styleGuideBase + "#doc-comments" + +// lintExported examines the exported names. +// It complains if any required doc comments are missing, +// or if they are not of the right form. The exact rules are in +// lintFuncDoc, lintTypeDoc and lintValueSpecDoc; this function +// also tracks the GenDecl structure being traversed to permit +// doc comments for constants to be on top of the const block. +// It also complains if the names stutter when combined with +// the package name. +func (f *file) lintExported() { + if f.isTest() { + return + } + + var lastGen *ast.GenDecl // last GenDecl entered. + + // Set of GenDecls that have already had missing comments flagged. + genDeclMissingComments := make(map[*ast.GenDecl]bool) + + f.walk(func(node ast.Node) bool { + switch v := node.(type) { + case *ast.GenDecl: + if v.Tok == token.IMPORT { + return false + } + // token.CONST, token.TYPE or token.VAR + lastGen = v + return true + case *ast.FuncDecl: + f.lintFuncDoc(v) + if v.Recv == nil { + // Only check for stutter on functions, not methods. + // Method names are not used package-qualified. + f.checkStutter(v.Name, "func") + } + // Don't proceed inside funcs. + return false + case *ast.TypeSpec: + // inside a GenDecl, which usually has the doc + doc := v.Doc + if doc == nil { + doc = lastGen.Doc + } + f.lintTypeDoc(v, doc) + f.checkStutter(v.Name, "type") + // Don't proceed inside types. + return false + case *ast.ValueSpec: + f.lintValueSpecDoc(v, lastGen, genDeclMissingComments) + return false + } + return true + }) +} + +var ( + allCapsRE = regexp.MustCompile(`^[A-Z0-9_]+$`) + anyCapsRE = regexp.MustCompile(`[A-Z]`) +) + +// knownNameExceptions is a set of names that are known to be exempt from naming checks. +// This is usually because they are constrained by having to match names in the +// standard library. +var knownNameExceptions = map[string]bool{ + "LastInsertId": true, // must match database/sql + "kWh": true, +} + +func isInTopLevel(f *ast.File, ident *ast.Ident) bool { + path, _ := astutil.PathEnclosingInterval(f, ident.Pos(), ident.End()) + for _, f := range path { + switch f.(type) { + case *ast.File, *ast.GenDecl, *ast.ValueSpec, *ast.Ident: + continue + } + return false + } + return true +} + +// lintNames examines all names in the file. +// It complains if any use underscores or incorrect known initialisms. +func (f *file) lintNames() { + // Package names need slightly different handling than other names. + if strings.Contains(f.f.Name.Name, "_") && !strings.HasSuffix(f.f.Name.Name, "_test") { + f.errorf(f.f, 1, link("http://golang.org/doc/effective_go.html#package-names"), category("naming"), "don't use an underscore in package name") + } + if anyCapsRE.MatchString(f.f.Name.Name) { + f.errorf(f.f, 1, link("http://golang.org/doc/effective_go.html#package-names"), category("mixed-caps"), "don't use MixedCaps in package name; %s should be %s", f.f.Name.Name, strings.ToLower(f.f.Name.Name)) + } + + check := func(id *ast.Ident, thing string) { + if id.Name == "_" { + return + } + if knownNameExceptions[id.Name] { + return + } + + // Handle two common styles from other languages that don't belong in Go. + if len(id.Name) >= 5 && allCapsRE.MatchString(id.Name) && strings.Contains(id.Name, "_") { + capCount := 0 + for _, c := range id.Name { + if 'A' <= c && c <= 'Z' { + capCount++ + } + } + if capCount >= 2 { + f.errorf(id, 0.8, link(styleGuideBase+"#mixed-caps"), category("naming"), "don't use ALL_CAPS in Go names; use CamelCase") + return + } + } + if thing == "const" || (thing == "var" && isInTopLevel(f.f, id)) { + if len(id.Name) > 2 && id.Name[0] == 'k' && id.Name[1] >= 'A' && id.Name[1] <= 'Z' { + should := string(id.Name[1]+'a'-'A') + id.Name[2:] + f.errorf(id, 0.8, link(styleGuideBase+"#mixed-caps"), category("naming"), "don't use leading k in Go names; %s %s should be %s", thing, id.Name, should) + } + } + + should := lintName(id.Name) + if id.Name == should { + return + } + + if len(id.Name) > 2 && strings.Contains(id.Name[1:], "_") { + f.errorf(id, 0.9, link("http://golang.org/doc/effective_go.html#mixed-caps"), category("naming"), "don't use underscores in Go names; %s %s should be %s", thing, id.Name, should) + return + } + f.errorf(id, 0.8, link(styleGuideBase+"#initialisms"), category("naming"), "%s %s should be %s", thing, id.Name, should) + } + checkList := func(fl *ast.FieldList, thing string) { + if fl == nil { + return + } + for _, f := range fl.List { + for _, id := range f.Names { + check(id, thing) + } + } + } + f.walk(func(node ast.Node) bool { + switch v := node.(type) { + case *ast.AssignStmt: + if v.Tok == token.ASSIGN { + return true + } + for _, exp := range v.Lhs { + if id, ok := exp.(*ast.Ident); ok { + check(id, "var") + } + } + case *ast.FuncDecl: + if f.isTest() && (strings.HasPrefix(v.Name.Name, "Example") || strings.HasPrefix(v.Name.Name, "Test") || strings.HasPrefix(v.Name.Name, "Benchmark")) { + return true + } + + thing := "func" + if v.Recv != nil { + thing = "method" + } + + // Exclude naming warnings for functions that are exported to C but + // not exported in the Go API. + // See https://github.com/golang/lint/issues/144. + if ast.IsExported(v.Name.Name) || !isCgoExported(v) { + check(v.Name, thing) + } + + checkList(v.Type.Params, thing+" parameter") + checkList(v.Type.Results, thing+" result") + case *ast.GenDecl: + if v.Tok == token.IMPORT { + return true + } + var thing string + switch v.Tok { + case token.CONST: + thing = "const" + case token.TYPE: + thing = "type" + case token.VAR: + thing = "var" + } + for _, spec := range v.Specs { + switch s := spec.(type) { + case *ast.TypeSpec: + check(s.Name, thing) + case *ast.ValueSpec: + for _, id := range s.Names { + check(id, thing) + } + } + } + case *ast.InterfaceType: + // Do not check interface method names. + // They are often constrainted by the method names of concrete types. + for _, x := range v.Methods.List { + ft, ok := x.Type.(*ast.FuncType) + if !ok { // might be an embedded interface name + continue + } + checkList(ft.Params, "interface method parameter") + checkList(ft.Results, "interface method result") + } + case *ast.RangeStmt: + if v.Tok == token.ASSIGN { + return true + } + if id, ok := v.Key.(*ast.Ident); ok { + check(id, "range var") + } + if id, ok := v.Value.(*ast.Ident); ok { + check(id, "range var") + } + case *ast.StructType: + for _, f := range v.Fields.List { + for _, id := range f.Names { + check(id, "struct field") + } + } + } + return true + }) +} + +// lintName returns a different name if it should be different. +func lintName(name string) (should string) { + // Fast path for simple cases: "_" and all lowercase. + if name == "_" { + return name + } + allLower := true + for _, r := range name { + if !unicode.IsLower(r) { + allLower = false + break + } + } + if allLower { + return name + } + + // Split camelCase at any lower->upper transition, and split on underscores. + // Check each word for common initialisms. + runes := []rune(name) + w, i := 0, 0 // index of start of word, scan + for i+1 <= len(runes) { + eow := false // whether we hit the end of a word + if i+1 == len(runes) { + eow = true + } else if runes[i+1] == '_' { + // underscore; shift the remainder forward over any run of underscores + eow = true + n := 1 + for i+n+1 < len(runes) && runes[i+n+1] == '_' { + n++ + } + + // Leave at most one underscore if the underscore is between two digits + if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { + n-- + } + + copy(runes[i+1:], runes[i+n+1:]) + runes = runes[:len(runes)-n] + } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { + // lower->non-lower + eow = true + } + i++ + if !eow { + continue + } + + // [w,i) is a word. + word := string(runes[w:i]) + if u := strings.ToUpper(word); commonInitialisms[u] { + // Keep consistent case, which is lowercase only at the start. + if w == 0 && unicode.IsLower(runes[w]) { + u = strings.ToLower(u) + } + // All the common initialisms are ASCII, + // so we can replace the bytes exactly. + copy(runes[w:], []rune(u)) + } else if w > 0 && strings.ToLower(word) == word { + // already all lowercase, and not the first word, so uppercase the first character. + runes[w] = unicode.ToUpper(runes[w]) + } + w = i + } + return string(runes) +} + +// commonInitialisms is a set of common initialisms. +// Only add entries that are highly unlikely to be non-initialisms. +// For instance, "ID" is fine (Freudian code is rare), but "AND" is not. +var commonInitialisms = map[string]bool{ + "ACL": true, + "API": true, + "ASCII": true, + "CPU": true, + "CSS": true, + "DNS": true, + "EOF": true, + "GUID": true, + "HTML": true, + "HTTP": true, + "HTTPS": true, + "ID": true, + "IP": true, + "JSON": true, + "LHS": true, + "QPS": true, + "RAM": true, + "RHS": true, + "RPC": true, + "SLA": true, + "SMTP": true, + "SQL": true, + "SSH": true, + "TCP": true, + "TLS": true, + "TTL": true, + "UDP": true, + "UI": true, + "UID": true, + "UUID": true, + "URI": true, + "URL": true, + "UTF8": true, + "VM": true, + "XML": true, + "XMPP": true, + "XSRF": true, + "XSS": true, +} + +// lintTypeDoc examines the doc comment on a type. +// It complains if they are missing from an exported type, +// or if they are not of the standard form. +func (f *file) lintTypeDoc(t *ast.TypeSpec, doc *ast.CommentGroup) { + if !ast.IsExported(t.Name.Name) { + return + } + if doc == nil { + f.errorf(t, 1, link(docCommentsLink), category("comments"), "exported type %v should have comment or be unexported", t.Name) + return + } + + s := doc.Text() + articles := [...]string{"A", "An", "The"} + for _, a := range articles { + if strings.HasPrefix(s, a+" ") { + s = s[len(a)+1:] + break + } + } + if !strings.HasPrefix(s, t.Name.Name+" ") { + f.errorf(doc, 1, link(docCommentsLink), category("comments"), `comment on exported type %v should be of the form "%v ..." (with optional leading article)`, t.Name, t.Name) + } +} + +var commonMethods = map[string]bool{ + "Error": true, + "Read": true, + "ServeHTTP": true, + "String": true, + "Write": true, +} + +// lintFuncDoc examines doc comments on functions and methods. +// It complains if they are missing, or not of the right form. +// It has specific exclusions for well-known methods (see commonMethods above). +func (f *file) lintFuncDoc(fn *ast.FuncDecl) { + if !ast.IsExported(fn.Name.Name) { + // func is unexported + return + } + kind := "function" + name := fn.Name.Name + if fn.Recv != nil && len(fn.Recv.List) > 0 { + // method + kind = "method" + recv := receiverType(fn) + if !ast.IsExported(recv) { + // receiver is unexported + return + } + if commonMethods[name] { + return + } + switch name { + case "Len", "Less", "Swap": + if f.pkg.sortable[recv] { + return + } + } + name = recv + "." + name + } + if fn.Doc == nil { + f.errorf(fn, 1, link(docCommentsLink), category("comments"), "exported %s %s should have comment or be unexported", kind, name) + return + } + s := fn.Doc.Text() + prefix := fn.Name.Name + " " + if !strings.HasPrefix(s, prefix) { + f.errorf(fn.Doc, 1, link(docCommentsLink), category("comments"), `comment on exported %s %s should be of the form "%s..."`, kind, name, prefix) + } +} + +// lintValueSpecDoc examines package-global variables and constants. +// It complains if they are not individually declared, +// or if they are not suitably documented in the right form (unless they are in a block that is commented). +func (f *file) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genDeclMissingComments map[*ast.GenDecl]bool) { + kind := "var" + if gd.Tok == token.CONST { + kind = "const" + } + + if len(vs.Names) > 1 { + // Check that none are exported except for the first. + for _, n := range vs.Names[1:] { + if ast.IsExported(n.Name) { + f.errorf(vs, 1, category("comments"), "exported %s %s should have its own declaration", kind, n.Name) + return + } + } + } + + // Only one name. + name := vs.Names[0].Name + if !ast.IsExported(name) { + return + } + + if vs.Doc == nil && gd.Doc == nil { + if genDeclMissingComments[gd] { + return + } + block := "" + if kind == "const" && gd.Lparen.IsValid() { + block = " (or a comment on this block)" + } + f.errorf(vs, 1, link(docCommentsLink), category("comments"), "exported %s %s should have comment%s or be unexported", kind, name, block) + genDeclMissingComments[gd] = true + return + } + // If this GenDecl has parens and a comment, we don't check its comment form. + if gd.Lparen.IsValid() && gd.Doc != nil { + return + } + // The relevant text to check will be on either vs.Doc or gd.Doc. + // Use vs.Doc preferentially. + doc := vs.Doc + if doc == nil { + doc = gd.Doc + } + prefix := name + " " + if !strings.HasPrefix(doc.Text(), prefix) { + f.errorf(doc, 1, link(docCommentsLink), category("comments"), `comment on exported %s %s should be of the form "%s..."`, kind, name, prefix) + } +} + +func (f *file) checkStutter(id *ast.Ident, thing string) { + pkg, name := f.f.Name.Name, id.Name + if !ast.IsExported(name) { + // unexported name + return + } + // A name stutters if the package name is a strict prefix + // and the next character of the name starts a new word. + if len(name) <= len(pkg) { + // name is too short to stutter. + // This permits the name to be the same as the package name. + return + } + if !strings.EqualFold(pkg, name[:len(pkg)]) { + return + } + // We can assume the name is well-formed UTF-8. + // If the next rune after the package name is uppercase or an underscore + // the it's starting a new word and thus this name stutters. + rem := name[len(pkg):] + if next, _ := utf8.DecodeRuneInString(rem); next == '_' || unicode.IsUpper(next) { + f.errorf(id, 0.8, link(styleGuideBase+"#package-names"), category("naming"), "%s name will be used as %s.%s by other packages, and that stutters; consider calling this %s", thing, pkg, name, rem) + } +} + +// zeroLiteral is a set of ast.BasicLit values that are zero values. +// It is not exhaustive. +var zeroLiteral = map[string]bool{ + "false": true, // bool + // runes + `'\x00'`: true, + `'\000'`: true, + // strings + `""`: true, + "``": true, + // numerics + "0": true, + "0.": true, + "0.0": true, + "0i": true, +} + +// lintElses examines else blocks. It complains about any else block whose if block ends in a return. +func (f *file) lintElses() { + // We don't want to flag if { } else if { } else { } constructions. + // They will appear as an IfStmt whose Else field is also an IfStmt. + // Record such a node so we ignore it when we visit it. + ignore := make(map[*ast.IfStmt]bool) + + f.walk(func(node ast.Node) bool { + ifStmt, ok := node.(*ast.IfStmt) + if !ok || ifStmt.Else == nil { + return true + } + if elseif, ok := ifStmt.Else.(*ast.IfStmt); ok { + ignore[elseif] = true + return true + } + if ignore[ifStmt] { + return true + } + if _, ok := ifStmt.Else.(*ast.BlockStmt); !ok { + // only care about elses without conditions + return true + } + if len(ifStmt.Body.List) == 0 { + return true + } + shortDecl := false // does the if statement have a ":=" initialization statement? + if ifStmt.Init != nil { + if as, ok := ifStmt.Init.(*ast.AssignStmt); ok && as.Tok == token.DEFINE { + shortDecl = true + } + } + lastStmt := ifStmt.Body.List[len(ifStmt.Body.List)-1] + if _, ok := lastStmt.(*ast.ReturnStmt); ok { + extra := "" + if shortDecl { + extra = " (move short variable declaration to its own line if necessary)" + } + f.errorf(ifStmt.Else, 1, link(styleGuideBase+"#indent-error-flow"), category("indent"), "if block ends with a return statement, so drop this else and outdent its block"+extra) + } + return true + }) +} + +// lintRanges examines range clauses. It complains about redundant constructions. +func (f *file) lintRanges() { + f.walk(func(node ast.Node) bool { + rs, ok := node.(*ast.RangeStmt) + if !ok { + return true + } + + if isIdent(rs.Key, "_") && (rs.Value == nil || isIdent(rs.Value, "_")) { + p := f.errorf(rs.Key, 1, category("range-loop"), "should omit values from range; this loop is equivalent to `for range ...`") + + newRS := *rs // shallow copy + newRS.Value = nil + newRS.Key = nil + p.ReplacementLine = f.firstLineOf(&newRS, rs) + + return true + } + + if isIdent(rs.Value, "_") { + p := f.errorf(rs.Value, 1, category("range-loop"), "should omit 2nd value from range; this loop is equivalent to `for %s %s range ...`", f.render(rs.Key), rs.Tok) + + newRS := *rs // shallow copy + newRS.Value = nil + p.ReplacementLine = f.firstLineOf(&newRS, rs) + } + + return true + }) +} + +// lintErrorf examines errors.New and testing.Error calls. It complains if its only argument is an fmt.Sprintf invocation. +func (f *file) lintErrorf() { + f.walk(func(node ast.Node) bool { + ce, ok := node.(*ast.CallExpr) + if !ok || len(ce.Args) != 1 { + return true + } + isErrorsNew := isPkgDot(ce.Fun, "errors", "New") + var isTestingError bool + se, ok := ce.Fun.(*ast.SelectorExpr) + if ok && se.Sel.Name == "Error" { + if typ := f.pkg.typeOf(se.X); typ != nil { + isTestingError = typ.String() == "*testing.T" + } + } + if !isErrorsNew && !isTestingError { + return true + } + if !f.imports("errors") { + return true + } + arg := ce.Args[0] + ce, ok = arg.(*ast.CallExpr) + if !ok || !isPkgDot(ce.Fun, "fmt", "Sprintf") { + return true + } + errorfPrefix := "fmt" + if isTestingError { + errorfPrefix = f.render(se.X) + } + p := f.errorf(node, 1, category("errors"), "should replace %s(fmt.Sprintf(...)) with %s.Errorf(...)", f.render(se), errorfPrefix) + + m := f.srcLineWithMatch(ce, `^(.*)`+f.render(se)+`\(fmt\.Sprintf\((.*)\)\)(.*)$`) + if m != nil { + p.ReplacementLine = m[1] + errorfPrefix + ".Errorf(" + m[2] + ")" + m[3] + } + + return true + }) +} + +// lintErrors examines global error vars. It complains if they aren't named in the standard way. +func (f *file) lintErrors() { + for _, decl := range f.f.Decls { + gd, ok := decl.(*ast.GenDecl) + if !ok || gd.Tok != token.VAR { + continue + } + for _, spec := range gd.Specs { + spec := spec.(*ast.ValueSpec) + if len(spec.Names) != 1 || len(spec.Values) != 1 { + continue + } + ce, ok := spec.Values[0].(*ast.CallExpr) + if !ok { + continue + } + if !isPkgDot(ce.Fun, "errors", "New") && !isPkgDot(ce.Fun, "fmt", "Errorf") { + continue + } + + id := spec.Names[0] + prefix := "err" + if id.IsExported() { + prefix = "Err" + } + if !strings.HasPrefix(id.Name, prefix) { + f.errorf(id, 0.9, category("naming"), "error var %s should have name of the form %sFoo", id.Name, prefix) + } + } + } +} + +func lintErrorString(s string) (isClean bool, conf float64) { + const basicConfidence = 0.8 + const capConfidence = basicConfidence - 0.2 + first, firstN := utf8.DecodeRuneInString(s) + last, _ := utf8.DecodeLastRuneInString(s) + if last == '.' || last == ':' || last == '!' || last == '\n' { + return false, basicConfidence + } + if unicode.IsUpper(first) { + // People use proper nouns and exported Go identifiers in error strings, + // so decrease the confidence of warnings for capitalization. + if len(s) <= firstN { + return false, capConfidence + } + // Flag strings starting with something that doesn't look like an initialism. + if second, _ := utf8.DecodeRuneInString(s[firstN:]); !unicode.IsUpper(second) { + return false, capConfidence + } + } + return true, 0 +} + +// lintErrorStrings examines error strings. +// It complains if they are capitalized or end in punctuation or a newline. +func (f *file) lintErrorStrings() { + f.walk(func(node ast.Node) bool { + ce, ok := node.(*ast.CallExpr) + if !ok { + return true + } + if !isPkgDot(ce.Fun, "errors", "New") && !isPkgDot(ce.Fun, "fmt", "Errorf") { + return true + } + if len(ce.Args) < 1 { + return true + } + str, ok := ce.Args[0].(*ast.BasicLit) + if !ok || str.Kind != token.STRING { + return true + } + s, _ := strconv.Unquote(str.Value) // can assume well-formed Go + if s == "" { + return true + } + clean, conf := lintErrorString(s) + if clean { + return true + } + + f.errorf(str, conf, link(styleGuideBase+"#error-strings"), category("errors"), + "error strings should not be capitalized or end with punctuation or a newline") + return true + }) +} + +// lintReceiverNames examines receiver names. It complains about inconsistent +// names used for the same type and names such as "this". +func (f *file) lintReceiverNames() { + typeReceiver := map[string]string{} + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok || fn.Recv == nil || len(fn.Recv.List) == 0 { + return true + } + names := fn.Recv.List[0].Names + if len(names) < 1 { + return true + } + name := names[0].Name + const ref = styleGuideBase + "#receiver-names" + if name == "_" { + f.errorf(n, 1, link(ref), category("naming"), `receiver name should not be an underscore, omit the name if it is unused`) + return true + } + if name == "this" || name == "self" { + f.errorf(n, 1, link(ref), category("naming"), `receiver name should be a reflection of its identity; don't use generic names such as "this" or "self"`) + return true + } + recv := receiverType(fn) + if prev, ok := typeReceiver[recv]; ok && prev != name { + f.errorf(n, 1, link(ref), category("naming"), "receiver name %s should be consistent with previous receiver name %s for %s", name, prev, recv) + return true + } + typeReceiver[recv] = name + return true + }) +} + +// lintIncDec examines statements that increment or decrement a variable. +// It complains if they don't use x++ or x--. +func (f *file) lintIncDec() { + f.walk(func(n ast.Node) bool { + as, ok := n.(*ast.AssignStmt) + if !ok { + return true + } + if len(as.Lhs) != 1 { + return true + } + if !isOne(as.Rhs[0]) { + return true + } + var suffix string + switch as.Tok { + case token.ADD_ASSIGN: + suffix = "++" + case token.SUB_ASSIGN: + suffix = "--" + default: + return true + } + f.errorf(as, 0.8, category("unary-op"), "should replace %s with %s%s", f.render(as), f.render(as.Lhs[0]), suffix) + return true + }) +} + +// lintErrorReturn examines function declarations that return an error. +// It complains if the error isn't the last parameter. +func (f *file) lintErrorReturn() { + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok || fn.Type.Results == nil { + return true + } + ret := fn.Type.Results.List + if len(ret) <= 1 { + return true + } + if isIdent(ret[len(ret)-1].Type, "error") { + return true + } + // An error return parameter should be the last parameter. + // Flag any error parameters found before the last. + for _, r := range ret[:len(ret)-1] { + if isIdent(r.Type, "error") { + f.errorf(fn, 0.9, category("arg-order"), "error should be the last type when returning multiple items") + break // only flag one + } + } + return true + }) +} + +// lintUnexportedReturn examines exported function declarations. +// It complains if any return an unexported type. +func (f *file) lintUnexportedReturn() { + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok { + return true + } + if fn.Type.Results == nil { + return false + } + if !fn.Name.IsExported() { + return false + } + thing := "func" + if fn.Recv != nil && len(fn.Recv.List) > 0 { + thing = "method" + if !ast.IsExported(receiverType(fn)) { + // Don't report exported methods of unexported types, + // such as private implementations of sort.Interface. + return false + } + } + for _, ret := range fn.Type.Results.List { + typ := f.pkg.typeOf(ret.Type) + if exportedType(typ) { + continue + } + f.errorf(ret.Type, 0.8, category("unexported-type-in-api"), + "exported %s %s returns unexported type %s, which can be annoying to use", + thing, fn.Name.Name, typ) + break // only flag one + } + return false + }) +} + +// exportedType reports whether typ is an exported type. +// It is imprecise, and will err on the side of returning true, +// such as for composite types. +func exportedType(typ types.Type) bool { + switch T := typ.(type) { + case *types.Named: + // Builtin types have no package. + return T.Obj().Pkg() == nil || T.Obj().Exported() + case *types.Map: + return exportedType(T.Key()) && exportedType(T.Elem()) + case interface { + Elem() types.Type + }: // array, slice, pointer, chan + return exportedType(T.Elem()) + } + // Be conservative about other types, such as struct, interface, etc. + return true +} + +// timeSuffixes is a list of name suffixes that imply a time unit. +// This is not an exhaustive list. +var timeSuffixes = []string{ + "Sec", "Secs", "Seconds", + "Msec", "Msecs", + "Milli", "Millis", "Milliseconds", + "Usec", "Usecs", "Microseconds", + "MS", "Ms", +} + +func (f *file) lintTimeNames() { + f.walk(func(node ast.Node) bool { + v, ok := node.(*ast.ValueSpec) + if !ok { + return true + } + for _, name := range v.Names { + origTyp := f.pkg.typeOf(name) + // Look for time.Duration or *time.Duration; + // the latter is common when using flag.Duration. + typ := origTyp + if pt, ok := typ.(*types.Pointer); ok { + typ = pt.Elem() + } + if !f.pkg.isNamedType(typ, "time", "Duration") { + continue + } + suffix := "" + for _, suf := range timeSuffixes { + if strings.HasSuffix(name.Name, suf) { + suffix = suf + break + } + } + if suffix == "" { + continue + } + f.errorf(v, 0.9, category("time"), "var %s is of type %v; don't use unit-specific suffix %q", name.Name, origTyp, suffix) + } + return true + }) +} + +// lintContextKeyTypes checks for call expressions to context.WithValue with +// basic types used for the key argument. +// See: https://golang.org/issue/17293 +func (f *file) lintContextKeyTypes() { + f.walk(func(node ast.Node) bool { + switch node := node.(type) { + case *ast.CallExpr: + f.checkContextKeyType(node) + } + + return true + }) +} + +// checkContextKeyType reports an error if the call expression calls +// context.WithValue with a key argument of basic type. +func (f *file) checkContextKeyType(x *ast.CallExpr) { + sel, ok := x.Fun.(*ast.SelectorExpr) + if !ok { + return + } + pkg, ok := sel.X.(*ast.Ident) + if !ok || pkg.Name != "context" { + return + } + if sel.Sel.Name != "WithValue" { + return + } + + // key is second argument to context.WithValue + if len(x.Args) != 3 { + return + } + key := f.pkg.typesInfo.Types[x.Args[1]] + + if ktyp, ok := key.Type.(*types.Basic); ok && ktyp.Kind() != types.Invalid { + f.errorf(x, 1.0, category("context"), fmt.Sprintf("should not use basic type %s as key in context.WithValue", key.Type)) + } +} + +// lintContextArgs examines function declarations that contain an +// argument with a type of context.Context +// It complains if that argument isn't the first parameter. +func (f *file) lintContextArgs() { + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok || len(fn.Type.Params.List) <= 1 { + return true + } + // A context.Context should be the first parameter of a function. + // Flag any that show up after the first. + for _, arg := range fn.Type.Params.List[1:] { + if isPkgDot(arg.Type, "context", "Context") { + f.errorf(fn, 0.9, link("https://golang.org/pkg/context/"), category("arg-order"), "context.Context should be the first parameter of a function") + break // only flag one + } + } + return true + }) +} + +// containsComments returns whether the interval [start, end) contains any +// comments without "// MATCH " prefix. +func (f *file) containsComments(start, end token.Pos) bool { + for _, cgroup := range f.f.Comments { + comments := cgroup.List + if comments[0].Slash >= end { + // All comments starting with this group are after end pos. + return false + } + if comments[len(comments)-1].Slash < start { + // Comments group ends before start pos. + continue + } + for _, c := range comments { + if start <= c.Slash && c.Slash < end && !strings.HasPrefix(c.Text, "// MATCH ") { + return true + } + } + } + return false +} + +// receiverType returns the named type of the method receiver, sans "*", +// or "invalid-type" if fn.Recv is ill formed. +func receiverType(fn *ast.FuncDecl) string { + switch e := fn.Recv.List[0].Type.(type) { + case *ast.Ident: + return e.Name + case *ast.StarExpr: + if id, ok := e.X.(*ast.Ident); ok { + return id.Name + } + } + // The parser accepts much more than just the legal forms. + return "invalid-type" +} + +func (f *file) walk(fn func(ast.Node) bool) { + ast.Walk(walker(fn), f.f) +} + +func (f *file) render(x interface{}) string { + var buf bytes.Buffer + if err := printer.Fprint(&buf, f.fset, x); err != nil { + panic(err) + } + return buf.String() +} + +func (f *file) debugRender(x interface{}) string { + var buf bytes.Buffer + if err := ast.Fprint(&buf, f.fset, x, nil); err != nil { + panic(err) + } + return buf.String() +} + +// walker adapts a function to satisfy the ast.Visitor interface. +// The function return whether the walk should proceed into the node's children. +type walker func(ast.Node) bool + +func (w walker) Visit(node ast.Node) ast.Visitor { + if w(node) { + return w + } + return nil +} + +func isIdent(expr ast.Expr, ident string) bool { + id, ok := expr.(*ast.Ident) + return ok && id.Name == ident +} + +// isBlank returns whether id is the blank identifier "_". +// If id == nil, the answer is false. +func isBlank(id *ast.Ident) bool { return id != nil && id.Name == "_" } + +func isPkgDot(expr ast.Expr, pkg, name string) bool { + sel, ok := expr.(*ast.SelectorExpr) + return ok && isIdent(sel.X, pkg) && isIdent(sel.Sel, name) +} + +func isOne(expr ast.Expr) bool { + lit, ok := expr.(*ast.BasicLit) + return ok && lit.Kind == token.INT && lit.Value == "1" +} + +func isCgoExported(f *ast.FuncDecl) bool { + if f.Recv != nil || f.Doc == nil { + return false + } + + cgoExport := regexp.MustCompile(fmt.Sprintf("(?m)^//export %s$", regexp.QuoteMeta(f.Name.Name))) + for _, c := range f.Doc.List { + if cgoExport.MatchString(c.Text) { + return true + } + } + return false +} + +var basicTypeKinds = map[types.BasicKind]string{ + types.UntypedBool: "bool", + types.UntypedInt: "int", + types.UntypedRune: "rune", + types.UntypedFloat: "float64", + types.UntypedComplex: "complex128", + types.UntypedString: "string", +} + +// isUntypedConst reports whether expr is an untyped constant, +// and indicates what its default type is. +// scope may be nil. +func (f *file) isUntypedConst(expr ast.Expr) (defType string, ok bool) { + // Re-evaluate expr outside of its context to see if it's untyped. + // (An expr evaluated within, for example, an assignment context will get the type of the LHS.) + exprStr := f.render(expr) + tv, err := types.Eval(f.fset, f.pkg.typesPkg, expr.Pos(), exprStr) + if err != nil { + return "", false + } + if b, ok := tv.Type.(*types.Basic); ok { + if dt, ok := basicTypeKinds[b.Kind()]; ok { + return dt, true + } + } + + return "", false +} + +// firstLineOf renders the given node and returns its first line. +// It will also match the indentation of another node. +func (f *file) firstLineOf(node, match ast.Node) string { + line := f.render(node) + if i := strings.Index(line, "\n"); i >= 0 { + line = line[:i] + } + return f.indentOf(match) + line +} + +func (f *file) indentOf(node ast.Node) string { + line := srcLine(f.src, f.fset.Position(node.Pos())) + for i, r := range line { + switch r { + case ' ', '\t': + default: + return line[:i] + } + } + return line // unusual or empty line +} + +func (f *file) srcLineWithMatch(node ast.Node, pattern string) (m []string) { + line := srcLine(f.src, f.fset.Position(node.Pos())) + line = strings.TrimSuffix(line, "\n") + rx := regexp.MustCompile(pattern) + return rx.FindStringSubmatch(line) +} + +// imports returns true if the current file imports the specified package path. +func (f *file) imports(importPath string) bool { + all := astutil.Imports(f.fset, f.f) + for _, p := range all { + for _, i := range p { + uq, err := strconv.Unquote(i.Path.Value) + if err == nil && importPath == uq { + return true + } + } + } + return false +} + +// srcLine returns the complete line at p, including the terminating newline. +func srcLine(src []byte, p token.Position) string { + // Run to end of line in both directions if not at line start/end. + lo, hi := p.Offset, p.Offset+1 + for lo > 0 && src[lo-1] != '\n' { + lo-- + } + for hi < len(src) && src[hi-1] != '\n' { + hi++ + } + return string(src[lo:hi]) +} diff --git a/vendor/github.com/golangci/maligned/LICENSE b/vendor/github.com/golangci/maligned/LICENSE new file mode 100644 index 000000000..744875676 --- /dev/null +++ b/vendor/github.com/golangci/maligned/LICENSE @@ -0,0 +1,27 @@ +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. diff --git a/vendor/github.com/golangci/maligned/README b/vendor/github.com/golangci/maligned/README new file mode 100644 index 000000000..4e57f6eab --- /dev/null +++ b/vendor/github.com/golangci/maligned/README @@ -0,0 +1,7 @@ +Install: + + go get github.com/mdempsky/maligned + +Usage: + + maligned cmd/compile/internal/gc cmd/link/internal/ld diff --git a/vendor/github.com/golangci/maligned/maligned.go b/vendor/github.com/golangci/maligned/maligned.go new file mode 100644 index 000000000..c2492b2ff --- /dev/null +++ b/vendor/github.com/golangci/maligned/maligned.go @@ -0,0 +1,253 @@ +// 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 maligned + +import ( + "fmt" + "go/ast" + "go/build" + "go/token" + "go/types" + "sort" + "strings" + + "golang.org/x/tools/go/loader" +) + +var fset = token.NewFileSet() + +type Issue struct { + OldSize, NewSize int + NewStructDef string + Pos token.Position +} + +func Run(prog *loader.Program) []Issue { + flagVerbose := true + fset = prog.Fset + + var issues []Issue + + for _, pkg := range prog.InitialPackages() { + for _, file := range pkg.Files { + ast.Inspect(file, func(node ast.Node) bool { + if s, ok := node.(*ast.StructType); ok { + i := malign(node.Pos(), pkg.Types[s].Type.(*types.Struct), flagVerbose) + if i != nil { + issues = append(issues, *i) + } + } + return true + }) + } + } + + return issues +} + +func malign(pos token.Pos, str *types.Struct, verbose bool) *Issue { + wordSize := int64(8) + maxAlign := int64(8) + switch build.Default.GOARCH { + case "386", "arm": + wordSize, maxAlign = 4, 4 + case "amd64p32": + wordSize = 4 + } + + s := gcSizes{wordSize, maxAlign} + sz := s.Sizeof(str) + opt, fields := optimalSize(str, &s, verbose) + if sz == opt { + return nil + } + + newStructDefParts := []string{"struct{"} + + var w int + for _, f := range fields { + if n := len(f.Name()); n > w { + w = n + } + } + spaces := strings.Repeat(" ", w) + for _, f := range fields { + line := fmt.Sprintf("\t%s%s\t%s,", f.Name(), spaces[len(f.Name()):], f.Type().String()) + newStructDefParts = append(newStructDefParts, line) + } + newStructDefParts = append(newStructDefParts, "}") + + return &Issue{ + OldSize: int(sz), + NewSize: int(opt), + NewStructDef: strings.Join(newStructDefParts, "\n"), + Pos: fset.Position(pos), + } +} + +func optimalSize(str *types.Struct, sizes *gcSizes, stable bool) (int64, []*types.Var) { + nf := str.NumFields() + fields := make([]*types.Var, nf) + alignofs := make([]int64, nf) + sizeofs := make([]int64, nf) + for i := 0; i < nf; i++ { + fields[i] = str.Field(i) + ft := fields[i].Type() + alignofs[i] = sizes.Alignof(ft) + sizeofs[i] = sizes.Sizeof(ft) + } + if stable { // Stable keeps as much of the order as possible, but slower + sort.Stable(&byAlignAndSize{fields, alignofs, sizeofs}) + } else { + sort.Sort(&byAlignAndSize{fields, alignofs, sizeofs}) + } + return sizes.Sizeof(types.NewStruct(fields, nil)), fields +} + +type byAlignAndSize struct { + fields []*types.Var + alignofs []int64 + sizeofs []int64 +} + +func (s *byAlignAndSize) Len() int { return len(s.fields) } +func (s *byAlignAndSize) Swap(i, j int) { + s.fields[i], s.fields[j] = s.fields[j], s.fields[i] + s.alignofs[i], s.alignofs[j] = s.alignofs[j], s.alignofs[i] + s.sizeofs[i], s.sizeofs[j] = s.sizeofs[j], s.sizeofs[i] +} + +func (s *byAlignAndSize) Less(i, j int) bool { + // Place zero sized objects before non-zero sized objects. + if s.sizeofs[i] == 0 && s.sizeofs[j] != 0 { + return true + } + if s.sizeofs[j] == 0 && s.sizeofs[i] != 0 { + return false + } + + // Next, place more tightly aligned objects before less tightly aligned objects. + if s.alignofs[i] != s.alignofs[j] { + return s.alignofs[i] > s.alignofs[j] + } + + // Lastly, order by size. + if s.sizeofs[i] != s.sizeofs[j] { + return s.sizeofs[i] > s.sizeofs[j] + } + + return false +} + +// Code below based on go/types.StdSizes. + +type gcSizes struct { + WordSize int64 + MaxAlign int64 +} + +func (s *gcSizes) Alignof(T types.Type) int64 { + // NOTE: On amd64, complex64 is 8 byte aligned, + // even though float32 is only 4 byte aligned. + + // For arrays and structs, alignment is defined in terms + // of alignment of the elements and fields, respectively. + switch t := T.Underlying().(type) { + case *types.Array: + // spec: "For a variable x of array type: unsafe.Alignof(x) + // is the same as unsafe.Alignof(x[0]), but at least 1." + return s.Alignof(t.Elem()) + case *types.Struct: + // spec: "For a variable x of struct type: unsafe.Alignof(x) + // is the largest of the values unsafe.Alignof(x.f) for each + // field f of x, but at least 1." + max := int64(1) + for i, nf := 0, t.NumFields(); i < nf; i++ { + if a := s.Alignof(t.Field(i).Type()); a > max { + max = a + } + } + return max + } + a := s.Sizeof(T) // may be 0 + // spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1." + if a < 1 { + return 1 + } + if a > s.MaxAlign { + return s.MaxAlign + } + return a +} + +var basicSizes = [...]byte{ + types.Bool: 1, + types.Int8: 1, + types.Int16: 2, + types.Int32: 4, + types.Int64: 8, + types.Uint8: 1, + types.Uint16: 2, + types.Uint32: 4, + types.Uint64: 8, + types.Float32: 4, + types.Float64: 8, + types.Complex64: 8, + types.Complex128: 16, +} + +func (s *gcSizes) Sizeof(T types.Type) int64 { + switch t := T.Underlying().(type) { + case *types.Basic: + k := t.Kind() + if int(k) < len(basicSizes) { + if s := basicSizes[k]; s > 0 { + return int64(s) + } + } + if k == types.String { + return s.WordSize * 2 + } + case *types.Array: + n := t.Len() + if n == 0 { + return 0 + } + a := s.Alignof(t.Elem()) + z := s.Sizeof(t.Elem()) + return align(z, a)*(n-1) + z + case *types.Slice: + return s.WordSize * 3 + case *types.Struct: + nf := t.NumFields() + if nf == 0 { + return 0 + } + + var o int64 + max := int64(1) + for i := 0; i < nf; i++ { + ft := t.Field(i).Type() + a, sz := s.Alignof(ft), s.Sizeof(ft) + if a > max { + max = a + } + if i == nf-1 && sz == 0 && o != 0 { + sz = 1 + } + o = align(o, a) + sz + } + return align(o, max) + case *types.Interface: + return s.WordSize * 2 + } + return s.WordSize // catch-all +} + +// align returns the smallest y >= x such that y % a == 0. +func align(x, a int64) int64 { + y := x + a - 1 + return y - y%a +} diff --git a/vendor/github.com/golangci/misspell/.gitignore b/vendor/github.com/golangci/misspell/.gitignore new file mode 100644 index 000000000..b1b707e32 --- /dev/null +++ b/vendor/github.com/golangci/misspell/.gitignore @@ -0,0 +1,34 @@ +dist/ +bin/ +vendor/ + +# editor turds +*~ +*.gz +*.bz2 +*.csv + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/golangci/misspell/.travis.yml b/vendor/github.com/golangci/misspell/.travis.yml new file mode 100644 index 000000000..e63e6c2bd --- /dev/null +++ b/vendor/github.com/golangci/misspell/.travis.yml @@ -0,0 +1,20 @@ +sudo: required +dist: trusty +group: edge +language: go +go: + - "1.10" +git: + depth: 1 + +script: + - ./scripts/travis.sh + +# calls goreleaser when a new tag is pushed +deploy: +- provider: script + skip_cleanup: true + script: curl -sL http://git.io/goreleaser | bash + on: + tags: true + condition: $TRAVIS_OS_NAME = linux diff --git a/vendor/github.com/golangci/misspell/Dockerfile b/vendor/github.com/golangci/misspell/Dockerfile new file mode 100644 index 000000000..b8ea37b4c --- /dev/null +++ b/vendor/github.com/golangci/misspell/Dockerfile @@ -0,0 +1,37 @@ +FROM golang:1.10.0-alpine + +# cache buster +RUN echo 4 + +# git is needed for "go get" below +RUN apk add --no-cache git make + +# these are my standard testing / linting tools +RUN /bin/true \ + && go get -u github.com/golang/dep/cmd/dep \ + && go get -u github.com/alecthomas/gometalinter \ + && gometalinter --install \ + && rm -rf /go/src /go/pkg +# +# * SCOWL word list +# +# Downloads +# http://wordlist.aspell.net/dicts/ +# --> http://app.aspell.net/create +# + +# use en_US large size +# use regular size for others +ENV SOURCE_US_BIG http://app.aspell.net/create?max_size=70&spelling=US&max_variant=2&diacritic=both&special=hacker&special=roman-numerals&download=wordlist&encoding=utf-8&format=inline + +# should be able tell difference between English variations using this +ENV SOURCE_US http://app.aspell.net/create?max_size=60&spelling=US&max_variant=1&diacritic=both&download=wordlist&encoding=utf-8&format=inline +ENV SOURCE_GB_ISE http://app.aspell.net/create?max_size=60&spelling=GBs&max_variant=2&diacritic=both&download=wordlist&encoding=utf-8&format=inline +ENV SOURCE_GB_IZE http://app.aspell.net/create?max_size=60&spelling=GBz&max_variant=2&diacritic=both&download=wordlist&encoding=utf-8&format=inline +ENV SOURCE_CA http://app.aspell.net/create?max_size=60&spelling=CA&max_variant=2&diacritic=both&download=wordlist&encoding=utf-8&format=inline + +RUN /bin/true \ + && mkdir /scowl-wl \ + && wget -O /scowl-wl/words-US-60.txt ${SOURCE_US} \ + && wget -O /scowl-wl/words-GB-ise-60.txt ${SOURCE_GB_ISE} + diff --git a/vendor/github.com/golangci/misspell/Gopkg.lock b/vendor/github.com/golangci/misspell/Gopkg.lock new file mode 100644 index 000000000..90ed45115 --- /dev/null +++ b/vendor/github.com/golangci/misspell/Gopkg.lock @@ -0,0 +1,24 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/gobwas/glob" + packages = [ + ".", + "compiler", + "match", + "syntax", + "syntax/ast", + "syntax/lexer", + "util/runes", + "util/strings" + ] + revision = "5ccd90ef52e1e632236f7326478d4faa74f99438" + version = "v0.2.3" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "087ea4c49358ea8258ad9edfe514cd5ce9975c889c258e5ec7b5d2b720aae113" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golangci/misspell/Gopkg.toml b/vendor/github.com/golangci/misspell/Gopkg.toml new file mode 100644 index 000000000..e9b8e6a45 --- /dev/null +++ b/vendor/github.com/golangci/misspell/Gopkg.toml @@ -0,0 +1,34 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/gobwas/glob" + version = "0.2.3" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golangci/misspell/LICENSE b/vendor/github.com/golangci/misspell/LICENSE new file mode 100644 index 000000000..423e1f9e0 --- /dev/null +++ b/vendor/github.com/golangci/misspell/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015-2017 Nick Galbreath + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/golangci/misspell/Makefile b/vendor/github.com/golangci/misspell/Makefile new file mode 100644 index 000000000..862ab77b0 --- /dev/null +++ b/vendor/github.com/golangci/misspell/Makefile @@ -0,0 +1,74 @@ +CONTAINER=nickg/misspell + +install: ## install misspell into GOPATH/bin + go install ./cmd/misspell + +build: hooks ## build and lint misspell + ./scripts/build.sh + +test: ## run all tests + go test . + +# real publishing is done only by travis +publish: ## test goreleaser + ./scripts/goreleaser-dryrun.sh + +# the grep in line 2 is to remove misspellings in the spelling dictionary +# that trigger false positives!! +falsepositives: /scowl-wl + cat /scowl-wl/words-US-60.txt | \ + grep -i -v -E "payed|Tyre|Euclidian|nonoccurence|dependancy|reenforced|accidently|surprize|dependance|idealogy|binominal|causalities|conquerer|withing|casette|analyse|analogue|dialogue|paralyse|catalogue|archaeolog|clarinettist|catalyses|cancell|chisell|ageing|cataloguing" | \ + misspell -debug -error + cat /scowl-wl/words-GB-ise-60.txt | \ + grep -v -E "payed|nonoccurence|withing" | \ + misspell -locale=UK -debug -error +# cat /scowl-wl/words-GB-ize-60.txt | \ +# grep -v -E "withing" | \ +# misspell -debug -error +# cat /scowl-wl/words-CA-60.txt | \ +# grep -v -E "withing" | \ +# misspell -debug -error + +bench: ## run benchmarks + go test -bench '.*' + +clean: ## clean up time + rm -rf dist/ bin/ + go clean ./... + git gc --aggressive + +ci: ## run test like travis-ci does, requires docker + docker run --rm \ + -v $(PWD):/go/src/github.com/client9/misspell \ + -w /go/src/github.com/client9/misspell \ + ${CONTAINER} \ + make build falsepositives + +docker-build: ## build a docker test image + docker build -t ${CONTAINER} . + +docker-pull: ## pull latest test image + docker pull ${CONTAINER} + +docker-console: ## log into the test image + docker run --rm -it \ + -v $(PWD):/go/src/github.com/client9/misspell \ + -w /go/src/github.com/client9/misspell \ + ${CONTAINER} sh + +.git/hooks/pre-commit: scripts/pre-commit.sh + cp -f scripts/pre-commit.sh .git/hooks/pre-commit +.git/hooks/commit-msg: scripts/commit-msg.sh + cp -f scripts/commit-msg.sh .git/hooks/commit-msg +hooks: .git/hooks/pre-commit .git/hooks/commit-msg ## install git precommit hooks + +.PHONY: help ci console docker-build bench + +# https://www.client9.com/self-documenting-makefiles/ +help: + @awk -F ':|##' '/^[^\t].+?:.*?##/ {\ + printf "\033[36m%-30s\033[0m %s\n", $$1, $$NF \ + }' $(MAKEFILE_LIST) +.DEFAULT_GOAL=help +.PHONY=help + diff --git a/vendor/github.com/golangci/misspell/README.md b/vendor/github.com/golangci/misspell/README.md new file mode 100644 index 000000000..5b68af04d --- /dev/null +++ b/vendor/github.com/golangci/misspell/README.md @@ -0,0 +1,424 @@ +[![Build Status](https://travis-ci.org/client9/misspell.svg?branch=master)](https://travis-ci.org/client9/misspell) [![Go Report Card](https://goreportcard.com/badge/github.com/client9/misspell)](https://goreportcard.com/report/github.com/client9/misspell) [![GoDoc](https://godoc.org/github.com/client9/misspell?status.svg)](https://godoc.org/github.com/client9/misspell) [![Coverage](http://gocover.io/_badge/github.com/client9/misspell)](http://gocover.io/github.com/client9/misspell) [![license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://raw.githubusercontent.com/client9/misspell/master/LICENSE) + +Correct commonly misspelled English words... quickly. + +### Install + + +If you just want a binary and to start using `misspell`: + +``` +curl -L -o ./install-misspell.sh https://git.io/misspell +sh ./install-misspell.sh +``` + + +Both will install as `./bin/misspell`. You can adjust the download location using the `-b` flag. File a ticket if you want another platform supported. + + +If you use [Go](https://golang.org/), the best way to run `misspell` is by using [gometalinter](#gometalinter). Otherwise, install `misspell` the old-fashioned way: + +``` +go get -u github.com/client9/misspell/cmd/misspell +``` + +and misspell will be in your `GOPATH` + + +Also if you like to live dangerously, one could do + +```bash +curl -L https://git.io/misspell | bash +``` + +### Usage + + +```bash +$ misspell all.html your.txt important.md files.go +your.txt:42:10 found "langauge" a misspelling of "language" + +# ^ file, line, column +``` + +``` +$ misspell -help +Usage of misspell: + -debug + Debug matching, very slow + -error + Exit with 2 if misspelling found + -f string + 'csv', 'sqlite3' or custom Golang template for output + -i string + ignore the following corrections, comma separated + -j int + Number of workers, 0 = number of CPUs + -legal + Show legal information and exit + -locale string + Correct spellings using locale perferances for US or UK. Default is to use a neutral variety of English. Setting locale to US will correct the British spelling of 'colour' to 'color' + -o string + output file or [stderr|stdout|] (default "stdout") + -q Do not emit misspelling output + -source string + Source mode: auto=guess, go=golang source, text=plain or markdown-like text (default "auto") + -w Overwrite file with corrections (default is just to display) +``` + +## FAQ + +* [Automatic Corrections](#correct) +* [Converting UK spellings to US](#locale) +* [Using pipes and stdin](#stdin) +* [Golang special support](#golang) +* [gometalinter support](#gometalinter) +* [CSV Output](#csv) +* [Using SQLite3](#sqlite) +* [Changing output format](#output) +* [Checking a folder recursively](#recursive) +* [Performance](#performance) +* [Known Issues](#issues) +* [Debugging](#debug) +* [False Negatives and missing words](#missing) +* [Origin of Word Lists](#words) +* [Software License](#license) +* [Problem statement](#problem) +* [Other spelling correctors](#others) +* [Other ideas](#otherideas) + + +### How can I make the corrections automatically? + +Just add the `-w` flag! + +``` +$ misspell -w all.html your.txt important.md files.go +your.txt:9:21:corrected "langauge" to "language" + +# ^ File is rewritten only if a misspelling is found +``` + + +### How do I convert British spellings to American (or vice-versa)? + +Add the `-locale US` flag! + +```bash +$ misspell -locale US important.txt +important.txt:10:20 found "colour" a misspelling of "color" +``` + +Add the `-locale UK` flag! + +```bash +$ echo "My favorite color is blue" | misspell -locale UK +stdin:1:3:found "favorite color" a misspelling of "favourite colour" +``` + +Help is appreciated as I'm neither British nor an +expert in the English language. + + +### How do you check an entire folder recursively? + +Just list a directory you'd like to check + +```bash +misspell . +misspell aDirectory anotherDirectory aFile +``` + +You can also run misspell recursively using the following shell tricks: + +```bash +misspell directory/**/* +``` + +or + +```bash +find . -type f | xargs misspell +``` + +You can select a type of file as well. The following examples selects all `.txt` files that are *not* in the `vendor` directory: + +```bash +find . -type f -name '*.txt' | grep -v vendor/ | xargs misspell -error +``` + + +### Can I use pipes or `stdin` for input? + +Yes! + +Print messages to `stderr` only: + +```bash +$ echo "zeebra" | misspell +stdin:1:0:found "zeebra" a misspelling of "zebra" +``` + +Print messages to `stderr`, and corrected text to `stdout`: + +```bash +$ echo "zeebra" | misspell -w +stdin:1:0:corrected "zeebra" to "zebra" +zebra +``` + +Only print the corrected text to `stdout`: + +```bash +$ echo "zeebra" | misspell -w -q +zebra +``` + + +### Are there special rules for golang source files? + +Yes! If the file ends in `.go`, then misspell will only check spelling in +comments. + +If you want to force a file to be checked as a golang source, use `-source=go` +on the command line. Conversely, you can check a golang source as if it were +pure text by using `-source=text`. You might want to do this since many +variable names have misspellings in them! + +### Can I check only-comments in other other programming languages? + +I'm told the using `-source=go` works well for ruby, javascript, java, c and +c++. + +It doesn't work well for python and bash. + + +### Does this work with gometalinter? + +[gometalinter](https://github.com/alecthomas/gometalinter) runs +multiple golang linters. Starting on [2016-06-12](https://github.com/alecthomas/gometalinter/pull/134) +gometalinter supports `misspell` natively but it is disabled by default. + +```bash +# update your copy of gometalinter +go get -u github.com/alecthomas/gometalinter + +# install updates and misspell +gometalinter --install --update +``` + +To use, just enable `misspell` + +``` +gometalinter --enable misspell ./... +``` + +Note that gometalinter only checks golang files, and uses the default options +of `misspell` + +You may wish to run this on your plaintext (.txt) and/or markdown files too. + + + +### How Can I Get CSV Output? + +Using `-f csv`, the output is standard comma-seprated values with headers in the first row. + +``` +misspell -f csv * +file,line,column,typo,corrected +"README.md",9,22,langauge,language +"README.md",47,25,langauge,language +``` + + +### How can I export to SQLite3? + +Using `-f sqlite`, the output is a [sqlite3](https://www.sqlite.org/index.html) dump-file. + +```bash +$ misspell -f sqlite * > /tmp/misspell.sql +$ cat /tmp/misspell.sql + +PRAGMA foreign_keys=OFF; +BEGIN TRANSACTION; +CREATE TABLE misspell( + "file" TEXT, + "line" INTEGER,i + "column" INTEGER,i + "typo" TEXT, + "corrected" TEXT +); +INSERT INTO misspell VALUES("install.txt",202,31,"immediatly","immediately"); +# etc... +COMMIT; +``` + +```bash +$ sqlite3 -init /tmp/misspell.sql :memory: 'select count(*) from misspell' +1 +``` + +With some tricks you can directly pipe output to sqlite3 by using `-init /dev/stdin`: + +``` +misspell -f sqlite * | sqlite3 -init /dev/stdin -column -cmd '.width 60 15' ':memory' \ + 'select substr(file,35),typo,count(*) as count from misspell group by file, typo order by count desc;' +``` + + +### How can I ignore rules? + +Using the `-i "comma,separated,rules"` flag you can specify corrections to ignore. + +For example, if you were to run `misspell -w -error -source=text` against document that contains the string `Guy Finkelshteyn Braswell`, misspell would change the text to `Guy Finkelstheyn Bras well`. You can then +determine the rules to ignore by reverting the change and running the with the `-debug` flag. You can then see +that the corrections were `htey -> they` and `aswell -> as well`. To ignore these two rules, you add `-i "htey,aswell"` to +your command. With debug mode on, you can see it print the corrections, but it will no longer make them. + + +### How can I change the output format? + +Using the `-f template` flag you can pass in a +[golang text template](https://golang.org/pkg/text/template/) to format the output. + +One can use `printf "%q" VALUE` to safely quote a value. + +The default template is compatible with [gometalinter](https://github.com/alecthomas/gometalinter) +``` +{{ .Filename }}:{{ .Line }}:{{ .Column }}:corrected {{ printf "%q" .Original }} to "{{ printf "%q" .Corrected }}" +``` + +To just print probable misspellings: + +``` +-f '{{ .Original }}' +``` + + +### What problem does this solve? + +This corrects commonly misspelled English words in computer source +code, and other text-based formats (`.txt`, `.md`, etc). + +It is designed to run quickly so it can be +used as a [pre-commit hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) +with minimal burden on the developer. + +It does not work with binary formats (e.g. Word, etc). + +It is not a complete spell-checking program nor a grammar checker. + + +### What are other misspelling correctors and what's wrong with them? + +Some other misspelling correctors: + +* https://github.com/vlajos/misspell_fixer +* https://github.com/lyda/misspell-check +* https://github.com/lucasdemarchi/codespell + +They all work but had problems that prevented me from using them at scale: + +* slow, all of the above check one misspelling at a time (i.e. linear) using regexps +* not MIT/Apache2 licensed (or equivalent) +* have dependencies that don't work for me (python3, bash, linux sed, etc) +* don't understand American vs. British English and sometimes makes unwelcome "corrections" + +That said, they might be perfect for you and many have more features +than this project! + + +### How fast is it? + +Misspell is easily 100x to 1000x faster than other spelling correctors. You +should be able to check and correct 1000 files in under 250ms. + +This uses the mighty power of golang's +[strings.Replacer](https://golang.org/pkg/strings/#Replacer) which is +a implementation or variation of the +[Aho–Corasick algorithm](https://en.wikipedia.org/wiki/Aho–Corasick_algorithm). +This makes multiple substring matches *simultaneously*. + +In addition this uses multiple CPU cores to work on multiple files. + + +### What problems does it have? + +Unlike the other projects, this doesn't know what a "word" is. There may be +more false positives and false negatives due to this. On the other hand, it +sometimes catches things others don't. + +Either way, please file bugs and we'll fix them! + +Since it operates in parallel to make corrections, it can be non-obvious to +determine exactly what word was corrected. + + +### It's making mistakes. How can I debug? + +Run using `-debug` flag on the file you want. It should then print what word +it is trying to correct. Then [file a +bug](https://github.com/client9/misspell/issues) describing the problem. +Thanks! + + +### Why is it making mistakes or missing items in golang files? + +The matching function is *case-sensitive*, so variable names that are multiple +worlds either in all-upper or all-lower case sometimes can cause false +positives. For instance a variable named `bodyreader` could trigger a false +positive since `yrea` is in the middle that could be corrected to `year`. +Other problems happen if the variable name uses a English contraction that +should use an apostrophe. The best way of fixing this is to use the +[Effective Go naming +conventions](https://golang.org/doc/effective_go.html#mixed-caps) and use +[camelCase](https://en.wikipedia.org/wiki/CamelCase) for variable names. You +can check your code using [golint](https://github.com/golang/lint) + + +### What license is this? + +The main code is [MIT](https://github.com/client9/misspell/blob/master/LICENSE). + +Misspell also makes uses of the Golang standard library and contains a modified version of Golang's [strings.Replacer](https://golang.org/pkg/strings/#Replacer) +which are covered under a [BSD License](https://github.com/golang/go/blob/master/LICENSE). Type `misspell -legal` for more details or see [legal.go](https://github.com/client9/misspell/blob/master/legal.go) + + +### Where do the word lists come from? + +It started with a word list from +[Wikipedia](https://en.wikipedia.org/wiki/Wikipedia:Lists_of_common_misspellings/For_machines). +Unfortunately, this list had to be highly edited as many of the words are +obsolete or based from mistakes on mechanical typewriters (I'm guessing). + +Additional words were added based on actually mistakes seen in +the wild (meaning self-generated). + +Variations of UK and US spellings are based on many sources including: + +* http://www.tysto.com/uk-us-spelling-list.html (with heavy editing, many are incorrect) +* http://www.oxforddictionaries.com/us/words/american-and-british-spelling-american (excellent site but incomplete) +* Diffing US and UK [scowl dictionaries](http://wordlist.aspell.net) + +American English is more accepting of spelling variations than is British +English, so "what is American or not" is subject to opinion. Corrections and help welcome. + + +### What are some other enhancements that could be done? + +Here's some ideas for enhancements: + +*Capitalization of proper nouns* could be done (e.g. weekday and month names, country names, language names) + +*Opinionated US spellings* US English has a number of words with alternate +spellings. Think [adviser vs. +advisor](http://grammarist.com/spelling/adviser-advisor/). While "advisor" is not wrong, the opinionated US +locale would correct "advisor" to "adviser". + +*Versioning* Some type of versioning is needed so reporting mistakes and errors is easier. + +*Feedback* Mistakes would be sent to some server for agregation and feedback review. + +*Contractions and Apostrophes* This would optionally correct "isnt" to +"isn't", etc. diff --git a/vendor/github.com/golangci/misspell/RELEASE-HOWTO.md b/vendor/github.com/golangci/misspell/RELEASE-HOWTO.md new file mode 100644 index 000000000..55b52d962 --- /dev/null +++ b/vendor/github.com/golangci/misspell/RELEASE-HOWTO.md @@ -0,0 +1,38 @@ +# Release HOWTO + +since I forget. + + +1. Review existing tags and pick new release number + + ```sh + git tag + ``` + +2. Tag locally + + ```sh + git tag -a v0.1.0 -m "First release" + ``` + + If things get screwed up, delete the tag with + + ```sh + git tag -d v0.1.0 + ``` + +3. Test goreleaser + + TODO: how to install goreleaser + + ```sh + ./scripts/goreleaser-dryrun.sh + ``` + +4. Push + + ```bash + git push origin v0.1.0 + ``` + +5. Verify release and edit notes. See https://github.com/client9/misspell/releases diff --git a/vendor/github.com/golangci/misspell/ascii.go b/vendor/github.com/golangci/misspell/ascii.go new file mode 100644 index 000000000..1430718d6 --- /dev/null +++ b/vendor/github.com/golangci/misspell/ascii.go @@ -0,0 +1,62 @@ +package misspell + +// ByteToUpper converts an ascii byte to upper cases +// Uses a branchless algorithm +func ByteToUpper(x byte) byte { + b := byte(0x80) | x + c := b - byte(0x61) + d := ^(b - byte(0x7b)) + e := (c & d) & (^x & 0x7f) + return x - (e >> 2) +} + +// ByteToLower converts an ascii byte to lower case +// uses a branchless algorithm +func ByteToLower(eax byte) byte { + ebx := eax&byte(0x7f) + byte(0x25) + ebx = ebx&byte(0x7f) + byte(0x1a) + ebx = ((ebx & ^eax) >> 2) & byte(0x20) + return eax + ebx +} + +// ByteEqualFold does ascii compare, case insensitive +func ByteEqualFold(a, b byte) bool { + return a == b || ByteToLower(a) == ByteToLower(b) +} + +// StringEqualFold ASCII case-insensitive comparison +// golang toUpper/toLower for both bytes and strings +// appears to be Unicode based which is super slow +// based from https://codereview.appspot.com/5180044/patch/14007/21002 +func StringEqualFold(s1, s2 string) bool { + if len(s1) != len(s2) { + return false + } + for i := 0; i < len(s1); i++ { + c1 := s1[i] + c2 := s2[i] + // c1 & c2 + if c1 != c2 { + c1 |= 'a' - 'A' + c2 |= 'a' - 'A' + if c1 != c2 || c1 < 'a' || c1 > 'z' { + return false + } + } + } + return true +} + +// StringHasPrefixFold is similar to strings.HasPrefix but comparison +// is done ignoring ASCII case. +// / +func StringHasPrefixFold(s1, s2 string) bool { + // prefix is bigger than input --> false + if len(s1) < len(s2) { + return false + } + if len(s1) == len(s2) { + return StringEqualFold(s1, s2) + } + return StringEqualFold(s1[:len(s2)], s2) +} diff --git a/vendor/github.com/golangci/misspell/case.go b/vendor/github.com/golangci/misspell/case.go new file mode 100644 index 000000000..2ea3850df --- /dev/null +++ b/vendor/github.com/golangci/misspell/case.go @@ -0,0 +1,59 @@ +package misspell + +import ( + "strings" +) + +// WordCase is an enum of various word casing styles +type WordCase int + +// Various WordCase types.. likely to be not correct +const ( + CaseUnknown WordCase = iota + CaseLower + CaseUpper + CaseTitle +) + +// CaseStyle returns what case style a word is in +func CaseStyle(word string) WordCase { + upperCount := 0 + lowerCount := 0 + + // this iterates over RUNES not BYTES + for i := 0; i < len(word); i++ { + ch := word[i] + switch { + case ch >= 'a' && ch <= 'z': + lowerCount++ + case ch >= 'A' && ch <= 'Z': + upperCount++ + } + } + + switch { + case upperCount != 0 && lowerCount == 0: + return CaseUpper + case upperCount == 0 && lowerCount != 0: + return CaseLower + case upperCount == 1 && lowerCount > 0 && word[0] >= 'A' && word[0] <= 'Z': + return CaseTitle + } + return CaseUnknown +} + +// CaseVariations returns +// If AllUpper or First-Letter-Only is upcased: add the all upper case version +// If AllLower, add the original, the title and upcase forms +// If Mixed, return the original, and the all upcase form +// +func CaseVariations(word string, style WordCase) []string { + switch style { + case CaseLower: + return []string{word, strings.ToUpper(word[0:1]) + word[1:], strings.ToUpper(word)} + case CaseUpper: + return []string{strings.ToUpper(word)} + default: + return []string{word, strings.ToUpper(word)} + } +} diff --git a/vendor/github.com/golangci/misspell/goreleaser.yml b/vendor/github.com/golangci/misspell/goreleaser.yml new file mode 100644 index 000000000..560cb3810 --- /dev/null +++ b/vendor/github.com/golangci/misspell/goreleaser.yml @@ -0,0 +1,38 @@ +# goreleaser.yml +# https://github.com/goreleaser/goreleaser + +project_name: misspell + +builds: + - + main: cmd/misspell/main.go + binary: misspell + ldflags: -s -w -X main.version={{.Version}} + goos: + - darwin + - linux + - windows + goarch: + - amd64 + env: + - CGO_ENABLED=0 + ignore: + - goos: darwin + goarch: 386 + - goos: windows + goarch: 386 + +archive: + name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + replacements: + amd64: 64bit + 386: 32bit + darwin: mac + files: + - none* + +checksum: + name_template: "{{ .ProjectName }}_{{ .Version }}_checksums.txt" + +snapshot: + name_template: "SNAPSHOT-{{.Commit}}" diff --git a/vendor/github.com/golangci/misspell/install-misspell.sh b/vendor/github.com/golangci/misspell/install-misspell.sh new file mode 100644 index 000000000..e24a84a20 --- /dev/null +++ b/vendor/github.com/golangci/misspell/install-misspell.sh @@ -0,0 +1,362 @@ +#!/bin/sh +set -e +# Code generated by godownloader. DO NOT EDIT. +# + +usage() { + this=$1 + cat </dev/null +} +echoerr() { + echo "$@" 1>&2 +} +log_prefix() { + echo "$0" +} +_logp=6 +log_set_priority() { + _logp="$1" +} +log_priority() { + if test -z "$1"; then + echo "$_logp" + return + fi + [ "$1" -ge "$_logp" ] +} +log_debug() { + log_priority 7 && echoerr "$(log_prefix)" "DEBUG" "$@" +} +log_info() { + log_priority 6 && echoerr "$(log_prefix)" "INFO" "$@" +} +log_err() { + log_priority 3 && echoerr "$(log_prefix)" "ERR" "$@" +} +log_crit() { + log_priority 2 && echoerr "$(log_prefix)" "CRIT" "$@" +} +uname_os() { + os=$(uname -s | tr '[:upper:]' '[:lower:]') + case "$os" in + msys_nt) os="windows" ;; + esac + echo "$os" +} +uname_arch() { + arch=$(uname -m) + case $arch in + x86_64) arch="amd64" ;; + x86) arch="386" ;; + i686) arch="386" ;; + i386) arch="386" ;; + aarch64) arch="arm64" ;; + armv5*) arch="arm5" ;; + armv6*) arch="arm6" ;; + armv7*) arch="arm7" ;; + esac + echo ${arch} +} +uname_os_check() { + os=$(uname_os) + case "$os" in + darwin) return 0 ;; + dragonfly) return 0 ;; + freebsd) return 0 ;; + linux) return 0 ;; + android) return 0 ;; + nacl) return 0 ;; + netbsd) return 0 ;; + openbsd) return 0 ;; + plan9) return 0 ;; + solaris) return 0 ;; + windows) return 0 ;; + esac + log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib" + return 1 +} +uname_arch_check() { + arch=$(uname_arch) + case "$arch" in + 386) return 0 ;; + amd64) return 0 ;; + arm64) return 0 ;; + armv5) return 0 ;; + armv6) return 0 ;; + armv7) return 0 ;; + ppc64) return 0 ;; + ppc64le) return 0 ;; + mips) return 0 ;; + mipsle) return 0 ;; + mips64) return 0 ;; + mips64le) return 0 ;; + s390x) return 0 ;; + amd64p32) return 0 ;; + esac + log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib" + return 1 +} +untar() { + tarball=$1 + case "${tarball}" in + *.tar.gz | *.tgz) tar -xzf "${tarball}" ;; + *.tar) tar -xf "${tarball}" ;; + *.zip) unzip "${tarball}" ;; + *) + log_err "untar unknown archive format for ${tarball}" + return 1 + ;; + esac +} +mktmpdir() { + test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" + mkdir -p "${TMPDIR}" + echo "${TMPDIR}" +} +http_download() { + local_file=$1 + source_url=$2 + header=$3 + headerflag='' + destflag='' + if is_command curl; then + cmd='curl --fail -sSL' + destflag='-o' + headerflag='-H' + elif is_command wget; then + cmd='wget -q' + destflag='-O' + headerflag='--header' + else + log_crit "http_download unable to find wget or curl" + return 1 + fi + if [ -z "$header" ]; then + $cmd $destflag "$local_file" "$source_url" + else + $cmd $headerflag "$header" $destflag "$local_file" "$source_url" + fi +} +github_api() { + local_file=$1 + source_url=$2 + header="" + case "$source_url" in + https://api.github.com*) + test -z "$GITHUB_TOKEN" || header="Authorization: token $GITHUB_TOKEN" + ;; + esac + http_download "$local_file" "$source_url" "$header" +} +github_last_release() { + owner_repo=$1 + version=$2 + test -z "$version" && version="latest" + giturl="https://github.com/${owner_repo}/releases/${version}" + json=$(http_download "-" "$giturl" "Accept:application/json") + version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//') + test -z "$version" && return 1 + echo "$version" +} +hash_sha256() { + TARGET=${1:-/dev/stdin} + if is_command gsha256sum; then + hash=$(gsha256sum "$TARGET") || return 1 + echo "$hash" | cut -d ' ' -f 1 + elif is_command sha256sum; then + hash=$(sha256sum "$TARGET") || return 1 + echo "$hash" | cut -d ' ' -f 1 + elif is_command shasum; then + hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1 + echo "$hash" | cut -d ' ' -f 1 + elif is_command openssl; then + hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1 + echo "$hash" | cut -d ' ' -f a + else + log_crit "hash_sha256 unable to find command to compute sha-256 hash" + return 1 + fi +} +hash_sha256_verify() { + TARGET=$1 + checksums=$2 + if [ -z "$checksums" ]; then + log_err "hash_sha256_verify checksum file not specified in arg2" + return 1 + fi + BASENAME=${TARGET##*/} + want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1) + if [ -z "$want" ]; then + log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'" + return 1 + fi + got=$(hash_sha256 "$TARGET") + if [ "$want" != "$got" ]; then + log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got" + return 1 + fi +} +cat /dev/null < 50000 { + fin, err := os.Open(filename) + if err != nil { + return "", fmt.Errorf("Unable to open large file %q: %s", filename, err) + } + defer fin.Close() + buf := make([]byte, 512) + _, err = io.ReadFull(fin, buf) + if err != nil { + return "", fmt.Errorf("Unable to read 512 bytes from %q: %s", filename, err) + } + if !isTextFile(buf) { + return "", nil + } + + // set so we don't double check this file + isText = true + } + + // read in whole file + raw, err := ioutil.ReadFile(filename) + if err != nil { + return "", fmt.Errorf("Unable to read all %q: %s", filename, err) + } + + if !isText && !isTextFile(raw) { + return "", nil + } + return string(raw), nil +} diff --git a/vendor/github.com/golangci/misspell/notwords.go b/vendor/github.com/golangci/misspell/notwords.go new file mode 100644 index 000000000..06d0d5a5a --- /dev/null +++ b/vendor/github.com/golangci/misspell/notwords.go @@ -0,0 +1,85 @@ +package misspell + +import ( + "bytes" + "regexp" + "strings" +) + +var ( + reEmail = regexp.MustCompile(`[a-zA-Z0-9_.%+-]+@[a-zA-Z0-9-.]+\.[a-zA-Z]{2,6}[^a-zA-Z]`) + reHost = regexp.MustCompile(`[a-zA-Z0-9-.]+\.[a-zA-Z]+`) + reBackslash = regexp.MustCompile(`\\[a-z]`) +) + +// RemovePath attempts to strip away embedded file system paths, e.g. +// /foo/bar or /static/myimg.png +// +// TODO: windows style +// +func RemovePath(s string) string { + out := bytes.Buffer{} + var idx int + for len(s) > 0 { + if idx = strings.IndexByte(s, '/'); idx == -1 { + out.WriteString(s) + break + } + + if idx > 0 { + idx-- + } + + var chclass string + switch s[idx] { + case '/', ' ', '\n', '\t', '\r': + chclass = " \n\r\t" + case '[': + chclass = "]\n" + case '(': + chclass = ")\n" + default: + out.WriteString(s[:idx+2]) + s = s[idx+2:] + continue + } + + endx := strings.IndexAny(s[idx+1:], chclass) + if endx != -1 { + out.WriteString(s[:idx+1]) + out.Write(bytes.Repeat([]byte{' '}, endx)) + s = s[idx+endx+1:] + } else { + out.WriteString(s) + break + } + } + return out.String() +} + +// replaceWithBlanks returns a string with the same number of spaces as the input +func replaceWithBlanks(s string) string { + return strings.Repeat(" ", len(s)) +} + +// RemoveEmail remove email-like strings, e.g. "nickg+junk@xfoobar.com", "nickg@xyz.abc123.biz" +func RemoveEmail(s string) string { + return reEmail.ReplaceAllStringFunc(s, replaceWithBlanks) +} + +// RemoveHost removes host-like strings "foobar.com" "abc123.fo1231.biz" +func RemoveHost(s string) string { + return reHost.ReplaceAllStringFunc(s, replaceWithBlanks) +} + +// RemoveBackslashEscapes removes characters that are preceeded by a backslash +// commonly found in printf format stringd "\nto" +func removeBackslashEscapes(s string) string { + return reBackslash.ReplaceAllStringFunc(s, replaceWithBlanks) +} + +// RemoveNotWords blanks out all the not words +func RemoveNotWords(s string) string { + // do most selective/specific first + return removeBackslashEscapes(RemoveHost(RemoveEmail(RemovePath(StripURL(s))))) +} diff --git a/vendor/github.com/golangci/misspell/replace.go b/vendor/github.com/golangci/misspell/replace.go new file mode 100644 index 000000000..a99bbcc58 --- /dev/null +++ b/vendor/github.com/golangci/misspell/replace.go @@ -0,0 +1,246 @@ +package misspell + +import ( + "bufio" + "bytes" + "io" + "regexp" + "strings" + "text/scanner" +) + +func max(x, y int) int { + if x > y { + return x + } + return y +} + +func inArray(haystack []string, needle string) bool { + for _, word := range haystack { + if needle == word { + return true + } + } + return false +} + +var wordRegexp = regexp.MustCompile(`[a-zA-Z0-9']+`) + +// Diff is datastructure showing what changed in a single line +type Diff struct { + Filename string + FullLine string + Line int + Column int + Original string + Corrected string +} + +// Replacer is the main struct for spelling correction +type Replacer struct { + Replacements []string + Debug bool + engine *StringReplacer + corrected map[string]string +} + +// New creates a new default Replacer using the main rule list +func New() *Replacer { + r := Replacer{ + Replacements: DictMain, + } + r.Compile() + return &r +} + +// RemoveRule deletes existings rules. +// TODO: make inplace to save memory +func (r *Replacer) RemoveRule(ignore []string) { + newwords := make([]string, 0, len(r.Replacements)) + for i := 0; i < len(r.Replacements); i += 2 { + if inArray(ignore, r.Replacements[i]) { + continue + } + newwords = append(newwords, r.Replacements[i:i+2]...) + } + r.engine = nil + r.Replacements = newwords +} + +// AddRuleList appends new rules. +// Input is in the same form as Strings.Replacer: [ old1, new1, old2, new2, ....] +// Note: does not check for duplictes +func (r *Replacer) AddRuleList(additions []string) { + r.engine = nil + r.Replacements = append(r.Replacements, additions...) +} + +// Compile compiles the rules. Required before using the Replace functions +func (r *Replacer) Compile() { + + r.corrected = make(map[string]string, len(r.Replacements)/2) + for i := 0; i < len(r.Replacements); i += 2 { + r.corrected[r.Replacements[i]] = r.Replacements[i+1] + } + r.engine = NewStringReplacer(r.Replacements...) +} + +/* +line1 and line2 are different +extract words from each line1 + +replace word -> newword +if word == new-word + continue +if new-word in list of replacements + continue +new word not original, and not in list of replacements + some substring got mixed up. UNdo +*/ +func (r *Replacer) recheckLine(s string, lineNum int, buf io.Writer, next func(Diff)) { + first := 0 + redacted := RemoveNotWords(s) + + idx := wordRegexp.FindAllStringIndex(redacted, -1) + for _, ab := range idx { + word := s[ab[0]:ab[1]] + newword := r.engine.Replace(word) + if newword == word { + // no replacement done + continue + } + + // ignore camelCase words + // https://github.com/client9/misspell/issues/113 + if CaseStyle(word) == CaseUnknown { + continue + } + + if StringEqualFold(r.corrected[strings.ToLower(word)], newword) { + // word got corrected into something we know + io.WriteString(buf, s[first:ab[0]]) + io.WriteString(buf, newword) + first = ab[1] + next(Diff{ + FullLine: s, + Line: lineNum, + Original: word, + Corrected: newword, + Column: ab[0], + }) + continue + } + // Word got corrected into something unknown. Ignore it + } + io.WriteString(buf, s[first:]) +} + +// ReplaceGo is a specialized routine for correcting Golang source +// files. Currently only checks comments, not identifiers for +// spelling. +func (r *Replacer) ReplaceGo(input string) (string, []Diff) { + var s scanner.Scanner + s.Init(strings.NewReader(input)) + s.Mode = scanner.ScanIdents | scanner.ScanFloats | scanner.ScanChars | scanner.ScanStrings | scanner.ScanRawStrings | scanner.ScanComments + lastPos := 0 + output := "" +Loop: + for { + switch s.Scan() { + case scanner.Comment: + origComment := s.TokenText() + newComment := r.engine.Replace(origComment) + + if origComment != newComment { + // s.Pos().Offset is the end of the current token + // subtract len(origComment) to get the start of the token + offset := s.Pos().Offset + output = output + input[lastPos:offset-len(origComment)] + newComment + lastPos = offset + } + case scanner.EOF: + break Loop + } + } + + if lastPos == 0 { + // no changes, no copies + return input, nil + } + if lastPos < len(input) { + output = output + input[lastPos:] + } + diffs := make([]Diff, 0, 8) + buf := bytes.NewBuffer(make([]byte, 0, max(len(input), len(output))+100)) + // faster that making a bytes.Buffer and bufio.ReadString + outlines := strings.SplitAfter(output, "\n") + inlines := strings.SplitAfter(input, "\n") + for i := 0; i < len(inlines); i++ { + if inlines[i] == outlines[i] { + buf.WriteString(outlines[i]) + continue + } + r.recheckLine(inlines[i], i+1, buf, func(d Diff) { + diffs = append(diffs, d) + }) + } + + return buf.String(), diffs + +} + +// Replace is corrects misspellings in input, returning corrected version +// along with a list of diffs. +func (r *Replacer) Replace(input string) (string, []Diff) { + output := r.engine.Replace(input) + if input == output { + return input, nil + } + diffs := make([]Diff, 0, 8) + buf := bytes.NewBuffer(make([]byte, 0, max(len(input), len(output))+100)) + // faster that making a bytes.Buffer and bufio.ReadString + outlines := strings.SplitAfter(output, "\n") + inlines := strings.SplitAfter(input, "\n") + for i := 0; i < len(inlines); i++ { + if inlines[i] == outlines[i] { + buf.WriteString(outlines[i]) + continue + } + r.recheckLine(inlines[i], i+1, buf, func(d Diff) { + diffs = append(diffs, d) + }) + } + + return buf.String(), diffs +} + +// ReplaceReader applies spelling corrections to a reader stream. Diffs are +// emitted through a callback. +func (r *Replacer) ReplaceReader(raw io.Reader, w io.Writer, next func(Diff)) error { + var ( + err error + line string + lineNum int + ) + reader := bufio.NewReader(raw) + for err == nil { + lineNum++ + line, err = reader.ReadString('\n') + + // if it's EOF, then line has the last line + // don't like the check of err here and + // in for loop + if err != nil && err != io.EOF { + return err + } + // easily 5x faster than regexp+map + if line == r.engine.Replace(line) { + io.WriteString(w, line) + continue + } + // but it can be inaccurate, so we need to double check + r.recheckLine(line, lineNum, w, next) + } + return nil +} diff --git a/vendor/github.com/golangci/misspell/stringreplacer.go b/vendor/github.com/golangci/misspell/stringreplacer.go new file mode 100644 index 000000000..3151eceb7 --- /dev/null +++ b/vendor/github.com/golangci/misspell/stringreplacer.go @@ -0,0 +1,336 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package misspell + +import ( + "io" + // "log" + "strings" +) + +// StringReplacer replaces a list of strings with replacements. +// It is safe for concurrent use by multiple goroutines. +type StringReplacer struct { + r replacer +} + +// replacer is the interface that a replacement algorithm needs to implement. +type replacer interface { + Replace(s string) string + WriteString(w io.Writer, s string) (n int, err error) +} + +// NewStringReplacer returns a new Replacer from a list of old, new string pairs. +// Replacements are performed in order, without overlapping matches. +func NewStringReplacer(oldnew ...string) *StringReplacer { + if len(oldnew)%2 == 1 { + panic("strings.NewReplacer: odd argument count") + } + + return &StringReplacer{r: makeGenericReplacer(oldnew)} +} + +// Replace returns a copy of s with all replacements performed. +func (r *StringReplacer) Replace(s string) string { + return r.r.Replace(s) +} + +// WriteString writes s to w with all replacements performed. +func (r *StringReplacer) WriteString(w io.Writer, s string) (n int, err error) { + return r.r.WriteString(w, s) +} + +// trieNode is a node in a lookup trie for prioritized key/value pairs. Keys +// and values may be empty. For example, the trie containing keys "ax", "ay", +// "bcbc", "x" and "xy" could have eight nodes: +// +// n0 - +// n1 a- +// n2 .x+ +// n3 .y+ +// n4 b- +// n5 .cbc+ +// n6 x+ +// n7 .y+ +// +// n0 is the root node, and its children are n1, n4 and n6; n1's children are +// n2 and n3; n4's child is n5; n6's child is n7. Nodes n0, n1 and n4 (marked +// with a trailing "-") are partial keys, and nodes n2, n3, n5, n6 and n7 +// (marked with a trailing "+") are complete keys. +type trieNode struct { + // value is the value of the trie node's key/value pair. It is empty if + // this node is not a complete key. + value string + // priority is the priority (higher is more important) of the trie node's + // key/value pair; keys are not necessarily matched shortest- or longest- + // first. Priority is positive if this node is a complete key, and zero + // otherwise. In the example above, positive/zero priorities are marked + // with a trailing "+" or "-". + priority int + + // A trie node may have zero, one or more child nodes: + // * if the remaining fields are zero, there are no children. + // * if prefix and next are non-zero, there is one child in next. + // * if table is non-zero, it defines all the children. + // + // Prefixes are preferred over tables when there is one child, but the + // root node always uses a table for lookup efficiency. + + // prefix is the difference in keys between this trie node and the next. + // In the example above, node n4 has prefix "cbc" and n4's next node is n5. + // Node n5 has no children and so has zero prefix, next and table fields. + prefix string + next *trieNode + + // table is a lookup table indexed by the next byte in the key, after + // remapping that byte through genericReplacer.mapping to create a dense + // index. In the example above, the keys only use 'a', 'b', 'c', 'x' and + // 'y', which remap to 0, 1, 2, 3 and 4. All other bytes remap to 5, and + // genericReplacer.tableSize will be 5. Node n0's table will be + // []*trieNode{ 0:n1, 1:n4, 3:n6 }, where the 0, 1 and 3 are the remapped + // 'a', 'b' and 'x'. + table []*trieNode +} + +func (t *trieNode) add(key, val string, priority int, r *genericReplacer) { + if key == "" { + if t.priority == 0 { + t.value = val + t.priority = priority + } + return + } + + if t.prefix != "" { + // Need to split the prefix among multiple nodes. + var n int // length of the longest common prefix + for ; n < len(t.prefix) && n < len(key); n++ { + if t.prefix[n] != key[n] { + break + } + } + if n == len(t.prefix) { + t.next.add(key[n:], val, priority, r) + } else if n == 0 { + // First byte differs, start a new lookup table here. Looking up + // what is currently t.prefix[0] will lead to prefixNode, and + // looking up key[0] will lead to keyNode. + var prefixNode *trieNode + if len(t.prefix) == 1 { + prefixNode = t.next + } else { + prefixNode = &trieNode{ + prefix: t.prefix[1:], + next: t.next, + } + } + keyNode := new(trieNode) + t.table = make([]*trieNode, r.tableSize) + t.table[r.mapping[t.prefix[0]]] = prefixNode + t.table[r.mapping[key[0]]] = keyNode + t.prefix = "" + t.next = nil + keyNode.add(key[1:], val, priority, r) + } else { + // Insert new node after the common section of the prefix. + next := &trieNode{ + prefix: t.prefix[n:], + next: t.next, + } + t.prefix = t.prefix[:n] + t.next = next + next.add(key[n:], val, priority, r) + } + } else if t.table != nil { + // Insert into existing table. + m := r.mapping[key[0]] + if t.table[m] == nil { + t.table[m] = new(trieNode) + } + t.table[m].add(key[1:], val, priority, r) + } else { + t.prefix = key + t.next = new(trieNode) + t.next.add("", val, priority, r) + } +} + +func (r *genericReplacer) lookup(s string, ignoreRoot bool) (val string, keylen int, found bool) { + // Iterate down the trie to the end, and grab the value and keylen with + // the highest priority. + bestPriority := 0 + node := &r.root + n := 0 + for node != nil { + if node.priority > bestPriority && !(ignoreRoot && node == &r.root) { + bestPriority = node.priority + val = node.value + keylen = n + found = true + } + + if s == "" { + break + } + if node.table != nil { + index := r.mapping[ByteToLower(s[0])] + if int(index) == r.tableSize { + break + } + node = node.table[index] + s = s[1:] + n++ + } else if node.prefix != "" && StringHasPrefixFold(s, node.prefix) { + n += len(node.prefix) + s = s[len(node.prefix):] + node = node.next + } else { + break + } + } + return +} + +// genericReplacer is the fully generic algorithm. +// It's used as a fallback when nothing faster can be used. +type genericReplacer struct { + root trieNode + // tableSize is the size of a trie node's lookup table. It is the number + // of unique key bytes. + tableSize int + // mapping maps from key bytes to a dense index for trieNode.table. + mapping [256]byte +} + +func makeGenericReplacer(oldnew []string) *genericReplacer { + r := new(genericReplacer) + // Find each byte used, then assign them each an index. + for i := 0; i < len(oldnew); i += 2 { + key := strings.ToLower(oldnew[i]) + for j := 0; j < len(key); j++ { + r.mapping[key[j]] = 1 + } + } + + for _, b := range r.mapping { + r.tableSize += int(b) + } + + var index byte + for i, b := range r.mapping { + if b == 0 { + r.mapping[i] = byte(r.tableSize) + } else { + r.mapping[i] = index + index++ + } + } + // Ensure root node uses a lookup table (for performance). + r.root.table = make([]*trieNode, r.tableSize) + + for i := 0; i < len(oldnew); i += 2 { + r.root.add(strings.ToLower(oldnew[i]), oldnew[i+1], len(oldnew)-i, r) + } + return r +} + +type appendSliceWriter []byte + +// Write writes to the buffer to satisfy io.Writer. +func (w *appendSliceWriter) Write(p []byte) (int, error) { + *w = append(*w, p...) + return len(p), nil +} + +// WriteString writes to the buffer without string->[]byte->string allocations. +func (w *appendSliceWriter) WriteString(s string) (int, error) { + *w = append(*w, s...) + return len(s), nil +} + +type stringWriterIface interface { + WriteString(string) (int, error) +} + +type stringWriter struct { + w io.Writer +} + +func (w stringWriter) WriteString(s string) (int, error) { + return w.w.Write([]byte(s)) +} + +func getStringWriter(w io.Writer) stringWriterIface { + sw, ok := w.(stringWriterIface) + if !ok { + sw = stringWriter{w} + } + return sw +} + +func (r *genericReplacer) Replace(s string) string { + buf := make(appendSliceWriter, 0, len(s)) + r.WriteString(&buf, s) + return string(buf) +} + +func (r *genericReplacer) WriteString(w io.Writer, s string) (n int, err error) { + sw := getStringWriter(w) + var last, wn int + var prevMatchEmpty bool + for i := 0; i <= len(s); { + // Fast path: s[i] is not a prefix of any pattern. + if i != len(s) && r.root.priority == 0 { + index := int(r.mapping[ByteToLower(s[i])]) + if index == r.tableSize || r.root.table[index] == nil { + i++ + continue + } + } + + // Ignore the empty match iff the previous loop found the empty match. + val, keylen, match := r.lookup(s[i:], prevMatchEmpty) + prevMatchEmpty = match && keylen == 0 + if match { + orig := s[i : i+keylen] + switch CaseStyle(orig) { + case CaseUnknown: + // pretend we didn't match + // i++ + // continue + case CaseUpper: + val = strings.ToUpper(val) + case CaseLower: + val = strings.ToLower(val) + case CaseTitle: + if len(val) < 2 { + val = strings.ToUpper(val) + } else { + val = strings.ToUpper(val[:1]) + strings.ToLower(val[1:]) + } + } + wn, err = sw.WriteString(s[last:i]) + n += wn + if err != nil { + return + } + //log.Printf("%d: Going to correct %q with %q", i, s[i:i+keylen], val) + wn, err = sw.WriteString(val) + n += wn + if err != nil { + return + } + i += keylen + last = i + continue + } + i++ + } + if last != len(s) { + wn, err = sw.WriteString(s[last:]) + n += wn + } + return +} diff --git a/vendor/github.com/golangci/misspell/stringreplacer_test.gox b/vendor/github.com/golangci/misspell/stringreplacer_test.gox new file mode 100644 index 000000000..70da997f6 --- /dev/null +++ b/vendor/github.com/golangci/misspell/stringreplacer_test.gox @@ -0,0 +1,421 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package misspell_test + +import ( + "bytes" + "fmt" + "strings" + "testing" + + . "github.com/client9/misspell" +) + +var htmlEscaper = NewStringReplacer( + "&", "&", + "<", "<", + ">", ">", + `"`, """, + "'", "'", +) + +var htmlUnescaper = NewStringReplacer( + "&", "&", + "<", "<", + ">", ">", + """, `"`, + "'", "'", +) + +// The http package's old HTML escaping function. +func oldHTMLEscape(s string) string { + s = strings.Replace(s, "&", "&", -1) + s = strings.Replace(s, "<", "<", -1) + s = strings.Replace(s, ">", ">", -1) + s = strings.Replace(s, `"`, """, -1) + s = strings.Replace(s, "'", "'", -1) + return s +} + +var capitalLetters = NewStringReplacer("a", "A", "b", "B") + +// TestReplacer tests the replacer implementations. +func TestReplacer(t *testing.T) { + type testCase struct { + r *StringReplacer + in, out string + } + var testCases []testCase + + // str converts 0xff to "\xff". This isn't just string(b) since that converts to UTF-8. + str := func(b byte) string { + return string([]byte{b}) + } + var s []string + + // inc maps "\x00"->"\x01", ..., "a"->"b", "b"->"c", ..., "\xff"->"\x00". + for i := 0; i < 256; i++ { + s = append(s, str(byte(i)), str(byte(i+1))) + } + inc := NewStringReplacer(s...) + + // Test cases with 1-byte old strings, 1-byte new strings. + testCases = append(testCases, + testCase{capitalLetters, "brad", "BrAd"}, + testCase{capitalLetters, strings.Repeat("a", (32<<10)+123), strings.Repeat("A", (32<<10)+123)}, + testCase{capitalLetters, "", ""}, + + testCase{inc, "brad", "csbe"}, + testCase{inc, "\x00\xff", "\x01\x00"}, + testCase{inc, "", ""}, + + testCase{NewStringReplacer("a", "1", "a", "2"), "brad", "br1d"}, + ) + + // repeat maps "a"->"a", "b"->"bb", "c"->"ccc", ... + s = nil + for i := 0; i < 256; i++ { + n := i + 1 - 'a' + if n < 1 { + n = 1 + } + s = append(s, str(byte(i)), strings.Repeat(str(byte(i)), n)) + } + repeat := NewStringReplacer(s...) + + // Test cases with 1-byte old strings, variable length new strings. + testCases = append(testCases, + testCase{htmlEscaper, "No changes", "No changes"}, + testCase{htmlEscaper, "I <3 escaping & stuff", "I <3 escaping & stuff"}, + testCase{htmlEscaper, "&&&", "&&&"}, + testCase{htmlEscaper, "", ""}, + + testCase{repeat, "brad", "bbrrrrrrrrrrrrrrrrrradddd"}, + testCase{repeat, "abba", "abbbba"}, + testCase{repeat, "", ""}, + + testCase{NewStringReplacer("a", "11", "a", "22"), "brad", "br11d"}, + ) + + // The remaining test cases have variable length old strings. + + testCases = append(testCases, + testCase{htmlUnescaper, "&amp;", "&"}, + testCase{htmlUnescaper, "<b>HTML's neat</b>", "HTML's neat"}, + testCase{htmlUnescaper, "", ""}, + + testCase{NewStringReplacer("a", "1", "a", "2", "xxx", "xxx"), "brad", "br1d"}, + + testCase{NewStringReplacer("a", "1", "aa", "2", "aaa", "3"), "aaaa", "1111"}, + + testCase{NewStringReplacer("aaa", "3", "aa", "2", "a", "1"), "aaaa", "31"}, + ) + + // gen1 has multiple old strings of variable length. There is no + // overall non-empty common prefix, but some pairwise common prefixes. + gen1 := NewStringReplacer( + "aaa", "3[aaa]", + "aa", "2[aa]", + "a", "1[a]", + "i", "i", + "longerst", "most long", + "longer", "medium", + "long", "short", + "xx", "xx", + "x", "X", + "X", "Y", + "Y", "Z", + ) + testCases = append(testCases, + testCase{gen1, "fooaaabar", "foo3[aaa]b1[a]r"}, + testCase{gen1, "long, longerst, longer", "short, most long, medium"}, + testCase{gen1, "xxxxx", "xxxxX"}, + testCase{gen1, "XiX", "YiY"}, + testCase{gen1, "", ""}, + ) + + // gen2 has multiple old strings with no pairwise common prefix. + gen2 := NewStringReplacer( + "roses", "red", + "violets", "blue", + "sugar", "sweet", + ) + testCases = append(testCases, + testCase{gen2, "roses are red, violets are blue...", "red are red, blue are blue..."}, + testCase{gen2, "", ""}, + ) + + // gen3 has multiple old strings with an overall common prefix. + gen3 := NewStringReplacer( + "abracadabra", "poof", + "abracadabrakazam", "splat", + "abraham", "lincoln", + "abrasion", "scrape", + "abraham", "isaac", + ) + testCases = append(testCases, + testCase{gen3, "abracadabrakazam abraham", "poofkazam lincoln"}, + testCase{gen3, "abrasion abracad", "scrape abracad"}, + testCase{gen3, "abba abram abrasive", "abba abram abrasive"}, + testCase{gen3, "", ""}, + ) + + // foo{1,2,3,4} have multiple old strings with an overall common prefix + // and 1- or 2- byte extensions from the common prefix. + foo1 := NewStringReplacer( + "foo1", "A", + "foo2", "B", + "foo3", "C", + ) + foo2 := NewStringReplacer( + "foo1", "A", + "foo2", "B", + "foo31", "C", + "foo32", "D", + ) + foo3 := NewStringReplacer( + "foo11", "A", + "foo12", "B", + "foo31", "C", + "foo32", "D", + ) + foo4 := NewStringReplacer( + "foo12", "B", + "foo32", "D", + ) + testCases = append(testCases, + testCase{foo1, "fofoofoo12foo32oo", "fofooA2C2oo"}, + testCase{foo1, "", ""}, + + testCase{foo2, "fofoofoo12foo32oo", "fofooA2Doo"}, + testCase{foo2, "", ""}, + + testCase{foo3, "fofoofoo12foo32oo", "fofooBDoo"}, + testCase{foo3, "", ""}, + + testCase{foo4, "fofoofoo12foo32oo", "fofooBDoo"}, + testCase{foo4, "", ""}, + ) + + // genAll maps "\x00\x01\x02...\xfe\xff" to "[all]", amongst other things. + allBytes := make([]byte, 256) + for i := range allBytes { + allBytes[i] = byte(i) + } + allString := string(allBytes) + genAll := NewStringReplacer( + allString, "[all]", + "\xff", "[ff]", + "\x00", "[00]", + ) + testCases = append(testCases, + testCase{genAll, allString, "[all]"}, + testCase{genAll, "a\xff" + allString + "\x00", "a[ff][all][00]"}, + testCase{genAll, "", ""}, + ) + + // Test cases with empty old strings. + + blankToX1 := NewStringReplacer("", "X") + blankToX2 := NewStringReplacer("", "X", "", "") + blankHighPriority := NewStringReplacer("", "X", "o", "O") + blankLowPriority := NewStringReplacer("o", "O", "", "X") + blankNoOp1 := NewStringReplacer("", "") + blankNoOp2 := NewStringReplacer("", "", "", "A") + blankFoo := NewStringReplacer("", "X", "foobar", "R", "foobaz", "Z") + testCases = append(testCases, + testCase{blankToX1, "foo", "XfXoXoX"}, + testCase{blankToX1, "", "X"}, + + testCase{blankToX2, "foo", "XfXoXoX"}, + testCase{blankToX2, "", "X"}, + + testCase{blankHighPriority, "oo", "XOXOX"}, + testCase{blankHighPriority, "ii", "XiXiX"}, + testCase{blankHighPriority, "oiio", "XOXiXiXOX"}, + testCase{blankHighPriority, "iooi", "XiXOXOXiX"}, + testCase{blankHighPriority, "", "X"}, + + testCase{blankLowPriority, "oo", "OOX"}, + testCase{blankLowPriority, "ii", "XiXiX"}, + testCase{blankLowPriority, "oiio", "OXiXiOX"}, + testCase{blankLowPriority, "iooi", "XiOOXiX"}, + testCase{blankLowPriority, "", "X"}, + + testCase{blankNoOp1, "foo", "foo"}, + testCase{blankNoOp1, "", ""}, + + testCase{blankNoOp2, "foo", "foo"}, + testCase{blankNoOp2, "", ""}, + + testCase{blankFoo, "foobarfoobaz", "XRXZX"}, + testCase{blankFoo, "foobar-foobaz", "XRX-XZX"}, + testCase{blankFoo, "", "X"}, + ) + + // single string replacer + + abcMatcher := NewStringReplacer("abc", "[match]") + + testCases = append(testCases, + testCase{abcMatcher, "", ""}, + testCase{abcMatcher, "ab", "ab"}, + testCase{abcMatcher, "abc", "[match]"}, + testCase{abcMatcher, "abcd", "[match]d"}, + testCase{abcMatcher, "cabcabcdabca", "c[match][match]d[match]a"}, + ) + + // Issue 6659 cases (more single string replacer) + + noHello := NewStringReplacer("Hello", "") + testCases = append(testCases, + testCase{noHello, "Hello", ""}, + testCase{noHello, "Hellox", "x"}, + testCase{noHello, "xHello", "x"}, + testCase{noHello, "xHellox", "xx"}, + ) + + // No-arg test cases. + + nop := NewStringReplacer() + testCases = append(testCases, + testCase{nop, "abc", "abc"}, + testCase{nop, "", ""}, + ) + + // Run the test cases. + + for i, tc := range testCases { + if s := tc.r.Replace(tc.in); s != tc.out { + t.Errorf("%d. strings.Replace(%q) = %q, want %q", i, tc.in, s, tc.out) + } + var buf bytes.Buffer + n, err := tc.r.WriteString(&buf, tc.in) + if err != nil { + t.Errorf("%d. WriteString: %v", i, err) + continue + } + got := buf.String() + if got != tc.out { + t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tc.in, got, tc.out) + continue + } + if n != len(tc.out) { + t.Errorf("%d. WriteString(%q) wrote correct string but reported %d bytes; want %d (%q)", + i, tc.in, n, len(tc.out), tc.out) + } + } +} + +type errWriter struct{} + +func (errWriter) Write(p []byte) (n int, err error) { + return 0, fmt.Errorf("unwritable") +} + +func BenchmarkGenericNoMatch(b *testing.B) { + str := strings.Repeat("A", 100) + strings.Repeat("B", 100) + generic := NewStringReplacer("a", "A", "b", "B", "12", "123") // varying lengths forces generic + for i := 0; i < b.N; i++ { + generic.Replace(str) + } +} + +func BenchmarkGenericMatch1(b *testing.B) { + str := strings.Repeat("a", 100) + strings.Repeat("b", 100) + generic := NewStringReplacer("a", "A", "b", "B", "12", "123") + for i := 0; i < b.N; i++ { + generic.Replace(str) + } +} + +func BenchmarkGenericMatch2(b *testing.B) { + str := strings.Repeat("It's <b>HTML</b>!", 100) + for i := 0; i < b.N; i++ { + htmlUnescaper.Replace(str) + } +} + +func benchmarkSingleString(b *testing.B, pattern, text string) { + r := NewStringReplacer(pattern, "[match]") + b.SetBytes(int64(len(text))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + r.Replace(text) + } +} + +func BenchmarkSingleMaxSkipping(b *testing.B) { + benchmarkSingleString(b, strings.Repeat("b", 25), strings.Repeat("a", 10000)) +} + +func BenchmarkSingleLongSuffixFail(b *testing.B) { + benchmarkSingleString(b, "b"+strings.Repeat("a", 500), strings.Repeat("a", 1002)) +} + +func BenchmarkSingleMatch(b *testing.B) { + benchmarkSingleString(b, "abcdef", strings.Repeat("abcdefghijklmno", 1000)) +} + +func BenchmarkByteByteNoMatch(b *testing.B) { + str := strings.Repeat("A", 100) + strings.Repeat("B", 100) + for i := 0; i < b.N; i++ { + capitalLetters.Replace(str) + } +} + +func BenchmarkByteByteMatch(b *testing.B) { + str := strings.Repeat("a", 100) + strings.Repeat("b", 100) + for i := 0; i < b.N; i++ { + capitalLetters.Replace(str) + } +} + +func BenchmarkByteStringMatch(b *testing.B) { + str := "<" + strings.Repeat("a", 99) + strings.Repeat("b", 99) + ">" + for i := 0; i < b.N; i++ { + htmlEscaper.Replace(str) + } +} + +func BenchmarkHTMLEscapeNew(b *testing.B) { + str := "I <3 to escape HTML & other text too." + for i := 0; i < b.N; i++ { + htmlEscaper.Replace(str) + } +} + +func BenchmarkHTMLEscapeOld(b *testing.B) { + str := "I <3 to escape HTML & other text too." + for i := 0; i < b.N; i++ { + oldHTMLEscape(str) + } +} + +func BenchmarkByteStringReplacerWriteString(b *testing.B) { + str := strings.Repeat("I <3 to escape HTML & other text too.", 100) + buf := new(bytes.Buffer) + for i := 0; i < b.N; i++ { + htmlEscaper.WriteString(buf, str) + buf.Reset() + } +} + +func BenchmarkByteReplacerWriteString(b *testing.B) { + str := strings.Repeat("abcdefghijklmnopqrstuvwxyz", 100) + buf := new(bytes.Buffer) + for i := 0; i < b.N; i++ { + capitalLetters.WriteString(buf, str) + buf.Reset() + } +} + +// BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces. +func BenchmarkByteByteReplaces(b *testing.B) { + str := strings.Repeat("a", 100) + strings.Repeat("b", 100) + for i := 0; i < b.N; i++ { + strings.Replace(strings.Replace(str, "a", "A", -1), "b", "B", -1) + } +} diff --git a/vendor/github.com/golangci/misspell/url.go b/vendor/github.com/golangci/misspell/url.go new file mode 100644 index 000000000..1a259f5f9 --- /dev/null +++ b/vendor/github.com/golangci/misspell/url.go @@ -0,0 +1,17 @@ +package misspell + +import ( + "regexp" +) + +// Regexp for URL https://mathiasbynens.be/demo/url-regex +// +// original @imme_emosol (54 chars) has trouble with dashes in hostname +// @(https?|ftp)://(-\.)?([^\s/?\.#-]+\.?)+(/[^\s]*)?$@iS +var reURL = regexp.MustCompile(`(?i)(https?|ftp)://(-\.)?([^\s/?\.#]+\.?)+(/[^\s]*)?`) + +// StripURL attemps to replace URLs with blank spaces, e.g. +// "xxx http://foo.com/ yyy -> "xxx yyyy" +func StripURL(s string) string { + return reURL.ReplaceAllStringFunc(s, replaceWithBlanks) +} diff --git a/vendor/github.com/golangci/misspell/words.go b/vendor/github.com/golangci/misspell/words.go new file mode 100644 index 000000000..1603d87e6 --- /dev/null +++ b/vendor/github.com/golangci/misspell/words.go @@ -0,0 +1,31194 @@ +package misspell + +// Code generated automatically. DO NOT EDIT. + +// DictMain is the main rule set, not including locale-specific spellings +var DictMain = []string{ + "differentiatiations", "differentiations", + "disproportionaltely", "disproportionately", + "oversimplificiation", "oversimplification", + "transcendentational", "transcendental", + "anthromorphization", "anthropomorphization", + "disporportionately", "disproportionately", + "dispraportionately", "disproportionately", + "disproportianately", "disproportionately", + "disproportionatley", "disproportionately", + "disproprotionately", "disproportionately", + "fundamentalistisch", "fundamentalists", + "fundamentalistiska", "fundamentalists", + "fundamentalistiske", "fundamentalists", + "fundamentalistiskt", "fundamentalists", + "histocompatability", "histocompatibility", + "microtransacations", "microtransactions", + "microtransacciones", "microtransactions", + "microtransactional", "microtransactions", + "microtransactioned", "microtransactions", + "misunderstandingly", "misunderstandings", + "oversemplification", "oversimplification", + "oversimplifacation", "oversimplification", + "oversimplificaiton", "oversimplification", + "oversimplificating", "oversimplification", + "oversimplyfication", "oversimplification", + "cardiovasculaires", "cardiovascular", + "certificationkits", "certifications", + "counterporductive", "counterproductive", + "coutnerproductive", "counterproductive", + "disporportionatly", "disproportionately", + "disproportiantely", "disproportionately", + "disproportionatly", "disproportionately", + "disproportionnate", "disproportionate", + "disrepresentation", "misrepresentation", + "fundamentalistisk", "fundamentalists", + "incompatabilities", "incompatibilities", + "inconsequentional", "inconsequential", + "indistinguishible", "indistinguishable", + "indistingusihable", "indistinguishable", + "indistinquishable", "indistinguishable", + "indistuingishable", "indistinguishable", + "instatutionalized", "institutionalized", + "institucionalized", "institutionalized", + "institutionilized", "institutionalized", + "instutitionalized", "institutionalized", + "instututionalized", "institutionalized", + "interchangeablely", "interchangeably", + "interchangeablity", "interchangeably", + "intercontinential", "intercontinental", + "micortransactions", "microtransactions", + "microstansactions", "microtransactions", + "microtramsactions", "microtransactions", + "microtranasctions", "microtransactions", + "microtransacitons", "microtransactions", + "microtransacrions", "microtransactions", + "microtransactioms", "microtransactions", + "microtransactiosn", "microtransactions", + "microtranscations", "microtransactions", + "microtrasnactions", "microtransactions", + "mircotransactions", "microtransactions", + "misinterpretating", "misinterpreting", + "misrepresantation", "misrepresentation", + "misrepresentaiton", "misrepresentation", + "misrepresentating", "misrepresenting", + "misunderstantings", "misunderstandings", + "mocrotransactions", "microtransactions", + "oversimplifaction", "oversimplification", + "oversimplificaton", "oversimplification", + "oversimplifiction", "oversimplification", + "responsibillities", "responsibilities", + "unconstitutionnal", "unconstitutional", + "accomplishements", "accomplishments", + "admininistrative", "administrative", + "antidepresssants", "antidepressants", + "architechturally", "architecturally", + "cardiovasculaire", "cardiovascular", + "charactarization", "characterization", + "characterazation", "characterization", + "characterisitics", "characteristics", + "characteristsics", "characteristic", + "characterizarion", "characterization", + "charecterization", "characterization", + "charicterization", "characterization", + "circumstantional", "circumstantial", + "conversationable", "conversational", + "counterprodutive", "counterproductive", + "demonstrationens", "demonstrations", + "deterministische", "deterministic", + "differenciations", "differentiation", + "differentiantion", "differentiation", + "differentiatiors", "differentiation", + "differentitation", "differentiation", + "disperportionate", "disproportionate", + "disporportionate", "disproportionate", + "dispraportionate", "disproportionate", + "disproportianate", "disproportionate", + "disproportionaly", "disproportionately", + "disproprotionate", "disproportionate", + "electromagnectic", "electromagnetic", + "enviornmentalist", "environmentalist", + "environmentality", "environmentally", + "extraordinairily", "extraordinarily", + "extraordinarilly", "extraordinary", + "extraterrestials", "extraterrestrials", + "fundamentalismos", "fundamentalists", + "fundamentalismus", "fundamentalists", + "fundamentalistas", "fundamentalists", + "fundamentalisten", "fundamentalists", + "fundamentalister", "fundamentalists", + "imcomprehensible", "incomprehensible", + "immunosupressant", "immunosuppressant", + "imperfectionists", "imperfections", + "implementaciones", "implementations", + "implementationen", "implementations", + "implementationer", "implementations", + "inappropriatelly", "inappropriately", + "incompatablities", "incompatibilities", + "incompatiblities", "incompatibilities", + "incomprehencible", "incomprehensible", + "incomprehendible", "incomprehensible", + "incomprehenisble", "incomprehensible", + "incomprehensable", "incomprehensible", + "incomprehinsible", "incomprehensible", + "incomprihensible", "incomprehensible", + "inconprehensible", "incomprehensible", + "inconsistentcies", "inconsistencies", + "inconstitutional", "unconstitutional", + "incrompehensible", "incomprehensible", + "indistinguisable", "indistinguishable", + "institutionlized", "institutionalized", + "intellectualiser", "intellectuals", + "intellectualisme", "intellectuals", + "interchangeabley", "interchangeably", + "internationnally", "internationally", + "interpretaciones", "interpretations", + "interpretationen", "interpretations", + "manoeuverability", "maneuverability", + "massachusettians", "massachusetts", + "microtransacions", "microtransactions", + "microtransacting", "microtransactions", + "microtransactios", "microtransactions", + "microtransactons", "microtransactions", + "microtransations", "microtransactions", + "microtranscation", "microtransactions", + "mircotransaction", "microtransactions", + "miscommunciation", "miscommunication", + "miscommunicaiton", "miscommunication", + "miscomunnication", "miscommunication", + "miscummunication", "miscommunication", + "misinterpretated", "misinterpreted", + "misinterpretions", "misinterpreting", + "misinterpretting", "misinterpreting", + "misproportionate", "disproportionate", + "misrepresenation", "misrepresentation", + "misrepresentaion", "misrepresentation", + "misrepresentated", "misrepresented", + "misrepresentatie", "misrepresentation", + "misrepresentativ", "misrepresentation", + "misubderstanding", "misunderstandings", + "misudnerstanding", "misunderstandings", + "misundarstanding", "misunderstandings", + "misunderatanding", "misunderstandings", + "misunderdtanding", "misunderstandings", + "misundersatnding", "misunderstandings", + "misundersranding", "misunderstandings", + "misunderstadings", "misunderstandings", + "misunderstadning", "misunderstandings", + "misunderstamding", "misunderstandings", + "misunderstandigs", "misunderstandings", + "misunderstandimg", "misunderstandings", + "misunderstandind", "misunderstandings", + "misunderstanging", "misunderstandings", + "misunderstanidng", "misunderstandings", + "misunderstanings", "misunderstandings", + "misunderstansing", "misunderstandings", + "misunderstanting", "misunderstandings", + "misunderstending", "misunderstandings", + "misunderstnading", "misunderstandings", + "misunderstsnding", "misunderstandings", + "misunderstunding", "misunderstandings", + "misundertsanding", "misunderstandings", + "misundrestanding", "misunderstandings", + "misunterstanding", "misunderstandings", + "nationalistische", "nationalistic", + "nationalististic", "nationalistic", + "neconstitutional", "unconstitutional", + "notwhithstanding", "notwithstanding", + "objectificiation", "objectification", + "organisationnels", "organisations", + "perpendiculaires", "perpendicular", + "phillosophically", "philosophically", + "preinitalization", "preinitialization", + "prescriptionists", "prescriptions", + "procrastinarting", "procrastinating", + "procrastinationg", "procrastinating", + "procrastinazione", "procrastination", + "professionalisim", "professionalism", + "professionalisme", "professionals", + "professionallism", "professionalism", + "professionnalism", "professionalism", + "programattically", "programmatically", + "proportionallity", "proportionally", + "reaponsibilities", "responsibilities", + "reinitalizations", "reinitializations", + "representaciones", "representations", + "representationen", "representations", + "representationer", "representations", + "repsonsibilities", "responsibilities", + "responcibilities", "responsibilities", + "responisbilities", "responsibilities", + "responsabilities", "responsibilities", + "responsebilities", "responsibilities", + "straightforeward", "straightforward", + "surrepetitiously", "surreptitiously", + "technologicially", "technologically", + "unconditionnally", "unconditionally", + "unconfortability", "discomfort", + "unconstititional", "unconstitutional", + "uncontrollablely", "uncontrollably", + "underestimateing", "underestimating", + "understandablely", "understandably", + "unintentionnally", "unintentionally", + "unsubstantianted", "unsubstantiated", + "unsubstantiative", "unsubstantiated", + "acclimitization", "acclimatization", + "accomplishemnts", "accomplishments", + "accountabillity", "accountability", + "acknolwedgement", "acknowledgement", + "acknoweldgement", "acknowledgement", + "acknowldegement", "acknowledgement", + "acknowlegdement", "acknowledgement", + "administratieve", "administrative", + "administratiors", "administrators", + "administrativne", "administrative", + "aforementionned", "aforementioned", + "anitdepressants", "antidepressants", + "antidepressents", "antidepressants", + "archetecturally", "architecturally", + "associationthis", "associations", + "authobiographic", "autobiographic", + "awknowledgement", "acknowledgement", + "bureaucratische", "bureaucratic", + "cardiovascualar", "cardiovascular", + "carnagie-mellon", "carnegie-mellon", + "carnigie-mellon", "carnegie-mellon", + "celebrationists", "celebrations", + "charactaristics", "characteristics", + "characterisitcs", "characteristics", + "characterisitic", "characteristic", + "characterizaton", "characterization", + "charactersistic", "characteristic", + "charactersitics", "characteristics", + "charactoristics", "characteristics", + "charecteristics", "characteristics", + "comfrontational", "confrontational", + "commuinications", "communications", + "compatabilities", "compatibilities", + "complimentarity", "complimentary", + "compositionwise", "compositions", + "confidenciality", "confidential", + "confidentuality", "confidential", + "confrentational", "confrontational", + "confrontacional", "confrontational", + "conglaturations", "congratulations", + "congradulations", "congratulations", + "congragulations", "congratulations", + "congratualtions", "congratulations", + "congraturations", "congratulations", + "consequentually", "consequently", + "constitutionnal", "constitutional", + "deinitalization", "deinitialization", + "denominationals", "denominations", + "destinationhash", "destinations", + "deterministisch", "deterministic", + "developmentwise", "developments", + "differantiation", "differentiation", + "differenciation", "differentiation", + "differientation", "differentiation", + "discriminatoire", "discriminate", + "discriminatorie", "discriminate", + "disproportiante", "disproportionate", + "disproportinate", "disproportionate", + "elecrtomagnetic", "electromagnetic", + "electormagnetic", "electromagnetic", + "electromagentic", "electromagnetic", + "electromagnatic", "electromagnetic", + "electromangetic", "electromagnetic", + "electromegnetic", "electromagnetic", + "electronagnetic", "electromagnetic", + "enivronmentally", "environmentally", + "entrepreneurers", "entrepreneurs", + "enviornmentally", "environmentally", + "enviromentalist", "environmentalist", + "environemntally", "environmentally", + "envrionmentally", "environmentally", + "evolutionarilly", "evolutionary", + "experementation", "experimentation", + "experimantation", "experimentation", + "experimentacion", "experimentation", + "experimentating", "experimentation", + "experimenterade", "experimented", + "experimintation", "experimentation", + "expirementation", "experimentation", + "extraodrinarily", "extraordinarily", + "extraordinairly", "extraordinarily", + "extraordinarely", "extraordinarily", + "extraordinaryly", "extraordinarily", + "extraterrestial", "extraterrestrial", + "extroardinarily", "extraordinarily", + "fondamentalists", "fundamentalists", + "fundamendalists", "fundamentalists", + "fundamentalisme", "fundamentals", + "fundamentalismo", "fundamentals", + "fundamentalista", "fundamentals", + "fundamentalisti", "fundamentals", + "fundamnetalists", "fundamentalists", + "fundemantalists", "fundamentalists", + "fundimentalists", "fundamentalists", + "fundumentalists", "fundamentalists", + "gongratulations", "congratulations", + "grammaticallity", "grammatically", + "gundamentalists", "fundamentalists", + "idiosynchracies", "idiosyncrasies", + "implementaitons", "implementations", + "implimentations", "implementations", + "inapporpriately", "inappropriately", + "inappropraitely", "inappropriately", + "inappropriatley", "inappropriately", + "incompatability", "incompatibility", + "incompetentence", "incompetence", + "incomprehensibe", "incomprehensible", + "incomprehesible", "incomprehensible", + "inconcequential", "inconsequential", + "inconcistencies", "inconsistencies", + "inconditionally", "unconditionally", + "inconsecuential", "inconsequential", + "inconsequantial", "inconsequential", + "inconsequencial", "inconsequential", + "inconsequentual", "inconsequential", + "inconsiquential", "inconsequential", + "inconsistancies", "inconsistencies", + "inconsistencias", "inconsistencies", + "inconsistensies", "inconsistencies", + "inconsistenties", "inconsistencies", + "independentisme", "independents", + "independentiste", "independents", + "independentness", "independents", + "inexperiencable", "inexperience", + "inplementations", "implementations", + "instantaneoulsy", "instantaneous", + "institutionella", "institutional", + "institutionnels", "institutions", + "instutionalized", "institutionalized", + "insubstantiated", "unsubstantiated", + "interchangabley", "interchangeably", + "interchangebale", "interchangeable", + "intercontinetal", "intercontinental", + "interpertations", "interpretations", + "interpratations", "interpretations", + "interpritations", "interpretations", + "intersectionals", "intersections", + "intrepretations", "interpretations", + "investigationes", "investigations", + "journalistische", "journalistic", + "libertarianisim", "libertarianism", + "libertarianisme", "libertarians", + "libertarianismo", "libertarians", + "libertarianists", "libertarians", + "libertariansism", "libertarianism", + "manisfestations", "manifestations", + "manouverability", "maneuverability", + "manufacturerers", "manufacturers", + "marshmallowiest", "marshmallows", + "marshmallowness", "marshmallows", + "microtransacton", "microtransactions", + "mininterpreting", "misinterpreting", + "miscommuniation", "miscommunication", + "miscommunicatie", "miscommunication", + "miscommuniction", "miscommunication", + "misinterperting", "misinterpreting", + "misinterprating", "misinterpreting", + "misinterprented", "misinterpret", + "misinterprested", "misinterpret", + "misinterpretion", "misinterpreting", + "misinterpretted", "misinterpreted", + "misinterpriting", "misinterpreting", + "misintrepreting", "misinterpreting", + "misrepresention", "misrepresenting", + "misunderstading", "misunderstanding", + "misunderstandig", "misunderstandings", + "misunderstandng", "misunderstandings", + "misunderstaning", "misunderstanding", + "multicultralism", "multiculturalism", + "multinationella", "multinational", + "nationalistisch", "nationalists", + "nationalistisen", "nationalists", + "nationalistiska", "nationalists", + "nationalistiske", "nationalists", + "nationalistiskt", "nationalists", + "nationalistista", "nationalists", + "objectificaiton", "objectification", + "objectivication", "objectification", + "organisationens", "organisations", + "organisationers", "organisations", + "overestimateing", "overestimating", + "paychologically", "psychologically", + "performancetest", "performances", + "performancewise", "performances", + "perpendiculaire", "perpendicular", + "pharamceuticals", "pharmaceutical", + "pharmacueticals", "pharmaceutical", + "philoshopically", "philosophically", + "philosohpically", "philosophically", + "philosophycally", "philosophically", + "phsycologically", "psychologically", + "phychologically", "psychologically", + "phylosophically", "philosophically", + "physcologically", "psychologically", + "precrastination", "procrastination", + "prefessionalism", "professionalism", + "premonasterians", "premonstratensians", + "procastrinating", "procrastinating", + "procastrination", "procrastination", + "procrascinating", "procrastinating", + "procrastenating", "procrastinating", + "procrastiantion", "procrastination", + "procrastibating", "procrastinating", + "procrastibation", "procrastination", + "procrastonating", "procrastinating", + "procrestinating", "procrastinating", + "procrestination", "procrastination", + "professionalsim", "professionalism", + "prograstination", "procrastination", + "progressionists", "progressions", + "progressionwise", "progressions", + "prokrastination", "procrastination", + "proportionallly", "proportionally", + "proscratination", "procrastination", + "pscyhologically", "psychologically", + "pshycologically", "psychologically", + "psichologically", "psychologically", + "psychedelicious", "psychedelics", + "psychedelicness", "psychedelics", + "psycholigically", "psychologically", + "psychopathische", "psychopathic", + "pyschologically", "psychologically", + "racionalization", "rationalization", + "rationalizaiton", "rationalization", + "rationalizating", "rationalization", + "reccomendations", "recommendations", + "recommandations", "recommendations", + "recommondations", "recommendations", + "reinitalization", "reinitialization", + "repersentations", "representations", + "represantations", "representations", + "represantatives", "representatives", + "representatieve", "representative", + "representativas", "representatives", + "representetives", "representatives", + "representitives", "representatives", + "responibilities", "responsibilities", + "responsibilites", "responsibilities", + "responsibilitys", "responsibilities", + "responsibillity", "responsibility", + "responsibilties", "responsibilities", + "responsiblities", "responsibilities", + "ridiculoussness", "ridiculousness", + "saskatchewinian", "saskatchewan", + "satisfactorally", "satisfactory", + "satisfactorilly", "satisfactory", + "schizophreniiic", "schizophrenic", + "sensationalisim", "sensationalism", + "spreadsheeticus", "spreadsheets", + "starightforward", "straightforward", + "straigthforward", "straightforward", + "striaghtforward", "straightforward", + "sustainabillity", "sustainability", + "technoligically", "technologically", + "troubelshooting", "troubleshooting", + "troublehsooting", "troubleshooting", + "troubleshotting", "troubleshooting", + "trustworthyness", "trustworthiness", + "ubsubstantiated", "unsubstantiated", + "unappropriately", "inappropriately", + "uncomfortablely", "uncomfortably", + "uncomfortablity", "uncomfortably", + "unconditionable", "unconditional", + "unconstituional", "unconstitutional", + "uncontitutional", "unconstitutional", + "uncontrollabley", "uncontrollably", + "uncontrollablly", "uncontrollably", + "unconventionnal", "unconventional", + "underastimating", "underestimating", + "underestemating", "underestimating", + "understandabley", "understandably", + "unintensionally", "unintentionally", + "unprofessionnal", "unprofessional", + "unresponsivness", "unresponsive", + "unsibstantiated", "unsubstantiated", + "unsubstanciated", "unsubstantiated", + "unsubstansiated", "unsubstantiated", + "unsusbtantiated", "unsubstantiated", + "untranslateable", "untranslatable", + "vulernabilities", "vulnerabilities", + "vulnarabilities", "vulnerabilities", + "vulnurabilities", "vulnerabilities", + "vunlerabilities", "vulnerabilities", + "vurnerabilities", "vulnerabilities", + "accomplishemnt", "accomplishment", + "accomplishents", "accomplishes", + "acconplishment", "accomplishment", + "acknowledgeing", "acknowledging", + "acknowledgemnt", "acknowledgement", + "acomplishments", "accomplishments", + "administartion", "administration", + "administartors", "administrators", + "administraters", "administrators", + "administratief", "administrative", + "administratiei", "administrative", + "administratior", "administrator", + "administrativo", "administration", + "adminsitration", "administration", + "adminsitrative", "administrative", + "adminsitrators", "administrators", + "affectionatley", "affectionate", + "aforememtioned", "aforementioned", + "aforementioend", "aforementioned", + "alternativelly", "alternatively", + "amministrative", "administrative", + "anitdepressant", "antidepressants", + "approproximate", "approximate", + "approximatelly", "approximately", + "archeaologists", "archeologists", + "architechtures", "architectures", + "architectureal", "architectural", + "architecturial", "architectural", + "assassintation", "assassination", + "authenitcation", "authentication", + "authenticaiton", "authentication", + "authobiography", "autobiography", + "breakthroughts", "breakthroughs", + "bureaucratisch", "bureaucratic", + "calssification", "classification", + "capatilization", "capitalization", + "capitalizacion", "capitalization", + "capitalizaiton", "capitalization", + "capitalizating", "capitalization", + "capitilazation", "capitalization", + "capitolization", "capitalization", + "captialization", "capitalization", + "cardiocascular", "cardiovascular", + "cardiovascualr", "cardiovascular", + "cardiovasuclar", "cardiovascular", + "caridovascular", "cardiovascular", + "cessationalism", "sensationalism", + "cessationalist", "sensationalist", + "charactaristic", "characteristic", + "characterisics", "characteristics", + "characterisitc", "characteristics", + "characteristcs", "characteristics", + "characteritics", "characteristic", + "charactersitic", "characteristics", + "charasteristic", "characteristics", + "charecteristic", "characteristic", + "cheeseburguers", "cheeseburgers", + "cinematagraphy", "cinematography", + "cinematagrophy", "cinematography", + "cinematograhpy", "cinematography", + "cinematogrophy", "cinematography", + "cinematogrpahy", "cinematography", + "cinemetography", "cinematography", + "cinimatography", "cinematography", + "circumstansial", "circumstantial", + "circumstantual", "circumstantial", + "circumstential", "circumstantial", + "circunstantial", "circumstantial", + "classificaiton", "classification", + "coincedentally", "coincidentally", + "coinsidentally", "coincidentally", + "commemmorating", "commemorating", + "communciations", "communications", + "compatablities", "compatibilities", + "compatibillity", "compatibility", + "compatiblities", "compatibilities", + "competitioners", "competitions", + "comphrehensive", "comprehensive", + "computationnal", "computational", + "concatentation", "concatenation", + "conciderations", "considerations", + "condescenscion", "condescension", + "condradictions", "contradictions", + "configuartions", "configurations", + "confugurations", "configurations", + "conglaturation", "congratulations", + "congratulatons", "congratulations", + "conicidentally", "coincidentally", + "conifgurations", "configurations", + "conscioussness", "consciousness", + "consentrations", "concentrations", + "consiciousness", "consciousness", + "considerablely", "considerably", + "considerstions", "considerations", + "constititional", "constitutional", + "constitucional", "constitutional", + "contamporaries", "contemporaries", + "contemporaneus", "contemporaneous", + "contraceptivos", "contraceptives", + "contradicitons", "contradictions", + "contradictiong", "contradicting", + "contriceptives", "contraceptives", + "controceptives", "contraceptives", + "controdictions", "contradictions", + "conversacional", "conversational", + "converstaional", "conversational", + "correpsondence", "correspondence", + "correspondants", "correspondents", + "correspondense", "correspondence", + "correspondente", "correspondence", + "corrispondants", "correspondents", + "corrispondence", "correspondence", + "corrospondence", "correspondence", + "costumizations", "customization", + "councidentally", "coincidentally", + "crystalisation", "crystallisation", + "curcumstantial", "circumstantial", + "demenstrations", "demonstrations", + "deminstrations", "demonstrations", + "demonstartions", "demonstrations", + "demonstrativno", "demonstrations", + "demonstrativos", "demonstrations", + "demosntrations", "demonstrations", + "desintegration", "disintegration", + "deterioriating", "deteriorating", + "determinisitic", "deterministic", + "differentiaton", "differentiation", + "disatisfaction", "dissatisfaction", + "discrimanatory", "discriminatory", + "discriminacion", "discrimination", + "discriminitory", "discriminatory", + "disillusionned", "disillusioned", + "diskrimination", "discrimination", + "disproportiate", "disproportionate", + "distingiushing", "distinguishing", + "distingquished", "distinguished", + "distingusihing", "distinguishing", + "distinquishing", "distinguishing", + "distuingishing", "distinguishing", + "dysfunctionnal", "dysfunctional", + "eldistribution", "redistribution", + "electromagnetc", "electromagnetic", + "electromagntic", "electromagnetic", + "endoctrination", "indoctrination", + "enthusiastisch", "enthusiastic", + "entrepreneuers", "entrepreneurs", + "entrepreneures", "entrepreneurs", + "enviormentally", "environmentally", + "enviromentally", "environmentally", + "environmentals", "environments", + "environmentaly", "environmentally", + "experimentaion", "experimentation", + "experimentella", "experimental", + "extraordinairy", "extraordinary", + "extraordinarly", "extraordinary", + "extrordinarily", "extraordinarily", + "fondamentalist", "fundamentalist", + "foreshadowning", "foreshadowing", + "functionallity", "functionality", + "fundamendalist", "fundamentalist", + "fundamentalits", "fundamentalists", + "fundamnetalist", "fundamentalist", + "fundemantalist", "fundamentalist", + "fundimentalist", "fundamentalist", + "fundumentalist", "fundamentalist", + "generalizacion", "generalization", + "generalizating", "generalization", + "generelization", "generalization", + "geographacilly", "geographically", + "geographycally", "geographically", + "geogrpahically", "geographically", + "geopraphically", "geographically", + "goegraphically", "geographically", + "grandchilderen", "grandchildren", + "gravitationnal", "gravitational", + "groubdbreaking", "groundbreaking", + "groudnbreaking", "groundbreaking", + "hallcuinations", "hallucination", + "hallicunations", "hallucinations", + "hallucenations", "hallucinations", + "halluciantions", "hallucinations", + "hallucinaitons", "hallucination", + "hallunications", "hallucinations", + "hallusinations", "hallucinations", + "halluzinations", "hallucinations", + "hellucinations", "hallucinations", + "heterosexuella", "heterosexual", + "hipothetically", "hypothetically", + "homosexuallity", "homosexuality", + "hullucinations", "hallucinations", + "hyopthetically", "hypothetically", + "hypathetically", "hypothetically", + "hypethetically", "hypothetically", + "hypotehtically", "hypothetically", + "hypotethically", "hypothetically", + "identificacion", "identification", + "identificaiton", "identification", + "identificativo", "identification", + "identifikation", "identification", + "imlpementation", "implementations", + "impelmentation", "implementations", + "impersonationg", "impersonating", + "implementacion", "implementation", + "implementaiton", "implementation", + "implementating", "implementation", + "implementatino", "implementations", + "implemetnation", "implementations", + "implimentation", "implementation", + "impossibillity", "impossibility", + "inadvertantely", "inadvertently", + "inappropriatly", "inappropriately", + "inapproprietly", "inappropriately", + "incompatablity", "incompatibility", + "incompatiblity", "incompatibility", + "inconsequental", "inconsequential", + "inconsistentcy", "inconsistency", + "incontrollably", "uncontrollably", + "inconventional", "unconventional", + "inconvienenced", "inconvenience", + "indestrictible", "indestructible", + "indestructuble", "indestructible", + "indetification", "identification", + "indistructible", "indestructible", + "individuallity", "individuality", + "indocrtination", "indoctrination", + "indoctrication", "indoctrination", + "indoktrination", "indoctrination", + "industiralized", "industrialized", + "industrailized", "industrialized", + "industrualized", "industrialized", + "industructible", "indestructible", + "inexplicablely", "inexplicably", + "infrastracture", "infrastructure", + "infrastructuur", "infrastructure", + "infrastrucutre", "infrastructure", + "infrastrukture", "infrastructure", + "infrastrutture", "infrastructure", + "infrasturcture", "infrastructure", + "initalisations", "initialisations", + "initalizations", "initializations", + "inplementation", "implementation", + "inspirationnal", "inspirational", + "instinctivelly", "instinctively", + "institutionale", "institutionalized", + "institutionals", "institutions", + "institutionnal", "institutional", + "intellectualis", "intellectuals", + "intellectualls", "intellectuals", + "intellecutally", "intellectually", + "intercepticons", "interceptions", + "interchangable", "interchangeable", + "interchangably", "interchangeably", + "interchangeble", "interchangeable", + "interchangebly", "interchangeably", + "interlectually", "intellectually", + "internationaal", "international", + "internationaly", "internationally", + "internationnal", "international", + "interpersonnal", "interpersonal", + "interpertation", "interpretation", + "interpratation", "interpretation", + "interpretacion", "interpretation", + "interpretaiton", "interpretations", + "interpretating", "interpretation", + "interpritation", "interpretation", + "interstellaire", "interstellar", + "intillectually", "intellectually", + "intrepretation", "interpretation", + "invesitgations", "investigations", + "investiagtions", "investigations", + "investigatiors", "investigations", + "investigativos", "investigations", + "investigstions", "investigations", + "irrationallity", "irrationally", + "irresponsibile", "irresponsible", + "journalistisch", "journalistic", + "justificativos", "justifications", + "koncentrations", "concentrations", + "liberatrianism", "libertarianism", + "libertarainism", "libertarianism", + "libertariansim", "libertarianism", + "libertarinaism", "libertarianism", + "libertaryanism", "libertarianism", + "libertatianism", "libertarianism", + "liberterianism", "libertarianism", + "libretarianism", "libertarianism", + "manufactureers", "manufactures", + "manufactureras", "manufactures", + "manufacturered", "manufactured", + "manufactureres", "manufacturers", + "manufactureros", "manufactures", + "massachusettes", "massachusetts", + "massachussetts", "massachusetts", + "mataphorically", "metaphorically", + "mathameticians", "mathematicians", + "mathemagically", "mathematically", + "mathematitians", "mathematicians", + "mathemetically", "mathematically", + "mathemeticians", "mathematicians", + "mathimatically", "mathematically", + "mediterainnean", "mediterranean", + "mediterrannean", "mediterranean", + "metaphotically", "metaphorically", + "metephorically", "metaphorically", + "methaporically", "metaphorically", + "metiphorically", "metaphorically", + "metophorically", "metaphorically", + "metropolitaine", "metropolitan", + "misconseptions", "misconceptions", + "misinterperted", "misinterpreted", + "misintrepreted", "misinterpreted", + "mulitnationals", "multinational", + "mulitplication", "multiplication", + "multiplicacion", "multiplication", + "multiplicaiton", "multiplication", + "multiplicativo", "multiplication", + "multiplikation", "multiplication", + "mutlinationals", "multinational", + "mutliplication", "multiplication", + "nationalisitic", "nationalistic", + "nationalistics", "nationalists", + "nationalisties", "nationalists", + "nationalistisk", "nationalists", + "neighbourhoood", "neighbourhood", + "nieghbourhoods", "neighbourhood", + "northereastern", "northeastern", + "objectificaton", "objectification", + "opthalmologist", "ophthalmologist", + "organizacional", "organizational", + "organizaitonal", "organizational", + "organziational", "organizational", + "orginazational", "organizational", + "overestemating", "overestimating", + "overextimating", "overestimating", + "overhwelmingly", "overwhelmingly", + "overhwlemingly", "overwhelmingly", + "overpolulation", "overpopulation", + "overpopluation", "overpopulation", + "oversetimating", "overestimating", + "overshadowered", "overshadowed", + "overwhemlingly", "overwhelmingly", + "overwhlemingly", "overwhelmingly", + "paliamentarian", "parliamentarian", + "parliamentiary", "parliamentary", + "performancepcs", "performances", + "personalitites", "personalities", + "pharamceutical", "pharmaceutical", + "pharmaceudical", "pharmaceutical", + "pharmacuetical", "pharmaceutical", + "pharmaseutical", "pharmaceutical", + "pharmeceutical", "pharmaceutical", + "philosophicaly", "philosophically", + "phramaceutical", "pharmaceutical", + "playthroughers", "playthroughs", + "porportionally", "proportionally", + "practitionners", "practitioners", + "predeterminded", "predetermined", + "predominantely", "predominantly", + "predominantley", "predominantly", + "preinitalizing", "preinitializing", + "prerequisities", "prerequisite", + "procrastinatin", "procrastination", + "procrastinaton", "procrastination", + "professionials", "professionalism", + "professionnals", "professionals", + "profitabillity", "profitability", + "progressivelly", "progressively", + "progressivisme", "progressives", + "pronounciation", "pronunciation", + "proportianally", "proportionally", + "proportionalty", "proportionally", + "proportionella", "proportionally", + "proprotionally", "proportionally", + "protruberances", "protuberances", + "pseudononymous", "pseudonymous", + "psychologicaly", "psychologically", + "qaulifications", "qualification", + "qualifiactions", "qualification", + "qualificaitons", "qualifications", + "quarterbackers", "quarterbacks", + "rationalizaton", "rationalization", + "reaponsibility", "responsibility", + "recommandation", "recommendation", + "recommedations", "recommendations", + "recommondation", "recommendation", + "reconnaissence", "reconnaissance", + "reconstruccion", "reconstruction", + "reconsturction", "reconstruction", + "redistirbution", "redistribution", + "redistribucion", "redistribution", + "redistributivo", "redistribution", + "redistrubition", "redistribution", + "refridgeration", "refrigeration", + "rehabilitacion", "rehabilitation", + "rehabilitaiton", "rehabilitation", + "reinforcemnets", "reinforcements", + "rekommendation", "recommendation", + "rektifications", "certifications", + "reniforcements", "reinforcements", + "repersentation", "representation", + "represantation", "representation", + "represantative", "representative", + "representacion", "representation", + "representaiton", "representations", + "representatief", "representative", + "representating", "representation", + "representativo", "representation", + "representetive", "representative", + "representitive", "representative", + "representstion", "representations", + "representstive", "representatives", + "represetnation", "representations", + "represnetation", "representations", + "reprezentative", "representative", + "repsonsibility", "responsibility", + "resistribution", "redistribution", + "responcibility", "responsibility", + "responisbility", "responsibility", + "responnsibilty", "responsibility", + "responsability", "responsibility", + "responsibilies", "responsibilities", + "responsibities", "responsibilities", + "restaraunteurs", "restaurateurs", + "retroactivelly", "retroactively", + "revolutionairy", "revolutionary", + "revolutionnary", "revolutionary", + "ridicilousness", "ridiculousness", + "ridicoulusness", "ridiculousness", + "rienforcements", "reinforcements", + "righteoussness", "righteousness", + "satisfactoraly", "satisfactory", + "satisfactority", "satisfactorily", + "sceintifically", "scientifically", + "schizophrentic", "schizophrenic", + "screenwrighter", "screenwriter", + "sensacionalism", "sensationalism", + "sensacionalist", "sensationalist", + "sensasionalism", "sensationalism", + "sensasionalist", "sensationalist", + "sensationality", "sensationalist", + "sensationalizm", "sensationalism", + "sensationalsim", "sensationalism", + "sensationilism", "sensationalism", + "sensationilist", "sensationalist", + "sensationslism", "sensationalism", + "sensetionalism", "sensationalism", + "sensibilisiert", "sensibilities", + "sentationalism", "sensationalism", + "sentationalist", "sensationalist", + "senzationalism", "sensationalism", + "senzationalist", "sensationalist", + "sepcifications", "specification", + "simaltaneously", "simultaneously", + "simeltaneously", "simultaneously", + "similtaneously", "simultaneously", + "simlutaneously", "simultaneously", + "simplificacion", "simplification", + "simplificaiton", "simplification", + "simplificating", "simplification", + "simulatenously", "simultaneously", + "simulatneously", "simultaneously", + "simultaenously", "simultaneously", + "simultainously", "simultaneously", + "simultaneoulsy", "simultaneously", + "simultaniously", "simultaneously", + "simulteanously", "simultaneously", + "sistematically", "systematically", + "slaugterhouses", "slaughterhouses", + "specailization", "specialization", + "specialication", "specialization", + "specializaiton", "specialization", + "specificaitons", "specification", + "speciliazation", "specialization", + "spectacularely", "spectacularly", + "spectacularily", "spectacularly", + "spesifications", "specifications", + "spezialisation", "specialization", + "sportsmansship", "sportsmanship", + "spreadsheeters", "spreadsheets", + "straightforwad", "straightforward", + "subconcsiously", "subconsciously", + "subconsicously", "subconsciously", + "subsconciously", "subconsciously", + "sunconsciously", "subconsciously", + "superintendant", "superintendent", + "suppliementing", "supplementing", + "surrepetitious", "surreptitious", + "survivabililty", "survivability", + "survivabillity", "survivability", + "sustainabiltiy", "sustainability", + "syncronization", "synchronization", + "systemetically", "systematically", + "systimatically", "systematically", + "technologicaly", "technologically", + "thermodinamics", "thermodynamics", + "thermodyanmics", "thermodynamics", + "thermodymamics", "thermodynamics", + "thermodymanics", "thermodynamics", + "thermodynamcis", "thermodynamics", + "thermodynanics", "thermodynamics", + "thermodynmaics", "thermodynamics", + "thernodynamics", "thermodynamics", + "theromdynamics", "thermodynamics", + "transformacion", "transformation", + "transfromation", "transformation", + "transitionable", "transitional", + "transitionning", "transitioning", + "transofrmation", "transformation", + "trasnformation", "transformation", + "trasnportation", "transportation", + "unbelievablely", "unbelievably", + "unchallengable", "unchallengeable", + "uncomfortabley", "uncomfortably", + "uncomfortablly", "uncomfortably", + "unconciousness", "unconsciousness", + "unconditionaly", "unconditionally", + "unconditionnal", "unconditional", + "unconsciouslly", "unconsciously", + "uncontrallable", "uncontrollable", + "uncontrallably", "uncontrollably", + "uncontrolablly", "uncontrollably", + "unconvectional", "unconventional", + "unconvencional", "unconventional", + "unconvensional", "unconventional", + "unconventianal", "unconventional", + "underastimated", "underestimated", + "underestamated", "underestimated", + "underestemated", "underestimated", + "underestimeted", "underestimated", + "undersetimated", "underestimated", + "understandebly", "understandably", + "understandible", "understandable", + "understandibly", "understandably", + "undestructible", "indestructible", + "unforetunately", "unfortunately", + "unfortunatelly", "unfortunately", + "unfourtunately", "unfortunately", + "uninitalizable", "uninitializable", + "unintelligient", "unintelligent", + "unintentionaly", "unintentionally", + "unintentionnal", "unintentional", + "unmanouverable", "unmaneuverable", + "unneccessarily", "unnecessarily", + "unnecessarilly", "unnecessarily", + "unprecendented", "unprecedented", + "unprofessionel", "unprofessional", + "unreasonablely", "unreasonably", + "unsubstantiaed", "unsubstantiated", + "unsurprizingly", "unsurprisingly", + "vizualisations", "visualization", + "vulnerabilites", "vulnerabilities", + "vulnerabillity", "vulnerability", + "vulnerablility", "vulnerability", + "wholeheartadly", "wholeheartedly", + "wholeheartidly", "wholeheartedly", + "abbrievations", "abbreviation", + "accelleration", "acceleration", + "accomadations", "accommodations", + "accommadating", "accommodating", + "accommadation", "accommodation", + "accommidation", "accommodation", + "accomodations", "accommodations", + "accomondating", "accommodating", + "accomondation", "accommodation", + "accomplishent", "accomplishment", + "accountabilty", "accountability", + "accredidation", "accreditation", + "acknolwedging", "acknowledging", + "acknowlegding", "acknowledging", + "acomplishment", "accomplishment", + "acquaintaince", "acquaintance", + "acquaintences", "acquaintances", + "acquaintinces", "acquaintances", + "acquanitances", "acquaintance", + "acquantainces", "acquaintances", + "acquantiances", "acquaintances", + "acquiantances", "acquaintances", + "acquiantences", "acquaintances", + "adminastrator", "administrator", + "administartor", "administrator", + "administraion", "administration", + "administraron", "administrator", + "administrater", "administrator", + "administratio", "administrator", + "administraton", "administration", + "adminsitrator", "administrator", + "adminstration", "administration", + "adminstrative", "administrative", + "admissability", "admissibility", + "adnimistrator", "administrators", + "adverticement", "advertisement", + "advertisiment", "advertisement", + "advertisments", "advertisements", + "advirtisement", "advertisement", + "aestethically", "aesthetically", + "aesthatically", "aesthetically", + "aesthitically", "aesthetically", + "affectionnate", "affectionate", + "aforementiond", "aforementioned", + "agriculturual", "agricultural", + "agrumentative", "argumentative", + "alterantively", "alternatively", + "alternativets", "alternatives", + "alternativley", "alternatively", + "alternitavely", "alternatively", + "alternitively", "alternatively", + "aninteresting", "uninteresting", + "annoucnements", "announcements", + "antagonisitic", "antagonistic", + "anthropolgist", "anthropologist", + "apporpriately", "appropriately", + "apporpriation", "appropriation", + "apporximately", "approximately", + "appreciateing", "appreciating", + "appreciateive", "appreciative", + "appreciationg", "appreciating", + "appropirately", "appropriately", + "appropiration", "appropriation", + "appropraitely", "appropriately", + "appropreation", "appropriation", + "appropriatley", "appropriately", + "appropropiate", "appropriate", + "approrpiation", "appropriation", + "approxamately", "approximately", + "approxiamtely", "approximately", + "approximatley", "approximately", + "approximitely", "approximately", + "aqcuaintances", "acquaintances", + "aqquaintances", "acquaintances", + "archaelogical", "archaeological", + "archaelogists", "archaeologists", + "archeaologist", "archeologist", + "archetectural", "architectural", + "architechture", "architecture", + "architechural", "architectural", + "architectrual", "architectural", + "architecutral", "architectural", + "argumentitive", "argumentative", + "arugmentative", "argumentative", + "asethetically", "aesthetically", + "assasinations", "assassinations", + "audomoderator", "automoderator", + "australianess", "australians", + "authenticaion", "authentication", + "authenticaton", "authentication", + "autherization", "authorization", + "authoratitive", "authoritative", + "authoritatian", "authoritarian", + "authoritation", "authorization", + "authorititive", "authoritative", + "authoritorian", "authoritarian", + "authorotative", "authoritative", + "authroization", "authorization", + "automoderador", "automoderator", + "automoderater", "automoderator", + "automodorator", "automoderator", + "automoterator", "automoderator", + "autoritharian", "authoritarian", + "availabillity", "availability", + "awknowledging", "acknowledging", + "billingualism", "bilingualism", + "billionairres", "billionaire", + "borderlanders", "borderlands", + "breadtfeeding", "breastfeeding", + "breastfeading", "breastfeeding", + "breatsfeeding", "breastfeeding", + "broadacasting", "broadcasting", + "bureaucractic", "bureaucratic", + "bureaucratics", "bureaucrats", + "bureaucratius", "bureaucrats", + "californiaman", "californian", + "calrification", "clarification", + "capitalizaton", "capitalization", + "carbohdyrates", "carbohydrates", + "carbohidrates", "carbohydrates", + "carbohyrdates", "carbohydrates", + "carboyhdrates", "carbohydrates", + "carthographer", "cartographer", + "catagorically", "categorically", + "catastrophies", "catastrophe", + "catastrophize", "catastrophe", + "catigorically", "categorically", + "catterpillars", "caterpillars", + "celebrationis", "celebrations", + "ceritfication", "certifications", + "certificaiton", "certification", + "championchips", "championship", + "championshiop", "championships", + "championsship", "championships", + "chanpionships", "championships", + "charactarized", "characterized", + "characterisic", "characteristic", + "characteristc", "characteristics", + "characterists", "characteristics", + "charicterized", "characterized", + "charismatisch", "charismatic", + "checkpointusa", "checkpoints", + "cheeseburgare", "cheeseburger", + "cheeseburgler", "cheeseburger", + "cheeseburguer", "cheeseburger", + "cheezeburgers", "cheeseburgers", + "chornological", "chronological", + "chronoligical", "chronological", + "chronologicly", "chronological", + "cinematograhy", "cinematography", + "cinematograpy", "cinematography", + "circomference", "circumference", + "circumcission", "circumcision", + "circumferance", "circumference", + "circumsicions", "circumcision", + "circumstanial", "circumstantial", + "circumstantal", "circumstantial", + "circumstnaces", "circumstance", + "circunference", "circumference", + "circunstances", "circumstances", + "cirucmference", "circumference", + "cirucmstances", "circumstances", + "civilications", "civilizations", + "civilizaitons", "civilizations", + "clarificaiton", "clarification", + "clasification", "clarification", + "clerification", "clarification", + "coincidentaly", "coincidentally", + "coincidential", "coincidental", + "colaborations", "collaborations", + "collabaration", "collaboration", + "collaberation", "collaboration", + "collaberative", "collaborative", + "collaboratore", "collaborate", + "collectioners", "collections", + "collectivelly", "collectively", + "collobaration", "collaboration", + "combatibility", "compatibility", + "comeptitively", "competitively", + "comfortablely", "comfortably", + "comfortablity", "comfortably", + "comfrontation", "confrontation", + "commemerative", "commemorative", + "commericially", "commercially", + "commerorative", "commemorative", + "comminication", "communication", + "comminucation", "communications", + "commissionees", "commissions", + "commissionned", "commissioned", + "commissionner", "commissioner", + "commmemorated", "commemorated", + "commuications", "communications", + "commuincation", "communications", + "communciation", "communication", + "communiaction", "communications", + "communicaiton", "communication", + "communicatoin", "communications", + "communicatons", "communications", + "compadibility", "compatibility", + "comparativley", "comparatively", + "comparetively", "comparatively", + "comparitavely", "comparatively", + "comparitively", "comparatively", + "compatability", "compatibility", + "compatibiltiy", "compatibility", + "compeditively", "competitively", + "compensantion", "compensation", + "compensationg", "compensating", + "comperatively", "comparatively", + "comperhension", "comprehension", + "competatively", "competitively", + "competitavely", "competitively", + "competitevely", "competitively", + "competitivley", "competitively", + "competiveness", "competitiveness", + "compilcations", "complication", + "compitability", "compatibility", + "complciations", "complication", + "complecations", "complications", + "compliactions", "complication", + "complicaitons", "complication", + "complilations", "complications", + "complimentery", "complimentary", + "complimentoni", "complimenting", + "complimentory", "complimentary", + "comprehention", "comprehension", + "computacional", "computational", + "comtamination", "contamination", + "comtemplating", "contemplating", + "concatination", "contamination", + "conceivablely", "conceivably", + "concencration", "concentration", + "concenrtation", "concentrations", + "concentartion", "concentrations", + "concentracion", "concentration", + "concentraited", "concentrated", + "concentraiton", "concentrations", + "concentratons", "concentrations", + "concervatives", "conservatives", + "concideration", "consideration", + "concioussness", "consciousness", + "concnetration", "concentrations", + "concsiousness", "consciousness", + "condascending", "condescending", + "condescencion", "condescension", + "condescendion", "condescension", + "condescensing", "condescension", + "condiscending", "condescending", + "conditionning", "conditioning", + "condradicting", "contradicting", + "condradiction", "contradiction", + "condradictory", "contradictory", + "conecntration", "concentrations", + "conenctration", "concentrations", + "confidentally", "confidentially", + "configrations", "configurations", + "configruation", "configurations", + "configuartion", "configuration", + "configuracion", "configuration", + "configuraiton", "configuration", + "configuratoin", "configurations", + "configureable", "configurable", + "confrentation", "confrontation", + "confrontacion", "confrontation", + "confrontating", "confrontation", + "confrontativo", "confrontation", + "congratualted", "congratulate", + "conifguration", "configurations", + "conisderation", "considerations", + "connecticunts", "connecticut", + "connectivitiy", "connectivity", + "conpassionate", "compassionate", + "conplications", "complications", + "conplimentary", "complimentary", + "conplimenting", "complimenting", + "conprehension", "comprehension", + "consdieration", "considerations", + "consenquently", "consequently", + "consentrating", "concentrating", + "consentration", "concentration", + "consequencies", "consequence", + "consequentely", "consequently", + "consequeseces", "consequences", + "conservatisim", "conservatism", + "conservativsm", "conservatism", + "conservitives", "conservatives", + "consicousness", "consciousness", + "considerabely", "considerable", + "considerabile", "considerable", + "considerabley", "considerably", + "considerablly", "considerably", + "consideracion", "consideration", + "consideratoin", "considerations", + "considerstion", "considerations", + "considertaion", "considerations", + "consituencies", "constituencies", + "consitutional", "constitutional", + "constallation", "constellation", + "constarnation", "consternation", + "constillation", "constellation", + "constituintes", "constituents", + "constituional", "constitutional", + "constitutents", "constitutes", + "constitutinal", "constitutional", + "constructicon", "construction", + "constructieve", "constructive", + "constructiong", "constructing", + "consttruction", "construction", + "contaminacion", "contamination", + "contaminanted", "contaminated", + "contanimation", "contamination", + "contenplating", "contemplating", + "contimplating", "contemplating", + "contraceptivo", "contraception", + "contradiccion", "contradiction", + "contradicitng", "contradicting", + "contradiciton", "contradiction", + "contradictary", "contradictory", + "contradictons", "contradicts", + "contraticting", "contradicting", + "contravercial", "controversial", + "contraversial", "controversial", + "contreception", "contraception", + "contreversial", "controversial", + "contributeurs", "contributes", + "contributiors", "contributors", + "contriception", "contraception", + "contridictory", "contradictory", + "contritutions", "contributions", + "contriversial", "controversial", + "controception", "contraception", + "controdicting", "contradicting", + "controdiction", "contradiction", + "controvercial", "controversial", + "controverisal", "controversial", + "controversary", "controversy", + "controversity", "controversy", + "controvertial", "controversial", + "contstruction", "construction", + "conventionnal", "conventional", + "converastions", "conservation", + "conversationa", "conservation", + "conversationg", "conservation", + "conversationy", "conservation", + "conversatiosn", "conservation", + "conversatives", "conservatives", + "converstaions", "conversations", + "convorsations", "conversations", + "cooresponding", "corresponding", + "coorperations", "corporations", + "correctionals", "corrections", + "correpsonding", "corresponding", + "correspondant", "correspondent", + "correspondece", "correspondence", + "corresponders", "corresponds", + "corresponsing", "corresponding", + "corrispondant", "correspondent", + "corrisponding", "corresponding", + "corrosponding", "corresponding", + "costomization", "customization", + "costumization", "customization", + "counterfeight", "counterfeit", + "creationistas", "creationists", + "cricumference", "circumference", + "cringeworthey", "cringeworthy", + "cringeworthly", "cringeworthy", + "crytopgraphic", "cryptographic", + "curcumference", "circumference", + "curcumstances", "circumstances", + "custumization", "customization", + "cuztomization", "customization", + "decentraliced", "decentralized", + "decentrilized", "decentralized", + "decomissioned", "decommissioned", + "decompositing", "decomposing", + "definitivelly", "definitively", + "deinitalizing", "deinitializing", + "demenstration", "demonstration", + "democraticaly", "democratically", + "democraticlly", "democratically", + "demoninations", "denominations", + "demonstarting", "demonstrating", + "demonstartion", "demonstration", + "demonstraiton", "demonstrations", + "demonstratbly", "demonstrably", + "demonstraties", "demonstrate", + "demonstrativo", "demonstration", + "demosntrating", "demonstrating", + "demosntration", "demonstrations", + "denomenations", "denominations", + "denomonations", "denominations", + "deomnstration", "demonstrations", + "dermatalogist", "dermatologist", + "dermatolagist", "dermatologist", + "dermatoligist", "dermatologist", + "dermatologyst", "dermatologist", + "dermetologist", "dermatologist", + "dermitologist", "dermatologist", + "derpatologist", "dermatologist", + "desentralized", "decentralized", + "desillusioned", "disillusioned", + "desintegrated", "disintegrated", + "desinterested", "disinterested", + "determenation", "determination", + "determinacion", "determination", + "determinining", "determining", + "determinisitc", "deterministic", + "determinsitic", "deterministic", + "detmatologist", "dermatologist", + "developmently", "developmental", + "dezentralized", "decentralized", + "differantiate", "differentiate", + "differenciate", "differentiate", + "differintiate", "differentiate", + "diffirentiate", "differentiate", + "disadvandages", "disadvantaged", + "disadvantadge", "disadvantaged", + "disadvanteged", "disadvantaged", + "disadvanteges", "disadvantages", + "disadvatanges", "disadvantages", + "disadventaged", "disadvantaged", + "disadventages", "disadvantages", + "disallusioned", "disillusioned", + "disappearence", "disappearance", + "disappearnace", "disappearance", + "disappearring", "disappearing", + "disatvantaged", "disadvantaged", + "disatvantages", "disadvantages", + "disciplinairy", "disciplinary", + "disciplinerad", "disciplined", + "discipliniary", "disciplinary", + "disconnecters", "disconnects", + "discontinuted", "discontinued", + "discrimianted", "discriminated", + "discriminante", "discriminate", + "discriminatie", "discriminate", + "discriminatin", "discrimination", + "disillisioned", "disillusioned", + "disillutioned", "disillusioned", + "disingenuious", "disingenuous", + "disollusioned", "disillusioned", + "disrecpectful", "disrespectful", + "disrecpecting", "disrespecting", + "disrepsectful", "disrespectful", + "disrepsecting", "disrespecting", + "disresepctful", "disrespectful", + "disresepcting", "disrespecting", + "disrespection", "disrespecting", + "disrespekting", "disrespecting", + "disrispectful", "disrespectful", + "disrispecting", "disrespecting", + "dissagreement", "disagreement", + "dissapearance", "disappearance", + "dissapointted", "dissapointed", + "dissappointed", "disappointed", + "dissobediance", "disobedience", + "dissobedience", "disobedience", + "distingishing", "distinguishing", + "distinguising", "distinguishing", + "distinquished", "distinguished", + "distirbutions", "distributions", + "distiungished", "distinguished", + "distribustion", "distributions", + "distributiors", "distributors", + "distributivos", "distributions", + "distrobutions", "distributions", + "distrubitions", "distributions", + "distuingished", "distinguished", + "documantaries", "documentaries", + "documenatries", "documentaries", + "documentacion", "documentation", + "documentaires", "documentaries", + "documentaiton", "documentation", + "documentarios", "documentaries", + "documentaties", "documentaries", + "documentating", "documentation", + "documenteries", "documentaries", + "documentories", "documentaries", + "drammatically", "grammatically", + "dsyfunctional", "dysfunctional", + "dumbfoundeads", "dumbfounded", + "dusfunctional", "dysfunctional", + "dustification", "justification", + "dysfonctional", "dysfunctional", + "dysfucntional", "dysfunctional", + "dysfuncitonal", "dysfunctional", + "dysfunktional", "dysfunctional", + "easthetically", "aesthetically", + "effectiviness", "effectiveness", + "effictiveness", "effectiveness", + "effortlessely", "effortlessly", + "effortlessley", "effortlessly", + "embarrasement", "embarrassment", + "embarrasments", "embarrassment", + "embarressment", "embarrassment", + "emberrassment", "embarrassment", + "encarceration", "incarceration", + "encorporating", "incorporating", + "encyclopeadia", "encyclopedia", + "encyclopeadic", "encyclopedia", + "encyclopeedia", "encyclopedia", + "encycolpedias", "encyclopedia", + "endoctrinated", "indoctrinated", + "enlightenting", "enlightening", + "enlightnement", "enlightenment", + "enligthenment", "enlightenment", + "enteratinment", "entertainment", + "enterpreneurs", "entrepreneurs", + "enterprenuers", "entrepreneurs", + "enterpreuners", "entrepreneurs", + "entertianment", "entertainment", + "enthusiasists", "enthusiasts", + "enthusiastics", "enthusiasts", + "entrepraneurs", "entrepreneurs", + "entreprenaurs", "entrepreneurs", + "entrepreneuer", "entrepreneurs", + "entreprenours", "entrepreneurs", + "entreprenuers", "entrepreneurs", + "entreprenures", "entrepreneurs", + "entrepreuners", "entrepreneurs", + "entretainment", "entertainment", + "enviornmental", "environmental", + "environemntal", "environmental", + "environmently", "environmental", + "envolutionary", "evolutionary", + "envrionmental", "environmental", + "estabilshment", "establishments", + "establishemnt", "establishments", + "establishmnet", "establishments", + "establsihment", "establishments", + "estbalishment", "establishments", + "ethnocentricm", "ethnocentrism", + "evolutionairy", "evolutionary", + "evolutionarly", "evolutionary", + "evolutionnary", "evolutionary", + "exaggeratting", "exaggerating", + "excpetionally", "exceptionally", + "executioneers", "executioner", + "existentiella", "existential", + "expectionally", "exceptionally", + "experementing", "experimenting", + "experienceing", "experiencing", + "experimentais", "experiments", + "experimention", "experimenting", + "experimentors", "experiments", + "expirementing", "experimenting", + "expodentially", "exponentially", + "exponantially", "exponentially", + "exponencially", "exponentially", + "exponentiella", "exponential", + "extraodrinary", "extraordinary", + "extraordianry", "extraordinary", + "extraordinair", "extraordinary", + "extraordinaly", "extraordinary", + "extraoridnary", "extraordinary", + "extremeophile", "extremophile", + "extroardinary", "extraordinary", + "familiarizate", "familiarize", + "fantasitcally", "fantastically", + "fantasmically", "fantastically", + "fantistically", "fantastically", + "faptastically", "fantastically", + "figurativeley", "figuratively", + "figurativelly", "figuratively", + "frankenstiens", "frankenstein", + "frankenstined", "frankenstein", + "frankenstiner", "frankenstein", + "frankenstines", "frankenstein", + "friendzoneado", "friendzoned", + "fucntionality", "functionality", + "funcitonality", "functionality", + "functionailty", "functionality", + "fundamentalis", "fundamentals", + "fundamnetally", "fundamentally", + "fundementally", "fundamentally", + "fundimentally", "fundamentally", + "gamifications", "ramifications", + "generalizaing", "generalizing", + "generalizaton", "generalization", + "generationals", "generations", + "generationens", "generations", + "generationers", "generations", + "generationnal", "generational", + "geographicaly", "geographically", + "geographicial", "geographical", + "geometricians", "geometers", + "goreshadowing", "foreshadowing", + "governmential", "governmental", + "gradification", "gratification", + "grammarically", "grammatically", + "grandchildern", "grandchildren", + "gratificacion", "gratification", + "gratificaiton", "gratification", + "grativational", "gravitational", + "gravitacional", "gravitational", + "gravitaitonal", "gravitational", + "hallcuination", "hallucination", + "hallicunation", "hallucination", + "hallucenation", "hallucination", + "halluciantion", "hallucinations", + "hallukination", "hallucination", + "hallunication", "hallucination", + "hallusination", "hallucination", + "halluzination", "hallucination", + "heiroglyphics", "hieroglyphics", + "hellucination", "hallucination", + "highlightning", "highlighting", + "homesexuality", "homosexuality", + "homosexualtiy", "homosexuality", + "homosexulaity", "homosexuality", + "horizontallly", "horizontally", + "hullucination", "hallucination", + "hypocriticial", "hypocritical", + "hypotheticaly", "hypothetically", + "hystericallly", "hysterically", + "identificaton", "identification", + "ideoligically", "ideologically", + "ideosyncratic", "idiosyncratic", + "idiologically", "ideologically", + "illistrations", "illustrations", + "illustartions", "illustrations", + "imperfactions", "imperfections", + "impersinating", "impersonating", + "implementaion", "implementation", + "implementatin", "implementations", + "implimenation", "implementation", + "imprefections", "imperfections", + "impresonating", "impersonating", + "inaccessibile", "inaccessible", + "inadventently", "inadvertently", + "inadverdently", "inadvertently", + "inadvertantly", "inadvertently", + "inadvertendly", "inadvertently", + "inapporpriate", "inappropriate", + "inappropirate", "inappropriate", + "inappropraite", "inappropriate", + "inaproppriate", "inappropriate", + "incarcaration", "incarceration", + "incarciration", "incarceration", + "incarseration", "incarceration", + "incerceration", "incarceration", + "incidentially", "incidentally", + "incomfortable", "uncomfortable", + "incomfortably", "uncomfortably", + "incompatabile", "incompatible", + "incompatiable", "incompatible", + "incompatibile", "incompatible", + "inconciderate", "inconsiderate", + "inconcistency", "inconsistency", + "inconditional", "unconditional", + "inconsciously", "unconsciously", + "inconsiderant", "inconsiderate", + "inconsistance", "inconsistency", + "inconsistancy", "inconsistency", + "inconsistenly", "inconsistency", + "inconsistensy", "inconsistency", + "inconsistenty", "inconsistency", + "inconveinence", "inconvenience", + "inconveniance", "inconvenience", + "inconveniente", "inconvenience", + "inconvienence", "inconvenience", + "incoroporated", "incorporated", + "incorparating", "incorporating", + "incorperating", "incorporating", + "incorperation", "incorporation", + "incorruptable", "incorruptible", + "incramentally", "incrementally", + "incrementarla", "incremental", + "incrementarlo", "incremental", + "indavertently", "inadvertently", + "indefinitelly", "indefinitely", + "independantes", "independents", + "independantly", "independently", + "independendet", "independent", + "independendly", "independently", + "indepentently", "independently", + "indespensable", "indispensable", + "indespensible", "indispensable", + "indestructble", "indestructible", + "indestructibe", "indestructible", + "indictrinated", "indoctrinated", + "indipendently", "independently", + "indispensible", "indispensable", + "indivuduality", "individuality", + "indocrtinated", "indoctrinated", + "indocternated", "indoctrinated", + "indoctornated", "indoctrinated", + "indoctrinatie", "indoctrinated", + "indoctrinatin", "indoctrination", + "indoctronated", "indoctrinated", + "industrialied", "industrialized", + "industrialzed", "industrialized", + "inexeprienced", "inexperience", + "inexpeirenced", "inexperience", + "inexpereinced", "inexperienced", + "inexperianced", "inexperienced", + "inexperiecned", "inexperience", + "inexperineced", "inexperience", + "inexpierenced", "inexperienced", + "inexplicabley", "inexplicably", + "inexplicablly", "inexplicably", + "infilitration", "infiltration", + "infrastructre", "infrastructure", + "infrastrucure", "infrastructure", + "inintelligent", "unintelligent", + "ininteresting", "uninteresting", + "initalisation", "initialisation", + "initalization", "initialization", + "inperfections", "imperfections", + "inpersonating", "impersonating", + "inpossibility", "impossibility", + "inpredictable", "unpredictable", + "inresponsible", "irresponsible", + "insectiverous", "insectivorous", + "insecuritites", "insecurities", + "insiginficant", "insignificant", + "insiginifcant", "insignificant", + "insignificent", "insignificant", + "insignificunt", "insignificant", + "insignifigant", "insignificant", + "insiprational", "inspirational", + "insperational", "inspirational", + "inspiritional", "inspirational", + "inspriational", "inspirational", + "instantaenous", "instantaneous", + "instantanious", "instantaneous", + "instanteneous", "instantaneous", + "instantenious", "instantaneous", + "instincitvely", "instinctively", + "instinctivley", "instinctively", + "instititional", "institutional", + "institutionel", "institutional", + "insturmentals", "instrumental", + "instutitional", "institutional", + "insustainable", "unsustainable", + "intelelctuals", "intellectuals", + "intellectualy", "intellectually", + "intellectuels", "intellectuals", + "intellecutals", "intellectuals", + "intellegently", "intelligently", + "intelluctuals", "intellectuals", + "intepretation", "interpretation", + "intereactions", "intersections", + "interesctions", "intersections", + "interlectuals", "intellectuals", + "intermittient", "intermittent", + "intermittment", "intermittent", + "internacional", "international", + "interpersonel", "interpersonal", + "interpresonal", "interpersonal", + "interpretaion", "interpretation", + "interpretarea", "interpreter", + "interpretarem", "interpreter", + "interpretares", "interpreter", + "interpretarse", "interpreter", + "interpretarte", "interpreter", + "interpretatin", "interpretations", + "interpreteert", "interpreter", + "interragation", "interrogation", + "interregation", "interrogation", + "interrigation", "interrogation", + "interrogacion", "interrogation", + "interrogativo", "interrogation", + "intertainment", "entertainment", + "intillectuals", "intellectuals", + "intraspection", "introspection", + "intrensically", "intrinsically", + "intriniscally", "intrinsically", + "intrinsecally", "intrinsically", + "intrisincally", "intrinsically", + "intristically", "intrinsically", + "introductiory", "introductory", + "introspeccion", "introspection", + "introspectivo", "introspection", + "introspektion", "introspection", + "invertibrates", "invertebrates", + "invesitgation", "investigation", + "invesitgative", "investigative", + "invesitgators", "investigators", + "investagators", "investigators", + "investegating", "investigating", + "investegators", "investigators", + "investiagtion", "investigation", + "investiagtive", "investigative", + "investigacion", "investigation", + "investigaiton", "investigations", + "investigaters", "investigators", + "investigativo", "investigation", + "investigatons", "investigations", + "investigsting", "investigating", + "investigstion", "investigations", + "investogators", "investigators", + "invisibillity", "invisibility", + "involuntarely", "involuntary", + "involuntarity", "involuntary", + "invulnerabile", "invulnerable", + "irrationallly", "irrationally", + "irresponcible", "irresponsible", + "irresponisble", "irresponsible", + "irresponsable", "irresponsible", + "irresponsbile", "irresponsible", + "irreversiable", "irreversible", + "irreversibelt", "irreversible", + "irreversibile", "irreversible", + "irrisponsible", "irresponsible", + "jacksonvillle", "jacksonville", + "journalisitic", "journalistic", + "journalistens", "journalists", + "journalisters", "journalists", + "journalistisk", "journalists", + "jsutification", "justifications", + "jurisdicitons", "jurisdictions", + "jurisidctions", "jurisdictions", + "juristictions", "jurisdictions", + "jursidictions", "jurisdictions", + "jusitfication", "justifications", + "justifiaction", "justifications", + "justificacion", "justification", + "justificaiton", "justification", + "justificativo", "justification", + "justificatons", "justifications", + "justificstion", "justifications", + "justiifcation", "justifications", + "karbohydrates", "carbohydrates", + "knoweldgeable", "knowledgeable", + "knowledegable", "knowledgeable", + "knowledgebale", "knowledgable", + "knowlegdeable", "knowledgeable", + "kollaboration", "collaboration", + "koncentration", "concentration", + "konfiguration", "configuration", + "konfrontation", "confrontation", + "konservatives", "conservatives", + "konstellation", "constellation", + "kontamination", "contamination", + "legitimatelly", "legitimately", + "libertariaism", "libertarianism", + "libertariansm", "libertarianism", + "libitarianisn", "libertarianism", + "lighthearthed", "lighthearted", + "mainfestation", "manifestation", + "manafacturers", "manufacturers", + "manafacturing", "manufacturing", + "manafestation", "manifestation", + "manefestation", "manifestation", + "manfuacturers", "manufactures", + "manifacturers", "manufacturers", + "manifacturing", "manufacturing", + "manifastation", "manifestation", + "manifestacion", "manifestation", + "manifestating", "manifestation", + "manifistation", "manifestation", + "manipulationg", "manipulating", + "manufacterers", "manufacturers", + "manufactering", "manufacturing", + "manufacterurs", "manufactures", + "manufactorers", "manufacturers", + "manufactoring", "manufacturing", + "manufactuered", "manufactured", + "manufactuerer", "manufacturer", + "manufactueres", "manufactures", + "manufacturedd", "manufactured", + "manufactureds", "manufactures", + "manufacturerd", "manufactured", + "manufacturier", "manufacturer", + "manufacturors", "manufacturers", + "manufactuters", "manufactures", + "manufacutrers", "manufactures", + "manufcaturers", "manufactures", + "marshmalllows", "marshmallows", + "massachsuetts", "massachusetts", + "massachucetts", "massachusetts", + "massachuestts", "massachusetts", + "massachusents", "massachusetts", + "massachusites", "massachusetts", + "massachussets", "massachusetts", + "massechusetts", "massachusetts", + "masturbateing", "masturbating", + "materialisimo", "materialism", + "mathamatician", "mathematician", + "mathametician", "mathematician", + "mathematicals", "mathematics", + "mathematicaly", "mathematically", + "mathematicans", "mathematics", + "mathematicion", "mathematician", + "mathematitian", "mathematician", + "mathemetician", "mathematician", + "mathmatically", "mathematically", + "mathmaticians", "mathematicians", + "mechanicallly", "mechanically", + "medeterranean", "mediterranean", + "meditarrenean", "mediterranean", + "meditereanean", "mediterranean", + "membranaphone", "membranophone", + "metamorphysis", "metamorphosis", + "metaphoricaly", "metaphorically", + "metaphoricial", "metaphorical", + "metaphysicals", "metaphysics", + "metaphysicans", "metaphysics", + "methamatician", "mathematician", + "methematician", "mathematician", + "metropolitain", "metropolitan", + "metropolitcan", "metropolitan", + "metropolitian", "metropolitan", + "millionairres", "millionaire", + "minneapolites", "minneapolis", + "misanderstood", "misunderstood", + "miscellanious", "miscellaneous", + "misconcpetion", "misconceptions", + "misconecption", "misconceptions", + "misinterperet", "misinterpret", + "misinterprate", "misinterpret", + "misinterprent", "misinterpret", + "misinterprted", "misinterpret", + "misogynisitic", "misogynistic", + "misrepreseted", "misrepresented", + "misunterstood", "misunderstood", + "modificaitons", "modifications", + "motivationals", "motivations", + "motivationnal", "motivational", + "mulitnational", "multinational", + "multimational", "multinational", + "multiplicaton", "multiplication", + "muncipalities", "municipalities", + "munnicipality", "municipality", + "mutlinational", "multinational", + "nacionalistic", "nationalistic", + "narcissisitic", "narcissistic", + "narcississtic", "narcissistic", + "natioanlistic", "nationalistic", + "nationalisitc", "nationalistic", + "nationalistes", "nationalists", + "nationalsitic", "nationalistic", + "neigbhourhood", "neighbourhood", + "neighboorhoud", "neighbourhood", + "neighborehood", "neighbourhood", + "neighborhoood", "neighborhoods", + "neighbourbood", "neighbourhood", + "neighbourgood", "neighbourhood", + "neighbourhoud", "neighbourhood", + "neighourhoods", "neighborhoods", + "nieghborhoods", "neighborhoods", + "nieghbourhood", "neighbourhood", + "noncombatents", "noncombatants", + "noninitalized", "noninitialized", + "northwestener", "northwestern", + "notificaitons", "notifications", + "occassionally", "occasionally", + "operationable", "operational", + "oppertunities", "opportunities", + "opprotunities", "opportunities", + "oppurtunities", "opportunities", + "opthamologist", "ophthalmologist", + "organistaions", "organisations", + "organizatinal", "organizational", + "organizativos", "organizations", + "organsiations", "organisations", + "organziations", "organizations", + "orginasations", "organisations", + "orginazations", "organizations", + "overpopulaton", "overpopulation", + "overreactiong", "overreacting", + "overshaddowed", "overshadowed", + "overwheliming", "overwhelming", + "overwhelmigly", "overwhelmingly", + "overwhelmingy", "overwhelmingly", + "overwhelminly", "overwhelmingly", + "palestininans", "palestinians", + "paraphraseing", "paraphrasing", + "paraphrashing", "paraphrasing", + "parilamentary", "parliamentary", + "parlaimentary", "parliamentary", + "parliamantary", "parliamentary", + "parliamentery", "parliamentary", + "parliamnetary", "parliamentary", + "parliementary", "parliamentary", + "particiaption", "participation", + "participacion", "participation", + "participantes", "participants", + "participativo", "participation", + "particularely", "particularly", + "particularily", "particularly", + "particularlly", "particularly", + "partizipation", "participation", + "passionatelly", "passionately", + "paychiatrists", "psychiatrists", + "paychologists", "psychologists", + "pennsylvainia", "pennsylvania", + "pennsylvanica", "pennsylvania", + "pennsylvannia", "pennsylvania", + "perdominantly", "predominantly", + "perpandicular", "perpendicular", + "perpendicualr", "perpendicular", + "perpenticular", "perpendicular", + "perpetuationg", "perpetuating", + "perpindicular", "perpendicular", + "personalitits", "personalities", + "pessimistisch", "pessimistic", + "pharmaceutial", "pharmaceutical", + "philisophical", "philosophical", + "philosiphical", "philosophical", + "philosohpical", "philosophical", + "philosophycal", "philosophically", + "philospohical", "philosophical", + "phisiological", "physiological", + "photagraphers", "photographers", + "photographics", "photographs", + "photographied", "photographed", + "photographier", "photographer", + "photograpphed", "photographed", + "photogrophers", "photographers", + "photogrpahers", "photographers", + "photoshoppade", "photoshopped", + "photoshoppped", "photoshopped", + "phsyiological", "physiological", + "phychiatrists", "psychiatrists", + "phychological", "psychological", + "phychologists", "psychologists", + "phylosophical", "philosophical", + "physciatrists", "psychiatrists", + "physcological", "psychological", + "physcologists", "psychologists", + "physioligical", "physiological", + "planeswlakers", "planeswalker", + "plansewalkers", "planeswalker", + "playthroughts", "playthroughs", + "polysaccaride", "polysaccharide", + "practicallity", "practically", + "practicioners", "practitioners", + "practisioners", "practitioners", + "practitioneer", "practitioners", + "practitionner", "practitioner", + "pratictioners", "practitioners", + "preconceieved", "preconceived", + "predecessores", "predecessors", + "predetermiend", "predetermined", + "predetirmined", "predetermined", + "preditermined", "predetermined", + "predomenantly", "predominantly", + "predominently", "predominantly", + "pregressively", "progressively", + "preinitalized", "preinitialized", + "preinitalizes", "preinitializes", + "preliferation", "proliferation", + "prependicular", "perpendicular", + "preposterious", "preposterous", + "prerequisties", "prerequisite", + "prerequistite", "prerequisite", + "prescribtions", "prescriptions", + "presumptuious", "presumptuous", + "pretedermined", "predetermined", + "problematisch", "problematic", + "proclaimation", "proclamation", + "prodominantly", "predominantly", + "professionnal", "professional", + "profitiablity", "profitability", + "profitibality", "profitability", + "progressivily", "progressively", + "progressivley", "progressively", + "prononciation", "pronunciation", + "pronouciation", "pronunciation", + "pronunciacion", "pronunciation", + "pronunciating", "pronunciation", + "pronuncuation", "pronunciation", + "pronunication", "pronunciation", + "pronuntiation", "pronunciation", + "propabilities", "probabilities", + "proportionaly", "proportionally", + "proportionnal", "proportional", + "proseletyzing", "proselytizing", + "protagonistas", "protagonists", + "protagonistes", "protagonists", + "protestantisk", "protestants", + "protruberance", "protuberance", + "provocativley", "provocative", + "pscyhiatrists", "psychiatrists", + "pscyhological", "psychological", + "pscyhologists", "psychologists", + "pshycological", "psychological", + "pshycologists", "psychologists", + "psichological", "psychological", + "psychaitrists", "psychiatrists", + "psychedellics", "psychedelics", + "psychiatrisch", "psychiatric", + "psycholigical", "psychological", + "psycholigists", "psychologists", + "psychologycal", "psychologically", + "psychologysts", "psychologists", + "psychyatrists", "psychiatrists", + "psysiological", "physiological", + "purpendicular", "perpendicular", + "pyschiatrists", "psychiatrists", + "pyschological", "psychological", + "pyschologists", "psychologists", + "qaulification", "qualification", + "qualifiaction", "qualification", + "qualificaiton", "qualifications", + "qualificatons", "qualifications", + "qualifikation", "qualification", + "questionalble", "questionable", + "quinessential", "quintessential", + "ramificaitons", "ramifications", + "realisitcally", "realistically", + "realtionships", "relationships", + "reccommending", "recommending", + "receptionnist", "receptionist", + "receptionsist", "receptionist", + "reconaissance", "reconnaissance", + "reconcilation", "reconciliation", + "reconnaisance", "reconnaissance", + "reconstrucion", "reconstruction", + "recreationnal", "recreational", + "rectangulaire", "rectangular", + "redistribuito", "redistribution", + "redistributin", "redistribution", + "reencarnation", "reincarnation", + "refridgerator", "refrigerator", + "rehabilitaion", "rehabilitation", + "rehabilitatin", "rehabilitation", + "rehabilitaton", "rehabilitation", + "reincarantion", "reincarnation", + "reincatnation", "reincarnation", + "reinforcemens", "reinforcements", + "reinforcemnts", "reinforcements", + "reinitalising", "reinitialising", + "reinitalizing", "reinitializing", + "reinkarnation", "reincarnation", + "reinstallling", "reinstalling", + "reintarnation", "reincarnation", + "relationshits", "relationships", + "relationsship", "relationships", + "relatiopnship", "relationship", + "relentlessely", "relentlessly", + "relentlessley", "relentlessly", + "relinqushment", "relinquishment", + "remifications", "ramifications", + "reprehenisble", "reprehensible", + "reprehensable", "reprehensible", + "reprehinsible", "reprehensible", + "represenation", "representation", + "represensible", "reprehensible", + "representaion", "representation", + "representatie", "representatives", + "representatin", "representations", + "representerad", "represented", + "representitve", "representative", + "representives", "representatives", + "repricussions", "repercussions", + "reprihensible", "reprehensible", + "resolutionary", "revolutionary", + "respectivelly", "respectively", + "responsibiliy", "responsibility", + "responsibilty", "responsibility", + "responsiblity", "responsibility", + "respositories", "repositories", + "resssurecting", "resurrecting", + "ressurrection", "resurrection", + "restaraunteur", "restaurateur", + "retoractively", "retroactively", + "retroactivily", "retroactively", + "retroactivley", "retroactively", + "retrocatively", "retroactively", + "revelutionary", "revolutionary", + "revolutionair", "revolutionary", + "revolutionens", "revolutions", + "revolutioners", "revolutions", + "revoultionary", "revolutionary", + "ridiculouness", "ridiculousness", + "rienforcement", "reinforcements", + "righetousness", "righteousness", + "rightiousness", "righteousness", + "rigtheousness", "righteousness", + "rollarcoaster", "rollercoaster", + "rollercaoster", "rollercoaster", + "rollercoaters", "rollercoaster", + "rollercoatser", "rollercoaster", + "rollerocaster", "rollercoaster", + "rollertoaster", "rollercoaster", + "rollorcoaster", "rollercoaster", + "sacrastically", "sarcastically", + "sarcasitcally", "sarcastically", + "satisfactorly", "satisfactory", + "scandianvians", "scandinavian", + "scateboarding", "skateboarding", + "schisophrenic", "schizophrenic", + "schiziphrenic", "schizophrenic", + "schizophernia", "schizophrenia", + "schizophernic", "schizophrenic", + "schizophrania", "schizophrenia", + "schizoprhenia", "schizophrenia", + "schizoprhenic", "schizophrenic", + "schozophrenia", "schizophrenia", + "schozophrenic", "schizophrenic", + "schyzophrenia", "schizophrenia", + "schyzophrenic", "schizophrenic", + "schziophrenia", "schizophrenia", + "schziophrenic", "schizophrenic", + "scientificaly", "scientifically", + "scientificlly", "scientifically", + "segementation", "segmentation", + "sensationable", "sensational", + "sensationails", "sensationalism", + "sensationaism", "sensationalism", + "sensationalim", "sensationalism", + "sensationella", "sensational", + "shcizophrenic", "schizophrenic", + "significanlty", "significantly", + "significently", "significantly", + "signifigantly", "significantly", + "simultaneosly", "simultaneously", + "simultaneuous", "simultaneous", + "simultanously", "simultaneously", + "singificantly", "significantly", + "skatebaording", "skateboarding", + "skateborading", "skateboarding", + "socioecenomic", "socioeconomic", + "socioecomonic", "socioeconomic", + "socioeconimic", "socioeconomic", + "sohpisticated", "sophisticated", + "sophisitcated", "sophisticated", + "sophistacated", "sophisticated", + "sophistocated", "sophisticated", + "sophosticated", "sophisticated", + "spacification", "specification", + "specializaton", "specialization", + "specificaiton", "specifications", + "specificatons", "specifications", + "specifikation", "specification", + "spectaculaire", "spectacular", + "spectaculalry", "spectacularly", + "spectatularly", "spectacularly", + "spesification", "specification", + "spirituallity", "spiritually", + "sponatenously", "spontaneously", + "spontaenously", "spontaneously", + "spontainously", "spontaneously", + "spontaneoulsy", "spontaneously", + "spontaneuosly", "spontaneously", + "spontaniously", "spontaneously", + "spontanuously", "spontaneously", + "sponteanously", "spontaneously", + "sponteneously", "spontaneously", + "sporstmanship", "sportsmanship", + "sportmansship", "sportsmanship", + "sportsmamship", "sportsmanship", + "sportsmenship", "sportsmanship", + "sprotsmanship", "sportsmanship", + "stakeboarding", "skateboarding", + "startegically", "strategically", + "statisitcally", "statistically", + "statistacally", "statistically", + "stereotipical", "stereotypical", + "stereotpyical", "stereotypical", + "stereotypcial", "stereotypical", + "stereotypeing", "stereotyping", + "stereotypying", "stereotyping", + "steriotypical", "stereotypical", + "steroetypical", "stereotypical", + "steryotypical", "stereotypical", + "storytellling", "storytelling", + "stragegically", "strategically", + "stragetically", "strategically", + "straightenend", "straightened", + "straitforward", "straightforward", + "stratagically", "strategically", + "stratigically", "strategically", + "strawberrries", "strawberries", + "stregnthening", "strengthening", + "strenghtening", "strengthening", + "strengthining", "strengthening", + "stretegically", "strategically", + "subcatagories", "subcategories", + "subconsciosly", "subconsciously", + "subconsciouly", "subconsciously", + "subconsiously", "subconsciously", + "subjectivelly", "subjectively", + "subscribtions", "subscriptions", + "substancially", "substantially", + "substanitally", "substantially", + "substansially", "substantially", + "substantiable", "substantial", + "substantually", "substantially", + "substitutents", "substitutes", + "successfullly", "successfully", + "supermarkedet", "supermarket", + "supermarkerts", "supermarkets", + "superpowereds", "superpowers", + "supersticious", "superstitious", + "superstisious", "superstitious", + "superstitiosi", "superstitious", + "superstitiuos", "superstitious", + "superstituous", "superstitious", + "suphisticated", "sophisticated", + "supscriptions", "subscriptions", + "surreptiously", "surreptitiously", + "survavibility", "survivability", + "survibability", "survivability", + "survivabiltiy", "survivability", + "survivalibity", "survivability", + "survivavility", "survivability", + "survivebility", "survivability", + "susbtantially", "substantially", + "sustainabilty", "sustainability", + "synchornously", "synchronously", + "systematicaly", "systematically", + "systematiclly", "systematically", + "techmological", "technological", + "technicallity", "technically", + "technoligical", "technological", + "technologicly", "technological", + "techonlogical", "technological", + "telaportation", "teleportation", + "teleportating", "teleportation", + "teleprotation", "teleportation", + "teliportation", "teleportation", + "teloportation", "teleportation", + "territoriella", "territorial", + "theoratically", "theoretically", + "theoritically", "theoretically", + "therapeutisch", "therapeutic", + "thereotically", "theoretically", + "thermodynaics", "thermodynamics", + "thermodynamcs", "thermodynamics", + "theroetically", "theoretically", + "thoeretically", "theoretically", + "tranistioning", "transitioning", + "transcendance", "transcendence", + "transcribtion", "transcription", + "transcripcion", "transcription", + "transferrring", "transferring", + "transformarea", "transformer", + "transformarem", "transformer", + "transformarse", "transformers", + "transformaton", "transformation", + "transformered", "transformed", + "transgengered", "transgendered", + "transisioning", "transitioning", + "transitionals", "transitions", + "transitionnal", "transitional", + "transitionned", "transitioned", + "transkription", "transcription", + "translyvanian", "transylvania", + "transmisisons", "transmissions", + "transmissable", "transmissible", + "transmisssion", "transmissions", + "transparantie", "transparent", + "transparentcy", "transparency", + "transplantees", "transplants", + "transporation", "transportation", + "transportaion", "transportation", + "transportarme", "transporter", + "transportarse", "transporter", + "transportarte", "transporter", + "transporteurs", "transporter", + "transsexuella", "transsexual", + "transylvannia", "transylvania", + "trasngendered", "transgendered", + "troubleshooot", "troubleshoot", + "udnerestimate", "underestimated", + "umcomfortable", "uncomfortable", + "umcomfortably", "uncomfortably", + "umpredictable", "unpredictable", + "unappropriate", "inappropriate", + "unbelievabley", "unbelievably", + "unbelievablly", "unbelievably", + "uncertaintity", "uncertainty", + "uncomfertable", "uncomfortable", + "uncomfertably", "uncomfortably", + "uncomfortabel", "uncomfortably", + "uncomforyable", "uncomfortably", + "uncomfrotable", "uncomfortable", + "uncomfrotably", "uncomfortably", + "uncomftorable", "uncomfortable", + "uncomftorably", "uncomfortably", + "unconcsiously", "unconsciously", + "unconfortable", "uncomfortable", + "unconfortably", "uncomfortably", + "unconscioulsy", "unconsciously", + "unconsicously", "unconsciously", + "unconsiderate", "inconsiderate", + "uncontrollabe", "uncontrollable", + "uncontrollaby", "uncontrollably", + "unconventinal", "unconventional", + "uncounciously", "unconsciously", + "uncousciously", "unconsciously", + "underastimate", "underestimate", + "underesitmate", "underestimated", + "underestamate", "underestimate", + "underestemate", "underestimate", + "underestiamte", "underestimated", + "undergratuate", "undergraduate", + "underhwelming", "underwhelming", + "underhwleming", "underwhelming", + "underminining", "undermining", + "underpowererd", "underpowered", + "undersetimate", "underestimate", + "understandble", "understandable", + "understandbly", "understandably", + "underwealming", "underwhelming", + "underwhemling", "underwhelming", + "underwhleming", "underwhelming", + "undoctrinated", "indoctrinated", + "unexpectadely", "unexpectedly", + "unfomfortable", "uncomfortable", + "unforgiveable", "unforgivable", + "unfortuantely", "unfortunately", + "unfortunantly", "unfortunately", + "unfortunatley", "unfortunately", + "unfortuneatly", "unfortunately", + "unfortunetely", "unfortunately", + "unilaterallly", "unilaterally", + "uninstallling", "uninstalling", + "unintellegent", "unintelligent", + "unintelligant", "unintelligent", + "unintensional", "unintentional", + "uninteristing", "uninteresting", + "universitites", "universities", + "unnecassarily", "unnecessarily", + "unneccesarily", "unnecessarily", + "unnecessairly", "unnecessarily", + "unnecessarely", "unnecessarily", + "unnecessarity", "unnecessarily", + "unnecesserily", "unnecessarily", + "unnecissarily", "unnecessarily", + "unnessecarily", "unnecessarily", + "unoperational", "nonoperational", + "unprecendeted", "unprecedented", + "unprecidented", "unprecedented", + "unpredecented", "unprecedented", + "unpredicatble", "unpredictable", + "unpredictible", "unpredictable", + "unpresedented", "unprecedented", + "unpridictable", "unpredictable", + "unprofessinal", "unprofessional", + "unrealistisch", "unrealistic", + "unreasonabley", "unreasonably", + "unreasonablly", "unreasonably", + "unrestrictred", "unrestricted", + "unsistainable", "unsustainable", + "unsubscribade", "unsubscribed", + "unsubscribbed", "unsubscribe", + "unsuccesfully", "unsuccessfully", + "unsuccessfull", "unsuccessful", + "unsucessfully", "unsuccessfully", + "unsuprisingly", "unsurprisingly", + "unsuprizingly", "unsurprisingly", + "unsustainible", "unsustainable", + "unsustianable", "unsustainable", + "vertification", "certification", + "villification", "vilification", + "virualization", "visualization", + "visualizacion", "visualization", + "visualizaiton", "visualization", + "visualizating", "visualization", + "vitualization", "visualization", + "vizualization", "visualization", + "volounteering", "volunteering", + "vulberability", "vulnerability", + "vulernability", "vulnerability", + "vulnarability", "vulnerability", + "vulnerabiltiy", "vulnerability", + "vulnurability", "vulnerability", + "vunlerability", "vulnerability", + "vurnerability", "vulnerability", + "weightlfiting", "weightlifting", + "weightlifitng", "weightlifting", + "weightligting", "weightlifting", + "weigthlifting", "weightlifting", + "wholeheartdly", "wholeheartedly", + "wholeheartedy", "wholeheartedly", + "wholeheartely", "wholeheartedly", + "wieghtlifting", "weightlifting", + "abberivation", "abbreviation", + "abberviation", "abbreviation", + "abbreivation", "abbreviation", + "abbreveation", "abbreviation", + "abbrievation", "abbreviation", + "abortificant", "abortifacient", + "abrreviation", "abbreviation", + "academcially", "academically", + "accedentally", "accidentally", + "accelarating", "accelerating", + "accelaration", "acceleration", + "acceleartion", "acceleration", + "acceleraptor", "accelerator", + "accelorating", "accelerating", + "accessibilty", "accessibility", + "accidentlaly", "accidently", + "accomadating", "accommodating", + "accomadation", "accommodation", + "accomodating", "accommodating", + "accomodation", "accommodation", + "accrediation", "accreditation", + "acculumation", "accumulation", + "accumalation", "accumulation", + "accumilation", "accumulation", + "acedemically", "academically", + "acheivements", "achievements", + "acknolwedged", "acknowledged", + "acknolwedges", "acknowledges", + "acknoweldged", "acknowledged", + "acknoweldges", "acknowledges", + "acknowiedged", "acknowledged", + "acknowladges", "acknowledges", + "acknowldeged", "acknowledged", + "acknowledget", "acknowledgement", + "acknowleding", "acknowledging", + "acknowlegded", "acknowledged", + "acknowlegdes", "acknowledges", + "ackumulation", "accumulation", + "acquaintaces", "acquaintances", + "acquaintence", "acquaintance", + "acquantaince", "acquaintance", + "acquantiance", "acquaintances", + "acquiantance", "acquaintances", + "acquiantence", "acquaintance", + "adknowledged", "acknowledged", + "adknowledges", "acknowledges", + "administored", "administer", + "adminsitered", "administered", + "adminstrator", "administrator", + "advantagious", "advantageous", + "advantegeous", "advantageous", + "adventageous", "advantageous", + "adventureous", "adventures", + "adventureres", "adventures", + "adventurious", "adventurous", + "adventuruous", "adventurous", + "advertisiers", "advertisers", + "advertisment", "advertisement", + "advertisters", "advertisers", + "advertisting", "advertising", + "aestheticaly", "aesthetically", + "aestheticlly", "aesthetically", + "afficianados", "aficionados", + "afficionados", "aficionados", + "afghanisthan", "afghanistan", + "afterhtought", "afterthought", + "afterthougth", "afterthought", + "aggressivley", "aggressively", + "agircultural", "agricultural", + "agknowledged", "acknowledged", + "agnosticisim", "agnosticism", + "agracultural", "agricultural", + "agriculteral", "agricultural", + "agriculteurs", "agriculture", + "agricultrual", "agricultural", + "agriculutral", "agricultural", + "agrigultural", "agricultural", + "agrocultural", "agricultural", + "allegiancies", "allegiance", + "alterantives", "alternatives", + "alternatevly", "alternately", + "alternatiely", "alternately", + "alternatieve", "alternative", + "alternativly", "alternatively", + "alternativos", "alternatives", + "alternatvely", "alternately", + "alternitives", "alternatives", + "altruistisch", "altruistic", + "amendmenters", "amendments", + "amohetamines", "amphetamines", + "ampehtamines", "amphetamines", + "ampethamines", "amphetamines", + "amphatamines", "amphetamines", + "amphedamines", "amphetamines", + "amphetamenes", "amphetamines", + "amphetemines", "amphetamines", + "amphetimines", "amphetamines", + "amphetmaines", "amphetamines", + "anecdotallly", "anecdotally", + "annhiliation", "annihilation", + "annihalition", "annihilation", + "annihilatron", "annihilation", + "annihliation", "annihilation", + "annilihation", "annihilation", + "anniversairy", "anniversary", + "anniversarry", "anniversary", + "anniversiary", "anniversary", + "annoucenment", "announcements", + "annoucnement", "announcement", + "announcemnet", "announcements", + "announcemnts", "announcements", + "anphetamines", "amphetamines", + "ansalisation", "nasalisation", + "ansalization", "nasalization", + "antaganistic", "antagonistic", + "antagonisitc", "antagonistic", + "antagonostic", "antagonist", + "antibioticos", "antibiotics", + "anticiaption", "anticipation", + "anticipacion", "anticipation", + "antisipation", "anticipation", + "antogonistic", "antagonistic", + "antrhopology", "anthropology", + "antrophology", "anthropology", + "apllications", "applications", + "apocalypitic", "apocalyptic", + "apologistics", "apologists", + "apologizeing", "apologizing", + "apostrophied", "apostrophe", + "apostrophies", "apostrophe", + "apperciation", "appreciation", + "applicaitons", "applications", + "appoitnments", "appointments", + "apporachable", "approachable", + "appraochable", "approachable", + "appreceating", "appreciating", + "appreciaters", "appreciates", + "appreciatied", "appreciative", + "appreicating", "appreciating", + "appreication", "appreciation", + "appretiation", "appreciation", + "appropriatin", "appropriation", + "appropriatly", "appropriately", + "appropriaton", "appropriation", + "approprietly", "appropriately", + "approstraphe", "apostrophe", + "approxiately", "approximately", + "approximatly", "approximately", + "approximetly", "approximately", + "aproximately", "approximately", + "aqcuaintance", "acquaintance", + "aqquaintance", "acquaintance", + "arbitrariliy", "arbitrarily", + "arbitrarilly", "arbitrarily", + "archetecture", "architecture", + "architechure", "architecture", + "architectual", "architectural", + "architectuur", "architecture", + "architecutre", "architecture", + "architexture", "architecture", + "arcitechture", "architecture", + "areodynamics", "aerodynamics", + "argicultural", "agricultural", + "argumentatie", "argumentative", + "arithmetisch", "arithmetic", + "armageddomon", "armageddon", + "arrengements", "arrangements", + "articifially", "artificially", + "artificailly", "artificially", + "artificiella", "artificial", + "artificually", "artificially", + "artifiically", "artificially", + "assasination", "assassination", + "assassinatin", "assassination", + "assissinated", "assassinated", + "associationg", "associating", + "assoications", "associations", + "assosiations", "associations", + "assosication", "assassination", + "assotiations", "associations", + "assymetrical", "asymmetrical", + "asthetically", "aesthetically", + "astranomical", "astronomical", + "astromonical", "astronomical", + "astronautlis", "astronauts", + "astronimical", "astronomical", + "astronomicly", "astronomical", + "athleticisim", "athleticism", + "atmosphereic", "atmospheric", + "audiobookmrs", "audiobooks", + "auhtenticate", "authenticate", + "australianas", "australians", + "australianos", "australians", + "authentisity", "authenticity", + "authorithies", "authorities", + "authoritiers", "authorities", + "authorizaton", "authorization", + "authrorities", "authorities", + "autochtonous", "autochthonous", + "autocorrrect", "autocorrect", + "automobilies", "automobile", + "automodertor", "automoderator", + "automonomous", "autonomous", + "auxilliaries", "auxiliaries", + "avaliability", "availability", + "avialability", "availability", + "awknowledged", "acknowledged", + "awknowledges", "acknowledges", + "awkwardsness", "awkwardness", + "babysittting", "babysitting", + "beaurocratic", "bureaucratic", + "beautifullly", "beautifully", + "belligerante", "belligerent", + "beuraucratic", "bureaucratic", + "billionairre", "billionaire", + "billionaries", "billionaires", + "billioniares", "billionaires", + "bioligically", "biologically", + "birmingharam", "birmingham", + "bittersweeet", "bittersweet", + "blamethrower", "flamethrower", + "blueberrries", "blueberries", + "blueprintcss", "blueprints", + "boardcasting", "broadcasting", + "bobybuilding", "bodybuilding", + "bodybuidling", "bodybuilding", + "bodybuilidng", "bodybuilding", + "bodybuliding", "bodybuilding", + "bodydbuilder", "bodybuilder", + "bombardement", "bombardment", + "boradcasting", "broadcasting", + "botivational", "motivational", + "brainwahsing", "brainwashing", + "brakethrough", "breakthrough", + "braodcasting", "broadcasting", + "brazilianese", "brazilians", + "brazilianess", "brazilians", + "breakthorugh", "breakthrough", + "breaktrhough", "breakthrough", + "breastfeedig", "breastfeeding", + "breastfeeing", "breastfeeding", + "breasttaking", "breathtaking", + "brianwashing", "brainwashing", + "broadcastors", "broadcasts", + "brotherhoood", "brotherhood", + "buearucratic", "bureaucratic", + "bueraucratic", "bureaucratic", + "bulletprooof", "bulletproof", + "bureaocratic", "bureaucratic", + "bureaucracie", "bureaucratic", + "bureaucracts", "bureaucrats", + "bureaucrates", "bureaucrats", + "bureuacratic", "bureaucratic", + "businessemen", "businessmen", + "cababilities", "capabilities", + "caclulations", "calculations", + "calcluations", "calculation", + "calcualtions", "calculations", + "calculationg", "calculating", + "calculatoare", "calculator", + "californains", "californian", + "californican", "californian", + "californinan", "californian", + "caluclations", "calculations", + "camouflagued", "camouflage", + "canceltation", "cancellation", + "cannibalisim", "cannibalism", + "canniballism", "cannibalism", + "cannotations", "connotations", + "capitalistes", "capitalists", + "caracterized", "characterized", + "carbohydrats", "carbohydrates", + "carbohyrdate", "carbohydrates", + "caricaturale", "caricature", + "caricaturile", "caricature", + "caricaturise", "caricature", + "caricaturize", "caricature", + "catastraphic", "catastrophic", + "catastrohpic", "catastrophic", + "catastrophie", "catastrophe", + "categoricaly", "categorically", + "categoriezed", "categorized", + "catergorized", "categorized", + "caterpillers", "caterpillars", + "catestrophic", "catastrophic", + "catholicisim", "catholicism", + "catholocisim", "catholicism", + "catistrophic", "catastrophic", + "catostraphic", "catastrophic", + "catostrophic", "catastrophic", + "catterpilars", "caterpillars", + "catterpillar", "caterpillar", + "celebratings", "celebrations", + "celebritites", "celebrities", + "celibrations", "celebrations", + "cententenial", "centennial", + "cercumstance", "circumstance", + "cerification", "verification", + "certificiate", "certificate", + "challengeing", "challenging", + "chamiponship", "championships", + "champinoship", "championships", + "championchip", "championship", + "championsihp", "championships", + "championsips", "championships", + "champiosnhip", "championships", + "champoinship", "championship", + "chanpionship", "championship", + "charactarize", "characterize", + "charaterized", "characterized", + "charismastic", "charismatic", + "cheerlearder", "cheerleader", + "cheerleeders", "cheerleaders", + "cheeseberger", "cheeseburger", + "cheeseborger", "cheeseburger", + "cheesebruger", "cheeseburgers", + "cheeseburges", "cheeseburgers", + "cheeseburgie", "cheeseburger", + "cheezeburger", "cheeseburger", + "chirstianity", "christianity", + "chocolateers", "chocolates", + "chrisitanity", "christianity", + "christainity", "christianity", + "christiantiy", "christianity", + "christinaity", "christianity", + "chromosomers", "chromosomes", + "chronologial", "chronological", + "chrsitianity", "christianity", + "cilivization", "civilizations", + "circulatiing", "circulating", + "circulationg", "circulating", + "circumcisied", "circumcised", + "circumcition", "circumcision", + "circumsicion", "circumcision", + "circumsision", "circumcision", + "circumsition", "circumcision", + "circumsizion", "circumcision", + "circumstanes", "circumstance", + "circumstanta", "circumstantial", + "circumstante", "circumstance", + "circuncision", "circumcision", + "circunstance", "circumstance", + "civiliaztion", "civilizations", + "civilizacion", "civilization", + "civilizaiton", "civilization", + "civilizatoin", "civilizations", + "civilizatons", "civilizations", + "civilziation", "civilizations", + "civizilation", "civilizations", + "claculations", "calculations", + "classificato", "classification", + "cockroachers", "cockroaches", + "coefficienct", "coefficient", + "coencidental", "coincidental", + "coincedental", "coincidental", + "coincidencal", "coincidental", + "coincidentia", "coincidental", + "coindidental", "coincidental", + "coinsidental", "coincidental", + "cointerpoint", "counterpoint", + "collaberator", "collaborate", + "collaboratie", "collaborate", + "collaboratin", "collaboration", + "collectivily", "collectively", + "collectivley", "collectively", + "colonialisim", "colonialism", + "colonizacion", "colonization", + "colonizators", "colonizers", + "colonozation", "colonization", + "combanations", "combinations", + "combonations", "combinations", + "comdemnation", "condemnation", + "comemmorates", "commemorates", + "comemoretion", "commemoration", + "comeptitions", "competitions", + "comfirmation", "confirmation", + "comfortabley", "comfortably", + "comfortablly", "comfortably", + "comissioning", "commissioning", + "commandemnts", "commandment", + "commandmants", "commandments", + "commandmends", "commandments", + "commemmorate", "commemorate", + "commendments", "commandments", + "commenteries", "commenters", + "commenwealth", "commonwealth", + "commerciales", "commercials", + "commerically", "commercially", + "comminicated", "communicated", + "commishioned", "commissioned", + "commishioner", "commissioner", + "commisioning", "commissioning", + "commissionar", "commissioner", + "commissionor", "commissioner", + "committments", "commitments", + "commoditites", "commodities", + "commomwealth", "commonwealth", + "commonhealth", "commonwealth", + "commonweatlh", "commonwealth", + "commonwelath", "commonwealth", + "communciated", "communicated", + "communiation", "communication", + "communicatie", "communicate", + "communicatin", "communications", + "communicaton", "communication", + "communitites", "communities", + "compansating", "compensating", + "compansation", "compensation", + "comparativly", "comparatively", + "comparisions", "comparisons", + "comparission", "comparisons", + "comparissons", "comparisons", + "compatablity", "compatibility", + "compatibiliy", "compatibility", + "compatibilty", "compatibility", + "compatiblity", "compatibility", + "compensacion", "compensation", + "compensative", "compensate", + "compesitions", "compositions", + "competetions", "competitions", + "competitevly", "competitively", + "competitiion", "competition", + "competitiors", "competitors", + "competitivly", "competitively", + "competitivos", "competitions", + "compinsating", "compensating", + "compinsation", "compensation", + "complainging", "complaining", + "completetion", "completion", + "compliations", "compilation", + "complicacion", "complication", + "complicatied", "complicate", + "complicaties", "complicate", + "complicatred", "complicate", + "complicatted", "complicate", + "complilation", "complication", + "complimation", "complication", + "complimenary", "complimentary", + "complimentje", "complimented", + "complimentry", "complimentary", + "complination", "complication", + "complitation", "complication", + "composistion", "compositions", + "compramising", "compromising", + "compremising", "compromising", + "compresssion", "compression", + "compromissen", "compromise", + "compromisses", "compromises", + "compromizing", "compromising", + "compromosing", "compromising", + "comptability", "compatibility", + "compulsivley", "compulsive", + "compulsorary", "compulsory", + "computarized", "computerized", + "comrpomising", "compromising", + "comtaminated", "contaminated", + "comtemporary", "contemporary", + "conbinations", "combinations", + "concatinated", "contaminated", + "conceivabley", "conceivably", + "concellation", "cancellation", + "concentraded", "concentrated", + "concentraing", "concentrating", + "concentraion", "concentration", + "concentrarte", "concentrate", + "concentratie", "concentrate", + "concentratin", "concentration", + "concequences", "consequences", + "concequently", "consequently", + "concersation", "conservation", + "concervation", "conservation", + "concervatism", "conservatism", + "concervative", "conservative", + "conciderable", "considerable", + "conciderably", "considerably", + "conciousness", "consciousness", + "conclusiones", "conclusions", + "conclusivley", "conclusive", + "condamnation", "condemnation", + "condemantion", "condemnation", + "condenmation", "condemnation", + "condescening", "condescending", + "condescenion", "condescension", + "conditionnal", "conditional", + "conditionned", "conditioned", + "conditionner", "conditioner", + "condmenation", "condemnation", + "condolencies", "condolences", + "condolensces", "condolences", + "condomnation", "condemnation", + "condradicted", "contradicted", + "conenctivity", "connectivity", + "confedential", "confidential", + "confederancy", "confederacy", + "confederatie", "confederate", + "confermation", "confirmation", + "confersation", "conservation", + "confessionis", "confessions", + "confidencial", "confidential", + "confidentail", "confidential", + "confidentaly", "confidently", + "confidentely", "confidently", + "confidentiel", "confidential", + "configuratin", "configurations", + "configuraton", "configuration", + "confirmacion", "confirmation", + "confrimation", "confirmation", + "confrontaion", "confrontation", + "congegration", "congregation", + "congergation", "congregation", + "congradulate", "congratulate", + "congragation", "congregation", + "congragulate", "congratulate", + "congratualte", "congratulate", + "congregacion", "congregation", + "congresional", "congressional", + "congresssman", "congressman", + "congresssmen", "congressmen", + "congretation", "congregation", + "congrigation", "congregation", + "conicidental", "coincidental", + "connatations", "connotations", + "connecticuit", "connecticut", + "connectivety", "connectivity", + "connetations", "connotations", + "connitations", "connotations", + "connonations", "connotations", + "conolization", "colonization", + "conpensating", "compensating", + "conpensation", "compensation", + "conpetitions", "competitions", + "conplimented", "complimented", + "conpromising", "compromising", + "consciouness", "consciousness", + "consciouslly", "consciously", + "consectutive", "consecutive", + "consecuences", "consequences", + "consecuentes", "consequences", + "consecuently", "consequently", + "consensuarlo", "consensual", + "consentrated", "concentrated", + "consentrates", "concentrates", + "conseqeunces", "consequence", + "consequenses", "consequences", + "consequental", "consequently", + "consequneces", "consequence", + "conservacion", "conservation", + "conservaties", "conservatives", + "conservativo", "conservation", + "conservativs", "conservatism", + "conservitave", "conservatives", + "conservitism", "conservatism", + "conservitive", "conservative", + "considerarle", "considerable", + "considerarte", "considerate", + "consideraste", "considerate", + "consideratie", "considerate", + "consideratin", "considerations", + "consideribly", "considerably", + "consilidated", "consolidated", + "consipracies", "conspiracies", + "consiquently", "consequently", + "consistantly", "consistently", + "consistencey", "consistency", + "consistentcy", "consistently", + "consitutents", "constituents", + "consoldiated", "consolidated", + "consolitated", "consolidate", + "consolodated", "consolidated", + "consoltation", "consultation", + "conspericies", "conspiracies", + "conspiracize", "conspiracies", + "conspiriator", "conspirator", + "conspiricies", "conspiracies", + "conspriacies", "conspiracies", + "consqeuences", "consequence", + "constinually", "continually", + "constitition", "constitution", + "constituante", "constituents", + "constituants", "constituents", + "constituates", "constitutes", + "constitucion", "constitution", + "constituient", "constitute", + "constituinte", "constituents", + "constitutiei", "constitute", + "constitutues", "constitute", + "constiutents", "constituents", + "constracting", "constructing", + "constraction", "construction", + "constrainsts", "constraints", + "construccion", "construction", + "construciton", "construction", + "constructeds", "constructs", + "constructief", "constructive", + "constructies", "constructs", + "constructifs", "constructs", + "constructiin", "constructing", + "constructivo", "construction", + "consturction", "construction", + "consultating", "consultation", + "consumerisim", "consumerism", + "contaiminate", "contaminate", + "contaminatie", "contaminated", + "contaminaton", "contamination", + "contaminents", "containment", + "contamporary", "contemporary", + "contanimated", "contaminated", + "contaniments", "containment", + "contemperary", "contemporary", + "contemporany", "contemporary", + "continentais", "continents", + "continential", "continental", + "contineously", "continuously", + "continiously", "continuously", + "continuacion", "continuation", + "continuating", "continuation", + "continuativo", "continuation", + "continuining", "continuing", + "contirbution", "contribution", + "contirbutors", "contributors", + "contiunation", "continuation", + "contrabution", "contribution", + "contraceptie", "contraceptives", + "contradicing", "contradicting", + "contradicion", "contradiction", + "contradicory", "contradictory", + "contradictie", "contradicted", + "contradictin", "contradiction", + "contradicton", "contradiction", + "contraticted", "contradicted", + "contribucion", "contribution", + "contribuitor", "contributor", + "contributers", "contributors", + "contributivo", "contribution", + "contributons", "contributors", + "contrictions", "contractions", + "contridicted", "contradicted", + "controlleras", "controllers", + "controlllers", "controllers", + "controverial", "controversial", + "controveries", "controversies", + "controversal", "controversial", + "controversey", "controversy", + "contructions", "contractions", + "conveinently", "conveniently", + "convencional", "conventional", + "conveniantly", "conveniently", + "converastion", "conversations", + "converdation", "conservation", + "conversacion", "conversation", + "conversaiton", "conversations", + "conversatino", "conservation", + "conversatism", "conservatism", + "conversatoin", "conversations", + "conversiones", "conversions", + "converstaion", "conversation", + "convertables", "convertibles", + "convertiable", "convertible", + "convertibile", "convertible", + "convervation", "conservation", + "convervatism", "conservatism", + "converzation", "conservation", + "convesration", "conservation", + "convienently", "conveniently", + "convorsation", "conversation", + "convseration", "conservation", + "coordenation", "coordination", + "coordiantion", "coordination", + "coordinacion", "coordination", + "coordinaters", "coordinates", + "coordinatior", "coordinator", + "coordinatore", "coordinate", + "coordonation", "coordination", + "cooridnation", "coordination", + "coorperation", "cooperation", + "coprorations", "corporations", + "corinthianos", "corinthians", + "corinthinans", "corinthians", + "corparations", "corporations", + "corperations", "corporations", + "corporativos", "corporations", + "corproations", "corporations", + "corrdination", "coordination", + "correponding", "corresponding", + "correposding", "corresponding", + "correspondes", "corresponds", + "correspondig", "corresponding", + "corresponing", "corresponding", + "corrisponded", "corresponded", + "costomizable", "customizable", + "costumizable", "customizable", + "councidental", "coincidental", + "counsellling", "counselling", + "counterfiets", "counterfeit", + "counterfited", "counterfeit", + "counterracts", "counterparts", + "countertraps", "counterparts", + "countrywides", "countryside", + "coutnerparts", "counterparts", + "coutnerpoint", "counterpoint", + "covnersation", "conservation", + "crankenstein", "frankenstein", + "creationisim", "creationism", + "creationnism", "creationism", + "creationnist", "creationist", + "creationsism", "creationism", + "creationsist", "creationist", + "creationsits", "creationists", + "credibillity", "credibility", + "crigneworthy", "cringeworthy", + "cringewhorty", "cringeworthy", + "cringeworhty", "cringeworthy", + "cringewrothy", "cringeworthy", + "cringyworthy", "cringeworthy", + "criticallity", "critically", + "criticiszing", "criticising", + "croporations", "corporations", + "crucifiction", "crucifixion", + "cuestionable", "questionable", + "culiminating", "culminating", + "cumulatative", "cumulative", + "cuntaminated", "contaminated", + "curcumcision", "circumcision", + "curcumstance", "circumstance", + "custamizable", "customizable", + "custimizable", "customizable", + "customizaton", "customization", + "customizeble", "customizable", + "customizible", "customizable", + "custumizable", "customizable", + "cuztomizable", "customizable", + "dabilitating", "debilitating", + "dangerousely", "dangerously", + "decensitized", "desensitized", + "deceptionist", "receptionist", + "declareation", "declaration", + "decomposeion", "decomposition", + "decomposited", "decomposed", + "decscription", "description", + "deffensively", "defensively", + "deficiancies", "deficiencies", + "deficiencias", "deficiencies", + "deficiensies", "deficiencies", + "definatively", "definitively", + "defininitely", "definitively", + "definitavely", "definitively", + "definitevely", "definitively", + "definitifely", "definitively", + "definitinely", "definitively", + "definititely", "definitively", + "definitivley", "definitively", + "deinitalized", "deinitialized", + "deinitalizes", "deinitializes", + "delibaretely", "deliberately", + "deliberatley", "deliberately", + "delibirately", "deliberately", + "delibitating", "debilitating", + "deliverately", "deliberately", + "delusionally", "delusively", + "demesticated", "domesticated", + "democracries", "democracies", + "democraphics", "demographics", + "democratisch", "democratic", + "demograhpics", "demographics", + "demogrpahics", "demographics", + "demonination", "denominations", + "demonstarted", "demonstrated", + "demonstartes", "demonstrates", + "demonstrabil", "demonstrably", + "demonstraion", "demonstration", + "demonstraits", "demonstrates", + "demonstrants", "demonstrates", + "demonstratie", "demonstrate", + "demonstratin", "demonstration", + "demonstrerat", "demonstrate", + "demosntrably", "demonstrably", + "demosntrated", "demonstrated", + "demosntrates", "demonstrates", + "demostration", "demonstration", + "denomenation", "denomination", + "denominacion", "denomination", + "denominatior", "denominator", + "denominatons", "denominations", + "denomonation", "denomination", + "deomgraphics", "demographics", + "depencencies", "dependencies", + "dependancies", "dependencies", + "dependencias", "dependencies", + "dependenices", "dependencies", + "dependensies", "dependencies", + "deperecation", "deprecation", + "deplacements", "replacements", + "deregualtion", "deregulation", + "deregulaiton", "deregulation", + "derugulation", "deregulation", + "describtions", "descriptions", + "descriminant", "discriminant", + "descriptivos", "descriptions", + "desctiptions", "descriptions", + "desctruction", "destruction", + "desencitized", "desensitized", + "desensatized", "desensitized", + "desensitived", "desensitized", + "desentisized", "desensitized", + "desentitized", "desensitized", + "desentizised", "desensitized", + "desginations", "destinations", + "desgustingly", "disgustingly", + "desitnations", "destinations", + "despectively", "respectively", + "despensaries", "dispensaries", + "desperatedly", "desperately", + "desperatelly", "desperately", + "desqualified", "disqualified", + "desregarding", "disregarding", + "dessertation", "dissertation", + "destiantions", "destinations", + "destinctions", "destinations", + "destractions", "distractions", + "destributors", "distributors", + "determinanti", "determination", + "determinaton", "determination", + "determinging", "determining", + "determinisic", "deterministic", + "determinisim", "determinism", + "deterministc", "deterministic", + "determinitic", "deterministic", + "detrimential", "detrimental", + "developement", "development", + "developmenet", "developments", + "develpoments", "developments", + "devolopement", "development", + "devolopments", "developments", + "diasspointed", "dissapointed", + "dicitonaries", "dictionaries", + "dictadorship", "dictatorship", + "dictarorship", "dictatorship", + "dictatorshop", "dictatorship", + "dictionaires", "dictionaries", + "didsapointed", "dissapointed", + "differencial", "differential", + "differencies", "differences", + "differentate", "differentiate", + "differnetial", "differential", + "difficulites", "difficulties", + "difficutlies", "difficulties", + "diffuculties", "difficulties", + "dimensionals", "dimensions", + "dimensionnal", "dimensional", + "dimensionsal", "dimensional", + "diplomatisch", "diplomatic", + "directionnal", "directional", + "disaapointed", "dissapointed", + "disadvandage", "disadvantaged", + "disadvantged", "disadvantaged", + "disadvantges", "disadvantages", + "disadvatange", "disadvantage", + "disadventage", "disadvantage", + "disagremeent", "disagreements", + "disapointing", "disappointing", + "disappearnce", "disappearance", + "disappearred", "disappeared", + "disapperaing", "disappearing", + "disaspointed", "dissapointed", + "disastisfied", "dissatisfied", + "disatissfied", "dissatisfied", + "disatvantage", "disadvantage", + "discertation", "dissertation", + "disciniplary", "disciplinary", + "disciplanary", "disciplinary", + "disciplenary", "disciplinary", + "disciplinare", "discipline", + "disciplinera", "disciplinary", + "disciplinery", "disciplinary", + "disclipinary", "disciplinary", + "disconencted", "disconnected", + "disconnectes", "disconnects", + "disconnectme", "disconnected", + "disconnectus", "disconnects", + "discontiuned", "discontinued", + "discountined", "discontinued", + "discreditied", "discredited", + "discreditted", "discredited", + "discriminare", "discriminate", + "discriminted", "discriminated", + "disctinction", "distinction", + "disctinctive", "distinctive", + "disctintions", "distinctions", + "discualified", "disqualified", + "discustingly", "disgustingly", + "disemination", "dissemination", + "disenchanged", "disenchanted", + "disengenuous", "disingenuous", + "disenginuous", "disingenuous", + "disensitized", "desensitized", + "disgareement", "disagreements", + "disgruntaled", "disgruntled", + "disgrunteled", "disgruntled", + "disguntingly", "disgustingly", + "disingeneous", "disingenuous", + "disingenious", "disingenuous", + "disinteresed", "disinterested", + "disintereted", "disinterested", + "dismantleing", "dismantling", + "disobediance", "disobedience", + "disobeidence", "disobedience", + "dispalcement", "displacement", + "dispapointed", "dissapointed", + "dispencaries", "dispensaries", + "dispensaires", "dispensaries", + "dispensarios", "dispensaries", + "dispensiries", "dispensaries", + "dispensories", "dispensaries", + "disqaulified", "disqualified", + "disqualifyed", "disqualified", + "disqustingly", "disgustingly", + "disrecpected", "disrespected", + "disrepsected", "disrespected", + "disresepcted", "disrespected", + "disrespecful", "disrespectful", + "disrespecing", "disrespecting", + "disrespectul", "disrespectful", + "disrespekted", "disrespected", + "disrtibution", "distributions", + "dissapearing", "disappearing", + "dissapionted", "dissapointed", + "dissapoimted", "dissapointed", + "dissapoitned", "dissapointed", + "dissaponited", "dissapointed", + "dissapoonted", "dissapointed", + "dissapounted", "dissapointed", + "dissappinted", "dissapointed", + "dissapponted", "dissapointed", + "dissastified", "dissatisfied", + "dissatisifed", "dissatisfied", + "dissatsified", "dissatisfied", + "dissepointed", "dissapointed", + "dissipointed", "dissapointed", + "dissobediant", "disobedient", + "dissobedient", "disobedient", + "dissopointed", "dissapointed", + "disspaointed", "dissapointed", + "dissppointed", "dissapointed", + "dissspointed", "dissapointed", + "distinations", "distinctions", + "distincitons", "distinctions", + "distingished", "distinguished", + "distingishes", "distinguishes", + "distinguised", "distinguished", + "distirbuting", "distributing", + "distirbution", "distribution", + "distrabution", "distribution", + "distribitors", "distributors", + "distribtuion", "distributions", + "distribucion", "distribution", + "distribuited", "distributed", + "distribuiton", "distributions", + "distribuitor", "distributor", + "distribusion", "distributions", + "distributino", "distributions", + "distributior", "distributor", + "distributons", "distributors", + "distributore", "distribute", + "distriubtion", "distributions", + "distrobution", "distribution", + "distrubances", "disturbance", + "distrubiting", "distributing", + "distrubition", "distribution", + "distrubitors", "distributors", + "distrubution", "distribution", + "distrubutors", "distributors", + "distructions", "distractions", + "distustingly", "disgustingly", + "ditactorship", "dictatorship", + "documenation", "documentation", + "documentaion", "documentation", + "documentaire", "documentaries", + "documentarse", "documentaries", + "documentarsi", "documentaries", + "domesitcated", "domesticated", + "domisticated", "domesticated", + "donesticated", "domesticated", + "donwloadable", "downloadable", + "dossapointed", "dissapointed", + "downlaodable", "downloadable", + "downloadbale", "downloadable", + "downloadeble", "downloadable", + "drankenstein", "frankenstein", + "dublications", "publications", + "dusgustingly", "disgustingly", + "dynamicallly", "dynamically", + "dyregulation", "deregulation", + "earthquackes", "earthquakes", + "earthquakers", "earthquakes", + "econimically", "economically", + "economisesti", "economists", + "educationnal", "educational", + "effectionate", "affectionate", + "effectivelly", "effectively", + "effectivenss", "effectiveness", + "efficienctly", "efficiency", + "effordlessly", "effortlessly", + "ejacualtions", "ejaculation", + "electorlytes", "electrolytes", + "electricrain", "electrician", + "electrictian", "electrician", + "electrobytes", "electrolytes", + "electrocytes", "electrolytes", + "electrolites", "electrolytes", + "electroltyes", "electrolytes", + "electronicas", "electronics", + "electronicos", "electronics", + "electroyltes", "electrolytes", + "elektrolytes", "electrolytes", + "eloctrolytes", "electrolytes", + "embarassment", "embarrassment", + "embarasssing", "embarassing", + "embarrasment", "embarrassment", + "embarressing", "embarrassing", + "embarrissing", "embarrassing", + "emberrassing", "embarrassing", + "emphetamines", "amphetamines", + "emprisonment", "imprisonment", + "encarcerated", "incarcerated", + "enceclopedia", "encyclopedia", + "enchancement", "enhancement", + "enchancments", "enchantments", + "enchantmants", "enchantments", + "enchentments", "enchantments", + "enciclopedia", "encyclopedia", + "enclycopedia", "encyclopedia", + "encorporated", "incorporated", + "encourageing", "encouraging", + "encyclapedia", "encyclopedia", + "encyclepedia", "encyclopedia", + "encyclopadia", "encyclopedia", + "encyclopeida", "encyclopedia", + "encyclopidia", "encyclopedia", + "encycolpedia", "encyclopedia", + "encyklopedia", "encyclopedia", + "encylcopedia", "encyclopedia", + "encyplopedia", "encyclopedia", + "endoresments", "endorsement", + "enemployment", "unemployment", + "enfringement", "infringement", + "enlightended", "enlightened", + "enlightenend", "enlightened", + "enlightented", "enlightened", + "enlightining", "enlightening", + "enligthening", "enlightening", + "entaglements", "entanglements", + "entartaining", "entertaining", + "enterpreneur", "entrepreneurs", + "enterprenuer", "entrepreneur", + "entertainted", "entertained", + "enthusiaists", "enthusiasts", + "enthusuastic", "enthusiastic", + "entoxication", "intoxication", + "entrepeneurs", "entrepreneurs", + "entreperneur", "entrepreneurs", + "entreprenaur", "entrepreneur", + "entrepreners", "entrepreneurs", + "entrepreneus", "entrepreneurs", + "entreprenour", "entrepreneur", + "entreprenure", "entrepreneurs", + "entreprenurs", "entrepreneurs", + "entrepreuner", "entrepreneurs", + "entretaining", "entertaining", + "enviormental", "environmental", + "enviornments", "environments", + "enviromental", "environmental", + "environemnts", "environments", + "environmentl", "environmentally", + "environmetal", "environmental", + "envrionments", "environments", + "errorneously", "erroneously", + "establishmet", "establishments", + "evelutionary", "evolutionary", + "exagerrating", "exaggerating", + "exaggarating", "exaggerating", + "exaggaration", "exaggeration", + "exaggeratted", "exaggerated", + "exaggurating", "exaggerating", + "exagguration", "exaggeration", + "exceptionaly", "exceptionally", + "exceptionnal", "exceptional", + "exclusiveity", "exclusivity", + "exclusivelly", "exclusively", + "exclusivitiy", "exclusivity", + "excorciating", "excruciating", + "excrusiating", "excruciating", + "excurciating", "excruciating", + "exectuioners", "executioner", + "executioneer", "executioner", + "executionees", "executions", + "executioness", "executions", + "executionier", "executioner", + "executionner", "executioner", + "exeggerating", "exaggerating", + "exeggeration", "exaggeration", + "expeditonary", "expeditionary", + "expendatures", "expenditures", + "expendetures", "expenditures", + "expentitures", "expenditures", + "experamental", "experimental", + "expereincing", "experiencing", + "experemental", "experimental", + "experiancing", "experiencing", + "experiemntal", "experimental", + "experiemnted", "experimented", + "experimantal", "experimental", + "experimentan", "experimentation", + "experimentes", "experiments", + "experimentle", "experimented", + "experimentos", "experiments", + "experimentul", "experimental", + "expidentures", "expenditures", + "expierencing", "experiencing", + "expiremental", "experimental", + "expiremented", "experimented", + "explaination", "explanation", + "explenations", "explanations", + "expliotation", "exploitation", + "exploitaiton", "exploitation", + "exploitating", "exploitation", + "exploititive", "exploitative", + "explortation", "exploitation", + "explotiation", "exploitation", + "explotiative", "exploitative", + "expolitation", "exploitation", + "expolitative", "exploitative", + "exponentialy", "exponentially", + "expropiation", "expropriation", + "extensivelly", "extensively", + "extradiction", "extradition", + "extraordiary", "extraordinary", + "extraordinay", "extraordinary", + "extrapolerat", "extrapolate", + "extrapoloate", "extrapolate", + "extremistisk", "extremists", + "extrordinary", "extraordinary", + "extruciating", "excruciating", + "facilitatile", "facilitate", + "fahrenheight", "fahrenheit", + "falmethrower", "flamethrower", + "familiarlize", "familiarize", + "fanslaughter", "manslaughter", + "fantasticaly", "fantastically", + "fantasticlly", "fantastically", + "fashionalble", "fashionable", + "fermantation", "fermentation", + "fermentacion", "fermentation", + "fermentaiton", "fermentation", + "fermentating", "fermentation", + "fermintation", "fermentation", + "fictionaries", "dictionaries", + "figuartively", "figuratively", + "figuratevely", "figuratively", + "figurativley", "figuratively", + "figuretively", "figuratively", + "figuritively", "figuratively", + "fingerpoints", "fingerprints", + "firefigthers", "firefighters", + "flamethorwer", "flamethrower", + "flametrhower", "flamethrower", + "flanethrower", "flamethrower", + "flexibillity", "flexibility", + "flourishment", "flourishing", + "fluctiations", "fluctuations", + "flucutations", "fluctuations", + "fluxtuations", "fluctuations", + "forgivenness", "forgiveness", + "fortunatelly", "fortunately", + "framethrower", "flamethrower", + "frankenstain", "frankenstein", + "frankensteen", "frankenstein", + "frankenstine", "frankenstein", + "frankinstein", "frankenstein", + "frementation", "fermentation", + "friendzonded", "friendzoned", + "friendzonned", "friendzoned", + "friendzowned", "friendzoned", + "fringeworthy", "cringeworthy", + "fronkenstein", "frankenstein", + "fruitsations", "frustrations", + "frustrastion", "frustrations", + "fucntionally", "functionally", + "funcitonally", "functionally", + "functionable", "functional", + "functionaliy", "functionally", + "functionalty", "functionality", + "functionlity", "functionality", + "functionning", "functioning", + "fundamentais", "fundamentals", + "fundamentalt", "fundamentalist", + "fundamentaly", "fundamentally", + "fundemantals", "fundamentals", + "fundementals", "fundamentals", + "fundimentals", "fundamentals", + "furstrations", "frustrations", + "futuristisch", "futuristic", + "fwankenstein", "frankenstein", + "geneological", "genealogical", + "generacional", "generational", + "generalizare", "generalize", + "generalizate", "generalize", + "generelizing", "generalizing", + "geograhpical", "geographical", + "geographicly", "geographical", + "geographisch", "geographic", + "geogrpahical", "geographical", + "goegraphical", "geographical", + "governemntal", "governmental", + "governmently", "governmental", + "grammaticaal", "grammatical", + "grammaticaly", "grammatically", + "grandchilden", "grandchildren", + "grandchilder", "grandchildren", + "grandchilren", "grandchildren", + "grassrooters", "grassroots", + "gringeworthy", "cringeworthy", + "guantanameow", "guantanamo", + "guantanamero", "guantanamo", + "hallucinatin", "hallucinations", + "hallucinaton", "hallucination", + "handwritting", "handwriting", + "harrassments", "harassments", + "headqaurters", "headquarters", + "headquatered", "headquartered", + "healthercare", "healthcare", + "heavywieghts", "heavyweight", + "helicopteros", "helicopters", + "hererosexual", "heterosexual", + "heretosexual", "heterosexual", + "heteresexual", "heterosexual", + "hetreosexual", "heterosexual", + "highligthing", "highlighting", + "hipocritical", "hypocritical", + "hipothetical", "hypothetical", + "histarically", "historically", + "histerically", "historically", + "historicians", "historians", + "homogeneized", "homogenized", + "homogenenous", "homogeneous", + "homosexuales", "homosexuals", + "homosexualiy", "homosexuality", + "homosexualls", "homosexuals", + "homosexualty", "homosexuality", + "homosexuella", "homosexual", + "hopsitalized", "hospitalized", + "horisontally", "horizontally", + "horizantally", "horizontally", + "horiztonally", "horizontally", + "horozontally", "horizontally", + "hospitallity", "hospitality", + "hospitilized", "hospitalized", + "hospitolized", "hospitalized", + "hosptialized", "hospitalized", + "humanitarien", "humanitarian", + "humanitarion", "humanitarian", + "humanitatian", "humanitarian", + "humaniterian", "humanitarian", + "humantiarian", "humanitarian", + "huminatarian", "humanitarian", + "hurricanefps", "hurricanes", + "hyopthetical", "hypothetical", + "hypathetical", "hypothetical", + "hypertrophey", "hypertrophy", + "hypethetical", "hypothetical", + "hypocrticial", "hypocritical", + "hypocrytical", "hypocritical", + "hypotehtical", "hypothetical", + "hypotethical", "hypothetical", + "hypotherical", "hypothetical", + "hypotheticly", "hypothetical", + "hystarically", "hysterically", + "hystorically", "hysterically", + "idealistisch", "idealistic", + "identificato", "identification", + "identifierad", "identified", + "identifieras", "identifies", + "identifyable", "identifiable", + "ideologicaly", "ideologically", + "idiosyncracy", "idiosyncrasy", + "illegetimate", "illegitimate", + "illegitamate", "illegitimate", + "illegitamite", "illegitimate", + "illegitemate", "illegitimate", + "illegitimite", "illegitimate", + "illigetimate", "illegitimate", + "illigitemate", "illegitimate", + "illistration", "illustration", + "illsutration", "illustrations", + "illustartion", "illustration", + "illustraitor", "illustrator", + "illustraties", "illustrate", + "illustratior", "illustrator", + "imcompatible", "incompatible", + "imcompetence", "incompetence", + "imexperience", "inexperience", + "immediatelly", "immediately", + "immortallity", "immortality", + "imperialfist", "imperialist", + "imperialisim", "imperialism", + "imperialstic", "imperialist", + "implamenting", "implementing", + "implausibile", "implausible", + "implecations", "implications", + "implementase", "implements", + "implementasi", "implements", + "implementato", "implementation", + "implentation", "implementation", + "implimenting", "implementing", + "imporvements", "improvements", + "impossibilty", "impossibility", + "impossiblely", "impossibly", + "impossiblity", "impossibly", + "impovershied", "impoverished", + "impoversihed", "impoverished", + "imprefection", "imperfections", + "improsonment", "imprisonment", + "improviserad", "improvised", + "imrpovements", "improvements", + "imtimidating", "intimidating", + "imtimidation", "intimidation", + "inaccesibles", "inaccessible", + "inaccessable", "inaccessible", + "inaccessbile", "inaccessible", + "inaccurasies", "inaccuracies", + "inaccuraties", "inaccuracies", + "inaccuricies", "inaccuracies", + "inacuraccies", "inaccuracies", + "inadvertenly", "inadvertently", + "inappropiate", "inappropriate", + "inapproprate", "inappropriate", + "inappropriae", "inappropriately", + "inappropriet", "inappropriately", + "inattractive", "unattractive", + "inbelievable", "unbelievable", + "incarcelated", "incarcerated", + "incarcirated", "incarcerated", + "incarserated", "incarcerated", + "incedentally", "incidentally", + "incentiveise", "incentives", + "incestigator", "investigator", + "incomaptible", "incompatible", + "incomparible", "incompatible", + "incompatable", "incompatible", + "incompatibil", "incompatible", + "incompetance", "incompetence", + "incompetente", "incompetence", + "incompitable", "incompatible", + "incomptetent", "incompetent", + "inconcistent", "inconsistent", + "inconsistant", "inconsistent", + "inconsistecy", "inconsistency", + "inconsisteny", "inconsistency", + "inconveinent", "inconvenient", + "inconveniant", "inconvenient", + "inconveniece", "inconvenience", + "inconvenince", "inconvenience", + "inconvienent", "inconvenient", + "incorparated", "incorporated", + "incorperated", "incorporated", + "incorportaed", "incorporated", + "incorportate", "incorporate", + "incrediblely", "incredibly", + "incrementers", "increments", + "incremential", "incremental", + "indefinately", "indefinitely", + "indefineable", "undefinable", + "indefinetely", "indefinitely", + "indefinitive", "indefinite", + "indefinitley", "indefinitely", + "indefintiely", "indefinitely", + "indepedantly", "independently", + "indepencence", "independence", + "independance", "independence", + "independante", "independents", + "independenet", "independents", + "independenly", "independently", + "independense", "independents", + "independente", "independence", + "independetly", "independently", + "indepentents", "independents", + "indetifiable", "identifiable", + "indianaoplis", "indianapolis", + "indianopolis", "indianapolis", + "indicentally", "incidentally", + "indifferance", "indifference", + "indifferente", "indifference", + "indiffernece", "indifference", + "indimidating", "intimidating", + "indimidation", "intimidation", + "indipendence", "independence", + "indisputible", "indisputable", + "indisputibly", "indisputably", + "individuales", "individuals", + "individualty", "individuality", + "individuella", "individual", + "indiviudally", "individually", + "indivudually", "individually", + "indpendently", "independently", + "indroduction", "introduction", + "indroductory", "introductory", + "industriella", "industrial", + "industrijske", "industries", + "inefficienct", "inefficient", + "inefficienty", "inefficiently", + "inevitablely", "inevitably", + "inevitablity", "inevitably", + "inevititably", "inevitably", + "inexblicably", "inexplicably", + "inexpectedly", "unexpectedly", + "inexpereince", "inexperience", + "inexperiance", "inexperience", + "inexperieced", "inexperienced", + "inexperiened", "inexperienced", + "inexperiente", "inexperience", + "inexpierence", "inexperienced", + "inexplicabil", "inexplicably", + "inexplicibly", "inexplicably", + "infalability", "infallibility", + "infilitrated", "infiltrated", + "infiltraitor", "infiltrator", + "infiltratior", "infiltrator", + "infiltratred", "infiltrate", + "influenceing", "influencing", + "infogrpahics", "infographic", + "inforgivable", "unforgivable", + "infrantryman", "infantryman", + "infridgement", "infringement", + "infrignement", "infringement", + "ingestigator", "investigator", + "ingredientes", "ingredients", + "ingreediants", "ingredients", + "ininterested", "uninterested", + "initalizable", "initializable", + "inkompatible", "incompatible", + "inkompetence", "incompetence", + "inkonsistent", "inconsistent", + "inlightening", "enlightening", + "innersection", "intersection", + "innerstellar", "interstellar", + "inpenetrable", "impenetrable", + "inplementing", "implementing", + "inplications", "implications", + "inpoverished", "impoverished", + "inprisonment", "imprisonment", + "inproductive", "unproductive", + "inprovements", "improvements", + "inresponsive", "unresponsive", + "insentivised", "insensitive", + "insentivises", "insensitive", + "insignifiant", "insignificant", + "insignificat", "insignificant", + "insinuationg", "insinuating", + "instabillity", "instability", + "instalaltion", "installations", + "installatons", "installations", + "installatron", "installation", + "instantaneos", "instantaneous", + "instantaneus", "instantaneous", + "instantanous", "instantaneous", + "instinctivly", "instinctively", + "institutuion", "institution", + "instramental", "instrumental", + "instrcutions", "instruction", + "instrucitons", "instruction", + "instructiosn", "instruction", + "instructores", "instructors", + "instrumentos", "instruments", + "instrumentul", "instrumental", + "insturmental", "instrumental", + "instutitions", "institutions", + "insuccessful", "unsuccessful", + "insufficiant", "insufficient", + "insuffucient", "insufficient", + "insuspecting", "unsuspecting", + "intaxication", "intoxication", + "intelelctual", "intellectuals", + "intellectals", "intellectuals", + "intellectaul", "intellectuals", + "intellectuel", "intellectual", + "intellecutal", "intellectual", + "intelligance", "intelligence", + "intelligenly", "intelligently", + "intelligente", "intelligence", + "intelligenty", "intelligently", + "intelligient", "intelligent", + "intenational", "international", + "intentionnal", "intentional", + "intepretator", "interpretor", + "interatellar", "interstellar", + "interational", "international", + "intercection", "interception", + "intercepcion", "interception", + "interceptons", "interceptions", + "intereaction", "intersection", + "interections", "interactions", + "interersting", "interpreting", + "interesction", "intersection", + "interestigly", "interestingly", + "interestinly", "interestingly", + "interferance", "interference", + "interfereing", "interfering", + "interferisce", "interferes", + "interferisse", "interferes", + "interferring", "interfering", + "intergration", "integration", + "interlectual", "intellectual", + "intermediare", "intermediate", + "intermediete", "intermediate", + "intermettent", "intermittent", + "intermideate", "intermediate", + "intermidiate", "intermediate", + "internatinal", "international", + "internationl", "international", + "internations", "interactions", + "internediate", "intermediate", + "internelized", "internalized", + "internilized", "internalized", + "interperters", "interpreter", + "interperting", "interpreting", + "interprating", "interpreting", + "interpretare", "interpreter", + "interpretato", "interpretation", + "interpreteer", "interpreter", + "interpretier", "interpreter", + "interpretion", "interpreting", + "interpretter", "interpreter", + "interpriting", "interpreting", + "interraccial", "interracial", + "interractial", "interracial", + "interrogatin", "interrogation", + "interrumping", "interrupting", + "interrupteds", "interrupts", + "interruptors", "interrupts", + "interseccion", "intersection", + "interseciton", "intersections", + "interseption", "interception", + "intersetllar", "interstellar", + "interstallar", "interstellar", + "interstaller", "interstellar", + "intersteller", "interstellar", + "interstellor", "interstellar", + "intertaining", "entertaining", + "intertwinded", "intertwined", + "intertwinned", "intertwined", + "interveiwing", "interviewing", + "intervencion", "intervention", + "interveneing", "intervening", + "intervension", "intervention", + "interviening", "interviewing", + "intidimation", "intimidation", + "intillectual", "intellectual", + "intimidacion", "intimidation", + "intimidative", "intimidate", + "intimitading", "intimidating", + "intimitating", "intimidating", + "intimitation", "intimidation", + "intorduction", "introduction", + "intorductory", "introductory", + "intoxicacion", "intoxication", + "intoxination", "intoxication", + "intrepreting", "interpreting", + "intrinsicaly", "intrinsically", + "introdiction", "introduction", + "introduccion", "introduction", + "introduceras", "introduces", + "introduceres", "introduces", + "introduciton", "introduction", + "introductary", "introductory", + "introducting", "introduction", + "introductury", "introductory", + "introduktion", "introduction", + "introspectin", "introspection", + "intruduction", "introduction", + "intruductory", "introductory", + "intsrumental", "instrumental", + "intuitivelly", "intuitively", + "inturrupting", "interrupting", + "invervention", "intervention", + "investagated", "investigated", + "investagator", "investigator", + "investegated", "investigated", + "investegator", "investigator", + "investigaron", "investigator", + "investigater", "investigator", + "investigatie", "investigative", + "investigatin", "investigation", + "investigatio", "investigator", + "investigaton", "investigation", + "investingate", "investigate", + "investogator", "investigator", + "invicibility", "invisibility", + "invididually", "individually", + "invisibiltiy", "invisibility", + "invisilibity", "invisibility", + "invisivility", "invisibility", + "invlunerable", "invulnerable", + "involnerable", "invulnerable", + "involuntairy", "involuntary", + "involuntarly", "involuntary", + "invonvenient", "inconvenient", + "invulenrable", "invulnerable", + "invulernable", "invulnerable", + "invulnarable", "invulnerable", + "invulnerbale", "invulnerable", + "invulnurable", "invulnerable", + "invulverable", "invulnerable", + "invunlerable", "invulnerable", + "invurnerable", "invulnerable", + "irrationably", "irrationally", + "irrationatly", "irrationally", + "irrationella", "irrational", + "irreplacable", "irreplaceable", + "irresistable", "irresistible", + "irresistably", "irresistibly", + "irrespecitve", "irrespective", + "irresponsble", "irresponsible", + "irresponsibe", "irresponsible", + "irreverisble", "irreversible", + "irreversebly", "irreversible", + "irreversibel", "irreversible", + "irrevirsible", "irreversible", + "irrispective", "irrespective", + "irriversible", "irreversible", + "isdefinitely", "indefinitely", + "isntallation", "installation", + "isntrumental", "instrumental", + "jackonsville", "jacksonville", + "jounralistic", "journalistic", + "jouranlistic", "journalistic", + "journalisitc", "journalistic", + "journalistes", "journalists", + "judgementals", "judgements", + "juggernaunts", "juggernaut", + "juridisction", "jurisdictions", + "jurisdiccion", "jurisdiction", + "jurisdiciton", "jurisdiction", + "jurisdiktion", "jurisdiction", + "jurisfiction", "jurisdiction", + "jurisidction", "jurisdiction", + "juristiction", "jurisdiction", + "jursidiction", "jurisdiction", + "jusridiction", "jurisdiction", + "justificatin", "justifications", + "katastrophic", "catastrophic", + "kidnergarten", "kindergarten", + "kindergarden", "kindergarten", + "kingergarten", "kindergarten", + "kintergarten", "kindergarten", + "knolwedgable", "knowledgable", + "knoweldgable", "knowledgable", + "knowladgable", "knowledgable", + "knowldegable", "knowledgable", + "knowldgeable", "knowledgable", + "knowleagable", "knowledgable", + "knowledagble", "knowledgable", + "knowledeable", "knowledgable", + "knowledgabel", "knowledgable", + "knowledgeble", "knowledgeable", + "knowledgebly", "knowledgable", + "knowledgible", "knowledgable", + "knowlegdable", "knowledgable", + "knowlegeable", "knowledgeable", + "knwoledgable", "knowledgable", + "kolonization", "colonization", + "kombinations", "combinations", + "kommissioner", "commissioner", + "kompensation", "compensation", + "konfidential", "confidential", + "konfirmation", "confirmation", + "kongregation", "congregation", + "konservatism", "conservatism", + "konservative", "conservative", + "konsultation", "consultation", + "konversation", "conversation", + "koordination", "coordination", + "krankenstein", "frankenstein", + "leaglization", "legalization", + "legalizacion", "legalization", + "legalizaiton", "legalization", + "legendariske", "legendaries", + "legimitately", "legitimately", + "legislatiors", "legislators", + "legistration", "registration", + "legitamately", "legitimately", + "legitamitely", "legitimately", + "legitemately", "legitimately", + "legitimatley", "legitimately", + "legitimitely", "legitimately", + "liberatrians", "libertarians", + "libertarains", "libertarians", + "libertariens", "libertarians", + "libertaryans", "libertarians", + "libertatians", "libertarians", + "liberterians", "libertarians", + "libretarians", "libertarians", + "lighthearded", "lighthearted", + "linguisticas", "linguistics", + "linguisticos", "linguistics", + "linguistisch", "linguistics", + "litllefinger", "littlefinger", + "littelfinger", "littlefinger", + "litterfinger", "littlefinger", + "littiefinger", "littlefinger", + "littlefigner", "littlefinger", + "littlefinder", "littlefinger", + "littlepinger", "littlefinger", + "lnowledgable", "knowledgable", + "longitudonal", "longitudinal", + "madturbating", "masturbating", + "madturbation", "masturbation", + "magnificient", "magnificent", + "maintainance", "maintenance", + "maintainence", "maintenance", + "maintenaince", "maintenance", + "malfucntions", "malfunction", + "manafactured", "manufactured", + "manafacturer", "manufacturer", + "manafactures", "manufactures", + "manifactured", "manufactured", + "manifacturer", "manufacturer", + "manifactures", "manufactures", + "manifestaion", "manifestation", + "manifestanti", "manifestation", + "manipluating", "manipulating", + "manipluation", "manipulation", + "manipualting", "manipulating", + "manipualtion", "manipulation", + "manipualtive", "manipulative", + "manipulacion", "manipulation", + "manipulitive", "manipulative", + "maniuplating", "manipulating", + "maniuplation", "manipulation", + "maniuplative", "manipulative", + "manouverable", "maneuverable", + "mansalughter", "manslaughter", + "manslaugther", "manslaughter", + "mansluaghter", "manslaughter", + "manufactered", "manufactured", + "manufacterer", "manufacturer", + "manufacteres", "manufactures", + "manufacteurs", "manufactures", + "manufactored", "manufactured", + "manufactorer", "manufacturer", + "manufactores", "manufactures", + "manufactuers", "manufacturers", + "manufactuing", "manufacturing", + "manufacturas", "manufactures", + "manufacturor", "manufacturer", + "manufactuter", "manufacture", + "manufacuters", "manufactures", + "manufacutred", "manufacture", + "manufacutres", "manufactures", + "manufaturing", "manufacturing", + "manupilating", "manipulating", + "manupulating", "manipulating", + "manupulation", "manipulation", + "manupulative", "manipulative", + "marchmallows", "marshmallows", + "marganilized", "marginalized", + "margenalized", "marginalized", + "marginilized", "marginalized", + "marhsmallows", "marshmallows", + "marshamllows", "marshmallows", + "marshmallons", "marshmallows", + "masoginistic", "misogynistic", + "masogynistic", "misogynistic", + "massachusets", "massachusetts", + "massachustts", "massachusetts", + "masterbation", "masturbation", + "masterpeices", "masterpiece", + "mastrubating", "masturbating", + "mastrubation", "masturbation", + "mastubration", "masturbation", + "masturabting", "masturbating", + "masturabtion", "masturbation", + "masturbacion", "masturbation", + "masturbaited", "masturbated", + "masturbathon", "masturbation", + "masturbsting", "masturbating", + "masturdating", "masturbating", + "mastutbation", "masturbation", + "mataphorical", "metaphorical", + "mataphysical", "metaphysical", + "matchmakeing", "matchmaking", + "mathemathics", "mathematics", + "mathematican", "mathematician", + "mathematicas", "mathematics", + "mathematicks", "mathematics", + "mathematicly", "mathematical", + "mathematisch", "mathematics", + "mathemetical", "mathematical", + "matheticians", "mathematicians", + "mathimatical", "mathematical", + "mathmatician", "mathematician", + "mecahnically", "mechanically", + "mechancially", "mechanically", + "meditaciones", "medications", + "mediteranean", "mediterranean", + "mediterraean", "mediterranean", + "mediterranen", "mediterranean", + "memerization", "memorization", + "memorizacion", "memorization", + "memorozation", "memorization", + "metalurgical", "metallurgical", + "metaphisical", "metaphysical", + "metaphoricly", "metaphorical", + "metaphsyical", "metaphysical", + "metaphyiscal", "metaphysical", + "metaphyscial", "metaphysical", + "metaphysisch", "metaphysics", + "metephorical", "metaphorical", + "metephysical", "metaphysical", + "meterologist", "meteorologist", + "meterosexual", "heterosexual", + "methaporical", "metaphorical", + "methematical", "mathematical", + "metiphorical", "metaphorical", + "metophorical", "metaphorical", + "metorpolitan", "metropolitan", + "metrololitan", "metropolitan", + "metropilitan", "metropolitan", + "metroploitan", "metropolitan", + "metropolians", "metropolis", + "metropoliten", "metropolitan", + "metropolitin", "metropolitan", + "metropoliton", "metropolitan", + "microcentres", "microcenter", + "microphonies", "microphones", + "microscophic", "microscopic", + "microscopice", "microscope", + "microscoptic", "microscopic", + "midfieldiers", "midfielders", + "millenialism", "millennialism", + "millionairre", "millionaire", + "millionaries", "millionaires", + "millioniares", "millionaires", + "minimalisitc", "minimalist", + "minimalisity", "minimalist", + "mininterpret", "misinterpret", + "minipulating", "manipulating", + "minipulation", "manipulation", + "minipulative", "manipulative", + "miracilously", "miraculously", + "miracurously", "miraculous", + "miscarraiges", "miscarriage", + "miscelaneous", "miscellaneous", + "miscellanous", "miscellaneous", + "mischievious", "mischievous", + "misdameanors", "misdemeanors", + "misdeamenors", "misdemeanor", + "misfourtunes", "misfortunes", + "misgoynistic", "misogynistic", + "misinterpert", "misinterpret", + "misinterpred", "misinterpreted", + "misinterprit", "misinterpreting", + "misinterpted", "misinterpret", + "misintrepret", "misinterpret", + "misisonaries", "missionaries", + "misoganistic", "misogynistic", + "misogenistic", "misogynistic", + "misoginystic", "misogynistic", + "misognyistic", "misogynistic", + "misogonistic", "misogynistic", + "misogynisitc", "misogynistic", + "misogynsitic", "misogynistic", + "misogynystic", "misogynistic", + "missionaires", "missionaries", + "mississipppi", "mississippi", + "misspellling", "misspelling", + "misteriously", "mysteriously", + "misundersood", "misunderstood", + "misunderstod", "misunderstood", + "misygonistic", "misogynistic", + "modificacion", "modification", + "modificaiton", "modification", + "modificatons", "modifications", + "modifikation", "modification", + "modivational", "motivational", + "moisterizing", "moisturizing", + "moistorizing", "moisturizing", + "moisutrizing", "moisturizing", + "momentarilly", "momentarily", + "monolithisch", "monolithic", + "mositurizing", "moisturizing", + "motherbaords", "motherboards", + "motherborads", "motherboards", + "motivacional", "motivational", + "motovational", "motivational", + "mousturizing", "moisturizing", + "muktitasking", "multitasking", + "mulittasking", "multitasking", + "multinatinal", "multinational", + "multitaksing", "multitasking", + "munipulative", "manipulative", + "mutlitasking", "multitasking", + "mysoganistic", "misogynistic", + "mysogenistic", "misogynistic", + "mysogonistic", "misogynistic", + "mysterioulsy", "mysteriously", + "nacionalists", "nationalists", + "narcisisstic", "narcissistic", + "narcissictic", "narcissistic", + "narcissisism", "narcissism", + "narcissisist", "narcissist", + "narcissisitc", "narcissist", + "narcississts", "narcissist", + "narssicistic", "narcissistic", + "natioanlists", "nationalists", + "nationalisic", "nationalistic", + "nationalisim", "nationalism", + "nationalistc", "nationalistic", + "nationalites", "nationalist", + "nationalitic", "nationalistic", + "nationalitys", "nationalist", + "nationallity", "nationally", + "nationalsits", "nationalists", + "nationalties", "nationalist", + "nazionalists", "nationalists", + "neccessarily", "necessarily", + "neccessities", "necessities", + "necessarilly", "necessarily", + "necessitites", "necessities", + "neckbearders", "neckbeards", + "neckbeardese", "neckbeards", + "neckbeardest", "neckbeards", + "neckbeardies", "neckbeards", + "neckbeardius", "neckbeards", + "negociations", "negotiations", + "negoitations", "negotiations", + "negotiatians", "negotiations", + "negotiatiing", "negotiating", + "negotiationg", "negotiating", + "negotiatiors", "negotiations", + "neigbhorhood", "neighborhoods", + "neigbourhood", "neighbourhood", + "neighboorhod", "neighbourhood", + "neighborhing", "neighboring", + "neighborhods", "neighborhoods", + "neighbourghs", "neighbours", + "neighbourhod", "neighbourhood", + "neighbourood", "neighbourhood", + "neighbrohood", "neighborhoods", + "neighourhood", "neighborhood", + "neoroscience", "neuroscience", + "neruological", "neurological", + "neruoscience", "neuroscience", + "netropolitan", "metropolitan", + "neuorscience", "neuroscience", + "neuralogical", "neurological", + "neuroligical", "neurological", + "neurosceince", "neuroscience", + "neuroscienze", "neuroscience", + "neurosicence", "neuroscience", + "neverhteless", "nevertheless", + "nieghborhood", "neighborhood", + "norhtwestern", "northwestern", + "nothingsness", "nothingness", + "noticeablely", "noticeably", + "notificacion", "notification", + "notificaiton", "notification", + "notificatons", "notifications", + "nuerological", "neurological", + "nueroscience", "neuroscience", + "nutritionnal", "nutritional", + "obersvations", "observations", + "objectivelly", "objectively", + "objectiviser", "objectives", + "objectivitiy", "objectivity", + "obversations", "observations", + "ocassionally", "occasionally", + "occaisonally", "occasionally", + "occasioanlly", "occasionally", + "occassionaly", "occasionally", + "occationally", "occasionally", + "occurrencies", "occurrences", + "offensivelly", "offensively", + "ogranisation", "organisation", + "omniverously", "omnivorously", + "operationnal", "operational", + "opportuniste", "opportunities", + "opportunites", "opportunities", + "oppositition", "opposition", + "opthalmology", "ophthalmology", + "optimistisch", "optimistic", + "optimizacion", "optimization", + "optimizating", "optimization", + "optimziation", "optimization", + "optmizations", "optimizations", + "oragnisation", "organisation", + "orchastrated", "orchestrated", + "orchestarted", "orchestrated", + "orchestraded", "orchestrated", + "orchistrated", "orchestrated", + "orgainsation", "organisation", + "orgainzation", "organizations", + "organisaiton", "organisation", + "organisatons", "organisations", + "organistaion", "organisation", + "organizacion", "organization", + "organizaiton", "organization", + "organizativo", "organization", + "organizatons", "organizations", + "organsiation", "organisation", + "organziation", "organization", + "orginasation", "organisation", + "orginazation", "organization", + "orgnaisation", "organisations", + "originallity", "originality", + "outraegously", "outrageously", + "outrageoulsy", "outrageously", + "outragesouly", "outrageously", + "outrageuosly", "outrageously", + "outragiously", "outrageously", + "outsourceing", "outsourcing", + "overbearring", "overbearing", + "overblocking", "overclocking", + "overclcoking", "overclocking", + "overclicking", "overclocking", + "overcloaking", "overclocking", + "overclockign", "overclocking", + "overclokcing", "overclocking", + "overhearting", "overreacting", + "overheathing", "overheating", + "overhtinking", "overthinking", + "overhwelming", "overwhelming", + "overlappping", "overlapping", + "overlcocking", "overclocking", + "overreaktion", "overreaction", + "overwealming", "overwhelming", + "overwhelemed", "overwhelmed", + "overwhemling", "overwhelming", + "overwhleming", "overwhelming", + "owerpowering", "overpowering", + "painkilllers", "painkillers", + "palastinians", "palestinians", + "palesitnians", "palestinians", + "palestenians", "palestinians", + "palestinains", "palestinians", + "palestiniens", "palestinians", + "palestininan", "palestinian", + "palestininas", "palestinians", + "palistinians", "palestinians", + "palythroughs", "playthroughs", + "parapharsing", "paraphrasing", + "paraphenalia", "paraphernalia", + "paraphrashed", "paraphrase", + "paraphrazing", "paraphrasing", + "paraprashing", "paraphrasing", + "paraprhasing", "paraphrasing", + "parenthesees", "parentheses", + "parenthesies", "parenthesis", + "parliamentry", "parliamentary", + "partecipants", "participants", + "partecipated", "participated", + "parternships", "partnership", + "particapated", "participated", + "particiapnts", "participant", + "particiapted", "participated", + "participante", "participate", + "participaste", "participants", + "participatie", "participated", + "participatin", "participation", + "participatns", "participant", + "participaton", "participant", + "participents", "participants", + "particualrly", "particularly", + "particulalry", "particularly", + "particullary", "particularly", + "passionatley", "passionately", + "pathalogical", "pathological", + "pathelogical", "pathological", + "patholigical", "pathological", + "paychedelics", "psychedelics", + "paychiatrist", "psychiatrist", + "paychologist", "psychologist", + "paychopathic", "psychopathic", + "penetratiing", "penetrating", + "penisylvania", "pennsylvania", + "pennsilvania", "pennsylvania", + "pennslyvania", "pennsylvania", + "pennsylvaina", "pennsylvania", + "pennsyvlania", "pennsylvania", + "pennyslvania", "pennsylvania", + "penssylvania", "pennsylvania", + "pentsylvania", "pennsylvania", + "percentagens", "percentages", + "perferential", "preferential", + "performantes", "performances", + "performences", "performances", + "perfromances", "performances", + "peridoically", "periodically", + "peripathetic", "peripatetic", + "periphereals", "peripherals", + "peripherials", "peripherals", + "permanantely", "permanently", + "permanentely", "permanently", + "permissiable", "permissible", + "peroidically", "periodically", + "perpatrators", "perpetrators", + "perpatuating", "perpetuating", + "perpertators", "perpetrators", + "perpertrated", "perpetrated", + "perpetraitor", "perpetrator", + "perpetraters", "perpetrators", + "perpetuaters", "perpetuates", + "perpitrators", "perpetrators", + "perposefully", "purposefully", + "perposterous", "preposterous", + "perpretators", "perpetrators", + "perpsectives", "perspectives", + "perputrators", "perpetrators", + "perputuating", "perpetuating", + "persepctives", "perspectives", + "perservation", "preservation", + "perseverence", "perseverance", + "personalites", "personalities", + "personallity", "personally", + "personilized", "personalized", + "perspecitves", "perspectives", + "perspectivas", "perspectives", + "persumptuous", "presumptuous", + "perticularly", "particularly", + "pertubations", "perturbations", + "pessimisitic", "pessimistic", + "pessimisstic", "pessimistic", + "phenomenonal", "phenomenal", + "phenomenonly", "phenomenally", + "phenomonenon", "phenomenon", + "phialdelphia", "philadelphia", + "philadalphia", "philadelphia", + "philadelhpia", "philadelphia", + "philadeplhia", "philadelphia", + "philadlephia", "philadelphia", + "philedalphia", "philadelphia", + "philedelphia", "philadelphia", + "philidalphia", "philadelphia", + "philippinnes", "philippines", + "philippinoes", "philippines", + "philisophers", "philosophers", + "philisophies", "philosophies", + "phillippines", "philippines", + "philosiphers", "philosophers", + "philosiphies", "philosophies", + "philosohpers", "philosopher", + "philosohpies", "philosophies", + "philosophiae", "philosophies", + "philosophics", "philosophies", + "philosophios", "philosophies", + "philospohers", "philosophers", + "philospohies", "philosophies", + "photagrapher", "photographer", + "photochopped", "photoshopped", + "photograhper", "photographer", + "photograpers", "photographers", + "photographes", "photographs", + "photographyi", "photographic", + "photogropher", "photographer", + "photogrpahed", "photographed", + "photogrpaher", "photographer", + "photoshipped", "photoshopped", + "photoshooped", "photoshopped", + "photoshoppad", "photoshopped", + "phychedelics", "psychedelics", + "phychiatrist", "psychiatrist", + "phychologist", "psychologist", + "phychopathic", "psychopathic", + "physcedelics", "psychedelics", + "physciatrist", "psychiatrist", + "physcologist", "psychologist", + "physcopathic", "psychopathic", + "physicallity", "physically", + "physiologial", "physiological", + "pilgrimmages", "pilgrimages", + "pitchforkers", "pitchforks", + "pkaythroughs", "playthroughs", + "plabeswalker", "planeswalker", + "plaestinians", "palestinians", + "planeswaller", "planeswalker", + "planeswlaker", "planeswalker", + "planetwalker", "planeswalker", + "plansewalker", "planeswalker", + "plauthroughs", "playthroughs", + "playhtroughs", "playthroughs", + "playtgroughs", "playthroughs", + "playthorughs", "playthroughs", + "playthourghs", "playthroughs", + "playthrougth", "playthroughs", + "playthrouhgs", "playthroughs", + "playthtoughs", "playthroughs", + "playtrhoughs", "playthroughs", + "populationes", "populations", + "pornograpghy", "pornography", + "porportional", "proportional", + "portabillity", "portability", + "portagonists", "protagonists", + "positionning", "positioning", + "positivitely", "positivity", + "possessivize", "possessive", + "possibillity", "possibility", + "possiblility", "possibility", + "possiblities", "possibilities", + "powerfisting", "powerlifting", + "powerlfiting", "powerlifting", + "powerlifitng", "powerlifting", + "powerlisting", "powerlifting", + "powetlifting", "powerlifting", + "powrrlifting", "powerlifting", + "practicioner", "practitioner", + "practisioner", "practitioner", + "pratictioner", "practitioners", + "precedessors", "predecessors", + "preconveived", "preconceived", + "predacessors", "predecessors", + "predeccesors", "predecessor", + "predecesores", "predecessor", + "predescesors", "predecessors", + "predessecors", "predecessors", + "predetermind", "predetermined", + "predicessors", "predecessors", + "predocessors", "predecessors", + "predomiantly", "predominately", + "predominanty", "predominantly", + "predominatly", "predominantly", + "preferantial", "preferential", + "preferentail", "preferential", + "preformances", "performances", + "preinitalize", "preinitialize", + "preliminarly", "preliminary", + "prematurelly", "prematurely", + "premillenial", "premillennial", + "preocupation", "preoccupation", + "preperations", "preparations", + "prepetrators", "perpetrators", + "prepetuating", "perpetuating", + "prepostorous", "preposterous", + "preposturous", "preposterous", + "prerequisets", "prerequisite", + "prescirption", "prescriptions", + "prescribtion", "prescription", + "prescripcion", "prescription", + "prescriptons", "prescriptions", + "prescritpion", "prescriptions", + "presedential", "presidential", + "presentacion", "presentation", + "presentaiton", "presentations", + "preservacion", "preservation", + "preservating", "preservation", + "preservativo", "preservation", + "presidencial", "presidential", + "presidenital", "presidential", + "presidentail", "presidential", + "presnetation", "presentations", + "presonalized", "personalized", + "prespectives", "perspectives", + "presrciption", "prescriptions", + "presumpteous", "presumptuous", + "presumputous", "presumptuous", + "prevantative", "preventative", + "preventation", "presentation", + "preventetive", "preventative", + "preventitive", "preventative", + "prezidential", "presidential", + "principlaity", "principality", + "probabiliste", "probabilities", + "probabilites", "probabilities", + "probabillity", "probability", + "probablistic", "probabilistic", + "proclomation", "proclamation", + "proconceived", "preconceived", + "profesisonal", "professionals", + "professiinal", "professionalism", + "professioanl", "professionals", + "professiomal", "professionalism", + "professionel", "professional", + "professionsl", "professionalism", + "professoinal", "professionals", + "professonial", "professionals", + "proffesional", "professional", + "proficientcy", "proficiency", + "profissional", "professional", + "profitabiliy", "profitability", + "profitabilty", "profitability", + "profressions", "progressions", + "progatonists", "protagonists", + "programmeurs", "programmer", + "progressieve", "progressive", + "progressioin", "progressions", + "progressiong", "progressing", + "progressisme", "progresses", + "progressiste", "progresses", + "progressivas", "progressives", + "progressivey", "progressively", + "progressivly", "progressively", + "progressivsm", "progressives", + "progresssing", "progressing", + "progresssion", "progressions", + "progresssive", "progressives", + "prohibitting", "prohibiting", + "projecticles", "projectiles", + "proletariaat", "proletariat", + "proletariant", "proletariat", + "proletaricat", "proletariat", + "prominantely", "prominently", + "promiscuious", "promiscuous", + "promisculous", "promiscuous", + "promotionnal", "promotional", + "pronounceing", "pronouncing", + "pronunciaton", "pronunciation", + "propertional", "proportional", + "propesterous", "preposterous", + "proportianal", "proportional", + "proportionel", "proportional", + "proposterous", "preposterous", + "proprotional", "proportional", + "prostetution", "prostitution", + "prostitition", "prostitution", + "prostitucion", "prostitution", + "prostituiton", "prostitution", + "prostitutiei", "prostitute", + "protaganists", "protagonists", + "protaginists", "protagonists", + "protagnoists", "protagonists", + "protestantes", "protestants", + "protoganists", "protagonists", + "prouncements", "pronouncements", + "pruposefully", "purposefully", + "pscyhologist", "psychologist", + "pscyhopathic", "psychopathic", + "pshyciatrist", "psychiatrist", + "pshycologist", "psychologist", + "pshycopathic", "psychopathic", + "psichologist", "psychologist", + "psychaitrist", "psychiatrist", + "psychedellic", "psychedelic", + "psychedilics", "psychedelics", + "psychemedics", "psychedelics", + "psychiatirst", "psychiatrists", + "psychiatrics", "psychiatrist", + "psychiatrict", "psychiatrist", + "psychiatrits", "psychiatrists", + "psychistrist", "psychiatrist", + "psychodelics", "psychedelics", + "psycholigist", "psychologist", + "psychologial", "psychological", + "psychologits", "psychologists", + "psychologyst", "psychologist", + "psychopathes", "psychopaths", + "psychyatrist", "psychiatrist", + "puplications", "publications", + "puritannical", "puritanical", + "purpetrators", "perpetrators", + "purpetuating", "perpetuating", + "purpusefully", "purposefully", + "pyschedelics", "psychedelics", + "pyschiatrist", "psychiatrist", + "pyschologist", "psychologist", + "pyschopathic", "psychopathic", + "qualificaton", "qualification", + "qualifierais", "qualifiers", + "qualtitative", "quantitative", + "quantatitive", "quantitative", + "quantititive", "quantitative", + "quarterblack", "quarterback", + "quesitonable", "questionable", + "questionalbe", "questionable", + "questionning", "questioning", + "questionsign", "questioning", + "radioactieve", "radioactive", + "rationallity", "rationally", + "reactionairy", "reactionary", + "reactionnary", "reactionary", + "realisticaly", "realistically", + "realisticlly", "realistically", + "reasonablely", "reasonably", + "recallection", "recollection", + "reccomending", "recommending", + "reccommended", "recommended", + "recepcionist", "receptionist", + "receptionest", "receptionist", + "recgonizable", "recognizable", + "reciporcated", "reciprocate", + "reciprociate", "reciprocate", + "reciprocrate", "reciprocate", + "recognizible", "recognizable", + "recolleciton", "recollection", + "recommanding", "recommending", + "recommendeds", "recommends", + "recommendors", "recommends", + "recommeneded", "recommended", + "recommenting", "recommending", + "recongizable", "recognizable", + "recontructed", "reconstructed", + "recpetionist", "receptionist", + "recreacional", "recreational", + "recriational", "recreational", + "referenceing", "referencing", + "refirgerator", "refrigerator", + "refriderator", "refrigerator", + "refrigarator", "refrigerator", + "refrigerador", "refrigerator", + "refrigerater", "refrigerator", + "refrigirator", "refrigerator", + "regenaration", "regeneration", + "regeneracion", "regeneration", + "regestration", "registration", + "registartion", "registration", + "registrating", "registration", + "regrigerator", "refrigerator", + "regulatorias", "regulators", + "regulatories", "regulators", + "regulatorios", "regulators", + "reicarnation", "reincarnation", + "reinforcemnt", "reinforcement", + "reinitalised", "reinitialised", + "reinitalises", "reinitialises", + "reinitalized", "reinitialized", + "reinitalizes", "reinitializes", + "reinstallled", "reinstalled", + "reisntalling", "reinstalling", + "relaitonship", "relationships", + "relatinoship", "relationships", + "reliabillity", "reliability", + "reluctanctly", "reluctantly", + "remarkablely", "remarkably", + "rememberance", "remembrance", + "reminiscient", "reminiscent", + "renaissaince", "renaissance", + "renegeration", "regeneration", + "reorganision", "reorganisation", + "repalcements", "replacements", + "repersenting", "representing", + "reporduction", "reproduction", + "reporductive", "reproductive", + "reprecussion", "repercussions", + "representate", "representative", + "represention", "representing", + "representive", "representative", + "reproducable", "reproducible", + "reproduccion", "reproduction", + "reproduciton", "reproduction", + "reproducting", "reproduction", + "reproductivo", "reproduction", + "reproduktion", "reproduction", + "repsectfully", "respectfully", + "repsectively", "respectively", + "republicanas", "republicans", + "republicanos", "republicans", + "republicants", "republicans", + "republicians", "republicans", + "requerimento", "requirement", + "requeriments", "requirements", + "requierments", "requirements", + "requriements", "requirements", + "resembelance", "resemblance", + "reseptionist", "receptionist", + "reserrection", "resurrection", + "resintalling", "reinstalling", + "resistancies", "resistances", + "resistencias", "resistances", + "respecitvely", "respectively", + "respectabile", "respectable", + "respectivily", "respectively", + "respectivley", "respectively", + "respectuflly", "respectfully", + "respiratiory", "respiratory", + "responsabile", "responsible", + "responsaveis", "responsive", + "responsbilty", "responsibly", + "responsibile", "responsible", + "responsibily", "responsibility", + "responsibley", "responsibly", + "responsibliy", "responsibly", + "responsiblty", "responsibly", + "ressemblance", "resemblance", + "ressemblence", "resemblance", + "ressurection", "resurrection", + "restaurantes", "restaurants", + "restauration", "restoration", + "restauraunts", "restaurants", + "restirctions", "restrictions", + "restrainting", "restraining", + "restrcitions", "restriction", + "restricitons", "restrictions", + "resurreccion", "resurrection", + "resurrektion", "resurrection", + "retalitation", "retaliation", + "retributioon", "retribution", + "retroactivly", "retroactively", + "revolutionay", "revolutionary", + "revolutionos", "revolutions", + "rezurrection", "resurrection", + "rictatorship", "dictatorship", + "ridicilously", "ridiculously", + "ridicoulusly", "ridiculously", + "righteouness", "righteousness", + "rockerfeller", "rockefeller", + "rollercoaser", "rollercoaster", + "rollercoater", "rollercoaster", + "romanitcally", "romantically", + "roundabounts", "roundabout", + "rudimentatry", "rudimentary", + "rysurrection", "resurrection", + "sacksonville", "jacksonville", + "sacreligious", "sacrilegious", + "sacrificeing", "sacrificing", + "saksatchewan", "saskatchewan", + "salughtering", "slaughtering", + "sanctionning", "sanctioning", + "sarcasticaly", "sarcastically", + "sarcasticlly", "sarcastically", + "sascatchewan", "saskatchewan", + "saskatcehwan", "saskatchewan", + "saskatchawan", "saskatchewan", + "saskatechwan", "saskatchewan", + "sasketchawan", "saskatchewan", + "sasketchewan", "saskatchewan", + "sasktachewan", "saskatchewan", + "satasfaction", "satisfaction", + "satasfactory", "satisfactory", + "satisfaccion", "satisfaction", + "satisfacting", "satisfaction", + "satisfcation", "satisfaction", + "satisfiction", "satisfaction", + "satistactory", "satisfactory", + "satsifaction", "satisfaction", + "satsifactory", "satisfactory", + "scandanivian", "scandinavian", + "scandenavian", "scandinavian", + "scandianvian", "scandinavian", + "scandinacian", "scandinavian", + "scandinaivan", "scandinavia", + "scandinavica", "scandinavian", + "scandinavien", "scandinavian", + "scandinavion", "scandinavian", + "scandivanian", "scandinavian", + "scandonavian", "scandinavian", + "schizophrena", "schizophrenia", + "scholarhsips", "scholarships", + "scholerships", "scholarships", + "scholorships", "scholarships", + "scnadinavian", "scandinavian", + "screenshoots", "screenshot", + "sensationail", "sensational", + "sensationnal", "sensational", + "sensibilites", "sensibilities", + "sensitivitiy", "sensitivity", + "sentimentals", "sentiments", + "sertificates", "certificates", + "serveillance", "surveillance", + "seskatchewan", "saskatchewan", + "shakesperean", "shakespeare", + "shamelessely", "shamelessly", + "shamelessley", "shamelessly", + "shampionship", "championship", + "shardholders", "shareholders", + "shenanigains", "shenanigans", + "shenanigangs", "shenanigans", + "shenaniganns", "shenanigans", + "shenanighans", "shenanigans", + "shopkeeepers", "shopkeepers", + "showboarding", "snowboarding", + "siginificant", "significant", + "significanly", "significantly", + "significante", "significance", + "significanty", "significantly", + "significatly", "significantly", + "signleplayer", "singleplayer", + "simaltaneous", "simultaneous", + "simeltaneous", "simultaneous", + "similaraties", "similarities", + "similiarites", "similarities", + "similiarties", "similarities", + "similiraties", "similarities", + "similtaneous", "simultaneous", + "simliarities", "similarities", + "simlutaneous", "simultaneous", + "simpathizers", "sympathizers", + "simplistisch", "simplistic", + "simulatenous", "simultaneous", + "simulatneous", "simultaneous", + "simultaenous", "simultaneous", + "simultaneuos", "simultaneous", + "simultanious", "simultaneous", + "simulteneous", "simultaneous", + "singelplayer", "singleplayer", + "singlepalyer", "singleplayer", + "sinlgeplayer", "singleplayer", + "situationals", "situations", + "situationnal", "situational", + "skandinavian", "scandinavian", + "skateboaring", "skateboarding", + "skrawberries", "strawberries", + "slaugthering", "slaughtering", + "sloughtering", "slaughtering", + "sluaghtering", "slaughtering", + "snowballling", "snowballing", + "snowbaording", "snowboarding", + "socialistisk", "socialists", + "socialogical", "sociological", + "socioeconimc", "socioeconomic", + "socioeconmic", "socioeconomic", + "socioligical", "sociological", + "sociopolical", "sociological", + "somethingest", "somethings", + "sophisticaed", "sophisticated", + "sophisticted", "sophisticated", + "southamption", "southampton", + "southernerns", "southerners", + "sovereighnty", "sovereignty", + "sovereignety", "sovereignty", + "sovereignity", "sovereignty", + "specialistes", "specialists", + "specializare", "specialize", + "specializate", "specialize", + "specializeds", "specializes", + "specializied", "specialize", + "speciallized", "specialised", + "specifcation", "specification", + "spectacuarly", "spectacular", + "spectaculair", "spectacular", + "spectaculary", "spectacularly", + "spectacullar", "spectacularly", + "specualtions", "speculation", + "spermatozoan", "spermatozoon", + "spesifically", "specifically", + "spirituallly", "spiritually", + "spirtiuality", "spirituality", + "spirutuality", "spirituality", + "spontaneosly", "spontaneously", + "spontaneouly", "spontaneously", + "spreadhseets", "spreadsheets", + "spreadsheats", "spreadsheets", + "spreadsheeds", "spreadsheets", + "spreadsheeet", "spreadsheets", + "standartized", "standardized", + "standerdized", "standardized", + "stardardized", "standardized", + "starightened", "straightened", + "starwberries", "strawberries", + "statisticaly", "statistically", + "stereotpying", "stereotyping", + "stereotypers", "stereotypes", + "stereotypian", "stereotyping", + "steriotyping", "stereotyping", + "steroetyping", "stereotyping", + "steryotyping", "stereotyping", + "straigntened", "straightened", + "straigthened", "straightened", + "strategicaly", "strategically", + "strategiclly", "strategically", + "strawburries", "strawberries", + "streemlining", "streamlining", + "streightened", "straightened", + "strenghening", "strengthening", + "strenghtened", "strengthened", + "strengtheing", "strengthening", + "stroytelling", "storytelling", + "subconcsious", "subconscious", + "subconsicous", "subconscious", + "subcouncious", "subconscious", + "subcsription", "subscriptions", + "subesquently", "subsequently", + "subjectivety", "subjectively", + "subjectivily", "subjectively", + "subjectivley", "subjectively", + "subjudgation", "subjugation", + "subredditors", "subreddits", + "subscirption", "subscriptions", + "subsconcious", "subconscious", + "subscribbers", "subscribers", + "subscribbing", "subscribing", + "subscribirse", "subscriber", + "subscribtion", "subscription", + "subscriptons", "subscriptions", + "subscritpion", "subscriptions", + "subscrpition", "subscriptions", + "subsiquently", "subsequently", + "subsrciption", "subscriptions", + "subsricption", "subscriptions", + "substantialy", "substantially", + "substantitve", "substantive", + "substitition", "substitution", + "substituters", "substitutes", + "substitutivo", "substitution", + "substitutues", "substitutes", + "substracting", "subtracting", + "substraction", "subtraction", + "subterranian", "subterranean", + "succsessfull", "successful", + "sunconscious", "subconscious", + "supermarkeds", "supermarkets", + "supermarkers", "supermarkets", + "supermarkert", "supermarkets", + "supermarkten", "supermarket", + "supermarktes", "supermarkets", + "supernarkets", "supermarkets", + "supernatrual", "supernatural", + "supersticion", "superstition", + "superstision", "superstition", + "superstitios", "superstitious", + "superstitous", "superstitious", + "supervisiors", "supervisors", + "supervisoras", "supervisors", + "supervisores", "supervisors", + "supllemental", "supplemental", + "supplamental", "supplemental", + "supplamented", "supplemented", + "supplimental", "supplemental", + "suppresssion", "suppression", + "supscription", "subscription", + "supsiciously", "suspiciously", + "surprizingly", "surprisingly", + "surrenderred", "surrendered", + "surrundering", "surrendering", + "survaillance", "surveillance", + "survaillence", "surveillance", + "survallience", "surveillance", + "surveillence", "surveillance", + "survelliance", "surveillance", + "surviellance", "surveillance", + "survivabiity", "survivability", + "survivabiliy", "survivability", + "survivabilty", "survivability", + "susceptiable", "susceptible", + "susceptibile", "susceptible", + "suspeciously", "suspiciously", + "suspicioulsy", "suspiciously", + "suspiciuosly", "suspiciously", + "suspisiously", "suspiciously", + "sustainabily", "sustainability", + "symapthizers", "sympathizers", + "symetrically", "symmetrically", + "symmetricaly", "symmetrically", + "sympathethic", "sympathetic", + "sympathsizer", "sympathizers", + "sympathyzers", "sympathizers", + "sympethizers", "sympathizers", + "symphatizers", "sympathizers", + "sympithizers", "sympathizers", + "syncronously", "synchronously", + "sysmatically", "systematically", + "systematisch", "systematic", + "tablespooons", "tablespoon", + "tacticallity", "tactically", + "tangencially", "tangentially", + "tangenitally", "tangentially", + "tangientally", "tangentially", + "teamfighters", "teamfights", + "teansylvania", "transylvania", + "techanically", "mechanically", + "techincality", "technicality", + "technologial", "technological", + "telelevision", "television", + "teleportaion", "teleportation", + "teleportaton", "teleportation", + "temepratures", "temperatures", + "temparatures", "temperatures", + "temperaturas", "temperatures", + "temporarilly", "temporarily", + "tempreatures", "temperatures", + "tempuratures", "temperatures", + "tengentially", "tangentially", + "termendously", "tremendously", + "territorrial", "territorial", + "territorries", "territories", + "testasterone", "testosterone", + "testestorone", "testosterone", + "thanskgiving", "thanksgiving", + "theologicial", "theological", + "theoreticaly", "theoretically", + "thermomenter", "thermometer", + "thermomether", "thermometer", + "thumbnailers", "thumbnails", + "thunderboldt", "thunderbolt", + "tindergarten", "kindergarten", + "torubleshoot", "troubleshoot", + "totalitarion", "totalitarian", + "totalitatian", "totalitarian", + "touchscreeen", "touchscreen", + "traditionaly", "traditionally", + "traditionnal", "traditional", + "tradtionally", "traditionally", + "tramendously", "tremendously", + "tramsformers", "transformers", + "tramsforming", "transforming", + "tranditional", "transitional", + "tranistional", "transitional", + "tranistioned", "transitioned", + "tranlsations", "translations", + "tranmsission", "transmissions", + "transaltions", "translations", + "transaprency", "transparency", + "transational", "transitional", + "transcations", "transactions", + "transcendant", "transcendent", + "transcripton", "transcription", + "transcriptus", "transcripts", + "transesxuals", "transsexuals", + "transfarmers", "transformers", + "transfarring", "transferring", + "transferrred", "transferred", + "transformare", "transformers", + "transformase", "transforms", + "transformees", "transforms", + "transforners", "transformers", + "transfromers", "transformers", + "transfroming", "transforming", + "transgenderd", "transgendered", + "transgendred", "transgendered", + "transgenered", "transgender", + "transicional", "transitional", + "transilvania", "transylvania", + "transimssion", "transmissions", + "transisioned", "transitioned", + "translastion", "translations", + "translateing", "translating", + "translationg", "translating", + "translucient", "translucent", + "translyvania", "transylvania", + "transmisions", "transmission", + "transmisison", "transmission", + "transmissons", "transmissions", + "transmitirte", "transmitter", + "transmittted", "transmitted", + "transmorfers", "transformer", + "transofrmers", "transformers", + "transofrming", "transforming", + "transparancy", "transparency", + "transparenty", "transparency", + "transparrent", "transparent", + "transperancy", "transparency", + "transperency", "transparency", + "transplantes", "transplants", + "transporteur", "transporter", + "transportion", "transporting", + "transpotting", "transporting", + "transsmision", "transmissions", + "transylmania", "transylvania", + "transylvanai", "transylvania", + "trasnferring", "transferring", + "trasnformers", "transformers", + "trasnforming", "transforming", + "trasnmission", "transmissions", + "trasnparency", "transparency", + "trasnporting", "transporting", + "trememdously", "tremendously", + "tremendoulsy", "tremendously", + "tremondously", "tremendously", + "troubelshoot", "troubleshoot", + "troublehsoot", "troubleshoot", + "trumendously", "tremendously", + "trustworthly", "trustworthy", + "ubsubscribed", "unsubscribed", + "udnerpowered", "underpowered", + "umbelievable", "unbelievable", + "umemployment", "unemployment", + "unaccaptable", "unacceptable", + "unacceptible", "unacceptable", + "unaccpetable", "unacceptable", + "unacompanied", "unaccompanied", + "unappealling", "unappealing", + "unattractice", "unattractive", + "unautherized", "unauthorized", + "unauthroized", "unauthorized", + "unbeleivable", "unbelievable", + "unbeleivably", "unbelievably", + "unbeliavable", "unbelievable", + "unbeliavably", "unbelievably", + "unbeliebable", "unbelievable", + "unbelieveble", "unbelievable", + "unbelievibly", "unbelievably", + "unbeliveable", "unbelievable", + "unbeliveably", "unbelievably", + "unbelizeable", "unbelievable", + "unbolievable", "unbelievable", + "uncertainity", "uncertainty", + "uncertaintly", "uncertainty", + "uncompatible", "incompatible", + "unconditinal", "unconditional", + "unconsciosly", "unconsciously", + "unconsciouly", "unconsciously", + "unconsistent", "inconsistent", + "unconvenient", "inconvenient", + "unconvential", "unconventional", + "undecideable", "undecidable", + "undefinitely", "indefinitely", + "undeniablely", "undeniably", + "undergradate", "undergraduate", + "undergradute", "undergraduate", + "underminding", "undermining", + "undermineing", "undermining", + "undermineras", "undermines", + "undermineres", "undermines", + "underminging", "undermining", + "underminning", "undermining", + "undertakeing", "undertaking", + "underwhelimg", "underwhelming", + "underwheling", "underwhelming", + "undesireable", "undesirable", + "undoubtedbly", "undoubtedly", + "unemployemnt", "unemployment", + "unemplyoment", "unemployment", + "unempolyment", "unemployment", + "unenployment", "unemployment", + "unequalities", "inequalities", + "unexpectadly", "unexpectedly", + "unexpectetly", "unexpectedly", + "unexpectidly", "unexpectedly", + "unexperience", "inexperience", + "unexpextedly", "unexpectedly", + "unexplicably", "inexplicably", + "unforgetable", "unforgettable", + "unforgiveble", "unforgivable", + "unforgivible", "unforgivable", + "unfortunatly", "unfortunately", + "unfortunetly", "unfortunately", + "unilatreally", "unilaterally", + "uniliterally", "unilaterally", + "unimpresssed", "unimpressed", + "uninitalised", "uninitialised", + "uninitalized", "uninitialized", + "uninstallimg", "uninstalling", + "uninstallled", "uninstalled", + "unintentinal", "unintentional", + "uninteresing", "uninteresting", + "uninterneted", "uninterested", + "uninterruped", "uninterrupted", + "uninterupted", "uninterrupted", + "unisntalling", "uninstalling", + "unitesstates", "unitedstates", + "univerisites", "universities", + "univeristies", "universities", + "universitets", "universities", + "unliaterally", "unilaterally", + "unneccessary", "unnecessary", + "unnecesarily", "unnecessarily", + "unnecessairy", "unnecessarily", + "unnecessarly", "unnecessarily", + "unnistalling", "uninstalling", + "unpredictabe", "unpredictable", + "unpreductive", "unproductive", + "unproduktive", "unproductive", + "unrealisitic", "unrealistic", + "unreaponsive", "unresponsive", + "unreasonalby", "unreasonably", + "unrepsonsive", "unresponsive", + "unresponcive", "unresponsive", + "unresponisve", "unresponsive", + "unresponsibe", "unresponsive", + "unrestircted", "unrestricted", + "unrestrcited", "unrestricted", + "unristricted", "unrestricted", + "unseccessful", "unsuccessful", + "unsespecting", "unsuspecting", + "unsibscribed", "unsubscribed", + "unsoliciated", "unsolicited", + "unsolicitied", "unsolicited", + "unsubscirbed", "unsubscribed", + "unsubscrible", "unsubscribed", + "unsubscrided", "unsubscribed", + "unsubscriped", "unsubscribed", + "unsubscrubed", "unsubscribed", + "unsubsrcibed", "unsubscribed", + "unsucessfull", "unsuccessful", + "unsunscribed", "unsubscribed", + "unsurprizing", "unsurprising", + "unsusbcribed", "unsubscribed", + "unsustainble", "unsustainable", + "unvelievable", "unbelievable", + "unvelievably", "unbelievably", + "unviersities", "universities", + "unvulnerable", "invulnerable", + "varification", "verification", + "vegetarianas", "vegetarians", + "vegetarianos", "vegetarians", + "verficiation", "verification", + "verificacion", "verification", + "verificaiton", "verification", + "verifikation", "verification", + "vernaculaire", "vernacular", + "versatillity", "versatility", + "verticallity", "vertically", + "videogamemes", "videogames", + "visualizaton", "visualization", + "vocabularily", "vocabulary", + "vocabularity", "vocabulary", + "volonteering", "volunteering", + "volounteered", "volunteered", + "voluntarilly", "voluntarily", + "volunterring", "volunteering", + "vulnerabilty", "vulnerability", + "weightlifing", "weightlifting", + "withdrawalls", "withdrawals", + "withdrawling", "withdrawing", + "withdrawning", "withdrawing", + "wonderfullly", "wonderfully", + "worshippping", "worshipping", + "xenophobical", "xenophobia", + "abandenment", "abandonment", + "abandomnent", "abandonment", + "abandonding", "abandoning", + "abandonnent", "abandonment", + "abandonning", "abandoning", + "abbreviatin", "abbreviation", + "abbreviaton", "abbreviation", + "abdominable", "abdominal", + "abomanation", "abomination", + "abominacion", "abomination", + "abomonation", "abomination", + "abonimation", "abomination", + "aboriginial", "aboriginal", + "aborigional", "aboriginal", + "abreviation", "abbreviation", + "abritrarily", "arbitrarily", + "abritration", "arbitration", + "absolutelly", "absolutely", + "absolutelys", "absolutes", + "absolutisme", "absolutes", + "absolutiste", "absolutes", + "abstraccion", "abstraction", + "abstraktion", "abstraction", + "abstruction", "abstraction", + "abundancies", "abundances", + "academicaly", "academically", + "academicese", "academics", + "accelarated", "accelerated", + "accelarator", "accelerator", + "accelerater", "accelerator", + "acceleratie", "accelerate", + "acceleratio", "accelerator", + "acceleraton", "acceleration", + "accelorated", "accelerated", + "accelorator", "accelerator", + "acceptabelt", "acceptable", + "accesseries", "accessories", + "accessibile", "accessible", + "accessibily", "accessibility", + "accessoires", "accessories", + "accidantely", "accidently", + "accidentaly", "accidentally", + "accidentely", "accidently", + "accidential", "accidental", + "accidentily", "accidently", + "accidentlay", "accidently", + "accidentley", "accidently", + "accidentlly", "accidently", + "accomadated", "accommodated", + "accomadates", "accommodates", + "accommadate", "accommodate", + "accommidate", "accommodate", + "accomodated", "accommodated", + "accomodates", "accommodates", + "accomondate", "accommodate", + "accompained", "accompanied", + "accompanyed", "accompanied", + "accompianed", "accompanied", + "accompinied", "accompanied", + "accomplises", "accomplishes", + "accomplishs", "accomplishes", + "accomponied", "accompanied", + "accountatns", "accountants", + "accountents", "accountants", + "accquainted", "acquainted", + "accrediated", "accredited", + "accreditied", "accredited", + "accreditted", "accredited", + "acculumated", "accumulated", + "accumalated", "accumulated", + "accumelated", "accumulated", + "accumilated", "accumulated", + "accumulatin", "accumulation", + "accumulaton", "accumulation", + "accuratelly", "accurately", + "accustommed", "accustomed", + "acheivement", "achievement", + "acheivments", "achievements", + "achievemint", "achievement", + "achievemnts", "achievements", + "achievments", "achievements", + "achivements", "achievements", + "acknolwedge", "acknowledge", + "acknoweldge", "acknowledge", + "acknowleded", "acknowledged", + "acknowlegde", "acknowledge", + "acknowleged", "acknowledge", + "acknowleges", "acknowledges", + "acknwoledge", "acknowledges", + "acomplished", "accomplished", + "acopalyptic", "apocalyptic", + "acquaintace", "acquaintance", + "acquisation", "acquisition", + "activateing", "activating", + "activationg", "activating", + "activistion", "activision", + "additinally", "additionally", + "additionaly", "additionally", + "additonally", "additionally", + "adequatedly", "adequately", + "adjectiveus", "adjectives", + "administerd", "administered", + "administrar", "administrator", + "administren", "administer", + "administrer", "administer", + "administres", "administer", + "administrez", "administer", + "adminstered", "administered", + "adminstrate", "administrate", + "admittadely", "admittedly", + "adolencence", "adolescence", + "adolescance", "adolescence", + "adolescense", "adolescence", + "advantadges", "advantages", + "advantageos", "advantageous", + "advantageus", "advantageous", + "advantagous", "advantageous", + "adventerous", "adventures", + "adventourus", "adventurous", + "adversiting", "advertising", + "advertisors", "advertisers", + "advertisted", "advertised", + "aesthethics", "aesthetics", + "afficionado", "aficionado", + "affiliction", "affiliation", + "affirmitave", "affirmative", + "affirmitive", "affirmative", + "affixiation", "affiliation", + "affrimative", "affirmative", + "afgahnistan", "afghanistan", + "afganhistan", "afghanistan", + "afghanastan", "afghanistan", + "afghansitan", "afghanistan", + "afhganistan", "afghanistan", + "afternarket", "aftermarket", + "afterthougt", "afterthought", + "aggaravates", "aggravates", + "aggragating", "aggravating", + "aggregatore", "aggregate", + "aggressivly", "aggressively", + "aggresssion", "aggression", + "aggrovating", "aggravating", + "agnostacism", "agnosticism", + "agnostisicm", "agnosticism", + "agnostisism", "agnosticism", + "agnostocism", "agnosticism", + "agnsoticism", "agnosticism", + "agonsticism", "agnosticism", + "agressively", "aggressively", + "agressivley", "agressive", + "agressivnes", "agressive", + "agricolture", "agriculture", + "agriculteur", "agriculture", + "agricultral", "agricultural", + "agricultual", "agricultural", + "agricutlure", "agriculture", + "ahtleticism", "athleticism", + "alcoholicas", "alcoholics", + "alcoholicos", "alcoholics", + "alcoholisim", "alcoholism", + "algorithems", "algorithm", + "algorithims", "algorithm", + "algorithmes", "algorithms", + "algorithmns", "algorithms", + "algorithmus", "algorithms", + "algorithyms", "algorithm", + "algorythims", "algorithms", + "alientating", "alienating", + "alleigances", "allegiance", + "alltogether", "altogether", + "alterantive", "alternative", + "alternatley", "alternately", + "alternitive", "alternative", + "altheticism", "athleticism", + "altnerately", "alternately", + "altruisitic", "altruistic", + "altruistric", "altruistic", + "amalgomated", "amalgamated", + "ambulancier", "ambulance", + "amerliorate", "ameliorate", + "ammendments", "amendments", + "ampehtamine", "amphetamine", + "ampethamine", "amphetamine", + "amphetamies", "amphetamines", + "amphetamins", "amphetamines", + "amphetemine", "amphetamine", + "amphetimine", "amphetamine", + "amphetmaine", "amphetamines", + "analyticals", "analytics", + "anarchistes", "anarchists", + "ancedotally", "anecdotally", + "androgenous", "androgynous", + "anecdatally", "anecdotally", + "anecdotelly", "anecdotally", + "anecodtally", "anecdotally", + "anectodally", "anecdotally", + "anectotally", "anecdotally", + "anedoctally", "anecdotally", + "angosticism", "agnosticism", + "anihilation", "annihilation", + "anitbiotics", "antibiotics", + "annihalated", "annihilated", + "annihilaton", "annihilation", + "annihilited", "annihilated", + "annihliated", "annihilated", + "annilihated", "annihilated", + "anniversery", "anniversary", + "annonymouse", "anonymous", + "announceing", "announcing", + "announcemet", "announcements", + "announcemnt", "announcement", + "announcents", "announces", + "annoymously", "anonymously", + "anonamously", "anonymously", + "anonimously", "anonymously", + "anonmyously", "anonymously", + "anonomously", "anonymously", + "anonymousny", "anonymously", + "anouncement", "announcement", + "antagonisic", "antagonistic", + "antagonistc", "antagonistic", + "antagonstic", "antagonist", + "anthropolgy", "anthropology", + "anthropoloy", "anthropology", + "antibiodics", "antibiotics", + "antibioitcs", "antibiotic", + "antibioitic", "antibiotic", + "antibitoics", "antibiotics", + "antiboitics", "antibiotics", + "anticapated", "anticipated", + "anticiapted", "anticipated", + "anticipatin", "anticipation", + "antiobitics", "antibiotic", + "antiquaited", "antiquated", + "antisipated", "anticipated", + "apacolyptic", "apocalyptic", + "apocaliptic", "apocalyptic", + "apocalpytic", "apocalyptic", + "apocalytpic", "apocalyptic", + "apolagizing", "apologizing", + "apolegetics", "apologetics", + "apologistas", "apologists", + "apologistes", "apologists", + "apostrophie", "apostrophe", + "apparantely", "apparently", + "appareances", "appearances", + "apparentely", "apparently", + "appartments", "apartments", + "appeareance", "appearance", + "appearences", "appearances", + "apperciated", "appreciated", + "apperciates", "appreciates", + "appereances", "appearances", + "applicabile", "applicable", + "applicaiton", "application", + "applicatins", "applicants", + "applicatons", "applications", + "appoitnment", "appointments", + "apporaching", "approaching", + "apporpriate", "appropriate", + "apporximate", "approximate", + "appraoching", "approaching", + "apprearance", "appearance", + "apprecaited", "appreciated", + "apprecaites", "appreciates", + "appreciaite", "appreciative", + "appreciatie", "appreciative", + "appreciatin", "appreciation", + "appreciaton", "appreciation", + "appreciatve", "appreciative", + "appreicated", "appreciated", + "appreicates", "appreciates", + "apprentince", "apprentice", + "appriciated", "appreciated", + "appriciates", "appreciates", + "apprieciate", "appreciate", + "appropirate", "appropriate", + "appropraite", "appropriate", + "appropriato", "appropriation", + "approxamate", "approximate", + "approxiamte", "approximate", + "approxmiate", "approximate", + "aprehensive", "apprehensive", + "apsirations", "aspirations", + "aqcuisition", "acquisition", + "aquaintance", "acquaintance", + "aquiantance", "acquaintance", + "arbitrairly", "arbitrarily", + "arbitralily", "arbitrarily", + "arbitrarely", "arbitrarily", + "arbitrarion", "arbitration", + "arbitratily", "arbitrarily", + "arbritarily", "arbitrarily", + "arbritation", "arbitration", + "arcaheology", "archaeology", + "archaoelogy", "archeology", + "archeaology", "archaeology", + "archimedian", "archimedean", + "architechts", "architect", + "architectes", "architects", + "architecure", "architecture", + "argiculture", "agriculture", + "argumentate", "argumentative", + "aribtrarily", "arbitrarily", + "aribtration", "arbitration", + "arithmentic", "arithmetic", + "arithmethic", "arithmetic", + "arithmetric", "arithmetic", + "armagedddon", "armageddon", + "armageddeon", "armageddon", + "arrangments", "arrangements", + "arrengement", "arrangement", + "articluated", "articulated", + "articualted", "articulated", + "artifically", "artificially", + "artificialy", "artificially", + "aspergerers", "aspergers", + "asphyxation", "asphyxiation", + "aspriations", "aspirations", + "assasinated", "assassinated", + "assasinates", "assassinates", + "assassiante", "assassinate", + "assassinare", "assassinate", + "assassinatd", "assassinated", + "assassinato", "assassination", + "assassinats", "assassins", + "assassinted", "assassinated", + "assembleing", "assembling", + "assemblying", "assembling", + "assertation", "assertion", + "assignemnts", "assignments", + "assimialted", "assimilate", + "assimilatie", "assimilate", + "assimilerat", "assimilate", + "assimiliate", "assimilate", + "assimliated", "assimilate", + "assingments", "assignments", + "assistantes", "assistants", + "assocaition", "associations", + "associaiton", "associations", + "associaties", "associates", + "associatons", "associations", + "assoication", "association", + "assosiating", "associating", + "assosiation", "association", + "assoziation", "association", + "assumptious", "assumptions", + "astonashing", "astonishing", + "astonoshing", "astonishing", + "astronaught", "astronaut", + "astronaunts", "astronaut", + "astronautas", "astronauts", + "astronautes", "astronauts", + "asychronous", "asynchronous", + "asyncronous", "asynchronous", + "atatchments", "attachments", + "atheistisch", "atheistic", + "athelticism", "athleticism", + "athletecism", "athleticism", + "athleticsim", "athleticism", + "athletisicm", "athleticism", + "athletisism", "athleticism", + "atmopsheric", "atmospheric", + "atmoshperic", "atmospheric", + "atmosoheric", "atmospheric", + "atomspheric", "atmospheric", + "atrocitites", "atrocities", + "attachemnts", "attachments", + "attackerasu", "attackers", + "attackerats", "attackers", + "attactments", "attachments", + "attributred", "attributed", + "attributted", "attribute", + "attrocities", "atrocities", + "atttributes", "attributes", + "audiobookas", "audiobooks", + "audioboooks", "audiobook", + "auotcorrect", "autocorrect", + "austrailans", "australians", + "austrailian", "australian", + "australiaan", "australians", + "australiams", "australians", + "australiens", "australians", + "australlian", "australian", + "authenticiy", "authenticity", + "authenticor", "authenticator", + "authenticty", "authenticity", + "authorative", "authoritative", + "authoritate", "authoritative", + "authoroties", "authorities", + "autoatttack", "autoattack", + "autocoreect", "autocorrect", + "autocorrekt", "autocorrect", + "autocorrent", "autocorrect", + "autocorrext", "autocorrect", + "autoctonous", "autochthonous", + "autokorrect", "autocorrect", + "automaticly", "automatically", + "automatonic", "automation", + "automoblies", "automobile", + "auxillaries", "auxiliaries", + "availabiliy", "availability", + "availabilty", "availability", + "availablity", "availability", + "awesoneness", "awesomeness", + "babysittter", "babysitter", + "backbacking", "backpacking", + "backgorunds", "backgrounds", + "backhacking", "backpacking", + "backjacking", "backpacking", + "backtacking", "backpacking", + "bangaldeshi", "bangladesh", + "bangladesch", "bangladesh", + "barceloneta", "barcelona", + "bargainning", "bargaining", + "battelfield", "battlefield", + "battelfront", "battlefront", + "battelships", "battleship", + "battlefeild", "battlefield", + "battlefiend", "battlefield", + "battlefiled", "battlefield", + "battlefornt", "battlefront", + "battlehsips", "battleship", + "beastiality", "bestiality", + "beaurocracy", "bureaucracy", + "beautyfully", "beautifully", + "behaviorial", "behavioral", + "belittleing", "belittling", + "belittlling", "belittling", + "belligerant", "belligerent", + "belligirent", "belligerent", + "bellweather", "bellwether", + "benefitical", "beneficial", + "bestiallity", "bestiality", + "beuatifully", "beautifully", + "beuraucracy", "bureaucracy", + "beuraucrats", "bureaucrats", + "billegerent", "belligerent", + "billionairs", "billionaires", + "billionarie", "billionaire", + "billioniare", "billionaire", + "biologicaly", "biologically", + "birthdayers", "birthdays", + "birthdaymas", "birthdays", + "bittersweat", "bittersweet", + "bitterwseet", "bittersweet", + "blackberrry", "blackberry", + "blacksmitch", "blacksmith", + "bloodboorne", "bloodborne", + "bluebarries", "blueberries", + "blueburries", "blueberries", + "blueprients", "blueprints", + "bodybuildig", "bodybuilding", + "bodybuildng", "bodybuilding", + "bodybuiling", "bodybuilding", + "bombardeada", "bombarded", + "bombardeado", "bombarded", + "bombarderad", "bombarded", + "bordelrands", "borderlands", + "bordlerands", "borderlands", + "bortherhood", "brotherhood", + "bourgeousie", "bourgeois", + "boycottting", "boycotting", + "bracelettes", "bracelets", + "brainwahsed", "brainwashed", + "brainwasing", "brainwashing", + "braziliians", "brazilians", + "breakthough", "breakthrough", + "breakthrouh", "breakthrough", + "breathtakng", "breathtaking", + "brianwashed", "brainwashed", + "brillaintly", "brilliantly", + "broadcasing", "broadcasting", + "broadcastes", "broadcasts", + "broderlands", "borderlands", + "brotherwood", "brotherhood", + "buddhistisk", "buddhists", + "buearucrats", "bureaucrats", + "bueraucracy", "bureaucracy", + "bueraucrats", "bureaucrats", + "buisnessman", "businessman", + "buisnessmen", "businessmen", + "bullerproof", "bulletproof", + "bulletbroof", "bulletproof", + "bulletproff", "bulletproof", + "bulletprrof", "bulletproof", + "bullitproof", "bulletproof", + "bureacuracy", "bureaucracy", + "bureaocracy", "bureaucracy", + "bureaocrats", "bureaucrats", + "bureaucraps", "bureaucrats", + "bureaucrash", "bureaucrats", + "bureaucrasy", "bureaucrats", + "bureaucrazy", "bureaucracy", + "bureuacracy", "bureaucracy", + "bureuacrats", "bureaucrats", + "burueacrats", "bureaucrats", + "businessnes", "businessmen", + "busniessmen", "businessmen", + "butterfiles", "butterflies", + "butterfleye", "butterfly", + "butterflyes", "butterflies", + "butterfries", "butterflies", + "butterlfies", "butterflies", + "caclulating", "calculating", + "caclulation", "calculation", + "caclulators", "calculators", + "cailbration", "calibration", + "calbiration", "calibration", + "calcualting", "calculating", + "calcualtion", "calculations", + "calcualtors", "calculators", + "calculaters", "calculators", + "calculatios", "calculators", + "calculatons", "calculations", + "calibartion", "calibration", + "calibraiton", "calibration", + "califorinan", "californian", + "californain", "californian", + "californica", "california", + "californien", "californian", + "californiia", "californian", + "californina", "californian", + "californnia", "californian", + "califronian", "californian", + "caluclating", "calculating", + "caluclation", "calculation", + "caluclators", "calculators", + "caluculated", "calculated", + "caluiflower", "cauliflower", + "camouflague", "camouflage", + "camouflauge", "camouflage", + "campagining", "campaigning", + "campainging", "campaigning", + "canadianese", "canadians", + "cannabilism", "cannibalism", + "cannabolism", "cannibalism", + "canniablism", "cannibalism", + "cannibalizm", "cannibalism", + "cannibaljim", "cannibalism", + "cannibalsim", "cannibalism", + "cannibilism", "cannibalism", + "cannobalism", "cannibalism", + "cannotation", "connotation", + "capabilites", "capabilities", + "capabilitiy", "capability", + "capabillity", "capability", + "capacitaron", "capacitor", + "capacitores", "capacitors", + "capatilists", "capitalists", + "capatilized", "capitalized", + "caperbility", "capability", + "capitalisim", "capitalism", + "capitilists", "capitalists", + "capitilized", "capitalized", + "capitolists", "capitalists", + "capitolized", "capitalized", + "captialists", "capitalists", + "captialized", "capitalized", + "cariactures", "caricature", + "carniverous", "carnivorous", + "castatrophe", "catastrophe", + "catagorized", "categorized", + "catapillars", "caterpillars", + "catapillers", "caterpillars", + "catasthrope", "catastrophe", + "catastraphe", "catastrophe", + "catastrohpe", "catastrophe", + "catastropic", "catastrophic", + "categroized", "categorized", + "catepillars", "caterpillars", + "catergorize", "categorize", + "caterogized", "categorized", + "caterpilars", "caterpillars", + "caterpiller", "caterpillar", + "catholacism", "catholicism", + "catholicsim", "catholicism", + "catholisicm", "catholicism", + "catholisism", "catholicism", + "catholizism", "catholicism", + "catholocism", "catholicism", + "catogerized", "categorized", + "catterpilar", "caterpillar", + "cauilflower", "cauliflower", + "caulfilower", "cauliflower", + "celebartion", "celebrations", + "celebirties", "celebrities", + "celebracion", "celebration", + "celebrasion", "celebrations", + "celebratons", "celebrations", + "centipeddle", "centipede", + "cerimonious", "ceremonious", + "certaintity", "certainty", + "certificaat", "certificate", + "certificare", "certificate", + "certificato", "certification", + "certificats", "certificates", + "challanging", "challenging", + "challeneged", "challenged", + "challeneger", "challenger", + "challeneges", "challenges", + "chameleooon", "chameleon", + "championshp", "championship", + "championsip", "championship", + "chancellour", "chancellor", + "charachters", "characters", + "charasmatic", "charismatic", + "charimastic", "charismatic", + "charsimatic", "charismatic", + "cheerleadra", "cheerleader", + "cheerleards", "cheerleaders", + "cheerleeder", "cheerleader", + "cheesebuger", "cheeseburger", + "cheeseburgs", "cheeseburgers", + "chihuahuita", "chihuahua", + "childrenmrs", "childrens", + "chloesterol", "cholesterol", + "cholesteral", "cholesterol", + "cholestoral", "cholesterol", + "cholestorol", "cholesterol", + "cholosterol", "cholesterol", + "chormosomes", "chromosomes", + "christianty", "christianity", + "chromasomes", "chromosomes", + "chromesomes", "chromosomes", + "chromisomes", "chromosomes", + "chromosones", "chromosomes", + "chromossome", "chromosomes", + "chromozomes", "chromosomes", + "chronicales", "chronicles", + "chronichles", "chronicles", + "cicrulating", "circulating", + "cincinnasti", "cincinnati", + "cincinnatti", "cincinnati", + "cincinnnati", "cincinnati", + "circimcised", "circumcised", + "circluating", "circulating", + "circualtion", "circulation", + "circulacion", "circulation", + "circumcison", "circumcision", + "circumsiced", "circumcised", + "circumsised", "circumcised", + "circumstace", "circumstance", + "circumvrent", "circumvent", + "circuncised", "circumcised", + "cirticising", "criticising", + "ciruclating", "circulating", + "ciruclation", "circulation", + "citicenship", "citizenship", + "citisenship", "citizenship", + "citizinship", "citizenship", + "civilizatin", "civilizations", + "civilizaton", "civilization", + "claculators", "calculators", + "classifides", "classified", + "cleanilness", "cleanliness", + "cleanleness", "cleanliness", + "cleanlyness", "cleanliness", + "cleansiness", "cleanliness", + "cliffbanger", "cliffhanger", + "cliffhander", "cliffhanger", + "cliffhangar", "cliffhanger", + "clifthanger", "cliffhanger", + "cockaroches", "cockroaches", + "cockraoches", "cockroaches", + "cockroackes", "cockroaches", + "cocktailers", "cocktails", + "coefficeint", "coefficient", + "coefficiant", "coefficient", + "coincedince", "coincidence", + "coincidance", "coincidence", + "coincidense", "coincidence", + "coincidente", "coincidence", + "coincidince", "coincidence", + "coinsidence", "coincidence", + "collabarate", "collaborate", + "collaberate", "collaborate", + "collaborant", "collaborate", + "collaborare", "collaborate", + "collaborato", "collaboration", + "collapseing", "collapsing", + "collaterial", "collateral", + "collectieve", "collective", + "collectivly", "collectively", + "collectivos", "collections", + "collobarate", "collaborate", + "colloborate", "collaborate", + "colonializm", "colonialism", + "colonialsim", "colonialism", + "colonianism", "colonialism", + "colonizaton", "colonization", + "comaprisons", "comparisons", + "combiantion", "combinations", + "combinacion", "combination", + "combinaison", "combinations", + "combinaiton", "combinations", + "combinatino", "combinations", + "combinatins", "combinations", + "combinatios", "combinations", + "combinining", "combining", + "combonation", "combination", + "comediantes", "comedians", + "comeptition", "competition", + "comeptitive", "competitive", + "comeptitors", "competitors", + "comfertable", "comfortable", + "comfertably", "comfortably", + "comfortabel", "comfortably", + "comfortabil", "comfortably", + "comfrotable", "comfortable", + "comftorable", "comfortable", + "comftorably", "comfortably", + "comisioning", "commissioning", + "comissioned", "commissioned", + "comissioner", "commissioner", + "commandered", "commanded", + "commandmant", "commandment", + "commantator", "commentator", + "commendment", "commandment", + "commentarea", "commenter", + "commentaren", "commenter", + "commentater", "commentator", + "commenteers", "commenter", + "commentries", "commenters", + "commercialy", "commercially", + "commericals", "commercials", + "commericial", "commercial", + "comminicate", "communicate", + "comminucate", "communicate", + "commisioned", "commissioned", + "commisioner", "commissioner", + "commisssion", "commissions", + "committment", "commitment", + "commodoties", "commodities", + "commomplace", "commonplace", + "commonspace", "commonplace", + "commonweath", "commonwealth", + "commonwelth", "commonwealth", + "commuincate", "communicated", + "communciate", "communicate", + "communicted", "communicated", + "communistas", "communists", + "communistes", "communists", + "compability", "compatibility", + "compalation", "compilation", + "compansated", "compensated", + "comparabile", "comparable", + "comparasion", "comparison", + "comparasons", "comparisons", + "comparement", "compartment", + "comparetive", "comparative", + "comparision", "comparison", + "comparisson", "comparisons", + "comparitave", "comparative", + "comparitive", "comparative", + "comparsions", "comparisons", + "compassione", "compassionate", + "compasssion", "compassion", + "compatabile", "compatible", + "compatative", "comparative", + "compatiable", "compatible", + "compatibile", "compatible", + "compatibily", "compatibility", + "compeditive", "competitive", + "compeditors", "competitors", + "compeitions", "competitions", + "compeittion", "competitions", + "compelation", "compilation", + "compensante", "compensate", + "compensatie", "compensate", + "compensatin", "compensation", + "compenstate", "compensate", + "comperative", "comparative", + "compesition", "composition", + "competation", "computation", + "competative", "competitive", + "competators", "competitors", + "competetion", "competition", + "competetors", "competitors", + "competiters", "competitors", + "competiting", "competition", + "competitior", "competitor", + "competitivo", "competition", + "competitoin", "competitions", + "competitons", "competitors", + "competution", "computation", + "compilacion", "compilation", + "compilcated", "complicate", + "compination", "compilation", + "compinsated", "compensated", + "compitation", "computation", + "compitetion", "competitions", + "complacient", "complacent", + "complciated", "complicate", + "compleation", "compilation", + "complecated", "complicated", + "completaste", "completes", + "completeing", "completing", + "completeion", "completion", + "completelly", "completely", + "completelyl", "completely", + "completelys", "completes", + "completenes", "completes", + "complexitiy", "complexity", + "compliacted", "complicate", + "compliation", "compilation", + "complicarte", "complicate", + "complicatie", "complicit", + "complicatii", "complicit", + "complicatin", "complicit", + "complictaed", "complicate", + "complimente", "complement", + "complimenty", "complimentary", + "complusions", "compulsion", + "compolation", "compilation", + "componenets", "components", + "componentes", "components", + "composicion", "composition", + "composiiton", "compositions", + "composision", "compositions", + "compositied", "composite", + "composities", "composite", + "compositoin", "compositions", + "compositons", "compositions", + "compositore", "composite", + "compostiion", "compositions", + "compotition", "composition", + "compramised", "compromised", + "compramises", "compromises", + "compremised", "compromised", + "compremises", "compromises", + "comprension", "compression", + "compresores", "compressor", + "compresssed", "compressed", + "compresssor", "compressor", + "comprimised", "compromised", + "comprimises", "compromises", + "compromessi", "compromises", + "compromisng", "compromising", + "compromisse", "compromises", + "compromisso", "compromises", + "compromized", "compromised", + "compulstion", "compulsion", + "compunation", "computation", + "computacion", "computation", + "computating", "computation", + "computition", "computation", + "conceivibly", "conceivably", + "concencrate", "concentrate", + "concentrace", "concentrate", + "concentrade", "concentrated", + "concentrait", "concentrate", + "concentrant", "concentrate", + "concentrare", "concentrate", + "concentrato", "concentration", + "concertmate", "concentrate", + "conceviable", "conceivable", + "conceviably", "conceivably", + "concidering", "considering", + "conciveable", "conceivable", + "conciveably", "conceivably", + "conclsuions", "concussions", + "concludendo", "concluded", + "conclussion", "conclusions", + "conclussive", "conclusive", + "conclutions", "conclusions", + "concsiously", "consciously", + "conculsions", "conclusions", + "concusssion", "concussions", + "condeferacy", "confederacy", + "condicional", "conditional", + "condidtions", "conditions", + "conditionar", "conditioner", + "conditionel", "conditional", + "condolances", "condolences", + "condolenses", "condolences", + "condolonces", "condolences", + "conductiong", "conducting", + "condulences", "condolences", + "conenctions", "connections", + "conescutive", "consecutive", + "confedaracy", "confederacy", + "confedarate", "confederate", + "confederecy", "confederacy", + "conferances", "conferences", + "conferedate", "confederate", + "confererate", "confederate", + "confescated", "confiscated", + "confesssion", "confessions", + "confidantly", "confidently", + "configurare", "configure", + "configurate", "configure", + "configurato", "configuration", + "confilcting", "conflicting", + "confisgated", "confiscated", + "conflciting", "conflicting", + "confortable", "comfortable", + "confrontato", "confrontation", + "confussions", "confessions", + "congrassman", "congressman", + "congratuate", "congratulate", + "conicidence", "coincidence", + "conjonction", "conjunction", + "conjucntion", "conjunction", + "conjuncting", "conjunction", + "conlcusions", "conclusions", + "connatation", "connotation", + "connecitcut", "connecticut", + "connecticon", "connection", + "connectiong", "connecting", + "connectivty", "connectivity", + "connetation", "connotation", + "connonation", "connotation", + "connotacion", "connotation", + "conontation", "connotation", + "conotations", "connotations", + "conquerring", "conquering", + "consdidered", "considered", + "consectuive", "consecutive", + "consecuence", "consequence", + "conseguence", "consequence", + "conselation", "consolation", + "consentrate", "concentrate", + "consequenes", "consequence", + "consequense", "consequences", + "consequente", "consequence", + "consequenty", "consequently", + "consequtive", "consecutive", + "conservanti", "conservation", + "conservatie", "conservatives", + "conservaton", "conservation", + "consficated", "confiscated", + "considerabe", "considerate", + "considerais", "considers", + "considerant", "considerate", + "considerato", "consideration", + "considerble", "considerable", + "considerbly", "considerably", + "considereis", "considers", + "consilation", "consolation", + "consilidate", "consolidate", + "consistance", "consistency", + "consistenly", "consistently", + "consistensy", "consistency", + "consistenty", "consistently", + "consitution", "constitution", + "conslutants", "consultant", + "consolacion", "consolation", + "consoldiate", "consolidate", + "consolidare", "consolidate", + "consolodate", "consolidate", + "consomation", "consolation", + "conspiraces", "conspiracies", + "conspiracys", "conspiracies", + "conspirancy", "conspiracy", + "constantins", "constants", + "constantivs", "constants", + "constarints", "constraint", + "constituant", "constituent", + "constituion", "constitution", + "constituite", "constitute", + "constitutie", "constitutes", + "constrating", "constraint", + "constriants", "constraints", + "construcing", "constructing", + "construcion", "construction", + "construcive", "constructive", + "constructie", "constructive", + "constructos", "constructs", + "constructur", "constructor", + "constructus", "constructs", + "constuction", "construction", + "consturcted", "constructed", + "consuelling", "counselling", + "consulation", "consolation", + "consultaion", "consultation", + "consultanti", "consultation", + "consumation", "consumption", + "consumbales", "consumables", + "consumersim", "consumerism", + "consumibles", "consumables", + "contagiosum", "contagious", + "containered", "contained", + "containmemt", "containment", + "containters", "containers", + "containting", "containing", + "contaminato", "contamination", + "contaminent", "containment", + "contaminted", "contaminated", + "contancting", "contracting", + "contanimate", "contaminated", + "contemplare", "contemplate", + "contempoary", "contemporary", + "contemporay", "contemporary", + "contencious", "contentious", + "contenental", "continental", + "contengency", "contingency", + "contenintal", "continental", + "contenplate", "contemplate", + "contensious", "contentious", + "contentants", "contestants", + "contentuous", "contentious", + "contestaste", "contestants", + "contestents", "contestants", + "contianment", "containment", + "contientous", "contentious", + "contimplate", "contemplate", + "continenets", "continents", + "continentes", "continents", + "continentul", "continental", + "contingancy", "contingency", + "contingient", "contingent", + "contingincy", "contingency", + "continously", "continuously", + "continuarla", "continual", + "continuarlo", "continual", + "continuasse", "continues", + "continueing", "continuing", + "continuemos", "continues", + "continueous", "continuous", + "continuious", "continuous", + "continuning", "continuing", + "continunity", "continuity", + "continuosly", "continuously", + "continuting", "continuing", + "continutity", "continuity", + "continuuing", "continuing", + "continuuity", "continuity", + "contirbuted", "contributed", + "contiunally", "continually", + "contraccion", "contraction", + "contraddice", "contradicted", + "contradices", "contradicts", + "contradtion", "contraction", + "contraversy", "controversy", + "contreversy", "controversy", + "contribuent", "contribute", + "contribuito", "contribution", + "contributer", "contributor", + "contributie", "contribute", + "contributin", "contribution", + "contributos", "contributors", + "contribuyes", "contributes", + "contricting", "contracting", + "contriction", "contraction", + "contridicts", "contradicts", + "contriversy", "controversy", + "controleurs", "controllers", + "controllore", "controllers", + "controvercy", "controversy", + "controversa", "controversial", + "contrubutes", "contributes", + "contructing", "contracting", + "contruction", "construction", + "contructors", "contractors", + "conveinence", "convenience", + "conveneince", "convenience", + "conveniance", "convenience", + "conveniente", "convenience", + "convenietly", "conveniently", + "conventinal", "conventional", + "converitble", "convertible", + "conversaion", "conversion", + "conversatin", "conversations", + "converseley", "conversely", + "converstion", "conversion", + "convertirea", "converter", + "convertirle", "convertible", + "convertirme", "converter", + "convertirte", "converter", + "convicitons", "convictions", + "convienence", "convenience", + "convienient", "convenient", + "convinceing", "convincing", + "convincente", "convenient", + "convincersi", "convinces", + "convirtible", "convertible", + "cooperacion", "cooperation", + "cooperativo", "cooperation", + "cooporation", "cooperation", + "cooporative", "cooperative", + "coordenated", "coordinated", + "coordenates", "coordinates", + "coordianted", "coordinated", + "coordiantes", "coordinates", + "coordiantor", "coordinator", + "coordinador", "coordinator", + "coordinants", "coordinates", + "coordinater", "coordinator", + "coordinaton", "coordination", + "coordonated", "coordinated", + "coordonates", "coordinates", + "coordonator", "coordinator", + "cooridnated", "coordinated", + "cooridnates", "coordinates", + "cooridnator", "coordinator", + "copenhaagen", "copenhagen", + "copenhaegen", "copenhagen", + "copenhaguen", "copenhagen", + "copenhangen", "copenhagen", + "copmetitors", "competitors", + "coproration", "corporation", + "copyrigthed", "copyrighted", + "corinthains", "corinthians", + "corintheans", "corinthians", + "corinthiens", "corinthians", + "corinthinas", "corinthians", + "cornithians", "corinthians", + "corparation", "corporation", + "corperation", "corporation", + "corporacion", "corporation", + "corporativo", "corporation", + "corralation", "correlation", + "correctings", "corrections", + "correctivos", "corrections", + "correktions", "corrections", + "correktness", "correctness", + "correlacion", "correlation", + "correlaties", "correlates", + "corrilation", "correlation", + "corrisponds", "corresponds", + "corrolation", "correlation", + "corrosponds", "corresponds", + "costitution", "constitution", + "councellors", "councillors", + "counrtyside", "countryside", + "counsilling", "counselling", + "countercoat", "counteract", + "counteredit", "counterfeit", + "counterfact", "counteract", + "counterfait", "counterfeit", + "counterfest", "counterfeit", + "counterfiet", "counterfeit", + "counterpaly", "counterplay", + "counterpary", "counterplay", + "counterpath", "counterpart", + "counterpats", "counterparts", + "counterpont", "counterpoint", + "counterract", "counterpart", + "counterside", "countryside", + "countertrap", "counterpart", + "countriside", "countryside", + "countrycide", "countryside", + "countrywise", "countryside", + "courthourse", "courthouse", + "coutnerfeit", "counterfeit", + "coutnerpart", "counterpart", + "coutnerplay", "counterplay", + "creacionism", "creationism", + "creationkit", "creationist", + "creationsim", "creationism", + "creationsit", "creationist", + "creationsts", "creationists", + "creativelly", "creatively", + "credencials", "credentials", + "credentails", "credentials", + "credentaisl", "credentials", + "credientals", "credentials", + "credintials", "credentials", + "cricitising", "criticising", + "criculating", "circulating", + "cringeworhy", "cringeworthy", + "cringeworty", "cringeworthy", + "cringewothy", "cringeworthy", + "criticicing", "criticising", + "criticisied", "criticise", + "criticisims", "criticisms", + "criticisize", "criticise", + "criticiszed", "criticise", + "critisicing", "criticizing", + "critisising", "criticising", + "critizicing", "criticizing", + "critizising", "criticizing", + "critizizing", "criticizing", + "crockodiles", "crocodiles", + "crocodiller", "crocodile", + "crocodilule", "crocodile", + "croporation", "corporation", + "crossfiters", "crossfire", + "cultivative", "cultivate", + "curricullum", "curriculum", + "customizabe", "customizable", + "customizble", "customizable", + "dangeroulsy", "dangerously", + "dardenelles", "dardanelles", + "deadlifters", "deadlifts", + "dealershits", "dealerships", + "deceptivley", "deceptive", + "declaracion", "declaration", + "decleration", "declaration", + "declinining", "declining", + "decloration", "declaration", + "decoartions", "decoration", + "decomposits", "decomposes", + "decoratieve", "decorative", + "decorativos", "decorations", + "decotations", "decorations", + "decsendants", "descendants", + "deductiable", "deductible", + "defenderlas", "defenders", + "defenderlos", "defenders", + "defendernos", "defenders", + "defenesless", "defenseless", + "defenisvely", "defensively", + "defensivley", "defensively", + "deficiencey", "deficiency", + "deficienies", "deficiencies", + "deficientcy", "deficiency", + "definantley", "definately", + "definatedly", "definately", + "definateley", "definately", + "definatelly", "definately", + "definatelty", "definately", + "definatetly", "definately", + "definations", "definitions", + "definatlely", "definately", + "definetally", "definately", + "definetlely", "definetly", + "definitaley", "definately", + "definitelly", "definitely", + "definitevly", "definitively", + "definitiely", "definitively", + "definitieve", "definitive", + "definitiley", "definitively", + "definitivly", "definitively", + "definitivno", "definition", + "definitivos", "definitions", + "definitlely", "definitly", + "definitlety", "definitly", + "deflecticon", "deflection", + "degenererat", "degenerate", + "degradacion", "degradation", + "degradating", "degradation", + "degragation", "degradation", + "degridation", "degradation", + "dehyrdation", "dehydration", + "deinitalize", "deinitialize", + "delaerships", "dealerships", + "delapidated", "dilapidated", + "delcaration", "declaration", + "delearships", "dealerships", + "delevopment", "development", + "deliberante", "deliberate", + "deliberatly", "deliberately", + "deliberetly", "deliberately", + "delightlful", "delightful", + "deliverying", "delivering", + "delusionnal", "delusional", + "deminsional", "dimensional", + "democarcies", "democracies", + "democracize", "democracies", + "democractic", "democratic", + "democraphic", "demographic", + "democrasies", "democracies", + "democrazies", "democracies", + "democrocies", "democracies", + "demograhpic", "demographic", + "demographis", "demographics", + "demograpics", "demographics", + "demogrpahic", "demographic", + "demoninator", "denominator", + "demonstarte", "demonstrate", + "demonstates", "demonstrates", + "demonstraby", "demonstrably", + "demonstrant", "demonstrate", + "demonstrats", "demonstrates", + "demosntrate", "demonstrate", + "denegrating", "denigrating", + "denomenator", "denominator", + "denominador", "denominator", + "denominaron", "denominator", + "denominater", "denominator", + "denominaton", "denomination", + "denomitator", "denominator", + "denomonator", "denominator", + "denonimator", "denominator", + "deocrations", "decorations", + "deomcracies", "democracies", + "deparmental", "departmental", + "depedencies", "dependencies", + "dependancey", "dependency", + "dependencey", "dependency", + "dependencie", "dependence", + "dependenies", "dependencies", + "deplorabile", "deplorable", + "depressieve", "depressive", + "depresssion", "depression", + "deprevation", "deprivation", + "deprication", "deprivation", + "deprivating", "deprivation", + "deprivition", "deprivation", + "deprovation", "deprivation", + "depserately", "desperately", + "depseration", "desperation", + "deregulatin", "deregulation", + "derivativos", "derivatives", + "derivitaves", "derivatives", + "derivitives", "derivatives", + "derpivation", "deprivation", + "derviatives", "derivatives", + "descandants", "descendants", + "descendands", "descendants", + "descendends", "descended", + "descendenta", "descendants", + "descentants", "descendants", + "descirption", "descriptions", + "descprition", "descriptions", + "describiste", "describes", + "describtion", "description", + "descripcion", "description", + "descripiton", "descriptions", + "descripters", "descriptors", + "descriptoin", "descriptions", + "descriptons", "descriptions", + "descritpion", "descriptions", + "descrpition", "descriptions", + "desensitied", "desensitized", + "desensitzed", "desensitized", + "desentisize", "desensitized", + "desgination", "designation", + "designacion", "designation", + "designstion", "designation", + "desinations", "destinations", + "desingation", "designation", + "desitnation", "destination", + "desoriented", "disoriented", + "desparately", "desperately", + "desparation", "desperation", + "desperating", "desperation", + "desperatley", "desperately", + "despirately", "desperately", + "despiration", "desperation", + "destablized", "destabilized", + "destiantion", "destinations", + "destinaiton", "destinations", + "destinatons", "destinations", + "destinction", "destination", + "destraction", "destruction", + "destruccion", "destruction", + "destruciton", "destruction", + "destructivo", "destruction", + "destruktion", "destruction", + "destruktive", "destructive", + "deteoriated", "deteriorated", + "determanism", "determinism", + "determening", "determining", + "determenism", "determinism", + "determinare", "determine", + "determinato", "determination", + "determinded", "determine", + "determinsim", "determinism", + "detramental", "detrimental", + "detremental", "detrimental", + "detrimentul", "detrimental", + "detuschland", "deutschland", + "deustchland", "deutschland", + "deutchsland", "deutschland", + "deutcshland", "deutschland", + "deutschalnd", "deutschland", + "deutshcland", "deutschland", + "develepmont", "developments", + "develompent", "developments", + "developemnt", "developments", + "developmant", "developmental", + "developmetn", "developments", + "developmnet", "developments", + "developpers", "developers", + "develpoment", "developments", + "deveolpment", "developments", + "deveploment", "developments", + "devestating", "devastating", + "devistating", "devastating", + "deyhdration", "dehydration", + "diagnositcs", "diagnostic", + "diagnositic", "diagnostic", + "diagonstics", "diagnostic", + "dictatorhip", "dictatorship", + "dictionaire", "dictionaries", + "dictionairy", "dictionary", + "dictionarys", "dictionaries", + "dictionnary", "dictionary", + "differances", "differences", + "differantly", "differently", + "differental", "differential", + "differentes", "differences", + "differneces", "differences", + "differnetly", "differently", + "difficulity", "difficulty", + "difficultes", "difficulties", + "dificulties", "difficulties", + "dimensiones", "dimensions", + "dimentional", "dimensional", + "dimesnional", "dimensional", + "diminisheds", "diminishes", + "diminsihing", "diminishing", + "diminuitive", "diminutive", + "diminushing", "diminishing", + "dinosaurios", "dinosaurs", + "direccional", "directional", + "direcitonal", "directional", + "directorguy", "directory", + "directorios", "directors", + "direktional", "directional", + "disadvantge", "disadvantage", + "disagreemet", "disagreements", + "disagreemtn", "disagreements", + "disapperead", "disappeared", + "disapporval", "disapproval", + "disapprovel", "disapproval", + "disasterous", "disastrous", + "disastreous", "disastrous", + "disastrious", "disastrous", + "disastruous", "disastrous", + "disatisfied", "dissatisfied", + "disciplened", "disciplined", + "disciplinas", "disciplines", + "disciplince", "disciplines", + "disclipined", "disciplined", + "disclipines", "disciplines", + "discogrophy", "discography", + "discogrpahy", "discography", + "disconencts", "disconnects", + "disconneted", "disconnected", + "disconnnect", "disconnect", + "discontined", "discontinued", + "discontiued", "discontinued", + "discrapency", "discrepancy", + "discretited", "discredited", + "discrimante", "discriminate", + "discrimiate", "discriminate", + "discussiong", "discussing", + "discusssion", "discussions", + "disgraseful", "disgraceful", + "disgrateful", "disgraceful", + "disgrunteld", "disgruntled", + "disgustigly", "disgustingly", + "disgustingy", "disgustingly", + "disgustinly", "disgustingly", + "disicplined", "disciplined", + "disicplines", "disciplines", + "disingenuos", "disingenuous", + "dismanlting", "dismantling", + "dismantaled", "dismantled", + "dismanteled", "dismantled", + "disobediant", "disobedient", + "disocgraphy", "discography", + "disparingly", "disparagingly", + "dispensaire", "dispensaries", + "dispensarie", "dispenser", + "dispensiary", "dispensary", + "displacemnt", "displacement", + "disposicion", "disposition", + "disputandem", "disputandum", + "disqualifed", "disqualified", + "disregaring", "disregarding", + "dissapeared", "disappeared", + "dissapoined", "dissapointed", + "dissapointd", "dissapointed", + "dissapoited", "dissapointed", + "dissappears", "disappears", + "dissatisfed", "dissatisfied", + "disscusions", "discussions", + "dissertaion", "dissertation", + "dissipatore", "dissipate", + "distatesful", "distasteful", + "distatseful", "distasteful", + "disterbance", "disturbance", + "disticntion", "distinctions", + "distinciton", "distinction", + "distincitve", "distinctive", + "distinctily", "distinctly", + "distingiush", "distinguish", + "distinguise", "distinguished", + "distinktion", "distinction", + "distinquish", "distinguish", + "distirbance", "disturbance", + "distirbuted", "distribute", + "distirbutor", "distributor", + "distraccion", "distraction", + "distractons", "distracts", + "distraktion", "distraction", + "distribitor", "distributor", + "distribuent", "distribute", + "distribuite", "distribute", + "distribuito", "distribution", + "distributie", "distributed", + "distributin", "distribution", + "distributio", "distributor", + "distrobuted", "distributed", + "distrubance", "disturbance", + "distrubited", "distributed", + "distrubitor", "distributor", + "distrubuted", "distributed", + "distrubutor", "distributor", + "distructive", "destructive", + "distuingish", "distinguish", + "distunguish", "distinguish", + "disturbante", "disturbance", + "disturbence", "disturbance", + "disucssions", "discussions", + "divisionals", "divisions", + "doccumented", "documented", + "documantary", "documentary", + "documenatry", "documentary", + "documentare", "documentaries", + "documentato", "documentation", + "documentery", "documentary", + "documentory", "documentary", + "domesticted", "domesticated", + "dominateurs", "dominates", + "dominationg", "dominating", + "donwloading", "downloading", + "doublellift", "doublelift", + "downlaoding", "downloading", + "downloadbel", "downloadable", + "downloadbig", "downloading", + "downloadble", "downloadable", + "downvoteers", "downvoters", + "downvoteing", "downvoting", + "downvoteres", "downvoters", + "downvoteros", "downvoters", + "downvoteurs", "downvoters", + "downvotters", "downvoters", + "downvotting", "downvoting", + "dramaticaly", "dramatically", + "dramaticlly", "dramatically", + "drasitcally", "drastically", + "dsyfunction", "dysfunction", + "duetschland", "deutschland", + "durabillity", "durability", + "dyanmically", "dynamically", + "dymanically", "dynamically", + "dysfonction", "dysfunction", + "dysfucntion", "dysfunction", + "dysfunciton", "dysfunction", + "dysfunktion", "dysfunction", + "earhtquakes", "earthquakes", + "earthqaukes", "earthquakes", + "earthquacks", "earthquakes", + "economicaly", "economically", + "economiclly", "economically", + "economisiti", "economist", + "economistes", "economists", + "educacional", "educational", + "effeciently", "efficiently", + "effecitvely", "effectively", + "effectivley", "effectively", + "efficeintly", "efficiently", + "efficiantly", "efficiently", + "efficientcy", "efficiently", + "effortlesly", "effortlessly", + "effortlessy", "effortlessly", + "egaletarian", "egalitarian", + "egalitatian", "egalitarian", + "egaliterian", "egalitarian", + "egostitical", "egotistical", + "egotastical", "egotistical", + "egotestical", "egotistical", + "egotisitcal", "egotistical", + "egotisticle", "egotistical", + "egotystical", "egotistical", + "ehtnicities", "ethnicities", + "ejacluation", "ejaculation", + "ejacualtion", "ejaculation", + "electoratul", "electoral", + "electornics", "electronics", + "electricain", "electrician", + "electricial", "electrical", + "electricien", "electrician", + "electricion", "electrician", + "electricman", "electrician", + "electrisity", "electricity", + "electritian", "electrician", + "electrocity", "electricity", + "electrolyes", "electrolytes", + "electrolyts", "electrolytes", + "electroncis", "electrons", + "electroylte", "electrolytes", + "elementrary", "elementary", + "eleminating", "eliminating", + "elimanation", "elimination", + "eliminacion", "elimination", + "elimintates", "eliminates", + "ellipitcals", "elliptical", + "eloquentely", "eloquently", + "emabrassing", "embarassing", + "embaraasing", "embarassing", + "embarasaing", "embarassing", + "embarassign", "embarassing", + "embarassimg", "embarassing", + "embarassing", "embarrassing", + "embarissing", "embarassing", + "embarrasing", "embarrassing", + "embarressed", "embarrassed", + "embarrssing", "embarassing", + "emergancies", "emergencies", + "emergencias", "emergencies", + "emergenices", "emergencies", + "emmediately", "immediately", + "emmisarries", "emissaries", + "emotionella", "emotionally", + "empahsizing", "emphasizing", + "empathethic", "empathetic", + "emphacizing", "emphasizing", + "emphatising", "emphasizing", + "emphatizing", "emphasizing", + "emphazising", "emphasizing", + "emphesizing", "emphasizing", + "empiracally", "empirically", + "empirialism", "imperialism", + "empirialist", "imperialist", + "enchamtment", "enchantment", + "enchancment", "enchantment", + "enchanement", "enchantment", + "enchanthing", "enchanting", + "enchantmant", "enchantment", + "enchantmens", "enchantments", + "enchantmets", "enchantments", + "encomapsses", "encompasses", + "encompasess", "encompasses", + "encompesses", "encompasses", + "encounteres", "encounters", + "encoutnered", "encountered", + "encryptiion", "encryption", + "encyclopdia", "encyclopedia", + "encylopedia", "encyclopedia", + "endagnering", "endangering", + "endandering", "endangering", + "endorcement", "endorsement", + "endoresment", "endorsement", + "engagaments", "engagements", + "engeneering", "engineering", + "enginerring", "engineering", + "enginnering", "engineering", + "enlargments", "enlargements", + "enligthened", "enlightened", + "enourmously", "enormously", + "enterpirses", "enterprises", + "enterprices", "enterprises", + "enterprishe", "enterprises", + "entertainig", "entertaining", + "entertwined", "entertained", + "enthicities", "ethnicities", + "enthisiasts", "enthusiasts", + "enthuasists", "enthusiasts", + "enthuisasts", "enthusiasts", + "enthusaists", "enthusiasts", + "enthusiants", "enthusiast", + "enthusiasic", "enthusiastic", + "enthusiasim", "enthusiasm", + "enthusiasum", "enthusiasm", + "enthusiatic", "enthusiastic", + "enthusiests", "enthusiasts", + "enthusigasm", "enthusiasm", + "enthusisast", "enthusiasts", + "entrepeneur", "entrepreneur", + "entreperure", "entrepreneur", + "entrepeuner", "entrepreneur", + "entreprener", "entrepreneurs", + "entreprenur", "entrepreneur", + "entretained", "entertained", + "envinroment", "environments", + "enviorments", "environments", + "enviornment", "environment", + "envirnoment", "environment", + "enviroments", "environments", + "enviromnent", "environments", + "environemnt", "environment", + "environmnet", "environments", + "envrionment", "environment", + "equilavents", "equivalents", + "equilbirium", "equilibrium", + "equilevants", "equivalents", + "equilibirum", "equilibrium", + "equilibriam", "equilibrium", + "equilibruim", "equilibrium", + "equivalance", "equivalence", + "equivalants", "equivalents", + "equivalenet", "equivalents", + "equivallent", "equivalent", + "equivelance", "equivalence", + "equivelants", "equivalents", + "equivelents", "equivalents", + "equivilants", "equivalents", + "equivilence", "equivalence", + "equivilents", "equivalents", + "equivlalent", "equivalent", + "equivlanets", "equivalents", + "equivolence", "equivalence", + "equivolents", "equivalents", + "essencially", "essentially", + "essentailly", "essentially", + "essentialls", "essentials", + "essentually", "essentially", + "establising", "establishing", + "ethicallity", "ethically", + "ethincities", "ethnicities", + "ethniticies", "ethnicities", + "europeaners", "europeans", + "europeaness", "europeans", + "evaluatiing", "evaluating", + "evaluationg", "evaluating", + "evangalical", "evangelical", + "evangelikal", "evangelical", + "evengalical", "evangelical", + "evenhtually", "eventually", + "everyonehas", "everyones", + "everyonelse", "everyones", + "evidentally", "evidently", + "exacarbated", "exacerbated", + "exacberated", "exacerbated", + "exagerating", "exaggerating", + "exagerrated", "exaggerated", + "exagerrates", "exaggerates", + "exaggarated", "exaggerated", + "exaggareted", "exaggerate", + "exaggeratin", "exaggeration", + "exaggerrate", "exaggerate", + "exaggurated", "exaggerated", + "exarcebated", "exacerbated", + "excalmation", "exclamation", + "excepcional", "exceptional", + "exceptionel", "exceptional", + "excessivley", "excessively", + "exceutioner", "executioner", + "exchanching", "exchanging", + "exclamacion", "exclamation", + "exclamating", "exclamation", + "exclamativo", "exclamation", + "exclemation", "exclamation", + "exclimation", "exclamation", + "exclucivity", "exclusivity", + "exclusivety", "exclusivity", + "exclusivily", "exclusivity", + "exclusivley", "exclusively", + "excpetional", "exceptional", + "exculsively", "exclusively", + "exculsivity", "exclusivity", + "execitioner", "executioner", + "execptional", "exceptional", + "exectuables", "executable", + "exectuioner", "executioner", + "executionar", "executioner", + "executionor", "executioner", + "exerciseing", "exercising", + "exeuctioner", "executioner", + "existantial", "existential", + "existencial", "existential", + "existensial", "existential", + "existentiel", "existential", + "exlcamation", "exclamation", + "exlcusively", "exclusively", + "exlcusivity", "exclusivity", + "exoskelaton", "exoskeleton", + "expansiones", "expansions", + "expectantcy", "expectancy", + "expectating", "expectation", + "expectional", "exceptional", + "expendature", "expenditure", + "expendeture", "expenditure", + "expentiture", "expenditure", + "expereinced", "experienced", + "expereinces", "experiences", + "experements", "experiments", + "experianced", "experienced", + "experiances", "experiences", + "experiemnts", "experiments", + "experiening", "experiencing", + "experimetal", "experimental", + "experimeted", "experimented", + "experssions", "expressions", + "expiditions", "expeditions", + "expierenced", "experienced", + "expierences", "experiences", + "expirements", "experiments", + "explainging", "explaining", + "explaintory", "explanatory", + "explanaiton", "explanations", + "explanetary", "explanatory", + "explanetory", "explanatory", + "explanitary", "explanatory", + "explanotory", "explanatory", + "explenation", "explanation", + "explenatory", "explanatory", + "explicitely", "explicitly", + "explicitily", "explicitly", + "explination", "explanation", + "explinatory", "explanatory", + "exploitaion", "exploitation", + "exploitatie", "exploitative", + "explonation", "exploration", + "exploracion", "exploration", + "explorating", "exploration", + "explorerers", "explorers", + "explosiones", "explosions", + "explotacion", "exploration", + "expodential", "exponential", + "exponantial", "exponential", + "exponencial", "exponential", + "exponentiel", "exponential", + "expresscoin", "expression", + "expressivos", "expressions", + "expresssive", "expressive", + "expressview", "expressive", + "exprimental", "experimental", + "expropiated", "expropriated", + "extensiones", "extensions", + "extensivley", "extensively", + "extragavant", "extravagant", + "extrapalate", "extrapolate", + "extraploate", "extrapolate", + "extrapolant", "extrapolate", + "extrapolare", "extrapolate", + "extrapolite", "extrapolate", + "extrapulate", "extrapolate", + "extravagent", "extravagant", + "extravagina", "extravagant", + "extravegant", "extravagant", + "extravigant", "extravagant", + "extravogant", "extravagant", + "extremistas", "extremists", + "extremistes", "extremists", + "extropolate", "extrapolate", + "fabircation", "fabrication", + "fabricacion", "fabrication", + "fabrikation", "fabrication", + "facilitarte", "facilitate", + "facilitiate", "facilitate", + "facillitate", "facilitate", + "facisnation", "fascination", + "facsination", "fascination", + "factuallity", "factually", + "familairity", "familiarity", + "familairize", "familiarize", + "familiaries", "familiarize", + "familierize", "familiarize", + "fanatsizing", "fantasizing", + "fanficitons", "fanfiction", + "fantacising", "fantasizing", + "fantacizing", "fantasizing", + "fantasazing", "fantasizing", + "fantasiaing", "fantasizing", + "fantasyzing", "fantasizing", + "fantazising", "fantasizing", + "fascinacion", "fascination", + "fascinatinf", "fascination", + "fascisation", "fascination", + "fascization", "fascination", + "fashionalbe", "fashionable", + "fashoinable", "fashionable", + "fatalitites", "fatalities", + "favoritisme", "favorites", + "favoutrable", "favourable", + "felxibility", "flexibility", + "feministers", "feminists", + "feministisk", "feminists", + "fermentaion", "fermentation", + "fermenterad", "fermented", + "fertilizier", "fertilizer", + "fertizilers", "fertilizer", + "festivalens", "festivals", + "fignernails", "fingernails", + "fignerprint", "fingerprint", + "figurativly", "figuratively", + "finanically", "financially", + "finantially", "financially", + "fingerpints", "fingertips", + "fingerpoint", "fingerprint", + "fingertrips", "fingertips", + "firefighers", "firefighters", + "firefigther", "firefighters", + "firendzoned", "friendzoned", + "firghtening", "frightening", + "flatterende", "flattered", + "flawlessely", "flawlessly", + "flawlessley", "flawlessly", + "flexibiltiy", "flexibility", + "flourescent", "fluorescent", + "fluctuaties", "fluctuate", + "fluctuative", "fluctuate", + "flutteryshy", "fluttershy", + "forcefullly", "forcefully", + "foreseaable", "foreseeable", + "foresseable", "foreseeable", + "forgettting", "forgetting", + "forgiviness", "forgiveness", + "formallized", "formalized", + "formattting", "formatting", + "formidabble", "formidable", + "formidabelt", "formidable", + "formidabile", "formidable", + "fortitudine", "fortitude", + "fortuantely", "fortunately", + "fortunantly", "fortunately", + "fortunatley", "fortunately", + "fortunetely", "fortunately", + "franchieses", "franchises", + "frankensite", "frankenstein", + "frankensten", "frankenstein", + "fransiscans", "franciscans", + "freindships", "friendships", + "freindzoned", "friendzoned", + "frequenices", "frequencies", + "frequensies", "frequencies", + "frequenties", "frequencies", + "frequentily", "frequently", + "frequenzies", "frequencies", + "friendboned", "friendzoned", + "friendlines", "friendlies", + "friendzonie", "friendzoned", + "frientships", "friendships", + "frientzoned", "friendzoned", + "frightenend", "frightened", + "frightining", "frightening", + "frigthening", "frightening", + "frinedzoned", "friendzoned", + "frontlinies", "frontline", + "frontlinjen", "frontline", + "frustartion", "frustrations", + "frustracion", "frustration", + "frustraited", "frustrated", + "frustrantes", "frustrates", + "frustrasion", "frustrations", + "frustrasted", "frustrates", + "frustraties", "frustrates", + "fucntioning", "functioning", + "fulfillling", "fulfilling", + "fulfullment", "fulfillment", + "fullfilment", "fulfillment", + "fullscreeen", "fullscreen", + "funcitoning", "functioning", + "functionaly", "functionally", + "functionnal", "functional", + "fundamentas", "fundamentals", + "fundamently", "fundamental", + "fundametals", "fundamentals", + "fundamnetal", "fundamentals", + "fundemantal", "fundamental", + "fundemental", "fundamental", + "fundimental", "fundamental", + "furhtermore", "furthermore", + "furstration", "frustration", + "furthremore", "furthermore", + "furthurmore", "furthermore", + "futurisitic", "futuristic", + "gangsterest", "gangsters", + "gangsterous", "gangsters", + "gauntlettes", "gauntlets", + "geneologies", "genealogies", + "generalizng", "generalizing", + "generatting", "generating", + "genitaliban", "genitalia", + "gentlemanne", "gentlemen", + "girlfirends", "girlfriends", + "girlfreinds", "girlfriends", + "girlfrients", "girlfriends", + "glorifierad", "glorified", + "glorifindel", "glorified", + "goosebumbps", "goosebumps", + "govenrments", "governments", + "govermental", "governmental", + "governemnts", "governments", + "governmanet", "governmental", + "governmeant", "governmental", + "govormental", "governmental", + "gracefullly", "gracefully", + "grahpically", "graphically", + "grammarical", "grammatical", + "grammaticly", "grammatical", + "grammitical", "grammatical", + "graphcially", "graphically", + "grassrooots", "grassroots", + "gratuitious", "gratuitous", + "gratuituous", "gratuitous", + "gravitatiei", "gravitate", + "grilfriends", "girlfriends", + "grpahically", "graphically", + "guaranteeds", "guarantees", + "guerrillera", "guerrilla", + "gunslingner", "gunslinger", + "hamburgaren", "hamburger", + "hamburgeres", "hamburgers", + "hamburglers", "hamburgers", + "hamburguers", "hamburgers", + "handlebards", "handlebars", + "handrwiting", "handwriting", + "handycapped", "handicapped", + "hanidcapped", "handicapped", + "harassement", "harassment", + "harrasments", "harassments", + "harrassment", "harassment", + "harvestgain", "harvesting", + "headquartes", "headquarters", + "headquaters", "headquarters", + "hearhtstone", "hearthstone", + "heartborken", "heartbroken", + "heartbraker", "heartbreak", + "heartbrakes", "heartbreak", + "heartsthone", "hearthstone", + "heaviweight", "heavyweight", + "heavyweigth", "heavyweight", + "heavywieght", "heavyweight", + "helicoptors", "helicopters", + "helicotpers", "helicopters", + "helicpoters", "helicopters", + "helictopers", "helicopters", + "helikopters", "helicopters", + "hemipsheres", "hemisphere", + "hemishperes", "hemisphere", + "herathstone", "hearthstone", + "heterosexal", "heterosexual", + "hexidecimal", "hexadecimal", + "hierachical", "hierarchical", + "hierarcical", "hierarchical", + "highlighing", "highlighting", + "highschoool", "highschool", + "hipopotamus", "hippopotamus", + "historicaly", "historically", + "historicans", "historians", + "historietas", "histories", + "historinhas", "historians", + "homecomeing", "homecoming", + "homecomming", "homecoming", + "homelesness", "homelessness", + "homelessess", "homelessness", + "homeowneris", "homeowners", + "homoegenous", "homogeneous", + "homogeneize", "homogenize", + "homogenious", "homogeneous", + "homogenuous", "homogeneous", + "homophoboes", "homophobe", + "homosexuais", "homosexuals", + "homosexuels", "homosexuals", + "hopelessely", "hopelessly", + "hopelessley", "hopelessly", + "hopsitality", "hospitality", + "horizonatal", "horizontal", + "horizontaal", "horizontal", + "horizontaly", "horizontally", + "horrendeous", "horrendous", + "horrendious", "horrendous", + "horrenduous", "horrendous", + "hospitalzed", "hospitalized", + "hospotality", "hospitality", + "househoulds", "households", + "humanitarna", "humanitarian", + "humanitites", "humanities", + "humilitaing", "humiliating", + "humilitaion", "humiliation", + "humillating", "humiliating", + "humillation", "humiliation", + "hurricaines", "hurricanes", + "hurricances", "hurricanes", + "hurricanger", "hurricane", + "hyperbollic", "hyperbolic", + "hyperbrophy", "hypertrophy", + "hyperthropy", "hypertrophy", + "hypertorphy", "hypertrophy", + "hypertrohpy", "hypertrophy", + "hypocritcal", "hypocritical", + "hypocritial", "hypocritical", + "hypocrities", "hypocrite", + "hypothesees", "hypotheses", + "hypothesies", "hypothesis", + "hystericaly", "hysterically", + "hystericlly", "hysterically", + "iconclastic", "iconoclastic", + "idealisitic", "idealistic", + "identifible", "identifiable", + "identitites", "identities", + "identitties", "identities", + "ideologiers", "ideologies", + "ideologisen", "ideologies", + "ideologiset", "ideologies", + "ideologiske", "ideologies", + "illegallity", "illegally", + "illegitamte", "illegitimate", + "illegitmate", "illegitimate", + "illsutrator", "illustrator", + "illuminanti", "illuminati", + "illuminarti", "illuminati", + "illuminatti", "illuminati", + "illuminauti", "illuminati", + "illuminiati", "illuminati", + "illuminista", "illuminati", + "illumintati", "illuminati", + "illustarted", "illustrated", + "illustartor", "illustrator", + "illustraded", "illustrated", + "illustraion", "illustration", + "illustrater", "illustrator", + "illustratie", "illustrate", + "illustratin", "illustrations", + "illustraton", "illustration", + "imaganative", "imaginative", + "imaganitive", "imaginative", + "imaginacion", "imagination", + "imaginatiei", "imaginative", + "imaginating", "imagination", + "imaginativo", "imagination", + "imaginitave", "imaginative", + "imbalanaced", "imbalanced", + "imbalanaces", "imbalances", + "imbalancers", "imbalances", + "immatureity", "immaturity", + "immedeately", "immediately", + "immediantly", "immediately", + "immediatley", "immediately", + "immedietely", "immediately", + "immideately", "immediately", + "immidiately", "immediately", + "immigraiton", "immigration", + "immigrantes", "immigrants", + "immoratlity", "immortality", + "immortailty", "immortality", + "immortalisy", "immortals", + "impeccabile", "impeccable", + "imperailist", "imperialist", + "imperealist", "imperialist", + "imperialims", "imperialism", + "imperialsim", "imperialism", + "imperiarist", "imperialist", + "imperically", "empirically", + "imperislist", "imperialist", + "implausable", "implausible", + "implausbile", "implausible", + "implementas", "implements", + "implementes", "implements", + "implementig", "implementing", + "implementos", "implements", + "implicacion", "implication", + "implicatons", "implications", + "implicitely", "implicitly", + "implicitily", "implicitly", + "implikation", "implication", + "implimented", "implemented", + "importantce", "importance", + "importently", "importantly", + "imporvement", "improvement", + "impossibile", "impossible", + "impossibily", "impossibly", + "impossibley", "impossibly", + "impossiblly", "impossibly", + "impoverised", "impoverished", + "impracticle", "impractical", + "impressario", "impresario", + "impresssion", "impressions", + "imprisonent", "imprisonment", + "imprisonned", "imprisoned", + "improbabile", "improbable", + "improtantly", "importantly", + "improvemnts", "improvements", + "improvished", "improvised", + "improvision", "improvisation", + "improvments", "improvements", + "impulsivley", "impulsive", + "imrpovement", "improvement", + "inaccessble", "inaccessible", + "inaccuraces", "inaccuracies", + "inaccurrate", "inaccurate", + "inadvertant", "inadvertent", + "inaguration", "inauguration", + "inahbitants", "inhabitants", + "incarantion", "incarnation", + "incarcerato", "incarceration", + "incarnacion", "incarnation", + "incentivare", "incentive", + "incentivate", "incentive", + "incentivice", "incentive", + "incentivies", "incentives", + "incidencies", "incidence", + "incidentaly", "incidentally", + "incidential", "incidental", + "inclanation", "inclination", + "inclenation", "inclination", + "inclinacion", "inclination", + "inclinaison", "inclination", + "incognition", "incognito", + "incoherrent", "incoherent", + "incompatble", "incompatible", + "incompatent", "incompetent", + "incompetant", "incompetent", + "incompitent", "incompetent", + "incompotent", "incompetent", + "incomptable", "incompatible", + "inconsisent", "inconsistent", + "inconveniet", "inconvenient", + "incoroprate", "incorporate", + "incorparate", "incorporate", + "incorperate", "incorporate", + "incorporare", "incorporate", + "incorported", "incorporated", + "incorprates", "incorporates", + "incorproate", "incorporated", + "incramental", "incremental", + "increadible", "incredible", + "incrediable", "incredible", + "incrediably", "incredibly", + "incredibile", "incredible", + "incredibily", "incredibly", + "incredibley", "incredibly", + "incrememnts", "increments", + "incremenets", "increments", + "incrementas", "increments", + "incremently", "incremental", + "incrementos", "increments", + "incrimental", "incremental", + "inctroduced", "introduced", + "indefinetly", "indefinitely", + "indefininte", "indefinite", + "indefinitly", "indefinitely", + "indepdenent", "independents", + "indepedence", "independence", + "indepednent", "independents", + "independant", "independent", + "independece", "independence", + "independens", "independents", + "independetn", "independents", + "independets", "independents", + "independnet", "independents", + "indepentend", "independents", + "indepentent", "independent", + "indianapols", "indianapolis", + "indicateurs", "indicates", + "indicatiors", "indicators", + "indictement", "indictment", + "indifferant", "indifferent", + "indiffernce", "indifference", + "indigeneous", "indigenous", + "indigenious", "indigenous", + "indigenuous", "indigenous", + "indigineous", "indigenous", + "indipendent", "independent", + "indirectely", "indirectly", + "individiual", "individual", + "individuais", "individuals", + "individualy", "individually", + "individuati", "individuality", + "individuels", "individuals", + "indivuduals", "individuals", + "industriels", "industries", + "ineffecitve", "ineffective", + "ineffektive", "ineffective", + "inefficeint", "inefficient", + "inefficiant", "inefficient", + "ineffictive", "ineffective", + "ineffizient", "inefficient", + "inequallity", "inequality", + "inevitabile", "inevitable", + "inevitabily", "inevitably", + "inevitabley", "inevitably", + "inevitablly", "inevitably", + "inexpencive", "inexpensive", + "inexpenisve", "inexpensive", + "inexperiece", "inexperience", + "inexperince", "inexperience", + "inexplicaby", "inexplicably", + "infallibale", "infallible", + "infallibile", "infallible", + "infectation", "infestation", + "inferioirty", "inferiority", + "infestating", "infestation", + "infilitrate", "infiltrate", + "infiltartor", "infiltrator", + "infiltraron", "infiltrator", + "infiltrarte", "infiltrate", + "infiltrater", "infiltrator", + "infiltratie", "infiltrate", + "infiltrerat", "infiltrate", + "infinitelly", "infinitely", + "infintrator", "infiltrator", + "inflamation", "inflammation", + "inflatabale", "inflatable", + "inflitrator", "infiltrator", + "influancing", "influencing", + "influencial", "influential", + "influencian", "influencing", + "influenting", "influencing", + "influentual", "influential", + "influincing", "influencing", + "infograhpic", "infographic", + "infograpgic", "infographic", + "infogrpahic", "infographic", + "informacion", "information", + "informatice", "informative", + "informatief", "informative", + "informatiei", "informative", + "informatike", "informative", + "informativo", "information", + "informitive", "informative", + "infrigement", "infringement", + "infringeing", "infringing", + "infromation", "information", + "infromative", "informative", + "infulential", "influential", + "ingerdients", "ingredients", + "ingrediants", "ingredients", + "ingreidents", "ingredient", + "ingriedents", "ingredient", + "inhabitents", "inhabitants", + "inheirtance", "inheritance", + "inheratance", "inheritance", + "inheretance", "inheritance", + "inheritence", "inheritance", + "inhertiance", "inheritance", + "initaitives", "initiatives", + "initalisers", "initialisers", + "initalising", "initialising", + "initalizers", "initializers", + "initalizing", "initializing", + "initiaitive", "initiative", + "inititiaves", "initiatives", + "innocenters", "innocents", + "innocentius", "innocents", + "innoculated", "inoculated", + "inpsiration", "inspiration", + "inquisicion", "inquisition", + "inquisistor", "inquisitor", + "inquisiting", "inquisition", + "inquisitior", "inquisitor", + "inquisitivo", "inquisition", + "inquizition", "inquisition", + "insecurites", "insecurities", + "insensative", "insensitive", + "insensetive", "insensitive", + "insentitive", "insensitive", + "insepctions", "inspections", + "inseperable", "inseparable", + "insipration", "inspiration", + "insitutions", "institutions", + "insparation", "inspiration", + "inspecticon", "inspection", + "inspectoras", "inspectors", + "insperation", "inspiration", + "inspiracion", "inspiration", + "inspirating", "inspiration", + "inspriation", "inspiration", + "instalation", "installation", + "instalement", "installment", + "installatin", "installations", + "installeert", "installer", + "installemnt", "installment", + "installling", "installing", + "installmant", "installment", + "instanciate", "instantiate", + "instantaneu", "instantaneous", + "institucion", "institution", + "institutiei", "institute", + "instituttet", "institute", + "instraments", "instruments", + "instruccion", "instruction", + "instruciton", "instruction", + "instructers", "instructors", + "instructior", "instructor", + "instructios", "instructors", + "instructivo", "instruction", + "instructons", "instructors", + "instruktion", "instruction", + "instrumenal", "instrumental", + "instrumetal", "instrumental", + "insturction", "instruction", + "insturctors", "instructors", + "insturments", "instruments", + "instutition", "institution", + "instutution", "institution", + "insufficent", "insufficient", + "insuinating", "insinuating", + "insuniating", "insinuating", + "insurgencey", "insurgency", + "intangiable", "intangible", + "intangibile", "intangible", + "inteferring", "interfering", + "integracion", "integration", + "integratron", "integration", + "integrering", "interfering", + "intelectual", "intellectual", + "inteligence", "intelligence", + "intellectul", "intellectuals", + "intellectus", "intellectuals", + "intellecual", "intellectual", + "intellegent", "intelligent", + "intelligant", "intelligent", + "intencional", "intentional", + "intentionly", "intentional", + "interaccion", "interaction", + "interactice", "interactive", + "interacties", "interacts", + "interactifs", "interacts", + "interactins", "interacts", + "interactios", "interacts", + "interactivo", "interaction", + "interactons", "interacts", + "interaktion", "interaction", + "interaktive", "interactive", + "interasting", "interacting", + "intercation", "integration", + "interceptin", "interception", + "intercoarse", "intercourse", + "intercource", "intercourse", + "interecting", "interacting", + "interection", "interaction", + "interelated", "interrelated", + "interersted", "interpreted", + "interesring", "interfering", + "interessted", "interested", + "interferece", "interference", + "interferens", "interferes", + "interferire", "interfere", + "interfernce", "interference", + "interferred", "interfere", + "interferres", "interferes", + "intergation", "integration", + "intergrated", "integrated", + "intermedate", "intermediate", + "intermedite", "intermediate", + "intermitent", "intermittent", + "internation", "international", + "interneters", "internets", + "internetese", "internets", + "internetest", "internets", + "interneting", "interesting", + "internetors", "internets", + "internettes", "internets", + "interperted", "interpreted", + "interperter", "interpreter", + "interprered", "interpreter", + "interpretor", "interpreter", + "interratial", "interracial", + "interresing", "interfering", + "interrogato", "interrogation", + "interrputed", "interrupted", + "interruping", "interrupting", + "interruptes", "interrupts", + "interruptis", "interrupts", + "intersecton", "intersection", + "interstelar", "interstellar", + "intertained", "intertwined", + "intertvined", "intertwined", + "intertwyned", "intertwined", + "intervalles", "intervals", + "intervation", "integration", + "interveiwed", "interviewed", + "interveiwer", "interviewer", + "intervenion", "intervening", + "intervenire", "intervene", + "interventie", "intervene", + "intervewing", "intervening", + "interviened", "interviewed", + "interviewes", "interviews", + "interviewie", "interviewer", + "intervining", "intervening", + "interwebers", "interwebs", + "interwiever", "interviewer", + "intestinces", "intestines", + "inticracies", "intricacies", + "intimadated", "intimidated", + "intimidades", "intimidated", + "intimidante", "intimidate", + "intimidatie", "intimidated", + "intimidatin", "intimidation", + "intimidaton", "intimidation", + "intimidiate", "intimidate", + "intiminated", "intimidated", + "intimitaded", "intimidated", + "intimitated", "intimidated", + "intiutively", "intuitively", + "intoleranse", "intolerance", + "intolerante", "intolerance", + "intolerence", "intolerance", + "intolernace", "intolerance", + "intolorance", "intolerance", + "intolorence", "intolerance", + "intorducing", "introducing", + "intorverted", "introverted", + "intoxicatin", "intoxication", + "intoxicaton", "intoxication", + "intoxinated", "intoxicated", + "intoxocated", "intoxicated", + "intracacies", "intricacies", + "intracicies", "intricacies", + "intraverted", "introverted", + "intrecacies", "intricacies", + "intrepreted", "interpreted", + "intrepreter", "interpreter", + "intrerupted", "interrupted", + "intricasies", "intricacies", + "intricicies", "intricacies", + "intrigueing", "intriguing", + "intrinsisch", "intrinsic", + "introducion", "introduction", + "introducted", "introduced", + "introductie", "introduce", + "introvertie", "introverted", + "introvertis", "introverts", + "intruducing", "introducing", + "intrumental", "instrumental", + "intuatively", "intuitively", + "intuitevely", "intuitively", + "intuitivley", "intuitively", + "intuituvely", "intuitively", + "inutitively", "intuitively", + "invaldiates", "invalidates", + "invalidades", "invalidates", + "invalidante", "invalidate", + "invariabley", "invariably", + "invariablly", "invariably", + "inventiones", "inventions", + "invesitgate", "investigate", + "investagate", "investigate", + "investiagte", "investigate", + "investigare", "investigate", + "invincibile", "invincible", + "invincinble", "invincible", + "invisibiity", "invisibility", + "invisibiliy", "invisibility", + "invokations", "invocations", + "involantary", "involuntary", + "involentary", "involuntary", + "involintary", "involuntary", + "involontary", "involuntary", + "involunatry", "involuntary", + "invulnerabe", "invulnerable", + "invulnerble", "invulnerable", + "iresistable", "irresistible", + "iresistably", "irresistibly", + "iresistible", "irresistible", + "iresistibly", "irresistibly", + "irrationaly", "irrationally", + "irrationnal", "irrational", + "islamisists", "islamists", + "islamisters", "islamists", + "islamistisk", "islamists", + "isntruments", "instruments", + "jacksonvile", "jacksonville", + "jailbroaken", "jailbroken", + "jailbrocken", "jailbroken", + "jounralists", "journalists", + "jouranlists", "journalists", + "journalisim", "journalism", + "journalistc", "journalistic", + "journolists", "journalists", + "judegmental", "judgemental", + "judgamental", "judgemental", + "judgementle", "judgemental", + "judgementsl", "judgemental", + "judgenental", "judgemental", + "jugdemental", "judgemental", + "juggernaugt", "juggernaut", + "juggernault", "juggernaut", + "juggernaunt", "juggernaut", + "justifyable", "justifiable", + "kidnappning", "kidnapping", + "kidnappping", "kidnapping", + "kilometeres", "kilometers", + "kindergaten", "kindergarten", + "knowledgabe", "knowledgable", + "knowledgble", "knowledgable", + "kryptoninte", "kryptonite", + "lacklusture", "lackluster", + "laughablely", "laughably", + "legalizaing", "legalizing", + "legalizaton", "legalization", + "legalizeing", "legalizing", + "legenadries", "legendaries", + "legendaires", "legendaries", + "legendarios", "legendaries", + "legendarisk", "legendaries", + "legendaryes", "legendaries", + "legenderies", "legendaries", + "legilsation", "legislation", + "legislacion", "legislation", + "legislativo", "legislation", + "legistation", "legislation", + "legistative", "legislative", + "legistators", "legislators", + "legitematly", "legitimately", + "legitimancy", "legitimacy", + "legitimatcy", "legitimacy", + "legitimatly", "legitimately", + "legitimetly", "legitimately", + "legnedaries", "legendaries", + "lengedaries", "legendaries", + "liberalisim", "liberalism", + "liberatrian", "libertarians", + "libertairan", "libertarians", + "libertarain", "libertarian", + "libertarias", "libertarians", + "libertarien", "libertarian", + "libertaryan", "libertarian", + "libertatian", "libertarian", + "liberterian", "libertarian", + "libguistics", "linguistics", + "libretarian", "libertarian", + "lieutennant", "lieutenant", + "lieutentant", "lieutenant", + "lightenning", "lightening", + "lightenting", "lightening", + "lightheared", "lighthearted", + "lightheated", "lighthearted", + "lightweigth", "lightweight", + "lightwieght", "lightweight", + "lightwright", "lightweight", + "ligthweight", "lightweight", + "limitaitons", "limitation", + "linguisitcs", "linguistics", + "linguisitic", "linguistic", + "lingusitics", "linguistics", + "lithuaninan", "lithuania", + "littlefiger", "littlefinger", + "littlefiner", "littlefinger", + "lockscreeen", "lockscreen", + "longevitity", "longevity", + "lotharingen", "lothringen", + "louisvillle", "louisville", + "maginficent", "magnificent", + "magneficent", "magnificent", + "magnicifent", "magnificent", + "magnifacent", "magnificent", + "magnifecent", "magnificent", + "magnificant", "magnificent", + "magnitudine", "magnitude", + "maintainted", "maintained", + "maintanance", "maintenance", + "maintanence", "maintenance", + "maintenence", "maintenance", + "maintianing", "maintaining", + "maintinaing", "maintaining", + "maintinance", "maintenance", + "maintinence", "maintenance", + "malfonction", "malfunction", + "malfucntion", "malfunction", + "malfunciton", "malfunction", + "malfuncting", "malfunction", + "malfunktion", "malfunction", + "malpractise", "malpractice", + "malpractive", "malpractice", + "maneouvring", "manoeuvring", + "manifestado", "manifesto", + "manifestano", "manifesto", + "manifestato", "manifesto", + "manifestion", "manifesto", + "manifestior", "manifesto", + "manifestons", "manifests", + "manifestors", "manifests", + "manipluated", "manipulated", + "manipualted", "manipulated", + "manipulatie", "manipulative", + "manipulatin", "manipulation", + "manipulaton", "manipulation", + "maniuplated", "manipulated", + "mannerisims", "mannerisms", + "manslaugher", "manslaughter", + "manslaugter", "manslaughter", + "manufacters", "manufactures", + "manufacteur", "manufactures", + "manufactued", "manufactured", + "manufactuer", "manufacture", + "manufacturs", "manufactures", + "manufacuter", "manufacture", + "manufacutre", "manufactures", + "manufatured", "manufactured", + "manupilated", "manipulated", + "marganilize", "marginalized", + "marhsmallow", "marshmallow", + "marijuannas", "marijuana", + "markerplace", "marketplace", + "marketpalce", "marketplace", + "marshamllow", "marshmallow", + "marshmalows", "marshmallows", + "masculanity", "masculinity", + "masculenity", "masculinity", + "masrhmallow", "marshmallow", + "mastermined", "mastermind", + "masterpeace", "masterpiece", + "masterpeice", "masterpiece", + "mastrubated", "masturbated", + "mastrubates", "masturbate", + "masturabted", "masturbated", + "masturbaing", "masturbating", + "masturbarte", "masturbate", + "masturbathe", "masturbated", + "masturbatie", "masturbated", + "masturbatin", "masturbation", + "masturbaton", "masturbation", + "masturbsted", "masturbated", + "masturpiece", "masterpiece", + "masuclinity", "masculinity", + "matchamking", "matchmaking", + "materalists", "materialist", + "materialsim", "materialism", + "mathamatics", "mathematics", + "mathcmaking", "matchmaking", + "mathemagics", "mathematics", + "mathemetics", "mathematics", + "mathimatics", "mathematics", + "matieralism", "materialism", + "maybelleine", "maybelline", + "maybelliene", "maybelline", + "maybellinne", "maybelline", + "maybellline", "maybelline", + "mdifielders", "midfielders", + "meatballers", "meatballs", + "mecernaries", "mercenaries", + "mechanicaly", "mechanically", + "mechanichal", "mechanical", + "mechaniclly", "mechanically", + "mechanicsms", "mechanisms", + "mechanisims", "mechanism", + "mechanismus", "mechanisms", + "medicaitons", "medications", + "medicineras", "medicines", + "meditatiing", "meditating", + "meditationg", "meditating", + "mentionning", "mentioning", + "mercanaries", "mercenaries", + "mercaneries", "mercenaries", + "mercenaires", "mercenaries", + "mercenarias", "mercenaries", + "mercenarios", "mercenaries", + "merceneries", "mercenaries", + "merchandice", "merchandise", + "merchandies", "merchandise", + "merchanidse", "merchandise", + "merchanters", "merchants", + "merchendise", "merchandise", + "merchindise", "merchandise", + "mercinaries", "mercenaries", + "mercineries", "mercenaries", + "metabolisim", "metabolism", + "metabolitic", "metabolic", + "metaphisics", "metaphysics", + "metaphorial", "metaphorical", + "metaphorics", "metaphors", + "metaphsyics", "metaphysics", + "metaphyiscs", "metaphysics", + "methodoligy", "methodology", + "metholodogy", "methodology", + "metropolian", "metropolitan", + "metropolies", "metropolis", + "metropollis", "metropolis", + "metropolois", "metropolis", + "micorcenter", "microcenter", + "micorphones", "microphones", + "microcender", "microcenter", + "microcentre", "microcenter", + "microcentro", "microcenter", + "microhpones", "microphones", + "microscrope", "microscope", + "microwavees", "microwaves", + "microwavers", "microwaves", + "midfeilders", "midfielders", + "midfiedlers", "midfielders", + "midfileders", "midfielders", + "midifelders", "midfielders", + "millienaire", "millionaire", + "millionairs", "millionaires", + "millionarie", "millionaire", + "millioniare", "millionaire", + "mindlessely", "mindlessly", + "mindlessley", "mindlessly", + "minimalstic", "minimalist", + "ministerens", "ministers", + "ministerios", "ministers", + "minneaoplis", "minneapolis", + "minneaplois", "minneapolis", + "minniapolis", "minneapolis", + "miraculaous", "miraculous", + "miraculosly", "miraculously", + "miraculousy", "miraculously", + "mircocenter", "microcenter", + "mircophones", "microphones", + "mircoscopic", "microscopic", + "miscairrage", "miscarriage", + "miscarraige", "miscarriage", + "miscarridge", "miscarriage", + "miscarriege", "miscarriage", + "mischeivous", "mischievous", + "mischevious", "mischievous", + "misdameanor", "misdemeanor", + "misdeamenor", "misdemeanor", + "misdemeaner", "misdemeanor", + "misdemenaor", "misdemeanor", + "misdemenors", "misdemeanors", + "misdimeanor", "misdemeanor", + "misdomeanor", "misdemeanor", + "miserablely", "miserably", + "misfortunte", "misfortune", + "misimformed", "misinformed", + "misinterept", "misinterpret", + "misinterpet", "misinterpret", + "misoginysts", "misogynist", + "misognyists", "misogynist", + "misogyinsts", "misogynist", + "misogynisic", "misogynistic", + "misogynistc", "misogynistic", + "misogynstic", "misogynist", + "missionaire", "missionaries", + "missionairy", "missionary", + "missionares", "missionaries", + "missionaris", "missionaries", + "missionarry", "missionary", + "missionnary", "missionary", + "mississipis", "mississippi", + "misspeeling", "misspelling", + "misspellled", "misspelled", + "mistakengly", "mistakenly", + "mistakently", "mistakenly", + "moderatedly", "moderately", + "moderateurs", "moderates", + "moderatorin", "moderation", + "modificaton", "modification", + "moisterizer", "moisturizer", + "moistruizer", "moisturizer", + "moisturizng", "moisturizing", + "moisturizor", "moisturizer", + "moistutizer", "moisturizer", + "moisutrizer", "moisturizer", + "moleculaire", "molecular", + "molestating", "molestation", + "moleststion", "molestation", + "momemtarily", "momentarily", + "momentairly", "momentarily", + "momentaraly", "momentarily", + "momentarely", "momentarily", + "momenterily", "momentarily", + "monestaries", "monasteries", + "monitoreada", "monitored", + "monitoreado", "monitored", + "monogameous", "monogamous", + "monolitihic", "monolithic", + "monopollies", "monopolies", + "monstorsity", "monstrosity", + "monstrasity", "monstrosity", + "monstrisity", "monstrosity", + "monstrocity", "monstrosity", + "monstrosoty", "monstrosity", + "monstrostiy", "monstrosity", + "monumentaal", "monumental", + "monumentais", "monuments", + "monumentals", "monuments", + "monumentous", "monuments", + "mositurizer", "moisturizer", + "mosntrosity", "monstrosity", + "motehrboard", "motherboard", + "mothebroard", "motherboards", + "motherbaord", "motherboard", + "motherboads", "motherboards", + "motherboars", "motherboards", + "motherborad", "motherboard", + "motherbords", "motherboards", + "motherobard", "motherboards", + "mothreboard", "motherboards", + "motivatinal", "motivational", + "motorcicles", "motorcycles", + "motorcylces", "motorcycles", + "mouthpeices", "mouthpiece", + "mulitplayer", "multiplayer", + "mulitplying", "multiplying", + "multipalyer", "multiplayer", + "multiplater", "multiplayer", + "multiplebgs", "multiples", + "multipleies", "multiples", + "multitaskng", "multitasking", + "multitudine", "multitude", + "multiverese", "multiverse", + "multyplayer", "multiplayer", + "multyplying", "multiplying", + "muncipality", "municipality", + "murdererous", "murderers", + "musicallity", "musically", + "mutliplayer", "multiplayer", + "mutliplying", "multiplying", + "mysterieuse", "mysteries", + "mysteriosly", "mysteriously", + "mysteriouly", "mysteriously", + "mysteriousy", "mysteriously", + "napoleonian", "napoleonic", + "narcisissim", "narcissism", + "narcisissts", "narcissist", + "narcisscism", "narcissism", + "narcisscist", "narcissist", + "narcissisim", "narcissism", + "narcississm", "narcissism", + "narcississt", "narcissist", + "narcissistc", "narcissistic", + "narcissitic", "narcissistic", + "narcisssism", "narcissism", + "narcisssist", "narcissist", + "narcissstic", "narcissist", + "natioanlist", "nationalist", + "nationailty", "nationality", + "nationalesl", "nationals", + "nationalisn", "nationals", + "nationalite", "nationalist", + "nationalits", "nationalist", + "nationalizm", "nationalism", + "nationalsim", "nationalism", + "neccesarily", "necessarily", + "necessairly", "necessarily", + "necessaties", "necessities", + "necesseraly", "necessarily", + "necesserily", "necessarily", + "necessiates", "necessities", + "necessitive", "necessities", + "neckbeardos", "neckbeards", + "neckbeardus", "neckbeards", + "necormancer", "necromancer", + "necromamcer", "necromancer", + "necromanser", "necromancer", + "necromencer", "necromancer", + "needlessley", "needlessly", + "negativeity", "negativity", + "negativelly", "negatively", + "negativitiy", "negativity", + "negiotating", "negotiating", + "negligiable", "negligible", + "negociating", "negotiating", + "negociation", "negotiation", + "negoitating", "negotiating", + "negoitation", "negotiation", + "negotiatied", "negotiate", + "negotiative", "negotiate", + "negotiatons", "negotiations", + "neigborhood", "neighborhood", + "neigbouring", "neighbouring", + "neighborhod", "neighborhood", + "neighbourgs", "neighbours", + "neighouring", "neighboring", + "nercomancer", "necromancer", + "nessasarily", "necessarily", + "neurologial", "neurological", + "neurosciene", "neuroscience", + "neutrallity", "neutrality", + "neverthelss", "nevertheless", + "neverthless", "nevertheless", + "newspapaers", "newspapers", + "newspappers", "newspapers", + "nieghboring", "neighboring", + "nightmarket", "nightmare", + "nonsencical", "nonsensical", + "nonsenscial", "nonsensical", + "nonsensicle", "nonsensical", + "normallized", "normalized", + "northwesten", "northwestern", + "nostalgisch", "nostalgic", + "noteworthly", "noteworthy", + "noticeabley", "noticeably", + "notificaton", "notification", + "notoriuosly", "notoriously", + "numericable", "numerical", + "nurtitional", "nutritional", + "nutricional", "nutritional", + "nutrutional", "nutritional", + "obamination", "abomination", + "obersvation", "observation", + "obilterated", "obliterated", + "objectivety", "objectivity", + "objectivify", "objectivity", + "objectivily", "objectivity", + "objectivley", "objectively", + "obliberated", "obliterated", + "obliderated", "obliterated", + "obligerated", "obliterated", + "oblitarated", "obliterated", + "obliteraded", "obliterated", + "obliterared", "obliterated", + "oblitirated", "obliterated", + "oblitorated", "obliterated", + "obliverated", "obliterated", + "observacion", "observation", + "observaiton", "observant", + "observasion", "observations", + "observating", "observation", + "observerats", "observers", + "obsessivley", "obsessive", + "obstruccion", "obstruction", + "obstruktion", "obstruction", + "obsturction", "obstruction", + "obversation", "observation", + "ocasionally", "occasionally", + "ocassionaly", "occasionally", + "occasionals", "occasions", + "occasionaly", "occasionally", + "occasionnal", "occasional", + "occassional", "occasional", + "occassioned", "occasioned", + "occurrances", "occurrences", + "offensivley", "offensively", + "offesnively", "offensively", + "officiallly", "officially", + "olbiterated", "obliterated", + "omniscienct", "omniscient", + "operacional", "operational", + "operasional", "operational", + "operationel", "operational", + "oppresssing", "oppressing", + "oppresssion", "oppression", + "opprotunity", "opportunity", + "optimisitic", "optimistic", + "optimizaton", "optimization", + "optmization", "optimization", + "orchestraed", "orchestrated", + "orchestrial", "orchestra", + "oreintation", "orientation", + "organisaton", "organisation", + "organiserad", "organised", + "organistion", "organisation", + "organizarea", "organizer", + "organizarem", "organizer", + "organizarme", "organizer", + "organizarte", "organizer", + "organiztion", "organization", + "oridinarily", "ordinarily", + "orientacion", "orientation", + "originially", "originally", + "originnally", "originally", + "origniality", "originality", + "ostensiably", "ostensibly", + "ostensibily", "ostensibly", + "outclasssed", "outclassed", + "outnunbered", "outnumbered", + "outperfroms", "outperform", + "outpreforms", "outperform", + "outrageosly", "outrageously", + "outrageouly", "outrageously", + "outragerous", "outrageous", + "outskirters", "outskirts", + "outsorucing", "outsourcing", + "outsourcade", "outsourced", + "outsoursing", "outsourcing", + "overbraking", "overbearing", + "overcapping", "overlapping", + "overcharing", "overarching", + "overclcoked", "overclocked", + "overclicked", "overclocked", + "overcloaked", "overclocked", + "overclocing", "overclocking", + "overclockig", "overclocking", + "overclocled", "overclocked", + "overcomeing", "overcoming", + "overcomming", "overcoming", + "overeaching", "overarching", + "overfapping", "overlapping", + "overheading", "overheating", + "overhooking", "overlooking", + "overhwelmed", "overwhelmed", + "overkapping", "overlapping", + "overklocked", "overclocked", + "overlapsing", "overlapping", + "overlcocked", "overclocked", + "overlcoking", "overlooking", + "overlooming", "overlooking", + "overloooked", "overlooked", + "overlordess", "overlords", + "overmapping", "overlapping", + "overpooling", "overlooking", + "overpovered", "overpowered", + "overpoweing", "overpowering", + "overreacing", "overreacting", + "overreactin", "overreaction", + "overreacton", "overreaction", + "overshaddow", "overshadowed", + "overshadowd", "overshadowed", + "overtapping", "overlapping", + "overthining", "overthinking", + "overthinkig", "overthinking", + "overvlocked", "overclocked", + "overwealmed", "overwhelmed", + "overwelming", "overwhelming", + "overwhelemd", "overwhelmed", + "overwhelimg", "overwhelm", + "overwheling", "overwhelming", + "overwhemled", "overwhelmed", + "overwhlemed", "overwhelmed", + "overwritted", "overwrite", + "pakistanais", "pakistani", + "pakistanezi", "pakistani", + "palceholder", "placeholder", + "palesitnian", "palestinians", + "palestenian", "palestinian", + "palestinain", "palestinians", + "palestinans", "palestinians", + "palestinier", "palestine", + "palistinian", "palestinian", + "palythrough", "playthrough", + "papanicalou", "papanicolaou", + "parachutage", "parachute", + "paragraphes", "paragraphs", + "paramedicks", "paramedics", + "paramedicos", "paramedics", + "parameteres", "parameters", + "paranthesis", "parenthesis", + "parapharsed", "paraphrase", + "paraprhased", "paraphrase", + "parasitisme", "parasites", + "parenthasis", "parenthesis", + "parenthesys", "parentheses", + "parenthises", "parenthesis", + "parenthisis", "parenthesis", + "parliamenty", "parliamentary", + "parntership", "partnership", + "parrallelly", "parallelly", + "partecipant", "participant", + "partecipate", "participate", + "parternship", "partnership", + "partiarchal", "patriarchal", + "particapate", "participate", + "particiapte", "participate", + "participait", "participant", + "participans", "participants", + "participare", "participate", + "participatd", "participant", + "participati", "participant", + "participats", "participant", + "participent", "participant", + "particpiate", "participated", + "particually", "particularly", + "particulaly", "particularly", + "particulary", "particularly", + "partnetship", "partnership", + "partonizing", "patronizing", + "passionatly", "passionately", + "passionetly", "passionately", + "passionnate", "passionate", + "passporters", "passports", + "pathologial", "pathological", + "patriarchia", "patriarchal", + "patriarcial", "patriarchal", + "patriarical", "patriarchal", + "patriotisch", "patriotic", + "patriotisim", "patriotism", + "patriottism", "patriotism", + "patronozing", "patronizing", + "peacefullly", "peacefully", + "pedestirans", "pedestrians", + "pedestrains", "pedestrians", + "pedophilies", "pedophile", + "pedophilles", "pedophile", + "penetracion", "penetration", + "penetrading", "penetrating", + "penetrarion", "penetration", + "penninsular", "peninsular", + "pennsylvnia", "pennsylvania", + "pepperocini", "pepperoni", + "percantages", "percentages", + "percautions", "precautions", + "percentille", "percentile", + "percpetions", "perceptions", + "percusssion", "percussion", + "perdicament", "predicament", + "perdictable", "predictable", + "perdictions", "predictions", + "perephirals", "peripherals", + "pereptually", "perpetually", + "perferences", "preferences", + "perfomrance", "performances", + "perforamnce", "performances", + "performaces", "performances", + "performacne", "performances", + "performanes", "performances", + "performanse", "performances", + "performence", "performance", + "performnace", "performances", + "perfromance", "performance", + "perhiperals", "peripherals", + "perihperals", "peripherals", + "periodicaly", "periodically", + "periperhals", "peripherals", + "periphereal", "peripheral", + "peripherial", "peripheral", + "periphirals", "peripherals", + "periphreals", "peripherals", + "periphrials", "peripherals", + "perjorative", "pejorative", + "perliminary", "preliminary", + "permamently", "permanently", + "permanantly", "permanently", + "permaturely", "prematurely", + "permenantly", "permanently", + "permenently", "permanently", + "perminantly", "permanently", + "perminently", "permanently", + "permisisons", "permissions", + "permissable", "permissible", + "permisssion", "permissions", + "pernamently", "permanently", + "perosnality", "personality", + "perparation", "preparation", + "perpatrated", "perpetrated", + "perpatrator", "perpetrator", + "perpatuated", "perpetuated", + "perpatuates", "perpetuates", + "perpertated", "perpetuated", + "perpertator", "perpetrators", + "perpetraded", "perpetrated", + "perpetrador", "perpetrator", + "perpetraron", "perpetrator", + "perpetrater", "perpetrator", + "perpetuaded", "perpetuated", + "perpetutate", "perpetuate", + "perpetuties", "perpetuates", + "perpitrated", "perpetrated", + "perpitrator", "perpetrator", + "perpretated", "perpetrated", + "perpretator", "perpetrators", + "perpsective", "perspective", + "perputrator", "perpetrator", + "perputually", "perpetually", + "perputuated", "perpetuated", + "perputuates", "perpetuates", + "perrogative", "prerogative", + "persceptive", "perspectives", + "persectuion", "persecution", + "persecucion", "persecution", + "persecusion", "persecution", + "persecutted", "persecuted", + "persepctive", "perspective", + "persicution", "persecution", + "persistance", "persistence", + "persistante", "persistent", + "persistense", "persistence", + "persistente", "persistence", + "personhoood", "personhood", + "perspecitve", "perspective", + "perspectief", "perspective", + "perspektive", "perspective", + "persuassion", "persuasion", + "persuassive", "persuasive", + "persucution", "persecution", + "persumption", "presumption", + "pertubation", "perturbation", + "pessimestic", "pessimistic", + "pharamcists", "pharmacist", + "phenomenona", "phenomena", + "philadelpha", "philadelphia", + "philadelpia", "philadelphia", + "philiphines", "philippines", + "philippenes", "philippines", + "philippenis", "philippines", + "philippides", "philippines", + "philippinas", "philippines", + "philippinos", "philippines", + "philisopher", "philosopher", + "phillipines", "philippines", + "philosipher", "philosopher", + "philosopers", "philosophers", + "philosophae", "philosopher", + "philosophia", "philosophical", + "philosopies", "philosophies", + "philosphies", "philosophies", + "philospoher", "philosopher", + "photograhed", "photographed", + "photograher", "photographer", + "photograhic", "photographic", + "photograhpy", "photography", + "photograped", "photographed", + "photograper", "photographer", + "photograpgh", "photographs", + "photograpic", "photographic", + "photogrpahs", "photographs", + "photogrpahy", "photography", + "physcedelic", "psychedelic", + "physciatric", "psychiatric", + "physcopaths", "psychopaths", + "piankillers", "painkillers", + "pilgrimmage", "pilgrimage", + "pitchforcks", "pitchforks", + "pitchforkes", "pitchforks", + "plaestinian", "palestinian", + "plagiariasm", "plagiarism", + "planeswaker", "planeswalker", + "planeswaler", "planeswalker", + "planeswalkr", "planeswalker", + "platfromers", "platformer", + "playhtrough", "playthrough", + "playthorugh", "playthrough", + "playthourgh", "playthrough", + "playthroguh", "playthroughs", + "playthrougs", "playthroughs", + "playthrouhg", "playthroughs", + "playthtough", "playthrough", + "playtrhough", "playthrough", + "ploretariat", "proletariat", + "policitally", "politically", + "policitians", "politicians", + "politicains", "politicians", + "politicanti", "politician", + "politiciens", "politicians", + "politiicans", "politician", + "polititians", "politicians", + "polyphonyic", "polyphonic", + "pomegranite", "pomegranate", + "popluations", "populations", + "poportional", "proportional", + "popoulation", "population", + "porjectiles", "projectiles", + "porletariat", "proletariat", + "pornagraphy", "pornography", + "pornograghy", "pornography", + "pornograhpy", "pornography", + "pornograpgy", "pornography", + "pornogrophy", "pornography", + "pornogrpahy", "pornography", + "porportions", "proportions", + "portestants", "protestants", + "portuguease", "portuguese", + "portuguesse", "portuguese", + "positionial", "positional", + "positionnal", "positional", + "positionned", "positioned", + "positiveity", "positivity", + "positiviely", "positively", + "positivisme", "positives", + "positivisty", "positivity", + "positivitey", "positivity", + "positivitiy", "positivity", + "possesseurs", "possesses", + "possesssion", "possessions", + "possestions", "possessions", + "possiblilty", "possibility", + "potencially", "potentially", + "potentailly", "potentially", + "powerhourse", "powerhouse", + "powerlifing", "powerlifting", + "powerliftng", "powerlifting", + "pracitcally", "practically", + "practicarlo", "practical", + "practioners", "practitioners", + "practitions", "practitioners", + "pragmatisch", "pragmatic", + "precausions", "precautions", + "precedessor", "predecessor", + "precendence", "precedence", + "precentages", "percentages", + "preconceved", "preconceived", + "preconcieve", "preconceived", + "precuations", "precautions", + "predacessor", "predecessor", + "predecesser", "predecessor", + "predections", "predictions", + "predescesor", "predecessors", + "predesessor", "predecessors", + "predesposed", "predisposed", + "predessecor", "predecessor", + "predicatble", "predictable", + "predicement", "predicament", + "predicessor", "predecessor", + "prediciment", "predicament", + "predicitons", "predictions", + "predictible", "predictable", + "predictious", "predictions", + "predictment", "predicament", + "predisposte", "predisposed", + "predocessor", "predecessor", + "preferabbly", "preferably", + "preferabely", "preferable", + "preferabley", "preferably", + "preferablly", "preferably", + "preferances", "preferences", + "preferenser", "preferences", + "preferental", "preferential", + "preferentes", "preferences", + "preferrably", "preferably", + "preferrring", "preferring", + "preformance", "performance", + "pregnanices", "pregnancies", + "pregnencies", "pregnancies", + "pregorative", "prerogative", + "preipherals", "peripherals", + "prejudicies", "prejudice", + "preleminary", "preliminary", + "prelimanary", "preliminary", + "prelimenary", "preliminary", + "premanently", "permanently", + "prematuraly", "prematurely", + "prematurily", "prematurely", + "prematurley", "prematurely", + "premilinary", "preliminary", + "premissible", "permissible", + "premissions", "permissions", + "preorderded", "preordered", + "preorderers", "preorders", + "preparacion", "preparation", + "preperation", "preparation", + "prepetrated", "perpetrated", + "prepetrator", "perpetrator", + "prepetually", "perpetually", + "prepetuated", "perpetuated", + "prepetuates", "perpetuates", + "preporation", "preparation", + "preposterus", "preposterous", + "prerequesit", "prerequisite", + "prerequiste", "prerequisite", + "prerequites", "prerequisite", + "prerogitive", "prerogative", + "prerogotive", "prerogative", + "prescripton", "prescription", + "presecution", "persecution", + "presedintia", "presidential", + "presentaion", "presentation", + "presentatin", "presentations", + "preservaton", "preservation", + "preservered", "preserved", + "presidencey", "presidency", + "presidental", "presidential", + "presidentcy", "presidency", + "presistence", "persistence", + "presitgious", "prestigious", + "presitigous", "prestigious", + "presomption", "presumption", + "prespective", "perspective", + "pressureing", "pressuring", + "prestegious", "prestigious", + "prestigeous", "prestigious", + "prestigieus", "prestigious", + "prestigiosa", "prestigious", + "prestigiose", "prestigious", + "prestigiosi", "prestigious", + "prestigioso", "prestigious", + "prestiguous", "prestigious", + "presumabely", "presumably", + "presumabley", "presumably", + "presumptous", "presumptuous", + "presumptuos", "presumptuous", + "pretencious", "pretentious", + "pretendendo", "pretended", + "pretensious", "pretentious", + "pretentieus", "pretentious", + "prevailaing", "prevailing", + "prevailling", "prevailing", + "preventitve", "preventative", + "preventivno", "prevention", + "primatively", "primitively", + "princessses", "princesses", + "principales", "principles", + "principalis", "principals", + "principielt", "principle", + "privatizied", "privatized", + "priveledges", "privileges", + "privelleges", "privileges", + "privilegeds", "privileges", + "privilegied", "privileged", + "privilegien", "privilege", + "privilegier", "privilege", + "privilegies", "privilege", + "proactivley", "proactive", + "probabilaty", "probability", + "probabilite", "probabilities", + "probalibity", "probability", + "probelmatic", "problematic", + "problamatic", "problematic", + "problimatic", "problematic", + "problomatic", "problematic", + "proccedings", "proceedings", + "proccessing", "processing", + "proceddings", "proceedings", + "procedureal", "procedural", + "procedurial", "procedural", + "procedurile", "procedure", + "processesor", "processors", + "processeurs", "processes", + "processsors", "processors", + "procrastion", "procreation", + "procriation", "procreation", + "prodcutions", "productions", + "prodictions", "productions", + "producerats", "producers", + "producitons", "productions", + "productioin", "productions", + "productivos", "productions", + "productivty", "productivity", + "produktions", "productions", + "professinal", "professional", + "professionl", "professionals", + "professoras", "professors", + "professores", "professors", + "professorin", "profession", + "professsion", "professions", + "proficiancy", "proficiency", + "proficienct", "proficient", + "proficienty", "proficiency", + "proficinecy", "proficiency", + "profitabile", "profitable", + "progerssion", "progressions", + "progerssive", "progressives", + "programable", "programmable", + "programmare", "programmer", + "programmars", "programmers", + "programmate", "programme", + "programmets", "programmers", + "programmeur", "programmer", + "programmier", "programmer", + "programmmed", "programme", + "programmmer", "programme", + "progresison", "progressions", + "progressers", "progresses", + "progressief", "progressive", + "progressino", "progressions", + "progressivo", "progression", + "progressoin", "progressions", + "progressvie", "progressives", + "prohabition", "prohibition", + "prohibation", "prohibition", + "prohibicion", "prohibition", + "prohibiteds", "prohibits", + "prohibitied", "prohibited", + "prohibitifs", "prohibits", + "prohibitivo", "prohibition", + "prohibitons", "prohibits", + "prohibitted", "prohibited", + "projecticle", "projectile", + "projectives", "projectiles", + "projectlies", "projectiles", + "prolateriat", "proletariat", + "proletariet", "proletariat", + "proletariot", "proletariat", + "proletaryat", "proletariat", + "proleteriat", "proletariat", + "prolitariat", "proletariat", + "prologomena", "prolegomena", + "promenantly", "prominently", + "promenently", "prominently", + "prometheius", "prometheus", + "prometheous", "prometheus", + "promethesus", "prometheus", + "prometheyus", "prometheus", + "promimently", "prominently", + "prominantly", "prominently", + "prominately", "prominently", + "promiscious", "promiscuous", + "promocional", "promotional", + "promsicuous", "promiscuous", + "pronography", "pornography", + "pronoucning", "pronouncing", + "pronounched", "pronounced", + "pronunciato", "pronunciation", + "propaganada", "propaganda", + "properitary", "proprietary", + "propertiary", "proprietary", + "propertions", "proportions", + "prophechies", "prophecies", + "propiertary", "proprietary", + "propogation", "propagation", + "proponenets", "proponents", + "proponentes", "proponents", + "proporition", "proposition", + "proportians", "proportions", + "proportinal", "proportional", + "proposicion", "proposition", + "propositivo", "proposition", + "propostions", "proportions", + "propreitary", "proprietary", + "propriatary", "proprietary", + "propriatery", "proprietary", + "propriatory", "proprietary", + "proprietery", "proprietary", + "proprietory", "proprietary", + "propriotary", "proprietary", + "proprotions", "proportions", + "propsective", "prospective", + "propulstion", "propulsion", + "prosectuion", "prosecution", + "prosectuors", "prosecutors", + "prosecuters", "prosecutors", + "prosicution", "prosecution", + "prosocution", "prosecution", + "prosperious", "prosperous", + "prospertity", "prosperity", + "prospettive", "prospective", + "prostethics", "prosthetic", + "prosthethic", "prosthetic", + "prostitites", "prostitutes", + "prostitiute", "prostitute", + "prostituate", "prostitute", + "prostitudes", "prostitutes", + "prostituees", "prostitutes", + "prostituion", "prostitution", + "prostitures", "prostitutes", + "prostitutas", "prostitutes", + "prostitutie", "prostitute", + "prostitutin", "prostitution", + "prostitutke", "prostitutes", + "prostituton", "prostitution", + "prostitutos", "prostitutes", + "protability", "portability", + "protaganist", "protagonist", + "protaginist", "protagonist", + "protagnoist", "protagonist", + "protagoinst", "protagonists", + "protagonits", "protagonists", + "protagonsit", "protagonists", + "protectings", "protections", + "protectoras", "protectors", + "protectores", "protectors", + "protectrons", "protections", + "protelariat", "proletariat", + "protestents", "protestants", + "protistants", "protestants", + "protoganist", "protagonist", + "protogonist", "protagonist", + "protostants", "protestants", + "protototype", "prototype", + "provacative", "provocative", + "provacotive", "provocative", + "provicative", "provocative", + "providencie", "providence", + "provinciaal", "provincial", + "provinicial", "provincial", + "provisiones", "provisions", + "provoactive", "provocative", + "provocatief", "provocative", + "provocitive", "provocative", + "provocotive", "provocative", + "provokative", "provocative", + "pscyhedelic", "psychedelic", + "pscyhiatric", "psychiatric", + "pscyhopaths", "psychopaths", + "pshyciatric", "psychiatric", + "pshycopaths", "psychopaths", + "psychaitric", "psychiatric", + "psychedilic", "psychedelic", + "psychedleic", "psychedelics", + "psychiatist", "psychiatrist", + "psychidelic", "psychedelic", + "psychodelic", "psychedelic", + "psychopants", "psychopaths", + "psychopatch", "psychopath", + "psychopatic", "psychopathic", + "psychotisch", "psychotic", + "psychriatic", "psychiatric", + "publikation", "publication", + "punctiation", "punctuation", + "puncutation", "punctuation", + "punshiments", "punishments", + "punsihments", "punishments", + "purchaseing", "purchasing", + "purchashing", "purchasing", + "purposefuly", "purposefully", + "pyschedelic", "psychedelic", + "pyschiatric", "psychiatric", + "pyschopaths", "psychopaths", + "qaurterback", "quarterback", + "qualificato", "qualification", + "qualifieres", "qualifiers", + "quantitaive", "quantitative", + "quantitatve", "quantitative", + "quantitites", "quantities", + "quantitties", "quantities", + "quarantaine", "quarantine", + "quarantenni", "quarantine", + "quartercask", "quarterbacks", + "quesitoning", "questioning", + "questionned", "questioned", + "questonable", "questionable", + "radiaoctive", "radioactive", + "radioactice", "radioactive", + "radioactief", "radioactive", + "radioaktive", "radioactive", + "radiocative", "radioactive", + "raidoactive", "radioactive", + "reaccurring", "recurring", + "reactionair", "reactionary", + "realibility", "reliability", + "realistisch", "realistic", + "reaserchers", "researchers", + "reaserching", "researching", + "reasonabley", "reasonably", + "reasonablly", "reasonably", + "reassureing", "reassuring", + "reassurring", "reassuring", + "rebuildling", "rebuilding", + "rebuplicans", "republicans", + "reccomended", "recommended", + "receptionst", "receptionist", + "recgonition", "recognition", + "recgonizing", "recognizing", + "rechargable", "rechargeable", + "recipientes", "recipients", + "reciporcate", "reciprocate", + "recipricate", "reciprocate", + "reciprocant", "reciprocate", + "reciprocite", "reciprocate", + "recivership", "receivership", + "reclutantly", "reluctantly", + "recognicing", "recognizing", + "recognision", "recognition", + "recomending", "recommending", + "recommandes", "recommends", + "recommendes", "recommends", + "recommented", "recommended", + "reconcilled", "reconcile", + "recongition", "recognition", + "recongizing", "recognizing", + "reconsidder", "reconsider", + "recrational", "recreational", + "recrutiment", "recruitment", + "rectangluar", "rectangular", + "rectangualr", "rectangular", + "rectengular", "rectangular", + "recuritment", "recruitment", + "redundantcy", "redundancy", + "reevalulate", "reevaluate", + "reevalutate", "reevaluate", + "reevaulated", "reevaluate", + "refelctions", "reflections", + "referancing", "referencing", + "refereneced", "referenced", + "refereneces", "references", + "referincing", "referencing", + "referrences", "references", + "reflectivos", "reflections", + "refreshener", "refresher", + "refrubished", "refurbished", + "refubrished", "refurbished", + "refurbushed", "refurbished", + "regeneratin", "regeneration", + "regeneraton", "regeneration", + "registerdns", "registers", + "registeries", "registers", + "registerred", "registered", + "registraion", "registration", + "regocnition", "recognition", + "regresssion", "regression", + "regresssive", "regressive", + "regualtions", "regulations", + "regulationg", "regulating", + "regulatiors", "regulators", + "reinassance", "renaissance", + "reinforcemt", "reinforcement", + "reinfornced", "reinforced", + "reinitalise", "reinitialise", + "reinitalize", "reinitialize", + "reinstaling", "reinstalling", + "reinstallng", "reinstalling", + "reisntalled", "reinstalled", + "relaibility", "reliability", + "relatiation", "retaliation", + "relationshp", "relationships", + "relativiser", "relatives", + "relativisme", "relatives", + "relativitiy", "relativity", + "relativitly", "relativity", + "relcutantly", "reluctantly", + "relentlesly", "relentlessly", + "relentlessy", "relentlessly", + "relevations", "revelations", + "relfections", "reflections", + "religeously", "religiously", + "religionens", "religions", + "religioners", "religions", + "relpacement", "replacement", + "reluctently", "reluctantly", + "remarkabley", "remarkably", + "remarkablly", "remarkably", + "remasterred", "remastered", + "remembrence", "remembrance", + "reminescent", "reminiscent", + "reminicient", "reminiscent", + "reminiscant", "reminiscent", + "reminiscint", "reminiscent", + "reminscient", "reminiscent", + "reminsicent", "reminiscent", + "renaiisance", "renaissance", + "renaiscance", "renaissance", + "renaissanse", "renaissance", + "renaissence", "renaissance", + "renassaince", "renaissance", + "renassiance", "renaissance", + "reniassance", "renaissance", + "rennovating", "renovating", + "rennovation", "renovation", + "repalcement", "replacement", + "repbulicans", "republicans", + "repeateadly", "repeatedly", + "repectively", "respectively", + "repersented", "represented", + "replacemnet", "replacements", + "replacemnts", "replacements", + "repleacable", "replaceable", + "repositiory", "repository", + "representas", "represents", + "representes", "represents", + "represssion", "repression", + "reproducion", "reproduction", + "reproducive", "reproductive", + "repsectable", "respectable", + "repsonsible", "responsible", + "repsonsibly", "responsibly", + "republcians", "republicans", + "republician", "republican", + "republicons", "republicans", + "repuglicans", "republicans", + "requeriment", "requirement", + "requierment", "requirements", + "resemblence", "resemblance", + "resemblense", "resembles", + "reserachers", "researchers", + "reseraching", "researching", + "resgination", "resignation", + "residencial", "residential", + "residentail", "residential", + "residentual", "residential", + "resignacion", "resignation", + "resignating", "resignation", + "resignement", "resignment", + "resignition", "resignation", + "resintalled", "reinstalled", + "resistansen", "resistances", + "resistanses", "resistances", + "resistences", "resistances", + "resistnaces", "resistances", + "resoltuions", "resolutions", + "resotration", "restoration", + "resoultions", "resolutions", + "respecatble", "respectable", + "respectabil", "respectable", + "respectfuly", "respectfully", + "respectible", "respectable", + "respectivly", "respectively", + "respectuful", "respectful", + "respektable", "respectable", + "resperatory", "respiratory", + "resperitory", "respiratory", + "respiritory", "respiratory", + "respitatory", "respiratory", + "responcible", "responsible", + "responcibly", "responsibly", + "respondendo", "responded", + "responisble", "responsible", + "responisbly", "responsibly", + "responsable", "responsible", + "responsably", "responsibly", + "responsbile", "responsible", + "responsbily", "responsibly", + "responsibel", "responsibly", + "responsibil", "responsibly", + "responsivle", "responsive", + "resporatory", "respiratory", + "respository", "repository", + "respriatory", "respiratory", + "ressembling", "resembling", + "ressurected", "resurrected", + "restaraunts", "restaurants", + "restaruants", "restaurants", + "restauraunt", "restaurant", + "restaurents", "restaurants", + "resteraunts", "restaurants", + "restirction", "restriction", + "restorarion", "restoration", + "restorating", "restoration", + "restrainted", "restrained", + "restrective", "restrictive", + "restriccion", "restriction", + "restricitng", "restricting", + "restriciton", "restrictions", + "restricitve", "restrictive", + "restricteds", "restricts", + "restricters", "restricts", + "restrictied", "restrictive", + "restrictifs", "restricts", + "restrictins", "restricts", + "restrictios", "restricts", + "restrictivo", "restriction", + "restrictons", "restricts", + "restriktion", "restriction", + "restriktive", "restrictive", + "restrittive", "restrictive", + "restructing", "restricting", + "restruction", "restriction", + "restuarants", "restaurants", + "resturaunts", "restaurants", + "resurecting", "resurrecting", + "resurrecion", "resurrection", + "retailation", "retaliation", + "retalitated", "retaliated", + "retardathon", "retardation", + "retardating", "retardation", + "retardatron", "retardation", + "retartation", "retardation", + "retirbution", "retribution", + "retrebution", "retribution", + "retribucion", "retribution", + "retribuiton", "retribution", + "retributivo", "retribution", + "retribvtion", "retribution", + "retrobution", "retribution", + "retrubution", "retribution", + "revealtions", "revelations", + "revelaitons", "revelations", + "revolations", "revolutions", + "revoultions", "revolutions", + "ridiculious", "ridiculous", + "ridiculosly", "ridiculously", + "ridiculouly", "ridiculously", + "ridiculousy", "ridiculously", + "rightfullly", "rightfully", + "rolepalying", "roleplaying", + "romanticaly", "romantically", + "roundabaout", "roundabout", + "roundabount", "roundabout", + "rudimentery", "rudimentary", + "rudimentory", "rudimentary", + "ruidmentary", "rudimentary", + "sacrifacing", "sacrificing", + "sacrificare", "sacrifice", + "sacrificied", "sacrifice", + "sacrificies", "sacrifice", + "sacrifieced", "sacrificed", + "sacrifising", "sacrificing", + "sacrifizing", "sacrificing", + "salughtered", "slaughtered", + "sanctionned", "sanctioned", + "sarcastisch", "sarcastic", + "saskatchewn", "saskatchewan", + "saskatchwan", "saskatchewan", + "satisfacion", "satisfaction", + "satisfacory", "satisfactory", + "scandanavia", "scandinavia", + "scandanivia", "scandinavian", + "scandenavia", "scandinavia", + "scandianvia", "scandinavian", + "scandimania", "scandinavia", + "scandinaiva", "scandinavian", + "scandinavan", "scandinavian", + "scandivania", "scandinavian", + "scandonavia", "scandinavia", + "scarificing", "sacrificing", + "scheduleing", "scheduling", + "schedulling", "scheduling", + "schoalrship", "scholarships", + "scholarhips", "scholarship", + "scholarstic", "scholastic", + "scholership", "scholarship", + "scholorship", "scholarship", + "scientiests", "scientists", + "scnadinavia", "scandinavia", + "scrambleing", "scrambling", + "screenshoot", "screenshot", + "seamlessley", "seamlessly", + "sedentarity", "sedentary", + "seflishness", "selfishness", + "segergation", "segregation", + "segragation", "segregation", + "segregacion", "segregation", + "segretation", "segregation", + "segrigation", "segregation", + "selectivley", "selectively", + "selfeshness", "selfishness", + "senitmental", "sentimental", + "sensacional", "sensational", + "sensasional", "sensational", + "sensationel", "sensational", + "sensetional", "sensational", + "sensitivety", "sensitivity", + "sentamental", "sentimental", + "sentemental", "sentimental", + "sentenceing", "sentencing", + "sentimentos", "sentiments", + "sentimentul", "sentimental", + "separatedly", "separately", + "separatelly", "separately", + "separatisme", "separates", + "separatiste", "separates", + "sepculating", "speculating", + "serivceable", "serviceable", + "serviciable", "serviceable", + "settelement", "settlement", + "settelments", "settlements", + "settlemetns", "settlements", + "sexualizied", "sexualized", + "shakeapeare", "shakespeare", + "shakepseare", "shakespeare", + "shakesphere", "shakespeare", + "shanenigans", "shenanigans", + "shareholdes", "shareholders", + "sharpeneing", "sharpening", + "sharpenning", "sharpening", + "shatterling", "shattering", + "shatterring", "shattering", + "sheakspeare", "shakespeare", + "shenadigans", "shenanigans", + "shenanagans", "shenanigans", + "shenanagins", "shenanigans", + "shenanegans", "shenanigans", + "shenanegins", "shenanigans", + "shenangians", "shenanigans", + "shenanigens", "shenanigans", + "shenanigins", "shenanigans", + "shenenigans", "shenanigans", + "sheninigans", "shenanigans", + "shennaigans", "shenanigans", + "shortenning", "shortening", + "shortenting", "shortening", + "signficiant", "significant", + "signifantly", "significantly", + "significane", "significance", + "significato", "significant", + "signifigant", "significant", + "signifikant", "significant", + "signitories", "signatories", + "signularity", "singularity", + "similarites", "similarities", + "similarlity", "similarity", + "similiarity", "similarity", + "simluations", "simulations", + "simplefying", "simplifying", + "simplicitly", "simplicity", + "simplifiing", "simplifying", + "simplisitic", "simplistic", + "simplyifing", "simplifying", + "simualtions", "simulations", + "simulatious", "simulations", + "simultaneos", "simultaneous", + "simultaneus", "simultaneous", + "simultanous", "simultaneous", + "singluarity", "singularity", + "singualrity", "singularity", + "singulairty", "singularity", + "singularily", "singularity", + "sitautional", "situational", + "situacional", "situational", + "situationly", "situational", + "siutational", "situational", + "skatebaords", "skateboard", + "skateboader", "skateboard", + "skepticisim", "skepticism", + "skillshoots", "skillshots", + "skillshosts", "skillshots", + "slaugthered", "slaughtered", + "slefishness", "selfishness", + "sluaghtered", "slaughtered", + "smarthpones", "smartphones", + "snowboaring", "snowboarding", + "snowbolling", "snowballing", + "snowfalling", "snowballing", + "socailizing", "socializing", + "socialicing", "socializing", + "socialistes", "socialists", + "socialistos", "socialists", + "socializare", "socialize", + "sociapathic", "sociopathic", + "sociologial", "sociological", + "sociopathes", "sociopaths", + "sociopathis", "sociopaths", + "sociophatic", "sociopathic", + "solidariety", "solidarity", + "somethingis", "somethings", + "sorrounding", "surrounding", + "soundtrakcs", "soundtracks", + "southamtpon", "southampton", + "southanpton", "southampton", + "southapmton", "southampton", + "southernese", "southerners", + "southerness", "southerners", + "southernest", "southerners", + "southernors", "southerners", + "southmapton", "southampton", + "southtampon", "southampton", + "soveregnity", "sovereignty", + "sovereighty", "sovereignty", + "sovereingty", "sovereignty", + "sovereinity", "sovereignty", + "soveriegnty", "sovereignty", + "soveriengty", "sovereignty", + "soverignity", "sovereignty", + "specailists", "specialists", + "specailized", "specialized", + "specailizes", "specializes", + "specatcular", "spectacular", + "specialiced", "specialized", + "specialices", "specializes", + "specialites", "specializes", + "speciallist", "specialist", + "speciallity", "specially", + "speciallize", "specialize", + "specialzied", "specialized", + "specifcally", "specifically", + "specificaly", "specifically", + "specificato", "specification", + "specificies", "specifics", + "specifiying", "specifying", + "specilaized", "specialize", + "speciliazed", "specialize", + "spectatores", "spectators", + "spectatular", "spectacular", + "spectauclar", "spectacular", + "spectaulars", "spectaculars", + "spectecular", "spectacular", + "specualting", "speculating", + "specualtion", "speculation", + "specualtive", "speculative", + "specularite", "speculative", + "speculaties", "speculative", + "spiritualiy", "spiritually", + "spiritualty", "spirituality", + "spirituella", "spiritually", + "spirtiually", "spiritually", + "spirutually", "spiritually", + "spitirually", "spiritually", + "sponatenous", "spontaneous", + "sponatneous", "spontaneous", + "sponsership", "sponsorship", + "sponsorhips", "sponsorship", + "sponsorhsip", "sponsorship", + "sponsorshop", "sponsorship", + "spontaenous", "spontaneous", + "spontainous", "spontaneous", + "spontaneuos", "spontaneous", + "spontanious", "spontaneous", + "sponteanous", "spontaneous", + "sponteneous", "spontaneous", + "spreadhseet", "spreadsheet", + "spreadsheat", "spreadsheet", + "spreadshets", "spreadsheets", + "spreedsheet", "spreadsheet", + "springfeild", "springfield", + "springfiled", "springfield", + "sprinklered", "sprinkled", + "squirrelies", "squirrels", + "squirrelius", "squirrels", + "stabilizare", "stabilize", + "stabilizied", "stabilize", + "stabilizier", "stabilize", + "stabilizies", "stabilize", + "staggerring", "staggering", + "staggerwing", "staggering", + "stationairy", "stationary", + "stationerad", "stationed", + "stationnary", "stationary", + "statisitcal", "statistical", + "statisticly", "statistical", + "statistisch", "statistics", + "statsitical", "statistical", + "stereotpyes", "stereotypes", + "stereotying", "stereotyping", + "steriotypes", "stereotypes", + "steroetypes", "stereotypes", + "steryotypes", "stereotypes", + "stimluating", "stimulating", + "stimualting", "stimulating", + "stimualtion", "stimulation", + "stimulantes", "stimulants", + "stockpilled", "stockpile", + "stormfrount", "stormfront", + "storyteling", "storytelling", + "straightden", "straightened", + "straightend", "straightened", + "straightmen", "straighten", + "straightned", "straightened", + "straightner", "straighten", + "strangeshit", "strangest", + "strategisch", "strategic", + "strategiske", "strategies", + "strawberies", "strawberries", + "strawberrry", "strawberry", + "strawbrerry", "strawberry", + "strenghened", "strengthened", + "strenghtend", "strengthen", + "strenghtens", "strengthen", + "strengtened", "strengthened", + "structurels", "structures", + "strugglebus", "struggles", + "struggleing", "struggling", + "stubborness", "stubbornness", + "stutterring", "stuttering", + "subcatagory", "subcategory", + "subconscius", "subconscious", + "subconscous", "subconscious", + "subisdizing", "subsidizing", + "subjectivly", "subjectively", + "submergered", "submerged", + "submisisons", "submissions", + "subredddits", "subreddits", + "subscirbers", "subscribers", + "subscribbed", "subscribe", + "subscribber", "subscriber", + "subscriping", "subscribing", + "subscriptin", "subscriptions", + "subscripton", "subscription", + "subsequenty", "subsequently", + "subsidiezed", "subsidized", + "subsidizied", "subsidized", + "subsidizies", "subsidize", + "subsiziding", "subsidizing", + "subsquently", "subsequently", + "subsrcibers", "subscribers", + "substancial", "substantial", + "substansial", "substantial", + "substansive", "substantive", + "substantied", "substantive", + "substanties", "substantive", + "substential", "substantial", + "substitiute", "substitute", + "substituded", "substituted", + "substitudes", "substitutes", + "substituion", "substitution", + "substitures", "substitutes", + "substitutie", "substitutes", + "substitutos", "substitutes", + "substitutue", "substitutes", + "substracted", "subtracted", + "suburburban", "suburban", + "succesfully", "successfully", + "successeurs", "successes", + "successfull", "successful", + "successfuly", "successfully", + "successsion", "succession", + "successully", "successfully", + "succsesfull", "successfully", + "sucessfully", "successfully", + "sucseptible", "susceptible", + "sufficently", "sufficiently", + "suggestieve", "suggestive", + "sumbissions", "submissions", + "sunglassses", "sunglasses", + "superceeded", "superseded", + "superficiel", "superficial", + "superfulous", "superfluous", + "superhereos", "superhero", + "superifical", "superficial", + "superiorest", "superiors", + "supermacist", "supremacist", + "supermakert", "supermarkets", + "supermakret", "supermarkets", + "supermakter", "supermarkets", + "supermarkts", "supermarkets", + "supermaster", "supermarkets", + "supernatual", "supernatural", + "supersition", "supervision", + "superstiton", "superstition", + "supervisers", "supervisors", + "supervisior", "supervisor", + "suplimented", "supplemented", + "supplaments", "supplements", + "supplemetal", "supplemental", + "supporteurs", "supporters", + "supposedely", "supposedly", + "supposidely", "supposedly", + "supposingly", "supposedly", + "suppresions", "suppression", + "suppresssor", "suppressor", + "supramacist", "supremacist", + "supremacits", "supremacist", + "supremasist", "supremacist", + "supremicist", "supremacist", + "suprimacist", "supremacist", + "suprisingly", "surprisingly", + "suprizingly", "surprisingly", + "suroundings", "surroundings", + "surpemacist", "supremacist", + "surprisinly", "surprisingly", + "surreptious", "surreptitious", + "surroundign", "surroundings", + "surroundigs", "surrounds", + "surroundins", "surrounds", + "surroundngs", "surrounds", + "surveilence", "surveillance", + "survivabily", "survivability", + "susbtantial", "substantial", + "susbtantive", "substantive", + "suscepitble", "susceptible", + "susceptable", "susceptible", + "suscpetible", "susceptible", + "susecptible", "susceptible", + "suspectible", "susceptible", + "suspiciosly", "suspiciously", + "suspiciouly", "suspiciously", + "suspiciouns", "suspicion", + "suspicision", "suspicions", + "suspicisons", "suspicions", + "sustainible", "sustainable", + "switerzland", "switzerland", + "switserland", "switzerland", + "switzlerand", "switzerland", + "swizterland", "switzerland", + "swtizerland", "switzerland", + "symapthetic", "sympathetic", + "symmertical", "symmetrical", + "sympathatic", "sympathetic", + "sympathiers", "sympathizers", + "sympathsize", "sympathize", + "sympethetic", "sympathetic", + "symphatetic", "sympathetic", + "symphatized", "sympathize", + "symphatizer", "sympathizers", + "symphatizes", "sympathize", + "sympothetic", "sympathetic", + "synthesasia", "synthesis", + "synthesesia", "synthesis", + "sypmathetic", "sympathetic", + "tabelspoons", "tablespoons", + "tablepsoons", "tablespoons", + "tablespooon", "tablespoon", + "tablesppons", "tablespoons", + "tailgateing", "tailgating", + "tailgatting", "tailgating", + "tangentialy", "tangentially", + "techincally", "technically", + "techincians", "technicians", + "techiniques", "techniques", + "techncially", "technically", + "technicalty", "technicality", + "technichian", "technician", + "technicials", "technicians", + "techniciens", "technicians", + "technitians", "technicians", + "technnology", "technology", + "technologia", "technological", + "techticians", "technicians", + "teleportato", "teleportation", + "teleportion", "teleporting", + "teleproting", "teleporting", + "temeprature", "temperature", + "temparament", "temperament", + "temparature", "temperature", + "temparement", "temperament", + "tempearture", "temperatures", + "temperamant", "temperament", + "temperarily", "temporarily", + "temperatues", "temperatures", + "temperaturs", "temperatures", + "temperatuur", "temperature", + "temperement", "temperament", + "tempermeant", "temperament", + "tempertaure", "temperature", + "temporairly", "temporarily", + "temporaraly", "temporarily", + "temporarity", "temporarily", + "tempreature", "temperature", + "temproarily", "temporarily", + "tempurature", "temperature", + "tepmorarily", "temporarily", + "termanology", "terminology", + "terminacion", "termination", + "terminaison", "termination", + "terminalogy", "terminology", + "terminatior", "terminator", + "terminatorn", "termination", + "terminilogy", "terminology", + "terminoligy", "terminology", + "terratorial", "territorial", + "terratories", "territories", + "terretorial", "territorial", + "terretories", "territories", + "terrirorial", "territorial", + "terrirories", "territories", + "terriroties", "territories", + "terristrial", "territorial", + "territoires", "territories", + "territorist", "terrorist", + "territority", "territory", + "terroristas", "terrorists", + "terroristes", "terrorists", + "terrorities", "territories", + "terrotorial", "territorial", + "terrotories", "territories", + "testiclular", "testicular", + "thankfullly", "thankfully", + "thanksgivng", "thanksgiving", + "theoligical", "theological", + "theoratical", "theoretical", + "theoreticly", "theoretical", + "theoritical", "theoretical", + "therapautic", "therapeutic", + "therapeudic", "therapeutic", + "therapeutuc", "therapeutic", + "therapuetic", "therapeutic", + "theraupetic", "therapeutic", + "thereaputic", "therapeutic", + "thereotical", "theoretical", + "therepeutic", "therapeutic", + "thermometor", "thermometer", + "thermometre", "thermometer", + "thermomiter", "thermometer", + "thermomoter", "thermometer", + "thermoneter", "thermometer", + "thermostaat", "thermostat", + "theroetical", "theoretical", + "thoeretical", "theoretical", + "threataning", "threatening", + "threatended", "threatened", + "threatining", "threatening", + "throttleing", "throttling", + "throughoput", "throughput", + "throughtout", "throughout", + "throughtput", "throughput", + "thudnerbolt", "thunderbolt", + "thunberbolt", "thunderbolt", + "thunderblot", "thunderbolt", + "thunderboat", "thunderbolt", + "thunderbots", "thunderbolt", + "thunderbowl", "thunderbolt", + "thunderjolt", "thunderbolt", + "thundervolt", "thunderbolt", + "tightenting", "tightening", + "tocuhscreen", "touchscreen", + "torrentking", "torrenting", + "torrentting", "torrenting", + "torublesome", "troublesome", + "torunaments", "tournaments", + "totalitaran", "totalitarian", + "totalitarni", "totalitarian", + "touranments", "tournaments", + "tournamnets", "tournaments", + "tournemants", "tournaments", + "tournements", "tournaments", + "tournmanets", "tournaments", + "tradicional", "traditional", + "tradionally", "traditionally", + "tradisional", "traditional", + "traditionel", "traditional", + "traditition", "tradition", + "tragicallly", "tragically", + "tramautized", "traumatized", + "tramuatized", "traumatized", + "trancendent", "transcendent", + "trancending", "transcending", + "tranclucent", "translucent", + "trandgender", "transgender", + "tranditions", "transitions", + "tranistions", "transitions", + "tranlastion", "translations", + "tranlsating", "translating", + "tranlsation", "translation", + "tranluscent", "translucent", + "trannsexual", "transsexual", + "tranpshobic", "transphobic", + "transaccion", "transaction", + "transaciton", "transactions", + "transalting", "translating", + "transaltion", "translation", + "transations", "transitions", + "transcluent", "translucent", + "transcripto", "transcription", + "transctions", "transitions", + "transculent", "translucent", + "transending", "transcending", + "transfender", "transgender", + "transferers", "transfers", + "transfering", "transferring", + "transfersom", "transforms", + "transfomers", "transforms", + "transformas", "transforms", + "transformes", "transformers", + "transformis", "transforms", + "transformus", "transforms", + "transforums", "transforms", + "transfromed", "transformed", + "transfromer", "transformers", + "transgemder", "transgender", + "transgended", "transgendered", + "transgenger", "transgender", + "transgenres", "transgender", + "transhpobic", "transphobic", + "transisions", "transitions", + "transisitor", "transistor", + "transistion", "transition", + "transistior", "transistor", + "transitiond", "transitioned", + "transitiong", "transitioning", + "translatron", "translation", + "translusent", "translucent", + "transmatter", "transmitter", + "transmision", "transmission", + "transmissin", "transmissions", + "transmisson", "transmission", + "transmittor", "transmitter", + "transmorged", "transformed", + "transmutter", "transmitter", + "transofrmed", "transformed", + "transohobic", "transphobic", + "transparant", "transparent", + "transparecy", "transparency", + "transpareny", "transparency", + "transperant", "transparent", + "transperent", "transparent", + "transphonic", "transphobic", + "transphopic", "transphobic", + "transplanet", "transplant", + "transporder", "transporter", + "transporing", "transporting", + "transportar", "transporter", + "transportng", "transporting", + "transportor", "transporter", + "transseuxal", "transsexual", + "transsexaul", "transsexual", + "transsexuel", "transsexual", + "transulcent", "translucent", + "transylvnia", "transylvania", + "tranzformer", "transformer", + "tranzitions", "transitions", + "tranzporter", "transporter", + "trasncripts", "transcripts", + "trasnferred", "transferred", + "trasnformed", "transformed", + "trasnformer", "transformer", + "trasngender", "transgender", + "trasnmitted", "transmitted", + "trasnmitter", "transmitter", + "trasnparent", "transparent", + "trasnphobic", "transphobic", + "trasnported", "transported", + "trasnporter", "transporter", + "traumatisch", "traumatic", + "traumetized", "traumatized", + "traumitized", "traumatized", + "travellerhd", "travelled", + "travellodge", "travelled", + "tremendeous", "tremendous", + "tremendious", "tremendous", + "tremenduous", "tremendous", + "trespessing", "trespassing", + "tresspasing", "trespassing", + "triggereing", "triggering", + "triggerring", "triggering", + "troubelsome", "troublesome", + "truamatized", "traumatized", + "trushworthy", "trustworthy", + "trustowrthy", "trustworthy", + "trustwhorty", "trustworthy", + "trustworhty", "trustworthy", + "truthfullly", "truthfully", + "tupperwears", "tupperware", + "turstworthy", "trustworthy", + "ubiquitious", "ubiquitous", + "ubiquituous", "ubiquitous", + "ukraininans", "ukrainians", + "ultimatelly", "ultimately", + "unanimoulsy", "unanimous", + "unappeasing", "unappealing", + "unappeeling", "unappealing", + "unathorised", "unauthorised", + "unattendend", "unattended", + "unatteneded", "unattended", + "unattracive", "unattractive", + "unauthoried", "unauthorized", + "unavailible", "unavailable", + "unavaliable", "unavailable", + "unaviodable", "unavoidable", + "unbalanaced", "unbalanced", + "unbraikable", "unbreakable", + "unbrakeable", "unbreakable", + "unbreakabie", "unbreakable", + "unbreakabke", "unbreakable", + "unbreakbale", "unbreakable", + "unbreakeble", "unbreakable", + "unbrearable", "unbreakable", + "uncensorred", "uncensored", + "uncertaincy", "uncertainty", + "uncertanity", "uncertainty", + "uncertianty", "uncertainty", + "unchangable", "unchangeable", + "uncompetive", "uncompetitive", + "unconcsious", "unconscious", + "unconsicous", "unconscious", + "uncouncious", "unconscious", + "undeniabely", "undeniably", + "undeniabley", "undeniably", + "undeniablly", "undeniably", + "undenialbly", "undeniably", + "underestime", "underestimate", + "undergating", "undertaking", + "undergorund", "underground", + "underheight", "underweight", + "undermiming", "undermining", + "undermindes", "undermines", + "undernearth", "underneath", + "underneight", "underweight", + "underpining", "undermining", + "underpowerd", "underpowered", + "underpowred", "underpowered", + "underratted", "underrated", + "understannd", "understands", + "understsand", "understands", + "undertacker", "undertaker", + "underwarter", "underwater", + "underwieght", "underweight", + "underwright", "underweight", + "undesireble", "undesirable", + "undesriable", "undesirable", + "undetecable", "undetectable", + "undiserable", "undesirable", + "undoubedtly", "undoubtedly", + "undoubetdly", "undoubtedly", + "undoubtadly", "undoubtedly", + "undoubtebly", "undoubtedly", + "undoubtetly", "undoubtedly", + "undreground", "underground", + "unemployeed", "unemployed", + "unemployent", "unemployment", + "unemploymed", "unemployed", + "unexpectdly", "unexpectedly", + "unexpectely", "unexpectedly", + "unfamilliar", "unfamiliar", + "unfortuante", "unfortunate", + "ungreatfull", "ungrateful", + "unilateraly", "unilaterally", + "unilaterlly", "unilaterally", + "unimportent", "unimportant", + "uninspiried", "uninspired", + "uninstaling", "uninstalling", + "uninstallng", "uninstalling", + "uninteresed", "uninterested", + "uniquesness", "uniqueness", + "unisntalled", "uninstalled", + "universella", "universally", + "universites", "universities", + "univesities", "universities", + "unjustifyed", "unjustified", + "unknowinlgy", "unknowingly", + "unkowningly", "unknowingly", + "unnecassary", "unnecessary", + "unneccesary", "unnecessary", + "unnecessery", "unnecessary", + "unnecissary", "unnecessary", + "unnessecary", "unnecessary", + "unnistalled", "uninstalled", + "unoriginial", "unoriginal", + "unorigional", "unoriginal", + "unoticeable", "unnoticeable", + "unpleaseant", "unpleasant", + "unportected", "unprotected", + "unprepaired", "unprepared", + "unpreparred", "unprepared", + "unproducive", "unproductive", + "unprotexted", "unprotected", + "unqaulified", "unqualified", + "unrealisitc", "unrealistic", + "unrealsitic", "unrealistic", + "unreasonbly", "unreasonably", + "unregluated", "unregulated", + "unregualted", "unregulated", + "unregulared", "unregulated", + "unrepentent", "unrepentant", + "unresponive", "unresponsive", + "unrestriced", "unrestricted", + "unsettleing", "unsettling", + "unsintalled", "uninstalled", + "unsolicated", "unsolicited", + "unsoliticed", "unsolicited", + "unsolocited", "unsolicited", + "unsubscirbe", "unsubscribe", + "unsubscrbed", "unsubscribed", + "unsubscried", "unsubscribed", + "unsubscripe", "unsubscribe", + "unsubscrive", "unsubscribe", + "unsubscrube", "unsubscribe", + "unsubsrcibe", "unsubscribe", + "unsuccesful", "unsuccessful", + "unsuccessul", "unsuccessful", + "unsucesfuly", "unsuccessfully", + "unsucessful", "unsuccessful", + "unsunscribe", "unsubscribe", + "unsuprising", "unsurprising", + "unsuprizing", "unsurprising", + "unsurprized", "unsurprised", + "unsusbcribe", "unsubscribe", + "unviersally", "universally", + "unwarrented", "unwarranted", + "utiliatrian", "utilitarian", + "utilitatian", "utilitarian", + "utiliterian", "utilitarian", + "utilizacion", "utilization", + "utilizaiton", "utilization", + "utilizating", "utilization", + "utiltiarian", "utilitarian", + "vacciantion", "vaccination", + "vaccinaties", "vaccinate", + "vegaterians", "vegetarians", + "vegetariens", "vegetarians", + "vegetatians", "vegetarians", + "vegeterians", "vegetarians", + "vehementely", "vehemently", + "venezuelean", "venezuela", + "venezuelian", "venezuela", + "ventalation", "ventilation", + "ventelation", "ventilation", + "ventialtion", "ventilation", + "ventilacion", "ventilation", + "verastility", "versatility", + "verfication", "verification", + "versatality", "versatility", + "versitality", "versatility", + "versitilaty", "versatility", + "victorieuse", "victories", + "victoriuous", "victorious", + "vietnameese", "vietnamese", + "vietnamesse", "vietnamese", + "vietnamiese", "vietnamese", + "vietnamnese", "vietnamese", + "vigilanties", "vigilante", + "visibillity", "visibility", + "vocabularly", "vocabulary", + "volatillity", "volatility", + "volonteered", "volunteered", + "volounteers", "volunteers", + "volunatrily", "voluntarily", + "voluntairly", "voluntarily", + "volunteeers", "volunteers", + "volunteraly", "voluntarily", + "voluntereed", "volunteered", + "volunterily", "voluntarily", + "vulnerabile", "vulnerable", + "wallpapaers", "wallpapers", + "wallpappers", "wallpapers", + "washingtion", "washington", + "watermeleon", "watermelon", + "waterprooof", "waterproof", + "wavelegnths", "wavelength", + "wavelenghth", "wavelength", + "wavelenghts", "wavelength", + "weaknessses", "weaknesses", + "wellingston", "wellington", + "wellingtion", "wellington", + "westernerns", "westerners", + "westmisnter", "westminster", + "westmnister", "westminster", + "westmonster", "westminster", + "whisperered", "whispered", + "whitholding", "withholding", + "wikileakers", "wikileaks", + "willingless", "willingness", + "wincheseter", "winchester", + "windsheilds", "windshield", + "withdrawels", "withdrawals", + "withdrawles", "withdrawals", + "withhelding", "withholding", + "withrdawing", "withdrawing", + "witnesssing", "witnessing", + "woodowrking", "woodworking", + "woodworkign", "woodworking", + "worhsipping", "worshipping", + "workstaiton", "workstation", + "workststion", "workstation", + "worshopping", "worshipping", + "xenophoblic", "xenophobic", + "abandining", "abandoning", + "abandonned", "abandoned", + "abbreviato", "abbreviation", + "abnoramlly", "abnormally", + "abnormalty", "abnormally", + "abnornally", "abnormally", + "abominaton", "abomination", + "abondoning", "abandoning", + "aborginial", "aboriginal", + "aboriganal", "aboriginal", + "aborigenal", "aboriginal", + "aborignial", "aboriginal", + "aborigonal", "aboriginal", + "aboroginal", "aboriginal", + "aboslutely", "absolutely", + "abosrption", "absorption", + "abreviated", "abbreviated", + "absintence", "abstinence", + "absitnence", "abstinence", + "absolument", "absolute", + "absolutley", "absolutely", + "absoprtion", "absorption", + "absorbsion", "absorption", + "absorbtion", "absorption", + "absorpsion", "absorption", + "absoultely", "absolutely", + "abstanence", "abstinence", + "abstenance", "abstinence", + "abstenince", "abstinence", + "abstinense", "abstinence", + "abstinince", "abstinence", + "absurditiy", "absurdity", + "abundacies", "abundances", + "academicas", "academics", + "academicos", "academics", + "academicus", "academics", + "accdiently", "accidently", + "accelarate", "accelerate", + "accelerade", "accelerated", + "accelerare", "accelerate", + "accelerato", "acceleration", + "acceleread", "accelerated", + "accelertor", "accelerator", + "accelorate", "accelerate", + "acceptabel", "acceptable", + "acceptabil", "acceptable", + "acceptence", "acceptance", + "accepterad", "accepted", + "acceptible", "acceptable", + "accerelate", "accelerated", + "accesories", "accessories", + "accessable", "accessible", + "accessbile", "accessible", + "accessoire", "accessories", + "accessoirs", "accessories", + "accicently", "accidently", + "accidantly", "accidently", + "accidebtly", "accidently", + "accidenlty", "accidently", + "accidentes", "accidents", + "accidentky", "accidently", + "accidently", "accidentally", + "accidnetly", "accidently", + "accomadate", "accommodate", + "accomodate", "accommodate", + "accompined", "accompanied", + "accomplise", "accomplishes", + "accompliss", "accomplishes", + "accostumed", "accustomed", + "accountent", "accountant", + "accpetable", "acceptable", + "accpetance", "acceptance", + "accuastion", "accusation", + "acculumate", "accumulate", + "accumalate", "accumulate", + "accumelate", "accumulate", + "accumilate", "accumulate", + "accumulare", "accumulate", + "accumulato", "accumulation", + "accumulted", "accumulated", + "accuratley", "accurately", + "accusating", "accusation", + "accusition", "accusation", + "accustumed", "accustomed", + "acheivable", "achievable", + "acheivment", "achievement", + "acheviable", "achievable", + "achiavable", "achievable", + "achieveble", "achievable", + "achievemnt", "achievement", + "achievemts", "achieves", + "achievents", "achieves", + "achievment", "achievement", + "achilleous", "achilles", + "achiveable", "achievable", + "achivement", "achievement", + "acitvating", "activating", + "acitvision", "activision", + "acknowldge", "acknowledge", + "acknowlede", "acknowledge", + "acknowlege", "acknowledge", + "acommodate", "accommodate", + "acopalypse", "apocalypse", + "acordingly", "accordingly", + "acqauinted", "acquainted", + "acquanited", "acquainted", + "acquianted", "acquainted", + "acquinated", "acquainted", + "acquisiton", "acquisition", + "acticating", "activating", + "actication", "activation", + "activacion", "activation", + "activaters", "activates", + "activiates", "activist", + "activiites", "activist", + "activisiom", "activism", + "activisits", "activist", + "activistas", "activists", + "activistes", "activists", + "activiting", "activating", + "activizion", "activision", + "acustommed", "accustomed", + "adaptacion", "adaptation", + "adaptating", "adaptation", + "adaquetely", "adequately", + "addicitons", "addictions", + "addionally", "additionally", + "additivies", "additive", + "additivley", "additive", + "addittions", "addictions", + "addmission", "admission", + "addresable", "addressable", + "addressess", "addresses", + "adequatley", "adequately", + "adequetely", "adequately", + "adequitely", "adequately", + "adernaline", "adrenaline", + "adjectivos", "adjectives", + "adjustible", "adjustable", + "admendment", "amendment", + "administed", "administered", + "administor", "administer", + "administre", "administer", + "administro", "administer", + "adminsiter", "administer", + "admissable", "admissible", + "admittadly", "admittedly", + "admittetly", "admittedly", + "admittidly", "admittedly", + "adolencent", "adolescent", + "adolescant", "adolescent", + "adolescene", "adolescence", + "adoloscent", "adolescent", + "adolsecent", "adolescent", + "adpatation", "adaptation", + "adreanline", "adrenaline", + "adrelanine", "adrenaline", + "adreneline", "adrenaline", + "adreniline", "adrenaline", + "adressable", "addressable", + "advanteges", "advantages", + "advatanges", "advantages", + "adventrous", "adventurous", + "adventrues", "adventures", + "adventuers", "adventures", + "adventuous", "adventurous", + "adventuros", "adventurous", + "adventurus", "adventurous", + "adverticed", "advertised", + "aestethics", "aesthetics", + "aesthatics", "aesthetics", + "aesthestic", "aesthetics", + "affiliaton", "affiliation", + "affilliate", "affiliate", + "affirmitve", "affirmative", + "afflcition", "affliction", + "afflection", "affliction", + "affliation", "affliction", + "affliciton", "affliction", + "afforadble", "affordable", + "affordible", "affordable", + "affortable", "affordable", + "africaners", "africans", + "africaness", "africans", + "aftermaket", "aftermarket", + "afternooon", "afternoon", + "aggravanti", "aggravating", + "aggraveted", "aggravated", + "aggreement", "agreement", + "aggregious", "egregious", + "aggresions", "aggression", + "aggressivo", "aggression", + "aggrovated", "aggravated", + "agnosticim", "agnosticism", + "agnosticsm", "agnosticism", + "agnostisch", "agnostic", + "agnostiscm", "agnosticism", + "agnostisim", "agnosticism", + "agreeement", "agreement", + "agricultre", "agriculture", + "agricultue", "agriculture", + "agriculure", "agriculture", + "agricuture", "agriculture", + "ailenating", "alienating", + "ajdectives", "adjectives", + "alchoholic", "alcoholic", + "alchoolism", "alcoholism", + "alcohalics", "alcoholics", + "alcohalism", "alcoholism", + "alcoholsim", "alcoholism", + "aleinating", "alienating", + "algorhitms", "algorithms", + "algorithem", "algorithm", + "algorithim", "algorithm", + "algorithsm", "algorithms", + "algorithum", "algorithm", + "algorithym", "algorithm", + "algoritmes", "algorithms", + "algoritmos", "algorithms", + "algorthims", "algorithms", + "algortihms", "algorithms", + "algorythms", "algorithms", + "alievating", "alienating", + "alledgedly", "allegedly", + "allegeance", "allegiance", + "allegedely", "allegedly", + "allegedley", "allegedly", + "allegience", "allegiance", + "alleigance", "allegiance", + "allergisch", "allergic", + "alliegance", "allegiance", + "alligeance", "allegiance", + "alocholics", "alcoholics", + "alocholism", "alcoholism", + "alogrithms", "algorithms", + "alphabeast", "alphabet", + "alteracion", "alteration", + "alterarion", "alteration", + "alterating", "alteration", + "alternador", "alternator", + "alternater", "alternator", + "alternatie", "alternatives", + "alternatly", "alternately", + "alternatve", "alternate", + "alternetly", "alternately", + "altogehter", "altogether", + "altogheter", "altogether", + "altriustic", "altruistic", + "altruisitc", "altruistic", + "altrusitic", "altruistic", + "alturistic", "altruistic", + "aluminimum", "aluminum", + "amargeddon", "armageddon", + "amateurest", "amateurs", + "ambassabor", "ambassador", + "ambassader", "ambassador", + "ambassator", "ambassador", + "ambassedor", "ambassador", + "ambassidor", "ambassador", + "ambassodor", "ambassador", + "ambiguitiy", "ambiguity", + "amendmants", "amendments", + "amendmends", "amendments", + "americains", "americas", + "americanas", "americans", + "americanis", "americas", + "americanss", "americas", + "americants", "americas", + "americanus", "americans", + "americares", "americas", + "ammendment", "amendment", + "amrageddon", "armageddon", + "analitical", "analytical", + "analitycal", "analytical", + "analogeous", "analogous", + "analyitcal", "analytical", + "analyseles", "analyses", + "analyseras", "analyses", + "analyseres", "analyses", + "analysised", "analyses", + "analysises", "analyses", + "analysisto", "analysts", + "analystics", "analysts", + "anarchisim", "anarchism", + "anarchistm", "anarchism", + "anarchiszm", "anarchism", + "anarchsits", "anarchists", + "anayltical", "analytical", + "ancilliary", "ancillary", + "androiders", "androids", + "androidtvs", "androids", + "anecdotale", "anecdote", + "anecdotice", "anecdote", + "anestheisa", "anesthesia", + "anesthetia", "anesthesia", + "anesthisia", "anesthesia", + "anitbiotic", "antibiotic", + "anitquated", "antiquated", + "anitsocial", "antisocial", + "aniversary", "anniversary", + "annilihate", "annihilated", + "anniverary", "anniversary", + "anniversay", "anniversary", + "anniversry", "anniversary", + "annointing", "anointing", + "annonceurs", "announcers", + "annoucners", "announcers", + "annoucning", "announcing", + "announched", "announce", + "annyoingly", "annoyingly", + "anonymosly", "anonymously", + "anonymousy", "anonymously", + "antaganist", "antagonist", + "antagnoist", "antagonist", + "antarcitca", "antarctica", + "antarctida", "antarctica", + "anthropoly", "anthropology", + "antibiodic", "antibiotic", + "antibiotcs", "antibiotics", + "antibitoic", "antibiotic", + "antiboitic", "antibiotics", + "anticapate", "anticipate", + "anticiapte", "anticipate", + "anticipare", "anticipate", + "anticipato", "anticipation", + "anticuated", "antiquated", + "antiquited", "antiquated", + "antiqvated", "antiquated", + "antisipate", "anticipate", + "antisocail", "antisocial", + "antisosial", "antisocial", + "antoganist", "antagonist", + "antractica", "antarctica", + "apacolypse", "apocalypse", + "apartheied", "apartheid", + "aplication", "application", + "apocalipse", "apocalypse", + "apocalpyse", "apocalypse", + "apocalypes", "apocalypse", + "apocalypic", "apocalyptic", + "apocalyspe", "apocalypse", + "apocalytic", "apocalyptic", + "apocaplyse", "apocalypse", + "apocolapse", "apocalypse", + "apolagetic", "apologetic", + "apolagized", "apologized", + "apolegetic", "apologetic", + "apoligetic", "apologetic", + "apoligists", "apologists", + "apoligized", "apologized", + "apologisms", "apologists", + "apologiste", "apologise", + "apologitic", "apologetic", + "apostraphe", "apostrophe", + "apostrephe", "apostrophe", + "apostrohpe", "apostrophe", + "apostropes", "apostrophe", + "apparantly", "apparently", + "appareance", "appearance", + "apparenlty", "apparently", + "appartment", "apartment", + "appealling", "appealing", + "appearence", "appearance", + "appearnace", "appearances", + "apperances", "appearances", + "apperantly", "apparently", + "apperciate", "appreciate", + "appereance", "appearance", + "appetities", "appetite", + "appetitite", "appetite", + "appication", "application", + "applainces", "appliances", + "applicaple", "applicable", + "applicates", "applicants", + "applicaton", "application", + "applicible", "applicable", + "appliences", "appliances", + "appointmet", "appointments", + "appologies", "apologies", + "apporached", "approached", + "apporaches", "approaches", + "appraoched", "approached", + "appraoches", "approaches", + "apprecaite", "appreciate", + "appreciato", "appreciation", + "appreciste", "appreciates", + "apprecitae", "appreciates", + "apprecited", "appreciated", + "apprectice", "apprentice", + "appreicate", "appreciate", + "apprendice", "apprentice", + "apprentace", "apprentice", + "apprentise", "apprentice", + "appretiate", "appreciate", + "appretince", "apprentice", + "appriceate", "appreciates", + "appriciate", "appreciate", + "appriecate", "appreciates", + "approacing", "approaching", + "appropiate", "appropriate", + "approprate", "appropriate", + "apropriate", "appropriate", + "aproximate", "approximate", + "apsotrophe", "apostrophe", + "aptitudine", "aptitude", + "aqcuainted", "acquainted", + "aquisition", "acquisition", + "aramgeddon", "armageddon", + "arangement", "arrangement", + "arbitarily", "arbitrarily", + "arbitraily", "arbitrarily", + "arbitraion", "arbitration", + "arbitrairy", "arbitrarily", + "arbitrarly", "arbitrary", + "arbitraton", "arbitration", + "arcehtypes", "archetypes", + "archaelogy", "archaeology", + "archaeolgy", "archaeology", + "archaology", "archeology", + "archatypes", "archetypes", + "archetects", "architects", + "archetipes", "archetypes", + "archetpyes", "archetypes", + "archetypus", "archetypes", + "archeytpes", "archetypes", + "archictect", "architect", + "architechs", "architects", + "architecht", "architect", + "architecte", "architecture", + "architexts", "architects", + "architypes", "archetypes", + "archtiects", "architects", + "archytypes", "archetypes", + "argentinia", "argentina", + "arguements", "arguments", + "argumentas", "arguments", + "argumentos", "arguments", + "arithemtic", "arithmetic", + "arithmitic", "arithmetic", + "aritmethic", "arithmetic", + "armagaddon", "armageddon", + "armageddan", "armageddon", + "armagedden", "armageddon", + "armageddin", "armageddon", + "armagedeon", "armageddon", + "armageedon", "armageddon", + "armagideon", "armageddon", + "armegaddon", "armageddon", + "arrangerad", "arranged", + "arrangment", "arrangement", + "arthimetic", "arithmetic", + "articifial", "artificial", + "articluate", "articulate", + "articualte", "articulate", + "articulted", "articulated", + "artifactos", "artifacts", + "artificiel", "artificial", + "artihmetic", "arithmetic", + "artillerly", "artillery", + "asbestoast", "asbestos", + "asethetics", "aesthetics", + "asisstants", "assistants", + "aspiratons", "aspirations", + "assasinate", "assassinate", + "assassians", "assassin", + "assassinas", "assassins", + "assassines", "assassins", + "assassinos", "assassins", + "assemblare", "assemble", + "assempling", "assembling", + "assersions", "assertions", + "assesement", "assessment", + "assestment", "assessment", + "assigments", "assignments", + "assignemnt", "assignment", + "assimalate", "assimilate", + "assimilant", "assimilate", + "assimilare", "assimilate", + "assimliate", "assimilate", + "assimulate", "assimilate", + "assingment", "assignment", + "assistanat", "assistants", + "assistanse", "assistants", + "assistante", "assistance", + "assistence", "assistance", + "assistendo", "assisted", + "assistents", "assistants", + "assmebling", "assembling", + "assocaited", "associated", + "assocaites", "associates", + "assocation", "association", + "associatie", "associated", + "associatin", "associations", + "associaton", "association", + "associsted", "associates", + "assoicated", "associated", + "assoicates", "associates", + "assosiated", "associated", + "assosiates", "associates", + "asssassans", "assassins", + "assupmtion", "assumptions", + "assymetric", "asymmetric", + "asteroides", "asteroids", + "asthetical", "aesthetical", + "astonising", "astonishing", + "astornauts", "astronauts", + "astranauts", "astronauts", + "astronatus", "astronauts", + "astronaunt", "astronaut", + "astronomia", "astronomical", + "astronouts", "astronauts", + "astronuats", "astronauts", + "asutralian", "australian", + "atatchment", "attachment", + "athleticos", "athletics", + "athleticsm", "athleticism", + "athletiscm", "athleticism", + "athletisim", "athleticism", + "atmopshere", "atmosphere", + "atmoshpere", "atmosphere", + "atomsphere", "atmosphere", + "atriculate", "articulate", + "atrocoties", "atrocities", + "atrosities", "atrocities", + "attachemnt", "attachment", + "attackeras", "attackers", + "attactment", "attachment", + "attemtping", "attempting", + "attendence", "attendance", + "attendents", "attendants", + "attirbutes", "attributes", + "attmepting", "attempting", + "attracters", "attracts", + "attractice", "attractive", + "attracties", "attracts", + "attractifs", "attracts", + "attraktion", "attraction", + "attraktive", "attractive", + "attribuito", "attribution", + "attritubes", "attributes", + "auctioners", "auctions", + "audioboook", "audiobook", + "audioboost", "audiobooks", + "auidobooks", "audiobooks", + "auotattack", "autoattack", + "austrailan", "australian", + "austrailia", "australia", + "australain", "australians", + "australien", "australian", + "australina", "australians", + "austrlaian", "australians", + "authenticy", "authenticity", + "autherized", "authorized", + "authoritay", "authority", + "authorites", "authorities", + "authorithy", "authority", + "authroized", "authorized", + "autistisch", "autistic", + "autoattaks", "autoattack", + "autocorect", "autocorrect", + "autocorrct", "autocorrect", + "autocorret", "autocorrect", + "autograpgh", "autograph", + "automatice", "automate", + "automatico", "automation", + "automatied", "automate", + "automatiek", "automate", + "automatron", "automation", + "automatted", "automate", + "automibile", "automobile", + "automitive", "automotive", + "automoblie", "automobile", + "automomous", "autonomous", + "automonous", "autonomous", + "automotice", "automotive", + "automotion", "automation", + "automotize", "automotive", + "automotove", "automotive", + "autonamous", "autonomous", + "autonation", "automation", + "autonimous", "autonomous", + "autonomity", "autonomy", + "autononous", "autonomous", + "auttoatack", "autoattack", + "auxilliary", "auxiliary", + "availabale", "available", + "availaible", "available", + "availiable", "available", + "averageadi", "averaged", + "averageifs", "averages", + "awesomeley", "awesomely", + "awesomelly", "awesomely", + "awesomenss", "awesomeness", + "awkwardess", "awkwardness", + "babysister", "babysitter", + "babysiting", "babysitting", + "babysittng", "babysitting", + "bachelores", "bachelors", + "backgorund", "background", + "backgroudn", "backgrounds", + "backgrouds", "backgrounds", + "backgrouns", "backgrounds", + "backgruond", "backgrounds", + "backpacing", "backpacking", + "backpackng", "backpacking", + "backrgound", "backgrounds", + "backrounds", "backgrounds", + "baksetball", "basketball", + "balanceada", "balanced", + "balanceado", "balanced", + "balckberry", "blackberry", + "balckhawks", "blackhawks", + "balcksmith", "blacksmith", + "bandwagoon", "bandwagon", + "bangaldesh", "bangladesh", + "bangladash", "bangladesh", + "bangledash", "bangladesh", + "bangledesh", "bangladesh", + "banglidesh", "bangladesh", + "bankrupcty", "bankruptcy", + "bankruptsy", "bankruptcy", + "bankrutpcy", "bankruptcy", + "barabrians", "barbarians", + "barbariens", "barbarians", + "barbarions", "barbarians", + "barbarisch", "barbaric", + "barberians", "barbarians", + "bargianing", "bargaining", + "bartendars", "bartenders", + "basektball", "basketball", + "baskteball", "basketball", + "bastardous", "bastards", + "battelship", "battleship", + "battelstar", "battlestar", + "battlearts", "battlestar", + "battlechip", "battleship", + "battlefied", "battlefield", + "battlefont", "battlefront", + "battlehips", "battleship", + "battlesaur", "battlestar", + "battlescar", "battlestar", + "battleshop", "battleship", + "battlestsr", "battlestar", + "beahviours", "behaviours", + "beautifuly", "beautifully", + "beautilful", "beautifully", + "beautyfull", "beautiful", + "becnhmarks", "benchmarks", + "beethoveen", "beethoven", + "begginings", "beginnings", + "begininngs", "beginnings", + "beginninng", "beginnings", + "behaivours", "behaviours", + "behaviorly", "behavioral", + "behavoiral", "behavioral", + "behavoiurs", "behaviours", + "behavorial", "behavioral", + "behavoural", "behavioral", + "behvaiours", "behaviours", + "beleagured", "beleaguered", + "beleivable", "believable", + "beliavable", "believable", + "beliebable", "believable", + "believeble", "believable", + "beliveable", "believable", + "benchamrks", "benchmarks", + "benchmakrs", "benchmarks", + "benckmarks", "benchmarks", + "benefecial", "beneficial", + "beneficary", "beneficiary", + "beneficiul", "beneficial", + "benefitial", "beneficial", + "beneifical", "beneficial", + "benelovent", "benevolent", + "benevalent", "benevolent", + "benevelant", "benevolent", + "benevelent", "benevolent", + "benevelont", "benevolent", + "benevloent", "benevolent", + "benevolant", "benevolent", + "benificial", "beneficial", + "benovelent", "benevolent", + "bernouilli", "bernoulli", + "besitality", "bestiality", + "bestaility", "bestiality", + "besteality", "bestiality", + "betrayeado", "betrayed", + "bilateraly", "bilaterally", + "billborads", "billboards", + "bioligical", "biological", + "biologiset", "biologist", + "biologiskt", "biologist", + "birghtness", "brightness", + "birmignham", "birmingham", + "birmimgham", "birmingham", + "bisexuella", "bisexual", + "bitterseet", "bittersweet", + "bitterswet", "bittersweet", + "blackahwks", "blackhawks", + "blackbarry", "blackberry", + "blackbeary", "blackberry", + "blackbeery", "blackberry", + "blackcawks", "blackhawks", + "blackhakws", "blackhawks", + "blackhwaks", "blackhawks", + "blackmsith", "blacksmith", + "blackshits", "blacksmith", + "blasphemey", "blasphemy", + "blitzkreig", "blitzkrieg", + "blochchain", "blockchain", + "blockcahin", "blockchain", + "blockchian", "blockchain", + "bloodboner", "bloodborne", + "bloodbonre", "bloodborne", + "bloodborbe", "bloodborne", + "bloodbrone", "bloodborne", + "bloodporne", "bloodborne", + "bloorborne", "bloodborne", + "blueberies", "blueberries", + "blueberris", "blueberries", + "blueberrry", "blueberry", + "bluebrints", "blueprints", + "boardcasts", "broadcasts", + "bodyheight", "bodyweight", + "bodyweigth", "bodyweight", + "bodywieght", "bodyweight", + "bombarment", "bombardment", + "bookmakred", "bookmarked", + "bootlaoder", "bootloader", + "bootleader", "bootloader", + "boradcasts", "broadcasts", + "borderlads", "borderlands", + "borderlans", "borderlands", + "bottelneck", "bottleneck", + "bottlebeck", "bottleneck", + "boundaires", "boundaries", + "bounderies", "boundaries", + "bourgeoius", "bourgeois", + "boycutting", "boycotting", + "boyfirends", "boyfriends", + "boyfreinds", "boyfriends", + "boyfrients", "boyfriends", + "braceletes", "bracelets", + "braceletts", "bracelets", + "brainwased", "brainwashed", + "brakedowns", "breakdowns", + "braodcasts", "broadcasts", + "brasillian", "brazilian", + "bratenders", "bartenders", + "brazilains", "brazilians", + "brazileans", "brazilians", + "braziliaan", "brazilians", + "brazilions", "brazilians", + "brazillans", "brazilians", + "brightoner", "brighten", + "brigthness", "brightness", + "brillaince", "brilliance", + "brilliante", "brilliance", + "brillianty", "brilliantly", + "brimestone", "brimstone", + "brimingham", "birmingham", + "broacasted", "broadcast", + "brotherhod", "brotherhood", + "brotherood", "brotherhood", + "brusselers", "brussels", + "brutallity", "brutally", + "buisnesses", "businesses", + "bulgariska", "bulgaria", + "bulletpoof", "bulletproof", + "bulletprof", "bulletproof", + "bureaucats", "bureaucrats", + "businesman", "businessman", + "businesmen", "businessmen", + "businessen", "businessmen", + "butterfies", "butterflies", + "cabinettas", "cabinets", + "caclulated", "calculated", + "caclulator", "calculator", + "cahracters", "characters", + "calcluator", "calculators", + "calcualted", "calculated", + "calcualtor", "calculator", + "calculador", "calculator", + "calcularon", "calculator", + "calculater", "calculator", + "calculatin", "calculations", + "calibratin", "calibration", + "calibraton", "calibration", + "califnoria", "californian", + "califonria", "californian", + "califorian", "californian", + "califorina", "california", + "californai", "californian", + "califronia", "california", + "caligraphy", "calligraphy", + "caliofrnia", "californian", + "calrifying", "clarifying", + "calssified", "classified", + "caluclated", "calculated", + "caluclator", "calculator", + "caluculate", "calculate", + "cambodican", "cambodia", + "camofluage", "camouflage", + "camoufalge", "camouflage", + "camouglage", "camouflage", + "campaiging", "campaigning", + "campaignes", "campaigns", + "cancellato", "cancellation", + "candidatas", "candidates", + "candidatxs", "candidates", + "candidiate", "candidate", + "canditates", "candidates", + "cannibalsm", "cannibalism", + "cannisters", "canisters", + "cannonical", "canonical", + "capabality", "capability", + "capabiltiy", "capability", + "capacators", "capacitors", + "capaciters", "capacitors", + "capactiors", "capacitors", + "capasitors", "capacitors", + "capatilism", "capitalism", + "capatilist", "capitalist", + "capatilize", "capitalize", + "capialized", "capitalized", + "capicators", "capacitors", + "capitalisn", "capitals", + "capitalits", "capitalists", + "capitalsim", "capitalism", + "capitalsit", "capitalists", + "capitarist", "capitalist", + "capitilism", "capitalism", + "capitilist", "capitalist", + "capitilize", "capitalize", + "capitlaism", "capitalism", + "capitlaist", "capitalist", + "capitlaize", "capitalized", + "capitolism", "capitalism", + "capitolist", "capitalist", + "capitolize", "capitalize", + "captainers", "captains", + "captialism", "capitalism", + "captialist", "capitalist", + "captialize", "capitalize", + "captivitiy", "captivity", + "caraciture", "caricature", + "carciature", "caricature", + "cardinales", "cardinals", + "cardinalis", "cardinals", + "carefullly", "carefully", + "cariacture", "caricature", + "caricatore", "caricature", + "cariciture", "caricature", + "caricuture", "caricature", + "carismatic", "charismatic", + "carribbean", "caribbean", + "cartdridge", "cartridge", + "cartdriges", "cartridges", + "carthagian", "carthaginian", + "cartilidge", "cartilage", + "cartirdges", "cartridges", + "cartrdiges", "cartridges", + "cartriages", "cartridges", + "cartrigdes", "cartridges", + "casaulties", "casualties", + "cassowarry", "cassowary", + "casualites", "casualties", + "casualries", "casualties", + "casulaties", "casualties", + "cataclysim", "cataclysm", + "cataclysym", "cataclysm", + "catagories", "categories", + "catapillar", "caterpillar", + "catapiller", "caterpillar", + "catastrope", "catastrophe", + "catastrphe", "catastrophe", + "categorice", "categorize", + "categoried", "categorized", + "categoriei", "categorize", + "cateogrize", "categorized", + "catepillar", "caterpillar", + "caterpilar", "caterpillar", + "catholicsm", "catholicism", + "catholicus", "catholics", + "catholisim", "catholicism", + "cativating", "activating", + "cattleship", "battleship", + "causalties", "casualties", + "cautionsly", "cautiously", + "celebratin", "celebration", + "celebrites", "celebrities", + "celebritiy", "celebrity", + "cellpading", "cellpadding", + "cellulaire", "cellular", + "cemetaries", "cemeteries", + "censorhsip", "censorship", + "censurship", "censorship", + "centipedle", "centipede", + "ceremonias", "ceremonies", + "ceremoniis", "ceremonies", + "ceremonije", "ceremonies", + "cerimonial", "ceremonial", + "cerimonies", "ceremonies", + "certainity", "certainty", + "certainlyt", "certainty", + "chairtable", "charitable", + "chalenging", "challenging", + "challanged", "challenged", + "challanges", "challenges", + "challegner", "challenger", + "challender", "challenger", + "challengue", "challenger", + "challengur", "challenger", + "challening", "challenging", + "challneger", "challenger", + "chanceller", "chancellor", + "chancillor", "chancellor", + "chansellor", "chancellor", + "charachter", "character", + "charactere", "characterize", + "characterz", "characterize", + "charactors", "characters", + "charakters", "characters", + "charatable", "charitable", + "charecters", "characters", + "charistics", "characteristics", + "charitible", "charitable", + "chartiable", "charitable", + "chechpoint", "checkpoint", + "checkpiont", "checkpoint", + "checkpoins", "checkpoints", + "checkponts", "checkpoints", + "cheesecase", "cheesecake", + "cheesecave", "cheesecake", + "cheeseface", "cheesecake", + "cheezecake", "cheesecake", + "chemcially", "chemically", + "chidlbirth", "childbirth", + "chihuahuha", "chihuahua", + "childbrith", "childbirth", + "childrends", "childrens", + "childrenis", "childrens", + "childrents", "childrens", + "chirstians", "christians", + "chocalates", "chocolates", + "chocloates", "chocolates", + "chocoaltes", "chocolates", + "chocolatie", "chocolates", + "chocolatos", "chocolates", + "chocolatte", "chocolates", + "chocolotes", "chocolates", + "cholestrol", "cholesterol", + "chormosome", "chromosome", + "chornicles", "chronicles", + "chrisitans", "christians", + "christains", "christians", + "christiaan", "christian", + "christimas", "christians", + "christinas", "christians", + "christines", "christians", + "christmans", "christians", + "chromasome", "chromosome", + "chromesome", "chromosome", + "chromisome", "chromosome", + "chromosmes", "chromosomes", + "chromosoms", "chromosomes", + "chromosone", "chromosome", + "chromosoom", "chromosome", + "chromozome", "chromosome", + "chronciles", "chronicles", + "chronicals", "chronicles", + "chronicels", "chronicles", + "chronocles", "chronicles", + "chronosome", "chromosome", + "chrsitians", "christians", + "cigarattes", "cigarettes", + "cigerattes", "cigarettes", + "cincinatti", "cincinnati", + "cinncinati", "cincinnati", + "circulaire", "circular", + "circulaton", "circulation", + "circumsice", "circumcised", + "circumsied", "circumcised", + "circumwent", "circumvent", + "circunvent", "circumvent", + "cirruculum", "curriculum", + "claculator", "calculator", + "clairfying", "clarifying", + "clasically", "classically", + "classicals", "classics", + "classrooom", "classroom", + "cleanliess", "cleanliness", + "cleareance", "clearance", + "cleverleys", "cleverly", + "cliffhager", "cliffhanger", + "climateers", "climates", + "climatiser", "climates", + "clincially", "clinically", + "clitoridis", "clitoris", + "clitorious", "clitoris", + "co-incided", "coincided", + "cockroachs", "cockroaches", + "cockroahes", "cockroaches", + "coefficent", "coefficient", + "cognatious", "contagious", + "cognitivie", "cognitive", + "coincidnce", "coincide", + "colelctive", "collective", + "colelctors", "collectors", + "collapsers", "collapses", + "collaquial", "colloquial", + "collasping", "collapsing", + "collataral", "collateral", + "collaterol", "collateral", + "collatoral", "collateral", + "collcetion", "collections", + "colleauges", "colleagues", + "colleciton", "collection", + "collectems", "collects", + "collectief", "collective", + "collecties", "collects", + "collectifs", "collects", + "collectivo", "collection", + "collectoin", "collections", + "collectons", "collections", + "collectros", "collects", + "collegaues", "colleagues", + "collequial", "colloquial", + "colleteral", "collateral", + "colliquial", "colloquial", + "collission", "collisions", + "collitions", "collisions", + "colloqiual", "colloquial", + "colloquail", "colloquial", + "colloqueal", "colloquial", + "collpasing", "collapsing", + "colonialsm", "colonialism", + "colorblend", "colorblind", + "coloublind", "colorblind", + "columbidae", "columbia", + "comapnions", "companions", + "comaprable", "comparable", + "comaprison", "comparison", + "comaptible", "compatible", + "combatabts", "combatants", + "combatents", "combatants", + "combinatin", "combinations", + "combinaton", "combination", + "comediants", "comedians", + "comepndium", "compendium", + "comferting", "comforting", + "comforming", "comforting", + "comfortbly", "comfortably", + "comisioned", "commissioned", + "comisioner", "commissioner", + "comissions", "commissions", + "commandbox", "commando", + "commandent", "commandment", + "commandeur", "commanders", + "commandore", "commanders", + "commandpod", "commando", + "commanists", "communists", + "commemters", "commenters", + "commencera", "commerce", + "commenciez", "commence", + "commentaar", "commentary", + "commentare", "commenter", + "commentars", "commenters", + "commentart", "commentator", + "commentery", "commentary", + "commentsry", "commenters", + "commercail", "commercials", + "commercent", "commence", + "commerical", "commercial", + "comminists", "communists", + "commisison", "commissions", + "commissons", "commissions", + "commiteted", "commited", + "commodites", "commodities", + "commtiment", "commitments", + "communicae", "communicated", + "communisim", "communism", + "communiste", "communities", + "communites", "communities", + "communters", "commenters", + "compadible", "compatible", + "compagnons", "companions", + "compainons", "companions", + "compairson", "comparison", + "compalined", "complained", + "compandium", "compendium", + "companians", "companions", + "companines", "companions", + "compansate", "compensate", + "comparabil", "comparable", + "comparason", "comparison", + "comparaste", "compares", + "comparatie", "comparative", + "compareble", "comparable", + "comparemos", "compares", + "comparions", "comparison", + "compariosn", "comparisons", + "comparisen", "compares", + "comparitve", "comparative", + "comparsion", "comparison", + "compartent", "compartment", + "compartmet", "compartment", + "compatibel", "compatible", + "compatibil", "compatible", + "compeating", "completing", + "compeditor", "competitor", + "compednium", "compendium", + "compeeting", "completing", + "compeltely", "completely", + "compelting", "completing", + "compeltion", "completion", + "compemdium", "compendium", + "compenduim", "compendium", + "compenents", "components", + "compenidum", "compendium", + "compensare", "compensate", + "comperable", "comparable", + "comperhend", "comprehend", + "compession", "compassion", + "competance", "competence", + "competator", "competitor", + "competenet", "competence", + "competense", "competence", + "competenze", "competence", + "competeted", "competed", + "competetor", "competitor", + "competidor", "competitor", + "competiors", "competitors", + "competitie", "competitive", + "competitin", "competitions", + "competitio", "competitor", + "competiton", "competition", + "competitve", "competitive", + "compilance", "compliance", + "compilaton", "compilation", + "compinsate", "compensate", + "compitable", "compatible", + "compitance", "compliance", + "complacant", "complacent", + "complaince", "compliance", + "complaines", "complaints", + "complainig", "complaining", + "complainte", "complained", + "complation", "completion", + "compleatly", "completely", + "complecate", "complicate", + "completeds", "completes", + "completent", "complement", + "completily", "complexity", + "completito", "completion", + "completley", "completely", + "complexers", "complexes", + "complexety", "complexity", + "complianed", "compliance", + "compliants", "complaints", + "complicaed", "complicate", + "complicare", "complicate", + "complicati", "complicit", + "complicato", "complication", + "complicite", "complicate", + "complicted", "complicated", + "complience", "compliance", + "complimate", "complicate", + "complition", "completion", + "complusion", "compulsion", + "complusive", "compulsive", + "complusory", "compulsory", + "compolsive", "compulsive", + "compolsory", "compulsory", + "compolsury", "compulsory", + "componants", "components", + "componenet", "components", + "componsate", "compensate", + "comporable", "comparable", + "compositae", "composite", + "compositie", "composite", + "compositon", "composition", + "compraison", "comparisons", + "compramise", "compromise", + "comprassem", "compress", + "comprehand", "comprehend", + "compresion", "compression", + "compresors", "compressor", + "compresser", "compressor", + "compressio", "compressor", + "compresson", "compression", + "comprihend", "comprehend", + "comprimise", "compromise", + "compromiss", "compromises", + "compromize", "compromise", + "compromsie", "compromises", + "comprossor", "compressor", + "compteting", "completing", + "comptetion", "completion", + "compulisve", "compulsive", + "compulosry", "compulsory", + "compulsary", "compulsory", + "compulsery", "compulsory", + "compulsing", "compulsion", + "compulsivo", "compulsion", + "compulsury", "compulsory", + "compuslion", "compulsion", + "compuslive", "compulsive", + "compuslory", "compulsory", + "compustion", "compulsion", + "computanti", "computation", + "conatiners", "containers", + "concedendo", "conceded", + "concedered", "conceded", + "conceitual", "conceptual", + "concentate", "concentrate", + "concenting", "connecting", + "conceptial", "conceptual", + "conceptuel", "conceptual", + "concersion", "concession", + "concesions", "concession", + "concidered", "considered", + "conciously", "consciously", + "concission", "concession", + "conclsuion", "concussion", + "conclusies", "conclusive", + "conclution", "conclusion", + "concorrent", "concurrent", + "concsience", "conscience", + "conculsion", "conclusion", + "conculsive", "conclusive", + "concurment", "concurrent", + "concurrant", "concurrent", + "concurrect", "concurrent", + "concusions", "concussion", + "concusison", "concussions", + "condamning", "condemning", + "condemming", "condemning", + "condencing", "condemning", + "condenming", "condemning", + "condensend", "condensed", + "condidtion", "condition", + "conditinal", "conditional", + "conditiner", "conditioner", + "conditiond", "conditioned", + "conditiong", "conditioning", + "condmening", "condemning", + "conduiting", "conducting", + "conencting", "connecting", + "conenction", "connection", + "conenctors", "connectors", + "conesencus", "consensus", + "confedarcy", "confederacy", + "confedence", "conference", + "confedercy", "confederacy", + "conferance", "conference", + "conferenze", "conference", + "conferming", "confirming", + "confernece", "conferences", + "confessino", "confessions", + "confidance", "confidence", + "confidenly", "confidently", + "confidense", "confidence", + "confidenty", "confidently", + "conflcting", "conflating", + "conflicing", "conflicting", + "conflictos", "conflicts", + "confliting", "conflating", + "confriming", "confirming", + "confussion", "confession", + "congratule", "congratulate", + "congresman", "congressman", + "congresmen", "congressmen", + "congressen", "congressmen", + "conjecutre", "conjecture", + "conjuction", "conjunction", + "conjuncion", "conjunction", + "conlcusion", "conclusion", + "conncetion", "connections", + "conneciton", "connection", + "connecties", "connects", + "connectins", "connects", + "connectivy", "connectivity", + "connectpro", "connector", + "conneticut", "connecticut", + "connotaion", "connotation", + "conpsiracy", "conspiracy", + "conqeuring", "conquering", + "conqouring", "conquering", + "conquerers", "conquerors", + "conquoring", "conquering", + "consciense", "conscience", + "consciouly", "consciously", + "consdiered", "considered", + "consending", "consenting", + "consensuel", "consensual", + "consenusal", "consensual", + "consequece", "consequence", + "consequnce", "consequence", + "conservare", "conserve", + "conservato", "conservation", + "conservice", "conserve", + "conservies", "conserve", + "conservite", "conserve", + "consicence", "conscience", + "consideras", "considers", + "consideret", "considerate", + "consipracy", "conspiracy", + "consistant", "consistent", + "consistens", "consists", + "consisteny", "consistency", + "consitency", "consistency", + "consituted", "constituted", + "conslutant", "consultant", + "consluting", "consulting", + "consolidad", "consolidated", + "consonents", "consonants", + "consorcium", "consortium", + "conspirace", "conspiracies", + "conspiricy", "conspiracy", + "conspriacy", "conspiracy", + "constaints", "constraints", + "constatnly", "constantly", + "constently", "constantly", + "constitude", "constitute", + "constitued", "constitute", + "constituem", "constitute", + "constituer", "constitute", + "constitues", "constitutes", + "constituie", "constitute", + "constituit", "constitute", + "constitutn", "constituents", + "constituye", "constitute", + "constnatly", "constantly", + "constracts", "constructs", + "constraits", "constraints", + "constransi", "constraints", + "constrants", "constraints", + "construced", "constructed", + "constructo", "construction", + "construint", "constraint", + "construits", "constructs", + "construted", "constructed", + "consueling", "consulting", + "consultata", "consultant", + "consultate", "consultant", + "consultati", "consultant", + "consultato", "consultation", + "consultent", "consultant", + "consumated", "consummated", + "consumbale", "consumables", + "consuments", "consumes", + "consumirem", "consumerism", + "consumires", "consumerism", + "consumirse", "consumerism", + "consumiste", "consumes", + "consumpion", "consumption", + "contaction", "contacting", + "contageous", "contagious", + "contagiosa", "contagious", + "contagioso", "contagious", + "contaigous", "contagious", + "containors", "containers", + "contaminen", "containment", + "contanting", "contacting", + "contection", "contention", + "contectual", "contextual", + "conteiners", "contenders", + "contempate", "contemplate", + "contemplat", "contempt", + "contempory", "contemporary", + "contenants", "continents", + "contencion", "contention", + "contendors", "contenders", + "contenents", "continents", + "conteneurs", "contenders", + "contengent", "contingent", + "contension", "contention", + "contentino", "contention", + "contentios", "contentious", + "contentous", "contentious", + "contestais", "contests", + "contestans", "contests", + "contestase", "contests", + "contestion", "contention", + "contestors", "contests", + "contextful", "contextual", + "contextuel", "contextual", + "contextura", "contextual", + "contianers", "containers", + "contianing", "containing", + "contibuted", "contributed", + "contibutes", "contributes", + "contigents", "continents", + "contigious", "contagious", + "contignent", "contingent", + "continants", "continents", + "continenal", "continental", + "continenet", "continents", + "contineous", "continuous", + "continetal", "continental", + "contingecy", "contingency", + "contingeny", "contingency", + "continient", "contingent", + "continious", "continuous", + "continiuty", "continuity", + "contintent", "contingent", + "continualy", "continually", + "continuare", "continue", + "continuati", "continuity", + "continuato", "continuation", + "continuent", "contingent", + "continuety", "continuity", + "continunes", "continents", + "continuons", "continuous", + "continutiy", "continuity", + "continuuum", "continuum", + "contitnent", "contingent", + "contiuning", "containing", + "contiunity", "continuity", + "contorller", "controllers", + "contracing", "contracting", + "contractar", "contractor", + "contracter", "contractor", + "contractin", "contraction", + "contractos", "contracts", + "contradice", "contradicted", + "contradics", "contradicts", + "contredict", "contradict", + "contribued", "contributed", + "contribuem", "contribute", + "contribuer", "contribute", + "contribues", "contributes", + "contribuie", "contribute", + "contribuit", "contribute", + "contributo", "contribution", + "contributs", "contributes", + "contribuye", "contribute", + "contricted", "contracted", + "contridict", "contradict", + "contriubte", "contributes", + "controlelr", "controllers", + "controlers", "controls", + "controling", "controlling", + "controlles", "controls", + "controvery", "controversy", + "controvesy", "controversy", + "contrubite", "contributes", + "contrubute", "contribute", + "contuining", "continuing", + "contuinity", "continuity", + "convaluted", "convoluted", + "convcition", "convictions", + "conveinent", "convenient", + "conveluted", "convoluted", + "convencion", "convention", + "conveniant", "convenient", + "conveniece", "convenience", + "convenince", "convenience", + "convential", "conventional", + "converesly", "conversely", + "convergens", "converse", + "converison", "conversions", + "converning", "converting", + "conversare", "converse", + "conversino", "conversions", + "conversley", "conversely", + "conversoin", "conversions", + "conversons", "conversions", + "convertion", "conversion", + "convertire", "converter", + "converying", "converting", + "conveyered", "conveyed", + "conviccion", "conviction", + "conviciton", "conviction", + "convienent", "convenient", + "conviluted", "convoluted", + "convincted", "convince", + "convinsing", "convincing", + "convinving", "convincing", + "convoluded", "convoluted", + "convoulted", "convoluted", + "convulated", "convoluted", + "convuluted", "convoluted", + "cooperatve", "cooperative", + "coordenate", "coordinate", + "coordiante", "coordinate", + "coordinare", "coordinate", + "coordinato", "coordination", + "coordinats", "coordinates", + "coordonate", "coordinate", + "cooridnate", "coordinate", + "copehnagen", "copenhagen", + "copenaghen", "copenhagen", + "copenahgen", "copenhagen", + "copengagen", "copenhagen", + "copengahen", "copenhagen", + "copenhagan", "copenhagen", + "copenhague", "copenhagen", + "copenhagun", "copenhagen", + "copenhaven", "copenhagen", + "copenhegan", "copenhagen", + "copyrighed", "copyrighted", + "copyrigted", "copyrighted", + "corinthans", "corinthians", + "corinthias", "corinthians", + "corinthins", "corinthians", + "cornmitted", "committed", + "corporatie", "corporate", + "corralated", "correlated", + "corralates", "correlates", + "correccion", "correction", + "correciton", "corrections", + "correcters", "correctors", + "correctess", "correctness", + "correctivo", "correction", + "correctons", "corrections", + "corregated", "correlated", + "correkting", "correcting", + "correlatas", "correlates", + "correlatie", "correlated", + "correlatos", "correlates", + "correspend", "correspond", + "corrilated", "correlated", + "corrilates", "correlates", + "corrispond", "correspond", + "corrolated", "correlated", + "corrolates", "correlates", + "corrospond", "correspond", + "corrpution", "corruption", + "corrulates", "correlates", + "corrupcion", "corruption", + "cosmeticas", "cosmetics", + "cosmeticos", "cosmetics", + "costumized", "customized", + "counceling", "counseling", + "councellor", "councillor", + "councelors", "counselors", + "councilers", "councils", + "counselers", "counselors", + "counsellng", "counselling", + "counsilers", "counselors", + "counsiling", "counseling", + "counsilors", "counselors", + "counsolers", "counselors", + "counsoling", "counseling", + "countepart", "counteract", + "counteratk", "counteract", + "counterbat", "counteract", + "countercat", "counteract", + "countercut", "counteract", + "counteries", "counters", + "countoring", "countering", + "countryies", "countryside", + "countrying", "countering", + "courcework", "coursework", + "coursefork", "coursework", + "courthosue", "courthouse", + "courtrooom", "courtroom", + "cousnelors", "counselors", + "coutneract", "counteract", + "coutnering", "countering", + "covenental", "covenant", + "cranberrry", "cranberry", + "creationis", "creations", + "creationsm", "creationism", + "creationst", "creationist", + "creativily", "creatively", + "creativley", "creatively", + "credibilty", "credibility", + "creeperest", "creepers", + "crimanally", "criminally", + "criminalty", "criminally", + "criminalul", "criminally", + "criticable", "critical", + "criticarlo", "critical", + "criticiing", "criticising", + "criticisim", "criticism", + "criticisme", "criticise", + "criticisng", "criticising", + "criticists", "critics", + "criticisze", "criticise", + "criticizms", "criticisms", + "criticizng", "criticizing", + "critisiced", "criticized", + "critisicms", "criticisms", + "critisicsm", "criticisms", + "critisiscm", "criticisms", + "critisisms", "criticisms", + "critisizes", "criticises", + "critisizms", "criticisms", + "critiziced", "criticized", + "critizised", "criticized", + "critizisms", "criticisms", + "critizized", "criticized", + "crocodille", "crocodile", + "crossfiter", "crossfire", + "crutchetts", "crutches", + "crystalens", "crystals", + "crystalisk", "crystals", + "crystallis", "crystals", + "cuatiously", "cautiously", + "culterally", "culturally", + "cultrually", "culturally", + "culumative", "cumulative", + "culutrally", "culturally", + "cumbersone", "cumbersome", + "cumbursome", "cumbersome", + "cumpolsory", "compulsory", + "cumulitive", "cumulative", + "currancies", "currencies", + "currenctly", "currency", + "currenices", "currencies", + "currentfps", "currents", + "currentlys", "currents", + "currentpos", "currents", + "currentusa", "currents", + "curriculem", "curriculum", + "curriculim", "curriculum", + "curriences", "currencies", + "curroption", "corruption", + "custimized", "customized", + "customzied", "customized", + "custumized", "customized", + "cutscences", "cutscene", + "cutscenses", "cutscene", + "dangerouly", "dangerously", + "dealerhsip", "dealerships", + "deathamtch", "deathmatch", + "deathmacth", "deathmatch", + "debateable", "debatable", + "decembeard", "december", + "decendants", "descendants", + "decendents", "descendants", + "decideable", "decidable", + "deciptions", "depictions", + "decisiones", "decisions", + "declarasen", "declares", + "declaraste", "declares", + "declaremos", "declares", + "decomposit", "decompose", + "decoracion", "decoration", + "decorativo", "decoration", + "decoritive", "decorative", + "decroative", "decorative", + "decsending", "descending", + "dedicacion", "dedication", + "dedikation", "dedication", + "deducatble", "deductible", + "deducitble", "deductible", + "defacation", "defamation", + "defamating", "defamation", + "defanitely", "definately", + "defelction", "deflection", + "defendeers", "defender", + "defendents", "defendants", + "defenderes", "defenders", + "defenesman", "defenseman", + "defenselss", "defenseless", + "defensivly", "defensively", + "defianetly", "definately", + "defiantely", "definately", + "defiantley", "definately", + "defibately", "definately", + "deficately", "definately", + "deficiancy", "deficiency", + "deficience", "deficiencies", + "deficienct", "deficient", + "deficienty", "deficiency", + "defiintely", "definately", + "definaetly", "definately", + "definaitly", "definately", + "definaltey", "definately", + "definataly", "definately", + "definateky", "definately", + "definately", "definitely", + "definatily", "definately", + "defination", "definition", + "definative", "definitive", + "definatlly", "definately", + "definatrly", "definately", + "definayely", "definately", + "defineatly", "definately", + "definetaly", "definately", + "definetely", "definitely", + "definetily", "definately", + "definetlly", "definetly", + "definettly", "definately", + "definicion", "definition", + "definietly", "definitely", + "definining", "defining", + "definitaly", "definately", + "definiteyl", "definitly", + "definitivo", "definition", + "definitley", "definitely", + "definitlly", "definitly", + "definitlry", "definitly", + "definitlty", "definitly", + "definjtely", "definately", + "definltely", "definately", + "definotely", "definately", + "definstely", "definately", + "defintaley", "definately", + "defintiely", "definitely", + "defintiion", "definitions", + "definutely", "definately", + "deflaction", "deflection", + "defleciton", "deflection", + "deflektion", "deflection", + "defniately", "definately", + "degenarate", "degenerate", + "degenerare", "degenerate", + "degenerite", "degenerate", + "degoratory", "derogatory", + "degraderad", "degraded", + "dehydraded", "dehydrated", + "dehyrdated", "dehydrated", + "deifnately", "definately", + "deisgnated", "designated", + "delaership", "dealership", + "delearship", "dealership", + "delegaties", "delegate", + "delegative", "delegate", + "delfection", "deflection", + "delibarate", "deliberate", + "deliberant", "deliberate", + "delibirate", "deliberate", + "deligthful", "delightful", + "deliverate", "deliberate", + "deliverees", "deliveries", + "deliviered", "delivered", + "deliviring", "delivering", + "delporable", "deplorable", + "delpoyment", "deployment", + "delutional", "delusional", + "dementieva", "dementia", + "deminsions", "dimensions", + "democracis", "democracies", + "democracts", "democrat", + "democratas", "democrats", + "democrates", "democrats", + "demograhic", "demographic", + "demographs", "demographics", + "demograpic", "demographic", + "demolation", "demolition", + "demolicion", "demolition", + "demolision", "demolition", + "demolitian", "demolition", + "demoliting", "demolition", + "demoloshed", "demolished", + "demolution", "demolition", + "demonished", "demolished", + "demonstate", "demonstrate", + "demonstras", "demonstrates", + "demorcracy", "democracy", + "denegerate", "degenerate", + "denominato", "denomination", + "denomintor", "denominator", + "deocrative", "decorative", + "deomcratic", "democratic", + "deparments", "departments", + "departmens", "departments", + "departmnet", "departments", + "depcitions", "depictions", + "depdending", "depending", + "depencency", "dependency", + "dependance", "dependence", + "dependancy", "dependency", + "dependandt", "dependant", + "dependends", "depended", + "dependened", "depended", + "dependenta", "dependant", + "dependente", "dependence", + "depicitons", "depictions", + "deplorabel", "deplorable", + "deplorabil", "deplorable", + "deplorible", "deplorable", + "deplyoment", "deployment", + "depolyment", "deployment", + "depositers", "deposits", + "depressief", "depressive", + "depressies", "depressive", + "deprivaton", "deprivation", + "deragotory", "derogatory", + "derivaties", "derivatives", + "deriviated", "derived", + "derivitave", "derivative", + "derivitive", "derivative", + "derogatary", "derogatory", + "derogatery", "derogatory", + "derogetory", "derogatory", + "derogitory", "derogatory", + "derogotary", "derogatory", + "derogotory", "derogatory", + "derviative", "derivative", + "descendats", "descendants", + "descendend", "descended", + "descenting", "descending", + "descerning", "descending", + "descipable", "despicable", + "descisions", "decisions", + "descriibes", "describes", + "descripton", "description", + "desginated", "designated", + "desigining", "designing", + "desireable", "desirable", + "desktopbsd", "desktops", + "despciable", "despicable", + "desperatly", "desperately", + "desperetly", "desperately", + "despicaple", "despicable", + "despicible", "despicable", + "dessicated", "desiccated", + "destinatin", "destinations", + "destinaton", "destination", + "destoryers", "destroyers", + "destorying", "destroying", + "destroyeds", "destroyers", + "destroyeer", "destroyers", + "destrucion", "destruction", + "destrucive", "destructive", + "destryoing", "destroying", + "detectarlo", "detector", + "detectaron", "detector", + "detectoare", "detector", + "determinas", "determines", + "determinig", "determining", + "determinsm", "determinism", + "deutschand", "deutschland", + "devastaded", "devastated", + "devastaing", "devastating", + "devastanti", "devastating", + "devasteted", "devastated", + "develepors", "developers", + "develoeprs", "developers", + "developmet", "developments", + "developors", "develops", + "developped", "developed", + "developres", "develops", + "develpment", "development", + "devestated", "devastated", + "devolvendo", "devolved", + "deyhdrated", "dehydrated", + "diagnosied", "diagnose", + "diagnosies", "diagnosis", + "diagnositc", "diagnostic", + "diagnossed", "diagnose", + "diagnosted", "diagnose", + "diagnotics", "diagnostic", + "diagonstic", "diagnostic", + "dichotomoy", "dichotomy", + "dicitonary", "dictionary", + "diconnects", "disconnects", + "dicovering", "discovering", + "dictateurs", "dictates", + "dictionare", "dictionaries", + "differance", "difference", + "differenly", "differently", + "differense", "differences", + "differente", "difference", + "differentl", "differential", + "differenty", "differently", + "differnece", "difference", + "difficulte", "difficulties", + "difficults", "difficulties", + "difficutly", "difficulty", + "diffuculty", "difficulty", + "diganostic", "diagnostic", + "dimensinal", "dimensional", + "dimentions", "dimensions", + "dimesnions", "dimensions", + "dimineshes", "diminishes", + "diminising", "diminishing", + "dimunitive", "diminutive", + "dinosaures", "dinosaurs", + "dinosaurus", "dinosaurs", + "dipections", "depictions", + "diplimatic", "diplomatic", + "diplomacia", "diplomatic", + "diplomancy", "diplomacy", + "dipolmatic", "diplomatic", + "directinla", "directional", + "directionl", "directional", + "directivos", "directions", + "directores", "directors", + "directorys", "directors", + "directsong", "directions", + "disaapoint", "disappoint", + "disagreeed", "disagreed", + "disapeared", "disappeared", + "disappeard", "disappeared", + "disappered", "disappeared", + "disappiont", "disappoint", + "disaproval", "disapproval", + "disastorus", "disastrous", + "disastrosa", "disastrous", + "disastrose", "disastrous", + "disastrosi", "disastrous", + "disastroso", "disastrous", + "disaterous", "disastrous", + "discalimer", "disclaimer", + "discapline", "discipline", + "discepline", "discipline", + "disception", "discretion", + "discharded", "discharged", + "disciplers", "disciples", + "disciplies", "disciplines", + "disciplins", "disciplines", + "disciprine", "discipline", + "disclamier", "disclaimer", + "discliamer", "disclaimer", + "disclipine", "discipline", + "disclousre", "disclosure", + "disclsoure", "disclosure", + "discograhy", "discography", + "discograpy", "discography", + "discolsure", "disclosure", + "disconenct", "disconnect", + "disconncet", "disconnects", + "disconnets", "disconnects", + "discontued", "discounted", + "discoruage", "discourages", + "discources", "discourse", + "discourgae", "discourages", + "discourges", "discourages", + "discoveres", "discovers", + "discoveryd", "discovered", + "discoverys", "discovers", + "discrecion", "discretion", + "discreddit", "discredited", + "discrepany", "discrepancy", + "discresion", "discretion", + "discreting", "discretion", + "discribing", "describing", + "discrimine", "discriminate", + "discrouage", "discourages", + "discrption", "discretion", + "discusison", "discussions", + "discusting", "discussing", + "disgracful", "disgraceful", + "disgrunted", "disgruntled", + "disgruntld", "disgruntled", + "disguisted", "disguise", + "disgustiny", "disgustingly", + "disgustosa", "disgusts", + "disgustose", "disgusts", + "disgustosi", "disgusts", + "disgustoso", "disgusts", + "dishcarged", "discharged", + "dishinored", "dishonored", + "disicpline", "discipline", + "disiplined", "disciplined", + "dislcaimer", "disclaimer", + "dismanteld", "dismantled", + "dismanting", "dismantling", + "dismentled", "dismantled", + "dispecable", "despicable", + "dispencary", "dispensary", + "dispencers", "dispenser", + "dispencing", "dispensing", + "dispensare", "dispenser", + "dispensory", "dispensary", + "dispesnary", "dispensary", + "dispicable", "despicable", + "displayfps", "displays", + "dispositon", "disposition", + "dispostion", "disposition", + "disputerad", "disputed", + "disrecpect", "disrespect", + "disrection", "discretion", + "disrepsect", "disrespect", + "disresepct", "disrespect", + "disrespekt", "disrespect", + "disription", "disruption", + "disrispect", "disrespect", + "disrputing", "disrupting", + "disruptivo", "disruption", + "disruptron", "disruption", + "dissapears", "disappears", + "dissappear", "disappear", + "disscusion", "discussion", + "dissmisive", "dismissive", + "dissodance", "dissonance", + "dissonante", "dissonance", + "dissonence", "dissonance", + "distastful", "distasteful", + "disticntly", "distinctly", + "distiction", "distinction", + "distincion", "distinction", + "distincive", "distinctive", + "distinclty", "distinctly", + "distinctie", "distinctive", + "distinctin", "distinctions", + "distingish", "distinguish", + "distingush", "distinguish", + "distintcly", "distinctly", + "distoriton", "distortion", + "distorsion", "distortion", + "distortian", "distortion", + "distortron", "distortion", + "distractes", "distracts", + "distractia", "district", + "distractin", "district", + "distractiv", "district", + "distration", "distortion", + "distribuem", "distribute", + "distribuer", "distribute", + "distribuie", "distribute", + "distribuit", "distribute", + "distributs", "distributors", + "distribuye", "distribute", + "distrotion", "distortion", + "distrubing", "disturbing", + "distrubtes", "distrust", + "distrubute", "distribute", + "distubring", "disturbing", + "disturbace", "disturbance", + "disturping", "disrupting", + "disucssing", "discussing", + "disucssion", "discussion", + "disurption", "disruption", + "ditributed", "distributed", + "diversifiy", "diversify", + "dividendes", "dividends", + "dividendos", "dividends", + "divideneds", "dividend", + "divinition", "divination", + "divinitory", "divinity", + "divisiones", "divisions", + "dobulelift", "doublelift", + "doccuments", "documents", + "documentry", "documentary", + "dogmatisch", "dogmatic", + "dolphinese", "dolphins", + "domianting", "dominating", + "domimation", "domination", + "dominacion", "domination", + "dominaters", "dominates", + "donwgraded", "downgraded", + "donwloaded", "downloaded", + "donwvoters", "downvoters", + "donwvoting", "downvoting", + "doomsdaily", "doomsday", + "doubellift", "doublelift", + "doubleiift", "doublelift", + "doubleleft", "doublelift", + "doublelfit", "doublelift", + "doublerift", "doublelift", + "doulbelift", "doublelift", + "downgarded", "downgraded", + "downgrated", "downgrade", + "downlaoded", "downloaded", + "downloadas", "downloads", + "downloades", "downloads", + "downovting", "downvoting", + "downroaded", "downgraded", + "downsiders", "downsides", + "downstaris", "downstairs", + "downstiars", "downstairs", + "downtokers", "downvoters", + "downtoking", "downvoting", + "downtraded", "downgraded", + "downviting", "downvoting", + "downvotear", "downvoters", + "downvoteas", "downvoters", + "downvoteds", "downvoters", + "downvotees", "downvoters", + "downvotesd", "downvoters", + "downvotess", "downvoters", + "downvotest", "downvoters", + "downvoteur", "downvoters", + "downvoties", "downvoters", + "downvotres", "downvoters", + "downvotted", "downvote", + "downvottes", "downvoters", + "downwoters", "downvoters", + "downwoting", "downvoting", + "drasticaly", "drastically", + "drasticlly", "drastically", + "draughtman", "draughtsman", + "dumbbellls", "dumbbells", + "dumbfouded", "dumbfounded", + "dumbfouned", "dumbfounded", + "dungeoness", "dungeons", + "dupilcates", "duplicates", + "duplicants", "duplicates", + "duplicatas", "duplicates", + "duplicitas", "duplicates", + "duplifaces", "duplicates", + "durabiltiy", "durability", + "dyamically", "dynamically", + "dynamicaly", "dynamically", + "dynamicdns", "dynamics", + "dynamiclly", "dynamically", + "dynamicpsf", "dynamics", + "dynamitage", "dynamite", + "dysfuncion", "dysfunction", + "earhtbound", "earthbound", + "earthqauke", "earthquake", + "earthquack", "earthquake", + "earthquaks", "earthquakes", + "earthquate", "earthquake", + "earthqukes", "earthquakes", + "easthetics", "aesthetics", + "ecoligical", "ecological", + "ecomonical", "economical", + "econimical", "economical", + "econimists", "economists", + "economicas", "economics", + "economicos", "economics", + "economicus", "economics", + "economisch", "economic", + "economisit", "economists", + "effeciency", "efficiency", + "effectivly", "effectively", + "efficeincy", "efficiency", + "efficently", "efficiently", + "efficiancy", "efficiency", + "efficienct", "efficient", + "efficienty", "efficiently", + "egotistcal", "egotistical", + "ehtnically", "ethnically", + "ejaculaion", "ejaculation", + "ejaculatie", "ejaculate", + "ejaculatin", "ejaculation", + "ejaculaton", "ejaculation", + "ejaculatte", "ejaculate", + "electircal", "electrical", + "electivite", "elective", + "electoraat", "electorate", + "electorale", "electorate", + "electorite", "electorate", + "electornic", "electronic", + "electrican", "electrician", + "electriciy", "electricity", + "electricty", "electricity", + "electrinic", "electrician", + "electroate", "electorate", + "electrodan", "electron", + "electroinc", "electron", + "electrolye", "electrolytes", + "electroman", "electron", + "electroncs", "electrons", + "electrones", "electrons", + "electronik", "election", + "electronis", "electronics", + "electronix", "election", + "elemantary", "elementary", + "elementery", "elementary", + "elementray", "elementary", + "eleminated", "eliminated", + "elephantes", "elephants", + "elephantis", "elephants", + "elephantos", "elephants", + "elephantus", "elephants", + "eletricity", "electricity", + "elimanates", "eliminates", + "elimenates", "eliminates", + "elimentary", "elementary", + "elimimates", "eliminates", + "eliminaste", "eliminates", + "eliminatin", "elimination", + "eliminaton", "elimination", + "eliminster", "eliminates", + "ellipitcal", "elliptical", + "ellipsical", "elliptical", + "ellipticle", "elliptical", + "ellitpical", "elliptical", + "ellpitical", "elliptical", + "eloquantly", "eloquently", + "eloquintly", "eloquently", + "emapthetic", "empathetic", + "embarassed", "embarrassed", + "embarassig", "embarassing", + "embarrased", "embarrassed", + "embarrases", "embarrassed", + "embezelled", "embezzled", + "emblamatic", "emblematic", + "embodyment", "embodiment", + "emergenies", "emergencies", + "emmigrated", "emigrated", + "emminently", "eminently", + "emmisaries", "emissaries", + "emobdiment", "embodiment", + "emotionaly", "emotionally", + "empahsized", "emphasized", + "empahsizes", "emphasizes", + "empathatic", "empathetic", + "emphacized", "emphasized", + "emphatetic", "empathetic", + "emphatised", "emphasized", + "emphatized", "emphasized", + "emphatizes", "emphasizes", + "emphazised", "emphasized", + "emphazises", "emphasizes", + "emphesized", "emphasized", + "emphesizes", "emphasizes", + "emphisized", "emphasized", + "emphisizes", "emphasizes", + "empiricaly", "empirically", + "employeers", "employees", + "employeurs", "employer", + "emprisoned", "imprisoned", + "encahnting", "enchanting", + "enchancing", "enchanting", + "enchanging", "enchanting", + "enchantent", "enchantment", + "enchantmet", "enchantments", + "encompases", "encompasses", + "encounterd", "encountered", + "encountred", "encountered", + "encouraing", "encouraging", + "encoutners", "encounters", + "encription", "encryption", + "encrpytion", "encryption", + "encyrption", "encryption", + "endlessley", "endlessly", + "endolithes", "endoliths", + "enforceing", "enforcing", + "engagemnet", "engagements", + "engagemnts", "engagements", + "engieneers", "engineers", + "enginereed", "engineered", + "enivitable", "inevitable", + "enlargment", "enlargement", + "enlighment", "enlighten", + "enlightend", "enlightened", + "enlightned", "enlightened", + "enrolement", "enrollment", + "enrollemnt", "enrollment", + "enterpirse", "enterprise", + "enterprice", "enterprise", + "enterpries", "enterprises", + "enterprize", "enterprise", + "enterprsie", "enterprises", + "enterrpise", "enterprises", + "entertaing", "entertaining", + "enthically", "ethnically", + "enthisiast", "enthusiast", + "enthuiasts", "enthusiast", + "enthuisast", "enthusiasts", + "enthusiams", "enthusiasm", + "enthusiant", "enthusiast", + "enthusiats", "enthusiast", + "enthusiest", "enthusiast", + "enthusists", "enthusiasts", + "envelopped", "envelope", + "enveloppen", "envelope", + "enveloppes", "envelope", + "enviorment", "environment", + "enviroment", "environment", + "environmet", "environments", + "equiavlent", "equivalents", + "equilavent", "equivalent", + "equilibium", "equilibrium", + "equilibrim", "equilibrium", + "equilibrum", "equilibrium", + "equippment", "equipment", + "equitorial", "equatorial", + "equivalant", "equivalent", + "equivalnce", "equivalence", + "equivalnet", "equivalents", + "equivelant", "equivalent", + "equivelent", "equivalent", + "equivilant", "equivalent", + "equivilent", "equivalent", + "equivlaent", "equivalents", + "equivolent", "equivalent", + "eratically", "erratically", + "escalative", "escalate", + "escavation", "escalation", + "esitmation", "estimation", + "esoterisch", "esoteric", + "especailly", "especially", + "espeically", "especially", + "espressino", "espresso", + "espression", "espresso", + "essencials", "essentials", + "essensials", "essentials", + "essentails", "essentials", + "essentialy", "essentially", + "essentiels", "essentials", + "essentuals", "essentials", + "estabishes", "establishes", + "estimacion", "estimation", + "estimativo", "estimation", + "estination", "estimation", + "ethicallly", "ethically", + "ethincally", "ethnically", + "ethnicites", "ethnicities", + "ethnicitiy", "ethnicity", + "euphorical", "euphoria", + "euphorisch", "euphoric", + "euthanaisa", "euthanasia", + "euthanazia", "euthanasia", + "euthanesia", "euthanasia", + "evaluacion", "evaluation", + "evalutaion", "evaluation", + "evaulating", "evaluating", + "evaulation", "evaluation", + "eventaully", "eventually", + "eventially", "eventually", + "everyoneis", "everyones", + "exacberate", "exacerbated", + "exagerated", "exaggerated", + "exagerates", "exaggerates", + "exagerrate", "exaggerate", + "exaggarate", "exaggerate", + "exaggurate", "exaggerate", + "exahusting", "exhausting", + "exahustion", "exhaustion", + "examinated", "examined", + "examinerad", "examined", + "exapansion", "expansion", + "exapnsions", "expansions", + "exauhsting", "exhausting", + "exauhstion", "exhaustion", + "excecuting", "executing", + "excecution", "execution", + "exceedigly", "exceedingly", + "exceedinly", "exceedingly", + "excellance", "excellence", + "excellenet", "excellence", + "excellenze", "excellence", + "excerising", "exercising", + "excessivly", "excessively", + "exchangees", "exchanges", + "excitiment", "excitement", + "exclsuives", "exclusives", + "exclusivas", "exclusives", + "exclusivly", "exclusively", + "exclusivos", "exclusives", + "exclusivty", "exclusivity", + "exclussive", "exclusives", + "exclusvies", "exclusives", + "excpetions", "exceptions", + "exculsives", "exclusives", + "exculsivly", "exclusively", + "execptions", "exceptions", + "exectuable", "executable", + "exectuions", "executions", + "exectuives", "executives", + "execusions", "executions", + "executabil", "executable", + "executible", "executable", + "executiner", "executioner", + "executings", "executions", + "executivas", "executives", + "exeedingly", "exceedingly", + "exepmtions", "exemptions", + "exeptional", "exceptional", + "exercicing", "exercising", + "exercizing", "exercising", + "exersicing", "exercising", + "exersising", "exercising", + "exersizing", "exercising", + "exerternal", "external", + "exeuctions", "executions", + "exhasuting", "exhausting", + "exhasution", "exhaustion", + "exhaustivo", "exhaustion", + "exhibicion", "exhibition", + "exhibitons", "exhibits", + "exhuasting", "exhausting", + "exhuastion", "exhaustion", + "exibitions", "exhibitions", + "exictement", "excitement", + "exipration", "expiration", + "existantes", "existent", + "existenial", "existential", + "existental", "existential", + "exlcusives", "exclusives", + "exorbatant", "exorbitant", + "exorbatent", "exorbitant", + "exorbidant", "exorbitant", + "exorbirant", "exorbitant", + "exorbitent", "exorbitant", + "expalining", "explaining", + "expanisons", "expansions", + "expansivos", "expansions", + "expanssion", "expansions", + "expantions", "expansions", + "expecially", "especially", + "expectaion", "expectation", + "expectansy", "expectancy", + "expectency", "expectancy", + "expections", "exceptions", + "expedetion", "expedition", + "expedicion", "expedition", + "expeditivo", "expedition", + "expeiments", "experiments", + "expemtions", "exemptions", + "expendeble", "expendable", + "expendible", "expendable", + "expensable", "expendable", + "expentancy", "expectancy", + "expereince", "experience", + "experement", "experiment", + "experiance", "experience", + "experieced", "experienced", + "experieces", "experiences", + "experiemnt", "experiment", + "experiened", "experienced", + "experiense", "experiences", + "expermient", "experiments", + "experssion", "expression", + "expextancy", "expectancy", + "expidetion", "expedition", + "expierence", "experience", + "expination", "expiration", + "expirement", "experiment", + "explanatin", "explanations", + "explicatia", "explicit", + "explicatie", "explicit", + "explicatif", "explicit", + "explicatii", "explicit", + "explicetly", "explicitly", + "explicilty", "explicitly", + "explioting", "exploiting", + "exploiding", "exploiting", + "exploition", "exploiting", + "explorarea", "explorer", + "exploreres", "explorers", + "explosivas", "explosives", + "explossion", "explosions", + "explossive", "explosives", + "explosvies", "explosives", + "explotions", "explosions", + "explusions", "explosions", + "expodition", "exposition", + "expoliting", "exploiting", + "expolsions", "explosions", + "expolsives", "explosives", + "exponental", "exponential", + "exposicion", "exposition", + "expositivo", "exposition", + "expotition", "exposition", + "exprensive", "expressive", + "expresions", "expression", + "expresison", "expressions", + "expressens", "expresses", + "expressief", "expressive", + "expressley", "expressly", + "expriation", "expiration", + "extensivly", "extensively", + "extentions", "extensions", + "exterioara", "exterior", + "exterioare", "exterior", + "extermally", "externally", + "extermists", "extremists", + "extraccion", "extraction", + "extractivo", "extraction", + "extractnow", "extraction", + "extradtion", "extraction", + "extremaste", "extremes", + "extremeley", "extremely", + "extremelly", "extremely", + "extrememly", "extremely", + "extremests", "extremists", + "extremised", "extremes", + "extremisim", "extremism", + "extremisme", "extremes", + "extremiste", "extremes", + "extrenally", "externally", + "extrimists", "extremists", + "eyeballers", "eyeballs", + "fabriacted", "fabricated", + "fabricatie", "fabricated", + "faciliated", "facilitated", + "facilitait", "facilitate", + "facilitant", "facilitate", + "facilitare", "facilitate", + "facisnated", "fascinated", + "facitilies", "facilities", + "facsinated", "fascinated", + "fahernheit", "fahrenheit", + "fahrenhiet", "fahrenheit", + "fallatious", "fallacious", + "fallicious", "fallacious", + "falshbacks", "flashbacks", + "familiarty", "familiarity", + "familiarze", "familiarize", + "fanaticals", "fanatics", + "fanfaction", "fanfiction", + "fanfcition", "fanfiction", + "fanficiton", "fanfiction", + "fanserivce", "fanservice", + "fanservise", "fanservice", + "fanservive", "fanservice", + "fantasiose", "fantasies", + "farehnheit", "fahrenheit", + "farhenheit", "fahrenheit", + "fascianted", "fascinated", + "fascinatie", "fascinated", + "fascinatin", "fascination", + "fascistisk", "fascists", + "fatalaties", "fatalities", + "favoruites", "favourites", + "favourates", "favourites", + "favouritsm", "favourites", + "favourties", "favourites", + "federacion", "federation", + "federativo", "federation", + "fellowhsip", "fellowship", + "fellowshop", "fellowship", + "feminimity", "femininity", + "feministas", "feminists", + "feminitity", "femininity", + "fermentato", "fermentation", + "fertalizer", "fertilizer", + "fertelizer", "fertilizer", + "fertilizar", "fertilizer", + "fertilzier", "fertilizer", + "fertiziler", "fertilizer", + "festivales", "festivals", + "fetishiste", "fetishes", + "ficticious", "fictitious", + "filessytem", "filesystem", + "filesytems", "filesystem", + "filmamkers", "filmmakers", + "filmmakare", "filmmakers", + "finallizes", "finalizes", + "financialy", "financially", + "fingernals", "fingernails", + "fingerpies", "fingertips", + "fingerpint", "fingerprint", + "fingertaps", "fingertips", + "fingertits", "fingertips", + "fingertops", "fingertips", + "fireballls", "fireballs", + "firefigher", "firefighter", + "firefigter", "firefighter", + "firendlies", "friendlies", + "firghtened", "frightened", + "fisionable", "fissionable", + "flashligth", "flashlight", + "flaskbacks", "flashbacks", + "flawleslly", "flawlessly", + "flexibiliy", "flexibility", + "flexibilty", "flexibility", + "flimmakers", "filmmakers", + "fluctuatie", "fluctuate", + "fluctuatin", "fluctuations", + "flutterhsy", "fluttershy", + "fluttersky", "fluttershy", + "flutterspy", "fluttershy", + "forcifully", "forcefully", + "forecfully", "forcefully", + "foreginers", "foreigners", + "foregorund", "foreground", + "foreignese", "foreigners", + "foreigness", "foreigners", + "foreignors", "foreigners", + "foreingers", "foreigners", + "forensisch", "forensic", + "foreseeble", "foreseeable", + "forgeiners", "foreigners", + "forgieners", "foreigners", + "forgivance", "forgiven", + "forgivenss", "forgiveness", + "forgotting", "forgetting", + "foriegners", "foreigners", + "formadible", "formidable", + "formalhaut", "fomalhaut", + "formallity", "formally", + "formallize", "formalize", + "formatiing", "formatting", + "formatings", "formations", + "formativos", "formations", + "formidabel", "formidable", + "formidabil", "formidable", + "formidible", "formidable", + "forminable", "formidable", + "formitable", "formidable", + "formuladas", "formulas", + "formulados", "formulas", + "forseeable", "foreseeable", + "fortelling", "foretelling", + "fortunatly", "fortunately", + "fortunetly", "fortunately", + "foundaiton", "foundations", + "foundaries", "foundries", + "foundatoin", "foundations", + "fractalers", "fractals", + "fractalius", "fractals", + "fractalpus", "fractals", + "fracturare", "fracture", + "fragmanted", "fragment", + "francaises", "franchises", + "franchices", "franchises", + "franchines", "franchises", + "franchizes", "franchises", + "franchsies", "franchises", + "fransiscan", "franciscan", + "franticaly", "frantically", + "franticlly", "frantically", + "fraternaty", "fraternity", + "fraternety", "fraternity", + "fraterntiy", "fraternity", + "fraturnity", "fraternity", + "fraudalent", "fraudulent", + "fraudelant", "fraudulent", + "fraudelent", "fraudulent", + "fraudolent", "fraudulent", + "fraudulant", "fraudulent", + "freedomers", "freedoms", + "freedomest", "freedoms", + "freindlies", "friendlies", + "freindship", "friendship", + "frequencey", "frequency", + "friednship", "friendships", + "friednzone", "friendzoned", + "friendhsip", "friendship", + "friendsies", "friendlies", + "friendzies", "friendlies", + "friendzond", "friendzoned", + "frientship", "friendship", + "frigthened", "frightened", + "fromatting", "formatting", + "fromidable", "formidable", + "frontlinie", "frontline", + "fruadulent", "fraudulent", + "frustraded", "frustrated", + "frustradet", "frustrates", + "frustraits", "frustrates", + "frustrants", "frustrates", + "frustratin", "frustration", + "frustrsted", "frustrates", + "fucntional", "functional", + "fulfulling", "fulfilling", + "fullfiling", "fulfilling", + "fullfilled", "fulfilled", + "fullscrean", "fullscreen", + "fulttershy", "fluttershy", + "funcitonal", "functional", + "fundametal", "fundamental", + "furstrated", "frustrated", + "furstrates", "frustrates", + "furutistic", "futuristic", + "futhermore", "furthermore", + "futurestic", "futuristic", + "futurisitc", "futuristic", + "futurustic", "futuristic", + "galvinized", "galvanized", + "garuanteed", "guaranteed", + "garuantees", "guarantees", + "gauntanamo", "guantanamo", + "gauntlents", "gauntlet", + "gauranteed", "guaranteed", + "gaurantees", "guarantees", + "gaurenteed", "guaranteed", + "gaurentees", "guarantees", + "generalice", "generalize", + "generalife", "generalize", + "generalnie", "generalize", + "generaters", "generates", + "generaties", "generate", + "generatios", "generators", + "generatons", "generators", + "generatore", "generate", + "generelize", "generalize", + "generocity", "generosity", + "generoisty", "generosity", + "generostiy", "generosity", + "geneticaly", "genetically", + "geneticlly", "genetically", + "genitalias", "genitals", + "genuinelly", "genuinely", + "geographia", "geographical", + "geogrpahic", "geographic", + "germanisch", "germanic", + "gigantisch", "gigantic", + "gimmickers", "gimmicks", + "girlfirend", "girlfriend", + "girlfreind", "girlfriend", + "girlfriens", "girlfriends", + "girlfrinds", "girlfriends", + "girlfrined", "girlfriends", + "goalkeaper", "goalkeeper", + "goalkeeprs", "goalkeeper", + "goalkepeer", "goalkeeper", + "goegraphic", "geographic", + "golakeeper", "goalkeeper", + "goldburger", "goldberg", + "goosebumbs", "goosebumps", + "goosegumps", "goosebumps", + "goosepumps", "goosebumps", + "gothenberg", "gothenburg", + "govenrment", "government", + "govermenet", "goverment", + "govermnent", "governments", + "governemnt", "government", + "governened", "governed", + "governered", "governed", + "governmant", "governmental", + "governmetn", "governments", + "governmnet", "government", + "govnerment", "government", + "govornment", "government", + "gradiating", "graduating", + "gradiation", "graduation", + "graduacion", "graduation", + "grapefriut", "grapefruit", + "grapefrukt", "grapefruit", + "graphicaly", "graphically", + "graphiclly", "graphically", + "gratituous", "gratuitous", + "gratiutous", "gratuitous", + "gratuidous", "gratuitous", + "gratuituos", "gratuitous", + "gratutious", "gratuitous", + "graudating", "graduating", + "graudation", "graduation", + "gravitatie", "gravitate", + "greatfully", "gratefully", + "greenhosue", "greenhouse", + "greviances", "grievances", + "grievences", "grievances", + "grilfriend", "girlfriend", + "guaduloupe", "guadalupe", + "guanatanmo", "guantanamo", + "guantamamo", "guantanamo", + "guantamano", "guantanamo", + "guantanano", "guantanamo", + "guantanemo", "guantanamo", + "guantanoma", "guantanamo", + "guantanomo", "guantanamo", + "guantonamo", "guantanamo", + "guarantess", "guarantees", + "guardiands", "guardians", + "guardianes", "guardians", + "guardianis", "guardians", + "guarenteed", "guaranteed", + "guarentees", "guarantees", + "guarnateed", "guaranteed", + "guarnatees", "guarantees", + "guarunteed", "guaranteed", + "guaruntees", "guarantees", + "guatamalan", "guatemalan", + "gunatanamo", "guantanamo", + "gunlsinger", "gunslinger", + "gunsiinger", "gunslinger", + "gunslanger", "gunslinger", + "gunsligner", "gunslinger", + "gunstinger", "gunslinger", + "gymanstics", "gymnastics", + "gymnasitcs", "gymnastics", + "gynmastics", "gymnastics", + "haemorrage", "haemorrhage", + "halloweeen", "halloween", + "hambergers", "hamburgers", + "hamburgare", "hamburger", + "hamburgesa", "hamburgers", + "hamburgles", "hamburgers", + "hamburgurs", "hamburgers", + "handcuffes", "handcuffs", + "handelbars", "handlebars", + "handicaped", "handicapped", + "handwritng", "handwriting", + "harasments", "harassments", + "hardlinked", "hardline", + "harmoniacs", "harmonic", + "harmonisch", "harmonic", + "harrasment", "harassment", + "harrassing", "harassing", + "harvasting", "harvesting", + "haversting", "harvesting", + "headhpones", "headphones", + "headphoens", "headphones", + "headquarer", "headquarter", + "headquater", "headquarter", + "headshoots", "headshot", + "healtchare", "healthcare", + "healtheast", "healthiest", + "healthyest", "healthiest", + "heapdhones", "headphones", + "heartbeart", "heartbeat", + "heartbeast", "heartbeat", + "heartborne", "heartbroken", + "heartbrake", "heartbreak", + "hearthsone", "hearthstone", + "heatlhcare", "healthcare", + "heavyweght", "heavyweight", + "heavyweigt", "heavyweight", + "hedgehodge", "hedgehog", + "heidelburg", "heidelberg", + "heigthened", "heightened", + "heistation", "hesitation", + "helathcare", "healthcare", + "helicopers", "helicopters", + "helicoptor", "helicopter", + "helicotper", "helicopters", + "helicpoter", "helicopter", + "helictoper", "helicopters", + "helikopter", "helicopter", + "hemingwary", "hemingway", + "hemingwavy", "hemingway", + "hemipshere", "hemisphere", + "hemishpere", "hemisphere", + "hemmorhage", "hemorrhage", + "hempishere", "hemisphere", + "herculeans", "hercules", + "herculeasy", "hercules", + "herculeees", "hercules", + "hesitstion", "hesitation", + "hestiation", "hesitation", + "hieghtened", "heightened", + "hierachies", "hierarchies", + "hieroglphs", "hieroglyphs", + "highalnder", "highlander", + "highlighed", "highlighted", + "highligted", "highlighted", + "highloader", "highlander", + "highpander", "highlander", + "highscholl", "highschool", + "highshcool", "highschool", + "hillarious", "hilarious", + "hinderance", "hindrance", + "hinderence", "hindrance", + "hipsterest", "hipsters", + "hispanicos", "hispanics", + "hispanicus", "hispanics", + "histarical", "historical", + "histerical", "historical", + "historiaan", "historians", + "historicas", "historians", + "historicly", "historical", + "historiens", "histories", + "historisch", "historic", + "hoemopathy", "homeopathy", + "hollywoood", "hollywood", + "homecuming", "homecoming", + "homeoapthy", "homeopathy", + "homeonwers", "homeowners", + "homeopahty", "homeopathy", + "homeophaty", "homeopathy", + "homeopothy", "homeopathy", + "homeothapy", "homeopathy", + "homepoathy", "homeopathy", + "homewoners", "homeowners", + "homoepathy", "homeopathy", + "homogeneos", "homogeneous", + "homogeneus", "homogeneous", + "homophibia", "homophobia", + "homophibic", "homophobic", + "homophobie", "homophobe", + "homophonia", "homophobia", + "homophopia", "homophobia", + "homophopic", "homophobic", + "homosexaul", "homosexual", + "homosexuel", "homosexual", + "honeymooon", "honeymoon", + "hopefullly", "hopefully", + "hopeleslly", "hopelessly", + "horisontal", "horizontal", + "horizantal", "horizontal", + "horizontes", "horizons", + "horiztonal", "horizontal", + "horrendeus", "horrendous", + "horriblely", "horribly", + "hospitales", "hospitals", + "hospitalty", "hospitality", + "hospitible", "hospitable", + "hsitorians", "historians", + "humanaties", "humanities", + "humanitary", "humanity", + "humiliatin", "humiliation", + "humiliaton", "humiliation", + "humilitied", "humiliated", + "humillated", "humiliated", + "hurricance", "hurricane", + "hurriganes", "hurricanes", + "hurrikanes", "hurricanes", + "hurrycanes", "hurricanes", + "hydropilic", "hydrophilic", + "hydropobic", "hydrophobic", + "hyperbolie", "hyperbole", + "hyperlobic", "hyperbolic", + "hyperlogic", "hyperbolic", + "hypertrohy", "hypertrophy", + "hypertropy", "hypertrophy", + "hyphotesis", "hypothesis", + "hypocrates", "hypocrites", + "hypocriscy", "hypocrisy", + "hypocrises", "hypocrites", + "hypocritus", "hypocrites", + "hypocrties", "hypocrites", + "hypocrytes", "hypocrites", + "hypokrites", "hypocrites", + "hypothecis", "hypothesis", + "hypotheiss", "hypotheses", + "hypothesus", "hypotheses", + "hypothises", "hypotheses", + "hypothisis", "hypothesis", + "hypothosis", "hypothesis", + "hyprocites", "hypocrites", + "hystarical", "hysterical", + "hystericly", "hysterical", + "hysteriska", "hysteria", + "ibuprofein", "ibuprofen", + "ibuprofine", "ibuprofen", + "icelandinc", "icelandic", + "idealisitc", "idealistic", + "idealogies", "ideologies", + "identicial", "identical", + "identifyed", "identified", + "identitets", "identities", + "ideolagies", "ideologies", + "ideoligies", "ideologies", + "ideologias", "ideologies", + "ideologice", "ideologies", + "ideologije", "ideologies", + "ideologins", "ideologies", + "ideologisk", "ideologies", + "ideolouges", "ideologies", + "illegalest", "illegals", + "illegallly", "illegally", + "illegimacy", "illegitimacy", + "illegitime", "illegitimate", + "illegitimt", "illegitimate", + "illimunati", "illuminati", + "illinoians", "illinois", + "illistrate", "illiterate", + "illitarate", "illiterate", + "illitirate", "illiterate", + "illumanati", "illuminati", + "illumaniti", "illuminati", + "illumianti", "illuminati", + "illumimati", "illuminati", + "illuminaci", "illuminati", + "illuminadi", "illuminati", + "illuminami", "illuminati", + "illuminazi", "illuminati", + "illuminite", "illuminati", + "illuminiti", "illuminati", + "illuminoti", "illuminati", + "illuminuti", "illuminati", + "illumniati", "illuminati", + "illumunati", "illuminati", + "illuninati", "illuminati", + "illusiones", "illusions", + "illustrant", "illustrate", + "illustrare", "illustrate", + "illustrato", "illustration", + "imablanced", "imbalanced", + "imablances", "imbalances", + "imaginatie", "imaginative", + "imaginaton", "imagination", + "imaginitve", "imaginative", + "imbalenced", "imbalanced", + "imbalences", "imbalances", + "imcomplete", "incomplete", + "imediately", "immediately", + "imigration", "emigration", + "immaturaty", "immaturity", + "immaturety", "immaturity", + "immedeatly", "immediately", + "immediatly", "immediately", + "immedietly", "immediately", + "immenseley", "immensely", + "immidately", "immediately", + "immigranti", "immigration", + "immigrents", "immigrants", + "immitating", "imitating", + "immobilien", "immobile", + "immobilier", "immobile", + "immobilzed", "immobile", + "immobilzer", "immobile", + "immobilzes", "immobile", + "immortales", "immortals", + "immortalis", "immortals", + "immortaliy", "immortality", + "immortalls", "immortals", + "immortalty", "immortality", + "impartirla", "impartial", + "impecabbly", "impeccably", + "impeccible", "impeccable", + "impeckable", "impeccable", + "impelments", "implements", + "imperetive", "imperative", + "imperialsm", "imperialism", + "imperialst", "imperialist", + "imperitave", "imperative", + "imperitive", "imperative", + "implaments", "implements", + "implantase", "implants", + "implausble", "implausible", + "implausibe", "implausible", + "implemenet", "implements", + "implicatia", "implicit", + "implicatie", "implicit", + "implicatii", "implicit", + "implicetly", "implicitly", + "impliciete", "implicit", + "implicilty", "implicitly", + "impliments", "implements", + "imporbable", "improbable", + "importanly", "importantly", + "importanty", "importantly", + "importence", "importance", + "importerad", "imported", + "imporvised", "improvised", + "impossable", "impossible", + "impossbily", "impossibly", + "impossibal", "impossibly", + "impossibel", "impossibly", + "impossibry", "impossibly", + "impossibul", "impossibly", + "impractial", "impractical", + "impreative", "imperative", + "impresison", "impressions", + "impressoin", "impressions", + "impressons", "impressions", + "improbabil", "improbable", + "improbible", "improbable", + "impropable", "improbable", + "improsined", "imprisoned", + "improsoned", "imprisoned", + "improvemnt", "improvement", + "improvents", "improves", + "improvized", "improvised", + "imprsioned", "imprisoned", + "impulsemos", "impulses", + "imrpovised", "improvised", + "inablility", "inability", + "inaccruate", "inaccurate", + "inadaquate", "inadequate", + "inadaquete", "inadequate", + "inadecuate", "inadequate", + "inadeguate", "inadequate", + "inadeqaute", "inadequate", + "inadequete", "inadequate", + "inadequite", "inadequate", + "inadiquate", "inadequate", + "inagurated", "inaugurated", + "inbalanced", "imbalanced", + "inbetweeen", "inbetween", + "incarnaton", "incarnation", + "incentivos", "incentives", + "inchoerent", "incoherent", + "incidentes", "incidents", + "incidently", "incidentally", + "incidentul", "incidental", + "inclreased", "increased", + "incognitio", "incognito", + "incoherant", "incoherent", + "incohorent", "incoherent", + "incorectly", "incorrectly", + "incorrecly", "incorrectly", + "incorrecty", "incorrectly", + "incorretly", "incorrectly", + "incraments", "increments", + "incredable", "incredible", + "incredably", "incredibly", + "incremetal", "incremental", + "incriments", "increments", + "inctroduce", "introduce", + "indefenite", "indefinite", + "indefinate", "indefinite", + "indefinete", "indefinite", + "indefinity", "indefinitely", + "indeginous", "indigenous", + "indentical", "identical", + "independet", "independent", + "indepenent", "independent", + "inderictly", "indirectly", + "indicaters", "indicates", + "indicativo", "indication", + "indicatore", "indicate", + "indicitave", "indicative", + "indicitive", "indicative", + "indiffernt", "indifferent", + "indigenius", "indigenous", + "indiginous", "indigenous", + "indigneous", "indigenous", + "indikation", "indication", + "indireclty", "indirectly", + "indirektly", "indirectly", + "individuel", "individual", + "indiviudal", "individuals", + "indivudual", "individual", + "indoensian", "indonesian", + "indonasian", "indonesian", + "indoneisan", "indonesian", + "indonesean", "indonesian", + "indonesien", "indonesian", + "indonesion", "indonesian", + "indonisian", "indonesian", + "indonistan", "indonesian", + "indpendent", "independent", + "industiral", "industrial", + "industires", "industries", + "industrail", "industrial", + "industrees", "industries", + "industrias", "industries", + "industriel", "industrial", + "industrija", "industrial", + "industrije", "industries", + "indviduals", "individuals", + "inefficent", "inefficient", + "ineqaulity", "inequality", + "inequailty", "inequality", + "inevatible", "inevitable", + "inevetable", "inevitable", + "inevetably", "inevitably", + "inevetible", "inevitable", + "inevidable", "inevitable", + "inevidably", "inevitably", + "inevitible", "inevitable", + "inevitibly", "inevitably", + "inevtiable", "inevitable", + "inevtiably", "inevitably", + "infallable", "infallible", + "infaltable", "inflatable", + "infeccious", "infectious", + "infecteous", "infectious", + "infectuous", "infectious", + "infedility", "infidelity", + "infektious", "infectious", + "inferioara", "inferior", + "inferioare", "inferior", + "inferiorty", "inferiority", + "inferrence", "inference", + "infestaion", "infestation", + "infestaton", "infestation", + "infestions", "infections", + "infideltiy", "infidelity", + "infidility", "infidelity", + "infiltrade", "infiltrate", + "infiltrait", "infiltrate", + "infiltrare", "infiltrate", + "infiltrase", "infiltrate", + "infinately", "infinitely", + "infinetely", "infinitely", + "infiniment", "infinite", + "infinitley", "infinitely", + "infintiely", "infinitely", + "inflamable", "inflatable", + "inflateble", "inflatable", + "inflatible", "inflatable", + "infleunced", "influenced", + "inflitrate", "infiltrate", + "influanced", "influenced", + "influances", "influences", + "influencie", "influences", + "influening", "influencing", + "influensed", "influences", + "influenser", "influences", + "influenses", "influences", + "influental", "influential", + "influented", "influenced", + "influentes", "influences", + "influneced", "influenced", + "infograhic", "infographic", + "infograpic", "infographic", + "infomation", "information", + "informable", "informal", + "informarla", "informal", + "informarle", "informal", + "informarlo", "informal", + "informatie", "informative", + "informella", "informal", + "informerad", "informed", + "informtion", "information", + "infridging", "infringing", + "infrigning", "infringing", + "infulenced", "influenced", + "infulences", "influences", + "ingenuitiy", "ingenuity", + "ingrediant", "ingredient", + "ingrediens", "ingredients", + "ingrediets", "ingredient", + "inhabitans", "inhabitants", + "inhabitats", "inhabitants", + "inherantly", "inherently", + "inherintly", "inherently", + "inheritage", "heritage", + "inhernetly", "inherently", + "inifnitely", "infinitely", + "initaition", "initiation", + "initalised", "initialised", + "initaliser", "initialiser", + "initalises", "initialises", + "initalisms", "initialisms", + "initalized", "initialized", + "initalizer", "initializer", + "initalizes", "initializes", + "initalling", "initialling", + "initalness", "initialness", + "initiaitve", "initiatives", + "initiaties", "initiatives", + "initiativs", "initiatives", + "initiatves", "initiatives", + "initiavite", "initiatives", + "inititaive", "initiatives", + "inititiave", "initiatives", + "initmately", "intimately", + "initmidate", "intimidate", + "inituition", "initiation", + "injustaces", "injustices", + "injusticas", "injustices", + "inmigrants", "immigrants", + "innoavtion", "innovations", + "innocentes", "innocents", + "innotation", "innovation", + "innovacion", "innovation", + "innovaiton", "innovations", + "innovatief", "innovate", + "innovaties", "innovate", + "innovativo", "innovation", + "innvoation", "innovation", + "inofficial", "unofficial", + "inpsection", "inspection", + "inquisator", "inquisitor", + "inquisidor", "inquisitor", + "inquisiter", "inquisitor", + "inquisitio", "inquisitor", + "inquisitir", "inquisitor", + "inquisiton", "inquisition", + "inquistior", "inquisitor", + "inquizitor", "inquisitor", + "inqusitior", "inquisitor", + "insensitve", "insensitive", + "insepction", "inspection", + "insistance", "insistence", + "insistente", "insistence", + "insistenze", "insistence", + "insistince", "insistence", + "insitution", "institution", + "inspeccion", "inspection", + "inspeciton", "inspections", + "inspectons", "inspections", + "inspectres", "inspectors", + "inspektion", "inspection", + "inspektors", "inspectors", + "inspiraste", "inspires", + "inspiraton", "inspiration", + "inspirerad", "inspired", + "inspireras", "inspires", + "insrugency", "insurgency", + "instabiliy", "instability", + "instabilty", "instability", + "installeer", "installer", + "installent", "installment", + "installesd", "installs", + "installion", "installing", + "instatance", "instance", + "instelling", "installing", + "instituded", "instituted", + "instituion", "institution", + "institutie", "institute", + "institutue", "instituted", + "instrament", "instrument", + "instrcutor", "instructors", + "instrucion", "instruction", + "instructer", "instructor", + "instructie", "instructed", + "instruktor", "instructor", + "instuction", "instruction", + "instuments", "instruments", + "insturcted", "instructed", + "insturctor", "instructor", + "insturment", "instrument", + "instutions", "intuitions", + "instututed", "instituted", + "insurgance", "insurgency", + "insurgancy", "insurgency", + "intangable", "intangible", + "intangeble", "intangible", + "intangibil", "intangible", + "intanjible", "intangible", + "integraded", "integrated", + "integrarla", "integral", + "integrarlo", "integral", + "integratie", "integrated", + "integreres", "interferes", + "integreted", "integrated", + "inteligent", "intelligent", + "intenseley", "intensely", + "intensitiy", "intensity", + "intentinal", "intentional", + "intentines", "intestines", + "interacive", "interactive", + "interactes", "interacts", + "interactie", "interactive", + "interactue", "interacted", + "interasted", "interacted", + "interbread", "interbreed", + "intercepto", "interception", + "intercorse", "intercourse", + "intercouse", "intercourse", + "intereacts", "interfaces", + "interected", "interacted", + "interefers", "interferes", + "interesant", "interest", + "interesing", "interesting", + "interestes", "interests", + "interfacce", "interfaces", + "interfears", "interferes", + "interfeers", "interferes", + "interferce", "interferes", + "interferre", "interfere", + "intergated", "integrated", + "interioara", "interior", + "interioare", "interior", + "intermedie", "intermediate", + "internetbs", "internets", + "internetes", "internets", + "internetis", "internets", + "internetts", "internets", + "internetus", "internets", + "interprate", "interpret", + "interrugum", "interregnum", + "interruped", "interrupted", + "interstela", "interstellar", + "intervalls", "intervals", + "intervalos", "intervals", + "interveign", "intervening", + "interveing", "intervening", + "interveiws", "interviews", + "intervento", "intervention", + "intervenue", "intervene", + "interveres", "interferes", + "intervieni", "interviewing", + "intervieuw", "interviews", + "interviewd", "interviewed", + "interviewr", "interviewer", + "intervines", "intervenes", + "interviwed", "interviewed", + "interviwer", "interviewer", + "interwebbs", "interwebs", + "intestents", "intestines", + "intestinas", "intestines", + "intestinos", "intestines", + "intestions", "intestines", + "intidimate", "intimidate", + "intimadate", "intimidate", + "intimatley", "intimately", + "intimiated", "intimidate", + "intimidade", "intimidated", + "intimidant", "intimidate", + "intimidare", "intimidate", + "intimitade", "intimidated", + "intimitaly", "intimately", + "intimitate", "intimidate", + "intimitely", "intimately", + "intolarant", "intolerant", + "intolerace", "intolerance", + "intolerate", "intolerant", + "intolerent", "intolerant", + "intolorant", "intolerant", + "intolorent", "intolerant", + "intorduced", "introduced", + "intorduces", "introduces", + "intorverts", "introverts", + "intoxicted", "intoxicated", + "intraverts", "introverts", + "intreguing", "intriguing", + "intricaces", "intricacies", + "intriguied", "intrigue", + "intrigured", "intrigue", + "intrinseci", "intrinsic", + "intrinsinc", "intrinsic", + "intriquing", "intriguing", + "intriuging", "intriguing", + "introdecks", "introduces", + "introdused", "introduces", + "introvents", "introverts", + "introvered", "introverted", + "introversa", "introverts", + "introverse", "introverts", + "introversi", "introverts", + "introverso", "introverts", + "introversy", "introverts", + "introveted", "introverted", + "intruduced", "introduced", + "intruduces", "introduces", + "intruiging", "intriguing", + "intruments", "instruments", + "intuitevly", "intuitively", + "intuitivly", "intuitively", + "intuitivno", "intuition", + "intutively", "intuitively", + "inumerable", "enumerable", + "inusrgency", "insurgency", + "invaderats", "invaders", + "invaildate", "invalidates", + "invairably", "invariably", + "invaldiate", "invalidates", + "invalidade", "invalidate", + "invalidare", "invalidate", + "invalubale", "invaluable", + "invalueble", "invaluable", + "invaraibly", "invariably", + "invariabil", "invariably", + "invaribaly", "invariably", + "invaulable", "invaluable", + "inveitable", "inevitable", + "inveitably", "inevitably", + "invensions", "inventions", + "inventario", "inventor", + "inventarlo", "inventor", + "inventaron", "inventor", + "inventings", "inventions", + "inventivos", "inventions", + "invertendo", "inverted", + "inverterad", "inverted", + "invertions", "inventions", + "investemnt", "investments", + "investiage", "investigate", + "investions", "inventions", + "investirat", "investigator", + "investmens", "investments", + "invicinble", "invincible", + "invididual", "individual", + "invincable", "invincible", + "invinceble", "invincible", + "invinicble", "invincible", + "invinsible", "invincible", + "invinvible", "invincible", + "invisibily", "invisibility", + "invitacion", "invitation", + "invitating", "invitation", + "involunary", "involuntary", + "involvment", "involvement", + "ironcially", "ironically", + "irracional", "irrational", + "irrationel", "irrational", + "irrelavant", "irrelevant", + "irrelavent", "irrelevant", + "irrelevent", "irrelevant", + "irrelivant", "irrelevant", + "irrelivent", "irrelevant", + "irrevelant", "irrelevant", + "irreverant", "irrelevant", + "irridation", "irritation", + "irriration", "irritation", + "irritacion", "irritation", + "irritaties", "irritate", + "islamisist", "islamist", + "islamistas", "islamists", + "isntalling", "installing", + "isntructed", "instructed", + "isntrument", "instrument", + "israeliens", "israelis", + "israelitas", "israelis", + "italianess", "italians", + "itnroduced", "introduced", + "jailborken", "jailbroken", + "jalibroken", "jailbroken", + "jamaicains", "jamaican", + "jamaicaman", "jamaican", + "jerusaleum", "jerusalem", + "jounralism", "journalism", + "jounralist", "journalist", + "jouranlism", "journalism", + "jouranlist", "journalist", + "journalims", "journals", + "journalits", "journals", + "journalizm", "journalism", + "journalsim", "journalism", + "journolist", "journalist", + "judegments", "judgements", + "judgemenal", "judgemental", + "judgemetal", "judgemental", + "jugdements", "judgements", + "juggarnaut", "juggernaut", + "juggeranut", "juggernaut", + "juggernath", "juggernaut", + "juggernout", "juggernaut", + "juggernuat", "juggernaut", + "juggetnaut", "juggernaut", + "jugglenaut", "juggernaut", + "juggurnaut", "juggernaut", + "justifible", "justifiable", + "juvenilles", "juvenile", + "kickstarer", "kickstarter", + "kickstartr", "kickstarter", + "kickstater", "kickstarter", + "kidnapning", "kidnapping", + "kidnappade", "kidnapped", + "killingest", "killings", + "kilometros", "kilometers", + "kilomiters", "kilometers", + "kilomoters", "kilometers", + "kilomteres", "kilometers", + "kindapping", "kidnapping", + "kingdomers", "kingdoms", + "krpytonite", "kryptonite", + "krypotnite", "kryptonite", + "krypronite", "kryptonite", + "kryptinite", "kryptonite", + "kryptolite", "kryptonite", + "kryptonyte", "kryptonite", + "krypyonite", "kryptonite", + "krytponite", "kryptonite", + "kyrptonite", "kryptonite", + "labarotory", "laboratory", + "laboratroy", "laboratory", + "laborerers", "laborers", + "laboritory", "laboratory", + "laborotory", "laboratory", + "lackbuster", "lackluster", + "lacklaster", "lackluster", + "landacapes", "landscapes", + "landingers", "landings", + "landshapes", "landscapes", + "landspaces", "landscapes", + "lannasters", "lannisters", + "lannesters", "lannisters", + "lannistars", "lannisters", + "lannsiters", "lannisters", + "lateration", "alteration", + "latitudine", "latitude", + "laughabley", "laughably", + "laughablly", "laughably", + "launchered", "launched", + "leaglizing", "legalizing", + "lectureres", "lectures", + "legalazing", "legalizing", + "legalizare", "legalize", + "legalizate", "legalize", + "legendaies", "legendaries", + "legendaris", "legendaries", + "legimitacy", "legitimacy", + "legimitate", "legitimate", + "legislatie", "legislative", + "legitamacy", "legitimacy", + "legitamate", "legitimate", + "legitamicy", "legitimacy", + "legitamite", "legitimate", + "legitemacy", "legitimacy", + "legitemate", "legitimate", + "legitimaly", "legitimacy", + "legitimicy", "legitimacy", + "legitimite", "legitimate", + "leiutenant", "lieutenant", + "lesbianese", "lesbians", + "lesbianest", "lesbians", + "leuitenant", "lieutenant", + "levetating", "levitating", + "liberacion", "liberation", + "liberalest", "liberate", + "liberalizm", "liberalism", + "liberalnim", "liberalism", + "liberalsim", "liberalism", + "liberarion", "liberation", + "liberaties", "liberate", + "liberatore", "liberate", + "libertania", "libertarians", + "libguistic", "linguistic", + "lietuenant", "lieutenant", + "lieutanant", "lieutenant", + "lieutanent", "lieutenant", + "lieutenent", "lieutenant", + "lifestiles", "lifestyles", + "lifestlyes", "lifestyles", + "lifesystem", "filesystem", + "lifesytles", "lifestyles", + "lifetimers", "lifetimes", + "lifetsyles", "lifestyles", + "lighhtning", "lightening", + "lightergas", "lighters", + "lighthning", "lightening", + "lighthorse", "lighthouse", + "lighthosue", "lighthouse", + "lighthours", "lighthouse", + "lightining", "lighting", + "lightneing", "lightening", + "lightnting", "lightening", + "lightrooom", "lightroom", + "lightweigt", "lightweight", + "ligitation", "litigation", + "ligthening", "lightening", + "ligthhouse", "lighthouse", + "likelyhood", "likelihood", + "limination", "limitation", + "limitacion", "limitation", + "limitaiton", "limitation", + "limitating", "limitation", + "limitativo", "limitation", + "linguisics", "linguistics", + "linguisitc", "linguistics", + "linguistcs", "linguistics", + "linguistis", "linguistics", + "linguitics", "linguistic", + "lingusitic", "linguistics", + "lingvistic", "linguistic", + "liousville", "louisville", + "listeneres", "listeners", + "literallly", "literally", + "literarely", "literary", + "literarlly", "literary", + "literatire", "literate", + "literative", "literate", + "literatute", "literate", + "lithuanina", "lithuania", + "litterally", "literally", + "liuetenant", "lieutenant", + "liveatream", "livestream", + "livelehood", "livelihood", + "liverpoool", "liverpool", + "livescream", "livestream", + "livestreem", "livestream", + "livestrems", "livestream", + "livilehood", "livelihood", + "livliehood", "livelihood", + "lobbyistes", "lobbyists", + "lockacreen", "lockscreen", + "logictical", "logistical", + "logisitcal", "logistical", + "logisticas", "logistics", + "logisticly", "logistical", + "loiusville", "louisville", + "lollipoopy", "lollipop", + "lonelyness", "loneliness", + "longevitiy", "longevity", + "lonileness", "loneliness", + "lonlieness", "loneliness", + "louieville", "louisville", + "louisiania", "louisiana", + "louisianna", "louisiana", + "louisivlle", "louisville", + "louisviile", "louisville", + "lousiville", "louisville", + "luietenant", "lieutenant", + "mabyelline", "maybelline", + "magnifient", "magnificent", + "mainpulate", "manipulate", + "mainstreem", "mainstream", + "maintaince", "maintained", + "maintaines", "maintains", + "maintainig", "maintaining", + "maintenace", "maintenance", + "maintianed", "maintained", + "maintioned", "mentioned", + "malfuncion", "malfunction", + "malpractce", "malpractice", + "managebale", "manageable", + "maneagable", "manageable", + "maneouvred", "manoeuvred", + "maneouvres", "manoeuvres", + "maneuveres", "maneuvers", + "maneuveurs", "maneuver", + "manifestas", "manifests", + "manifestes", "manifests", + "manifestus", "manifests", + "manipluate", "manipulate", + "manipualte", "manipulate", + "manipulant", "manipulate", + "manipulare", "manipulate", + "manipulted", "manipulated", + "maniuplate", "manipulate", + "mannarisms", "mannerisms", + "mannersims", "mannerisms", + "mannorisms", "mannerisms", + "manufacter", "manufacture", + "manufacure", "manufacture", + "manufature", "manufacture", + "maraudeurs", "marauder", + "margaritte", "margaret", + "margianlly", "marginally", + "marginaali", "marginal", + "marginable", "marginal", + "marignally", "marginally", + "marijuanna", "marijuana", + "marketting", "marketing", + "marshmalow", "marshmallow", + "masculinty", "masculinity", + "massacrare", "massacre", + "massivelly", "massively", + "masteriers", "masteries", + "masternind", "mastermind", + "masterpice", "masterpiece", + "mastrubate", "masturbate", + "mastubrate", "masturbated", + "masturabte", "masturbate", + "masturbait", "masturbate", + "masturbare", "masturbate", + "masturbeta", "masturbated", + "masturdate", "masturbate", + "materiales", "materials", + "materialsm", "materialism", + "maximazing", "maximizing", + "maximixing", "maximizing", + "mayballine", "maybelline", + "maybellene", "maybelline", + "maybellibe", "maybelline", + "maybilline", "maybelline", + "mccarthyst", "mccarthyist", + "mdifielder", "midfielder", + "meagthread", "megathread", + "meaningess", "meanings", + "meaningles", "meanings", + "meatballls", "meatballs", + "mecahnical", "mechanical", + "mecahnisms", "mechanisms", + "mechancial", "mechanical", + "mechandise", "merchandise", + "mechanichs", "mechanics", + "mechanicle", "mechanical", + "mechanicly", "mechanical", + "mechanicus", "mechanics", + "mechanincs", "mechanic", + "mechanisim", "mechanism", + "mechansims", "mechanisms", + "mechinical", "mechanical", + "mechinisms", "mechanisms", + "mediaction", "medications", + "medicacion", "medication", + "medicaiton", "medication", + "medicalert", "medicare", + "medicallly", "medically", + "medicatons", "medications", + "medicinens", "medicines", + "medicinske", "medicine", + "medicority", "mediocrity", + "medidating", "meditating", + "mediocirty", "mediocrity", + "mediocraty", "mediocrity", + "mediocrety", "mediocrity", + "mediocricy", "mediocrity", + "mediocrily", "mediocrity", + "mediocrisy", "mediocrity", + "meditacion", "medications", + "meditaiton", "meditation", + "melatonian", "melatonin", + "melatonion", "melatonin", + "mellinnium", "millennium", + "melodieuse", "melodies", + "membrances", "membrane", + "mentallity", "mentally", + "mentionnes", "mentions", + "mercenaire", "mercenaries", + "mercenares", "mercenaries", + "mercentile", "mercantile", + "merchanise", "merchandise", + "merchantos", "merchants", + "messagease", "messages", + "messagepad", "messaged", + "messenging", "messaging", + "metabalism", "metabolism", + "metabilism", "metabolism", + "metabloism", "metabolism", + "metablosim", "metabolism", + "metabolics", "metabolism", + "metabolizm", "metabolism", + "metabolsim", "metabolism", + "metalurgic", "metallurgic", + "metaphoras", "metaphors", + "metaphores", "metaphors", + "metaphyics", "metaphysics", + "meterology", "meteorology", + "methaphors", "metaphors", + "methodolgy", "methodology", + "methodoloy", "methodology", + "metrapolis", "metropolis", + "metrolopis", "metropolis", + "metropilis", "metropolis", + "metroplois", "metropolis", + "metropolin", "metropolitan", + "metropolos", "metropolis", + "metropolys", "metropolis", + "mexicanese", "mexicans", + "mexicaness", "mexicans", + "michelline", "michelle", + "micorwaves", "microwaves", + "microhpone", "microphone", + "microscoop", "microscope", + "microvaves", "microwaves", + "microvaxes", "microwaves", + "micrpohone", "microphones", + "midfeilder", "midfielder", + "midfiedler", "midfielder", + "midfieldes", "midfielders", + "midfielers", "midfielders", + "midfileder", "midfielder", + "midifelder", "midfielder", + "midnlessly", "mindlessly", + "migitation", "mitigation", + "migrainers", "migraines", + "miletsones", "milestones", + "milisecond", "millisecond", + "militiades", "militias", + "militiants", "militias", + "millinnium", "millennium", + "miminalist", "minimalist", + "minamilist", "minimalist", + "mindleslly", "mindlessly", + "minimazing", "minimizing", + "minimilast", "minimalist", + "minimilist", "minimalist", + "mininalist", "minimalist", + "ministeres", "ministers", + "ministerns", "ministers", + "minneaplis", "minneapolis", + "minneapols", "minneapolis", + "minnesotta", "minnesota", + "minoritets", "minorities", + "minoroties", "minorities", + "miracalous", "miraculous", + "miracluous", "miraculous", + "miracoulus", "miraculous", + "mircophone", "microphone", + "mircoscope", "microscope", + "mircowaves", "microwaves", + "misandrony", "misandry", + "miscarrage", "miscarriage", + "miscarrige", "miscarriage", + "misdemenor", "misdemeanor", + "miserabley", "miserably", + "miserablly", "miserably", + "misforture", "misfortune", + "misgoynist", "misogynist", + "misinfomed", "misinformed", + "misinterpt", "misinterpret", + "misisonary", "missionary", + "misoganist", "misogynist", + "misogenist", "misogynist", + "misoginist", "misogynist", + "misoginyst", "misogynist", + "misognyist", "misogynist", + "misogonist", "misogynist", + "misogonyst", "misogynist", + "misogyinst", "misogynist", + "misogynyst", "misogynist", + "misoygnist", "misogynist", + "mispelling", "misspelling", + "missionare", "missionaries", + "missionera", "missionary", + "missisippi", "mississippi", + "mississipi", "mississippi", + "mississppi", "mississippi", + "misspeling", "misspelling", + "misspellng", "misspelling", + "mistakedly", "mistakenly", + "mistakinly", "mistakenly", + "mistankely", "mistakenly", + "misterious", "mysterious", + "misteryous", "mysterious", + "mistreaded", "mistreated", + "misygonist", "misogynist", + "mitigaiton", "mitigation", + "moderacion", "moderation", + "moderaters", "moderates", + "moderatley", "moderately", + "moderatore", "moderate", + "moderatorn", "moderation", + "modificato", "modification", + "modifieras", "modifiers", + "modifieres", "modifiers", + "moisturier", "moisturizer", + "moleculair", "molecular", + "molestaion", "molestation", + "molestarle", "molester", + "molestarme", "molester", + "molestarse", "molester", + "molestarte", "molester", + "molestered", "molested", + "momentarly", "momentarily", + "monagomous", "monogamous", + "monetizare", "monetize", + "monitering", "monitoring", + "monogymous", "monogamous", + "monolistic", "monolithic", + "monolitich", "monolithic", + "monolopies", "monopolies", + "monolothic", "monolithic", + "monolythic", "monolithic", + "monopilies", "monopolies", + "monoploies", "monopolies", + "monopolets", "monopolies", + "monopolice", "monopolies", + "monopolios", "monopolies", + "monothilic", "monolithic", + "monsterous", "monsters", + "montioring", "monitoring", + "monumentos", "monuments", + "monumentul", "monumental", + "monumentus", "monuments", + "mormonisim", "mormonism", + "morphinate", "morphine", + "morrisette", "morissette", + "morrisound", "morrison", + "mosquitero", "mosquito", + "mosquiters", "mosquitoes", + "motherbard", "motherboard", + "motherboad", "motherboard", + "motherbord", "motherboard", + "motivaiton", "motivations", + "motiviated", "motivated", + "motorcicle", "motorcycle", + "motorcylce", "motorcycle", + "motorcyles", "motorcycles", + "motorollas", "motorola", + "mouthpeace", "mouthpiece", + "mouthpeice", "mouthpiece", + "movespeeed", "movespeed", + "mozzaralla", "mozzarella", + "mozzeralla", "mozzarella", + "mozzorella", "mozzarella", + "mulitation", "mutilation", + "mulitplied", "multiplied", + "mulitplier", "multiplier", + "mulitverse", "multiverse", + "multilpier", "multiplier", + "multiplaer", "multiplier", + "multiplaye", "multiply", + "multiplayr", "multiply", + "multiplays", "multiply", + "multipleye", "multiply", + "multipling", "multiplying", + "multiplyed", "multiplied", + "multiplyer", "multiple", + "multiplyng", "multiplying", + "murderered", "murdered", + "murdereres", "murderers", + "muscicians", "musicians", + "musculaire", "muscular", + "mushroooms", "mushroom", + "mutialtion", "mutilation", + "mutiliated", "mutilated", + "mutliation", "mutilation", + "mutliplied", "multiplied", + "mutliplier", "multiplier", + "mutliverse", "multiverse", + "mysogynist", "misogynist", + "mysterieus", "mysteries", + "nagivating", "navigating", + "nagivation", "navigation", + "narcassism", "narcissism", + "narcassist", "narcissist", + "narcessist", "narcissist", + "narciscism", "narcissism", + "narciscist", "narcissist", + "narcisissm", "narcissism", + "narcisisst", "narcissist", + "narcisists", "narcissist", + "narcissicm", "narcissism", + "narcissict", "narcissist", + "narcissitc", "narcissist", + "narcissits", "narcissist", + "narcoticos", "narcotics", + "narrativas", "narratives", + "narrativos", "narratives", + "narritives", "narratives", + "nashvillle", "nashville", + "nationales", "nationals", + "nationalis", "nationals", + "nationalit", "nationalist", + "nationaliy", "nationality", + "nationalty", "nationality", + "nationella", "national", + "naturually", "naturally", + "naviagting", "navigating", + "naviagtion", "navigation", + "navigatore", "navigate", + "neccessary", "necessary", + "necesarily", "necessarily", + "necessairy", "necessarily", + "necessarly", "necessary", + "necessarry", "necessary", + "necessiate", "necessitate", + "necessites", "necessities", + "neckbeared", "neckbeard", + "neckboards", "neckbeards", + "neckbreads", "neckbeards", + "neckneards", "neckbeards", + "necromacer", "necromancer", + "necromaner", "necromancer", + "needleslly", "needlessly", + "negativaty", "negativity", + "negativley", "negatively", + "negelcting", "neglecting", + "negilgence", "negligence", + "negiotated", "negotiated", + "neglacting", "neglecting", + "neglagence", "negligence", + "neglegance", "negligence", + "neglegible", "negligible", + "neglegting", "neglecting", + "neglibible", "negligible", + "neglicence", "negligence", + "neglicible", "negligible", + "neglicting", "neglecting", + "negligable", "negligible", + "negligance", "negligence", + "negligeble", "negligible", + "negligente", "negligence", + "negociated", "negotiated", + "negogiated", "negotiated", + "negoitated", "negotiated", + "negotaited", "negotiated", + "negotation", "negotiation", + "negotiaion", "negotiation", + "negotiatie", "negotiated", + "negotiatin", "negotiations", + "negotiaton", "negotiation", + "neigbhours", "neighbours", + "neighbhors", "neighbours", + "neighbords", "neighbours", + "neighbores", "neighbours", + "netowrking", "networking", + "netruality", "neutrality", + "neturality", "neutrality", + "netwroking", "networking", + "neurologia", "neurological", + "neutrailty", "neutrality", + "newletters", "newsletters", + "newlsetter", "newsletter", + "newsettler", "newsletter", + "newslatter", "newsletter", + "nieghbours", "neighbours", + "nightmates", "nightmares", + "nightmears", "nightmares", + "nightmeres", "nightmares", + "nigthmares", "nightmares", + "nipticking", "nitpicking", + "nitpciking", "nitpicking", + "nominacion", "nomination", + "nominatino", "nominations", + "nominativo", "nomination", + "nominatons", "nominations", + "nonsencial", "nonsensical", + "nontheless", "nonetheless", + "northerend", "northern", + "nostalgica", "nostalgia", + "nostalgija", "nostalgia", + "noteworhty", "noteworthy", + "nothingess", "nothingness", + "noticabely", "noticeably", + "noticabley", "noticeably", + "noticiably", "noticeably", + "notoriosly", "notoriously", + "novembeard", "november", + "nuetrality", "neutrality", + "nutricious", "nutritious", + "nutrientes", "nutrients", + "nutritents", "nutrients", + "nutritinal", "nutritional", + "nutritiuos", "nutritious", + "nutritivos", "nutritious", + "nutrituous", "nutritious", + "nutrutious", "nutritious", + "obatinable", "obtainable", + "obejctives", "objectives", + "obilgatory", "obligatory", + "objecitves", "objectives", + "objectivas", "objectives", + "objectivly", "objectively", + "objectivst", "objectives", + "objectivty", "objectivity", + "objektives", "objectives", + "obligitary", "obligatory", + "obligitory", "obligatory", + "observabil", "observable", + "observarse", "observers", + "observaton", "observation", + "observeras", "observers", + "observered", "observed", + "observeres", "observers", + "observible", "observable", + "obstancles", "obstacles", + "obstrucion", "obstruction", + "obstructin", "obstruction", + "obtainabie", "obtainable", + "obtaineble", "obtainable", + "obtainible", "obtainable", + "obtianable", "obtainable", + "ocasionaly", "occasionally", + "ocassional", "occasional", + "ocassioned", "occasioned", + "occaisonal", "occasional", + "occasionly", "occasional", + "occassions", "occasions", + "occational", "occasional", + "occulation", "occupation", + "occupaiton", "occupation", + "occurances", "occurrences", + "occurences", "occurrences", + "occurrance", "occurrence", + "octohedral", "octahedral", + "octohedron", "octahedron", + "offensivly", "offensively", + "offereings", "offerings", + "officailly", "officially", + "olbigatory", "obligatory", + "ominpotent", "omnipotent", + "ominscient", "omniscient", + "omnipetent", "omnipotent", + "omnipitent", "omnipotent", + "omnipotant", "omnipotent", + "omnisicent", "omniscient", + "omniverous", "omnivorous", + "omnsicient", "omniscient", + "on-premise", "on-premises", + "onmipotent", "omnipotent", + "onmiscient", "omniscient", + "operatings", "operations", + "operativne", "operative", + "operativos", "operations", + "oportunity", "opportunity", + "opponenets", "opponent", + "oppononent", "opponent", + "oppressiun", "oppressing", + "optimisitc", "optimistic", + "optimizare", "optimize", + "optimizate", "optimize", + "optimizied", "optimize", + "organicaly", "organically", + "organiclly", "organically", + "organisate", "organise", + "organische", "organise", + "organisera", "organizers", + "organisere", "organizers", + "organisert", "organizers", + "organisier", "organise", + "organisims", "organism", + "organismed", "organise", + "organismen", "organise", + "organismer", "organise", + "organismes", "organisms", + "organismus", "organisms", + "organisten", "organise", + "organiszed", "organise", + "organizaed", "organize", + "organizare", "organizer", + "organizate", "organize", + "organizors", "organizers", + "organizuje", "organize", + "organziers", "organizers", + "orientaion", "orientation", + "orientarla", "oriental", + "orientarlo", "oriental", + "origianlly", "originally", + "originales", "originals", + "originalet", "originated", + "originalis", "originals", + "originalty", "originality", + "orignially", "originally", + "origniated", "originated", + "origonally", "originally", + "origonated", "originated", + "ostencibly", "ostensibly", + "ostenisbly", "ostensibly", + "ostensably", "ostensibly", + "ostentibly", "ostensibly", + "ostrasiced", "ostracized", + "ostrasized", "ostracized", + "ostraziced", "ostracized", + "ostrazised", "ostracized", + "ostrecized", "ostracized", + "ostricized", "ostracized", + "ostrocized", "ostracized", + "oustanding", "outstanding", + "outcalssed", "outclassed", + "outlcassed", "outclassed", + "outnumberd", "outnumbered", + "outnumbred", "outnumbered", + "outperfoms", "outperform", + "outperfrom", "outperform", + "outpreform", "outperform", + "outrageuos", "outrageous", + "outragious", "outrageous", + "outragoues", "outrageous", + "outreagous", "outrageous", + "outsourcad", "outsourced", + "outsouring", "outsourcing", + "outsoursed", "outsourced", + "outweighes", "outweighs", + "overarcing", "overarching", + "overclockd", "overclocked", + "overcloked", "overclocked", + "overcoding", "overcoming", + "overheards", "overhead", + "overheared", "overhead", + "overhooked", "overlooked", + "overlanded", "overloaded", + "overlaoded", "overloaded", + "overlaping", "overlapping", + "overlauded", "overloaded", + "overloards", "overload", + "overlorded", "overloaded", + "overlordes", "overlords", + "overnurfed", "overturned", + "overpirced", "overpriced", + "overpowerd", "overpowered", + "overpowred", "overpowered", + "overprised", "overpriced", + "overtunned", "overturned", + "overtunred", "overturned", + "overturing", "overturn", + "overweigth", "overweight", + "overwhemed", "overwhelmed", + "overwieght", "overweight", + "overwritte", "overwrite", + "pahtfinder", "pathfinder", + "painfullly", "painfully", + "painkilers", "painkillers", + "pairlament", "parliament", + "pakistanti", "pakistani", + "paladinlst", "paladins", + "palcements", "placements", + "paleolitic", "paleolithic", + "palestinan", "palestinian", + "paltformer", "platformer", + "palyerbase", "playerbase", + "parachutte", "parachute", + "parademics", "paramedics", + "paradiggum", "paradigm", + "paragraghs", "paragraphs", + "paragrahps", "paragraphs", + "paragrapgh", "paragraphs", + "paragrpahs", "paragraphs", + "parahprase", "paraphrase", + "paralleles", "parallels", + "parallells", "parallels", + "paramadics", "paramedics", + "paramaters", "parameters", + "paramecias", "paramedics", + "parametics", "paramedics", + "parametros", "parameters", + "paramiters", "parameters", + "paramormal", "paranormal", + "paranoicas", "paranoia", + "paranomral", "paranormal", + "paranornal", "paranormal", + "parapharse", "paraphrase", + "paraphraze", "paraphrase", + "paraprhase", "paraphrase", + "parasitter", "parasite", + "parilament", "parliament", + "parituclar", "particular", + "parlaiment", "parliament", + "parliamant", "parliament", + "parliamone", "parliament", + "parliement", "parliament", + "parrallell", "parallel", + "parrallely", "parallelly", + "partiarchy", "patriarchy", + "participas", "participants", + "participat", "participants", + "participte", "participate", + "particualr", "particular", + "partiotism", "patriotism", + "passionais", "passions", + "passionale", "passionately", + "passionant", "passionate", + "passionite", "passionate", + "passivedns", "passives", + "passivelly", "passively", + "patenterad", "patented", + "pathfidner", "pathfinder", + "pathfindir", "pathfinder", + "pathifnder", "pathfinder", + "patientens", "patients", + "patrairchy", "patriarchy", + "patriachry", "patriarchy", + "patriarcal", "patriarchal", + "patriarhal", "patriarchal", + "patriatchy", "patriarchy", + "patriatism", "patriotism", + "patrionism", "patriotism", + "patriotics", "patriotism", + "patriotisk", "patriots", + "patroitism", "patriotism", + "patryarchy", "patriarchy", + "pedantisch", "pedantic", + "pedestiran", "pedestrian", + "pedestrain", "pedestrian", + "pedictions", "depictions", + "pedohpiles", "pedophiles", + "pedohpilia", "pedophilia", + "pedophilac", "pedophilia", + "pedophilea", "pedophilia", + "pedophilie", "pedophile", + "pedophilla", "pedophilia", + "pedophille", "pedophile", + "pedopholia", "pedophilia", + "penetraion", "penetration", + "penetratin", "penetration", + "penetraton", "penetration", + "penguinese", "penguins", + "penguiness", "penguins", + "peninsulla", "peninsula", + "penninsula", "peninsula", + "peodphiles", "pedophiles", + "peodphilia", "pedophilia", + "pepperment", "peppermint", + "pepperonni", "pepperoni", + "percantage", "percentage", + "percantile", "percentile", + "percaution", "precaution", + "percenatge", "percentages", + "percential", "percentile", + "percentige", "percentile", + "perceptoin", "perceptions", + "percession", "percussion", + "percetange", "percentages", + "percetnage", "percentages", + "percintile", "percentile", + "percission", "percussion", + "percpetion", "perceptions", + "percusions", "percussion", + "perdicting", "predicting", + "perdiction", "prediction", + "perdictive", "predictive", + "perenially", "perennially", + "perfeccion", "perfection", + "perfecxion", "perfection", + "perfektion", "perfection", + "perferable", "preferable", + "perferably", "preferably", + "perference", "preference", + "perferring", "preferring", + "perfexcion", "perfection", + "perfomance", "performance", + "performace", "performance", + "performane", "performances", + "performans", "performances", + "performens", "performers", + "performous", "performs", + "perfromers", "performers", + "perhiperal", "peripheral", + "peridinkle", "periwinkle", + "perihperal", "peripheral", + "periodisch", "periodic", + "periperhal", "peripheral", + "peripheals", "peripherals", + "peripheria", "peripheral", + "periphiral", "peripheral", + "periphreal", "peripheral", + "periphrial", "peripheral", + "peritinkle", "periwinkle", + "periwankle", "periwinkle", + "periwinkel", "periwinkle", + "periwinkie", "periwinkle", + "periwinlke", "periwinkle", + "permanenty", "permanently", + "permanetly", "permanently", + "permisions", "permission", + "permisison", "permissions", + "permissble", "permissible", + "permissibe", "permissible", + "permissons", "permissions", + "perogative", "prerogative", + "perordered", "preordered", + "perpatuate", "perpetuate", + "perpetualy", "perpetually", + "perpetuare", "perpetuate", + "persausion", "persuasion", + "persausive", "persuasive", + "persective", "respective", + "persectued", "persecuted", + "persecutie", "persecuted", + "persecutin", "persecution", + "perserving", "preserving", + "persicuted", "persecuted", + "persistant", "persistent", + "persistens", "persists", + "persoanlly", "personally", + "persocuted", "persecuted", + "personalie", "personalized", + "personalis", "personas", + "personarse", "personas", + "personatus", "personas", + "personnell", "personnel", + "perspecive", "perspective", + "perspectie", "perspectives", + "persuasian", "persuasion", + "persuasing", "persuasion", + "persuasivo", "persuasion", + "persuation", "persuasion", + "persucuted", "persecuted", + "persumably", "presumably", + "persussion", "persuasion", + "persvasive", "persuasive", + "perswasion", "persuasion", + "pertinante", "pertinent", + "pervailing", "prevailing", + "pervalence", "prevalence", + "pervention", "prevention", + "perversley", "perverse", + "pesitcides", "pesticides", + "pessimistc", "pessimistic", + "pessimitic", "pessimistic", + "pestacides", "pesticides", + "pestecides", "pesticides", + "pesticedes", "pesticides", + "pesticidas", "pesticides", + "pestisides", "pesticides", + "pestizides", "pesticides", + "pharamcist", "pharmacist", + "pharmacias", "pharmacist", + "pharmacyst", "pharmacist", + "pharmasist", "pharmacist", + "pharmicist", "pharmacist", + "phemonenon", "phenomenon", + "phenemenon", "phenomenon", + "phenemonal", "phenomenal", + "phenomanal", "phenomenal", + "phenomanon", "phenomenon", + "phenomemon", "phenomenon", + "phenomenen", "phenomenon", + "phenomenol", "phenomenal", + "phenomenom", "phenomenon", + "phenominon", "phenomenon", + "phenomonal", "phenomenal", + "phenomonen", "phenomenon", + "phenomonon", "phenomenon", + "phenonemal", "phenomenal", + "phenonemon", "phenomenon", + "phenonmena", "phenomena", + "philipines", "philippines", + "philippins", "philippines", + "philisophy", "philosophy", + "phillipine", "philippine", + "phillipses", "phillies", + "philosiphy", "philosophy", + "philosohpy", "philosophy", + "philosoper", "philosopher", + "philospher", "philosopher", + "philospohy", "philosophy", + "photogragh", "photograph", + "photograhs", "photographs", + "photograhy", "photography", + "photograps", "photographs", + "photograpy", "photography", + "photogrpah", "photographs", + "photoshopd", "photoshopped", + "photoshope", "photoshopped", + "phramacist", "pharmacist", + "phsyically", "physically", + "phsyicians", "physicians", + "phsyicists", "physicists", + "phsyiology", "physiology", + "phycisians", "physicians", + "phycisists", "physicists", + "phyiscally", "physically", + "phyisology", "physiology", + "physcially", "physically", + "physcology", "psychology", + "physcopath", "psychopath", + "physicials", "physicians", + "physiciens", "physicians", + "physioligy", "physiology", + "picthforks", "pitchforks", + "pinoneered", "pioneered", + "pitchferks", "pitchforks", + "pitchfolks", "pitchforks", + "pitchfords", "pitchforks", + "pitchworks", "pitchforks", + "pitckforks", "pitchforks", + "pittaburgh", "pittsburgh", + "pittsbrugh", "pittsburgh", + "placehoder", "placeholder", + "placeholdr", "placeholder", + "placeholer", "placeholder", + "placemenet", "placements", + "plagairism", "plagiarism", + "plagarisim", "plagiarism", + "plagiariam", "plagiarism", + "plagiarios", "plagiarism", + "plagiarius", "plagiarism", + "plagiarizm", "plagiarism", + "plagierism", "plagiarism", + "plaguarism", "plagiarism", + "plaigarism", "plagiarism", + "plasticosa", "plastics", + "platfarmer", "platformer", + "platformar", "platformer", + "platformie", "platformer", + "platfotmer", "platformer", + "platfromer", "platformer", + "platofrmer", "platformer", + "playaround", "playground", + "playersare", "playerbase", + "playgorund", "playground", + "playthrogh", "playthrough", + "playthrouh", "playthrough", + "playwrites", "playwrights", + "plethorian", "plethora", + "policitian", "politician", + "polinators", "pollinators", + "polishuset", "polishes", + "politessen", "politeness", + "politicain", "politician", + "politicaly", "politically", + "politicien", "politician", + "politicing", "politician", + "politicion", "politician", + "politickin", "politician", + "politiikan", "politician", + "politiness", "politeness", + "polititian", "politician", + "popualtion", "populations", + "populairty", "popularity", + "populaiton", "populations", + "popularaty", "popularity", + "popularest", "populate", + "popularily", "popularity", + "populaties", "populate", + "populatiry", "popularity", + "populative", "populate", + "populatoin", "populations", + "popultaion", "populations", + "pormetheus", "prometheus", + "pornograhy", "pornography", + "pornograpy", "pornography", + "pornogrphy", "pornography", + "porportion", "proportion", + "portabilty", "portability", + "portarying", "portraying", + "portoguese", "portuguese", + "portraiing", "portraying", + "portrating", "portraying", + "portrayels", "portrays", + "portugeuse", "portuguese", + "portuguise", "portuguese", + "posessions", "possessions", + "posicional", "positional", + "positevely", "positively", + "positioing", "positioning", + "positionly", "positional", + "positionne", "positioned", + "positivley", "positively", + "possesives", "possessive", + "possessers", "possesses", + "possessess", "possesses", + "possibiliy", "possibility", + "possibilty", "possibility", + "possissive", "possessive", + "posthomous", "posthumous", + "potentialy", "potentially", + "poulations", "populations", + "powerhorse", "powerhouse", + "powerhosue", "powerhouse", + "powerhours", "powerhouse", + "powerhsell", "powershell", + "powerprint", "powerpoint", + "powersehll", "powershell", + "ppublisher", "publisher", + "practially", "practically", + "practicaly", "practically", + "practicess", "practise", + "practiclly", "practically", + "practioner", "practitioner", + "precaucion", "precaution", + "precausion", "precaution", + "precautios", "precautions", + "precedance", "precedence", + "precedense", "precedence", + "preceeding", "preceding", + "precendece", "precedence", + "precentage", "percentage", + "precentile", "percentile", + "preciselly", "precisely", + "precuation", "precautions", + "precussion", "percussion", + "predecated", "predicated", + "predecence", "precedence", + "predecesor", "predecessor", + "predection", "prediction", + "predective", "predictive", + "prediccion", "prediction", + "prediceted", "predicated", + "predicited", "predicated", + "predicitng", "predicting", + "prediciton", "prediction", + "predicitve", "predictive", + "predickted", "predicated", + "predictave", "predictive", + "predictivo", "prediction", + "predictons", "predictions", + "predjuiced", "prejudiced", + "predjuices", "prejudices", + "preduction", "prediction", + "preductive", "predictive", + "predujiced", "prejudiced", + "predujices", "prejudices", + "prefarable", "preferable", + "prefarably", "preferably", + "prefection", "perfection", + "preferance", "preference", + "prefereble", "preferable", + "preferente", "preference", + "preferenze", "preference", + "preferible", "preferable", + "preferibly", "preferably", + "prefernece", "preferences", + "preformers", "performers", + "pregancies", "pregnancies", + "pregnanies", "pregnancies", + "preipheral", "peripheral", + "preisdents", "presidents", + "preisthood", "priesthood", + "prejeduced", "prejudiced", + "prejeduces", "prejudices", + "prejiduced", "prejudiced", + "prejiduces", "prejudices", + "prejucided", "prejudiced", + "prejucides", "prejudices", + "prejuduced", "prejudiced", + "prejuduces", "prejudices", + "prelimiary", "preliminary", + "prematurly", "prematurely", + "preminence", "preeminence", + "premission", "permission", + "preorderes", "preorders", + "prepartion", "preparation", + "prepetuate", "perpetuate", + "preposters", "preposterous", + "prescients", "presidents", + "prescirbed", "prescribed", + "prescriped", "prescribed", + "presearing", "preserving", + "presecuted", "persecuted", + "presedency", "presidency", + "presedents", "presidents", + "presenning", "presenting", + "presentase", "presents", + "presentato", "presentation", + "presention", "presenting", + "presentors", "presents", + "preservare", "preserve", + "preservato", "preservation", + "preserverd", "preserved", + "presidancy", "presidency", + "presidante", "presidents", + "presidenta", "presidential", + "presidenty", "presidency", + "presidunce", "presidency", + "presistent", "persistent", + "presonally", "personally", + "presonhood", "personhood", + "pressuming", "pressuring", + "prestigios", "prestigious", + "prestigous", "prestigious", + "presuambly", "presumably", + "presuasion", "persuasion", + "presuasive", "persuasive", + "presumebly", "presumably", + "presumendo", "presumed", + "presumibly", "presumably", + "presumpton", "presumption", + "pretaining", "pertaining", + "pretection", "protection", + "pretendias", "pretends", + "pretensive", "pretense", + "pretentios", "pretentious", + "pretentous", "pretentious", + "prevalecen", "prevalence", + "prevalente", "prevalence", + "prevencion", "prevention", + "preventivo", "prevention", + "preventors", "prevents", + "previaling", "prevailing", + "previosuly", "previously", + "previoulsy", "previously", + "prevolence", "prevalence", + "pricinpals", "principals", + "primarilly", "primarily", + "primatives", "primitives", + "princepals", "principals", + "princesess", "princesses", + "princibles", "principles", + "principaly", "principality", + "principels", "principals", + "principial", "principal", + "principias", "principals", + "principlas", "principals", + "prinicipal", "principal", + "prinicpals", "principals", + "prinicples", "principles", + "printerest", "printers", + "prioratize", "prioritize", + "prioretize", "prioritize", + "prioritice", "prioritize", + "prioritied", "prioritize", + "prioroties", "priorities", + "priorotize", "prioritize", + "priotities", "priorities", + "priotitize", "prioritize", + "privaleged", "privileged", + "privaleges", "privileges", + "privaticed", "privatized", + "privelaged", "privileged", + "privelages", "privileges", + "priveldges", "privileges", + "priveleged", "privileged", + "priveleges", "privileges", + "privelidge", "privileged", + "priveliged", "privileged", + "priveliges", "privileges", + "privetized", "privatized", + "privilaged", "privileged", + "privilages", "privileges", + "priviledge", "privilege", + "privilegde", "privileges", + "privilegie", "privilege", + "priviliged", "privileged", + "priviliges", "privileges", + "privitazed", "privatized", + "privitized", "privatized", + "probabiliy", "probability", + "probabilty", "probability", + "probablies", "probable", + "probablybe", "probable", + "problemita", "problematic", + "procalimed", "proclaimed", + "procceding", "proceeding", + "procedding", "proceeding", + "procederal", "procedural", + "procedings", "proceedings", + "procedrual", "procedural", + "proceededs", "proceeds", + "proceedure", "procedure", + "proceesing", "proceeding", + "processsor", "processors", + "proclamied", "proclaimed", + "proclaming", "proclaiming", + "procliamed", "proclaimed", + "procreatin", "procreation", + "procudures", "procedures", + "prodcution", "production", + "prodecural", "procedural", + "prodecures", "procedures", + "produccion", "production", + "produceras", "produces", + "produceres", "produces", + "producirse", "producers", + "produciton", "production", + "producting", "production", + "productino", "productions", + "productivo", "production", + "productivy", "productivity", + "productoin", "productions", + "produktion", "production", + "produktive", "productive", + "produtcion", "productions", + "profesions", "profession", + "professers", "professors", + "professorn", "profession", + "professsor", "professors", + "proffesion", "profession", + "proficeint", "proficient", + "proficiant", "proficient", + "proficieny", "proficiency", + "proficincy", "proficiency", + "profitabel", "profitable", + "profitabil", "profitable", + "profitible", "profitable", + "proftiable", "profitable", + "programmar", "programmer", + "programmme", "programme", + "progresing", "progressing", + "progresion", "progression", + "progresive", "progressive", + "progressie", "progressives", + "progressin", "progression", + "progresson", "progression", + "progressos", "progresses", + "progressus", "progresses", + "prohibirte", "prohibit", + "prohibites", "prohibits", + "prohibitng", "prohibiting", + "prohibiton", "prohibition", + "prohibitus", "prohibits", + "prohibitve", "prohibited", + "prohobited", "prohibited", + "prohpecies", "prophecies", + "projecitle", "projectiles", + "projectiel", "projectiles", + "projecties", "projectiles", + "projectils", "projectiles", + "projectles", "projectiles", + "projectlie", "projectiles", + "projectyle", "projectile", + "projektile", "projectile", + "projektion", "projection", + "prometheas", "prometheus", + "promethese", "prometheus", + "promethius", "prometheus", + "promethous", "prometheus", + "promethues", "prometheus", + "prominance", "prominence", + "prominenty", "prominently", + "prominetly", "prominently", + "promiscous", "promiscuous", + "promiscuos", "promiscuous", + "promoteurs", "promotes", + "promotheus", "prometheus", + "promotinal", "promotional", + "pronoucned", "pronounced", + "pronouning", "pronouncing", + "propechies", "prophecies", + "propencity", "propensity", + "propenents", "proponents", + "properites", "properties", + "propersity", "propensity", + "propertion", "proportion", + "propertius", "properties", + "prophacies", "prophecies", + "prophocies", "prophecies", + "propietary", "proprietary", + "proplusion", "propulsion", + "propoganda", "propaganda", + "propogates", "propagates", + "propolsion", "propulsion", + "proponants", "proponents", + "proponenet", "proponent", + "proporcion", "proportion", + "proporties", "properties", + "proporting", "proportion", + "propositon", "proposition", + "propotions", "proportions", + "proprietry", "proprietary", + "proprotion", "proportion", + "propserity", "prosperity", + "propserous", "prosperous", + "propulaios", "propulsion", + "propulsing", "propulsion", + "propultion", "propulsion", + "propuslion", "propulsion", + "prosectued", "prosecuted", + "prosectuor", "prosecutor", + "prosecuter", "prosecutor", + "prosecutie", "prosecuted", + "prosicuted", "prosecuted", + "prosicutor", "prosecutor", + "prosocuted", "prosecuted", + "prosparity", "prosperity", + "prospectos", "prospects", + "prosperety", "prosperity", + "prospertiy", "prosperity", + "prosphetic", "prosthetic", + "prosporous", "prosperous", + "prostehtic", "prosthetic", + "prosterity", "prosperity", + "prostethic", "prosthetic", + "prostitite", "prostitute", + "prostitude", "prostitute", + "prostituee", "prostitute", + "prostituer", "prostitute", + "prostitues", "prostitutes", + "prostiture", "prostitute", + "prostituto", "prostitution", + "prostituye", "prostitute", + "protaginst", "protagonist", + "protastant", "protestant", + "proteccion", "protection", + "proteciton", "protections", + "protectice", "protective", + "protectiei", "protective", + "protectoin", "protections", + "protectons", "protectors", + "protectron", "protection", + "protestans", "protests", + "protestare", "protesters", + "protestato", "protestant", + "protestent", "protestant", + "protestina", "protestant", + "prothsetic", "prosthetic", + "protistant", "protestant", + "protocoles", "protocols", + "protocolls", "protocols", + "protocolos", "protocols", + "protohypes", "prototypes", + "protostant", "protestant", + "prototipes", "prototypes", + "prototpyes", "prototypes", + "protraying", "portraying", + "protuguese", "portuguese", + "provencial", "provincial", + "proveribal", "proverbial", + "provervial", "proverbial", + "providance", "providence", + "providince", "providence", + "provinciae", "province", + "provincies", "province", + "provincija", "provincial", + "provinence", "providence", + "provinical", "provincial", + "provintial", "provincial", + "provinvial", "provincial", + "provisiosn", "provision", + "provisonal", "provisional", + "provocatie", "provocative", + "pscyhology", "psychology", + "pscyhopath", "psychopath", + "pshycology", "psychology", + "pshycopath", "psychopath", + "psychedlic", "psychedelic", + "psychiatic", "psychiatric", + "psycholoog", "psychology", + "psychopaat", "psychopath", + "psychopats", "psychopaths", + "ptichforks", "pitchforks", + "publicitan", "publication", + "publisheed", "published", + "publisherr", "publisher", + "publishher", "publisher", + "publissher", "publisher", + "publlisher", "publisher", + "punihsment", "punishments", + "punishemnt", "punishments", + "punishible", "punishable", + "punishmnet", "punishments", + "punissable", "punishable", + "punsihable", "punishable", + "purchacing", "purchasing", + "purpolsion", "propulsion", + "purposedly", "purposely", + "purposelly", "purposely", + "purpotedly", "purportedly", + "pususading", "persuading", + "pyschology", "psychology", + "pyschopath", "psychopath", + "qaulifiers", "qualifiers", + "quailfiers", "qualifiers", + "qualfiiers", "qualifiers", + "qualifieds", "qualifies", + "qualifiies", "qualifiers", + "qualifiing", "qualifying", + "qualifires", "qualifiers", + "qualifyers", "qualifiers", + "qualitying", "qualifying", + "quanitites", "quantities", + "quantaties", "quantities", + "quantitize", "quantities", + "quarantena", "quarantine", + "quarantene", "quarantine", + "quarantied", "quarantine", + "quarintine", "quarantine", + "quaruntine", "quarantine", + "quesitoned", "questioned", + "questional", "questionable", + "questionne", "questioned", + "rabinnical", "rabbinical", + "radiactive", "radioactive", + "radioacive", "radioactive", + "rainbowers", "rainbows", + "randmoness", "randomness", + "randomzied", "randomized", + "randonmess", "randomness", + "randumness", "randomness", + "raspberrry", "raspberry", + "rationalle", "rationale", + "readmition", "readmission", + "realitvely", "relatively", + "realtively", "relatively", + "realtivity", "relativity", + "reaserched", "researched", + "reasercher", "researcher", + "rebiulding", "rebuilding", + "reboudning", "rebounding", + "rebouncing", "rebounding", + "rebuidling", "rebuilding", + "rebuliding", "rebuilding", + "rebuplican", "republican", + "reccommend", "recommend", + "recepients", "recipients", + "receptoras", "receptors", + "receptores", "receptors", + "recgonised", "recognised", + "recgonized", "recognized", + "recgonizes", "recognizes", + "reciepents", "recipients", + "recipeints", "recipients", + "recipiants", "recipients", + "recocnised", "recognised", + "recoginsed", "recognised", + "recoginzed", "recognized", + "recognices", "recognizes", + "recogniton", "recognition", + "recognzied", "recognised", + "recomended", "recommended", + "recommande", "recommend", + "recommands", "recommends", + "recommeded", "recommended", + "recommened", "recommend", + "recommennd", "recommends", + "recomments", "recommends", + "recompence", "recompense", + "reconcider", "reconsider", + "reconcille", "reconcile", + "recongised", "recognised", + "recongized", "recognized", + "recongizes", "recognizes", + "reconisder", "reconsider", + "reconsiled", "reconsider", + "recordarle", "recorder", + "recordarme", "recorder", + "recordarse", "recorder", + "recordarte", "recorder", + "recreacion", "recreation", + "recreatief", "recreate", + "recreativo", "recreation", + "recrutiers", "recruiters", + "rectanglar", "rectangular", + "rectangual", "rectangular", + "rectanguar", "rectangular", + "recuriters", "recruiters", + "recurrance", "recurrence", + "recursivly", "recursively", + "redefinied", "redefine", + "redefinine", "redefine", + "redemtpion", "redemption", + "redepmtion", "redemption", + "redesiging", "redesign", + "rediculous", "ridiculous", + "redmeption", "redemption", + "redneckers", "rednecks", + "redneckese", "rednecks", + "redneckest", "rednecks", + "reduncancy", "redundancy", + "redundency", "redundancy", + "redundnacy", "redundancy", + "redunduncy", "redundancy", + "reenforced", "reinforced", + "reevaulate", "reevaluate", + "refedendum", "referendum", + "refelcting", "reflecting", + "refelction", "reflection", + "refelctive", "reflective", + "referances", "references", + "referandum", "referendum", + "referemces", "references", + "referemdum", "referendum", + "referendim", "referendum", + "referendom", "referendum", + "referenece", "reference", + "referening", "referencing", + "referenses", "referees", + "referentes", "references", + "referneces", "references", + "referrence", "reference", + "referundum", "referendum", + "refference", "reference", + "refleciton", "reflections", + "reflecters", "reflects", + "reflektion", "reflection", + "reflextion", "reflection", + "reformerad", "reformed", + "refrigerar", "refrigerator", + "refurbised", "refurbished", + "regenarate", "regenerate", + "registeres", "registers", + "registrato", "registration", + "regresives", "regressive", + "regressivo", "regression", + "regualting", "regulating", + "regualtion", "regulations", + "regualtors", "regulators", + "regulacion", "regulation", + "regulament", "regulate", + "regulaotrs", "regulators", + "regularily", "regularly", + "regularing", "regulating", + "regularlas", "regulars", + "regularlos", "regulars", + "regulaters", "regulators", + "regulatios", "regulators", + "regulatons", "regulations", + "rehtorical", "rhetorical", + "reinstaled", "reinstalled", + "reitrement", "retirement", + "relagation", "relaxation", + "relatation", "relaxation", + "relativety", "relativity", + "relativily", "relativity", + "relativley", "relatively", + "relavation", "relaxation", + "relaxating", "relaxation", + "relazation", "relaxation", + "releagtion", "relegation", + "relegetion", "relegation", + "relentness", "relentless", + "reletnless", "relentless", + "relevation", "revelation", + "relexation", "relegation", + "relfecting", "reflecting", + "relfection", "reflection", + "relfective", "reflective", + "reliabilty", "reliability", + "reliablely", "reliably", + "religiones", "religions", + "religiosly", "religiously", + "religiousy", "religiously", + "religously", "religiously", + "relitavely", "relatively", + "reluctanct", "reluctant", + "reluctanly", "reluctantly", + "reluctanty", "reluctantly", + "remarcably", "remarkably", + "remarkibly", "remarkably", + "rememberes", "remembers", + "remenicent", "reminiscent", + "reminisent", "reminiscent", + "reminscent", "reminiscent", + "remmebered", "remembered", + "renaissace", "renaissance", + "renderered", "rendered", + "renegerate", "regenerate", + "renewabels", "renewables", + "renewebles", "renewables", + "rennovated", "renovated", + "renweables", "renewables", + "repatition", "repetition", + "repblicans", "republicans", + "repbulican", "republican", + "repeadedly", "repeatedly", + "repeadetly", "repeatedly", + "repearable", "repeatable", + "repearedly", "repealed", + "repeatadly", "repeatedly", + "repeatedlt", "repealed", + "repeatetly", "repeatedly", + "repeatible", "repeatable", + "repeatidly", "repeatedly", + "repectable", "repeatable", + "repentable", "repeatable", + "repentence", "repentance", + "repersents", "represents", + "repetation", "repetition", + "repeteadly", "repeatedly", + "repetetion", "repetition", + "repeticion", "repetition", + "repetitivo", "repetition", + "replacated", "replicated", + "replaceble", "replaceable", + "replacemet", "replacements", + "replacemnt", "replacement", + "replacemtn", "replacements", + "replecated", "replicated", + "repoistory", "repository", + "reponsible", "responsible", + "reportadly", "reportedly", + "reporteros", "reporters", + "reportidly", "reportedly", + "repositary", "repository", + "reposotory", "repository", + "repostiory", "repository", + "representn", "representing", + "repressent", "represents", + "repressivo", "repression", + "repsectful", "respectful", + "repsecting", "respecting", + "repsective", "respective", + "repsonding", "responding", + "repsonsive", "responsive", + "reptuation", "reputation", + "repubicans", "republicans", + "republcian", "republican", + "republians", "republicans", + "republicon", "republican", + "repuglican", "republican", + "repulicans", "republicans", + "reputacion", "reputation", + "requirment", "requirement", + "requrement", "requirement", + "resemblace", "resemble", + "reserached", "researched", + "reseracher", "researchers", + "reserverad", "reserved", + "reservered", "reserved", + "residental", "residential", + "resistable", "resistible", + "resistanes", "resistances", + "resistanse", "resistances", + "resistence", "resistance", + "resistendo", "resisted", + "resistered", "resisted", + "resistnace", "resistances", + "resitsance", "resistances", + "resoltuion", "resolutions", + "resolucion", "resolution", + "resolutino", "resolutions", + "resolutoin", "resolutions", + "resolutons", "resolutions", + "resolvemos", "resolves", + "resolvendo", "resolved", + "resolveres", "resolves", + "resolverse", "resolves", + "resolviste", "resolves", + "resonabelt", "resonate", + "resoultion", "resolution", + "respecitve", "respective", + "respectifs", "respects", + "respection", "respecting", + "respectons", "respects", + "respectuos", "respects", + "respektive", "respective", + "respiratoy", "respiratory", + "responcive", "responsive", + "responisve", "responsive", + "responsibe", "responsive", + "responsiby", "responsibly", + "responsile", "responsive", + "responsing", "responding", + "ressembled", "resembled", + "restarants", "restaurants", + "restaraunt", "restaurant", + "restaruant", "restaurant", + "restatting", "restarting", + "restaurent", "restaurant", + "restauring", "restarting", + "resteraunt", "restaurant", + "restircted", "restricted", + "restorting", "restarting", + "restrainig", "restraining", + "restrcited", "restricted", + "restrcting", "restarting", + "restricing", "restricting", + "restricion", "restriction", + "restricive", "restrictive", + "restrictes", "restricts", + "restrictie", "restrictive", + "restricton", "restriction", + "restructed", "restricted", + "restuarant", "restaurant", + "resturants", "restaurants", + "resturaunt", "restaurant", + "retaliaton", "retaliation", + "rethorical", "rhetorical", + "retierment", "retirement", + "retribuito", "retribution", + "retrosepct", "retrospect", + "retrospekt", "retrospect", + "revaluated", "reevaluated", + "revealtion", "revelations", + "revelaiton", "revelations", + "revelatons", "revelations", + "revelution", "revelation", + "reversable", "reversible", + "reversably", "reversal", + "reviewtrue", "reviewer", + "revisiones", "revisions", + "revisionis", "revisions", + "revoltuion", "revolution", + "revoluiton", "revolutions", + "revolutoin", "revolutions", + "revoultion", "revolution", + "rewarching", "rewatching", + "rewatchibg", "rewatching", + "rewatchign", "rewatching", + "rewatchimg", "rewatching", + "rhapsodomy", "rhapsody", + "rhetorisch", "rhetoric", + "ridicilous", "ridiculous", + "ridicoulus", "ridiculous", + "ridiculise", "ridicule", + "ridiculize", "ridicule", + "ridiculled", "ridicule", + "ridiculose", "ridicule", + "ridiculued", "ridicule", + "rienforced", "reinforced", + "rigthfully", "rightfully", + "roleplaing", "roleplaying", + "romanmania", "romanian", + "roundaboot", "roundabout", + "rucuperate", "recuperate", + "rudimentry", "rudimentary", + "sacarmento", "sacramento", + "sacntioned", "sanctioned", + "sacraficed", "sacrificed", + "sacrafices", "sacrifices", + "sacramenno", "sacramento", + "sacreficed", "sacrificed", + "sacrefices", "sacrifices", + "sacremento", "sacramento", + "sacrifaced", "sacrificed", + "sacrifaces", "sacrifices", + "sacrifical", "sacrificial", + "sacrificas", "sacrifices", + "sacrificie", "sacrificed", + "sacrificng", "sacrificing", + "sacrifises", "sacrifices", + "sacrifized", "sacrificed", + "sacrifizes", "sacrifices", + "sacromento", "sacramento", + "sadistisch", "sadistic", + "sanctionne", "sanctioned", + "sandiwches", "sandwiches", + "sandviches", "sandwiches", + "sandwishes", "sandwiches", + "sanitazion", "sanitation", + "santiation", "sanitation", + "sastifying", "satisfying", + "satellitte", "satellites", + "satifsying", "satisfying", + "satrically", "satirically", + "satsifying", "satisfying", + "sattelites", "satellites", + "saturacion", "saturation", + "scandalosa", "scandals", + "scandalose", "scandals", + "scandalosi", "scandals", + "scandaloso", "scandals", + "scandaniva", "scandinavia", + "scandinava", "scandinavian", + "scandinvia", "scandinavia", + "scaramento", "sacramento", + "scarificed", "sacrificed", + "scarifices", "sacrifices", + "scarmbling", "scrambling", + "scartching", "scratching", + "sceintific", "scientific", + "sceintists", "scientists", + "scenarioes", "scenarios", + "scenarions", "scenarios", + "scenarious", "scenarios", + "scheudling", "scheduling", + "scholarhip", "scholarship", + "scholarley", "scholarly", + "sciencists", "scientists", + "scientests", "scientists", + "scirptures", "scriptures", + "scooterers", "scooters", + "scorebaord", "scoreboard", + "scoreborad", "scoreboard", + "scorebored", "scoreboard", + "scorpiomon", "scorpion", + "scracthing", "scratching", + "scramblies", "scramble", + "screenshat", "screenshot", + "screenshit", "screenshot", + "scriptores", "scriptures", + "scripturae", "scriptures", + "scriputres", "scriptures", + "scritpures", "scriptures", + "scrutinity", "scrutiny", + "seahawkers", "seahawks", + "sebastiaan", "sebastian", + "segegrated", "segregated", + "segragated", "segregated", + "segregaded", "segregated", + "segregatie", "segregated", + "segretated", "segregated", + "segrigated", "segregated", + "selectiose", "selections", + "selectivly", "selectively", + "selectivos", "selections", + "selfishess", "selfishness", + "senitments", "sentiments", + "sensitiviy", "sensitivity", + "sensitivty", "sensitivity", + "sentaments", "sentiments", + "sentancing", "sentencing", + "sentements", "sentiments", + "sentencian", "sentencing", + "sentensing", "sentencing", + "sentimenal", "sentimental", + "sentimetal", "sentimental", + "sentincing", "sentencing", + "sentinents", "sentiments", + "separacion", "separation", + "separaters", "separates", + "separatley", "separately", + "separatron", "separation", + "separetely", "separately", + "seperately", "separately", + "seperating", "separating", + "seperation", "separation", + "seperatism", "separatism", + "seperatist", "separatist", + "seperatley", "seperate", + "sepulchure", "sepulchre", + "serenitary", "serenity", + "serviceble", "serviceable", + "settelment", "settlement", + "settlemens", "settlements", + "settlemets", "settlements", + "settlemnts", "settlements", + "seuxalized", "sexualized", + "seventeeen", "seventeen", + "sexaulized", "sexualized", + "sexualixed", "sexualized", + "sexuallity", "sexually", + "sexualzied", "sexualized", + "sexulaized", "sexualized", + "shakespare", "shakespeare", + "shakespeer", "shakespeare", + "shakespere", "shakespeare", + "shamelesly", "shamelessly", + "shamelessy", "shamelessly", + "shaprening", "sharpening", + "shareholds", "shareholders", + "sharkening", "sharpening", + "sharpining", "sharpening", + "shartening", "sharpening", + "shatnering", "shattering", + "shattening", "shattering", + "shepharded", "shepherd", + "shilouette", "silhouette", + "shitlasses", "shitless", + "shortenend", "shortened", + "shortining", "shortening", + "sidelinien", "sideline", + "sidelinjen", "sideline", + "sidelinked", "sideline", + "sigantures", "signatures", + "sightstine", "sightstone", + "signficant", "significant", + "signifiant", "significant", + "significat", "significant", + "signitures", "signatures", + "sigthstone", "sightstone", + "sihlouette", "silhouette", + "silohuette", "silhouette", + "silouhette", "silhouette", + "similairty", "similarity", + "similarily", "similarly", + "similarlly", "similarly", + "similiarly", "similarly", + "similiarty", "similarity", + "simliarity", "similarity", + "simluation", "simulation", + "simplictic", "simplistic", + "simplifing", "simplifying", + "simplifyed", "simplified", + "simplifyng", "simplifying", + "simplisitc", "simplistic", + "simplisity", "simplicity", + "simplistes", "simplest", + "simplivity", "simplicity", + "simplyfied", "simplified", + "simualtion", "simulation", + "simulacion", "simulation", + "simulaiton", "simulations", + "simulaties", "simulate", + "simulative", "simulate", + "simulatons", "simulations", + "simulatore", "simulate", + "sincereley", "sincerely", + "sincerelly", "sincerely", + "singatures", "signatures", + "singulaire", "singular", + "singulariy", "singularity", + "singularty", "singularity", + "singulator", "singular", + "sitautions", "situations", + "situatinal", "situational", + "skatebaord", "skateboard", + "skateborad", "skateboard", + "skatebored", "skateboard", + "skatebrand", "skateboard", + "skeletones", "skeletons", + "skeptecism", "skepticism", + "skepticals", "skeptics", + "skepticles", "skeptics", + "skepticons", "skeptics", + "skeptisicm", "skepticism", + "skeptisism", "skepticism", + "sketchysex", "sketches", + "sketpicism", "skepticism", + "skillhosts", "skillshots", + "skillshits", "skillshots", + "skillshoot", "skillshots", + "skillslots", "skillshots", + "skillsofts", "skillshots", + "skillsshot", "skillshots", + "skirmiches", "skirmish", + "skpeticism", "skepticism", + "slaughterd", "slaughtered", + "slipperies", "slippers", + "smarpthone", "smartphones", + "smarthpone", "smartphone", + "snadwiches", "sandwiches", + "snowbaling", "snowballing", + "snowballes", "snowballs", + "snowballls", "snowballs", + "socailists", "socialists", + "socailized", "socialized", + "socialisim", "socialism", + "socializng", "socializing", + "socialsits", "socialists", + "sociapaths", "sociopaths", + "socilaists", "socialists", + "socilaized", "socialized", + "sociologia", "sociological", + "sociopatas", "sociopaths", + "sociopatch", "sociopaths", + "sociopatic", "sociopathic", + "socratease", "socrates", + "socreboard", "scoreboard", + "soemthings", "somethings", + "soldiarity", "solidarity", + "solidairty", "solidarity", + "soliditary", "solidarity", + "solitudine", "solitude", + "somehtings", "somethings", + "someonelse", "someones", + "somethibng", "somethin", + "somethigng", "somethin", + "somethigns", "somethings", + "somethihng", "somethin", + "somethiing", "somethin", + "somethijng", "somethin", + "somethikng", "somethin", + "somethimng", "somethin", + "somethinbg", "somethings", + "somethines", "somethings", + "somethinfg", "somethings", + "somethinhg", "somethings", + "somethinig", "somethings", + "somethinkg", "somethings", + "somethinks", "somethings", + "somethinmg", "somethings", + "somethinng", "somethings", + "somethintg", "somethings", + "somethiong", "somethin", + "somethiung", "somethin", + "sophicated", "sophisticated", + "sotrmfront", "stormfront", + "sotrylines", "storylines", + "soudntrack", "soundtrack", + "soundrtack", "soundtracks", + "soundtracs", "soundtracks", + "soundtrakc", "soundtracks", + "soundtrakk", "soundtrack", + "soundtraks", "soundtracks", + "southampon", "southampton", + "southamton", "southampton", + "southerers", "southerners", + "southernes", "southerners", + "southerton", "southern", + "souveniers", "souvenirs", + "sovereigny", "sovereignty", + "sovereinty", "sovereignty", + "soverignty", "sovereignty", + "spartaniis", "spartans", + "spartanops", "spartans", + "specailist", "specialist", + "specailize", "specializes", + "specialice", "specialize", + "specialied", "specialized", + "specialies", "specializes", + "specialits", "specials", + "speciallly", "specially", + "speciallty", "specially", + "specialops", "specials", + "specialsts", "specialists", + "specialtys", "specials", + "specialzed", "specialized", + "specialzes", "specializes", + "specifices", "specifics", + "specifiing", "specifying", + "specifiyng", "specifying", + "speciliast", "specialists", + "specimines", "specimen", + "spectarors", "spectators", + "spectaters", "spectators", + "spectracal", "spectral", + "spectraply", "spectral", + "spectrolab", "spectral", + "speculatie", "speculative", + "speculatin", "speculation", + "speecheasy", "speeches", + "speicalist", "specialist", + "spiritualy", "spiritually", + "sponsorees", "sponsors", + "sponsorhip", "sponsorship", + "sponsorise", "sponsors", + "spontaneos", "spontaneous", + "spontaneus", "spontaneous", + "spontanous", "spontaneous", + "spoonfulls", "spoonfuls", + "spreadshet", "spreadsheet", + "springfeld", "springfield", + "springfied", "springfield", + "spriritual", "spiritual", + "squirrells", "squirrels", + "squirrelus", "squirrels", + "stabelized", "stabilized", + "stabilzied", "stabilized", + "stablility", "stability", + "stablizied", "stabilized", + "staggaring", "staggering", + "stakeboard", "skateboard", + "starighten", "straighten", + "starnation", "starvation", + "startegies", "strategies", + "startupbus", "startups", + "starwberry", "strawberry", + "statememts", "statements", + "statictics", "statistics", + "stationair", "stationary", + "statisitcs", "statistics", + "statistcal", "statistical", + "statistisk", "statistics", + "stauration", "saturation", + "stealthboy", "stealthy", + "stealthely", "stealthy", + "stealthify", "stealthy", + "stealthray", "stealthy", + "steeleries", "steelers", + "stereotipe", "stereotype", + "stereotpye", "stereotypes", + "steriotype", "stereotype", + "steroetype", "stereotype", + "sterotypes", "stereotypes", + "steryotype", "stereotype", + "stimilants", "stimulants", + "stimilated", "stimulated", + "stimualted", "stimulated", + "stimulatie", "stimulated", + "stimulatin", "stimulation", + "stimulaton", "stimulation", + "stimulents", "stimulants", + "stomrfront", "stormfront", + "storelines", "storylines", + "stormfornt", "stormfront", + "stormfromt", "stormfront", + "stornfront", "stormfront", + "stornghold", "stronghold", + "stradegies", "strategies", + "strageties", "strategies", + "straighted", "straightened", + "straightie", "straighten", + "straightin", "straighten", + "straigthen", "straighten", + "stranglove", "strangle", + "strangreal", "strangle", + "stratagies", "strategies", + "strategems", "strategies", + "strategice", "strategies", + "strategisk", "strategies", + "stravation", "starvation", + "strawbarry", "strawberry", + "strawbeary", "strawberry", + "strawbeery", "strawberry", + "strawbrary", "strawberry", + "strawburry", "strawberry", + "streaching", "stretching", + "streamtrue", "streamer", + "strechting", "stretching", + "strecthing", "stretching", + "stregnthen", "strengthen", + "streichung", "stretching", + "strenghten", "strengthen", + "strengsten", "strengthen", + "strengthes", "strengths", + "strengthin", "strengthen", + "stressende", "stressed", + "striaghten", "straighten", + "stromfront", "stormfront", + "stronkhold", "stronghold", + "stroylines", "storylines", + "structered", "structured", + "structrual", "structural", + "structurel", "structural", + "strucutral", "structural", + "strucutred", "structured", + "strucutres", "structures", + "strugglign", "struggling", + "strwaberry", "strawberry", + "sttutering", "stuttering", + "stupidfree", "stupider", + "stupiditiy", "stupidity", + "sturctural", "structural", + "sturctures", "structures", + "sturggling", "struggling", + "subarmines", "submarines", + "subcultuur", "subculture", + "subesquent", "subsequent", + "subisdized", "subsidized", + "subjectief", "subjective", + "subjectifs", "subjects", + "subjectivy", "subjectively", + "subjektive", "subjective", + "submariens", "submarines", + "submarinas", "submarines", + "submergerd", "submerged", + "submerines", "submarines", + "submisison", "submissions", + "submissies", "submissive", + "submissons", "submissions", + "submittion", "submitting", + "subsadized", "subsidized", + "subscirbed", "subscribed", + "subscirber", "subscribers", + "subscribar", "subscriber", + "subscribir", "subscriber", + "subscrible", "subscriber", + "subscriped", "subscribed", + "subscrubed", "subscribed", + "subscryber", "subscriber", + "subsedized", "subsidized", + "subsequant", "subsequent", + "subsidezed", "subsidized", + "subsidiced", "subsidized", + "subsidizng", "subsidizing", + "subsiduary", "subsidiary", + "subsiquent", "subsequent", + "subsittute", "substitutes", + "subsizided", "subsidized", + "subsrcibed", "subscribed", + "substanial", "substantial", + "substansen", "substances", + "substanser", "substances", + "substanses", "substances", + "substantie", "substantive", + "substatial", "substantial", + "substences", "substances", + "substitite", "substitute", + "substittue", "substitutes", + "substitude", "substitute", + "substitued", "substitute", + "substituer", "substitute", + "substitues", "substitutes", + "substiture", "substitute", + "substituto", "substitution", + "substituts", "substitutes", + "substracts", "subtracts", + "substutite", "substitutes", + "subsudized", "subsidized", + "subtitltes", "subtitle", + "succceeded", "succeeded", + "succcesses", "successes", + "succesfuly", "successfully", + "succesions", "succession", + "successing", "succession", + "successivo", "succession", + "sucesfully", "successfully", + "sucessfull", "successful", + "sucessfuly", "successfully", + "sudnerland", "sunderland", + "sufferered", "suffered", + "sufferring", "suffering", + "sufficiant", "sufficient", + "suggestied", "suggestive", + "suggestief", "suggestive", + "suggestons", "suggests", + "sumbarines", "submarines", + "sumbissive", "submissive", + "sumbitting", "submitting", + "summerized", "summarized", + "summorized", "summarized", + "summurized", "summarized", + "sunderlona", "sunderland", + "sunderlund", "sunderland", + "sungalsses", "sunglasses", + "sunglesses", "sunglasses", + "sunglinger", "gunslinger", + "sunscreeen", "sunscreen", + "superfical", "superficial", + "superfluos", "superfluous", + "superioara", "superior", + "superioare", "superior", + "superioris", "superiors", + "superivsor", "supervisors", + "supermaket", "supermarket", + "supermarkt", "supermarket", + "superouman", "superhuman", + "superposer", "superpowers", + "superviors", "supervisors", + "superviosr", "supervisors", + "supervisar", "supervisor", + "superviser", "supervisor", + "supervisin", "supervision", + "supervison", "supervision", + "supervsior", "supervisors", + "supperssor", "suppressor", + "supplament", "supplement", + "supplemant", "supplemental", + "supplemets", "supplements", + "supportare", "supporters", + "supporteur", "supporter", + "supportied", "supported", + "supportors", "supporters", + "supposdely", "supposedly", + "supposebly", "supposedly", + "supposidly", "supposedly", + "suppresion", "suppression", + "suppresors", "suppressor", + "suppressin", "suppression", + "suppressio", "suppressor", + "suppresson", "suppression", + "suprassing", "surpassing", + "supressing", "suppressing", + "supression", "suppression", + "supsension", "suspension", + "supsicions", "suspicions", + "supsicious", "suspicious", + "surounding", "surrounding", + "surplanted", "supplanted", + "surpressed", "suppressed", + "surprizing", "surprising", + "surrenderd", "surrendered", + "surrouding", "surrounding", + "surroundes", "surrounds", + "surroundig", "surroundings", + "survivours", "survivor", + "suseptable", "susceptible", + "suseptible", "susceptible", + "suspecions", "suspicions", + "suspecious", "suspicious", + "suspencion", "suspension", + "suspendeds", "suspense", + "suspention", "suspension", + "suspicians", "suspicions", + "suspiciois", "suspicions", + "suspicioso", "suspicions", + "suspicioun", "suspicion", + "suspicison", "suspicions", + "suspiciuos", "suspicions", + "suspicsion", "suspicions", + "suspisions", "suspicions", + "suspisious", "suspicious", + "suspitions", "suspicions", + "sustainble", "sustainable", + "swaetshirt", "sweatshirt", + "swearengin", "swearing", + "swearshirt", "sweatshirt", + "sweathsirt", "sweatshirt", + "sweatshits", "sweatshirt", + "sweatshort", "sweatshirt", + "sweatshrit", "sweatshirt", + "sweerheart", "sweetheart", + "sweetshart", "sweetheart", + "switcheasy", "switches", + "switzerand", "switzerland", + "symapthize", "sympathize", + "symbolisch", "symbolic", + "symbolisim", "symbolism", + "symetrical", "symmetrical", + "sympatheic", "sympathetic", + "sympathiek", "sympathize", + "sympathien", "sympathize", + "sympathtic", "sympathetic", + "sympathyze", "sympathize", + "sympethize", "sympathize", + "symphatize", "sympathize", + "symphonity", "symphony", + "sympothize", "sympathize", + "syncronous", "synchronous", + "synomymous", "synonymous", + "synomynous", "synonymous", + "synonamous", "synonymous", + "synonimous", "synonymous", + "synonmyous", "synonymous", + "synonomous", "synonymous", + "synonumous", "synonymous", + "synonynous", "synonymous", + "sypmathize", "sympathize", + "systamatic", "systematic", + "systemetic", "systematic", + "systemisch", "systemic", + "systimatic", "systematic", + "tabelspoon", "tablespoon", + "tablespons", "tablespoons", + "tablesppon", "tablespoon", + "tacitcally", "tactically", + "taiwanesse", "taiwanese", + "taligating", "tailgating", + "tantrumers", "tantrums", + "targetting", "targeting", + "teamfigths", "teamfights", + "teamifghts", "teamfights", + "teamspeack", "teamspeak", + "techicians", "technicians", + "techincian", "technician", + "techinican", "technician", + "techinques", "techniques", + "technicain", "technician", + "technicaly", "technically", + "technicans", "technicians", + "technichan", "technician", + "technicien", "technician", + "technicion", "technician", + "technitian", "technician", + "technqiues", "techniques", + "techtician", "technician", + "tehnically", "ethnically", + "telegrapgh", "telegraph", + "teleporing", "teleporting", + "televesion", "television", + "televisivo", "television", + "temafights", "teamfights", + "temerature", "temperature", + "temperatue", "temperature", + "temperment", "temperament", + "temperture", "temperature", + "templarios", "templars", + "templarius", "templars", + "temporaily", "temporarily", + "temporarly", "temporary", + "temptating", "temptation", + "temptetion", "temptation", + "tendancies", "tendencies", + "tendencias", "tendencies", + "tendencije", "tendencies", + "tendensies", "tendencies", + "tendincies", "tendencies", + "tensionors", "tensions", + "tentacreul", "tentacle", + "termanator", "terminator", + "termendous", "tremendous", + "termiantor", "terminator", + "termigator", "terminator", + "terminales", "terminals", + "terminalis", "terminals", + "terminarla", "terminal", + "terminarlo", "terminal", + "terminaron", "terminator", + "terminater", "terminator", + "terminolgy", "terminology", + "terorrists", "terrorists", + "terrerists", "terrorists", + "terrestial", "terrestrial", + "terriblely", "terribly", + "terriories", "territories", + "territoral", "territorial", + "territores", "territories", + "territoris", "territories", + "territorry", "territory", + "terrorisim", "terrorism", + "terrorsits", "terrorists", + "terrurists", "terrorists", + "testiclees", "testicles", + "testiclies", "testicle", + "testimoney", "testimony", + "thankyooou", "thankyou", + "themselfes", "themselves", + "themsevles", "themselves", + "themsleves", "themselves", + "theocracry", "theocracy", + "theologial", "theological", + "therapetic", "therapeutic", + "therepists", "therapists", + "theripists", "therapists", + "thermastat", "thermostat", + "thermistat", "thermostat", + "thermomter", "thermometer", + "theromstat", "thermostat", + "thorttling", "throttling", + "thorughout", "throughout", + "thouroghly", "thoroughly", + "threadened", "threaded", + "threatenes", "threatens", + "threatning", "threatening", + "threshhold", "threshold", + "throthling", "throttling", + "throtlling", "throttling", + "throughiut", "throughput", + "thubmnails", "thumbnails", + "thumbmails", "thumbnails", + "thunderbot", "thunderbolt", + "thunderolt", "thunderbolt", + "tighetning", "tightening", + "tightining", "tightening", + "tigthening", "tightening", + "tjpanishad", "upanishad", + "toothbruch", "toothbrush", + "toothbruth", "toothbrush", + "toothbursh", "toothbrush", + "toothrbush", "toothbrush", + "toppingest", "toppings", + "torchilght", "torchlight", + "torchlgiht", "torchlight", + "torchligth", "torchlight", + "torhclight", "torchlight", + "torrentbig", "torrenting", + "torrenters", "torrents", + "torrentors", "torrents", + "tortillera", "tortilla", + "tortillias", "tortilla", + "tortillita", "tortilla", + "tortilllas", "tortilla", + "torunament", "tournament", + "totalitara", "totalitarian", + "touchsceen", "touchscreen", + "touchscren", "touchscreen", + "touranment", "tournaments", + "tourmanent", "tournaments", + "tournamets", "tournaments", + "tournamnet", "tournament", + "tournemant", "tournament", + "tournement", "tournament", + "toxicitity", "toxicity", + "trafficing", "trafficking", + "trainwreak", "trainwreck", + "traitorise", "traitors", + "tramboline", "trampoline", + "tramploine", "trampoline", + "trampolene", "trampoline", + "tranformed", "transformed", + "tranistion", "transition", + "tranlsated", "translated", + "transalted", "translated", + "transaltes", "translates", + "transaltor", "translator", + "transation", "transition", + "transciprt", "transcripts", + "transcirpt", "transcripts", + "transcrips", "transcripts", + "transcrito", "transcript", + "transcrits", "transcripts", + "transcrpit", "transcript", + "transfered", "transferred", + "transferer", "transferred", + "transferes", "transfers", + "transferrs", "transfers", + "transferts", "transfers", + "transfomed", "transformed", + "transfored", "transformed", + "transforme", "transfer", + "transfroms", "transforms", + "transgeder", "transgender", + "transgener", "transgender", + "transicion", "transition", + "transision", "transition", + "transister", "transistor", + "transitons", "transitions", + "transitors", "transistor", + "transkript", "transcript", + "translater", "translator", + "translatin", "translations", + "translatio", "translator", + "translpant", "transplants", + "transluent", "translucent", + "transmited", "transmitted", + "transmiter", "transmitter", + "transmitor", "transistor", + "transmorgs", "transforms", + "transpalnt", "transplants", + "transphoic", "transphobic", + "transplain", "transplant", + "transplate", "transplant", + "transplats", "transplants", + "transpoder", "transported", + "transportr", "transporter", + "transsexal", "transsexual", + "transtator", "translator", + "tranzistor", "transistor", + "trasncript", "transcript", + "trasnforms", "transforms", + "trasnlated", "translated", + "trasnlator", "translator", + "trasnplant", "transplant", + "traveleres", "travelers", + "travelodge", "traveled", + "traverlers", "traverse", + "traversare", "traverse", + "traversier", "traverse", + "treasurery", "treasury", + "trememdous", "tremendous", + "tremondous", "tremendous", + "trespasing", "trespassing", + "trianwreck", "trainwreck", + "trochlight", "torchlight", + "trustworhy", "trustworthy", + "trustworty", "trustworthy", + "trustwothy", "trustworthy", + "tryannical", "tyrannical", + "tunraround", "turnaround", + "tupparware", "tupperware", + "turnapound", "turnaround", + "turthfully", "truthfully", + "tutoriales", "tutorials", + "tyrantical", "tyrannical", + "ubiqituous", "ubiquitous", + "ubiquotous", "ubiquitous", + "ubiqutious", "ubiquitous", + "ukrainains", "ukrainians", + "ukraineans", "ukrainians", + "ukrainiens", "ukrainians", + "ukraininas", "ukrainians", + "ukrianians", "ukrainians", + "ulitmately", "ultimately", + "ulterioara", "ulterior", + "ulterioare", "ulterior", + "ultimative", "ultimate", + "ultimatley", "ultimately", + "ultimatuum", "ultimatum", + "unanwsered", "unanswered", + "unasnwered", "unanswered", + "unattanded", "unattended", + "unattented", "unattended", + "unavailabe", "unavailable", + "unavailble", "unavailable", + "unavoidble", "unavoidable", + "unawnsered", "unanswered", + "unbalenced", "unbalanced", + "unballance", "unbalance", + "unbalnaced", "unbalanced", + "unbareable", "unbearable", + "unbeakable", "unbeatable", + "unbeareble", "unbearable", + "unbeatbale", "unbeatable", + "unbeateble", "unbeatable", + "unbeerable", "unbearable", + "unbeetable", "unbeatable", + "unbeknowst", "unbeknownst", + "unbreakble", "unbreakable", + "uncencored", "uncensored", + "uncensered", "uncensored", + "uncersored", "uncensored", + "uncertainy", "uncertainty", + "uncertanty", "uncertainty", + "uncesnored", "uncensored", + "uncomitted", "uncommitted", + "uncommited", "uncommitted", + "unconcious", "unconscious", + "unconscous", "unconscious", + "undebiably", "undeniably", + "undeinable", "undeniable", + "undeinably", "undeniably", + "undenaible", "undeniable", + "undenaibly", "undeniably", + "undenyable", "undeniable", + "undenyably", "undeniably", + "underbaker", "undertaker", + "undercling", "underlying", + "underfaker", "undertaker", + "undergated", "underrated", + "undergrand", "undergrad", + "undergroud", "underground", + "undergrund", "underground", + "undermimes", "undermines", + "underminde", "undermines", + "underminig", "undermining", + "underneeth", "underneath", + "underneith", "underneath", + "undernieth", "underneath", + "underpowed", "underpowered", + "underraged", "underrated", + "underraker", "undertaker", + "underrater", "undertaker", + "undersatnd", "understands", + "understadn", "understands", + "understans", "understands", + "understnad", "understands", + "understoon", "understood", + "understsnd", "understands", + "undertoker", "undertaker", + "undertsand", "understands", + "undertunes", "undertones", + "underwager", "underwater", + "underwares", "underwater", + "underwolrd", "underworld", + "underwoord", "underworld", + "underwrold", "underworld", + "underyling", "underlying", + "undesrtand", "understands", + "undoubtedy", "undoubtedly", + "undoubtely", "undoubtedly", + "undoubtley", "undoubtedly", + "uneccesary", "unnecessary", + "unecessary", "unnecessary", + "unedcuated", "uneducated", + "unedicated", "uneducated", + "unempolyed", "unemployed", + "unexplaind", "unexplained", + "unexplaned", "unexplained", + "unfamilair", "unfamiliar", + "unfamilier", "unfamiliar", + "unfinsihed", "unfinished", + "unfirendly", "unfriendly", + "unfortuate", "unfortunate", + "unfreindly", "unfriendly", + "unfriednly", "unfriendly", + "unfriently", "unfriendly", + "ungrapeful", "ungrateful", + "ungreatful", "ungrateful", + "unhealthly", "unhealthy", + "unicornios", "unicorns", + "unifnished", "unfinished", + "unihabited", "uninhabited", + "unilatreal", "unilateral", + "unimporant", "unimportant", + "unimpresed", "unimpressed", + "unimpressd", "unimpressed", + "uninsipred", "uninspired", + "uninspried", "uninspired", + "uninstaled", "uninstalled", + "uniquiness", "uniqueness", + "univercity", "university", + "univeristy", "university", + "universale", "universe", + "universaly", "universally", + "universels", "universes", + "universets", "universes", + "universite", "universities", + "universtiy", "university", + "unjustifed", "unjustified", + "unknowingy", "unknowingly", + "unknowinly", "unknowingly", + "unnecesary", "unnecessary", + "unofficail", "unofficial", + "unoffocial", "unofficial", + "unorginial", "unoriginal", + "unorignial", "unoriginal", + "unorigonal", "unoriginal", + "unplacable", "unplayable", + "unplaybale", "unplayable", + "unplayeble", "unplayable", + "unpleasent", "unpleasant", + "unpopulair", "unpopular", + "unproteced", "unprotected", + "unqiueness", "uniqueness", + "unqualifed", "unqualified", + "unrealesed", "unreleased", + "unrealible", "unreliable", + "unrealistc", "unrealistic", + "unrealitic", "unrealistic", + "unreasonal", "unreasonably", + "unrelaible", "unreliable", + "unreleated", "unreleased", + "unrelyable", "unreliable", + "unrepetant", "unrepentant", + "unrepetent", "unrepentant", + "unresponse", "unresponsive", + "unsencored", "uncensored", + "unsetlling", "unsettling", + "unsolicted", "unsolicited", + "unsubscibe", "unsubscribe", + "unsubscrbe", "unsubscribe", + "unsucesful", "unsuccessful", + "unsuprised", "unsurprised", + "unsuprized", "unsurprised", + "unviersity", "university", + "unwrittern", "unwritten", + "urkainians", "ukrainians", + "utlimately", "ultimately", + "utlrasound", "ultrasound", + "vaccinatie", "vaccinated", + "vaccineras", "vaccines", + "valentians", "valentines", + "valentiens", "valentines", + "valentimes", "valentines", + "valentinas", "valentines", + "valentinos", "valentines", + "valentones", "valentines", + "validitity", "validity", + "valnetines", "valentines", + "vandalisim", "vandalism", + "vasectomey", "vasectomy", + "vegatarian", "vegetarian", + "vegaterian", "vegetarian", + "vegeratian", "vegetarians", + "vegetairan", "vegetarians", + "vegetarain", "vegetarians", + "vegetarien", "vegetarian", + "vegetarion", "vegetarian", + "vegetatian", "vegetarian", + "vegeterian", "vegetarian", + "vegitables", "vegetables", + "vehemantly", "vehemently", + "vehemontly", "vehemently", + "veitnamese", "vietnamese", + "veiwership", "viewership", + "veiwpoints", "viewpoints", + "venezuella", "venezuela", + "verificato", "verification", + "verifyable", "verifiable", + "veritcally", "vertically", + "veritiable", "verifiable", + "vernecular", "vernacular", + "vernicular", "vernacular", + "versatiliy", "versatility", + "versatille", "versatile", + "versatilty", "versatility", + "versitlity", "versatility", + "vewiership", "viewership", + "vibratoare", "vibrator", + "vicitmized", "victimized", + "vicotrious", "victorious", + "victemized", "victimized", + "victomized", "victimized", + "victorinos", "victorious", + "victorinus", "victorious", + "victoriosa", "victorious", + "victorioso", "victorious", + "victoriuos", "victorious", + "victumized", "victimized", + "videogaems", "videogames", + "videojames", "videogames", + "vidoegames", "videogames", + "vientamese", "vietnamese", + "vietmanese", "vietnamese", + "vietnamees", "vietnamese", + "vietnamise", "vietnamese", + "viewpionts", "viewpoints", + "vigilantie", "vigilante", + "vigoruosly", "vigorously", + "vigourosly", "vigorously", + "villageois", "villages", + "vindicitve", "vindictive", + "vindictave", "vindictive", + "visibiltiy", "visibility", + "vitenamese", "vietnamese", + "vocabluary", "vocabulary", + "volatiltiy", "volatility", + "volativity", "volatility", + "volitality", "volatility", + "volleyboll", "volleyball", + "vollyeball", "volleyball", + "volonteers", "volunteers", + "volounteer", "volunteer", + "voluntairy", "voluntarily", + "voluntarly", "voluntary", + "voluntears", "volunteers", + "volunteeer", "volunteers", + "volunteerd", "volunteered", + "voluntered", "volunteered", + "vulernable", "vulnerable", + "vulnarable", "vulnerable", + "vulnerabil", "vulnerable", + "vulnurable", "vulnerable", + "vunlerable", "vulnerable", + "warrandyte", "warranty", + "warrantles", "warranties", + "warrenties", "warranties", + "washignton", "washington", + "waterlemon", "watermelon", + "watermalon", "watermelon", + "waterproff", "waterproof", + "wavelegnth", "wavelength", + "wavelenghs", "wavelength", + "wavelenght", "wavelength", + "weakensses", "weaknesses", + "weaknesess", "weaknesses", + "weathliest", "wealthiest", + "wedensdays", "wednesdays", + "wednesdsay", "wednesdays", + "wednessday", "wednesdays", + "wednsedays", "wednesdays", + "weightened", "weighted", + "welathiest", "wealthiest", + "wellignton", "wellington", + "wellingotn", "wellington", + "wendesdays", "wednesdays", + "wereabouts", "whereabouts", + "westbroook", "westbrook", + "westernese", "westerners", + "westerness", "westerners", + "westminser", "westminster", + "westminter", "westminster", + "whatosever", "whatsoever", + "whatseover", "whatsoever", + "whipsering", "whispering", + "whsipering", "whispering", + "widepsread", "widespread", + "wikileakes", "wikileaks", + "wilderniss", "wilderness", + "wildreness", "wilderness", + "willfullly", "willfully", + "winchestor", "winchester", + "windhsield", "windshield", + "windsheild", "windshield", + "windshiled", "windshield", + "wisconsion", "wisconsin", + "wishpering", "whispering", + "withdrawan", "withdrawn", + "withdrawel", "withdrawal", + "withdrawin", "withdrawn", + "withholdng", "withholding", + "withrdawal", "withdrawals", + "witnissing", "witnessing", + "wonderfull", "wonderful", + "wonderfuly", "wonderfully", + "wonderwand", "wonderland", + "worhsiping", "worshiping", + "workingest", "workings", + "workstaion", "workstation", + "workstaton", "workstation", + "worshippig", "worshipping", + "worshoping", "worshiping", + "wrestlewar", "wrestler", + "xenohpobic", "xenophobic", + "xenophibia", "xenophobia", + "xenophibic", "xenophobic", + "xenophonic", "xenophobic", + "xenophopia", "xenophobia", + "xenophopic", "xenophobic", + "xeonphobia", "xenophobia", + "xeonphobic", "xenophobic", + "yourselfes", "yourselves", + "yoursleves", "yourselves", + "zimbabwaen", "zimbabwe", + "zionistisk", "zionists", + "abandonig", "abandoning", + "abandonne", "abandonment", + "abanonded", "abandoned", + "abdomnial", "abdominal", + "abdonimal", "abdominal", + "aberation", "aberration", + "abnormaly", "abnormally", + "abodminal", "abdominal", + "abondoned", "abandoned", + "aborigene", "aborigine", + "aboslutes", "absolutes", + "abosrbing", "absorbing", + "abreviate", "abbreviate", + "abritrary", "arbitrary", + "abruptley", "abruptly", + "absailing", "abseiling", + "absloutes", "absolutes", + "absolutey", "absolutely", + "absolutly", "absolutely", + "absoultes", "absolutes", + "abstracto", "abstraction", + "absurdley", "absurdly", + "absuridty", "absurdity", + "abusrdity", "absurdity", + "academica", "academia", + "accademic", "academic", + "accalimed", "acclaimed", + "accelerar", "accelerator", + "accending", "ascending", + "accension", "accession", + "accidenty", "accidently", + "acclamied", "acclaimed", + "accliamed", "acclaimed", + "accomdate", "accommodate", + "accordeon", "accordion", + "accordian", "accordion", + "accoridng", "according", + "accountas", "accountants", + "accountat", "accountants", + "accoustic", "acoustic", + "accroding", "according", + "accuraccy", "accuracy", + "acftually", "factually", + "acheiving", "achieving", + "achieveds", "achieves", + "achillees", "achilles", + "achilleos", "achilles", + "achilleus", "achilles", + "achiveing", "achieving", + "acitvates", "activates", + "aclhemist", "alchemist", + "acomplish", "accomplish", + "acquisito", "acquisition", + "acronymes", "acronyms", + "acronymns", "acronyms", + "acsending", "ascending", + "acsension", "ascension", + "activaste", "activates", + "activatin", "activation", + "activelly", "actively", + "activisim", "activism", + "activisit", "activist", + "activites", "activities", + "actresess", "actresses", + "acusation", "causation", + "acutality", "actuality", + "adavanced", "advanced", + "adbominal", "abdominal", + "additonal", "additional", + "addoptive", "adoptive", + "addresing", "addressing", + "addtional", "additional", + "adhearing", "adhering", + "adherance", "adherence", + "adjectivs", "adjectives", + "adjustabe", "adjustable", + "administr", "administer", + "admitedly", "admittedly", + "adolecent", "adolescent", + "adovcated", "advocated", + "adovcates", "advocates", + "adquiring", "acquiring", + "adresable", "addressable", + "adressing", "addressing", + "aduiobook", "audiobook", + "advatange", "advantage", + "adventurs", "adventures", + "adveristy", "adversity", + "advertisy", "adversity", + "advisorys", "advisors", + "aeorspace", "aerospace", + "aeropsace", "aerospace", + "aerosapce", "aerospace", + "aersopace", "aerospace", + "aestethic", "aesthetic", + "aethistic", "atheistic", + "affiliato", "affiliation", + "affinitiy", "affinity", + "affirmate", "affirmative", + "affliated", "affiliated", + "africanas", "africans", + "africanos", "africans", + "aggegrate", "aggregate", + "aggresive", "aggressive", + "agnosticm", "agnosticism", + "agregates", "aggregates", + "agreggate", "aggregate", + "agrentina", "argentina", + "agression", "aggression", + "agressive", "aggressive", + "agressvie", "agressive", + "agruement", "arguement", + "agruments", "arguments", + "agurement", "arguement", + "ailenated", "alienated", + "airbourne", "airborne", + "aircrafts", "aircraft", + "airplance", "airplane", + "airrcraft", "aircraft", + "aksreddit", "askreddit", + "alcehmist", "alchemist", + "alchemsit", "alchemist", + "alchimest", "alchemist", + "alchmeist", "alchemist", + "alchoolic", "alcoholic", + "alcoholis", "alcoholics", + "alechmist", "alchemist", + "alegience", "allegiance", + "aleinated", "alienated", + "algoriths", "algorithms", + "algoritms", "algorithms", + "algorthim", "algorithm", + "algortihm", "algorithm", + "alignemnt", "alignment", + "alimunium", "aluminium", + "alingment", "alignment", + "allainces", "alliances", + "alledgely", "allegedly", + "allegence", "allegiance", + "alleivate", "alleviate", + "allievate", "alleviate", + "alliviate", "alleviate", + "allopones", "allophones", + "allthough", "although", + "almightly", "almighty", + "alocholic", "alcoholic", + "alogrithm", "algorithm", + "alphabeat", "alphabet", + "alrightey", "alrighty", + "alrightly", "alrighty", + "alrightty", "alrighty", + "alrington", "arlington", + "alrorythm", "algorithm", + "alterante", "alternate", + "alternatr", "alternator", + "althetics", "athletics", + "althought", "although", + "altruisim", "altruism", + "amateures", "amateurs", + "ambluance", "ambulance", + "ambuigity", "ambiguity", + "amendmant", "amendment", + "amercians", "americans", + "americain", "american", + "americams", "americas", + "americaps", "americas", + "americats", "americas", + "amibguity", "ambiguity", + "aminosity", "animosity", + "amrstrong", "armstrong", + "amublance", "ambulance", + "amunition", "ammunition", + "anachrist", "anarchist", + "analagous", "analogous", + "analitycs", "analytics", + "analtyics", "analytics", + "analyitcs", "analytics", + "analyseas", "analyses", + "analysees", "analyses", + "analysens", "analyses", + "analysise", "analyses", + "analystes", "analysts", + "analzying", "analyzing", + "anarchsim", "anarchism", + "anayltics", "analytics", + "anaylzing", "analyzing", + "ancedotal", "anecdotal", + "ancedotes", "anecdotes", + "ancestory", "ancestry", + "androgeny", "androgyny", + "androides", "androids", + "androidos", "androids", + "anecdotle", "anecdote", + "anecodtal", "anecdotal", + "anecodtes", "anecdotes", + "anectodal", "anecdotal", + "anectodes", "anecdotes", + "anedoctal", "anecdotal", + "anedoctes", "anecdotes", + "animostiy", "animosity", + "anitvirus", "antivirus", + "anlaytics", "analytics", + "anniversy", "anniversary", + "annointed", "anointed", + "annoucnes", "announces", + "annoyingy", "annoyingly", + "annoymous", "anonymous", + "annoynace", "annoyance", + "annyoance", "annoyance", + "anomisity", "animosity", + "anomolies", "anomalies", + "anomolous", "anomalous", + "anomynity", "anonymity", + "anomynous", "anonymous", + "anonimity", "anonymity", + "anonmyous", "anonymous", + "anonymoys", "anonymously", + "anorexiac", "anorexic", + "anorexica", "anorexia", + "anrachist", "anarchist", + "ansestors", "ancestors", + "antarctia", "antarctica", + "antennaes", "antennas", + "antiviurs", "antivirus", + "antivrius", "antivirus", + "antivuris", "antivirus", + "anwsering", "answering", + "anynomity", "anonymity", + "anynomous", "anonymous", + "aparthide", "apartheid", + "aparthied", "apartheid", + "apartmens", "apartments", + "apocalype", "apocalypse", + "apostrope", "apostrophe", + "apparenty", "apparently", + "appearane", "appearances", + "appenines", "apennines", + "apperance", "appearance", + "appetitie", "appetite", + "applaudes", "applause", + "applicato", "application", + "appreciae", "appreciates", + "apprentie", "apprentice", + "approachs", "approaches", + "apratheid", "apartheid", + "apsaragus", "asparagus", + "apsergers", "aspergers", + "aquainted", "acquainted", + "arbirtary", "arbitrary", + "arbritary", "arbitrary", + "arcehtype", "archetype", + "archetect", "architect", + "archetpye", "archetype", + "archetyps", "archetypes", + "architecs", "architects", + "archtypes", "archetypes", + "aregument", "arguement", + "areospace", "aerospace", + "argessive", "agressive", + "argeument", "arguement", + "arguabley", "arguably", + "arguablly", "arguably", + "arguement", "argument", + "arguemnet", "arguement", + "arguemnts", "arguments", + "argumeent", "arguement", + "arhtritis", "arthritis", + "aribtrary", "arbitrary", + "ariplanes", "airplanes", + "aristolte", "aristotle", + "aristotel", "aristotle", + "aritfacts", "artifacts", + "arlignton", "arlington", + "arlingotn", "arlington", + "armistace", "armistice", + "armstorng", "armstrong", + "arpatheid", "apartheid", + "arthirtis", "arthritis", + "artifcats", "artifacts", + "artifical", "artificial", + "artillary", "artillery", + "arugement", "arguement", + "arugments", "arguments", + "asapragus", "asparagus", + "asbestoes", "asbestos", + "asborbing", "absorbing", + "asburdity", "absurdity", + "ascendend", "ascended", + "ascneding", "ascending", + "ascnesion", "ascension", + "asethetic", "aesthetic", + "asnwering", "answering", + "asociated", "associated", + "assasined", "assassinated", + "assassian", "assassin", + "assassine", "assassinate", + "assasssin", "assassins", + "assaultes", "assaults", + "assembeld", "assembled", + "assembley", "assembly", + "assemblie", "assemble", + "assisnate", "assassinate", + "assistans", "assistants", + "assistsnt", "assistants", + "assmebled", "assembled", + "associato", "association", + "assoicate", "associate", + "asssasins", "assassins", + "assualted", "assaulted", + "assulated", "assaulted", + "asteorids", "asteroids", + "astericks", "asterisk", + "asteriods", "asteroids", + "astroanut", "astronaut", + "astronuat", "astronaut", + "astrounat", "astronaut", + "asuterity", "austerity", + "atempting", "attempting", + "atheltics", "athletics", + "atheneans", "athenians", + "athesitic", "atheistic", + "athetlics", "athletics", + "athiestic", "atheistic", + "athleticm", "athleticism", + "atmosphir", "atmospheric", + "atributed", "attributed", + "atributes", "attributes", + "atrifacts", "artifacts", + "atrillery", "artillery", + "atrittion", "attrition", + "attachmet", "attachments", + "attaindre", "attainder", + "attemting", "attempting", + "attemtped", "attempted", + "attendent", "attendant", + "attension", "attention", + "attirbute", "attribute", + "attirtion", "attrition", + "attmepted", "attempted", + "attractes", "attracts", + "attractin", "attraction", + "attributo", "attribution", + "attributs", "attributes", + "attritube", "attribute", + "auctionrs", "auctions", + "auidobook", "audiobook", + "auromated", "automated", + "australin", "australians", + "authroity", "authority", + "autoattak", "autoattack", + "autogrpah", "autograph", + "autonomos", "autonomous", + "auxillary", "auxiliary", + "avaialble", "available", + "availible", "available", + "avalaible", "available", + "avaliable", "available", + "averageed", "averaged", + "avialable", "available", + "awakenend", "awakened", + "awesomley", "awesomely", + "awkawrdly", "awkwardly", + "awnsering", "answering", + "bacehlors", "bachelors", + "bachelour", "bachelor", + "bachleors", "bachelors", + "bacholers", "bachelors", + "backdooor", "backdoor", + "backfeild", "backfield", + "backfiled", "backfield", + "backgroud", "background", + "backpakcs", "backpacks", + "badnwagon", "bandwagon", + "badnwidth", "bandwidth", + "balckjack", "blackjack", + "balcklist", "blacklist", + "balitmore", "baltimore", + "ballisitc", "ballistic", + "ballsitic", "ballistic", + "balsphemy", "blasphemy", + "bandiwdth", "bandwidth", + "bandwdith", "bandwidth", + "bandwidht", "bandwidth", + "bandwitdh", "bandwidth", + "bankrupcy", "bankruptcy", + "bankrupty", "bankruptcy", + "banruptcy", "bankruptcy", + "baordwalk", "boardwalk", + "barabrian", "barbarian", + "barbarain", "barbarian", + "barbarina", "barbarian", + "barcelets", "bracelets", + "barcleona", "barcelona", + "bareclona", "barcelona", + "barrackus", "barracks", + "bascially", "basically", + "bastardes", "bastards", + "bastardos", "bastards", + "bastardus", "bastards", + "bathrooom", "bathroom", + "batlimore", "baltimore", + "battailon", "battalion", + "battlaion", "battalion", + "beahviour", "behaviour", + "beauitful", "beautiful", + "beautifyl", "beautifully", + "becnhmark", "benchmark", + "becomeing", "becoming", + "becomming", "becoming", + "beehtoven", "beethoven", + "begginers", "beginners", + "beggining", "beginning", + "begininng", "beginning", + "beginnins", "beginnings", + "behaivors", "behaviors", + "behaivour", "behaviour", + "behavoirs", "behaviors", + "behavoiur", "behaviour", + "behvaiour", "behaviour", + "beleiving", "believing", + "beliveing", "believing", + "belssings", "blessings", + "bemusemnt", "bemusement", + "benchamrk", "benchmark", + "benchmars", "benchmarks", + "benedicat", "benedict", + "benedickt", "benedict", + "benghazhi", "benghazi", + "benghazzi", "benghazi", + "bergamont", "bergamot", + "berkelely", "berkeley", + "bersekrer", "berserker", + "berskerer", "berserker", + "beseiging", "besieging", + "bestialiy", "bestiality", + "beuatiful", "beautiful", + "biginning", "beginning", + "bigrading", "brigading", + "billbaord", "billboard", + "billboars", "billboards", + "binominal", "binomial", + "birgading", "brigading", + "birghtest", "brightest", + "birhtdays", "birthdays", + "bitcoints", "bitcoins", + "blackbery", "blackberry", + "blackhaws", "blackhawks", + "blackshit", "blacksmith", + "blanketts", "blankets", + "blapshemy", "blasphemy", + "blashpemy", "blasphemy", + "blaspehmy", "blasphemy", + "blasphmey", "blasphemy", + "blatanlty", "blatantly", + "blatimore", "baltimore", + "bleuberry", "blueberry", + "bleutooth", "bluetooth", + "blisteres", "blisters", + "blizzcoin", "blizzcon", + "blockchan", "blockchain", + "blockeras", "blockers", + "bloodbore", "bloodborne", + "boardband", "broadband", + "boardcast", "broadcast", + "bodyweigt", "bodyweight", + "bookamrks", "bookmarks", + "bookmakrs", "bookmarks", + "bookmarkd", "bookmarked", + "boradband", "broadband", + "boradcast", "broadcast", + "boradwalk", "boardwalk", + "bouregois", "bourgeois", + "bourgeios", "bourgeois", + "bourgoeis", "bourgeois", + "boyfirend", "boyfriend", + "boyfreind", "boyfriend", + "boyfriens", "boyfriends", + "brabarian", "barbarian", + "bracelona", "barcelona", + "braodband", "broadband", + "braodcast", "broadcast", + "brazilias", "brazilians", + "breakdows", "breakdowns", + "breserker", "berserker", + "bretheren", "brethren", + "bridaging", "brigading", + "brightern", "brighten", + "brigthest", "brightest", + "brilliany", "brilliantly", + "brithdays", "birthdays", + "broadwalk", "boardwalk", + "bruiseres", "bruisers", + "brunettte", "brunette", + "brusseles", "brussels", + "brussells", "brussels", + "brutailty", "brutality", + "brutallly", "brutally", + "buddhisim", "buddhism", + "buddihsts", "buddhists", + "buddishts", "buddhists", + "buhddists", "buddhists", + "buidlings", "buildings", + "bulidings", "buildings", + "burgunday", "burgundy", + "burgundry", "burgundy", + "burritoes", "burritos", + "burtality", "brutality", + "busineses", "business", + "businessa", "businessman", + "businesse", "businessmen", + "businesss", "businesses", + "bussiness", "business", + "buthcered", "butchered", + "butterlfy", "butterfly", + "cacausian", "caucasian", + "caclulate", "calculate", + "cacuasian", "caucasian", + "caculater", "calculator", + "cafeteira", "cafeteria", + "cafetiera", "cafeteria", + "caffeinne", "caffeine", + "calcualte", "calculate", + "californa", "california", + "caluclate", "calculate", + "calulated", "calculated", + "calulater", "calculator", + "cambirdge", "cambridge", + "cambrdige", "cambridge", + "cambrigde", "cambridge", + "camoflage", "camouflage", + "campagins", "campaigns", + "campaings", "campaigns", + "campiagns", "campaigns", + "campusers", "campuses", + "camrbidge", "cambridge", + "canadains", "canadians", + "candadate", "candidate", + "candidats", "candidates", + "cannister", "canister", + "cannoical", "canonical", + "canoncial", "canonical", + "capactior", "capacitor", + "capicator", "capacitor", + "capitalis", "capitals", + "caprenter", "carpenter", + "capsulers", "capsules", + "capsulets", "capsules", + "carachter", "character", + "cardbaord", "cardboard", + "cardborad", "cardboard", + "cardianls", "cardinals", + "cardnials", "cardinals", + "caridnals", "cardinals", + "carmalite", "carmelite", + "carnberry", "cranberry", + "carolinia", "carolina", + "carpetner", "carpenter", + "carptener", "carpenter", + "carribean", "caribbean", + "cartdrige", "cartridge", + "cartilege", "cartilage", + "cartirdge", "cartridge", + "cartrdige", "cartridge", + "cartrigde", "cartridge", + "casaulity", "causality", + "cashieres", "cashiers", + "cassawory", "cassowary", + "cassettte", "cassette", + "casuation", "causation", + "cataclsym", "cataclysm", + "cataclyms", "cataclysm", + "catacylsm", "cataclysm", + "catacyslm", "cataclysm", + "catalcysm", "cataclysm", + "catalgoue", "catalogue", + "cathderal", "cathedral", + "catherdal", "cathedral", + "cathloics", "catholics", + "cathredal", "cathedral", + "caucaisan", "caucasian", + "caucasain", "caucasian", + "causacian", "caucasian", + "causailty", "causality", + "celebirty", "celebrity", + "celebrato", "celebration", + "celebrite", "celebrities", + "celesital", "celestial", + "celestail", "celestial", + "cementary", "cemetery", + "cemetarey", "cemetery", + "cenitpede", "centipede", + "centepide", "centipede", + "centipeed", "centipede", + "centruies", "centuries", + "centuties", "centuries", + "cerebrawl", "cerebral", + "certanity", "certainty", + "certianty", "certainty", + "cesspoool", "cesspool", + "chairmain", "chairman", + "challange", "challenge", + "challengr", "challenger", + "challengs", "challenges", + "chameloen", "chameleon", + "champagen", "champagne", + "champange", "champagne", + "chandlure", "chandler", + "changable", "changeable", + "charactor", "character", + "chatedral", "cathedral", + "chatolics", "catholics", + "checkmeat", "checkmate", + "checkpoit", "checkpoints", + "chekcmate", "checkmate", + "chemestry", "chemistry", + "chemicaly", "chemically", + "chemsitry", "chemistry", + "chernboyl", "chernobyl", + "chernobly", "chernobyl", + "chernoybl", "chernobyl", + "chernyobl", "chernobyl", + "cheronbyl", "chernobyl", + "chidlfree", "childfree", + "chidlrens", "childrens", + "chihauhua", "chihuahua", + "chihuahau", "chihuahua", + "childbird", "childbirth", + "childerns", "childrens", + "childisch", "childish", + "childresn", "childrens", + "chirstian", "christian", + "chirstmas", "christmas", + "chiuhahua", "chihuahua", + "chlidfree", "childfree", + "chlidrens", "childrens", + "chocloate", "chocolate", + "chocoalte", "chocolate", + "chocolats", "chocolates", + "chocolste", "chocolates", + "cholocate", "chocolate", + "chrenobyl", "chernobyl", + "chrisitan", "christian", + "christain", "christian", + "christams", "christmas", + "chrsitian", "christian", + "chrsitmas", "christmas", + "churchers", "churches", + "cigaretts", "cigarettes", + "cigeratte", "cigarette", + "cilivians", "civilians", + "cilpboard", "clipboard", + "cilynders", "cylinders", + "circuitos", "circuits", + "ciriculum", "curriculum", + "cirticise", "criticise", + "civilains", "civilians", + "civillian", "civilian", + "classicos", "classics", + "classicus", "classics", + "classifiy", "classify", + "cleanisng", "cleansing", + "cleasning", "cleansing", + "clikcbait", "clickbait", + "clinicaly", "clinically", + "clipbaord", "clipboard", + "clitories", "clitoris", + "clitorios", "clitoris", + "clitorius", "clitoris", + "clucthing", "clutching", + "clutchign", "clutching", + "cluthcing", "clutching", + "coca cola", "coca-cola", + "cockatils", "cocktails", + "cocktials", "cocktails", + "cognizent", "cognizant", + "colateral", "collateral", + "collabore", "collaborate", + "collasped", "collapsed", + "collaspes", "collapses", + "colleauge", "colleague", + "collectes", "collects", + "collectie", "collective", + "collecton", "collection", + "collectos", "collectors", + "collegaue", "colleague", + "collegues", "colleagues", + "collisson", "collisions", + "collonade", "colonnade", + "collonies", "colonies", + "collpased", "collapsed", + "collpases", "collapses", + "colombina", "colombia", + "columbina", "columbia", + "comapnies", "companies", + "combatans", "combatants", + "combinato", "combination", + "combusion", "combustion", + "comestics", "cosmetics", + "comisions", "commissions", + "comission", "commission", + "comitting", "committing", + "commandes", "commands", + "commentar", "commentator", + "commentes", "commenters", + "commercie", "commerce", + "commision", "commission", + "commiteed", "commited", + "commiting", "committing", + "commitmet", "commitments", + "commments", "comments", + "commongly", "commonly", + "communiss", "communists", + "communite", "communities", + "communits", "communist", + "communsim", "communism", + "compaines", "companies", + "compalins", "complains", + "compalint", "compliant", + "comparisn", "comparisons", + "compeltes", "completes", + "competant", "competent", + "competend", "competed", + "competion", "competition", + "competive", "competitive", + "compilant", "compliant", + "compilare", "compiler", + "compilato", "compilation", + "compitent", "competent", + "complaind", "complained", + "complaing", "complaining", + "completen", "complement", + "completey", "completely", + "completin", "completion", + "complians", "complains", + "componant", "component", + "comprable", "comparable", + "compresas", "compress", + "compreses", "compress", + "compteurs", "computers", + "comptuers", "computers", + "computato", "computation", + "comradets", "comrades", + "comsetics", "cosmetics", + "conanical", "canonical", + "conatiner", "container", + "concelaed", "concealed", + "concelaer", "concealer", + "concelear", "concealer", + "concensus", "consensus", + "conceptos", "concepts", + "conceptul", "conceptual", + "concernig", "concerning", + "concertas", "concerts", + "concevied", "conceived", + "conciders", "considers", + "concieted", "conceited", + "concieved", "conceived", + "conclusie", "conclusive", + "concsious", "conscious", + "concurret", "concurrent", + "condamned", "condemned", + "condemend", "condemned", + "condemmed", "condemned", + "condemnig", "condemning", + "condenmed", "condemned", + "condesend", "condensed", + "condesned", "condensed", + "condmened", "condemned", + "conection", "connection", + "conenctor", "connector", + "conferene", "conferences", + "confessin", "confession", + "confideny", "confidently", + "confilcts", "conflicts", + "confimred", "confirmed", + "confirmas", "confirms", + "conflcits", "conflicts", + "confrimed", "confirmed", + "congitive", "cognitive", + "conlcuded", "concluded", + "connectes", "connects", + "connectit", "connecticut", + "connectos", "connectors", + "conquerer", "conqueror", + "consdider", "consider", + "consensul", "consensual", + "conserned", "concerned", + "consicous", "conscious", + "considerd", "considered", + "considert", "considerate", + "consisent", "consistent", + "consistes", "consists", + "consolato", "consolation", + "consolide", "consolidate", + "consonent", "consonant", + "constanly", "constantly", + "constanst", "constants", + "constanty", "constantly", + "constasnt", "constants", + "constitue", "constitutes", + "constrait", "constraints", + "construcs", "constructs", + "construde", "construed", + "construst", "constructs", + "constucts", "constructs", + "constured", "construed", + "consulant", "consultant", + "consultat", "consultant", + "consumate", "consummate", + "contactes", "contacts", + "contactos", "contacts", + "contagios", "contagious", + "containes", "contains", + "containig", "containing", + "containts", "contains", + "contemple", "contemplate", + "contendor", "contender", + "contentas", "contents", + "contentes", "contents", + "contentos", "contents", + "contestas", "contests", + "contestat", "contestants", + "contestes", "contests", + "contextes", "contexts", + "contextos", "contexts", + "contianer", "container", + "contibute", "contribute", + "contigent", "contingent", + "continant", "continental", + "continens", "continents", + "continous", "continuous", + "continuos", "continuous", + "continute", "continue", + "contiunal", "continual", + "contracto", "contraction", + "contribue", "contribute", + "contribuo", "contributor", + "controlas", "controls", + "controled", "controlled", + "controles", "controls", + "controlls", "controls", + "convenant", "covenant", + "convencen", "convenience", + "conveniet", "convenient", + "conversie", "converse", + "conversin", "conversions", + "convertie", "convertible", + "convertis", "converts", + "cooldwons", "cooldowns", + "coordinar", "coordinator", + "copenhagn", "copenhagen", + "coprorate", "corporate", + "copywrite", "copyright", + "corcodile", "crocodile", + "corparate", "corporate", + "corproate", "corporate", + "correclty", "correctly", + "correctin", "correction", + "correlato", "correlation", + "corridoor", "corridor", + "corruptin", "corruption", + "corssfire", "crossfire", + "corsshair", "crosshair", + "corsspost", "crosspost", + "coruching", "crouching", + "cosemtics", "cosmetics", + "costumise", "costumes", + "counciles", "councils", + "councills", "councils", + "councilos", "councils", + "countains", "contains", + "counteres", "counters", + "countires", "countries", + "courching", "crouching", + "courtesey", "courtesy", + "courtesty", "courtesy", + "coururier", "courier", + "coutnered", "countered", + "crapenter", "carpenter", + "creativey", "creatively", + "creedence", "credence", + "crhistmas", "christmas", + "cricketts", "crickets", + "criminaly", "criminally", + "critereon", "criterion", + "criterias", "criteria", + "criticaly", "critically", + "criticies", "criticise", + "criticisn", "criticising", + "critisice", "criticise", + "critisicm", "criticism", + "critising", "criticising", + "critisism", "criticism", + "critisize", "criticise", + "critizing", "criticizing", + "crosshiar", "crosshair", + "crossifre", "crossfire", + "crticised", "criticised", + "crusdaers", "crusaders", + "crutchers", "crutches", + "crystalls", "crystals", + "crystalus", "crystals", + "crystalys", "crystals", + "cuacasian", "caucasian", + "cuasality", "causality", + "culitvate", "cultivate", + "culturaly", "culturally", + "culturels", "cultures", + "curiostiy", "curiosity", + "curisoity", "curiosity", + "currenlty", "currently", + "curriculm", "curriculum", + "cursaders", "crusaders", + "custcenes", "cutscenes", + "cutsceens", "cutscenes", + "cutscence", "cutscene", + "cutsences", "cutscenes", + "cyclinder", "cylinder", + "cyclistes", "cyclists", + "cylindres", "cylinders", + "cynicisim", "cynicism", + "dahsboard", "dashboard", + "dalmation", "dalmatian", + "dangeroys", "dangerously", + "dashbaord", "dashboard", + "daugthers", "daughters", + "davantage", "advantage", + "deadlfits", "deadlifts", + "deadpoool", "deadpool", + "dealershp", "dealerships", + "deathmath", "deathmatch", + "decalring", "declaring", + "decendant", "descendant", + "decendent", "descendant", + "decipting", "depicting", + "deciption", "depiction", + "decisivie", "decisive", + "declarase", "declares", + "declarees", "declares", + "decoratie", "decorative", + "decoratin", "decorations", + "decpetion", "deception", + "decpetive", "deceptive", + "decribing", "describing", + "decsended", "descended", + "deductibe", "deductible", + "defaintly", "defiantly", + "defaltion", "deflation", + "defanitly", "defiantly", + "defeintly", "definetly", + "defendent", "defendant", + "defensese", "defenseless", + "defianlty", "defiantly", + "deficeint", "deficient", + "deficieny", "deficiency", + "deficites", "deficits", + "definance", "defiance", + "definatey", "definately", + "definatly", "definitely", + "definetly", "definitely", + "definetyl", "definetly", + "definilty", "definitly", + "definitie", "definitive", + "definitin", "definitions", + "definitly", "definitely", + "definiton", "definition", + "definitve", "definite", + "definityl", "definitly", + "definltey", "definetly", + "defintaly", "defiantly", + "defintily", "definitly", + "defintion", "definition", + "defintley", "definetly", + "defitenly", "definetly", + "defitinly", "definitly", + "defitnaly", "defiantly", + "defitnely", "definetly", + "deflectin", "deflection", + "defnietly", "definetly", + "degeneret", "degenerate", + "degradato", "degradation", + "degradead", "degraded", + "degrassie", "degrasse", + "degrassse", "degrasse", + "deifnetly", "definetly", + "deifnitly", "definitly", + "deisgners", "designers", + "delagates", "delegates", + "delcaring", "declaring", + "delcining", "declining", + "delegatie", "delegate", + "delerious", "delirious", + "deleteing", "deleting", + "delfation", "deflation", + "deliveres", "delivers", + "deliverys", "delivers", + "delpoying", "deploying", + "demcorats", "democrats", + "deminsion", "dimension", + "democarcy", "democracy", + "democract", "democrat", + "demonstre", "demonstrate", + "denominar", "denominator", + "dentistas", "dentists", + "dentistes", "dentists", + "deomcrats", "democrats", + "deopsited", "deposited", + "deparment", "department", + "departmet", "departments", + "depciting", "depicting", + "depcition", "depiction", + "depection", "deception", + "depedency", "dependency", + "depicitng", "depicting", + "depiciton", "depiction", + "deplyoing", "deploying", + "depoisted", "deposited", + "depolying", "deploying", + "depositas", "deposits", + "deposites", "deposits", + "depositis", "deposits", + "depositos", "deposits", + "depostied", "deposited", + "depressie", "depressive", + "depressin", "depression", + "depserate", "desperate", + "depsoited", "deposited", + "descirbes", "describes", + "descision", "decision", + "desginers", "designers", + "desgining", "designing", + "desicions", "decisions", + "designade", "designated", + "designato", "designation", + "desingage", "disengage", + "desingers", "designers", + "desinging", "designing", + "desktopos", "desktops", + "desparate", "desperate", + "desperato", "desperation", + "despoited", "deposited", + "desriable", "desirable", + "dessigned", "designed", + "destinato", "destination", + "destoryed", "destroyed", + "destoryer", "destroyer", + "destroyes", "destroys", + "destructo", "destruction", + "destryoed", "destroyed", + "destryoer", "destroyer", + "desuction", "seduction", + "detailled", "detailed", + "detatched", "detached", + "detectivs", "detectives", + "deteriate", "deteriorate", + "determing", "determining", + "determins", "determines", + "developrs", "develops", + "diabetees", "diabetes", + "diablical", "diabolical", + "diagonaal", "diagonal", + "diagonsed", "diagnosed", + "diagonsis", "diagnosis", + "diagramas", "diagrams", + "diagramms", "diagrams", + "dialectes", "dialects", + "dialectos", "dialects", + "diarrheoa", "diarrhea", + "diasbling", "disabling", + "dichomoty", "dichotomy", + "dicovered", "discovered", + "dictaters", "dictates", + "dictionay", "dictionary", + "difenitly", "definitly", + "diferrent", "different", + "differene", "differences", + "differens", "differences", + "differeny", "differently", + "difficuly", "difficulty", + "diffucult", "difficult", + "dificulty", "difficulty", + "diganosed", "diagnosed", + "diganosis", "diagnosis", + "dimenions", "dimensions", + "dimention", "dimension", + "dimesnion", "dimension", + "diminishs", "diminishes", + "dinasours", "dinosaurs", + "dinosuars", "dinosaurs", + "dinsoaurs", "dinosaurs", + "dionsaurs", "dinosaurs", + "diphtongs", "diphthongs", + "dipthongs", "diphthongs", + "direcotry", "directory", + "directoty", "directory", + "directroy", "directory", + "disapears", "disappears", + "disaprity", "disparity", + "disastros", "disastrous", + "disatrous", "disastrous", + "disbaling", "disabling", + "disbeleif", "disbelief", + "disbelife", "disbelief", + "disciplen", "disciplines", + "disclamer", "disclaimer", + "disclosue", "disclosure", + "disconnet", "disconnect", + "discosure", "discourse", + "discoverd", "discovered", + "discovere", "discoveries", + "discredid", "discredited", + "discribed", "described", + "discribes", "describes", + "discussin", "discussion", + "diserable", "desirable", + "disgarees", "disagrees", + "disgiused", "disguised", + "disgusied", "disguised", + "disgustes", "disgusts", + "disgustos", "disgusts", + "disgustus", "disgusts", + "dishonesy", "dishonesty", + "dishonord", "dishonored", + "disicples", "disciples", + "dismantel", "dismantle", + "dismisals", "dismissal", + "disnegage", "disengage", + "dispairty", "disparity", + "dispalyed", "displayed", + "dispartiy", "disparity", + "dispenced", "dispensed", + "dispeners", "dispenser", + "displayes", "displays", + "disruptin", "disruption", + "dissapear", "disappear", + "dissarray", "disarray", + "dissmisal", "dismissal", + "disspiate", "dissipate", + "distincte", "distinctive", + "distrcits", "districts", + "distribue", "distributed", + "distrubed", "disturbed", + "distrupts", "distrust", + "disturben", "disturbance", + "diverisfy", "diversify", + "diveristy", "diversity", + "diverstiy", "diversity", + "dividened", "dividend", + "divinitiy", "divinity", + "doccument", "document", + "docrtines", "doctrines", + "docuhebag", "douchebag", + "dogdammit", "goddammit", + "dogfather", "godfather", + "dolphines", "dolphins", + "domecracy", "democracy", + "domecrats", "democrats", + "domiantes", "dominates", + "dominatin", "domination", + "dominaton", "domination", + "dominiant", "dominant", + "donwgrade", "downgrade", + "donwloads", "downloads", + "donwsides", "downsides", + "donwvoted", "downvoted", + "donwvotes", "downvotes", + "doublelit", "doublelift", + "doucehbag", "douchebag", + "downgarde", "downgrade", + "downlaods", "downloads", + "downloaad", "download", + "downovted", "downvoted", + "dravadian", "dravidian", + "drummless", "drumless", + "dsyphoria", "dysphoria", + "dsytopian", "dystopian", + "duaghters", "daughters", + "duplicats", "duplicates", + "durabiliy", "durability", + "dynamicus", "dynamics", + "dypshoria", "dysphoria", + "dyshporia", "dysphoria", + "dysoptian", "dystopian", + "dysphoira", "dysphoria", + "dysphroia", "dysphoria", + "dyspohria", "dysphoria", + "dyspotian", "dystopian", + "dystopain", "dystopian", + "dystpoian", "dystopian", + "eachohter", "eachother", + "eachotehr", "eachother", + "eachtoher", "eachother", + "earpluggs", "earplugs", + "earthboud", "earthbound", + "eastwoood", "eastwood", + "eastwoord", "eastwood", + "ecclectic", "eclectic", + "ecomonics", "economics", + "edficient", "deficient", + "effecient", "efficient", + "efficeint", "efficient", + "efficency", "efficiency", + "efficieny", "efficiency", + "effulence", "effluence", + "egalitara", "egalitarian", + "egpytians", "egyptians", + "egyptains", "egyptians", + "egytpians", "egyptians", + "ehtically", "ethically", + "ehtnicity", "ethnicity", + "eighteeen", "eighteen", + "eitquette", "etiquette", + "ejacualte", "ejaculate", + "electivre", "elective", + "electorns", "electrons", + "electrial", "electrical", + "electricy", "electricity", + "electroal", "electoral", + "elementay", "elementary", + "elepahnts", "elephants", + "eliminase", "eliminates", + "eliminato", "elimination", + "ellignton", "ellington", + "ellingotn", "ellington", + "eloquenty", "eloquently", + "elsehwere", "elsewhere", + "emapthize", "empathize", + "embarress", "embarrassed", + "emmisarry", "emissary", + "emmisions", "emissions", + "emmitting", "emitting", + "empahsize", "emphasize", + "emperical", "empirical", + "emphaised", "emphasised", + "emphatize", "empathize", + "emphazise", "emphasize", + "emphysyma", "emphysema", + "empitness", "emptiness", + "employeer", "employer", + "employeur", "employer", + "empolyees", "employees", + "emtpiness", "emptiness", + "emualtion", "emulation", + "enahncing", "enhancing", + "enchantig", "enchanting", + "enclousre", "enclosure", + "enclsoure", "enclosure", + "encolsure", "enclosure", + "encompase", "encompass", + "enconding", "encoding", + "encounted", "encountered", + "encrpyted", "encrypted", + "encrytped", "encrypted", + "encyrpted", "encrypted", + "endangerd", "endangered", + "enevlopes", "envelopes", + "enforcees", "enforces", + "engagemet", "engagements", + "engagment", "engagement", + "engieneer", "engineer", + "engineeer", "engineer", + "engineerd", "engineered", + "enhacning", "enhancing", + "enhanceds", "enhances", + "enligthen", "enlighten", + "enourmous", "enormous", + "ensconsed", "ensconced", + "enthicity", "ethnicity", + "enthusiam", "enthusiasm", + "enthusiat", "enthusiast", + "entirelly", "entirely", + "entitlied", "entitled", + "enveloppe", "envelope", + "epidsodes", "episodes", + "epilepsey", "epilepsy", + "epiphanny", "epiphany", + "episonage", "espionage", + "epscially", "specially", + "epsionage", "espionage", + "eqautions", "equations", + "equialent", "equivalent", + "equivalet", "equivalents", + "ermington", "remington", + "erroenous", "erroneous", + "escalatie", "escalate", + "escalatin", "escalation", + "esitmated", "estimated", + "esitmates", "estimates", + "eslewhere", "elsewhere", + "especialy", "especially", + "espianoge", "espionage", + "espinoage", "espionage", + "espoinage", "espionage", + "esponiage", "espionage", + "espressso", "espresso", + "essencial", "essential", + "essentail", "essential", + "essentias", "essentials", + "essentual", "essential", + "essesital", "essential", + "estiamted", "estimated", + "estiamtes", "estimates", + "estimatin", "estimation", + "ethcially", "ethically", + "ethincity", "ethnicity", + "ethnicaly", "ethnically", + "ethniticy", "ethnicity", + "etmyology", "etymology", + "euclidian", "euclidean", + "euorpeans", "europeans", + "euphoriac", "euphoric", + "euphorica", "euphoria", + "europenas", "europeans", + "europians", "europeans", + "eurpoeans", "europeans", + "evangelia", "evangelical", + "evelation", "elevation", + "evenlopes", "envelopes", + "eventally", "eventually", + "eventualy", "eventually", + "everthing", "everything", + "evertyime", "everytime", + "everwhere", "everywhere", + "everyoens", "everyones", + "everyteim", "everytime", + "everytiem", "everytime", + "everyting", "everything", + "eveyrones", "everyones", + "evreyones", "everyones", + "evreytime", "everytime", + "exagerate", "exaggerate", + "exahusted", "exhausted", + "exapnsive", "expansive", + "exauhsted", "exhausted", + "excahnges", "exchanges", + "excecuted", "executed", + "excecutes", "executes", + "excellant", "excellent", + "excercise", "exercise", + "excerised", "exercised", + "excerises", "exercises", + "exceuting", "executing", + "exchnages", "exchanges", + "exclsuive", "exclusive", + "excludeds", "excludes", + "exclusivs", "exclusives", + "exclusivy", "exclusivity", + "excpetion", "exception", + "exculding", "excluding", + "exculsion", "exclusion", + "exculsive", "exclusive", + "execising", "exercising", + "execption", "exception", + "exectuing", "executing", + "exectuion", "execution", + "exectuive", "executive", + "executabe", "executable", + "exepmtion", "exemption", + "exerbated", "exacerbated", + "exercices", "exercise", + "exerciese", "exercises", + "exercizes", "exercise", + "exersices", "exercises", + "exhasuted", "exhausted", + "exhaustin", "exhaustion", + "exhibites", "exhibits", + "exhibitin", "exhibition", + "exhibtion", "exhibition", + "exhuasted", "exhausted", + "exibition", "exhibition", + "existance", "existence", + "existenta", "existential", + "existince", "existence", + "existnace", "existance", + "exlcuding", "excluding", + "exlcusion", "exclusion", + "exlcusive", "exclusive", + "exlpoding", "exploding", + "exlporers", "explorers", + "exlposion", "explosion", + "exonorate", "exonerate", + "expalined", "explained", + "expanisve", "expansive", + "expatriot", "expatriate", + "expectany", "expectancy", + "expection", "exception", + "expemtion", "exemption", + "experimet", "experiments", + "explaines", "explains", + "explainig", "explaining", + "explaning", "explaining", + "expliciet", "explicit", + "explicity", "explicitly", + "explictly", "explicitly", + "explioted", "exploited", + "explodeds", "explodes", + "exploites", "exploits", + "explorare", "explorer", + "explotied", "exploited", + "expolding", "exploding", + "expolited", "exploited", + "expolsion", "explosion", + "expolsive", "explosive", + "expressie", "expressive", + "expressin", "expression", + "exsitance", "existance", + "extention", "extension", + "exteriour", "exterior", + "extermely", "extremely", + "extermism", "extremism", + "extermist", "extremist", + "externaly", "externally", + "extractin", "extraction", + "extrapole", "extrapolate", + "extreemly", "extremely", + "extremers", "extremes", + "extremley", "extremely", + "extrotion", "extortion", + "eyeballls", "eyeballs", + "eyebrowes", "eyebrows", + "eyebrowns", "eyebrows", + "eyesahdow", "eyeshadow", + "eyeshdaow", "eyeshadow", + "eygptians", "egyptians", + "eytmology", "etymology", + "faceboook", "facebook", + "faciliate", "facilitate", + "facilites", "facilities", + "facilitiy", "facility", + "facinated", "fascinated", + "facutally", "factually", + "familiair", "familiar", + "familiare", "familiarize", + "familiary", "familiarity", + "familliar", "familiar", + "fanaticas", "fanatics", + "fanaticos", "fanatics", + "fanaticus", "fanatics", + "fanatsies", "fantasies", + "fanatsize", "fantasize", + "fandation", "foundation", + "fanservie", "fanservice", + "fantazise", "fantasize", + "farenheit", "fahrenheit", + "fascistes", "fascists", + "fashoined", "fashioned", + "favorties", "favorites", + "favoruite", "favourite", + "favourits", "favourites", + "favourtie", "favourite", + "fedreally", "federally", + "feminisim", "feminism", + "feminsits", "feminists", + "femminist", "feminist", + "fesitvals", "festivals", + "fetishers", "fetishes", + "fightings", "fighting", + "filetimes", "lifetimes", + "filiament", "filament", + "filmmakes", "filmmakers", + "fingernal", "fingernails", + "flashligt", "flashlight", + "flavorade", "flavored", + "flavoures", "flavours", + "flavourus", "flavours", + "flawlessy", "flawlessly", + "flexibily", "flexibility", + "fluctaute", "fluctuate", + "flucutate", "fluctuate", + "fluttersy", "fluttershy", + "follwoing", "following", + "foootball", "football", + "forcefuly", "forcefully", + "forcibley", "forcibly", + "forciblly", "forcibly", + "forearmes", "forearms", + "foreginer", "foreigner", + "foregroud", "foreground", + "foreinger", "foreigner", + "forgeiner", "foreigner", + "forgiener", "foreigner", + "forgivens", "forgiveness", + "foriegner", "foreigner", + "forigener", "foreigner", + "formerlly", "formerly", + "formualte", "formulate", + "formulaes", "formulas", + "formulars", "formulas", + "forntline", "frontline", + "forntpage", "frontpage", + "fortuante", "fortunate", + "forumlate", "formulate", + "foundatin", "foundations", + "fourteeen", "fourteen", + "fractales", "fractals", + "fractalis", "fractals", + "fractalus", "fractals", + "fragement", "fragment", + "fragmenot", "fragment", + "franchies", "franchise", + "francsico", "francisco", + "franscico", "francisco", + "frecklers", "freckles", + "freedomes", "freedoms", + "freestlye", "freestyle", + "freesytle", "freestyle", + "fremented", "fermented", + "freqeuncy", "frequency", + "frequence", "frequencies", + "friendlis", "friendlies", + "frightend", "frightened", + "fromation", "formation", + "frontapge", "frontpage", + "frontilne", "frontline", + "frustrato", "frustration", + "frustrats", "frustrates", + "fucntions", "functions", + "fullscren", "fullscreen", + "funcitons", "functions", + "functiong", "functioning", + "functtion", "function", + "furiosuly", "furiously", + "furiuosly", "furiously", + "futuristc", "futuristic", + "gagnsters", "gangsters", + "galations", "galatians", + "galdiator", "gladiator", + "gallaxies", "galaxies", + "garanteed", "guaranteed", + "garantees", "guarantees", + "garuantee", "guarantee", + "gatherins", "gatherings", + "gauntelts", "gauntlets", + "gauntlent", "gauntlet", + "gaurantee", "guarantee", + "gaurentee", "guarantee", + "genatilia", "genitalia", + "geneology", "genealogy", + "generalbs", "generals", + "generalis", "generals", + "generaste", "generates", + "generatie", "generate", + "generatin", "generations", + "generatos", "generators", + "genitaila", "genitalia", + "genitales", "genitals", + "genitalis", "genitals", + "geniunely", "genuinely", + "gentailia", "genitalia", + "gentelmen", "gentlemen", + "gentialia", "genitalia", + "genuienly", "genuinely", + "genuinley", "genuinely", + "geogrpahy", "geography", + "germaniac", "germanic", + "geurrilla", "guerrilla", + "gimmickey", "gimmicky", + "gimmickly", "gimmicky", + "girlfried", "girlfriend", + "goalkeepr", "goalkeeper", + "godafther", "godfather", + "godspeeed", "godspeed", + "goegraphy", "geography", + "goldfisch", "goldfish", + "goosebums", "goosebumps", + "gorvement", "goverment", + "govemrent", "goverment", + "govenment", "government", + "goverance", "governance", + "goveremnt", "goverment", + "goverment", "government", + "govermetn", "goverment", + "govermnet", "goverment", + "governmet", "governments", + "govorment", "government", + "govrement", "goverment", + "gracefull", "graceful", + "gracefuly", "gracefully", + "graduaste", "graduates", + "graduatin", "graduation", + "grahpical", "graphical", + "grativate", "gravitate", + "graudally", "gradually", + "graudates", "graduates", + "greenalnd", "greenland", + "grenaders", "grenades", + "grpahical", "graphical", + "guadulupe", "guadalupe", + "guaranted", "guaranteed", + "guarantes", "guarantees", + "guardains", "guardians", + "guarentee", "guarantee", + "guaridans", "guardians", + "guatamala", "guatemala", + "guerrilas", "guerrillas", + "guradians", "guardians", + "guranteed", "guaranteed", + "gurantees", "guarantees", + "gutiarist", "guitarist", + "habsbourg", "habsburg", + "hairstlye", "hairstyle", + "hairsytle", "hairstyle", + "halarious", "hilarious", + "hambruger", "hamburger", + "hamburges", "hamburgers", + "hamphsire", "hampshire", + "hamsphire", "hampshire", + "handboook", "handbook", + "handedley", "handedly", + "handedlly", "handedly", + "handicape", "handicapped", + "hapmshire", "hampshire", + "happended", "happened", + "happenend", "happened", + "happenned", "happened", + "harasment", "harassment", + "hardenend", "hardened", + "hardwoord", "hardwood", + "haristyle", "hairstyle", + "harrasing", "harassing", + "harrassed", "harassed", + "harrasses", "harassed", + "hdinsight", "hindsight", + "headahces", "headaches", + "headhpone", "headphone", + "headshoot", "headshot", + "healither", "healthier", + "healtheir", "healthier", + "healthiet", "healthiest", + "healthire", "healthier", + "heapdhone", "headphone", + "hedgehoog", "hedgehog", + "hedgehorg", "hedgehog", + "heightend", "heightened", + "heirarchy", "hierarchy", + "herculase", "hercules", + "herculeas", "hercules", + "herculees", "hercules", + "herculeus", "hercules", + "heriarchy", "hierarchy", + "hesistant", "hesitant", + "hesistate", "hesitate", + "hesitatin", "hesitation", + "hieroglph", "hieroglyph", + "highschol", "highschool", + "hindisght", "hindsight", + "hindrence", "hindrance", + "hinduisim", "hinduism", + "hinduisum", "hinduism", + "hipsanics", "hispanics", + "hirearchy", "hierarchy", + "hirsohima", "hiroshima", + "hispancis", "hispanics", + "hitboxers", "hitboxes", + "hoepfully", "hopefully", + "holocasut", "holocaust", + "holocuast", "holocaust", + "homeonwer", "homeowner", + "homeopaty", "homeopathy", + "homewolrd", "homeworld", + "homewoner", "homeowner", + "homewrold", "homeworld", + "homogenes", "homogeneous", + "homosexul", "homosexuals", + "hopelessy", "hopelessly", + "hopsitals", "hospitals", + "horishima", "hiroshima", + "horizones", "horizons", + "horizonts", "horizons", + "horrendos", "horrendous", + "horribley", "horribly", + "horriblly", "horribly", + "horrifing", "horrifying", + "hositlity", "hostility", + "hospitaly", "hospitality", + "hosptials", "hospitals", + "hourgalss", "hourglass", + "hourlgass", "hourglass", + "househols", "households", + "humanitis", "humanities", + "humanoind", "humanoid", + "humiditiy", "humidity", + "hunagrian", "hungarian", + "hurriance", "hurricane", + "hurricans", "hurricanes", + "husbandos", "husbands", + "hydraluic", "hydraulic", + "hydropile", "hydrophile", + "hydropobe", "hydrophobe", + "hydrualic", "hydraulic", + "hyopcrite", "hypocrite", + "hypcorite", "hypocrite", + "hyperoble", "hyperbole", + "hypocracy", "hypocrisy", + "hypocrasy", "hypocrisy", + "hypocricy", "hypocrisy", + "hypocriet", "hypocrite", + "hypocrits", "hypocrites", + "hyporcite", "hypocrite", + "hypothess", "hypotheses", + "hyprocisy", "hypocrisy", + "hyprocite", "hypocrite", + "hyrdation", "hydration", + "hyrdaulic", "hydraulic", + "hysterica", "hysteria", + "hysteriia", "hysteria", + "iburpofen", "ibuprofen", + "icleandic", "icelandic", + "icongnito", "incognito", + "idealisim", "idealism", + "idealistc", "idealistic", + "identifer", "identifier", + "identifiy", "identify", + "ideologis", "ideologies", + "ignornace", "ignorance", + "illegales", "illegals", + "illegalis", "illegals", + "illegalls", "illegals", + "illnesess", "illnesses", + "illsuions", "illusions", + "illuminai", "illuminati", + "imagenary", "imaginary", + "imaginery", "imaginary", + "imaptient", "impatient", + "imigrated", "emigrated", + "immensley", "immensely", + "immerisve", "immersive", + "immesnely", "immensely", + "immidiate", "immediate", + "immigrato", "immigration", + "immitated", "imitated", + "immitator", "imitator", + "immobilie", "immobile", + "immobille", "immobile", + "immobilze", "immobile", + "immortaly", "immortality", + "immserive", "immersive", + "impaitent", "impatient", + "imparital", "impartial", + "impedence", "impedance", + "implantes", "implants", + "implicati", "implicit", + "impliciet", "implicit", + "implicity", "implicitly", + "impliment", "implement", + "implusive", "impulsive", + "importamt", "important", + "importend", "imported", + "imporving", "improving", + "impossibe", "impossible", + "imprefect", "imperfect", + "impressin", "impressions", + "imprioned", "imprisoned", + "improbabe", "improbable", + "impulisve", "impulsive", + "impuslive", "impulsive", + "imrpoving", "improving", + "inadequet", "inadequate", + "inadquate", "inadequate", + "inaugures", "inaugurates", + "inbalance", "imbalance", + "inbeetwen", "inbetween", + "inbetween", "between", + "inbewteen", "inbetween", + "incarnato", "incarnation", + "incgonito", "incognito", + "inclinato", "inclination", + "includeds", "includes", + "incoginto", "incognito", + "incongito", "incognito", + "incorpore", "incorporate", + "incpetion", "inception", + "incredibe", "incredible", + "incrediby", "incredibly", + "inculding", "including", + "incunabla", "incunabula", + "indicaste", "indicates", + "indicatie", "indicative", + "indicence", "incidence", + "indicents", "incidents", + "indigenos", "indigenous", + "indirecty", "indirectly", + "indisious", "insidious", + "individul", "individual", + "individus", "individuals", + "indoensia", "indonesia", + "indoneisa", "indonesia", + "indutrial", "industrial", + "inersting", "inserting", + "inexpense", "inexpensive", + "infallibe", "infallible", + "inferioir", "inferior", + "inferiour", "inferior", + "infestato", "infestation", + "infiltrar", "infiltrator", + "infinitey", "infinity", + "infinitie", "infinite", + "infinitiy", "infinity", + "infinitly", "infinity", + "inflatabe", "inflatable", + "influense", "influences", + "influenta", "influential", + "informate", "informative", + "infraread", "infrared", + "ingeniuty", "ingenuity", + "ingeunity", "ingenuity", + "ingocnito", "incognito", + "ingorance", "ignorance", + "inguenity", "ingenuity", + "inhabitat", "inhabitants", + "inheirted", "inherited", + "inhertied", "inherited", + "initailly", "initially", + "initalese", "initialese", + "initaling", "initialing", + "initalise", "initialise", + "initalism", "initialism", + "initalize", "initialize", + "initalled", "initialled", + "initation", "initiation", + "initiales", "initials", + "initiatie", "initiatives", + "initiatin", "initiation", + "initiatve", "initiate", + "injustics", "injustices", + "inlcuding", "including", + "inmigrant", "immigrant", + "innoucous", "innocuous", + "innovatin", "innovations", + "innovatve", "innovate", + "inpection", "inception", + "inpending", "impending", + "inproving", "improving", + "inpsector", "inspector", + "inpsiring", "inspiring", + "inquisito", "inquisition", + "inquisitr", "inquisitor", + "inresting", "inserting", + "insanelly", "insanely", + "insepctor", "inspector", + "insidiuos", "insidious", + "insipring", "inspiring", + "insluated", "insulated", + "inspectin", "inspection", + "instabilt", "instability", + "installes", "installs", + "installus", "installs", + "instering", "inserting", + "insticnts", "instincts", + "institude", "instituted", + "instituto", "institution", + "insualted", "insulated", + "insurence", "insurance", + "insurgeny", "insurgency", + "integirty", "integrity", + "integraal", "integral", + "integrade", "integrated", + "integrato", "integration", + "intenisty", "intensity", + "intensley", "intensely", + "interacte", "interactive", + "interents", "internets", + "interesat", "interest", + "interesst", "interests", + "interewbs", "interwebs", + "interfase", "interfaces", + "interfeer", "interfere", + "interfers", "interferes", + "intergate", "integrate", + "intergity", "integrity", + "interiour", "interior", + "internest", "internets", + "interpert", "interpret", + "interprut", "interrupt", + "interrups", "interrupts", + "interstae", "interstate", + "interveen", "intervene", + "intervied", "interviewed", + "intervier", "interviewer", + "intervies", "interviews", + "intesnely", "intensely", + "intesnity", "intensity", + "intestins", "intestines", + "intialize", "initialize", + "inticrate", "intricate", + "intimidad", "intimidated", + "intircate", "intricate", + "intiution", "intuition", + "intiutive", "intuitive", + "intorduce", "introduce", + "intorvert", "introvert", + "intracite", "intricate", + "intrduced", "introduced", + "intregity", "integrity", + "intrenets", "internets", + "intrepret", "interpret", + "intrerupt", "interrupt", + "intrewebs", "interwebs", + "intrinisc", "intrinsic", + "intrisinc", "intrinsic", + "intrisnic", "intrinsic", + "intriuged", "intrigued", + "introdued", "introduced", + "introduse", "introduces", + "introvers", "introverts", + "intruiged", "intrigued", + "intrument", "instrument", + "inutition", "intuition", + "inutitive", "intuitive", + "invaderas", "invaders", + "invalidas", "invalidates", + "inventios", "inventions", + "investige", "investigate", + "investmet", "investments", + "invincibe", "invincible", + "invloving", "involving", + "invovling", "involving", + "ipubrofen", "ibuprofen", + "iranianos", "iranians", + "irelevent", "irrelevant", + "ironicaly", "ironically", + "irritatie", "irritate", + "irritatin", "irritation", + "isalmists", "islamists", + "isalnders", "islanders", + "islamiskt", "islamist", + "islamsits", "islamists", + "islmaists", "islamists", + "isntaller", "installer", + "isntances", "instances", + "isntantly", "instantly", + "israelies", "israelis", + "israelits", "israelis", + "italianas", "italians", + "italianos", "italians", + "jailbrake", "jailbreak", + "jalibreak", "jailbreak", + "jamaicain", "jamaican", + "jersualem", "jerusalem", + "jeruselam", "jerusalem", + "jeruslaem", "jerusalem", + "journalis", "journals", + "judegment", "judgement", + "judgemant", "judgemental", + "judisuary", "judiciary", + "jugdement", "judgement", + "juggernat", "juggernaut", + "juvenille", "juvenile", + "keneysian", "keynesian", + "kentuckey", "kentucky", + "kenyesian", "keynesian", + "keybaords", "keyboards", + "keyensian", "keynesian", + "keyesnian", "keynesian", + "keynseian", "keynesian", + "keysenian", "keynesian", + "kilometes", "kilometers", + "kindapped", "kidnapped", + "kncokback", "knockback", + "knoweldge", "knowledge", + "knowlegde", "knowledge", + "konckback", "knockback", + "kryptonie", "kryptonite", + "labirynth", "labyrinth", + "laboratoy", "laboratory", + "laboreres", "laborers", + "labratory", "laboratory", + "labriynth", "labyrinth", + "labryinth", "labyrinth", + "labyrnith", "labyrinth", + "landscaps", "landscapes", + "landscspe", "landscapes", + "langauges", "languages", + "languague", "language", + "lanuchers", "launchers", + "lanugages", "languages", + "larington", "arlington", + "latitudie", "latitude", + "lattitude", "latitude", + "laucnhers", "launchers", + "laucnhing", "launching", + "launchign", "launching", + "laybrinth", "labyrinth", + "lebanesse", "lebanese", + "leceister", "leicester", + "leciester", "leicester", + "legitmate", "legitimate", + "legnedary", "legendary", + "lesbianas", "lesbians", + "lesbianus", "lesbians", + "letivicus", "leviticus", + "leutenant", "lieutenant", + "levaithan", "leviathan", + "levellign", "levelling", + "levetated", "levitated", + "levetates", "levitates", + "levicitus", "leviticus", + "levleling", "levelling", + "lfiesteal", "lifesteal", + "liberales", "liberals", + "liberalim", "liberalism", + "liberalis", "liberals", + "liberatin", "liberation", + "libraires", "libraries", + "liecester", "leicester", + "lieuenant", "lieutenant", + "lieutenat", "lieutenant", + "lifespawn", "lifespan", + "lifestlye", "lifestyle", + "lighnting", "lightning", + "lightnign", "lightning", + "ligthning", "lightning", + "ligthroom", "lightroom", + "lingerine", "lingerie", + "lispticks", "lipsticks", + "listenend", "listened", + "literarly", "literary", + "literarry", "literary", + "literatre", "literate", + "literatue", "literate", + "literture", "literature", + "lithaunia", "lithuania", + "lithuaina", "lithuania", + "lithuiana", "lithuania", + "lithunaia", "lithuania", + "litigatin", "litigation", + "lituhania", "lithuania", + "liveprool", "liverpool", + "livestrem", "livestream", + "lobbysits", "lobbyists", + "lockscren", "lockscreen", + "logisitcs", "logistics", + "logsitics", "logistics", + "loiusiana", "louisiana", + "lollipoop", "lollipop", + "louisvile", "louisville", + "luanchers", "launchers", + "luanching", "launching", + "lubicrant", "lubricant", + "lubircant", "lubricant", + "ludcrious", "ludicrous", + "ludricous", "ludicrous", + "lunaticos", "lunatics", + "lunaticus", "lunatics", + "macaronni", "macaroni", + "maestries", "masteries", + "magainzes", "magazines", + "magensium", "magnesium", + "magincian", "magician", + "magintude", "magnitude", + "magneisum", "magnesium", + "magnesuim", "magnesium", + "magnifine", "magnificent", + "mainfesto", "manifesto", + "mainfests", "manifests", + "mainstrem", "mainstream", + "maintaing", "maintaining", + "maintance", "maintenance", + "maintians", "maintains", + "mairjuana", "marijuana", + "malasyian", "malaysian", + "malayisan", "malaysian", + "malaysain", "malaysian", + "maletonin", "melatonin", + "maltesian", "maltese", + "malyasian", "malaysian", + "managable", "manageable", + "managment", "management", + "mandarian", "mandarin", + "mandarijn", "mandarin", + "mandarion", "mandarin", + "maneouvre", "manoeuvre", + "maneuveur", "maneuver", + "maneveurs", "maneuvers", + "manfiesto", "manifesto", + "manfiests", "manifests", + "mangesium", "magnesium", + "mangitude", "magnitude", + "manouvers", "maneuvers", + "mantained", "maintained", + "manuevers", "maneuvers", + "maraudeur", "marauder", + "marevlous", "marvelous", + "margarent", "margaret", + "margarite", "margaret", + "marginaal", "marginal", + "marginaly", "marginally", + "marijauna", "marijuana", + "marineras", "mariners", + "marineris", "mariners", + "marineros", "mariners", + "marjiuana", "marijuana", + "marjority", "majority", + "marmelade", "marmalade", + "marrtyred", "martyred", + "massagens", "massages", + "massivley", "massively", + "masteires", "masteries", + "mastereis", "masteries", + "masterise", "masteries", + "mastermid", "mastermind", + "mastieres", "masteries", + "masturbae", "masturbated", + "materiaal", "material", + "matierals", "materials", + "mattreses", "mattress", + "mayalsian", "malaysian", + "maylasian", "malaysian", + "mccarthey", "mccarthy", + "mecahnics", "mechanics", + "mecernary", "mercenary", + "mechancis", "mechanics", + "mechanims", "mechanism", + "mechaninc", "mechanic", + "mechansim", "mechanism", + "medicince", "medicine", + "mediciney", "mediciny", + "meditatie", "meditate", + "meditatin", "meditation", + "megathred", "megathread", + "melanotin", "melatonin", + "melborune", "melbourne", + "melbounre", "melbourne", + "membrance", "membrane", + "menstraul", "menstrual", + "menstural", "menstrual", + "mensutral", "menstrual", + "mentiones", "mentions", + "mercanery", "mercenary", + "merhcants", "merchants", + "messagers", "messages", + "messanger", "messenger", + "metabloic", "metabolic", + "metalurgy", "metallurgy", + "methaphor", "metaphor", + "methapors", "metaphors", + "methodoly", "methodology", + "metropols", "metropolis", + "mexicanas", "mexicans", + "mexicants", "mexicans", + "mexicanus", "mexicans", + "michellle", "michelle", + "micorwave", "microwave", + "micoscopy", "microscopy", + "microphen", "microphone", + "migrantes", "migrants", + "migrianes", "migraines", + "milawukee", "milwaukee", + "milennium", "millennium", + "milestons", "milestones", + "militians", "militias", + "millenial", "millennial", + "millenian", "millennia", + "millenium", "millennium", + "millionar", "millionaire", + "millitary", "military", + "miluwakee", "milwaukee", + "milwakuee", "milwaukee", + "milwuakee", "milwaukee", + "mindcarck", "mindcrack", + "mindlessy", "mindlessly", + "minerales", "minerals", + "minisclue", "miniscule", + "miniscuel", "miniscule", + "ministery", "ministry", + "minisucle", "miniscule", + "minitaure", "miniature", + "minituare", "miniature", + "minneosta", "minnesota", + "minnestoa", "minnesota", + "minsicule", "miniscule", + "minsiters", "ministers", + "minstries", "ministries", + "miraculos", "miraculous", + "mircowave", "microwave", + "mirrorred", "mirrored", + "miserabel", "miserable", + "mispelled", "misspelled", + "misreable", "miserable", + "misreably", "miserably", + "missisipi", "mississippi", + "missonary", "missionary", + "missourri", "missouri", + "misspelld", "misspelled", + "mobilitiy", "mobility", + "moderatey", "moderately", + "moderatin", "moderation", + "modifires", "modifiers", + "moelcules", "molecules", + "moleclues", "molecules", + "molestare", "molester", + "molestato", "molestation", + "molesterd", "molested", + "monestary", "monastery", + "monitores", "monitors", + "monolgoue", "monologue", + "monolight", "moonlight", + "monolouge", "monologue", + "monopolis", "monopolies", + "monopolly", "monopoly", + "monopoloy", "monopoly", + "monserrat", "montserrat", + "monstorus", "monstrous", + "monstruos", "monstrous", + "montanous", "mountainous", + "montoring", "monitoring", + "monumnets", "monuments", + "moratlity", "mortality", + "morbidley", "morbidly", + "morgatges", "mortgages", + "morgtages", "mortgages", + "morisette", "morissette", + "mormonsim", "mormonism", + "morroccan", "moroccan", + "mortailty", "mortality", + "mosquitto", "mosquito", + "motivatie", "motivate", + "motivatin", "motivations", + "motorcyce", "motorcycles", + "motorolja", "motorola", + "motoroloa", "motorola", + "moustahce", "moustache", + "movepseed", "movespeed", + "mozzarela", "mozzarella", + "mucisians", "musicians", + "mulitated", "mutilated", + "mulitples", "multiples", + "multipled", "multiplied", + "multplies", "multiples", + "murdererd", "murdered", + "muscially", "musically", + "muscician", "musician", + "musculair", "muscular", + "mushrooom", "mushroom", + "musicains", "musicians", + "mutatiohn", "mutation", + "mutialted", "mutilated", + "mutilatin", "mutilation", + "mutliated", "mutilated", + "mutliples", "multiples", + "mutlitude", "multitude", + "mysterise", "mysteries", + "mysterous", "mysterious", + "nacrotics", "narcotics", + "naferious", "nefarious", + "nahsville", "nashville", + "narcissim", "narcissism", + "narcissit", "narcissist", + "narcissts", "narcissist", + "narctoics", "narcotics", + "nasvhille", "nashville", + "nationaal", "national", + "nationaly", "nationally", + "nativelly", "natively", + "natrually", "naturally", + "navigatie", "navigate", + "navigatin", "navigation", + "neccesary", "necessary", + "necessite", "necessities", + "neckbears", "neckbeards", + "neckbread", "neckbeard", + "nedlessly", "endlessly", + "needlessy", "needlessly", + "negiotate", "negotiate", + "negociate", "negotiate", + "negoitate", "negotiate", + "neigbhour", "neighbour", + "neigbours", "neighbours", + "neighboor", "neighbor", + "nessecary", "necessary", + "newcaslte", "newcastle", + "newcastel", "newcastle", + "nieghbour", "neighbour", + "nightfa;;", "nightfall", + "nightlcub", "nightclub", + "nigthclub", "nightclub", + "nigthlife", "nightlife", + "nigthmare", "nightmare", + "nihilisim", "nihilism", + "ninteenth", "nineteenth", + "nominatie", "nominate", + "nominatin", "nomination", + "noninital", "noninitial", + "norhteast", "northeast", + "norhtwest", "northwest", + "normanday", "normandy", + "northeren", "northern", + "norwegain", "norwegian", + "norwiegan", "norwegian", + "nostaglia", "nostalgia", + "nostaglic", "nostalgic", + "nostaliga", "nostalgia", + "nostaligc", "nostalgic", + "nostlagia", "nostalgia", + "nostlagic", "nostalgic", + "nostriles", "nostrils", + "nostrills", "nostrils", + "notacible", "noticable", + "notciable", "noticable", + "noteboook", "notebook", + "noteriety", "notoriety", + "noteworty", "noteworthy", + "noticable", "noticeable", + "noticably", "noticeably", + "noticalbe", "noticable", + "noticeing", "noticing", + "noticible", "noticeable", + "notoroius", "notorious", + "novermber", "november", + "nullabour", "nullarbor", + "numberous", "numerous", + "numercial", "numerical", + "numerious", "numerous", + "nuremburg", "nuremberg", + "nurtients", "nutrients", + "nutirents", "nutrients", + "nutreints", "nutrients", + "nutritent", "nutrient", + "nutritian", "nutritional", + "nutritios", "nutritious", + "obediance", "obedience", + "obeidence", "obedience", + "obersvant", "observant", + "obersvers", "observers", + "obesssion", "obsession", + "obiedence", "obedience", + "obivously", "obviously", + "objectivs", "objectives", + "objectivy", "objectivity", + "obscruity", "obscurity", + "obscuirty", "obscurity", + "observare", "observer", + "observerd", "observed", + "obssesion", "obsession", + "obssesive", "obsessive", + "obssessed", "obsessed", + "obstruced", "obstructed", + "obsucrity", "obscurity", + "obtainabe", "obtainable", + "obviosuly", "obviously", + "obvioulsy", "obviously", + "obvisouly", "obviously", + "obvoiusly", "obviously", + "ocasional", "occasional", + "ocasioned", "occasioned", + "ocassions", "occasions", + "occaisons", "occasions", + "occassion", "occasion", + "occurance", "occurrence", + "occurence", "occurrence", + "octohedra", "octahedra", + "ocuntries", "countries", + "ocurrance", "occurrence", + "ocurrence", "occurrence", + "offcially", "officially", + "offically", "officially", + "officialy", "officially", + "offpsring", "offspring", + "offspirng", "offspring", + "offsrping", "offspring", + "ogliarchy", "oligarchy", + "oilgarchy", "oligarchy", + "oligrachy", "oligarchy", + "ommitting", "omitting", + "onlsaught", "onslaught", + "onsalught", "onslaught", + "onslaugth", "onslaught", + "onsluaght", "onslaught", + "onwership", "ownership", + "opiniones", "opinions", + "oposition", "opposition", + "opponenet", "opponent", + "opposiste", "opposites", + "opposties", "opposites", + "oppressin", "oppression", + "opression", "oppression", + "opressive", "oppressive", + "opthalmic", "ophthalmic", + "optimisim", "optimism", + "optimistc", "optimistic", + "optinally", "optimally", + "oragnered", "orangered", + "oragnised", "organised", + "oragnizer", "organizer", + "orcehstra", "orchestra", + "ordinarly", "ordinary", + "orgainsed", "organised", + "orgainzer", "organizer", + "organered", "orangered", + "organices", "organise", + "organisim", "organism", + "organiske", "organise", + "organiste", "organise", + "organites", "organise", + "organizms", "organism", + "organsied", "organised", + "organsims", "organisms", + "organzier", "organizer", + "orginally", "originally", + "orgnaised", "organised", + "orhcestra", "orchestra", + "orientato", "orientation", + "origanaly", "originally", + "originall", "original", + "originalt", "originality", + "originaly", "originally", + "origintea", "originate", + "origional", "original", + "orignally", "originally", + "orignials", "originals", + "oublisher", "publisher", + "oursleves", "ourselves", + "oustiders", "outsiders", + "oustpoken", "outspoken", + "outisders", "outsiders", + "outnumbed", "outnumbered", + "outpalyed", "outplayed", + "outperfom", "outperform", + "outpsoken", "outspoken", + "outrageos", "outrageous", + "outskirst", "outskirts", + "outskrits", "outskirts", + "outwieghs", "outweighs", + "overbaord", "overboard", + "overclcok", "overclock", + "overdirve", "overdrive", + "overhpyed", "overhyped", + "overhwelm", "overwhelm", + "overlcock", "overclock", + "overloard", "overload", + "overpaied", "overpaid", + "overpowed", "overpowered", + "overriden", "overridden", + "overwhlem", "overwhelm", + "overwirte", "overwrite", + "overwtach", "overwatch", + "overyhped", "overhyped", + "owernship", "ownership", + "pacificts", "pacifist", + "packageid", "packaged", + "pactivity", "captivity", + "painkills", "painkillers", + "paitently", "patiently", + "paitience", "patience", + "pakistain", "pakistani", + "pakistian", "pakistani", + "pakistnai", "pakistani", + "paksitani", "pakistani", + "paladines", "paladins", + "paladinos", "paladins", + "palestein", "palestine", + "palestina", "palestinian", + "palistian", "palestinian", + "paltforms", "platforms", + "palystyle", "playstyle", + "pancakers", "pancakes", + "pantomine", "pantomime", + "paradimes", "paradise", + "paragraps", "paragraphs", + "paragrpah", "paragraph", + "paralells", "parallels", + "paralelly", "parallelly", + "paralisys", "paralysis", + "parallely", "parallelly", + "paralzyed", "paralyzed", + "paramedis", "paramedics", + "paramters", "parameters", + "paranoica", "paranoia", + "paranoida", "paranoia", + "parasties", "parasites", + "paraylsis", "paralysis", + "paraylzed", "paralyzed", + "parellels", "parallels", + "paricular", "particular", + "parisitic", "parasitic", + "paritally", "partially", + "parliment", "parliament", + "parmesaen", "parmesan", + "parntered", "partnered", + "parrallel", "parallel", + "partchett", "pratchett", + "parterned", "partnered", + "participe", "participate", + "partiotic", "patriotic", + "partisain", "partisan", + "pasengers", "passengers", + "passagens", "passages", + "passagers", "passages", + "passerbys", "passersby", + "passiones", "passions", + "passivley", "passively", + "passowrds", "passwords", + "pateintly", "patiently", + "paticular", "particular", + "patinetly", "patiently", + "patriarca", "patriarchal", + "patriarcy", "patriarchy", + "patriotas", "patriots", + "patriotes", "patriots", + "patroitic", "patriotic", + "pattented", "patented", + "pavillion", "pavilion", + "pbulisher", "publisher", + "peacefuly", "peacefully", + "pedohpile", "pedophile", + "pedophila", "pedophilia", + "pedophils", "pedophiles", + "peircings", "piercings", + "penalites", "penalties", + "penatlies", "penalties", + "penduluum", "pendulum", + "penerator", "penetrator", + "penguines", "penguins", + "penguings", "penguins", + "penguinos", "penguins", + "peninsual", "peninsula", + "peninusla", "peninsula", + "penisnula", "peninsula", + "penisular", "peninsular", + "pennisula", "peninsula", + "pensinula", "peninsula", + "pentagoon", "pentagon", + "peodphile", "pedophile", + "pepperino", "pepperoni", + "peppermit", "peppermint", + "percepted", "perceived", + "percevied", "perceived", + "percieved", "perceived", + "percisely", "precisely", + "percision", "precision", + "percursor", "precursor", + "perdators", "predators", + "peremiter", "perimeter", + "perfeclty", "perfectly", + "perfomers", "performers", + "performas", "performs", + "perfromer", "performer", + "pericings", "piercings", + "perimetre", "perimeter", + "peristent", "persistent", + "periwinke", "periwinkle", + "permanant", "permanent", + "permature", "premature", + "permenant", "permanent", + "permieter", "perimeter", + "permissie", "permissible", + "permissin", "permissions", + "permisson", "permission", + "pernament", "permanent", + "perorders", "preorders", + "perpetrar", "perpetrator", + "perpetuae", "perpetuate", + "perpetuas", "perpetuates", + "persauded", "persuaded", + "perscribe", "prescribe", + "perserved", "preserved", + "persistes", "persists", + "personaes", "personas", + "personaly", "personally", + "personell", "personnel", + "personhod", "personhood", + "persuated", "persuade", + "pertended", "pretended", + "pertoleum", "petroleum", + "perusaded", "persuaded", + "pervertes", "perverse", + "pesticids", "pesticides", + "petroluem", "petroleum", + "phemonena", "phenomena", + "phenemona", "phenomena", + "phenonema", "phenomena", + "phillipse", "phillies", + "philosopy", "philosophy", + "philosphy", "philosophy", + "phonecian", "phoenecian", + "phonemena", "phenomena", + "phongraph", "phonograph", + "photograh", "photograph", + "phsyician", "physician", + "phsyicist", "physicist", + "phycisian", "physician", + "phycisist", "physicist", + "physicaly", "physically", + "physicits", "physicist", + "physisict", "physicist", + "piblisher", "publisher", + "picthfork", "pitchfork", + "pinetrest", "pinterest", + "placeheld", "placeholder", + "placemens", "placements", + "plaestine", "palestine", + "plagarism", "plagiarism", + "planatery", "planetary", + "planation", "plantation", + "planteary", "planetary", + "plasticas", "plastics", + "plasticos", "plastics", + "plasticus", "plastics", + "platfroms", "platforms", + "platofrms", "platforms", + "plausable", "plausible", + "plausbile", "plausible", + "plausibel", "plausible", + "playgroud", "playground", + "playright", "playwright", + "playstlye", "playstyle", + "playwrite", "playwright", + "plebicite", "plebiscite", + "plethoria", "plethora", + "ploarized", "polarized", + "pointeres", "pointers", + "polinator", "pollinator", + "polishees", "polishes", + "politelly", "politely", + "politican", "politician", + "politicas", "politics", + "politicin", "politician", + "politicus", "politics", + "polygammy", "polygamy", + "populatin", "populations", + "poralized", "polarized", + "porcelian", "porcelain", + "porcelina", "porcelain", + "poreclain", "porcelain", + "porftolio", "portfolio", + "porgramme", "programme", + "portfoilo", "portfolio", + "portoflio", "portfolio", + "portraing", "portraying", + "portrayes", "portrays", + "portrayls", "portrays", + "portriats", "portraits", + "portugese", "portuguese", + "portugues", "portuguese", + "posessing", "possessing", + "posession", "possession", + "positiond", "positioned", + "positiong", "positioning", + "positionl", "positional", + "positiviy", "positivity", + "possesess", "possesses", + "possesing", "possessing", + "possesion", "possession", + "possessin", "possessions", + "possibile", "possible", + "possibily", "possibility", + "possibley", "possibly", + "possiblly", "possibly", + "possition", "position", + "powderade", "powdered", + "powerfull", "powerful", + "pracitcal", "practical", + "practhett", "pratchett", + "practicly", "practically", + "practives", "practise", + "pragamtic", "pragmatic", + "preadtors", "predators", + "precedeed", "preceded", + "preceeded", "preceded", + "preceived", "perceived", + "preciesly", "precisely", + "precisley", "precisely", + "precurors", "precursor", + "precurosr", "precursor", + "precurser", "precursor", + "predatobr", "predator", + "predictie", "predictive", + "predictin", "prediction", + "predjuice", "prejudice", + "predujice", "prejudice", + "prefectly", "perfectly", + "preferens", "preferences", + "prefering", "preferring", + "preformer", "performer", + "pregnance", "pregnancies", + "preimeter", "perimeter", + "prejiduce", "prejudice", + "prejucide", "prejudice", + "premanent", "permanent", + "premeired", "premiered", + "preorderd", "preordered", + "preparato", "preparation", + "prepatory", "preparatory", + "presentas", "presents", + "presentes", "presents", + "presicely", "precisely", + "presicion", "precision", + "presideny", "presidency", + "prestigiu", "prestigious", + "prestigue", "prestige", + "presuaded", "persuaded", + "pretendas", "pretends", + "pretensje", "pretense", + "pretinent", "pertinent", + "prevelant", "prevalent", + "preventin", "prevention", + "previvous", "previous", + "priesthod", "priesthood", + "priestood", "priesthood", + "primaires", "primaries", + "primairly", "primarily", + "primarliy", "primarily", + "primative", "primitive", + "primordal", "primordial", + "princesas", "princess", + "princeses", "princess", + "princesss", "princesses", + "principas", "principals", + "principly", "principally", + "prinicple", "principle", + "prioritie", "prioritize", + "prioritse", "priorities", + "privalege", "privilege", + "privelege", "privilege", + "privelige", "privilege", + "privilage", "privilege", + "privilegs", "privileges", + "privledge", "privilege", + "probabily", "probability", + "probablly", "probably", + "problemas", "problems", + "procative", "proactive", + "procedger", "procedure", + "proceding", "proceeding", + "proceedes", "proceeds", + "procelain", "porcelain", + "procesess", "processes", + "processer", "processor", + "processos", "processors", + "proclamed", "proclaimed", + "procotols", "protocols", + "prodecure", "procedure", + "productie", "productive", + "productin", "productions", + "productos", "products", + "profesion", "profusion", + "professer", "professor", + "professin", "professions", + "proffesed", "professed", + "proffesor", "professor", + "progessed", "progressed", + "programas", "programs", + "programem", "programme", + "programes", "programs", + "programms", "programs", + "progresso", "progression", + "progresss", "progresses", + "projectie", "projectile", + "projectin", "projection", + "prominant", "prominent", + "promiscus", "promiscuous", + "promotted", "promoted", + "pronomial", "pronominal", + "pronouced", "pronounced", + "pronounds", "pronouns", + "pronounes", "pronouns", + "propagana", "propaganda", + "properies", "properties", + "propertly", "property", + "propeties", "properties", + "prophesie", "prophecies", + "prophetes", "prophets", + "propogate", "propagate", + "proposels", "proposes", + "proposito", "proposition", + "propperly", "properly", + "propsects", "prospects", + "prosperos", "prosperous", + "prostitue", "prostitute", + "protectes", "protects", + "protectie", "protective", + "protectos", "protectors", + "proteinas", "proteins", + "proteines", "proteins", + "protestas", "protests", + "protestat", "protestant", + "protestes", "protests", + "protestos", "protests", + "protfolio", "portfolio", + "protocool", "protocol", + "prototpye", "prototype", + "prototyps", "prototypes", + "protraits", "portraits", + "protrayal", "portrayal", + "protrayed", "portrayed", + "provicial", "provincial", + "provincie", "province", + "provisios", "provisions", + "pruchased", "purchased", + "pruchases", "purchases", + "prugatory", "purgatory", + "pruposely", "purposely", + "pscyhotic", "psychotic", + "pseudonyn", "pseudonym", + "pshycosis", "psychosis", + "pshycotic", "psychotic", + "psycology", "psychology", + "psycothic", "psychotic", + "ptichfork", "pitchfork", + "pubilsher", "publisher", + "publiaher", "publisher", + "publicaly", "publicly", + "publicani", "publication", + "publicher", "publisher", + "publiclly", "publicly", + "publihser", "publisher", + "publisehr", "publisher", + "publisger", "publisher", + "publishor", "publisher", + "publishre", "publisher", + "publsiher", "publisher", + "publusher", "publisher", + "puchasing", "purchasing", + "punishmet", "punishments", + "puplisher", "publisher", + "puragtory", "purgatory", + "purcahsed", "purchased", + "purcahses", "purchases", + "purhcased", "purchased", + "purposley", "purposely", + "pursuaded", "persuaded", + "pursuades", "persuades", + "pyramidas", "pyramids", + "pyramides", "pyramids", + "pyschosis", "psychosis", + "pyschotic", "psychotic", + "qaulifies", "qualifies", + "quantifiy", "quantify", + "quantitiy", "quantity", + "quantitty", "quantity", + "quartlery", "quarterly", + "queations", "equations", + "queenland", "queensland", + "questiond", "questioned", + "questiong", "questioning", + "questionn", "questioning", + "radicalis", "radicals", + "rapsberry", "raspberry", + "rasbperry", "raspberry", + "rationaly", "rationally", + "reactiony", "reactionary", + "realisitc", "realistic", + "realoding", "reloading", + "realsitic", "realistic", + "realtable", "relatable", + "realtions", "relations", + "realtives", "relatives", + "reamining", "remaining", + "reaplying", "replaying", + "reasearch", "research", + "reaveling", "revealing", + "rebellios", "rebellious", + "rebllions", "rebellions", + "recations", "creations", + "reccomend", "recommend", + "reccuring", "recurring", + "receeding", "receding", + "recepient", "recipient", + "recgonise", "recognise", + "recgonize", "recognize", + "recidents", "residents", + "recievers", "receivers", + "recieving", "receiving", + "recipiant", "recipient", + "reciproce", "reciprocate", + "reclutant", "reluctant", + "recoginse", "recognise", + "recoginze", "recognize", + "recomends", "recommends", + "recommens", "recommends", + "reconenct", "reconnect", + "recongise", "recognise", + "recongize", "recognize", + "reconicle", "reconcile", + "reconized", "recognized", + "recordare", "recorder", + "recoveres", "recovers", + "recoverys", "recovers", + "recpetive", "receptive", + "recpetors", "receptors", + "recquired", "required", + "recreatie", "recreate", + "recruitcs", "recruits", + "recruites", "recruits", + "recrusion", "recursion", + "recrutied", "recruited", + "recrutier", "recruiter", + "rectangel", "rectangle", + "rectanlge", "rectangle", + "recuiting", "recruiting", + "recurison", "recursion", + "recurited", "recruited", + "recuriter", "recruiter", + "recusrion", "recursion", + "redeemeed", "redeemed", + "redundany", "redundancy", + "redundent", "redundant", + "reedeming", "redeeming", + "refelcted", "reflected", + "refereces", "references", + "refereees", "referees", + "refereers", "referees", + "referemce", "reference", + "referencs", "references", + "referense", "references", + "referiang", "referring", + "referinng", "refering", + "refernces", "references", + "refernece", "reference", + "refershed", "refreshed", + "refersher", "refresher", + "reffering", "referring", + "reflectie", "reflective", + "refrehser", "refresher", + "refrences", "references", + "refromist", "reformist", + "regionaal", "regional", + "registerd", "registered", + "registery", "registry", + "regualrly", "regularly", + "regualtor", "regulator", + "regulaion", "regulation", + "regulalry", "regularly", + "regulares", "regulars", + "regularis", "regulars", + "regulatin", "regulations", + "regurally", "regularly", + "reigining", "reigning", + "reinstale", "reinstalled", + "reisntall", "reinstall", + "reknowned", "renowned", + "relaoding", "reloading", + "relatiate", "retaliate", + "relativiy", "relativity", + "relativly", "relatively", + "relativno", "relation", + "relavence", "relevance", + "relcutant", "reluctant", + "relevence", "relevance", + "relfected", "reflected", + "reliabily", "reliability", + "reliabley", "reliably", + "religeous", "religious", + "remasterd", "remastered", + "rememberd", "remembered", + "rememebrs", "remembers", + "remianing", "remaining", + "remignton", "remington", + "remingotn", "remington", + "remmebers", "remembers", + "remotelly", "remotely", + "rendevous", "rendezvous", + "rendezous", "rendezvous", + "renedered", "rende", + "renegated", "renegade", + "rennovate", "renovate", + "repalying", "replaying", + "repblican", "republican", + "repeatedy", "repeatedly", + "repective", "receptive", + "repeition", "repetition", + "repentent", "repentant", + "rephrasse", "rephrase", + "replusive", "repulsive", + "reportedy", "reportedly", + "represend", "represented", + "repressin", "repression", + "reprtoire", "repertoire", + "repsonded", "responded", + "reptition", "repetition", + "reptuable", "reputable", + "repubican", "republican", + "republian", "republican", + "repulican", "republican", + "repulisve", "repulsive", + "repuslive", "repulsive", + "resaurant", "restaurant", + "researchs", "researchers", + "resembels", "resembles", + "reserverd", "reserved", + "resintall", "reinstall", + "resistane", "resistances", + "resistans", "resistances", + "resistend", "resisted", + "resistent", "resistant", + "resmebles", "resembles", + "resolutin", "resolutions", + "resoruces", "resources", + "respectes", "respects", + "respectos", "respects", + "responces", "response", + "respondas", "responds", + "respondis", "responds", + "respondus", "responds", + "respoting", "reposting", + "ressemble", "resemble", + "ressurect", "resurrect", + "restarant", "restaurant", + "resticted", "restricted", + "restircts", "restricts", + "restorani", "restoration", + "restraind", "restrained", + "restraing", "restraining", + "restraunt", "restraint", + "restriant", "restraint", + "restricte", "restrictive", + "resturant", "restaurant", + "retailate", "retaliate", + "retalaite", "retaliate", + "retaliers", "retailers", + "reteriver", "retriever", + "retirever", "retriever", + "retrevier", "retriever", + "retriving", "retrieving", + "reuptable", "reputable", + "reveiwers", "reviewers", + "revelaing", "revealing", + "revelance", "relevance", + "revolutin", "revolutions", + "rewachted", "rewatched", + "rewatchig", "rewatching", + "rferences", "references", + "ridiculos", "ridiculous", + "ridiculue", "ridicule", + "ridiculus", "ridiculous", + "righetous", "righteous", + "rightfuly", "rightfully", + "rightoues", "righteous", + "rigourous", "rigorous", + "rigtheous", "righteous", + "rilvaries", "rivalries", + "rininging", "ringing", + "rivarlies", "rivalries", + "rivlaries", "rivalries", + "roaylties", "royalties", + "roboticus", "robotics", + "roganisms", "organisms", + "royalites", "royalties", + "roylaties", "royalties", + "ruleboook", "rulebook", + "sacarstic", "sarcastic", + "sacntuary", "sanctuary", + "sacrafice", "sacrifice", + "sacrastic", "sarcastic", + "sacrifise", "sacrifices", + "salughter", "slaughter", + "samckdown", "smackdown", + "sanctiond", "sanctioned", + "sancturay", "sanctuary", + "sancutary", "sanctuary", + "sandstrom", "sandstorm", + "sandwhich", "sandwich", + "sanhedrim", "sanhedrin", + "santcuary", "sanctuary", + "santioned", "sanctioned", + "sapphirre", "sapphire", + "sastified", "satisfied", + "sastifies", "satisfies", + "satelites", "satellites", + "saterdays", "saturdays", + "satisifed", "satisfied", + "satisifes", "satisfies", + "satrudays", "saturdays", + "satsified", "satisfied", + "satsifies", "satisfies", + "sattelite", "satellite", + "saxaphone", "saxophone", + "scaepgoat", "scapegoat", + "scaleable", "scalable", + "scandales", "scandals", + "scandalos", "scandals", + "scantuary", "sanctuary", + "scaricity", "scarcity", + "scarifice", "sacrifice", + "scarmbled", "scrambled", + "scartched", "scratched", + "scartches", "scratches", + "scavanged", "scavenged", + "sceintist", "scientist", + "scholalry", "scholarly", + "sciencers", "sciences", + "scientfic", "scientific", + "scientifc", "scientific", + "scientits", "scientist", + "sclupture", "sculpture", + "scnearios", "scenarios", + "scoreboad", "scoreboard", + "scottisch", "scottish", + "scracthed", "scratched", + "scracthes", "scratches", + "scrambeld", "scrambled", + "scrathces", "scratches", + "scrollade", "scrolled", + "scrutiney", "scrutiny", + "scrutinty", "scrutiny", + "sculpteur", "sculpture", + "sculputre", "sculpture", + "scultpure", "sculpture", + "scuplture", "sculpture", + "scuptures", "sculptures", + "seamlessy", "seamlessly", + "searchign", "searching", + "sebasitan", "sebastian", + "sebastain", "sebastian", + "sebsatian", "sebastian", + "secceeded", "seceded", + "secertary", "secretary", + "secratary", "secretary", + "secratery", "secretary", + "secretery", "secretary", + "secretley", "secretly", + "sednetary", "sedentary", + "seduciton", "seduction", + "semanitcs", "semantics", + "semestres", "semesters", + "semnatics", "semantics", + "semseters", "semesters", + "senatores", "senators", + "sendetary", "sedentary", + "sensitivy", "sensitivity", + "sentimant", "sentimental", + "sepcially", "specially", + "seperated", "separated", + "seperates", "separates", + "seperator", "separator", + "septmeber", "september", + "seraching", "searching", + "seriosuly", "seriously", + "serioulsy", "seriously", + "seriuosly", "seriously", + "servantes", "servants", + "settlment", "settlement", + "sexualizd", "sexualized", + "sexuallly", "sexually", + "shadasloo", "shadaloo", + "shaprness", "sharpness", + "sharpenss", "sharpness", + "shawhsank", "shawshank", + "sheilding", "shielding", + "shephered", "shepherd", + "shileding", "shielding", + "shitstrom", "shitstorm", + "shletered", "sheltered", + "shoudlers", "shoulders", + "shouldnot", "shouldnt", + "shperical", "spherical", + "shwashank", "shawshank", + "sidebaord", "sideboard", + "siganture", "signature", + "signapore", "singapore", + "signitory", "signatory", + "silhouete", "silhouette", + "similiair", "similiar", + "simliarly", "similarly", + "simluated", "simulated", + "simluator", "simulator", + "simplifiy", "simplify", + "simualted", "simulated", + "simualtor", "simulator", + "simulatie", "simulate", + "simulatin", "simulation", + "sinagpore", "singapore", + "sincerley", "sincerely", + "singature", "signature", + "singpaore", "singapore", + "singulair", "singular", + "singulary", "singularity", + "skateboad", "skateboard", + "skeletaal", "skeletal", + "skepitcal", "skeptical", + "skepticim", "skepticism", + "sketpical", "skeptical", + "slaughted", "slaughtered", + "slaugther", "slaughter", + "slipperly", "slippery", + "sluaghter", "slaughter", + "smackdwon", "smackdown", + "smealting", "smelting", + "smeesters", "semesters", + "snadstorm", "sandstorm", + "snippetts", "snippets", + "snowfalke", "snowflake", + "snowflaek", "snowflake", + "snowlfake", "snowflake", + "snwoballs", "snowballs", + "snythesis", "synthesis", + "snythetic", "synthetic", + "socailism", "socialism", + "socailist", "socialist", + "socailize", "socialize", + "soceities", "societies", + "socialini", "socializing", + "socialiss", "socialists", + "socialsim", "socialism", + "socieites", "societies", + "socilaism", "socialism", + "socilaist", "socialist", + "sociopati", "sociopathic", + "sociopats", "sociopaths", + "socratees", "socrates", + "socrateks", "socrates", + "soemthing", "something", + "sohpomore", "sophomore", + "soliliquy", "soliloquy", + "somehting", "something", + "someoneis", "someones", + "somethign", "something", + "somethins", "somethings", + "sopohmore", "sophomore", + "sotryline", "storyline", + "soundtrak", "soundtrack", + "sountrack", "soundtrack", + "sourthern", "southern", + "souvenier", "souvenir", + "soveregin", "sovereign", + "sovereing", "sovereign", + "soveriegn", "sovereign", + "spacegoat", "scapegoat", + "spagehtti", "spaghetti", + "spahgetti", "spaghetti", + "sparlking", "sparkling", + "spartants", "spartans", + "specailly", "specially", + "specailty", "specialty", + "specality", "specialty", + "speciales", "specials", + "specialis", "specials", + "speciatly", "specialty", + "specifing", "specifying", + "specimine", "specimen", + "spectrail", "spectral", + "specualte", "speculate", + "speechers", "speeches", + "spehrical", "spherical", + "speically", "specially", + "spetember", "september", + "sphagetti", "spaghetti", + "splatooon", "splatoon", + "sponosred", "sponsored", + "sponsered", "sponsored", + "sponsores", "sponsors", + "spontanes", "spontaneous", + "sponzored", "sponsored", + "sprakling", "sparkling", + "sprinkeld", "sprinkled", + "squadroon", "squadron", + "squirrles", "squirrels", + "squirrtle", "squirrel", + "squrriels", "squirrels", + "srirachia", "sriracha", + "srirachra", "sriracha", + "stabliize", "stabilize", + "stainlees", "stainless", + "startegic", "strategic", + "startlxde", "startled", + "statisitc", "statistic", + "staurdays", "saturdays", + "steadilly", "steadily", + "stealthly", "stealthy", + "stichting", "stitching", + "sticthing", "stitching", + "stimulans", "stimulants", + "stockplie", "stockpile", + "stornegst", "strongest", + "stragetic", "strategic", + "straightn", "straighten", + "strangets", "strangest", + "strategis", "strategies", + "strawbery", "strawberry", + "streamade", "streamed", + "streamare", "streamer", + "streamear", "streamer", + "strechted", "stretched", + "strechtes", "stretches", + "strecthed", "stretched", + "strecthes", "stretches", + "stregnths", "strengths", + "strenghen", "strengthen", + "strengthn", "strengthen", + "strentghs", "strengths", + "stressade", "stressed", + "stressers", "stresses", + "strictist", "strictest", + "stringnet", "stringent", + "stroyline", "storyline", + "structual", "structural", + "structurs", "structures", + "strucutre", "structure", + "struggeld", "struggled", + "struggels", "struggles", + "stryofoam", "styrofoam", + "stuctured", "structured", + "stuggling", "struggling", + "stupitidy", "stupidity", + "sturcture", "structure", + "sturggled", "struggled", + "sturggles", "struggles", + "styrofaom", "styrofoam", + "subarmine", "submarine", + "subculter", "subculture", + "submachne", "submachine", + "subpecies", "subspecies", + "subscirbe", "subscribe", + "subsidary", "subsidiary", + "subsizide", "subsidize", + "subsquent", "subsequent", + "subsrcibe", "subscribe", + "substanse", "substances", + "substanta", "substantial", + "substante", "substantive", + "substarte", "substrate", + "substitue", "substitute", + "substract", "subtract", + "subtances", "substances", + "subtiltes", "subtitles", + "subtitels", "subtitles", + "subtletly", "subtlety", + "subtlties", "subtitles", + "succedded", "succeeded", + "succeedes", "succeeds", + "succesful", "successful", + "succesion", "succession", + "succesive", "successive", + "suceeding", "succeeding", + "sucesfuly", "successfully", + "sucessful", "successful", + "sucession", "succession", + "sucessive", "successive", + "sufferage", "suffrage", + "sufferred", "suffered", + "sufficent", "sufficient", + "suggestes", "suggests", + "suggestie", "suggestive", + "sumbarine", "submarine", + "sumberged", "submerged", + "summenors", "summoners", + "summoenrs", "summoners", + "sunderlad", "sunderland", + "sunglases", "sunglasses", + "superfluu", "superfluous", + "superiour", "superior", + "superisor", "superiors", + "supermare", "supermarket", + "superviso", "supervision", + "suposedly", "supposedly", + "supportes", "supports", + "suppreses", "suppress", + "supressed", "suppressed", + "supresses", "suppresses", + "suprising", "surprising", + "suprizing", "surprising", + "supsicion", "suspicion", + "surounded", "surrounded", + "surprized", "surprised", + "surronded", "surrounded", + "surrouded", "surrounded", + "surrouned", "surround", + "survivers", "survivors", + "survivied", "survived", + "survivour", "survivor", + "susbcribe", "subscribe", + "susbtrate", "substrate", + "susncreen", "sunscreen", + "suspectes", "suspects", + "suspendes", "suspense", + "suspensie", "suspense", + "swastikka", "swastika", + "sweatshit", "sweatshirt", + "sweetheat", "sweetheart", + "switchign", "switching", + "swithcing", "switching", + "swtiching", "switching", + "sydnicate", "syndicate", + "sykwalker", "skywalker", + "sylablles", "syllables", + "syllabels", "syllables", + "symbolsim", "symbolism", + "symettric", "symmetric", + "symmetral", "symmetric", + "symmetria", "symmetrical", + "symoblism", "symbolism", + "sympathie", "sympathize", + "symphoney", "symphony", + "symptomes", "symptoms", + "symptomps", "symptoms", + "synagouge", "synagogue", + "syndacite", "syndicate", + "syndiacte", "syndicate", + "synidcate", "syndicate", + "synonymes", "synonyms", + "synonymis", "synonyms", + "synonymns", "synonyms", + "synonymos", "synonymous", + "synonymus", "synonyms", + "synopsies", "synopsis", + "syntehsis", "synthesis", + "syntehtic", "synthetic", + "syntethic", "synthetic", + "syphyllis", "syphilis", + "syracusae", "syracuse", + "sytrofoam", "styrofoam", + "tablespon", "tablespoon", + "tacticaly", "tactically", + "tanenhill", "tannehill", + "tannheill", "tannehill", + "targetted", "targeted", + "tawainese", "taiwanese", + "tawianese", "taiwanese", + "taxanomic", "taxonomic", + "teamfighs", "teamfights", + "teamfigth", "teamfight", + "teamifght", "teamfight", + "teampseak", "teamspeak", + "teaspooon", "teaspoon", + "techician", "technician", + "techinque", "technique", + "technolgy", "technology", + "teeangers", "teenagers", + "tehtering", "tethering", + "telegrpah", "telegraph", + "televsion", "television", + "temafight", "teamfight", + "tempaltes", "templates", + "temparate", "temperate", + "templaras", "templars", + "templares", "templars", + "temporali", "temporarily", + "tenacitiy", "tenacity", + "tensiones", "tensions", + "tentacels", "tentacles", + "tentacuel", "tentacle", + "tentalces", "tentacles", + "termianls", "terminals", + "terminato", "termination", + "terorrism", "terrorism", + "terorrist", "terrorist", + "terrabyte", "terabyte", + "terribley", "terribly", + "terriblly", "terribly", + "terriroty", "territory", + "terrorits", "terrorist", + "terrorsim", "terrorism", + "tesitcles", "testicles", + "tesitmony", "testimony", + "testicels", "testicles", + "testomony", "testimony", + "texturers", "textures", + "thankfuly", "thankfully", + "thankyoou", "thankyou", + "themselfs", "themselves", + "themselvs", "themselves", + "themslves", "themselves", + "theologia", "theological", + "therafter", "thereafter", + "therefoer", "therefor", + "therefour", "therefor", + "theroists", "theorists", + "thetering", "tethering", + "thirlling", "thrilling", + "thirteeen", "thirteen", + "thoecracy", "theocracy", + "thoerists", "theorists", + "thoroughy", "thoroughly", + "thoughout", "throughout", + "threatend", "threatened", + "throrough", "thorough", + "throughly", "thoroughly", + "througout", "throughout", + "thrusdays", "thursdays", + "thurdsays", "thursdays", + "thursdsay", "thursdays", + "thursters", "thrusters", + "tiawanese", "taiwanese", + "timestmap", "timestamp", + "tirangles", "triangles", + "tocuhdown", "touchdown", + "toghether", "together", + "tolerence", "tolerance", + "tommorrow", "tomorrow", + "torandoes", "tornadoes", + "torchligt", "torchlight", + "torelable", "tolerable", + "toritllas", "tortillas", + "tornaodes", "tornadoes", + "torpeados", "torpedoes", + "torrentas", "torrents", + "torrentes", "torrents", + "tortialls", "tortillas", + "tortillia", "tortilla", + "tortillla", "tortilla", + "tottehnam", "tottenham", + "tottenahm", "tottenham", + "tottneham", "tottenham", + "toturials", "tutorials", + "touchdwon", "touchdown", + "touristas", "tourists", + "touristes", "tourists", + "touristey", "touristy", + "touristly", "touristy", + "touristsy", "touristy", + "tournamet", "tournament", + "toxicitiy", "toxicity", + "trafficed", "trafficked", + "tragicaly", "tragically", + "traileras", "trailers", + "traingles", "triangles", + "trainwrek", "trainwreck", + "traitoris", "traitors", + "traitorus", "traitors", + "tramautic", "traumatic", + "tranlsate", "translate", + "transalte", "translate", + "transcris", "transcripts", + "transcrit", "transcript", + "transferd", "transferred", + "transfere", "transferred", + "transfors", "transforms", + "transfrom", "transform", + "transiten", "transient", + "transitin", "transitions", + "transofrm", "transform", + "transplat", "transplant", + "trasnfers", "transfers", + "trasnform", "transform", + "trasnport", "transport", + "traversie", "traverse", + "travestry", "travesty", + "treasuers", "treasures", + "treasurey", "treasury", + "treatmens", "treatments", + "treausres", "treasures", + "tremendos", "tremendous", + "trhilling", "thrilling", + "trhusters", "thrusters", + "triangels", "triangles", + "trianlges", "triangles", + "tribunaal", "tribunal", + "triguered", "triggered", + "trinagles", "triangles", + "truamatic", "traumatic", + "truthfuly", "truthfully", + "tunrtable", "turntable", + "turnaroud", "turnaround", + "turntabel", "turntable", + "typcially", "typically", + "tyrranies", "tyrannies", + "ubiquitos", "ubiquitous", + "ugprading", "upgrading", + "ukrainain", "ukrainian", + "ukrainias", "ukrainians", + "ukrainina", "ukrainian", + "ukrainisn", "ukrainians", + "ukrianian", "ukrainian", + "ulitmatum", "ultimatum", + "ulteriour", "ulterior", + "umbrellla", "umbrella", + "unaminous", "unanimous", + "unanmious", "unanimous", + "unanswerd", "unanswered", + "unanymous", "unanimous", + "unbannend", "unbanned", + "uncensord", "uncensored", + "uncomited", "uncommitted", + "undercunt", "undercut", + "underdong", "underdog", + "undergard", "undergrad", + "underming", "undermining", + "understad", "understands", + "underwaer", "underwear", + "underware", "underwear", + "undescore", "underscore", + "unforseen", "unforeseen", + "unfortune", "unfortunate", + "unfriendy", "unfriendly", + "unhealhty", "unhealthy", + "unheathly", "unhealthy", + "unhelathy", "unhealthy", + "unicornis", "unicorns", + "unicornus", "unicorns", + "uniformes", "uniforms", + "uninamous", "unanimous", + "unintuive", "unintuitive", + "uniquelly", "uniquely", + "unisntall", "uninstall", + "univerity", "university", + "universse", "universes", + "univesity", "university", + "unnistall", "uninstall", + "unoffical", "unofficial", + "unopenend", "unopened", + "unplayabe", "unplayable", + "unplesant", "unpleasant", + "unpopluar", "unpopular", + "unrankend", "unranked", + "unreliabe", "unreliable", + "unrwitten", "unwritten", + "untrianed", "untrained", + "unusaully", "unusually", + "unuseable", "unusable", + "unusuable", "unusable", + "unvierses", "universes", + "unweildly", "unwieldy", + "unwieldly", "unwieldy", + "unwirtten", "unwritten", + "unworthly", "unworthy", + "upcomming", "upcoming", + "upgarding", "upgrading", + "upgradded", "upgraded", + "uplfiting", "uplifting", + "uplifitng", "uplifting", + "urkainian", "ukrainian", + "utlimatum", "ultimatum", + "vacciante", "vaccinate", + "vaccinato", "vaccination", + "vacciners", "vaccines", + "vacestomy", "vasectomy", + "vaguaries", "vagaries", + "vaibility", "viability", + "vaildated", "validated", + "vairables", "variables", + "valdiated", "validated", + "valentein", "valentine", + "valentien", "valentine", + "valentins", "valentines", + "validitiy", "validity", + "valueable", "valuable", + "vanadlism", "vandalism", + "vandalsim", "vandalism", + "varaibles", "variables", + "varations", "variations", + "variantes", "variants", + "vascetomy", "vasectomy", + "vastecomy", "vasectomy", + "veganisim", "veganism", + "vegetarin", "vegetarians", + "vegitable", "vegetable", + "vehementy", "vehemently", + "veiwpoint", "viewpoint", + "velantine", "valentine", + "vendettta", "vendetta", + "venegance", "vengeance", + "veneuzela", "venezuela", + "venezeula", "venezuela", + "venezulea", "venezuela", + "vengaence", "vengeance", + "vengenace", "vengeance", + "ventilato", "ventilation", + "verbatium", "verbatim", + "verfiying", "verifying", + "verifiyng", "verifying", + "verisions", "revisions", + "versalite", "versatile", + "versatily", "versatility", + "versiones", "versions", + "versitale", "versatile", + "verstaile", "versatile", + "verticaly", "vertically", + "veryifing", "verifying", + "vicotrian", "victorian", + "vicotries", "victories", + "victoires", "victories", + "victorain", "victorian", + "victorina", "victorian", + "victorios", "victorious", + "videogaem", "videogame", + "videogams", "videogames", + "vidoegame", "videogame", + "viewpiont", "viewpoint", + "vigilence", "vigilance", + "vigliante", "vigilante", + "vigourous", "vigorous", + "viligante", "vigilante", + "viloently", "violently", + "vincinity", "vicinity", + "vioalting", "violating", + "violentce", "violence", + "virbation", "vibration", + "virgintiy", "virginity", + "virignity", "virginity", + "virutally", "virtually", + "visibiliy", "visibility", + "vitaminas", "vitamins", + "vitamines", "vitamins", + "vitrually", "virtually", + "vociemail", "voicemail", + "voilating", "violating", + "voilation", "violation", + "voilently", "violently", + "volatiliy", "volatility", + "voleyball", "volleyball", + "volontary", "voluntary", + "volonteer", "volunteer", + "volunatry", "voluntary", + "volunteed", "volunteered", + "vriginity", "virginity", + "wallpapes", "wallpapers", + "warrantly", "warranty", + "warrriors", "warriors", + "wavelengh", "wavelength", + "weakenend", "weakened", + "weakneses", "weakness", + "weaknesss", "weaknesses", + "wealtheir", "wealthier", + "weaponary", "weaponry", + "wedensday", "wednesday", + "wednesdsy", "wednesdays", + "wednessay", "wednesdays", + "wednseday", "wednesday", + "welathier", "wealthier", + "wendesday", "wednesday", + "wesbtrook", "westbrook", + "westernes", "westerners", + "westrbook", "westbrook", + "whereever", "wherever", + "whietlist", "whitelist", + "whilrwind", "whirlwind", + "whilsting", "whistling", + "whipsered", "whispered", + "whislting", "whistling", + "whisperes", "whispers", + "whitelsit", "whitelist", + "whitleist", "whitelist", + "whitsling", "whistling", + "whrilwind", "whirlwind", + "whsipered", "whispered", + "whtielist", "whitelist", + "widespred", "widespread", + "widesread", "widespread", + "windshied", "windshield", + "wintesses", "witnesses", + "wisconisn", "wisconsin", + "wishlisht", "wishlist", + "wishpered", "whispered", + "withdrawl", "withdrawal", + "withelist", "whitelist", + "witnesess", "witnesses", + "wolrdview", "worldview", + "wolrdwide", "worldwide", + "wonderlad", "wonderland", + "wordlview", "worldview", + "wordlwide", "worldwide", + "worhtless", "worthless", + "workfroce", "workforce", + "worldivew", "worldview", + "worldveiw", "worldview", + "worstened", "worsened", + "worthelss", "worthless", + "xenbolade", "xenoblade", + "xenobalde", "xenoblade", + "xenophoby", "xenophobia", + "xeonblade", "xenoblade", + "yementite", "yemenite", + "yorkshrie", "yorkshire", + "yorskhire", "yorkshire", + "yosemitie", "yosemite", + "youngents", "youngest", + "yourselvs", "yourselves", + "zimbabwae", "zimbabwe", + "zionistas", "zionists", + "zionistes", "zionists", + "abandond", "abandoned", + "abdomine", "abdomen", + "abilitiy", "ability", + "abilties", "abilities", + "abondons", "abandons", + "aboslute", "absolute", + "abosrbed", "absorbed", + "abruplty", "abruptly", + "abrutply", "abruptly", + "abscence", "absence", + "absestos", "asbestos", + "absoluts", "absolutes", + "absolvte", "absolve", + "absorbes", "absorbs", + "absoulte", "absolute", + "abstante", "bastante", + "abudance", "abundance", + "abudcted", "abducted", + "abundunt", "abundant", + "aburptly", "abruptly", + "abuseres", "abusers", + "abusrdly", "absurdly", + "academis", "academics", + "accademy", "academy", + "acccused", "accused", + "acceptes", "accepts", + "accidens", "accidents", + "accideny", "accidently", + "accoring", "according", + "accountt", "accountant", + "accpeted", "accepted", + "accuarcy", "accuracy", + "accumule", "accumulate", + "accusato", "accusation", + "accussed", "accused", + "acedamia", "academia", + "acedemic", "academic", + "acheived", "achieved", + "acheives", "achieves", + "achieval", "achievable", + "acnedote", "anecdote", + "acording", "according", + "acornyms", "acronyms", + "acousitc", "acoustic", + "acoutsic", "acoustic", + "acovados", "avocados", + "acquifer", "acquire", + "acquited", "acquitted", + "acquried", "acquired", + "acronmys", "acronyms", + "acronysm", "acronyms", + "acroynms", "acronyms", + "acrynoms", "acronyms", + "acsended", "ascended", + "actaully", "actually", + "activite", "activities", + "activits", "activities", + "activley", "actively", + "actresss", "actresses", + "actualey", "actualy", + "actualiy", "actuality", + "actualky", "actualy", + "actualmy", "actualy", + "actualoy", "actualy", + "actualpy", "actualy", + "actualty", "actualy", + "acutally", "actually", + "acutions", "auctions", + "adaptare", "adapter", + "adbandon", "abandon", + "adbucted", "abducted", + "addictes", "addicts", + "addictin", "addictions", + "addictis", "addictions", + "addional", "additional", + "addopted", "adopted", + "addresed", "addressed", + "adealide", "adelaide", + "adecuate", "adequate", + "adeilade", "adelaide", + "adeladie", "adelaide", + "adeliade", "adelaide", + "adeqaute", "adequate", + "adheisve", "adhesive", + "adhevise", "adhesive", + "adivsors", "advisors", + "admiraal", "admiral", + "adolence", "adolescent", + "adorbale", "adorable", + "adovcacy", "advocacy", + "adpaters", "adapters", + "adquired", "acquired", + "adquires", "acquires", + "adresing", "addressing", + "adressed", "addressed", + "adroable", "adorable", + "adultrey", "adultery", + "adventue", "adventures", + "adventus", "adventures", + "advertis", "adverts", + "advesary", "adversary", + "adviseer", "adviser", + "adviseur", "adviser", + "advocade", "advocated", + "advocats", "advocates", + "advsiors", "advisors", + "aethists", "atheists", + "affaires", "affairs", + "affilate", "affiliate", + "affintiy", "affinity", + "affleunt", "affluent", + "affulent", "affluent", + "afircans", "africans", + "africain", "african", + "afternon", "afternoon", + "againnst", "against", + "agnositc", "agnostic", + "agonstic", "agnostic", + "agravate", "aggravate", + "agreemnt", "agreement", + "agregate", "aggregate", + "agressie", "agressive", + "agressor", "aggressor", + "agrieved", "aggrieved", + "agruable", "arguable", + "agruably", "arguably", + "agrument", "argument", + "ahtletes", "athletes", + "aincents", "ancients", + "airboner", "airborne", + "airbrone", "airborne", + "aircarft", "aircraft", + "airplans", "airplanes", + "airporta", "airports", + "airpsace", "airspace", + "airscape", "airspace", + "akransas", "arkansas", + "alchemey", "alchemy", + "alchohol", "alcohol", + "alcholic", "alcoholic", + "alcoholc", "alcoholics", + "aldutery", "adultery", + "aleniate", "alienate", + "algoritm", "algorithm", + "alimoney", "alimony", + "alirghty", "alrighty", + "allaince", "alliance", + "alledged", "alleged", + "alledges", "alleges", + "allegedy", "allegedly", + "allegely", "allegedly", + "allegric", "allergic", + "allergey", "allergy", + "allianse", "alliances", + "alligned", "aligned", + "allinace", "alliance", + "allopone", "allophone", + "allready", "already", + "almigthy", "almighty", + "alpahbet", "alphabet", + "alrigthy", "alrighty", + "altantic", "atlantic", + "alterato", "alteration", + "alternar", "alternator", + "althetes", "athletes", + "althetic", "athletic", + "altriusm", "altruism", + "altrusim", "altruism", + "alturism", "altruism", + "aluminim", "aluminium", + "alumnium", "aluminum", + "alunimum", "aluminum", + "amatersu", "amateurs", + "amaterus", "amateurs", + "amendmet", "amendments", + "amercian", "american", + "amercias", "americas", + "amernian", "armenian", + "amethsyt", "amethyst", + "ameythst", "amethyst", + "ammended", "amended", + "amnestry", "amnesty", + "amoungst", "amongst", + "amplifiy", "amplify", + "amplifly", "amplify", + "amrchair", "armchair", + "amrenian", "armenian", + "amtheyst", "amethyst", + "analgoue", "analogue", + "analisys", "analysis", + "analitic", "analytic", + "analouge", "analogue", + "analysie", "analyse", + "analysit", "analyst", + "analyste", "analyse", + "analysze", "analyse", + "analzyed", "analyzed", + "anaolgue", "analogue", + "anarchim", "anarchism", + "anaylses", "analyses", + "anaylsis", "analysis", + "anaylsts", "analysts", + "anaylzed", "analyzed", + "ancedote", "anecdote", + "anceints", "ancients", + "ancinets", "ancients", + "andoirds", "androids", + "andorids", "androids", + "andriods", "androids", + "anecdots", "anecdotes", + "anectode", "anecdote", + "anedocte", "anecdote", + "aneroxia", "anorexia", + "aneroxic", "anorexic", + "angostic", "agnostic", + "angrilly", "angrily", + "anicents", "ancients", + "animatie", "animate", + "animatte", "animate", + "anlayses", "analyses", + "annoints", "anoints", + "annouced", "announced", + "annoucne", "announce", + "anntenas", "antennas", + "anoerxia", "anorexia", + "anoerxic", "anorexic", + "anonymos", "anonymous", + "anoreixa", "anorexia", + "anounced", "announced", + "anoxeria", "anorexia", + "anoxeric", "anorexic", + "answeres", "answers", + "antartic", "antarctic", + "antennea", "antenna", + "antennna", "antenna", + "anticipe", "anticipate", + "antiquae", "antique", + "antivirs", "antivirus", + "anwsered", "answered", + "anyhting", "anything", + "anyhwere", "anywhere", + "anyoneis", "anyones", + "anythign", "anything", + "anytying", "anything", + "aparment", "apartment", + "apartmet", "apartments", + "apenines", "apennines", + "aperutre", "aperture", + "aplhabet", "alphabet", + "apologes", "apologise", + "aposltes", "apostles", + "apostels", "apostles", + "appaluse", "applause", + "apparant", "apparent", + "appareal", "apparel", + "appareil", "apparel", + "apperead", "appeared", + "applaued", "applaud", + "appluase", "applause", + "appology", "apology", + "apporach", "approach", + "appraoch", "approach", + "apreture", "aperture", + "apsotles", "apostles", + "aqaurium", "aquarium", + "aqcuired", "acquired", + "aquaduct", "aqueduct", + "aquairum", "aquarium", + "aquaruim", "aquarium", + "aquiring", "acquiring", + "aquitted", "acquitted", + "arbitary", "arbitrary", + "arbitray", "arbitrary", + "arbiture", "arbiter", + "architet", "architect", + "archtype", "archetype", + "aremnian", "armenian", + "argentia", "argentina", + "argubaly", "arguably", + "arguemet", "arguement", + "arguemtn", "arguement", + "ariborne", "airborne", + "aricraft", "aircraft", + "ariplane", "airplane", + "ariports", "airports", + "arispace", "airspace", + "aristote", "aristotle", + "aritfact", "artifact", + "arizonia", "arizona", + "arkasnas", "arkansas", + "arlighty", "alrighty", + "armamant", "armament", + "armenain", "armenian", + "armenina", "armenian", + "armpitts", "armpits", + "armstrog", "armstrong", + "arpanoid", "paranoid", + "arpeture", "aperture", + "arragned", "arranged", + "arrestes", "arrests", + "arrestos", "arrests", + "arsenaal", "arsenal", + "artemios", "artemis", + "artemius", "artemis", + "arthrits", "arthritis", + "articule", "articulate", + "artifacs", "artifacts", + "artifcat", "artifact", + "artilley", "artillery", + "artisitc", "artistic", + "artistas", "artists", + "arugable", "arguable", + "arugably", "arguably", + "arugment", "argument", + "asborbed", "absorbed", + "asburdly", "absurdly", + "ascneded", "ascended", + "asissted", "assisted", + "askreddt", "askreddit", + "asnwered", "answered", + "aspectos", "aspects", + "asperges", "aspergers", + "assasins", "assassins", + "assemple", "assemble", + "assertin", "assertions", + "asshates", "asshats", + "asshatts", "asshats", + "assimile", "assimilate", + "assistat", "assistants", + "assitant", "assistant", + "assmeble", "assemble", + "assmebly", "assembly", + "asssasin", "assassin", + "assualts", "assaults", + "asteorid", "asteroid", + "asteriks", "asterisk", + "asteriod", "asteroid", + "asterois", "asteroids", + "astersik", "asterisk", + "asthetic", "aesthetic", + "astronat", "astronaut", + "asutrian", "austrian", + "atheisim", "atheism", + "atheistc", "atheistic", + "atheltes", "athletes", + "atheltic", "athletic", + "athenean", "athenian", + "athesits", "atheists", + "athetlic", "athletic", + "athients", "athiest", + "atittude", "attitude", + "atlantia", "atlanta", + "atmoizer", "atomizer", + "atomzier", "atomizer", + "atribute", "attribute", + "atrifact", "artifact", + "attackes", "attackers", + "attemped", "attempted", + "attemted", "attempted", + "attemtps", "attempts", + "attidute", "attitude", + "attitide", "attitude", + "attribue", "attribute", + "aucitons", "auctions", + "audactiy", "audacity", + "audcaity", "audacity", + "audeince", "audience", + "audiobok", "audiobook", + "austeriy", "austerity", + "austiran", "austrian", + "austitic", "autistic", + "austrain", "austrian", + "australa", "australian", + "austrija", "austria", + "austrila", "austria", + "autisitc", "autistic", + "autoattk", "autoattack", + "autograh", "autograph", + "automato", "automation", + "automony", "autonomy", + "autority", "authority", + "autsitic", "autistic", + "auxilary", "auxiliary", + "avacodos", "avocados", + "avaiable", "available", + "availabe", "available", + "availble", "available", + "avaition", "aviation", + "avalable", "available", + "avalance", "avalanche", + "avataras", "avatars", + "avatards", "avatars", + "avatares", "avatars", + "averadge", "averaged", + "avergaed", "averaged", + "avergaes", "averages", + "aviaiton", "aviation", + "avilable", "available", + "avnegers", "avengers", + "avodacos", "avocados", + "awekened", "weakened", + "awesomey", "awesomely", + "awfullly", "awfully", + "awkwardy", "awkwardly", + "awnsered", "answered", + "babysite", "babysitter", + "baceause", "because", + "bacehlor", "bachelor", + "bachleor", "bachelor", + "bacholer", "bachelor", + "backeast", "backseat", + "backerds", "backers", + "backfied", "backfield", + "backpacs", "backpacks", + "balcanes", "balances", + "balconey", "balcony", + "balconny", "balcony", + "ballistc", "ballistic", + "balnaced", "balanced", + "banannas", "bananas", + "banditas", "bandits", + "bandwith", "bandwidth", + "bangkock", "bangkok", + "baptisim", "baptism", + "barabric", "barbaric", + "barbarin", "barbarian", + "barbaris", "barbarians", + "bardford", "bradford", + "bargaing", "bargaining", + "baristia", "barista", + "barrakcs", "barracks", + "barrells", "barrels", + "basicaly", "basically", + "basiclay", "basicly", + "basicley", "basicly", + "basicliy", "basicly", + "batistia", "batista", + "battalin", "battalion", + "bayonent", "bayonet", + "beachead", "beachhead", + "beacuoup", "beaucoup", + "beardude", "bearded", + "beastley", "beastly", + "beatiful", "beautiful", + "beccause", "because", + "becuasse", "becuase", + "befirend", "befriend", + "befreind", "befriend", + "begginer", "beginner", + "begginig", "begging", + "begginng", "begging", + "begining", "beginning", + "beginnig", "beginning", + "behaivor", "behavior", + "behavios", "behaviours", + "behavoir", "behavior", + "behavour", "behavior", + "behngazi", "benghazi", + "behtesda", "bethesda", + "beleived", "believed", + "beleiver", "believer", + "beleives", "believes", + "beliefes", "beliefs", + "benefica", "beneficial", + "bengahzi", "benghazi", + "bengalas", "bengals", + "bengalos", "bengals", + "bengazhi", "benghazi", + "benghzai", "benghazi", + "bengzhai", "benghazi", + "benhgazi", "benghazi", + "benidect", "benedict", + "benifits", "benefits", + "berekley", "berkeley", + "berserkr", "berserker", + "beseiged", "besieged", + "betehsda", "bethesda", + "beteshda", "bethesda", + "bethdesa", "bethesda", + "bethedsa", "bethesda", + "bethseda", "bethesda", + "beyoncye", "beyonce", + "bibilcal", "biblical", + "bicylces", "bicycles", + "bigfooot", "bigfoot", + "bigining", "beginning", + "bilbical", "biblical", + "billboad", "billboard", + "bilsters", "blisters", + "bilzzard", "blizzard", + "bilzzcon", "blizzcon", + "biologia", "biological", + "birhtday", "birthday", + "birsbane", "brisbane", + "birthdsy", "birthdays", + "biseuxal", "bisexual", + "bisexaul", "bisexual", + "bitcions", "bitcoins", + "bitocins", "bitcoins", + "blackade", "blacked", + "blackend", "blacked", + "blackjak", "blackjack", + "blacklit", "blacklist", + "blatanty", "blatantly", + "blessins", "blessings", + "blessure", "blessing", + "bloggare", "blogger", + "bloggeur", "blogger", + "bluebery", "blueberry", + "bluetooh", "bluetooth", + "blugaria", "bulgaria", + "boardway", "broadway", + "bollcoks", "bollocks", + "bomberos", "bombers", + "bookmars", "bookmarks", + "boradway", "broadway", + "boredoom", "boredom", + "bouldore", "boulder", + "bounites", "bounties", + "boutnies", "bounties", + "boutqiue", "boutique", + "bouyancy", "buoyancy", + "boyfried", "boyfriend", + "bradcast", "broadcast", + "bradfrod", "bradford", + "brakeout", "breakout", + "braodway", "broadway", + "braverly", "bravery", + "breathis", "breaths", + "breathos", "breaths", + "brekaout", "breakout", + "brendamn", "brendan", + "breweres", "brewers", + "brewerey", "brewery", + "brewerks", "brewers", + "brewerys", "brewers", + "brigaged", "brigade", + "brigated", "brigade", + "brigthen", "brighten", + "briliant", "brilliant", + "brillant", "brilliant", + "bristool", "bristol", + "brithday", "birthday", + "brittish", "british", + "briusers", "bruisers", + "broadbad", "broadband", + "broadcat", "broadcasts", + "broadley", "broadly", + "brocolli", "broccoli", + "brodaway", "broadway", + "broncoes", "broncos", + "broswing", "browsing", + "browines", "brownies", + "browisng", "browsing", + "brtually", "brutally", + "brugundy", "burgundy", + "bruisend", "bruised", + "brussles", "brussels", + "brusting", "bursting", + "bubblews", "bubbles", + "buddhits", "buddhist", + "buddhsim", "buddhism", + "buddishm", "buddhism", + "buddisht", "buddhist", + "buglaria", "bulgaria", + "buhddism", "buddhism", + "buhddist", "buddhist", + "buidlers", "builders", + "buidling", "building", + "buildins", "buildings", + "buisness", "business", + "bulagria", "bulgaria", + "bulgaira", "bulgaria", + "buliders", "builders", + "buliding", "building", + "bulletts", "bullets", + "burisers", "bruisers", + "burriots", "burritos", + "burritio", "burrito", + "burritto", "burrito", + "burrtios", "burritos", + "burssels", "brussels", + "burtally", "brutally", + "burtsing", "bursting", + "busrting", "bursting", + "butcherd", "butchered", + "butterey", "buttery", + "butterfy", "butterfly", + "butterry", "buttery", + "butthoel", "butthole", + "bycicles", "bicycles", + "cabbagge", "cabbage", + "cabients", "cabinets", + "cabinate", "cabinet", + "cabinent", "cabinet", + "cabniets", "cabinets", + "caclulus", "calculus", + "cafetera", "cafeteria", + "caffinee", "caffeine", + "cahsiers", "cashiers", + "cainster", "canister", + "calander", "calendar", + "calcular", "calculator", + "calgarry", "calgary", + "calibler", "calibre", + "caloires", "calories", + "calrkson", "clarkson", + "calroies", "calories", + "calssify", "classify", + "calulate", "calculate", + "calymore", "claymore", + "camapign", "campaign", + "cambodai", "cambodia", + "camboida", "cambodia", + "cambpell", "campbell", + "cambride", "cambridge", + "cambrige", "cambridge", + "camoufle", "camouflage", + "campagin", "campaign", + "campaing", "campaign", + "campains", "campaigns", + "camperas", "campers", + "camperos", "campers", + "canadias", "canadians", + "cananbis", "cannabis", + "cancelas", "cancels", + "canceles", "cancels", + "cancells", "cancels", + "canceres", "cancers", + "cancerns", "cancers", + "cancerus", "cancers", + "candiate", "candidate", + "candiens", "candies", + "canistre", "canister", + "cannabil", "cannibal", + "cannbial", "cannibal", + "cannibas", "cannabis", + "cansiter", "canister", + "capitans", "captains", + "capitola", "capital", + "capitulo", "capitol", + "capmbell", "campbell", + "capsuels", "capsules", + "capsulse", "capsules", + "capsumel", "capsule", + "capteurs", "captures", + "captials", "capitals", + "captians", "captains", + "capusles", "capsules", + "caputres", "captures", + "cardboad", "cardboard", + "cardianl", "cardinal", + "cardnial", "cardinal", + "careflly", "carefully", + "carefull", "careful", + "carefuly", "carefully", + "caricate", "caricature", + "caridgan", "cardigan", + "caridnal", "cardinal", + "carinval", "carnival", + "carloina", "carolina", + "carnagie", "carnegie", + "carnigie", "carnegie", + "carnvial", "carnival", + "carrotts", "carrots", + "carrotus", "carrots", + "cartells", "cartels", + "cartmaan", "cartman", + "cartride", "cartridge", + "cartrige", "cartridge", + "carvinal", "carnival", + "casaulty", "casualty", + "casheirs", "cashiers", + "cashieer", "cashier", + "cashires", "cashiers", + "castleos", "castles", + "castlers", "castles", + "casulaty", "casualty", + "cataclym", "cataclysm", + "catagory", "category", + "cataline", "catiline", + "cataloge", "catalogue", + "catalsyt", "catalyst", + "cataylst", "catalyst", + "cathloic", "catholic", + "catlayst", "catalyst", + "caucasin", "caucasian", + "causalty", "casualty", + "cellural", "cellular", + "celullar", "cellular", + "celverly", "cleverly", + "cemetary", "cemetery", + "centeres", "centers", + "centerns", "centers", + "centrase", "centres", + "centrers", "centres", + "ceratine", "creatine", + "cerberal", "cerebral", + "cerbreus", "cerberus", + "cerbures", "cerberus", + "ceremone", "ceremonies", + "cerimony", "ceremony", + "ceromony", "ceremony", + "certainy", "certainty", + "challege", "challenge", + "chambear", "chamber", + "chambres", "chambers", + "champage", "champagne", + "chanisaw", "chainsaw", + "chanlder", "chandler", + "charcaol", "charcoal", + "chargehr", "charger", + "chargeur", "charger", + "chariman", "chairman", + "charimsa", "charisma", + "charmisa", "charisma", + "charocal", "charcoal", + "charsima", "charisma", + "chasiers", "cashiers", + "chassids", "chassis", + "chassies", "chassis", + "chatolic", "catholic", + "chcukles", "chuckles", + "checkare", "checker", + "checkear", "checker", + "cheesees", "cheeses", + "cheeseus", "cheeses", + "cheetoos", "cheetos", + "chemcial", "chemical", + "chemisty", "chemistry", + "chernobl", "chernobyl", + "chiansaw", "chainsaw", + "chidlish", "childish", + "chihuaha", "chihuahua", + "childres", "childrens", + "chillade", "chilled", + "chillead", "chilled", + "chillend", "chilled", + "chilvary", "chivalry", + "chinesse", "chinese", + "chivarly", "chivalry", + "chivlary", "chivalry", + "chlidish", "childish", + "chlroine", "chlorine", + "chmabers", "chambers", + "chocolae", "chocolates", + "chocolet", "chocolates", + "choesive", "cohesive", + "choicers", "choices", + "cholrine", "chlorine", + "chorline", "chlorine", + "chracter", "character", + "christin", "christian", + "chroline", "chlorine", + "chromose", "chromosome", + "chronice", "chronicles", + "chruches", "churches", + "chuckels", "chuckles", + "cielings", "ceilings", + "cigarete", "cigarettes", + "cigarets", "cigarettes", + "cilmbers", "climbers", + "cilnatro", "cilantro", + "ciltoris", "clitoris", + "circiuts", "circuits", + "circkets", "crickets", + "circlebs", "circles", + "circluar", "circular", + "ciricuit", "circuit", + "cirlcing", "circling", + "ciruclar", "circular", + "clannand", "clannad", + "clarifiy", "clarify", + "clarskon", "clarkson", + "clasical", "classical", + "classrom", "classroom", + "classsic", "classics", + "clausens", "clauses", + "cleanies", "cleanse", + "cleasner", "cleanser", + "clenaser", "cleanser", + "clevelry", "cleverly", + "clhorine", "chlorine", + "cliamtes", "climates", + "cliantro", "cilantro", + "clickare", "clicker", + "clickbat", "clickbait", + "clickear", "clicker", + "clientes", "clients", + "clincial", "clinical", + "clinicas", "clinics", + "clinicos", "clinics", + "clipboad", "clipboard", + "clitiros", "clitoris", + "closeing", "closing", + "closeley", "closely", + "clyamore", "claymore", + "clyinder", "cylinder", + "cmoputer", "computer", + "coindice", "coincide", + "collapes", "collapse", + "collares", "collars", + "collaris", "collars", + "collaros", "collars", + "collaspe", "collapse", + "colleage", "colleagues", + "collecte", "collective", + "collegue", "colleague", + "collisin", "collisions", + "collosal", "colossal", + "collpase", "collapse", + "coloardo", "colorado", + "colordao", "colorado", + "colubmia", "columbia", + "columnas", "columns", + "comadres", "comrades", + "comander", "commander", + "comandos", "commandos", + "comapany", "company", + "comapres", "compares", + "combiens", "combines", + "combinig", "combining", + "comediac", "comedic", + "comedias", "comedians", + "comestic", "cosmetic", + "comision", "commission", + "comiting", "committing", + "comitted", "committed", + "comittee", "committee", + "commandd", "commanded", + "commecen", "commence", + "commedic", "comedic", + "commense", "commenters", + "commenty", "commentary", + "commiest", "commits", + "commited", "committed", + "commitee", "committee", + "commites", "commits", + "committe", "committee", + "committs", "commits", + "commitus", "commits", + "commmand", "command", + "communit", "communist", + "companis", "companions", + "comparse", "compares", + "comparte", "compare", + "compasso", "compassion", + "compelte", "complete", + "compense", "compensate", + "complais", "complains", + "complane", "complacent", + "complate", "complacent", + "compleet", "complete", + "completi", "complexity", + "complets", "completes", + "complety", "completely", + "complexs", "complexes", + "complext", "complexity", + "complexy", "complexity", + "complict", "complicit", + "complier", "compiler", + "compones", "compose", + "componet", "components", + "componts", "compost", + "composet", "compost", + "composit", "compost", + "composte", "compose", + "comprese", "compressed", + "compreso", "compressor", + "compsers", "compress", + "comptown", "compton", + "compunet", "compute", + "computre", "compute", + "comradre", "comrade", + "comsetic", "cosmetic", + "conatins", "contains", + "conceald", "concealed", + "conceide", "conceived", + "conceled", "concede", + "concened", "concede", + "concepta", "conceptual", + "concered", "concede", + "concernt", "concert", + "concerte", "concrete", + "concesso", "concession", + "conceted", "concede", + "conceved", "concede", + "concibes", "concise", + "concider", "consider", + "concides", "concise", + "concious", "conscious", + "conclued", "conclude", + "concluse", "conclusive", + "concluso", "conclusion", + "concreet", "concrete", + "concrets", "concerts", + "condemnd", "condemned", + "conditon", "condition", + "condomes", "condoms", + "condomns", "condoms", + "conduict", "conduit", + "conected", "connected", + "conencts", "connects", + "confeses", "confess", + "confesos", "confess", + "confesso", "confession", + "configue", "configure", + "confilct", "conflict", + "confirmd", "confirmed", + "conflcit", "conflict", + "conflics", "conflicts", + "confrims", "confirms", + "conicide", "coincide", + "conlcude", "conclude", + "conqueor", "conquer", + "conquerd", "conquered", + "conqured", "conquered", + "conscent", "consent", + "consious", "conscious", + "constans", "constants", + "constast", "constants", + "constatn", "constant", + "constrat", "constraint", + "construt", "constructs", + "containd", "contained", + "containg", "containing", + "contaire", "containers", + "contanti", "contacting", + "contense", "contenders", + "contenst", "contents", + "contexta", "contextual", + "contextl", "contextual", + "contians", "contains", + "contined", "continued", + "contines", "continents", + "continum", "continuum", + "continus", "continues", + "continut", "continuity", + "continuu", "continuous", + "contracr", "contractor", + "contracs", "contracts", + "controll", "control", + "contruct", "construct", + "convenit", "convenient", + "convento", "convention", + "converst", "converts", + "convertr", "converter", + "conviced", "convinced", + "convicto", "conviction", + "convingi", "convincing", + "convinse", "convinces", + "cooldows", "cooldowns", + "coordine", "coordinate", + "coralina", "carolina", + "corollla", "corolla", + "corolloa", "corolla", + "corosion", "corrosion", + "corpsers", "corpses", + "corrdior", "corridor", + "correcty", "correctly", + "correnti", "correcting", + "corretly", "correctly", + "corrupto", "corruption", + "cosemtic", "cosmetic", + "cosutmes", "costumes", + "couldnot", "couldnt", + "coulored", "coloured", + "counries", "countries", + "counseil", "counsel", + "counsole", "counsel", + "counterd", "countered", + "countert", "counteract", + "countres", "counters", + "courtrom", "courtroom", + "courtsey", "courtesy", + "cousines", "cousins", + "cousings", "cousins", + "coutners", "counters", + "covanent", "covenant", + "coverted", "converted", + "coyotees", "coyotes", + "cpatains", "captains", + "cranbery", "cranberry", + "crayones", "crayons", + "creaeted", "created", + "createin", "creatine", + "createur", "creature", + "creatien", "creatine", + "creepgin", "creeping", + "cricling", "circling", + "cringely", "cringey", + "cringery", "cringey", + "criticas", "critics", + "critices", "critics", + "criticie", "criticise", + "criticim", "criticisms", + "criticis", "critics", + "criticms", "critics", + "criticos", "critics", + "criticts", "critics", + "criticus", "critics", + "critiera", "criteria", + "critized", "criticized", + "croatioa", "croatia", + "crossfie", "crossfire", + "crosshar", "crosshair", + "crosspot", "crosspost", + "crowbahr", "crowbar", + "cruasder", "crusader", + "cruciaal", "crucial", + "crucibel", "crucible", + "cruicble", "crucible", + "crusdaer", "crusader", + "crusiers", "cruisers", + "crusiing", "cruising", + "cruthces", "crutches", + "cthulhlu", "cthulhu", + "cthulluh", "cthulhu", + "cubpoard", "cupboard", + "cuddleys", "cuddles", + "culprint", "culprit", + "cultrual", "cultural", + "culutral", "cultural", + "cupbaord", "cupboard", + "cupborad", "cupboard", + "curcible", "crucible", + "curisers", "cruisers", + "curising", "cruising", + "currecny", "currency", + "currence", "currencies", + "currenly", "currently", + "currenty", "currently", + "cursader", "crusader", + "custcene", "cutscene", + "cutsceen", "cutscene", + "cutscens", "cutscenes", + "cutsence", "cutscene", + "cylcists", "cyclists", + "cylidner", "cylinder", + "cylindre", "cylinder", + "cynisicm", "cynicism", + "cyrstals", "crystals", + "dacquiri", "daiquiri", + "daimonds", "diamonds", + "dangeros", "dangers", + "dangerus", "dangers", + "darkenss", "darkness", + "darnkess", "darkness", + "dashboad", "dashboard", + "daugther", "daughter", + "deadlfit", "deadlift", + "deadlifs", "deadlifts", + "deafauts", "defaults", + "deafeted", "defeated", + "deafults", "defaults", + "dealying", "delaying", + "deamenor", "demeanor", + "deathcat", "deathmatch", + "debuffes", "debuffs", + "debufffs", "debuffs", + "decalred", "declared", + "decalres", "declares", + "decembre", "december", + "decidely", "decidedly", + "decieved", "deceived", + "decifits", "deficits", + "decipted", "depicted", + "declears", "declares", + "declinig", "declining", + "decmeber", "december", + "decribed", "described", + "decribes", "describes", + "dedicato", "dedication", + "deductie", "deductible", + "defautls", "defaults", + "defectos", "defects", + "defectus", "defects", + "defendas", "defends", + "defendes", "defenders", + "defendis", "defends", + "defendre", "defender", + "defendrs", "defends", + "defensea", "defenseman", + "defensen", "defenseman", + "defensie", "defensive", + "defetead", "defeated", + "deffined", "defined", + "deficiet", "deficient", + "definate", "definite", + "definaty", "definately", + "definety", "definetly", + "definito", "definition", + "definitv", "definitive", + "deflatin", "deflation", + "deflecto", "deflection", + "defualts", "defaults", + "degarded", "degraded", + "degenere", "degenerate", + "degraged", "degrade", + "degrated", "degrade", + "deisgned", "designed", + "deisgner", "designer", + "dekstops", "desktops", + "delcared", "declared", + "delcares", "declares", + "delepted", "depleted", + "delivere", "deliveries", + "delpeted", "depleted", + "delpoyed", "deployed", + "delyaing", "delaying", + "demandas", "demands", + "demandes", "demands", + "demenaor", "demeanor", + "democray", "democracy", + "demolito", "demolition", + "denseley", "densely", + "densitiy", "density", + "deomcrat", "democrat", + "deovtion", "devotion", + "departer", "departure", + "departue", "departure", + "depcited", "depicted", + "depelted", "depleted", + "dependat", "dependant", + "depictes", "depicts", + "depictin", "depictions", + "depolyed", "deployed", + "depositd", "deposited", + "depostis", "deposits", + "depresse", "depressive", + "depresso", "depression", + "derivate", "derivative", + "descened", "descend", + "descibed", "described", + "descirbe", "describe", + "descrise", "describes", + "desgined", "designed", + "desginer", "designer", + "desicive", "decisive", + "designad", "designated", + "designes", "designs", + "designet", "designated", + "desinged", "designed", + "desinger", "designer", + "desitned", "destined", + "desktiop", "desktop", + "desorder", "disorder", + "despides", "despised", + "despiste", "despise", + "destiney", "destiny", + "destinty", "destiny", + "destkops", "desktops", + "destorys", "destroys", + "destrose", "destroyers", + "destroyd", "destroyed", + "destroyr", "destroyers", + "detalied", "detailed", + "detectas", "detects", + "detectes", "detects", + "detectie", "detectives", + "determen", "determines", + "devasted", "devastated", + "develope", "develop", + "devialet", "deviate", + "deviatie", "deviate", + "devilers", "delivers", + "devloved", "devolved", + "devovled", "devolved", + "diaganol", "diagonal", + "diagnoal", "diagonal", + "diagnoes", "diagnose", + "diagnosi", "diagnostic", + "diagonse", "diagnose", + "diahrrea", "diarrhea", + "dialetcs", "dialects", + "dialgoue", "dialogue", + "dialouge", "dialogue", + "diarreah", "diarrhea", + "diarreha", "diarrhea", + "dichtomy", "dichotomy", + "dickisch", "dickish", + "dicovers", "discovers", + "dicovery", "discovery", + "dicussed", "discussed", + "diferent", "different", + "differnt", "different", + "difficut", "difficulty", + "diffrent", "different", + "diganose", "diagnose", + "dignitiy", "dignity", + "dimaonds", "diamonds", + "dinasour", "dinosaur", + "dinosaus", "dinosaurs", + "dinosuar", "dinosaur", + "dinsoaur", "dinosaur", + "dionsaur", "dinosaur", + "diphtong", "diphthong", + "diplomma", "diploma", + "dipthong", "diphthong", + "direclty", "directly", + "directin", "directions", + "directix", "directx", + "directos", "directors", + "directoy", "directory", + "directrx", "directx", + "dirfting", "drifting", + "disabeld", "disabled", + "disabels", "disables", + "disagred", "disagreed", + "disagres", "disagrees", + "disbaled", "disabled", + "disbales", "disables", + "disbelif", "disbelief", + "dischard", "discharged", + "dischare", "discharged", + "discound", "discounted", + "discoure", "discourse", + "discoved", "discovered", + "discreto", "discretion", + "discribe", "describe", + "disentry", "dysentery", + "disgiuse", "disguise", + "dishoner", "dishonored", + "dishonet", "dishonesty", + "dislikse", "dislikes", + "dismante", "dismantle", + "dismisse", "dismissive", + "disolved", "dissolved", + "dispacth", "dispatch", + "dispalys", "displays", + "dispence", "dispense", + "dispersa", "dispensary", + "displayd", "displayed", + "disposle", "dispose", + "disposte", "dispose", + "dispoves", "dispose", + "disptach", "dispatch", + "disricts", "districts", + "dissovle", "dissolve", + "distates", "distaste", + "distatse", "distaste", + "disticnt", "distinct", + "distorto", "distortion", + "distrcit", "district", + "districs", "districts", + "disturbd", "disturbed", + "disupted", "disputed", + "disuptes", "disputes", + "diversed", "diverse", + "diversiy", "diversify", + "dividens", "dividends", + "divintiy", "divinity", + "divisons", "divisions", + "doapmine", "dopamine", + "docrines", "doctrines", + "docrtine", "doctrine", + "doctines", "doctrines", + "doctirne", "doctrine", + "doctrins", "doctrines", + "dogamtic", "dogmatic", + "dolhpins", "dolphins", + "domapine", "dopamine", + "domecrat", "democrat", + "domiante", "dominate", + "dominato", "domination", + "dominats", "dominates", + "dominent", "dominant", + "dominoin", "dominion", + "donwload", "download", + "donwvote", "downvote", + "doomdsay", "doomsday", + "doosmday", "doomsday", + "doplhins", "dolphins", + "dopmaine", "dopamine", + "dormtund", "dortmund", + "dortumnd", "dortmund", + "dotrmund", "dortmund", + "douchely", "douchey", + "doucheus", "douches", + "dowloads", "downloads", + "downlaod", "download", + "downloas", "downloads", + "downstar", "downstairs", + "downvore", "downvoters", + "downvotr", "downvoters", + "downvots", "downvotes", + "draculea", "dracula", + "draculla", "dracula", + "dragones", "dragons", + "dragonus", "dragons", + "drfiting", "drifting", + "driectly", "directly", + "drifitng", "drifting", + "driveris", "drivers", + "drotmund", "dortmund", + "duaghter", "daughter", + "dumbbels", "dumbbells", + "dumptser", "dumpster", + "dumspter", "dumpster", + "dunegons", "dungeons", + "dungeoun", "dungeon", + "dungoens", "dungeons", + "dupicate", "duplicate", + "duplicas", "duplicates", + "dwarvens", "dwarves", + "dyanmics", "dynamics", + "dyanmite", "dynamite", + "dymanics", "dynamics", + "dymanite", "dynamite", + "dynastry", "dynasty", + "dysentry", "dysentery", + "dysphora", "dysphoria", + "earilest", "earliest", + "eatswood", "eastwood", + "eceonomy", "economy", + "ecidious", "deciduous", + "ecologia", "ecological", + "ecomonic", "economic", + "ecstacys", "ecstasy", + "ecstascy", "ecstasy", + "ecstasty", "ecstasy", + "ectastic", "ecstatic", + "editoras", "editors", + "editores", "editors", + "efficent", "efficient", + "egpytian", "egyptian", + "egyptain", "egyptian", + "egytpian", "egyptian", + "ehtereal", "ethereal", + "ehternet", "ethernet", + "eigtheen", "eighteen", + "electhor", "electro", + "electorn", "electron", + "elementy", "elementary", + "elephans", "elephants", + "elevatin", "elevation", + "elicided", "elicited", + "eligable", "eligible", + "elimiate", "eliminate", + "eliminas", "eliminates", + "elitisim", "elitism", + "elitistm", "elitism", + "ellected", "elected", + "embarass", "embarrass", + "embargos", "embargoes", + "embarras", "embarrass", + "embassay", "embassy", + "embassey", "embassy", + "embasssy", "embassy", + "emergend", "emerged", + "emergerd", "emerged", + "eminated", "emanated", + "emminent", "eminent", + "emmisary", "emissary", + "emmision", "emission", + "emmiting", "emitting", + "emmitted", "emitted", + "empathie", "empathize", + "empirial", "empirical", + "emulatin", "emulation", + "enahnces", "enhances", + "enchanct", "enchant", + "encolsed", "enclosed", + "endanged", "endangered", + "endevors", "endeavors", + "endevour", "endeavour", + "endlessy", "endlessly", + "endorces", "endorse", + "engeneer", "engineer", + "engeries", "energies", + "engineed", "engineered", + "engrames", "engrams", + "engramms", "engrams", + "enigneer", "engineer", + "enitrely", "entirely", + "enlcosed", "enclosed", + "enlsaved", "enslaved", + "ensalved", "enslaved", + "enterity", "entirety", + "entierly", "entirely", + "entierty", "entirety", + "entilted", "entitled", + "entirley", "entirely", + "entiteld", "entitled", + "entitity", "entity", + "entropay", "entropy", + "entrophy", "entropy", + "ephipany", "epiphany", + "epihpany", "epiphany", + "epilespy", "epilepsy", + "epilgoue", "epilogue", + "episdoes", "episodes", + "epitomie", "epitome", + "epliepsy", "epilepsy", + "epliogue", "epilogue", + "epsiodes", "episodes", + "epsresso", "espresso", + "eqaulity", "equality", + "eqaution", "equation", + "equailty", "equality", + "eraticly", "erratically", + "erroneos", "erroneous", + "errupted", "erupted", + "escalato", "escalation", + "esctatic", "ecstatic", + "esential", "essential", + "esitmate", "estimate", + "esperate", "seperate", + "esportes", "esports", + "estiamte", "estimate", + "estoeric", "esoteric", + "estonija", "estonia", + "estoniya", "estonia", + "etherael", "ethereal", + "etherent", "ethernet", + "ethicaly", "ethically", + "etiquete", "etiquette", + "etrailer", "retailer", + "eugencis", "eugenics", + "eugneics", "eugenics", + "euhporia", "euphoria", + "euhporic", "euphoric", + "euorpean", "european", + "euphoira", "euphoria", + "euphroia", "euphoria", + "euphroic", "euphoric", + "europian", "european", + "eurpoean", "european", + "evangers", "avengers", + "everyons", "everyones", + "evidencd", "evidenced", + "evidende", "evidenced", + "evloving", "evolving", + "evolveds", "evolves", + "evolveos", "evolves", + "evovling", "evolving", + "excecute", "execute", + "excedded", "exceeded", + "excelent", "excellent", + "exceptin", "exceptions", + "excerise", "exercise", + "excisted", "existed", + "exclusie", "exclusives", + "exculded", "excluded", + "exculdes", "excludes", + "exection", "execution", + "exectued", "executed", + "executie", "executive", + "executin", "execution", + "exellent", "excellent", + "exerbate", "exacerbate", + "exercide", "exercised", + "exercies", "exercise", + "exersice", "exercise", + "exersize", "exercise", + "exhalted", "exalted", + "exhaustn", "exhaustion", + "exhausto", "exhaustion", + "exicting", "exciting", + "exisitng", "existing", + "existane", "existance", + "existant", "existent", + "existend", "existed", + "exlcuded", "excluded", + "exlcudes", "excludes", + "exlporer", "explorer", + "exoticas", "exotics", + "exoticos", "exotics", + "expalins", "explains", + "expandas", "expands", + "expandes", "expands", + "expansie", "expansive", + "expectes", "expects", + "expectus", "expects", + "expedito", "expedition", + "expences", "expense", + "expensie", "expense", + "expensve", "expense", + "expertas", "experts", + "expertis", "experts", + "expertos", "experts", + "expireds", "expires", + "explaind", "explained", + "explaing", "explaining", + "expliots", "exploits", + "explodie", "explode", + "exploint", "exploit", + "explosie", "explosive", + "explosin", "explosions", + "exploted", "explode", + "expoldes", "explodes", + "expolits", "exploits", + "exportas", "exports", + "exportes", "exports", + "exportfs", "exports", + "exposees", "exposes", + "exposito", "exposition", + "expresse", "expressive", + "expresss", "expresses", + "expressy", "expressly", + "exressed", "expressed", + "exsitent", "existent", + "exsiting", "existing", + "extactly", "exactly", + "extemely", "extremely", + "extendes", "extends", + "extendos", "extends", + "extenion", "extension", + "extensie", "extensive", + "extensis", "extensions", + "extortin", "extortion", + "extracto", "extraction", + "extreems", "extremes", + "extremly", "extremely", + "eygptian", "egyptian", + "faboulus", "fabulous", + "fabricas", "fabrics", + "fabrices", "fabrics", + "fabricus", "fabrics", + "faceplam", "facepalm", + "facilisi", "facilities", + "faciltiy", "facility", + "facsists", "fascists", + "factores", "factors", + "factorys", "factors", + "factualy", "factually", + "faggotts", "faggots", + "faggotus", "faggots", + "falcones", "falcons", + "falgship", "flagship", + "faliures", "failures", + "falseley", "falsely", + "falshing", "flashing", + "falvored", "flavored", + "falvours", "flavours", + "familair", "familiar", + "famoulsy", "famously", + "fanatism", "fanaticism", + "fanatsic", "fanatics", + "fanserve", "fanservice", + "fantasty", "fantasy", + "farcking", "fracking", + "fascisim", "fascism", + "fashiond", "fashioned", + "fasicsts", "fascists", + "fatigure", "fatigue", + "favorits", "favorites", + "favourie", "favourites", + "feasable", "feasible", + "feasbile", "feasible", + "febraury", "february", + "februray", "february", + "feburary", "february", + "fedility", "fidelity", + "fedorahs", "fedoras", + "fedorans", "fedoras", + "feilding", "fielding", + "feisable", "feasible", + "feitshes", "fetishes", + "feltcher", "fletcher", + "felxible", "flexible", + "feminint", "femininity", + "feminsim", "feminism", + "feromone", "pheromone", + "fesiable", "feasible", + "festivas", "festivals", + "festivle", "festive", + "fictious", "fictitious", + "fideling", "fielding", + "fideltiy", "fidelity", + "fiedling", "fielding", + "fiedlity", "fidelity", + "fighitng", "fighting", + "figthing", "fighting", + "fileding", "fielding", + "fimilies", "families", + "finacial", "financial", + "fineshes", "finesse", + "fingersi", "fingertips", + "finnisch", "finnish", + "finsihes", "finishes", + "firebals", "fireballs", + "firendly", "friendly", + "firmwear", "firmware", + "firwmare", "firmware", + "flaghsip", "flagship", + "flamable", "flammable", + "flasghip", "flagship", + "flatterd", "flattered", + "flatteur", "flatter", + "flattire", "flatter", + "flavores", "flavors", + "flechter", "fletcher", + "flecther", "fletcher", + "flemmish", "flemish", + "flethcer", "fletcher", + "flexbile", "flexible", + "flexibel", "flexible", + "flippade", "flipped", + "flitered", "filtered", + "florecen", "florence", + "floridia", "florida", + "floruide", "fluoride", + "floruish", "flourish", + "flourine", "fluorine", + "floursih", "flourish", + "fluorish", "flourish", + "fluroide", "fluoride", + "folowing", "following", + "fontrier", "fontier", + "forasken", "forsaken", + "forbiden", "forbidden", + "foreamrs", "forearms", + "foreksin", "foreskin", + "forenics", "forensic", + "forenisc", "forensic", + "foresnic", "forensic", + "foreward", "foreword", + "foricbly", "forcibly", + "forigven", "forgiven", + "formatin", "formation", + "formelly", "formerly", + "formuals", "formulas", + "fornesic", "forensic", + "forresst", "forrest", + "forsekan", "forsaken", + "forsekin", "foreskin", + "forsenic", "forensic", + "forskaen", "forsaken", + "forsting", "frosting", + "fortitue", "fortitude", + "fortunae", "fortune", + "fortunte", "fortune", + "forumlas", "formulas", + "forunner", "forerunner", + "fossiles", "fossils", + "fossilis", "fossils", + "foundary", "foundry", + "fountian", "fountain", + "fourties", "forties", + "fowrards", "forwards", + "frackign", "fracking", + "framgent", "fragment", + "franches", "franchise", + "franchie", "franchises", + "franciso", "francisco", + "frankiln", "franklin", + "franlkin", "franklin", + "freckels", "freckles", + "freindly", "friendly", + "frequeny", "frequency", + "friendle", "friendlies", + "friendsi", "friendlies", + "frimware", "firmware", + "frogiven", "forgiven", + "frointer", "frontier", + "fromerly", "formerly", + "froniter", "frontier", + "fronteir", "frontier", + "frosaken", "forsaken", + "frutcose", "fructose", + "fucntion", "function", + "fufilled", "fulfilled", + "fulfiled", "fulfilled", + "fullfill", "fulfill", + "funciton", "function", + "fundirse", "fundies", + "funniliy", "funnily", + "funnilly", "funnily", + "furctose", "fructose", + "furition", "fruition", + "furuther", "further", + "futurers", "futures", + "futureus", "futures", + "gamemdoe", "gamemode", + "gamepaly", "gameplay", + "gamergat", "gamertag", + "gammeode", "gamemode", + "ganerate", "generate", + "garantee", "guarantee", + "gardient", "gradient", + "garfeild", "garfield", + "garfiled", "garfield", + "garflied", "garfield", + "garnison", "garrison", + "garrions", "garrison", + "garriosn", "garrison", + "garrsion", "garrison", + "gatherig", "gatherings", + "gauarana", "guaraná", + "gauntelt", "gauntlet", + "gauntles", "gauntlets", + "gaurdian", "guardian", + "gaurding", "guarding", + "gautnlet", "gauntlet", + "gemoetry", "geometry", + "generaly", "generally", + "generase", "generates", + "generats", "generates", + "genialia", "genitalia", + "genisues", "geniuses", + "genitala", "genitalia", + "genrates", "generates", + "gentials", "genitals", + "gentlemn", "gentlemen", + "genuises", "geniuses", + "geograpy", "geography", + "geomerty", "geometry", + "geomtery", "geometry", + "germanos", "germans", + "germanus", "germans", + "gernades", "grenades", + "giagbyte", "gigabyte", + "gigabtye", "gigabyte", + "gigaybte", "gigabyte", + "gigbayte", "gigabyte", + "gignatic", "gigantic", + "giltched", "glitched", + "giltches", "glitches", + "girafffe", "giraffe", + "girefing", "griefing", + "girlling", "grilling", + "gladiatr", "gladiator", + "glichted", "glitched", + "glichtes", "glitches", + "glicthed", "glitched", + "glicthes", "glitches", + "glitchey", "glitchy", + "glitchly", "glitchy", + "glitchty", "glitchy", + "glithced", "glitched", + "glithces", "glitches", + "gloablly", "globally", + "glodberg", "goldberg", + "glodfish", "goldfish", + "gloriuos", "glorious", + "gltiched", "glitched", + "gltiches", "glitches", + "gmaertag", "gamertag", + "goblings", "goblins", + "goddammn", "goddamn", + "goddammt", "goddammit", + "godesses", "goddesses", + "godlberg", "goldberg", + "godlfish", "goldfish", + "godounov", "godunov", + "godpseed", "godspeed", + "godspede", "godspeed", + "goldifsh", "goldfish", + "gonewidl", "gonewild", + "goodlcuk", "goodluck", + "goregous", "gorgeous", + "gorgoeus", "gorgeous", + "gorillia", "gorilla", + "gorillla", "gorilla", + "gospells", "gospels", + "gottleib", "gottlieb", + "gourmelt", "gourmet", + "gourment", "gourmet", + "gouvener", "governor", + "govement", "government", + "goverend", "governed", + "govermet", "goverment", + "governer", "governor", + "gradualy", "gradually", + "grafield", "garfield", + "grafitti", "graffiti", + "grahpics", "graphics", + "grahpite", "graphite", + "graident", "gradient", + "granolla", "granola", + "graphcis", "graphics", + "grapichs", "graphics", + "grappnel", "grapple", + "greandes", "grenades", + "greatful", "grateful", + "greeneer", "greener", + "greenhoe", "greenhouse", + "greenlad", "greenland", + "greenore", "greener", + "greusome", "gruesome", + "grieifng", "griefing", + "grifeing", "griefing", + "grizzlay", "grizzly", + "grizzley", "grizzly", + "grpahics", "graphics", + "grpahite", "graphite", + "gruseome", "gruesome", + "guantano", "guantanamo", + "guardain", "guardian", + "guardias", "guardians", + "guaridan", "guardian", + "guerrila", "guerrilla", + "guidence", "guidance", + "guiseppe", "giuseppe", + "guitards", "guitars", + "guitares", "guitars", + "guitarit", "guitarist", + "gullbile", "gullible", + "gunanine", "guanine", + "guniness", "guinness", + "gunniess", "guinness", + "guradian", "guardian", + "gurading", "guarding", + "gurantee", "guarantee", + "guresome", "gruesome", + "guttaral", "guttural", + "gutteral", "guttural", + "hacthing", "hatching", + "hafltime", "halftime", + "haircuit", "haircut", + "halfitme", "halftime", + "hallowen", "halloween", + "hamburgr", "hamburgers", + "hamitlon", "hamilton", + "hamliton", "hamilton", + "handcufs", "handcuffs", + "handeldy", "handedly", + "handlade", "handled", + "handlare", "handler", + "handledy", "handedly", + "hannbial", "hannibal", + "haording", "hoarding", + "hapening", "happening", + "happends", "happens", + "happenes", "happens", + "happilly", "happily", + "harldine", "hardline", + "harrased", "harassed", + "harrases", "harasses", + "hatchign", "hatching", + "hatesink", "heatsink", + "hathcing", "hatching", + "headachs", "headaches", + "headests", "headsets", + "headhsot", "headshot", + "headseat", "headset", + "healthit", "healthiest", + "heastink", "heatsink", + "heathern", "heathen", + "heatskin", "heatsink", + "heaviliy", "heavily", + "heavilly", "heavily", + "heavnely", "heavenly", + "hedeghog", "hedgehog", + "hegdehog", "hedgehog", + "heighest", "heights", + "heighted", "heightened", + "heirachy", "hierarchy", + "heistant", "hesitant", + "heistate", "hesitate", + "hellifre", "hellfire", + "helluvva", "helluva", + "helpfull", "helpful", + "heratige", "heritage", + "herclues", "hercules", + "heridity", "heredity", + "heroicas", "heroics", + "heroices", "heroics", + "heroicos", "heroics", + "heroicus", "heroics", + "hertiage", "heritage", + "herucles", "hercules", + "hestiant", "hesitant", + "hestiate", "hesitate", + "heveanly", "heavenly", + "hierachy", "hierarchy", + "hierarcy", "hierarchy", + "highlane", "highlander", + "hindiusm", "hinduism", + "hindusim", "hinduism", + "hinudism", "hinduism", + "hiptsers", "hipsters", + "hispanis", "hispanics", + "hispters", "hipsters", + "histroic", "historic", + "hodlings", "holdings", + "hoenstly", "honestly", + "hoildays", "holidays", + "holdiays", "holidays", + "hollywod", "hollywood", + "homeword", "homeworld", + "homineim", "hominem", + "homineum", "hominem", + "honeslty", "honestly", + "honeymon", "honeymoon", + "honsetly", "honestly", + "hopefuly", "hopefully", + "hopkings", "hopkins", + "hopsital", "hospital", + "horading", "hoarding", + "horzions", "horizons", + "hosptial", "hospital", + "hosteles", "hostels", + "hostiliy", "hostility", + "hotshoot", "hotshot", + "hotsport", "hotspot", + "hsyteria", "hysteria", + "htaching", "hatching", + "htiboxes", "hitboxes", + "huanting", "haunting", + "humaniod", "humanoid", + "humanite", "humanities", + "humantiy", "humanity", + "humerous", "humorous", + "huminoid", "humanoid", + "humitidy", "humidity", + "humoural", "humoral", + "humouros", "humorous", + "humurous", "humorous", + "hunderds", "hundreds", + "hundread", "hundred", + "hungarin", "hungarian", + "huntmsan", "huntsman", + "hutnsman", "huntsman", + "hybrides", "hybrids", + "hybridus", "hybrids", + "hydorgen", "hydrogen", + "hydratin", "hydration", + "hydregon", "hydrogen", + "hygience", "hygiene", + "hygienne", "hygiene", + "hyperbel", "hyperbole", + "hypocrit", "hypocrite", + "hyponsis", "hypnosis", + "hyrdogen", "hydrogen", + "icefrong", "icefrog", + "icelings", "ceilings", + "idaeidae", "idea", + "idealogy", "ideology", + "idealsim", "idealism", + "idenfity", "identify", + "idenitfy", "identify", + "identite", "identities", + "ideologe", "ideologies", + "illiegal", "illegal", + "illinios", "illinois", + "illionis", "illinois", + "illnesss", "illnesses", + "illumini", "illuminati", + "illustre", "illustrate", + "illution", "illusion", + "ilogical", "illogical", + "ilterate", "literate", + "imapired", "impaired", + "imgrants", "migrants", + "imigrant", "emigrant", + "immboile", "immobile", + "immenint", "imminent", + "immersie", "immerse", + "immersve", "immerse", + "immitate", "imitate", + "immoblie", "immobile", + "immortas", "immortals", + "impactes", "impacts", + "impactos", "impacts", + "imparied", "impaired", + "imperavi", "imperative", + "imperfet", "imperfect", + "implemet", "implements", + "implosed", "implode", + "impluses", "impulses", + "imporper", "improper", + "importas", "imports", + "importen", "importance", + "importes", "imports", + "imporved", "improved", + "imporves", "improves", + "impropre", "improper", + "improted", "imported", + "improvie", "improvised", + "impusles", "impulses", + "imrpoved", "improved", + "imrpoves", "improves", + "inbetwen", "inbetween", + "inclince", "incline", + "inclinde", "incline", + "includng", "including", + "incorect", "incorrect", + "incuding", "including", + "inculded", "included", + "indianas", "indians", + "indiands", "indians", + "indiania", "indiana", + "indianna", "indiana", + "indianos", "indians", + "indicato", "indication", + "indicats", "indicators", + "indonesa", "indonesia", + "indulgue", "indulge", + "infantis", "infants", + "infantus", "infants", + "infarred", "infrared", + "infectin", "infections", + "infermon", "inferno", + "infiltre", "infiltrate", + "infintie", "infinite", + "infintiy", "infinity", + "inflatie", "inflate", + "influens", "influences", + "informas", "informs", + "informis", "informs", + "infromal", "informal", + "infromed", "informed", + "ingenius", "ingenious", + "ingition", "ignition", + "ingorant", "ignorant", + "inheriet", "inherit", + "inherint", "inherit", + "inhumaan", "inhuman", + "inhumain", "inhuman", + "inifnite", "infinite", + "inifnity", "infinity", + "inisghts", "insights", + "initails", "initials", + "initaite", "initiate", + "initaled", "initialed", + "initally", "initially", + "initialy", "initially", + "initmacy", "intimacy", + "initmate", "intimate", + "injustie", "injustices", + "inlcuded", "included", + "inlcudes", "includes", + "innocens", "innocents", + "innocuos", "innocuous", + "innvoate", "innovate", + "inocence", "innocence", + "inpolite", "impolite", + "inpsired", "inspired", + "inquirey", "inquiry", + "inquirie", "inquire", + "inquiriy", "inquiry", + "inrested", "inserted", + "insanley", "insanely", + "insectes", "insects", + "insectos", "insects", + "insertas", "inserts", + "insertes", "inserts", + "insertos", "inserts", + "insidios", "insidious", + "insigths", "insights", + "insipred", "inspired", + "insipres", "inspires", + "insistas", "insists", + "insistes", "insists", + "insistis", "insists", + "insmonia", "insomnia", + "insomina", "insomnia", + "insonmia", "insomnia", + "inspried", "inspired", + "inspries", "inspires", + "instanse", "instances", + "instanty", "instantly", + "instered", "inserted", + "insticnt", "instinct", + "instincs", "instincts", + "institue", "institute", + "insultas", "insults", + "insultes", "insults", + "insultos", "insults", + "intamicy", "intimacy", + "intamite", "intimate", + "intendes", "intends", + "intendos", "intends", + "intentas", "intents", + "intented", "intended", + "interace", "interacted", + "interacs", "interacts", + "interect", "interacted", + "interent", "internet", + "interese", "interested", + "interfce", "interface", + "intergal", "integral", + "internts", "interns", + "internus", "interns", + "interpet", "interpret", + "interrim", "interim", + "interste", "interstate", + "interupt", "interrupt", + "intevene", "intervene", + "intially", "initially", + "intiials", "initials", + "intimaty", "intimately", + "intimide", "intimidate", + "intregal", "integral", + "intriuge", "intrigue", + "introdue", "introduces", + "introdus", "introduces", + "introvet", "introvert", + "intruige", "intrigue", + "intutive", "intuitive", + "inudstry", "industry", + "inventer", "inventor", + "invertes", "inverse", + "invincil", "invincible", + "invitato", "invitation", + "invloved", "involved", + "invloves", "involves", + "invovled", "involved", + "invovles", "involves", + "iranains", "iranians", + "iraninas", "iranians", + "iritable", "irritable", + "iritated", "irritated", + "ironicly", "ironically", + "irritato", "irritation", + "isalmist", "islamist", + "isarelis", "israelis", + "islamits", "islamist", + "islamsit", "islamist", + "islandes", "islanders", + "ismalist", "islamist", + "isntalls", "installs", + "isolatie", "isolate", + "israelli", "israeli", + "israleis", "israelis", + "isralies", "israelis", + "isrealis", "israelis", + "issueing", "issuing", + "italains", "italians", + "jaguards", "jaguars", + "jaguares", "jaguars", + "jailbrek", "jailbreak", + "jaimacan", "jamaican", + "jamacain", "jamaican", + "jamaicia", "jamaica", + "jamiacan", "jamaican", + "januaray", "january", + "janurary", "january", + "jeapardy", "jeopardy", + "jefferry", "jeffery", + "jefferty", "jeffery", + "jennigns", "jennings", + "jeoprady", "jeopardy", + "jepoardy", "jeopardy", + "jerusalm", "jerusalem", + "jewelrey", "jewelry", + "jewllery", "jewellery", + "joanthan", "jonathan", + "joepardy", "jeopardy", + "johanine", "johannine", + "jonatahn", "jonathan", + "journaal", "journal", + "journied", "journeyed", + "journies", "journeys", + "joysitck", "joystick", + "juadaism", "judaism", + "judaisim", "judaism", + "judgemet", "judgements", + "juducial", "judicial", + "jugnling", "jungling", + "junglign", "jungling", + "junlging", "jungling", + "justifiy", "justify", + "juveline", "juvenile", + "juvenlie", "juvenile", + "katemine", "ketamine", + "kennedey", "kennedy", + "ketmaine", "ketamine", + "keybaord", "keyboard", + "keyboars", "keyboards", + "keyborad", "keyboard", + "keychian", "keychain", + "kicthens", "kitchens", + "kindgoms", "kingdoms", + "kittiens", "kitties", + "knockbak", "knockback", + "knowlege", "knowledge", + "knuckels", "knuckles", + "koreanos", "koreans", + "kunckles", "knuckles", + "kurdisch", "kurdish", + "labatory", "lavatory", + "labenese", "lebanese", + "laboraty", "laboratory", + "laguages", "languages", + "landscae", "landscapes", + "langauge", "language", + "lanucher", "launcher", + "lanuches", "launches", + "laodouts", "loadouts", + "larwence", "lawrence", + "lasagnea", "lasagna", + "lasagnia", "lasagna", + "laucnhed", "launched", + "laucnher", "launcher", + "laucnhes", "launches", + "laundrey", "laundry", + "lawernce", "lawrence", + "lazyness", "laziness", + "leaglize", "legalize", + "lecteurs", "lectures", + "lecutres", "lectures", + "lefitsts", "leftists", + "leftsits", "leftists", + "legenday", "legendary", + "legionis", "legions", + "legitimt", "legitimate", + "lengthes", "lengths", + "lengthly", "lengthy", + "lentiles", "lentils", + "lentills", "lentils", + "lesbains", "lesbians", + "lesibans", "lesbians", + "levander", "lavender", + "levelign", "leveling", + "levetate", "levitate", + "leviathn", "leviathan", + "levleing", "leveling", + "liberato", "liberation", + "libertae", "liberate", + "libertea", "liberate", + "librarse", "libraries", + "licencie", "licence", + "licencse", "licence", + "liebrals", "liberals", + "liekable", "likeable", + "lifepsan", "lifespan", + "lifestel", "lifesteal", + "lifestye", "lifestyle", + "lighitng", "lighting", + "lightnig", "lightning", + "lightres", "lighters", + "lightrom", "lightroom", + "ligthers", "lighters", + "ligthing", "lighting", + "likebale", "likeable", + "limitant", "militant", + "limitato", "limitation", + "lincolin", "lincoln", + "lincolon", "lincoln", + "lineupes", "lineups", + "lingeire", "lingerie", + "lingiere", "lingerie", + "linnaena", "linnaean", + "lipstics", "lipsticks", + "liquidas", "liquids", + "liquides", "liquids", + "liquidos", "liquids", + "liscense", "license", + "lisenced", "silenced", + "listenes", "listens", + "listents", "listens", + "listners", "listeners", + "litature", "literature", + "litecion", "litecoin", + "liteicon", "litecoin", + "literaly", "literally", + "lithuana", "lithuania", + "litigato", "litigation", + "liverpol", "liverpool", + "locagion", "location", + "logtiech", "logitech", + "longitme", "longtime", + "longtiem", "longtime", + "looseley", "loosely", + "loreplay", "roleplay", + "luanched", "launched", + "luancher", "launcher", + "luanches", "launches", + "lubricat", "lubricant", + "lucifear", "lucifer", + "luckilly", "luckily", + "macarino", "macaroni", + "machiens", "machines", + "mackeral", "mackerel", + "macthups", "matchups", + "magasine", "magazine", + "magazins", "magazines", + "magentic", "magnetic", + "magicain", "magician", + "magisine", "magazine", + "magizine", "magazine", + "magnetis", "magnets", + "magnited", "magnitude", + "magnitue", "magnitude", + "mainfest", "manifest", + "maintian", "maintain", + "majoroty", "majority", + "makrsman", "marksman", + "malariya", "malaria", + "malasiya", "malaysia", + "malasyia", "malaysia", + "malayisa", "malaysia", + "malyasia", "malaysia", + "mamalian", "mammalian", + "manadrin", "mandarin", + "manaully", "manually", + "mandaste", "mandates", + "mandrain", "mandarin", + "mandrian", "mandarin", + "maneveur", "maneuver", + "manevuer", "maneuver", + "manfiest", "manifest", + "mangetic", "magnetic", + "manglade", "mangled", + "manifeso", "manifesto", + "manipule", "manipulate", + "manouver", "maneuver", + "manuales", "manuals", + "manuever", "maneuver", + "maraconi", "macaroni", + "maradeur", "marauder", + "maraduer", "marauder", + "maragret", "margaret", + "marbleds", "marbles", + "margerat", "margaret", + "margines", "margins", + "margings", "margins", + "marginis", "margins", + "marignal", "marginal", + "marilyin", "marilyn", + "marinens", "marines", + "markedet", "marketed", + "markeras", "markers", + "markerts", "markers", + "marniers", "mariners", + "marraige", "marriage", + "marryied", "married", + "marskman", "marksman", + "maruader", "marauder", + "marvelos", "marvelous", + "marxisim", "marxism", + "mascarra", "mascara", + "massacer", "massacre", + "massarce", "massacre", + "massasge", "massages", + "masscare", "massacre", + "masteris", "masteries", + "masturbe", "masturbate", + "materias", "materials", + "mathcups", "matchups", + "mathewes", "mathews", + "matieral", "material", + "matterss", "mattress", + "mauarder", "marauder", + "maximini", "maximizing", + "mayalsia", "malaysia", + "maybelle", "maybelline", + "maylasia", "malaysia", + "mccarhty", "mccarthy", + "mcgergor", "mcgregor", + "mchanics", "mechanics", + "mclarean", "mclaren", + "mcreggor", "mcgregor", + "meagtron", "megatron", + "meancing", "menacing", + "meaninng", "meaning", + "meatbals", "meatballs", + "mecahnic", "mechanic", + "mechanim", "mechanism", + "mechanis", "mechanics", + "medacine", "medicine", + "medatite", "meditate", + "medeival", "medieval", + "medevial", "medieval", + "mediavel", "medieval", + "medicaly", "medically", + "mediciad", "medicaid", + "medicins", "medicines", + "medicore", "mediocre", + "medievel", "medieval", + "mediocer", "mediocre", + "mediocry", "mediocrity", + "mediorce", "mediocre", + "meditato", "meditation", + "mediveal", "medieval", + "medoicre", "mediocre", + "meerkrat", "meerkat", + "megatorn", "megatron", + "meidcare", "medicare", + "meixcans", "mexicans", + "melboure", "melbourne", + "meltodwn", "meltdown", + "memoriez", "memorize", + "mencaing", "menacing", + "menstrul", "menstrual", + "mentiong", "mentioning", + "meoldies", "melodies", + "merchans", "merchants", + "mercurcy", "mercury", + "mercurey", "mercury", + "merficul", "merciful", + "merhcant", "merchant", + "mericful", "merciful", + "messgaed", "messaged", + "messiach", "messiah", + "metagaem", "metagame", + "metahpor", "metaphor", + "metamage", "metagame", + "methapor", "metaphor", + "metldown", "meltdown", + "metricas", "metrics", + "metrices", "metrics", + "metropos", "metropolis", + "mexcians", "mexicans", + "mexicain", "mexican", + "mhytical", "mythical", + "michagan", "michigan", + "michgian", "michigan", + "microtax", "microatx", + "microwae", "microwaves", + "midfeild", "midfield", + "midfiled", "midfield", + "midifeld", "midfield", + "migrains", "migraines", + "migriane", "migraine", + "milennia", "millennia", + "miligram", "milligram", + "miliitas", "militias", + "miliraty", "military", + "militais", "militias", + "millenia", "millennia", + "millenna", "millennia", + "miltiant", "militant", + "minature", "miniature", + "mindcrak", "mindcrack", + "minerial", "mineral", + "mingiame", "minigame", + "minimage", "minigame", + "minimals", "minimalist", + "minimalt", "minimalist", + "minimini", "minimizing", + "minimium", "minimum", + "miniscue", "miniscule", + "minsiter", "minister", + "minsitry", "ministry", + "miraculu", "miraculous", + "miralces", "miracles", + "mircales", "miracles", + "mircoatx", "microatx", + "mirgaine", "migraine", + "mirorred", "mirrored", + "misnadry", "misandry", + "misogynt", "misogynist", + "missigno", "mission", + "missiony", "missionary", + "misslies", "missiles", + "missorui", "missouri", + "misspeld", "misspelled", + "mistakey", "mistakenly", + "mistread", "mistreated", + "mobiltiy", "mobility", + "moderats", "moderates", + "modulair", "modular", + "moleculs", "molecules", + "momentos", "moments", + "momentus", "moments", + "monagomy", "monogamy", + "mongoles", "mongols", + "mongolos", "mongols", + "monitord", "monitored", + "monogmay", "monogamy", + "monolite", "monolithic", + "monologe", "monologue", + "monolopy", "monopoly", + "monoploy", "monopoly", + "monopols", "monopolies", + "monrachy", "monarchy", + "monstros", "monstrous", + "montaban", "montana", + "montains", "mountains", + "montanha", "montana", + "montania", "montana", + "montanna", "montana", + "montanta", "montana", + "montanya", "montana", + "montaran", "montana", + "monteize", "monetize", + "monteral", "montreal", + "montiors", "monitors", + "montnana", "montana", + "montypic", "monotypic", + "monumnet", "monument", + "moonligt", "moonlight", + "moprhine", "morphine", + "morbildy", "morbidly", + "mordibly", "morbidly", + "morevoer", "moreover", + "morhpine", "morphine", + "moribdly", "morbidly", + "mormones", "mormons", + "mormonts", "mormons", + "moroever", "moreover", + "morotola", "motorola", + "morphein", "morphine", + "morriosn", "morrison", + "morrocco", "morocco", + "morrsion", "morrison", + "mortards", "mortars", + "mortarts", "mortars", + "moruning", "mourning", + "mosnters", "monsters", + "mosqueto", "mosquitoes", + "mosquite", "mosquitoes", + "mosqutio", "mosquito", + "motoroal", "motorola", + "mounment", "monument", + "mounring", "mourning", + "mountian", "mountain", + "moustace", "moustache", + "movesped", "movespeed", + "mozillia", "mozilla", + "mozillla", "mozilla", + "msytical", "mystical", + "mucnhies", "munchies", + "mudering", "murdering", + "muffings", "muffins", + "muffinus", "muffins", + "mulitple", "multiple", + "mulitply", "multiply", + "multiplr", "multiplier", + "multipls", "multiples", + "mundance", "mundane", + "mundande", "mundane", + "muniches", "munchies", + "murderes", "murders", + "murderus", "murders", + "muscluar", "muscular", + "muscualr", "muscular", + "musicaly", "musically", + "musuclar", "muscular", + "mutliple", "multiple", + "mutliply", "multiply", + "myhtical", "mythical", + "mysitcal", "mystical", + "mysogyny", "misogyny", + "mysteris", "mysteries", + "mythraic", "mithraic", + "nagivate", "navigate", + "naopleon", "napoleon", + "napcakes", "pancakes", + "naploeon", "napoleon", + "napoelon", "napoleon", + "napolean", "napoleon", + "napoloen", "napoleon", + "narcissm", "narcissism", + "narcisst", "narcissist", + "narcotis", "narcotics", + "narwharl", "narwhal", + "naseuous", "nauseous", + "nashvile", "nashville", + "nasueous", "nauseous", + "natievly", "natively", + "nationas", "nationals", + "nationsl", "nationals", + "nativley", "natively", + "natuilus", "nautilus", + "naturaly", "naturally", + "naturels", "natures", + "naturely", "naturally", + "naturens", "natures", + "naturual", "natural", + "nauesous", "nauseous", + "naughtly", "naughty", + "nauitlus", "nautilus", + "nauseuos", "nauseous", + "nautiuls", "nautilus", + "nautlius", "nautilus", + "nautulis", "nautilus", + "naviagte", "navigate", + "navigato", "navigation", + "nazereth", "nazareth", + "necesary", "necessary", + "neckbead", "neckbeard", + "needlees", "needles", + "nefarios", "nefarious", + "negativy", "negativity", + "neglectn", "neglecting", + "neglible", "negligible", + "neigbour", "neighbour", + "neolitic", "neolithic", + "netboook", "netbook", + "neuronas", "neurons", + "neutraal", "neutral", + "neutralt", "neutrality", + "neutraly", "neutrality", + "newcaste", "newcastle", + "nickanme", "nickname", + "nickmane", "nickname", + "nieghbor", "neighbor", + "nightime", "nighttime", + "nightley", "nightly", + "nightlie", "nightlife", + "nihilsim", "nihilism", + "nilihism", "nihilism", + "nirtogen", "nitrogen", + "nirvanna", "nirvana", + "nitorgen", "nitrogen", + "niusance", "nuisance", + "noctrune", "nocturne", + "noctunre", "nocturne", + "nocturen", "nocturne", + "nominato", "nomination", + "nonsence", "nonsense", + "nonsesne", "nonsense", + "noramlly", "normally", + "norhtern", "northern", + "normalis", "normals", + "normalls", "normals", + "normalos", "normals", + "northeat", "northeast", + "northren", "northern", + "northwet", "northwest", + "norwegin", "norwegian", + "nostalga", "nostalgia", + "nostirls", "nostrils", + "notabley", "notably", + "notablly", "notably", + "noteable", "notable", + "noteably", "notably", + "noticabe", "noticable", + "notorios", "notorious", + "novmeber", "november", + "nromandy", "normandy", + "nuatilus", "nautilus", + "nuculear", "nuclear", + "nuetered", "neutered", + "nuisanse", "nuisance", + "nullifiy", "nullify", + "nurtient", "nutrient", + "nusaince", "nuisance", + "nusiance", "nuisance", + "nutirent", "nutrient", + "nutriens", "nutrients", + "nuturing", "nurturing", + "obdisian", "obsidian", + "obediant", "obedient", + "obession", "obsession", + "obilvion", "oblivion", + "obisdian", "obsidian", + "obsessie", "obsessive", + "obsessin", "obsession", + "obsidain", "obsidian", + "obstacal", "obstacle", + "obvilion", "oblivion", + "ocasions", "occasions", + "ocassion", "occasion", + "occaison", "occasion", + "occupato", "occupation", + "occuring", "occurring", + "octobear", "october", + "octopuns", "octopus", + "ofcoruse", "ofcourse", + "ofcoures", "ofcourse", + "ofcousre", "ofcourse", + "ofcrouse", "ofcourse", + "officals", "officials", + "officaly", "officially", + "offsited", "offside", + "ofocurse", "ofcourse", + "oligarcy", "oligarchy", + "olmypics", "olympics", + "olymipcs", "olympics", + "olypmics", "olympics", + "ommision", "omission", + "ommiting", "omitting", + "ommitted", "omitted", + "ongewild", "gonewild", + "onslaugt", "onslaught", + "operatie", "operative", + "opinoins", "opinions", + "oppinion", "opinion", + "opponant", "opponent", + "opposits", "opposites", + "oppossed", "opposed", + "oppresso", "oppression", + "optimaal", "optimal", + "optomism", "optimism", + "oragnise", "organise", + "orangerd", "orangered", + "orangers", "oranges", + "orangism", "organism", + "orchesta", "orchestra", + "ordianry", "ordinary", + "oreintal", "oriental", + "orgainse", "organise", + "orgainze", "organize", + "organims", "organism", + "organsie", "organise", + "organsim", "organism", + "organzie", "organize", + "orgasmes", "orgasms", + "orgasmos", "orgasms", + "orgasmus", "orgasms", + "orginize", "organise", + "orhtodox", "orthodox", + "oridnary", "ordinary", + "originas", "origins", + "origines", "origins", + "originsl", "originals", + "orphanes", "orphans", + "osbidian", "obsidian", + "othrodox", "orthodox", + "ourselvs", "ourselves", + "oustider", "outsider", + "outfeild", "outfield", + "outfidel", "outfield", + "outfiled", "outfield", + "outisder", "outsider", + "outplayd", "outplayed", + "outputed", "outputted", + "outsoure", "outsourced", + "overboad", "overboard", + "overclok", "overclock", + "overdrev", "overdrive", + "overhual", "overhaul", + "overlaod", "overload", + "overpiad", "overpaid", + "overules", "overuse", + "overwath", "overwatch", + "overwhem", "overwhelm", + "oximoron", "oxymoron", + "oylmpics", "olympics", + "pacakged", "packaged", + "packadge", "packaged", + "paficist", "pacifist", + "painfuly", "painfully", + "paitence", "patience", + "paitents", "patients", + "palidans", "paladins", + "palstics", "plastics", + "paltform", "platform", + "paltinum", "platinum", + "palyable", "playable", + "palyoffs", "playoffs", + "pancaeks", "pancakes", + "panckaes", "pancakes", + "pandoria", "pandora", + "pandorra", "pandora", + "panedmic", "pandemic", + "panethon", "pantheon", + "pankaces", "pancakes", + "panmedic", "pandemic", + "pantehon", "pantheon", + "panthoen", "pantheon", + "paradies", "paradise", + "paradyse", "parades", + "paragrah", "paragraph", + "paraiste", "parasite", + "paralell", "parallel", + "paralely", "parallelly", + "paralles", "parallels", + "parameds", "paramedics", + "paramter", "parameter", + "paranioa", "paranoia", + "paraniod", "paranoid", + "paraside", "paradise", + "parasits", "parasites", + "parastie", "parasite", + "parctise", "practise", + "paremsan", "parmesan", + "paristan", "partisan", + "parmasen", "parmesan", + "parmenas", "parmesan", + "parmsean", "parmesan", + "parnters", "partners", + "parralel", "parallel", + "parterns", "partners", + "partialy", "partially", + "partians", "partisan", + "partical", "particular", + "particel", "particle", + "partiets", "parties", + "partiots", "patriots", + "partnerd", "partnered", + "partsian", "partisan", + "passabel", "passable", + "passione", "passionate", + "passisve", "passives", + "passpost", "passports", + "passvies", "passives", + "passwors", "passwords", + "pasttime", "pastime", + "pastural", "pastoral", + "pateince", "patience", + "pateints", "patients", + "patethic", "pathetic", + "patheitc", "pathetic", + "patienty", "patiently", + "patirots", "patriots", + "patriarh", "patriarchy", + "patroits", "patriots", + "patrolls", "patrols", + "patronas", "patrons", + "patrones", "patrons", + "patronis", "patrons", + "patronos", "patrons", + "pattened", "patented", + "patterno", "patterson", + "pattersn", "patterson", + "pblisher", "publisher", + "peageant", "pageant", + "pebbleos", "pebbles", + "pebblers", "pebbles", + "pebblets", "pebbles", + "peciluar", "peculiar", + "pecuilar", "peculiar", + "peculair", "peculiar", + "peculure", "peculiar", + "peformed", "performed", + "peircing", "piercing", + "penaltis", "penalties", + "penatgon", "pentagon", + "penciles", "pencils", + "pendatic", "pedantic", + "pengiuns", "penguins", + "penisula", "peninsula", + "pensioen", "pension", + "pepperin", "pepperoni", + "perceded", "preceded", + "percente", "percentile", + "percieve", "perceive", + "percious", "precious", + "perclude", "preclude", + "perfecty", "perfectly", + "perfroms", "performs", + "perheaps", "perhaps", + "pericing", "piercing", + "peridoic", "periodic", + "perimetr", "perimeter", + "periodes", "periods", + "periodos", "periods", + "permanet", "permanent", + "permiere", "premiere", + "permises", "premises", + "permitas", "permits", + "permites", "permits", + "permitis", "permits", + "permitts", "permits", + "permiums", "premiums", + "peroidic", "periodic", + "perosnas", "personas", + "perpetue", "perpetuate", + "persaude", "persuade", + "perserve", "preserve", + "persisit", "persist", + "personel", "personnel", + "persones", "persons", + "personis", "persons", + "personsa", "personas", + "perstige", "prestige", + "persuaso", "persuasion", + "persuded", "persuaded", + "persuing", "pursuing", + "persuits", "pursuits", + "persumed", "presumed", + "pertaing", "pertaining", + "pertians", "pertains", + "pertinet", "pertinent", + "pervents", "prevents", + "perverst", "pervert", + "perviews", "previews", + "pervious", "previous", + "perxoide", "peroxide", + "pessiary", "pessary", + "petetion", "petition", + "petrolem", "petroleum", + "phantoom", "phantom", + "pharamcy", "pharmacy", + "pharmacs", "pharmacist", + "pharmsci", "pharmacist", + "phenomon", "phenomenon", + "phramacy", "pharmacy", + "phsyical", "physical", + "phsyique", "physique", + "phyiscal", "physical", + "phyisque", "physique", + "physcial", "physical", + "physicis", "physicians", + "physicks", "physics", + "physicts", "physicist", + "physqiue", "physique", + "picthers", "pitchers", + "pillards", "pillars", + "pillaris", "pillars", + "pinancle", "pinnacle", + "pinapple", "pineapple", + "pinnalce", "pinnacle", + "pinnaple", "pineapple", + "pinncale", "pinnacle", + "pinpiont", "pinpoint", + "pinteret", "pinterest", + "piolting", "piloting", + "pioneeer", "pioneer", + "pithcers", "pitchers", + "placebro", "placebo", + "placemet", "placements", + "planetas", "planets", + "planetos", "planets", + "plantiff", "plaintiff", + "plantium", "platinum", + "plasitcs", "plastics", + "platfrom", "platform", + "platimun", "platinum", + "platnium", "platinum", + "platnuim", "platinum", + "plausibe", "plausible", + "playbody", "playboy", + "playstye", "playstyle", + "pleasent", "pleasant", + "plehtora", "plethora", + "pleothra", "plethora", + "plethroa", "plethora", + "ploygamy", "polygamy", + "pnatheon", "pantheon", + "poeoples", "peoples", + "poingant", "poignant", + "pointeur", "pointer", + "pointure", "pointer", + "poisones", "poisons", + "poisonis", "poisons", + "poisonos", "poisons", + "poisonus", "poisons", + "polgyamy", "polygamy", + "polietly", "politely", + "politing", "piloting", + "politley", "politely", + "poltical", "political", + "poluting", "polluting", + "polution", "pollution", + "polygoon", "polygon", + "polymore", "polymer", + "pomotion", "promotion", + "popoulus", "populous", + "populair", "popular", + "populare", "popular", + "populary", "popularity", + "porcelan", "porcelain", + "porposes", "proposes", + "portabel", "portable", + "portalis", "portals", + "portalus", "portals", + "portayed", "portrayed", + "portgual", "portugal", + "portrais", "portraits", + "portrary", "portray", + "portrayl", "portrayal", + "portriat", "portrait", + "posessed", "possessed", + "posesses", "possesses", + "posioned", "poisoned", + "positivs", "positives", + "positivy", "positivity", + "possable", "possible", + "possably", "possibly", + "possbily", "possibly", + "posseses", "possesses", + "possesse", "possessive", + "possesss", "possesses", + "potrayed", "portrayed", + "poverful", "powerful", + "powerded", "powdered", + "powerpot", "powerpoint", + "pracitse", "practise", + "practial", "practical", + "practies", "practise", + "pratcise", "practise", + "praticle", "particle", + "prceeded", "preceded", + "preadtor", "predator", + "preample", "preamble", + "preceeds", "precedes", + "precisie", "precise", + "precisly", "precisely", + "precisou", "precious", + "preculde", "preclude", + "predicat", "predict", + "predicte", "predictive", + "preferas", "prefers", + "prefered", "preferred", + "preferes", "prefers", + "preferis", "prefers", + "preferrs", "prefers", + "preimere", "premiere", + "preimums", "premiums", + "preiodic", "periodic", + "preivews", "previews", + "prejudis", "prejudices", + "prelayed", "replayed", + "premeire", "premiere", + "premesis", "premises", + "premiare", "premier", + "premines", "premise", + "premuims", "premiums", + "preorded", "preordered", + "preordes", "preorders", + "preoxide", "peroxide", + "prepaird", "prepaid", + "preqeuls", "prequels", + "prequles", "prequels", + "prescrie", "prescribed", + "presense", "presence", + "presenst", "presets", + "presidet", "presidents", + "presists", "persists", + "presitge", "prestige", + "presonas", "personas", + "presuade", "persuade", + "pretador", "predator", + "pretains", "pertains", + "preveiws", "previews", + "preverse", "perverse", + "previwes", "previews", + "pricipal", "principal", + "priciple", "principle", + "priemere", "premiere", + "priestes", "priests", + "primaris", "primaries", + "primarly", "primarily", + "princila", "principals", + "principl", "principals", + "prisitne", "pristine", + "probelms", "problems", + "probleem", "problem", + "procalim", "proclaim", + "proccess", "process", + "proceded", "proceeded", + "proceder", "procedure", + "procedes", "proceeds", + "procedue", "procedure", + "proceeed", "proceed", + "procesed", "proceeds", + "processs", "processes", + "proclami", "proclaim", + "procliam", "proclaim", + "procotol", "protocol", + "prodcuts", "products", + "producto", "production", + "profesor", "professor", + "proficit", "proficient", + "profilic", "prolific", + "progroms", "pogroms", + "prohibis", "prohibits", + "prohpecy", "prophecy", + "prohpets", "prophets", + "projecte", "projectile", + "projecto", "projection", + "prolouge", "prologue", + "promplty", "promptly", + "promptes", "prompts", + "promptus", "prompts", + "promtply", "promptly", + "pronoune", "pronounced", + "propechy", "prophecy", + "propehcy", "prophecy", + "propehts", "prophets", + "prophacy", "prophecy", + "propmted", "prompted", + "propmtly", "promptly", + "proponet", "proponents", + "proposse", "proposes", + "proposte", "propose", + "proprety", "property", + "propsect", "prospect", + "prosepct", "prospect", + "prostite", "prostitute", + "protable", "portable", + "protecte", "protective", + "protiens", "proteins", + "protines", "proteins", + "protocal", "protocol", + "prototye", "prototype", + "protrait", "portrait", + "protrays", "portrays", + "protugal", "portugal", + "proverai", "proverbial", + "providee", "providence", + "proximty", "proximity", + "pruchase", "purchase", + "pryamids", "pyramids", + "ptichers", "pitchers", + "pubisher", "publisher", + "publiser", "publisher", + "puinsher", "punisher", + "pulisher", "publisher", + "pumkpins", "pumpkins", + "pumpinks", "pumpkins", + "pumpknis", "pumpkins", + "punshier", "punisher", + "punsiher", "punisher", + "punsihes", "punishes", + "purcahse", "purchase", + "pyramind", "pyramid", + "pyrimads", "pyramids", + "pyrmaids", "pyramids", + "qauntity", "quantity", + "qualifiy", "qualify", + "quanitfy", "quantify", + "quantaty", "quantity", + "quantite", "quantities", + "quantuum", "quantum", + "quarante", "quarantine", + "quartery", "quarterly", + "qucikest", "quickest", + "queation", "equation", + "quention", "quentin", + "quickets", "quickest", + "quicklyu", "quickly", + "rabbitos", "rabbits", + "rabbitts", "rabbits", + "racistas", "racists", + "racistes", "racists", + "radaince", "radiance", + "rahpsody", "rhapsody", + "raidance", "radiance", + "railraod", "railroad", + "randomes", "randoms", + "randomez", "randomized", + "randomns", "randoms", + "randomrs", "randoms", + "randomus", "randoms", + "raosting", "roasting", + "raphsody", "rhapsody", + "raptores", "raptors", + "raspbery", "raspberry", + "rationel", "rationale", + "realible", "reliable", + "realibly", "reliably", + "realiest", "earliest", + "realisim", "realism", + "realisme", "realise", + "realistc", "realistic", + "realiste", "realise", + "realoded", "reloaded", + "realsied", "realised", + "realtion", "relation", + "realtive", "relative", + "reamined", "remained", + "reapired", "repaired", + "reaplugs", "earplugs", + "reaserch", "research", + "reasonal", "reasonably", + "reatiler", "retailer", + "reaveled", "revealed", + "rebellis", "rebellious", + "reboudns", "rebounds", + "rebounce", "rebound", + "rebuildt", "rebuilt", + "rebuplic", "republic", + "receeded", "receded", + "recepits", "receipts", + "receptie", "receptive", + "receptos", "receptors", + "receving", "receiving", + "recident", "resident", + "reciding", "residing", + "recieved", "received", + "reciever", "receiver", + "recieves", "receives", + "recipees", "recipes", + "recipets", "recipes", + "recogise", "recognise", + "recogize", "recognize", + "recognie", "recognizes", + "recomend", "recommend", + "recommed", "recommend", + "reconnet", "reconnect", + "rectange", "rectangle", + "rectifiy", "rectify", + "recuring", "recurring", + "recurits", "recruits", + "redeisgn", "redesign", + "redemeed", "redeemed", + "redesgin", "redesign", + "redesing", "redesign", + "reedemed", "redeemed", + "refeeres", "referees", + "refelcts", "reflects", + "refelxes", "reflexes", + "referede", "referee", + "referene", "referee", + "referens", "references", + "referere", "referee", + "referign", "refering", + "refering", "referring", + "refernce", "references", + "reffered", "referred", + "refilles", "refills", + "refillls", "refills", + "reflecte", "reflective", + "reflecto", "reflection", + "reformes", "reforms", + "refreing", "refering", + "refrence", "reference", + "refreshd", "refreshed", + "refreshr", "refresher", + "refromed", "reformed", + "regardes", "regards", + "regenade", "renegade", + "regenere", "regenerate", + "regiones", "regions", + "regisrty", "registry", + "registed", "registered", + "regresas", "regress", + "regreses", "regress", + "regresos", "regress", + "regresse", "regressive", + "regresso", "regression", + "regrests", "regress", + "regretts", "regrets", + "regsitry", "registry", + "regualrs", "regulars", + "regualte", "regulate", + "reguarly", "regularly", + "regulary", "regularly", + "regulatr", "regulator", + "regulats", "regulators", + "rehersal", "rehearsal", + "rehtoric", "rhetoric", + "reiceved", "recieved", + "reigment", "regiment", + "reigonal", "regional", + "rekenton", "renekton", + "relaible", "reliable", + "relaibly", "reliably", + "relaised", "realised", + "relaoded", "reloaded", + "relasped", "relapsed", + "relatabe", "relatable", + "relateds", "relates", + "relativy", "relativity", + "relavent", "relevant", + "relected", "reelected", + "relegato", "relegation", + "releived", "relieved", + "releiver", "reliever", + "relevent", "relevant", + "relfects", "reflects", + "relfexes", "reflexes", + "reliased", "realised", + "religous", "religious", + "relpased", "relapsed", + "remainds", "remains", + "remainig", "remaining", + "remannts", "remnants", + "remarkes", "remarks", + "remembed", "remembered", + "remembee", "remembered", + "rememebr", "remember", + "remenant", "remnant", + "reminent", "remnant", + "remmeber", "remember", + "remotley", "remotely", + "renderes", "renders", + "reneagde", "renegade", + "renetkon", "renekton", + "renewabe", "renewables", + "renketon", "renekton", + "renmants", "remnants", + "renoylds", "reynolds", + "renteris", "renters", + "renyolds", "reynolds", + "reowrked", "reworked", + "repaires", "repairs", + "repalces", "replaces", + "reparied", "repaired", + "repblics", "republics", + "repbulic", "republic", + "repeatae", "repeatable", + "repeates", "repeats", + "repetion", "repetition", + "repharse", "rephrase", + "repitles", "reptiles", + "replased", "relapsed", + "replayes", "replays", + "replicae", "replicated", + "replubic", "republic", + "reportes", "reporters", + "reposity", "repository", + "repostas", "reposts", + "repostes", "reposts", + "repostig", "reposting", + "repostus", "reposts", + "represet", "represents", + "represso", "repression", + "reprhase", "rephrase", + "repsects", "respects", + "repsonds", "responds", + "repsonse", "response", + "repsoted", "reposted", + "repubics", "republics", + "republis", "republics", + "repulics", "republics", + "repulsie", "repulsive", + "requiers", "requires", + "requieum", "requiem", + "requilme", "requiem", + "requried", "required", + "requries", "requires", + "rescuecd", "rescued", + "researce", "researcher", + "resembes", "resembles", + "reserach", "research", + "resevoir", "reservoir", + "resgined", "resigned", + "residude", "residue", + "residule", "residue", + "resinged", "resigned", + "resistas", "resists", + "resisten", "resistance", + "resistes", "resists", + "resloved", "resolved", + "resloves", "resolves", + "resmeble", "resemble", + "resotred", "restored", + "resourse", "resources", + "resovled", "resolved", + "resovles", "resolves", + "respecte", "respective", + "respesct", "respects", + "responce", "response", + "responed", "respond", + "respones", "response", + "responsd", "responds", + "respoted", "reposted", + "restanti", "restarting", + "restrait", "restraint", + "restrics", "restricts", + "resuable", "reusable", + "retailes", "retailers", + "retalier", "retailer", + "rethoric", "rhetoric", + "retirase", "retires", + "retireds", "retires", + "retireus", "retires", + "retireve", "retrieve", + "retreive", "retrieve", + "retrived", "retrieved", + "retunred", "returned", + "reuasble", "reusable", + "reveales", "reveals", + "reveiwed", "reviewed", + "reveiwer", "reviewer", + "revelaed", "revealed", + "revelant", "relevant", + "revelead", "revealed", + "reverals", "reversal", + "reviewes", "reviewers", + "revlover", "revolver", + "revloves", "revolves", + "revovler", "revolver", + "revovles", "revolves", + "rewatchd", "rewatched", + "rewitten", "rewritten", + "rewritte", "rewrite", + "rewtched", "wretched", + "reynlods", "reynolds", + "reyonlds", "reynolds", + "rhaposdy", "rhapsody", + "rhaspody", "rhapsody", + "rheotric", "rhetoric", + "righteos", "righteous", + "rigntone", "ringtone", + "ringotne", "ringtone", + "ritalian", "ritalin", + "rivalrly", "rivalry", + "roachers", "roaches", + "robberts", "robbers", + "robberys", "robbers", + "robocoop", "robocop", + "robocorp", "robocop", + "robocoup", "robocop", + "roelplay", "roleplay", + "roganism", "organism", + "rolepaly", "roleplay", + "romaanin", "romanian", + "romainan", "romanian", + "romanain", "romanian", + "romanica", "romania", + "rosettta", "rosetta", + "rostaing", "roasting", + "routeros", "routers", + "rutgerus", "rutgers", + "ryenolds", "reynolds", + "sacrifie", "sacrifice", + "saddends", "saddens", + "saddenes", "saddens", + "sadisitc", "sadistic", + "salaires", "salaries", + "sandales", "sandals", + "sandalls", "sandals", + "sandstom", "sandstorm", + "sanotrum", "santorum", + "santourm", "santorum", + "santroum", "santorum", + "santurom", "santorum", + "sapcebar", "spacebar", + "sapphrie", "sapphire", + "sarcasam", "sarcasm", + "sarcasim", "sarcasm", + "sarcastc", "sarcastic", + "sargeant", "sergeant", + "sasauges", "sausages", + "sasuages", "sausages", + "satelite", "satellite", + "satellie", "satellites", + "saterday", "saturday", + "satifies", "satisfies", + "satisfiy", "satisfy", + "satrical", "satirical", + "satruday", "saturday", + "saturdsy", "saturdays", + "sawstika", "swastika", + "scandlas", "scandals", + "scannign", "scanning", + "scarmble", "scramble", + "scepture", "scepter", + "schedual", "schedule", + "schoalrs", "scholars", + "scholary", "scholarly", + "schoodle", "schooled", + "scientic", "scientific", + "scientis", "scientist", + "scoprion", "scorpion", + "scorates", "socrates", + "scoripon", "scorpion", + "scorpoin", "scorpion", + "scostman", "scotsman", + "scratchs", "scratches", + "scriptue", "scriptures", + "scriptus", "scripts", + "scritped", "scripted", + "scroates", "socrates", + "scropion", "scorpion", + "scrpited", "scripted", + "scruitny", "scrutiny", + "scrunity", "scrutiny", + "sctosman", "scotsman", + "sculpter", "sculpture", + "scurtiny", "scrutiny", + "seahakws", "seahawks", + "seahwaks", "seahawks", + "seantors", "senators", + "sebastin", "sebastian", + "seceeded", "succeeded", + "secertly", "secretly", + "secrelty", "secretly", + "secretas", "secrets", + "secretos", "secrets", + "secruity", "security", + "secuirty", "security", + "sedereal", "sidereal", + "seldomly", "seldom", + "selectie", "selective", + "selfiers", "selfies", + "semestre", "semester", + "semseter", "semester", + "senarios", "scenarios", + "senerity", "serenity", + "seniores", "seniors", + "senisble", "sensible", + "sensibel", "sensible", + "sensores", "sensors", + "senstive", "sensitive", + "sentaors", "senators", + "sentiers", "sentries", + "sentinet", "sentient", + "sentinte", "sentient", + "sentires", "sentries", + "sentreis", "sentries", + "separato", "separation", + "separete", "seperate", + "sepearte", "seperate", + "seperate", "separate", + "seplling", "spelling", + "sepreate", "seperate", + "sepulcre", "sepulchre", + "serached", "searched", + "seraches", "searches", + "serentiy", "serenity", + "sergaent", "sergeant", + "settigns", "settings", + "settting", "setting", + "seventen", "seventeen", + "severeal", "several", + "severeid", "severed", + "severide", "severed", + "severley", "severely", + "sexaully", "sexually", + "seziures", "seizures", + "sezuires", "seizures", + "shadoloo", "shadaloo", + "shangahi", "shanghai", + "shanghia", "shanghai", + "sharplay", "sharply", + "sharpley", "sharply", + "shawshak", "shawshank", + "shcolars", "scholars", + "shcooled", "schooled", + "sheilded", "shielded", + "shelterd", "sheltered", + "shelvers", "shelves", + "shelveys", "shelves", + "sherlcok", "sherlock", + "shetlers", "shelters", + "shfiting", "shifting", + "shifitng", "shifting", + "shifteer", "shifter", + "shileded", "shielded", + "shineing", "shining", + "shitstom", "shitstorm", + "shittoon", "shitton", + "shittown", "shitton", + "shleters", "shelters", + "shnaghai", "shanghai", + "shortend", "shortened", + "shotuout", "shoutout", + "shoudlnt", "shouldnt", + "shouldes", "shoulders", + "shoulndt", "shouldnt", + "shrapenl", "shrapnel", + "shrelock", "sherlock", + "shrinked", "shrunk", + "shrpanel", "shrapnel", + "shtiless", "shitless", + "shuoldnt", "shouldnt", + "sideboad", "sideboard", + "sidleine", "sideline", + "siezable", "sizeable", + "siezures", "seizures", + "signatue", "signatures", + "signfies", "signifies", + "signifiy", "signify", + "signigns", "signings", + "signular", "singular", + "silbings", "siblings", + "silicoln", "silicon", + "silicoon", "silicon", + "silimiar", "similiar", + "simialir", "similiar", + "simiilar", "similiar", + "similair", "similar", + "similari", "similiar", + "similart", "similarity", + "similary", "similarly", + "similiar", "similar", + "simliiar", "similiar", + "simluate", "simulate", + "simmilar", "similar", + "simpelst", "simplest", + "simplets", "simplest", + "simplicy", "simplicity", + "simplier", "simpler", + "simulato", "simulation", + "singlers", "singles", + "singluar", "singular", + "sinistre", "sinister", + "sinsiter", "sinister", + "sitckers", "stickers", + "sitrring", "stirring", + "sizebale", "sizeable", + "skateing", "skating", + "skecthes", "sketches", + "skelatel", "skeletal", + "skeletos", "skeletons", + "sketchey", "sketchy", + "sketpics", "skeptics", + "skillsto", "skillshots", + "skimrish", "skirmish", + "skpetics", "skeptics", + "skrimish", "skirmish", + "skteches", "sketches", + "skywalkr", "skywalker", + "slaptoon", "splatoon", + "slaverly", "slavery", + "slienced", "silenced", + "sliently", "silently", + "slighlty", "slightly", + "sligthly", "slightly", + "smartare", "smarter", + "snetries", "sentries", + "snippent", "snippet", + "snippert", "snippet", + "snowbals", "snowballs", + "snugglie", "snuggle", + "snydrome", "syndrome", + "snyopsis", "synopsis", + "soberity", "sobriety", + "sobreity", "sobriety", + "socailly", "socially", + "socalism", "socialism", + "socartes", "socrates", + "socialim", "socialism", + "socities", "societies", + "socttish", "scottish", + "soemthin", "somethin", + "soilders", "soldiers", + "solatary", "solitary", + "soldeirs", "soldiers", + "soliders", "soldiers", + "soluable", "soluble", + "solutide", "solitude", + "somalija", "somalia", + "somehtin", "somethin", + "someoens", "someones", + "somethis", "somethings", + "sometihn", "somethin", + "sometinh", "somethin", + "somoenes", "someones", + "somtimes", "sometimes", + "somwhere", "somewhere", + "soparnos", "sopranos", + "sophmore", "sophomore", + "sorcercy", "sorcery", + "sorcerey", "sorcery", + "sorceror", "sorcerer", + "sorcerry", "sorcery", + "sorpanos", "sopranos", + "southren", "southern", + "soverein", "sovereign", + "soverign", "sovereign", + "sovietes", "soviets", + "spagheti", "spaghetti", + "spainish", "spanish", + "spaltoon", "splatoon", + "spammade", "spammed", + "spammare", "spammer", + "spammear", "spammer", + "spammend", "spammed", + "spammeur", "spammer", + "spanisch", "spanish", + "sparklie", "sparkle", + "spawnign", "spawning", + "specemin", "specimen", + "speciaal", "special", + "specialt", "specialist", + "specialy", "specially", + "specialz", "specialize", + "specifed", "specified", + "specifiy", "specify", + "speciman", "specimen", + "specrtal", "spectral", + "speicals", "specials", + "spellign", "spelling", + "spendour", "splendour", + "sphereos", "spheres", + "spilnter", "splinter", + "spiltter", "splitter", + "spindrel", "spindle", + "spirites", "spirits", + "spiritis", "spirits", + "spiritus", "spirits", + "spirtied", "spirited", + "spleling", "spelling", + "splitner", "splinter", + "spoilerd", "spoiled", + "spoliers", "spoilers", + "sponsord", "sponsored", + "sporanos", "sopranos", + "spotifiy", "spotify", + "spotifty", "spotify", + "sppeches", "speeches", + "sprayade", "sprayed", + "spreaded", "spread", + "springst", "sprints", + "sprinkel", "sprinkle", + "sprintas", "sprints", + "spritual", "spiritual", + "sproutes", "sprouts", + "spwaning", "spawning", + "sqaudron", "squadron", + "sqaurely", "squarely", + "sqiurtle", "squirtle", + "squardon", "squadron", + "squareds", "squares", + "squarley", "squarely", + "squeakey", "squeaky", + "squeakly", "squeaky", + "squirlte", "squirtle", + "squirrle", "squirrel", + "squirtel", "squirtle", + "squishey", "squishy", + "squishly", "squishy", + "squritle", "squirtle", + "squrriel", "squirrel", + "squrtile", "squirtle", + "sriarcha", "sriracha", + "srriacha", "sriracha", + "sryacuse", "syracuse", + "staduims", "stadiums", + "staidums", "stadiums", + "staklers", "stalkers", + "stalekrs", "stalkers", + "stalkear", "stalker", + "staminia", "stamina", + "stampade", "stamped", + "stampeed", "stamped", + "stancels", "stances", + "stancers", "stances", + "standars", "standards", + "standbay", "standby", + "standbuy", "standby", + "stangant", "stagnant", + "staright", "straight", + "starined", "strained", + "starlted", "startled", + "startegy", "strategy", + "starteld", "startled", + "startsup", "startups", + "stateman", "statesman", + "staticts", "statist", + "stationd", "stationed", + "stationy", "stationary", + "statiskt", "statist", + "statistc", "statistic", + "statment", "statement", + "stattues", "statutes", + "statuets", "statutes", + "statuser", "stature", + "staurday", "saturday", + "steadliy", "steadily", + "stealhty", "stealthy", + "steathly", "stealthy", + "stelathy", "stealthy", + "sterilze", "sterile", + "steriods", "steroids", + "stichted", "stitched", + "sticthed", "stitched", + "sticthes", "stitches", + "stimulai", "stimuli", + "stimulas", "stimulants", + "stimulat", "stimulants", + "stimulli", "stimuli", + "stingent", "stringent", + "stirkers", "strikers", + "stlakers", "stalkers", + "stomache", "stomach", + "stormade", "stormed", + "stormend", "stormed", + "stradegy", "strategy", + "stragety", "strategy", + "straignt", "straighten", + "straigth", "straight", + "straings", "strains", + "strangel", "strangle", + "stranget", "strangest", + "stratgey", "strategy", + "stratled", "startled", + "streames", "streams", + "streamos", "streams", + "streamus", "streams", + "streamys", "streams", + "stregnth", "strength", + "stremear", "streamer", + "strenght", "strength", + "strengts", "strengths", + "strenous", "strenuous", + "strentgh", "strength", + "stretchs", "stretches", + "striaght", "straight", + "striclty", "strictly", + "striekrs", "strikers", + "strikely", "strikingly", + "stringet", "stringent", + "stubbron", "stubborn", + "stubmled", "stumbled", + "stucture", "structure", + "studioes", "studios", + "stuipder", "stupider", + "stumbeld", "stumbled", + "stupdily", "stupidly", + "stupidiy", "stupidity", + "stylisch", "stylish", + "styrofom", "styrofoam", + "suasages", "sausages", + "subltety", "subtlety", + "submarie", "submarines", + "subruban", "suburban", + "subscrie", "subscriber", + "subsidie", "subsidized", + "subsidiy", "subsidy", + "substace", "substance", + "substans", "substances", + "substite", "substitute", + "subtelty", "subtlety", + "subtetly", "subtlety", + "subtilte", "subtitle", + "subtitel", "subtitle", + "subtitls", "subtitles", + "subtltey", "subtlety", + "succeded", "succeeded", + "succedes", "succeeds", + "succeeed", "succeed", + "succesed", "succeeds", + "successs", "successes", + "succsess", "success", + "suceeded", "succeeded", + "sucesful", "successful", + "sucesion", "succession", + "sucesses", "successes", + "sucessor", "successor", + "sucessot", "successor", + "sucidial", "suicidal", + "suddnely", "suddenly", + "sufficit", "sufficient", + "suggesst", "suggests", + "suggeste", "suggestive", + "summenor", "summoner", + "summones", "summoners", + "sunfiber", "sunfire", + "sunscren", "sunscreen", + "superham", "superhuman", + "superheo", "superhero", + "superios", "superiors", + "supirsed", "suprised", + "suposing", "supposing", + "supporre", "supporters", + "suppoted", "supported", + "suprised", "surprised", + "suprized", "surprised", + "suprsied", "suprised", + "supsects", "suspects", + "supsense", "suspense", + "surbuban", "suburban", + "surounds", "surrounds", + "surpases", "surpass", + "surpress", "suppress", + "surprize", "surprise", + "surrouns", "surrounds", + "surveill", "surveil", + "surveyer", "surveyor", + "surviver", "survivor", + "suspened", "suspend", + "suspenso", "suspension", + "swaering", "swearing", + "swansoon", "swanson", + "swasitka", "swastika", + "swaskita", "swastika", + "swatiska", "swastika", + "swatsika", "swastika", + "swedisch", "swedish", + "swiftley", "swiftly", + "swithced", "switched", + "swithces", "switches", + "swtiched", "switched", + "swtiches", "switches", + "syarcuse", "syracuse", + "sydnrome", "syndrome", + "sylablle", "syllable", + "syllabel", "syllable", + "symapthy", "sympathy", + "symboles", "symbols", + "symhpony", "symphony", + "symmerty", "symmetry", + "symmtery", "symmetry", + "symoblic", "symbolic", + "symphaty", "sympathy", + "symptoom", "symptom", + "symtpoms", "symptoms", + "synomyns", "synonyms", + "synonmys", "synonyms", + "synonomy", "synonym", + "synoynms", "synonyms", + "synphony", "symphony", + "synposis", "synopsis", + "sypmathy", "sympathy", + "sypmtoms", "symptoms", + "sypnosis", "synopsis", + "syraucse", "syracuse", + "syrcause", "syracuse", + "syringae", "syringe", + "syringue", "syringe", + "sysamdin", "sysadmin", + "sysdamin", "sysadmin", + "tacticas", "tactics", + "tacticts", "tactics", + "tacticus", "tactics", + "tagliate", "tailgate", + "tahnkyou", "thankyou", + "tailsman", "talisman", + "taiwanee", "taiwanese", + "taligate", "tailgate", + "taliored", "tailored", + "tallents", "tallest", + "talsiman", "talisman", + "tanturms", "tantrums", + "tapitude", "aptitude", + "tasliman", "talisman", + "tattooes", "tattoos", + "tattooos", "tattoos", + "taxanomy", "taxonomy", + "teamfigt", "teamfight", + "teamspek", "teamspeak", + "teancity", "tenacity", + "teapsoon", "teaspoon", + "techniqe", "technique", + "teenages", "teenagers", + "telegrah", "telegraph", + "telphony", "telephony", + "tempalrs", "templars", + "tempalte", "template", + "templats", "templates", + "templeos", "temples", + "templers", "temples", + "temporay", "temporary", + "temprary", "temporary", + "tenacles", "tentacles", + "tenactiy", "tenacity", + "tencaity", "tenacity", + "tendancy", "tendency", + "tendence", "tendencies", + "tentacel", "tentacle", + "tentacls", "tentacles", + "tentalce", "tentacle", + "tequilia", "tequila", + "terriory", "territory", + "territoy", "territory", + "terroist", "terrorist", + "tesitcle", "testicle", + "testicel", "testicle", + "testifiy", "testify", + "teusdays", "tuesdays", + "texutres", "textures", + "thaliand", "thailand", + "theather", "theater", + "theathre", "theater", + "theature", "theater", + "theisitc", "theistic", + "themslef", "themself", + "theorits", "theorist", + "theraphy", "therapy", + "thereian", "therein", + "theroies", "theories", + "theroist", "theorist", + "thesitic", "theistic", + "thialand", "thailand", + "thiestic", "theistic", + "thikning", "thinking", + "thirites", "thirties", + "thirstay", "thirsty", + "thnakyou", "thankyou", + "thoeries", "theories", + "thoerist", "theorist", + "thomspon", "thompson", + "thopmson", "thompson", + "thougths", "thoughts", + "thourogh", "thorough", + "threates", "threatens", + "threefor", "therefor", + "thriteen", "thirteen", + "thrities", "thirties", + "throaths", "throats", + "throners", "thrones", + "throough", "thorough", + "throught", "thought", + "thrusday", "thursday", + "thumbnal", "thumbnails", + "thurdsay", "thursday", + "thursdsy", "thursdays", + "tightare", "tighter", + "timestap", "timestamp", + "tirangle", "triangle", + "tirbunal", "tribunal", + "titainum", "titanium", + "titanuim", "titanium", + "tocuhpad", "touchpad", + "togehter", "together", + "togheter", "together", + "toiletts", "toilets", + "tolerabe", "tolerable", + "tommorow", "tomorrow", + "tonguers", "tongues", + "toriodal", "toroidal", + "toritlla", "tortilla", + "tornadoe", "tornado", + "torotise", "tortoise", + "torpedeo", "torpedo", + "torphies", "trophies", + "tortiose", "tortoise", + "toruisty", "touristy", + "toruneys", "tourneys", + "touchapd", "touchpad", + "tounreys", "tourneys", + "tourisim", "tourism", + "touritsy", "touristy", + "tournyes", "tourneys", + "toursits", "tourists", + "toursity", "touristy", + "toxiticy", "toxicity", + "trabajao", "trabajo", + "trabajdo", "trabajo", + "trackres", "trackers", + "trageted", "targeted", + "traingle", "triangle", + "traitour", "traitor", + "trakcers", "trackers", + "traliers", "trailers", + "tranform", "transform", + "transeat", "translates", + "transfom", "transform", + "transfos", "transforms", + "transiet", "transient", + "transito", "transition", + "transpot", "transport", + "trasnfer", "transfer", + "tratiors", "traitors", + "traveles", "travels", + "traveres", "traverse", + "treasurs", "treasures", + "treatmet", "treatments", + "treatsie", "treaties", + "treausre", "treasure", + "tredning", "trending", + "tremelos", "tremolos", + "tresuary", "treasury", + "trialers", "trailers", + "trianers", "trainers", + "triangel", "triangle", + "triangls", "triangles", + "trianing", "training", + "trianlge", "triangle", + "triators", "traitors", + "tribuanl", "tribunal", + "trickyer", "trickery", + "triggern", "triggering", + "trilogoy", "trilogy", + "trinagle", "triangle", + "trinekts", "trinkets", + "tringale", "triangle", + "trinitiy", "trinity", + "triology", "trilogy", + "triumpth", "triumph", + "trohpies", "trophies", + "trollade", "trolled", + "tropcial", "tropical", + "trotilla", "tortilla", + "trpoical", "tropical", + "trubinal", "tribunal", + "trubines", "turbines", + "tsunamai", "tsunami", + "tuesdsay", "tuesdays", + "tunnells", "tunnels", + "turkisch", "turkish", + "turntabe", "turntable", + "turretts", "turrets", + "tusedays", "tuesdays", + "tutorual", "tutorial", + "twilgiht", "twilight", + "tylenool", "tylenol", + "typicaly", "typically", + "tyranies", "tyrannies", + "tyrannia", "tyrannical", + "ublisher", "publisher", + "udnercut", "undercut", + "udnerdog", "underdog", + "ugpraded", "upgraded", + "ugprades", "upgrades", + "ukrainie", "ukraine", + "ukrainin", "ukrainian", + "ukranian", "ukrainian", + "ulitmate", "ultimate", + "ultamite", "ultimate", + "ultiamte", "ultimate", + "ultimely", "ultimately", + "ultrason", "ultrasound", + "umberlla", "umbrella", + "unabnned", "unbanned", + "unbanend", "unbanned", + "uncanney", "uncanny", + "uncannny", "uncanny", + "underbog", "undergo", + "underglo", "undergo", + "undersog", "undergo", + "undertoe", "undertones", + "underwar", "underwater", + "unfailry", "unfairly", + "unfarily", "unfairly", + "ungodley", "ungodly", + "unhapppy", "unhappy", + "unhealty", "unhealthy", + "unicrons", "unicorns", + "unifroms", "uniforms", + "uniquley", "uniquely", + "univeral", "universal", + "unlikley", "unlikely", + "unlockes", "unlocks", + "unluckly", "unlucky", + "unpoened", "unopened", + "unqiuely", "uniquely", + "unrakned", "unranked", + "unrnaked", "unranked", + "unrpoven", "unproven", + "unsuable", "unusable", + "untraind", "untrained", + "unusualy", "unusually", + "unvierse", "universe", + "unworhty", "unworthy", + "upgarded", "upgraded", + "upgardes", "upgrades", + "uploades", "uploads", + "upstaris", "upstairs", + "upstiars", "upstairs", + "urethrea", "urethra", + "uruguary", "uruguay", + "ususally", "usually", + "utilitiy", "utility", + "utlimate", "ultimate", + "vaccinae", "vaccinated", + "vaccinet", "vaccinated", + "vacinity", "vicinity", + "vaguelly", "vaguely", + "vaiation", "aviation", + "vaieties", "varieties", + "vailidty", "validity", + "vairable", "variable", + "vaklyrie", "valkyrie", + "valenica", "valencia", + "valentie", "valentines", + "valentis", "valentines", + "validade", "validated", + "valkirye", "valkyrie", + "valkiyre", "valkyrie", + "valkriye", "valkyrie", + "valkryie", "valkyrie", + "valkyire", "valkyrie", + "valnecia", "valencia", + "valubale", "valuable", + "valykrie", "valkyrie", + "vamipres", "vampires", + "vampiers", "vampires", + "vampries", "vampires", + "vangurad", "vanguard", + "vanillia", "vanilla", + "vanillla", "vanilla", + "vanugard", "vanguard", + "varaible", "variable", + "varaints", "variants", + "variabel", "variable", + "varibale", "variable", + "varities", "varieties", + "vassales", "vassals", + "vassalls", "vassals", + "vassalos", "vassals", + "vaticaan", "vatican", + "vaticina", "vatican", + "vaulable", "valuable", + "vaylkrie", "valkyrie", + "vechiles", "vehicles", + "vectores", "vectors", + "vegansim", "veganism", + "vegtable", "vegetable", + "vehciles", "vehicles", + "vehicels", "vehicles", + "vehicule", "vehicle", + "veichles", "vehicles", + "venelope", "envelope", + "venemous", "venomous", + "vengance", "vengeance", + "vengence", "vengeance", + "verablly", "verbally", + "verbaitm", "verbatim", + "verisons", "versions", + "versatel", "versatile", + "vertabim", "verbatim", + "vertigro", "vertigo", + "vesseles", "vessels", + "vessells", "vessels", + "viabiliy", "viability", + "viatmins", "vitamins", + "vibratie", "vibrate", + "vibratin", "vibration", + "vicintiy", "vicinity", + "vicseral", "visceral", + "victimas", "victims", + "victimes", "victims", + "victorin", "victorian", + "victoris", "victories", + "vieweres", "viewers", + "viewpoit", "viewpoints", + "vigilane", "vigilante", + "vigliant", "vigilant", + "vikingos", "vikings", + "viligant", "vigilant", + "villegas", "villages", + "vindicte", "vindictive", + "vinicity", "vicinity", + "violatin", "violation", + "violenty", "violently", + "violetas", "violates", + "virament", "vraiment", + "virbator", "vibrator", + "virginas", "virgins", + "virgines", "virgins", + "virgings", "virgins", + "virginis", "virgins", + "virginus", "virgins", + "virtualy", "virtually", + "virtuels", "virtues", + "virtuose", "virtues", + "viscreal", "visceral", + "visercal", "visceral", + "visibily", "visibility", + "visibley", "visibly", + "visiblly", "visibly", + "vitailty", "vitality", + "vitimans", "vitamins", + "vitmains", "vitamins", + "vitories", "victories", + "voicemal", "voicemail", + "voilates", "violates", + "volatily", "volatility", + "volcando", "volcano", + "volcanoe", "volcano", + "volcaron", "volcano", + "vriament", "vraiment", + "wahtever", "whatever", + "wallpapr", "wallpapers", + "warantee", "warranty", + "warcarft", "warcraft", + "warrante", "warranties", + "warriros", "warriors", + "watchemn", "watchmen", + "watchign", "watching", + "wathcing", "watching", + "wathcmen", "watchmen", + "wathever", "whatever", + "watkings", "watkins", + "wealthly", "wealthy", + "webistes", "websites", + "websties", "websites", + "wednesdy", "wednesdays", + "weigthed", "weighted", + "weridest", "weirdest", + "werstler", "wrestler", + "wesbites", "websites", + "westbrok", "westbrook", + "westerse", "westerners", + "wherease", "whereas", + "whipsers", "whispers", + "whislist", "wishlist", + "whisltes", "whistles", + "whisperd", "whispered", + "whistels", "whistles", + "whitsles", "whistles", + "whsipers", "whispers", + "widgetas", "widgets", + "wieghted", "weighted", + "willaims", "williams", + "willfuly", "willfully", + "willimas", "williams", + "windsoar", "windsor", + "wininpeg", "winnipeg", + "winnigns", "winnings", + "winnpieg", "winnipeg", + "wiredest", "weirdest", + "wishlsit", "wishlist", + "wishpers", "whispers", + "withdral", "withdrawal", + "witnesss", "witnesses", + "wonderes", "wonders", + "wonderus", "wonders", + "workfore", "workforce", + "wouldnot", "wouldnt", + "wranlger", "wrangler", + "wreckign", "wrecking", + "wrecthed", "wretched", + "wrekcing", "wrecking", + "wreslter", "wrestler", + "wresters", "wrestlers", + "writting", "writing", + "wrnagler", "wrangler", + "wrteched", "wretched", + "yeilding", "yielding", + "yoesmite", "yosemite", + "yorksher", "yorkshire", + "yorkshie", "yorkshire", + "yosemeti", "yosemite", + "yosimete", "yosemite", + "zealotes", "zealots", + "zealoths", "zealots", + "zealotus", "zealots", + "zealouts", "zealous", + "zepplein", "zeppelin", + "zepplien", "zeppelin", + "zimbabew", "zimbabwe", + "zimbawbe", "zimbabwe", + "zinoists", "zionists", + "zionisim", "zionism", + "zionistm", "zionism", + "zionsits", "zionists", + "zoinists", "zionists", + "abiltiy", "ability", + "abodmen", "abdomen", + "abondon", "abandon", + "aboslve", "absolve", + "abosrbs", "absorbs", + "abriter", "arbiter", + "abrupty", "abruptly", + "absense", "absence", + "absolue", "absolute", + "absovle", "absolve", + "absrobs", "absorbs", + "absuers", "abusers", + "absurdy", "absurdly", + "absymal", "abysmal", + "abymsal", "abysmal", + "acadamy", "academy", + "acadmic", "academic", + "accesss", "access", + "accpets", "accepts", + "accross", "across", + "accuray", "accuracy", + "acheive", "achieve", + "achived", "achieved", + "acident", "accident", + "ackward", "awkward", + "acrlyic", "acrylic", + "actauly", "actualy", + "activit", "activist", + "activly", "actively", + "actualy", "actually", + "actulay", "actualy", + "acuracy", "accuracy", + "acusing", "causing", + "acustom", "accustom", + "acutaly", "actualy", + "acyrlic", "acrylic", + "adaptes", "adapters", + "adatper", "adapter", + "adbomen", "abdomen", + "addcits", "addicts", + "adderss", "address", + "addtion", "addition", + "adequet", "adequate", + "adequit", "adequate", + "adivser", "adviser", + "adivsor", "advisor", + "admited", "admitted", + "admrial", "admiral", + "adpater", "adapter", + "adquire", "acquire", + "adultey", "adultery", + "adverst", "adverts", + "adviced", "advised", + "advocay", "advocacy", + "advsior", "advisor", + "aeriels", "aerials", + "affaris", "affairs", + "affiars", "affairs", + "afircan", "african", + "africas", "africans", + "afwully", "awfully", + "againts", "against", + "agaisnt", "against", + "aganist", "against", + "aggreed", "agreed", + "agianst", "against", + "agreing", "agreeing", + "agruing", "arguing", + "ahtiest", "athiest", + "aicraft", "aircraft", + "ailmony", "alimony", + "airbore", "airborne", + "aircaft", "aircraft", + "airlfow", "airflow", + "airosft", "airsoft", + "airpost", "airports", + "airsfot", "airsoft", + "airzona", "arizona", + "alchmey", "alchemy", + "alchool", "alcohol", + "alcohal", "alcohol", + "aledged", "alleged", + "aledges", "alleges", + "alegbra", "algebra", + "algerba", "algebra", + "alienet", "alienate", + "alledge", "allege", + "allegry", "allergy", + "alltime", "all-time", + "almighy", "almighty", + "alochol", "alcohol", + "alotted", "allotted", + "alowing", "allowing", + "alphabt", "alphabet", + "alreayd", "already", + "alrighy", "alrighty", + "altanta", "atlanta", + "alteast", "atleast", + "altough", "although", + "alusion", "allusion", + "amateus", "amateurs", + "amatuer", "amateur", + "amature", "armature", + "amensia", "amnesia", + "amensty", "amnesty", + "amercia", "america", + "americs", "americas", + "ammount", "amount", + "ammused", "amused", + "amneisa", "amnesia", + "amnsety", "amnesty", + "amognst", "amongst", + "amongts", "amongst", + "amonsgt", "amongst", + "ampilfy", "amplify", + "amrpits", "armpits", + "analoge", "analogue", + "analsyt", "analyst", + "analyes", "analyse", + "analyts", "analyst", + "analzye", "analyze", + "anaylse", "analyse", + "anaylst", "analyst", + "anaylze", "analyze", + "anceint", "ancient", + "andorid", "android", + "andriod", "android", + "androis", "androids", + "angirly", "angrily", + "angluar", "angular", + "angualr", "angular", + "anicent", "ancient", + "anitque", "antique", + "anixety", "anxiety", + "anmesia", "amnesia", + "anmesty", "amnesty", + "annoint", "anoint", + "annualy", "annually", + "annuled", "annulled", + "anohter", "another", + "anomoly", "anomaly", + "answerd", "answered", + "anuglar", "angular", + "anulled", "annulled", + "anwsers", "answers", + "anwyays", "anyways", + "anxeity", "anxiety", + "anyoens", "anyones", + "anyonse", "anyones", + "anywyas", "anyways", + "aparent", "apparent", + "appeard", "appeared", + "appluad", "applaud", + "aproval", "approval", + "apsects", "aspects", + "apshalt", "asphalt", + "apsirin", "aspirin", + "aqcuire", "acquire", + "aquarim", "aquarium", + "aquired", "acquired", + "aranged", "arranged", + "arbitre", "arbiter", + "arcahic", "archaic", + "archiac", "archaic", + "arcylic", "acrylic", + "aresnal", "arsenal", + "aretmis", "artemis", + "argubly", "arguably", + "aribter", "arbiter", + "ariflow", "airflow", + "arisoft", "airsoft", + "aritsts", "artists", + "armchar", "armchair", + "arogant", "arrogant", + "arogent", "arrogant", + "arresst", "arrests", + "arround", "around", + "arsneal", "arsenal", + "artcile", "article", + "artical", "article", + "articel", "article", + "artistc", "artistic", + "artmeis", "artemis", + "artsits", "artists", + "aruging", "arguing", + "aseuxal", "asexual", + "asexaul", "asexual", + "ashpalt", "asphalt", + "asiprin", "aspirin", + "asissts", "assists", + "asnwers", "answers", + "asorbed", "absorbed", + "aspahlt", "asphalt", + "asphlat", "asphalt", + "aspriin", "aspirin", + "assagne", "assange", + "assasin", "assassin", + "assembe", "assemble", + "assemby", "assembly", + "assisst", "assists", + "assnage", "assange", + "asssits", "assists", + "assualt", "assault", + "asterik", "asterisk", + "asutria", "austria", + "atcualy", "actualy", + "atelast", "atleast", + "athesim", "atheism", + "athiesm", "atheism", + "athiest", "atheist", + "athiets", "athiest", + "athlets", "athletes", + "atlantc", "atlantic", + "atleats", "atleast", + "atlesat", "atleast", + "atorney", "attorney", + "atremis", "artemis", + "attemps", "attempts", + "attemts", "attempts", + "attened", "attended", + "attracs", "attracts", + "audbile", "audible", + "audibel", "audible", + "austira", "austria", + "austrai", "austria", + "autistc", "autistic", + "avation", "aviation", + "avtaars", "avatars", + "awakend", "awakened", + "bablyon", "babylon", + "backdor", "backdoor", + "backsta", "backseat", + "baclony", "balcony", + "badnits", "bandits", + "baiscly", "basicly", + "bakcers", "backers", + "balanse", "balances", + "balcked", "blacked", + "banhsee", "banshee", + "bankgok", "bangkok", + "baoynet", "bayonet", + "baptims", "baptism", + "baptsim", "baptism", + "baragin", "bargain", + "bargani", "bargain", + "bargian", "bargain", + "bariner", "brainer", + "barlkey", "barkley", + "barracs", "barracks", + "barrles", "barrels", + "barsita", "barista", + "barvery", "bravery", + "bascily", "basicly", + "basicly", "basically", + "basilcy", "basicly", + "basiton", "bastion", + "basnhee", "banshee", + "bastane", "bastante", + "bastars", "bastards", + "bastino", "bastion", + "bathrom", "bathroom", + "batitsa", "batista", + "batsita", "batista", + "bayblon", "babylon", + "baynoet", "bayonet", + "bayoent", "bayonet", + "bceuase", "becuase", + "beacuse", "because", + "bealtes", "beatles", + "beaslty", "beastly", + "beatels", "beatles", + "beaucop", "beaucoup", + "becamae", "became", + "becames", "becomes", + "becasue", "because", + "becouse", "because", + "becuaes", "becuase", + "becuase", "because", + "becusae", "becuase", + "befried", "befriend", + "beggins", "begins", + "beglian", "belgian", + "beglium", "belgium", + "begnals", "bengals", + "bejiing", "beijing", + "beleifs", "beliefs", + "beleive", "believe", + "belgain", "belgian", + "belguim", "belgium", + "believr", "believer", + "believs", "believes", + "belifes", "beliefs", + "beligan", "belgian", + "beligum", "belgium", + "belived", "believed", + "belives", "believes", + "benagls", "bengals", + "benedit", "benedict", + "benghai", "benghazi", + "benglas", "bengals", + "benifit", "benefit", + "beoynce", "beyonce", + "beraded", "bearded", + "bersekr", "berserk", + "beseige", "besiege", + "betales", "beatles", + "bethesa", "bethesda", + "betrayd", "betrayed", + "beucase", "becuase", + "bewteen", "between", + "bicthes", "bitches", + "bidrman", "birdman", + "biejing", "beijing", + "bifgoot", "bigfoot", + "bigorty", "bigotry", + "bigtoed", "bigoted", + "bigtory", "bigotry", + "biogted", "bigoted", + "biogtry", "bigotry", + "bioplar", "bipolar", + "biploar", "bipolar", + "birdamn", "birdman", + "birdges", "bridges", + "birgade", "brigade", + "bitcion", "bitcoin", + "bithced", "bitched", + "bithces", "bitches", + "bitocin", "bitcoin", + "bizzare", "bizarre", + "blacony", "balcony", + "blaimed", "blamed", + "blankes", "blankets", + "blegian", "belgian", + "blegium", "belgium", + "blizzad", "blizzard", + "blockes", "blockers", + "bloster", "bolster", + "blulets", "bullets", + "bobmers", "bombers", + "bollocs", "bollocks", + "bondary", "boundary", + "bonnano", "bonanno", + "bonsues", "bonuses", + "boraden", "broaden", + "borader", "broader", + "boradly", "broadly", + "bordeom", "boredom", + "boslter", "bolster", + "boudler", "boulder", + "boundry", "boundary", + "bounses", "bonuses", + "boutiqe", "boutique", + "bouyant", "buoyant", + "braevry", "bravery", + "braista", "barista", + "brakley", "barkley", + "branier", "brainer", + "braoden", "broaden", + "braoder", "broader", + "braodly", "broadly", + "brednan", "brendan", + "breifly", "briefly", + "breserk", "berserk", + "brethen", "brethren", + "brewrey", "brewery", + "briagde", "brigade", + "brianer", "brainer", + "bridman", "birdman", + "brielfy", "briefly", + "brigdes", "bridges", + "brightn", "brighten", + "brisben", "brisbane", + "britian", "britain", + "britsol", "bristol", + "briused", "bruised", + "briuser", "bruiser", + "briuses", "bruises", + "brocoli", "broccoli", + "bronocs", "broncos", + "browine", "brownie", + "brownei", "brownie", + "brownis", "brownies", + "bruglar", "burglar", + "brunete", "brunette", + "bruning", "burning", + "brusied", "bruised", + "brusies", "bruises", + "brusses", "brussels", + "brutaly", "brutally", + "btiched", "bitched", + "btiches", "bitches", + "bubbels", "bubbles", + "buddhim", "buddhism", + "buddhit", "buddhist", + "buddist", "buddhist", + "budgest", "budgets", + "bugdets", "budgets", + "buildes", "builders", + "bulgara", "bulgaria", + "bullest", "bullets", + "buoancy", "buoyancy", + "burguny", "burgundy", + "buriser", "bruiser", + "burlgar", "burglar", + "burnign", "burning", + "burried", "buried", + "burrtio", "burrito", + "busines", "business", + "busness", "business", + "butthoe", "butthole", + "buttrey", "buttery", + "cababge", "cabbage", + "cabines", "cabinets", + "cabniet", "cabinet", + "caclium", "calcium", + "cacuses", "caucuses", + "caffeen", "caffeine", + "cahched", "cached", + "cahotic", "chaotic", + "cahsier", "cashier", + "cailbre", "calibre", + "calaber", "caliber", + "calagry", "calgary", + "calback", "callback", + "calbire", "calibre", + "calcuim", "calcium", + "calculs", "calculus", + "calicum", "calcium", + "calrify", "clarify", + "calrity", "clarity", + "caluses", "clauses", + "camboda", "cambodia", + "campain", "campaign", + "campuss", "campuses", + "cancles", "cancels", + "cancres", "cancers", + "cancuks", "canucks", + "canides", "candies", + "cannnot", "cannot", + "canrage", "carnage", + "capible", "capable", + "capitas", "capitals", + "capsuls", "capsules", + "captais", "captains", + "captial", "capital", + "captiol", "capitol", + "captued", "captured", + "capturd", "captured", + "capusle", "capsule", + "carange", "carnage", + "carbien", "carbine", + "cardaic", "cardiac", + "cardina", "cardigan", + "careing", "caring", + "caridac", "cardiac", + "carmtan", "cartman", + "carnege", "carnage", + "carnige", "carnage", + "carolan", "carolina", + "carreer", "career", + "carrers", "careers", + "cartles", "cartels", + "caryons", "crayons", + "casette", "cassette", + "casheir", "cashier", + "cashies", "cashiers", + "cashire", "cashier", + "casltes", "castles", + "caspule", "capsule", + "cassete", "cassette", + "castels", "castles", + "casuing", "causing", + "cathlic", "catholic", + "cauncks", "canucks", + "cavarly", "cavalry", + "cavlary", "cavalry", + "celcius", "celsius", + "celisus", "celsius", + "celitcs", "celtics", + "celsuis", "celsius", + "centruy", "century", + "centuty", "century", + "ceratin", "certain", + "cermaic", "ceramic", + "certian", "certain", + "cervial", "cervical", + "cesspol", "cesspool", + "cetlics", "celtics", + "chambre", "chamber", + "charcol", "charcoal", + "charisa", "charisma", + "chasiss", "chassis", + "chatoic", "chaotic", + "cheeots", "cheetos", + "cheesse", "cheeses", + "chekcer", "checker", + "chelsae", "chelsea", + "cheslea", "chelsea", + "chiense", "chinese", + "childen", "children", + "chimeny", "chimney", + "chinees", "chinese", + "chinmey", "chimney", + "chipest", "chipset", + "chispet", "chipset", + "chivaly", "chivalry", + "chlesea", "chelsea", + "chnages", "changes", + "choatic", "chaotic", + "chocies", "choices", + "choosen", "chosen", + "chtulhu", "cthulhu", + "churchs", "churches", + "cilanto", "cilantro", + "cilents", "clients", + "circels", "circles", + "circuis", "circuits", + "cirlces", "circles", + "clacium", "calcium", + "claerer", "clearer", + "claerly", "clearly", + "clagary", "calgary", + "claibre", "calibre", + "claimes", "claims", + "clairfy", "clarify", + "clairty", "clarity", + "clanand", "clannad", + "clarfiy", "clarify", + "classis", "classics", + "clasues", "clauses", + "claymer", "claymore", + "claymoe", "claymore", + "cleanes", "cleanse", + "cleasne", "cleanse", + "cleints", "clients", + "clenase", "cleanse", + "clesius", "celsius", + "cletics", "celtics", + "clevery", "cleverly", + "climats", "climates", + "climbes", "climbers", + "clincis", "clinics", + "clitors", "clitoris", + "cloesly", "closely", + "closley", "closely", + "cluases", "clauses", + "cluprit", "culprit", + "coalese", "coalesce", + "coctail", "cocktail", + "cohesie", "cohesive", + "colgone", "cologne", + "collape", "collapse", + "collest", "collects", + "collony", "colony", + "collumn", "column", + "cologen", "cologne", + "colomba", "colombia", + "colonge", "cologne", + "colorao", "colorado", + "colourd", "coloured", + "columsn", "columns", + "comando", "commando", + "comapny", "company", + "comapre", "compare", + "comarde", "comrade", + "comback", "comeback", + "combins", "combines", + "comdeic", "comedic", + "comited", "committed", + "commano", "commando", + "commans", "commands", + "commere", "commerce", + "comming", "coming", + "commitd", "commited", + "compase", "compares", + "compede", "competed", + "compilr", "compiler", + "compnay", "company", + "compots", "compost", + "comrads", "comrades", + "comtpon", "compton", + "conceed", "concede", + "conceps", "concepts", + "conclue", "conclude", + "concret", "concert", + "condenm", "condemn", + "condiut", "conduit", + "condmen", "condemn", + "confids", "confides", + "confins", "confines", + "confise", "confines", + "conflit", "conflict", + "conived", "connived", + "connecs", "connects", + "conqeur", "conquer", + "conqure", "conquer", + "consept", "concept", + "consern", "concern", + "consums", "consumes", + "contacs", "contacts", + "contais", "contains", + "contast", "contacts", + "contemt", "contempt", + "contens", "contents", + "contess", "contests", + "contian", "contain", + "contine", "continue", + "convers", "converts", + "conveyd", "conveyed", + "convine", "convince", + "coprses", "corpses", + "coputer", "computer", + "corasir", "corsair", + "coratia", "croatia", + "coridal", "cordial", + "corsari", "corsair", + "corsiar", "corsair", + "corspes", "corpses", + "corwbar", "crowbar", + "costums", "costumes", + "coudlnt", "couldnt", + "coulmns", "columns", + "coulndt", "couldnt", + "counsle", "counsel", + "countes", "counters", + "courtey", "courtesy", + "covenat", "covenant", + "coytoes", "coyotes", + "crabine", "carbine", + "cralwed", "crawled", + "craotia", "croatia", + "craweld", "crawled", + "creamic", "ceramic", + "createn", "creatine", + "creater", "creature", + "creatie", "creatine", + "creatue", "creature", + "creepes", "creepers", + "creepig", "creeping", + "creulty", "cruelty", + "cricles", "circles", + "critera", "criteria", + "cropses", "corpses", + "crosair", "corsair", + "crpytic", "cryptic", + "crsytal", "crystal", + "crtical", "critical", + "crucibe", "crucible", + "cruetly", "cruelty", + "cruical", "crucial", + "crulety", "cruelty", + "crusdae", "crusade", + "crusier", "cruiser", + "crusies", "cruises", + "crusive", "cursive", + "crutchs", "crutches", + "crypitc", "cryptic", + "crystas", "crystals", + "crystsl", "crystals", + "crytpic", "cryptic", + "crytsal", "crystal", + "cthluhu", "cthulhu", + "cthuhlu", "cthulhu", + "cthuluh", "cthulhu", + "ctuhlhu", "cthulhu", + "cuasing", "causing", + "cubcile", "cubicle", + "cubilce", "cubicle", + "cuddels", "cuddles", + "culrpit", "culprit", + "culturs", "cultures", + "cupboad", "cupboard", + "cuplrit", "culprit", + "curatin", "curtain", + "curcial", "crucial", + "curcuit", "circuit", + "curelty", "cruelty", + "curiser", "cruiser", + "curisve", "cursive", + "currate", "curate", + "currens", "currents", + "curreny", "currency", + "currest", "currents", + "cursade", "crusade", + "curtian", "curtain", + "cyandie", "cyanide", + "cyclits", "cyclist", + "cycloen", "cyclone", + "cycolps", "cyclops", + "cylcist", "cyclist", + "cylcone", "cyclone", + "cylcops", "cyclops", + "cynaide", "cyanide", + "cyrptic", "cryptic", + "cyrstal", "crystal", + "dagners", "dangers", + "daimond", "diamond", + "damenor", "demeanor", + "dammage", "damage", + "darcula", "dracula", + "dargons", "dragons", + "darkets", "darkest", + "datbase", "database", + "daulity", "duality", + "dawrves", "dwarves", + "ddogers", "dodgers", + "ddoging", "dodging", + "deadlit", "deadlift", + "deadpol", "deadpool", + "deafult", "default", + "deahtly", "deathly", + "deatils", "details", + "deatlhy", "deathly", + "decalre", "declare", + "decison", "decision", + "declars", "declares", + "declase", "declares", + "decress", "decrees", + "decribe", "describe", + "decsend", "descend", + "dectect", "detect", + "defaint", "defiant", + "defauls", "defaults", + "defelct", "deflect", + "defensd", "defends", + "deffine", "define", + "definat", "defiant", + "definet", "definite", + "definie", "definite", + "definig", "defining", + "definit", "definite", + "defualt", "default", + "degarde", "degrade", + "degrase", "degrasse", + "degrate", "degrade", + "deiners", "deniers", + "deisgns", "designs", + "deivant", "deviant", + "dekstop", "desktop", + "delcare", "declare", + "delfect", "deflect", + "demenor", "demeanor", + "dementa", "dementia", + "demsond", "desmond", + "deneirs", "deniers", + "denisty", "density", + "densley", "densely", + "depcits", "depicts", + "dependd", "depended", + "depitcs", "depicts", + "deployd", "deployed", + "depsise", "despise", + "descrie", "describe", + "descuss", "discuss", + "desgins", "designs", + "desings", "designs", + "desitny", "destiny", + "desnely", "densely", + "desnity", "density", + "desomnd", "desmond", + "despict", "depict", + "despide", "despised", + "despies", "despise", + "destkop", "desktop", + "destory", "destroy", + "destros", "destroys", + "detaild", "detailed", + "detials", "details", + "detorit", "detroit", + "detriot", "detroit", + "deuling", "dueling", + "devaint", "deviant", + "devaite", "deviate", + "devided", "divided", + "devlove", "devolve", + "devotin", "devotion", + "devovle", "devolve", + "diabets", "diabetes", + "dialecs", "dialects", + "dialoge", "dialogue", + "diamons", "diamonds", + "diasble", "disable", + "dicksih", "dickish", + "dicover", "discover", + "dictats", "dictates", + "dieties", "deities", + "dilpoma", "diploma", + "dimaond", "diamond", + "dingity", "dignity", + "dinosar", "dinosaur", + "diosese", "diocese", + "dipolma", "diploma", + "dirbble", "dribble", + "directy", "directly", + "diretcx", "directx", + "dirived", "derived", + "dirvers", "drivers", + "disbale", "disable", + "disguss", "disgusts", + "disliks", "dislikes", + "disover", "discover", + "dispair", "despair", + "dispath", "dispatch", + "dispite", "despite", + "dispuse", "disputes", + "disputs", "disputes", + "dissole", "dissolve", + "distase", "distaste", + "distint", "distinct", + "divison", "division", + "docuhes", "douches", + "docuhey", "douchey", + "dogders", "dodgers", + "dogding", "dodging", + "dolhpin", "dolphin", + "dolphis", "dolphins", + "dominae", "dominate", + "dominno", "dominion", + "doplhin", "dolphin", + "dortmud", "dortmund", + "draclua", "dracula", + "dracual", "dracula", + "drakest", "darkest", + "dramtic", "dramatic", + "dribbel", "dribble", + "driectx", "directx", + "driftig", "drifting", + "drinkes", "drinkers", + "druming", "drumming", + "duailty", "duality", + "dualtiy", "duality", + "dubsetp", "dubstep", + "dulaity", "duality", + "duleing", "dueling", + "dunegon", "dungeon", + "dungeos", "dungeons", + "dungoen", "dungeon", + "durring", "during", + "dusbtep", "dubstep", + "dyansty", "dynasty", + "dynamis", "dynamics", + "dynsaty", "dynasty", + "earlies", "earliest", + "earliet", "earliest", + "earplus", "earplugs", + "eastwod", "eastwood", + "ebcuase", "becuase", + "ecilpse", "eclipse", + "eclipes", "eclipse", + "eclispe", "eclipse", + "eclpise", "eclipse", + "ectsasy", "ecstasy", + "edbiles", "edibles", + "edibels", "edibles", + "effords", "efforts", + "ehtanol", "ethanol", + "eifnach", "einfach", + "eighten", "eighteen", + "einfahc", "einfach", + "elasped", "elapsed", + "elcipse", "eclipse", + "elction", "election", + "elecrto", "electro", + "electic", "electric", + "electon", "election", + "ellitot", "elliott", + "elloitt", "elliott", + "elphant", "elephant", + "emabrgo", "embargo", + "emabssy", "embassy", + "emapthy", "empathy", + "embeded", "embedded", + "embrago", "embargo", + "eminate", "emanate", + "emipres", "empires", + "emision", "emission", + "emiting", "emitting", + "emition", "emission", + "emmited", "emitted", + "empahty", "empathy", + "emphsis", "emphasis", + "empiers", "empires", + "empited", "emptied", + "emplore", "employer", + "emporer", "emperor", + "empries", "empires", + "emtpied", "emptied", + "enameld", "enameled", + "encahnt", "enchant", + "encalve", "enclave", + "encrpyt", "encrypt", + "encyrpt", "encrypt", + "endores", "endorse", + "endrose", "endorse", + "energis", "energies", + "enforse", "enforces", + "enginer", "engineer", + "englsih", "english", + "enhanse", "enhances", + "enlcave", "enclave", + "enlgish", "english", + "enlsave", "enslave", + "ensalve", "enslave", + "entbook", "netbook", + "entirey", "entirety", + "entorpy", "entropy", + "epiloge", "epilogue", + "episdoe", "episode", + "epsiode", "episode", + "epsorts", "esports", + "eptiome", "epitome", + "equiped", "equipped", + "erested", "arrested", + "escapse", "escapes", + "escpaes", "escapes", + "esctasy", "ecstasy", + "esporst", "esports", + "espreso", "espresso", + "esprots", "esports", + "essense", "essence", + "etherel", "ethereal", + "ethnaol", "ethanol", + "euphora", "euphoria", + "europen", "european", + "eurpean", "european", + "everets", "everest", + "everset", "everest", + "evloved", "evolved", + "evloves", "evolves", + "evovled", "evolved", + "evovles", "evolves", + "exaclty", "exactly", + "exahust", "exhaust", + "examind", "examined", + "exapnds", "expands", + "exatled", "exalted", + "excange", "exchange", + "excatly", "exactly", + "excells", "excels", + "exceprt", "excerpt", + "excluse", "excludes", + "excrept", "excerpt", + "exculde", "exclude", + "exelent", "excellent", + "exemple", "example", + "exerpts", "excerpts", + "exhasut", "exhaust", + "exhuast", "exhaust", + "exising", "existing", + "existet", "existent", + "exlated", "exalted", + "exlcude", "exclude", + "exliled", "exiled", + "exludes", "excludes", + "exmaple", "example", + "exoitcs", "exotics", + "expalin", "explain", + "expeced", "expected", + "expells", "expels", + "expiers", "expires", + "explict", "explicit", + "expliot", "exploit", + "explods", "explodes", + "explose", "explodes", + "expolde", "explode", + "expolit", "exploit", + "exposse", "exposes", + "expries", "expires", + "exracts", "extracts", + "exsited", "existed", + "extered", "exerted", + "exterme", "extreme", + "extoics", "exotics", + "extreem", "extreme", + "extrems", "extremes", + "eyebals", "eyeballs", + "eyebros", "eyebrows", + "fabulos", "fabulous", + "facebok", "facebook", + "facepam", "facepalm", + "faclons", "falcons", + "facsism", "fascism", + "facsist", "fascist", + "failurs", "failures", + "faincee", "fiancee", + "falesly", "falsely", + "falired", "flaired", + "falshed", "flashed", + "falshes", "flashes", + "falsley", "falsely", + "falvors", "flavors", + "familes", "families", + "famoust", "famous", + "famousy", "famously", + "fanatsy", "fantasy", + "fantaic", "fanatic", + "faoming", "foaming", + "fascits", "fascist", + "fasicsm", "fascism", + "fasicst", "fascist", + "faslely", "falsely", + "fatiuge", "fatigue", + "febuary", "february", + "fecthed", "fetched", + "fecthes", "fetches", + "feminen", "feminine", + "feminie", "feminine", + "feminim", "feminism", + "feodras", "fedoras", + "fertily", "fertility", + "fesitve", "festive", + "fethced", "fetched", + "fethces", "fetches", + "fetishs", "fetishes", + "fianite", "finite", + "fianlly", "finally", + "fiercly", "fiercely", + "filcker", "flicker", + "filpped", "flipped", + "filterd", "filtered", + "finacee", "fiancee", + "fineses", "finesse", + "fininsh", "finnish", + "finishs", "finishes", + "finisse", "finishes", + "finnsih", "finnish", + "firends", "friends", + "firggin", "friggin", + "firsbee", "frisbee", + "firslty", "firstly", + "firtsly", "firstly", + "fitlers", "filters", + "flacons", "falcons", + "flahsed", "flashed", + "flahses", "flashes", + "flaried", "flaired", + "flasely", "falsely", + "flashig", "flashing", + "flavord", "flavored", + "flavous", "flavours", + "flawess", "flawless", + "flciker", "flicker", + "fliters", "filters", + "flordia", "florida", + "florene", "florence", + "fnaatic", "fanatic", + "fomaing", "foaming", + "fonetic", "phonetic", + "forefit", "forfeit", + "foregin", "foreign", + "foreing", "foreign", + "forfiet", "forfeit", + "forhead", "forehead", + "foriegn", "foreign", + "formaly", "formally", + "formery", "formerly", + "formost", "foremost", + "formual", "formula", + "formuls", "formulas", + "forrset", "forrest", + "forsakn", "forsaken", + "forsane", "forsaken", + "forumla", "formula", + "fountan", "fountain", + "fourten", "fourteen", + "fracter", "fracture", + "fragmet", "fragment", + "freedos", "freedoms", + "freinds", "friends", + "frigign", "friggin", + "fristly", "firstly", + "frostig", "frosting", + "frsibee", "frisbee", + "fruitin", "fruition", + "fullets", "fullest", + "fullset", "fullest", + "funides", "fundies", + "funtion", "function", + "furance", "furnace", + "furncae", "furnace", + "futhroc", "futhark", + "gadgest", "gadgets", + "gagdets", "gadgets", + "galatic", "galactic", + "galcier", "glacier", + "galsgow", "glasgow", + "gameply", "gameplay", + "gamerga", "gamertag", + "gankign", "ganking", + "ganster", "gangster", + "garabge", "garbage", + "garfied", "garfield", + "garnola", "granola", + "generas", "generals", + "genersl", "generals", + "geniuss", "geniuses", + "geogria", "georgia", + "geomety", "geometry", + "georiga", "georgia", + "gernade", "grenade", + "gerogia", "georgia", + "gigabye", "gigabyte", + "giltchy", "glitchy", + "gimmics", "gimmicks", + "gimmicy", "gimmicky", + "girzzly", "grizzly", + "glagsow", "glasgow", + "glaicer", "glacier", + "glicthy", "glitchy", + "glimpes", "glimpse", + "glimspe", "glimpse", + "glipmse", "glimpse", + "glitchd", "glitched", + "glitchs", "glitches", + "glithcy", "glitchy", + "globaly", "globally", + "gloiath", "goliath", + "glorios", "glorious", + "gltichy", "glitchy", + "gnaking", "ganking", + "gnawwed", "gnawed", + "goddanm", "goddamn", + "goddman", "goddamn", + "godliek", "godlike", + "godlman", "goldman", + "godsped", "godspeed", + "goergia", "georgia", + "goilath", "goliath", + "golaith", "goliath", + "golbins", "goblins", + "goldamn", "goldman", + "goldbeg", "goldberg", + "goldike", "godlike", + "golitah", "goliath", + "goodluk", "goodluck", + "gorumet", "gourmet", + "gosepls", "gospels", + "gosples", "gospels", + "gpysies", "gypsies", + "grabage", "garbage", + "grahpic", "graphic", + "grainte", "granite", + "grammer", "grammar", + "graniet", "granite", + "grantie", "granite", + "graphie", "graphite", + "graphis", "graphics", + "grappel", "grapple", + "greande", "grenade", + "grenads", "grenades", + "greneer", "greener", + "griaffe", "giraffe", + "gridles", "griddles", + "grillig", "grilling", + "grpahic", "graphic", + "guardin", "guardian", + "guiness", "guinness", + "gullibe", "gullible", + "gutiars", "guitars", + "gypises", "gypsies", + "gyspies", "gypsies", + "habaeus", "habeas", + "haethen", "heathen", + "hailfax", "halifax", + "halfiax", "halifax", + "handbok", "handbook", + "handedy", "handedly", + "handeld", "handled", + "hanlder", "handler", + "hannibl", "hannibal", + "hanuted", "haunted", + "haorder", "hoarder", + "hapened", "happened", + "happend", "happened", + "happliy", "happily", + "harased", "harassed", + "harases", "harasses", + "hardend", "hardened", + "hardwod", "hardwood", + "haricut", "haircut", + "hatchig", "hatching", + "hauntig", "haunting", + "haviest", "heaviest", + "headest", "headset", + "headses", "headsets", + "heaveny", "heavenly", + "heigher", "higher", + "heigths", "heights", + "helemts", "helmets", + "hellfie", "hellfire", + "hellvua", "helluva", + "helment", "helmet", + "helpped", "helped", + "hemlets", "helmets", + "henious", "heinous", + "heorics", "heroics", + "heorine", "heroine", + "heriocs", "heroics", + "herione", "heroine", + "herocis", "heroics", + "heronie", "heroine", + "hesiman", "heisman", + "hieghts", "heights", + "hienous", "heinous", + "hiesman", "heisman", + "himselv", "himself", + "hiptser", "hipster", + "hismelf", "himself", + "hispter", "hipster", + "hitboxs", "hitboxes", + "hoilday", "holiday", + "hokpins", "hopkins", + "holdiay", "holiday", + "holdins", "holdings", + "homniem", "hominem", + "horader", "hoarder", + "hosited", "hoisted", + "hosthot", "hotshot", + "hostles", "hostels", + "hostpot", "hotspot", + "hothsot", "hotshot", + "hotpsot", "hotspot", + "hotsopt", "hotspot", + "hounour", "honour", + "hseldon", "sheldon", + "huanted", "haunted", + "humanit", "humanist", + "humants", "humanist", + "humidiy", "humidity", + "humoros", "humorous", + "hunagry", "hungary", + "hunderd", "hundred", + "hundres", "hundreds", + "hungray", "hungary", + "hurdels", "hurdles", + "hurldes", "hurdles", + "husbans", "husbands", + "hweaton", "wheaton", + "hybirds", "hybrids", + "hydogen", "hydrogen", + "hygeine", "hygiene", + "hypnoss", "hypnosis", + "hyrbids", "hybrids", + "hystera", "hysteria", + "iceforg", "icefrog", + "ierland", "ireland", + "ignitin", "ignition", + "ignorat", "ignorant", + "illegas", "illegals", + "illegsl", "illegals", + "illinos", "illinois", + "imanent", "eminent", + "imapcts", "impacts", + "iminent", "eminent", + "imminet", "imminent", + "implict", "implicit", + "imploed", "implode", + "imploys", "employs", + "impluse", "impulse", + "impolde", "implode", + "importd", "imported", + "imporve", "improve", + "impules", "impulse", + "impusle", "impulse", + "imrpove", "improve", + "incldue", "include", + "incluse", "includes", + "indains", "indians", + "indeces", "indices", + "indiaan", "indiana", + "indluge", "indulge", + "indugle", "indulge", + "infalte", "inflate", + "infenro", "inferno", + "infered", "inferred", + "inferir", "inferior", + "infinet", "infinite", + "infinie", "infinite", + "infinit", "infinite", + "infornt", "infront", + "infroms", "informs", + "infrotn", "infront", + "inheirt", "inherit", + "inidans", "indians", + "initals", "initials", + "initisl", "initials", + "inlcine", "incline", + "inovker", "invoker", + "inpeach", "impeach", + "inpsect", "inspect", + "inpsire", "inspire", + "inquier", "inquire", + "inquriy", "inquiry", + "insaney", "insanely", + "inscets", "insects", + "insepct", "inspect", + "insipre", "inspire", + "insluts", "insults", + "instade", "instead", + "instint", "instinct", + "intenst", "intents", + "intered", "interred", + "interet", "interest", + "internt", "internet", + "interro", "interior", + "intrest", "interest", + "intrige", "intrigue", + "invlove", "involve", + "invoekr", "invoker", + "invovle", "involve", + "iornman", "ironman", + "iranain", "iranian", + "iranias", "iranians", + "iranina", "iranian", + "irleand", "ireland", + "ironamn", "ironman", + "isalmic", "islamic", + "isareli", "israeli", + "islamit", "islamist", + "islmaic", "islamic", + "isloate", "isolate", + "isralei", "israeli", + "isreali", "israeli", + "italias", "italians", + "jagaurs", "jaguars", + "jaguras", "jaguars", + "jamacia", "jamaica", + "jamaina", "jamaican", + "jamiaca", "jamaica", + "jamsine", "jasmine", + "janaury", "january", + "januray", "january", + "japanes", "japanese", + "jasmien", "jasmine", + "jaugars", "jaguars", + "jaunary", "january", + "jeircho", "jericho", + "jennins", "jennings", + "jeopary", "jeopardy", + "jeresys", "jerseys", + "jericoh", "jericho", + "jersyes", "jerseys", + "jewerly", "jewelry", + "jorunal", "journal", + "jounral", "journal", + "joystik", "joystick", + "juadism", "judaism", + "judasim", "judaism", + "judical", "judicial", + "juipter", "jupiter", + "junglig", "jungling", + "juptier", "jupiter", + "jusitfy", "justify", + "justfiy", "justify", + "karakoe", "karaoke", + "karoake", "karaoke", + "kenendy", "kennedy", + "kenndey", "kennedy", + "kentucy", "kentucky", + "keyboad", "keyboard", + "keychan", "keychain", + "keynode", "keynote", + "kicthen", "kitchen", + "killins", "killings", + "kineitc", "kinetic", + "kinghts", "knights", + "kinteic", "kinetic", + "kitches", "kitchens", + "kitites", "kitties", + "knietic", "kinetic", + "knigths", "knights", + "knuckel", "knuckle", + "kroeans", "koreans", + "krudish", "kurdish", + "ktichen", "kitchen", + "kubirck", "kubrick", + "kunckle", "knuckle", + "kurbick", "kubrick", + "kuridsh", "kurdish", + "laguage", "language", + "landins", "landings", + "lantren", "lantern", + "laready", "already", + "laregly", "largely", + "largley", "largely", + "lasanga", "lasagna", + "lasgana", "lasagna", + "latitue", "latitude", + "latnern", "lantern", + "launhed", "launched", + "lavendr", "lavender", + "leathal", "lethal", + "lefitst", "leftist", + "leftits", "leftist", + "legnths", "lengths", + "legnthy", "lengthy", + "legoins", "legions", + "leigons", "legions", + "lenghts", "lengths", + "lenoard", "leonard", + "lepoard", "leopard", + "lesbain", "lesbian", + "lesiban", "lesbian", + "lesiure", "leisure", + "liasion", "liaison", + "liasons", "liaisons", + "liberae", "liberate", + "liberas", "liberals", + "lienups", "lineups", + "liesure", "leisure", + "liftime", "lifetime", + "lighlty", "lightly", + "lightes", "lighters", + "ligthly", "lightly", + "linclon", "lincoln", + "linueps", "lineups", + "liqiuds", "liquids", + "lisence", "license", + "lisense", "license", + "listend", "listened", + "litecon", "litecoin", + "literae", "literate", + "lithuim", "lithium", + "litihum", "lithium", + "loadous", "loadouts", + "loenard", "leonard", + "loepard", "leopard", + "logiteh", "logitech", + "loosley", "loosely", + "luandry", "laundry", + "luckliy", "luckily", + "luicfer", "lucifer", + "lunatis", "lunatics", + "maching", "machine", + "machins", "machines", + "maclolm", "malcolm", + "macthup", "matchup", + "madsion", "madison", + "magents", "magnets", + "magicin", "magician", + "magolia", "magnolia", + "maidson", "madison", + "maintan", "maintain", + "mairlyn", "marilyn", + "malaira", "malaria", + "malaysa", "malaysia", + "malclom", "malcolm", + "manauls", "manuals", + "mandase", "mandates", + "mandats", "mandates", + "mangeld", "mangled", + "mangets", "magnets", + "manualy", "manually", + "manuver", "maneuver", + "marbels", "marbles", + "margart", "margaret", + "mariage", "marriage", + "mariens", "marines", + "maritan", "martian", + "marixsm", "marxism", + "mariyln", "marilyn", + "markede", "marketed", + "marlbes", "marbles", + "marliyn", "marilyn", + "marnies", "marines", + "marrage", "marriage", + "martail", "martial", + "martain", "martian", + "masacra", "mascara", + "massace", "massacre", + "mathcup", "matchup", + "mathwes", "mathews", + "matrial", "martial", + "maunals", "manuals", + "mcalren", "mclaren", + "meanins", "meanings", + "medicad", "medicaid", + "medicae", "medicare", + "medioce", "mediocre", + "meixcan", "mexican", + "meldoic", "melodic", + "melieux", "milieux", + "melodis", "melodies", + "memeber", "member", + "memoery", "memory", + "memorie", "memory", + "menally", "mentally", + "mentaly", "mentally", + "meoldic", "melodic", + "meranda", "veranda", + "merchat", "merchant", + "merucry", "mercury", + "messagd", "messaged", + "messaih", "messiah", + "metagem", "metagame", + "metalic", "metallic", + "mexcian", "mexican", + "michina", "michigan", + "midfied", "midfield", + "midotwn", "midtown", + "midtwon", "midtown", + "migrans", "migrants", + "militat", "militant", + "militis", "militias", + "miltary", "military", + "mimimum", "minimum", + "mineras", "minerals", + "mininos", "minions", + "ministr", "minister", + "ministy", "ministry", + "minoins", "minions", + "minstry", "ministry", + "minumum", "minimum", + "mirrord", "mirrored", + "misandy", "misandry", + "misison", "mission", + "misouri", "missouri", + "mispell", "misspell", + "missils", "missiles", + "mistery", "mystery", + "mobiliy", "mobility", + "modualr", "modular", + "momento", "memento", + "momment", "moment", + "monarcy", "monarchy", + "monatge", "montage", + "monglos", "mongols", + "monitos", "monitors", + "monstre", "monster", + "montaeg", "montage", + "montrel", "montreal", + "monumet", "monument", + "morbidy", "morbidly", + "morgage", "mortgage", + "morphen", "morphine", + "morphie", "morphine", + "morroco", "morocco", + "mortage", "mortgage", + "mosnter", "monster", + "mosture", "moisture", + "motivet", "motivate", + "motnage", "montage", + "motoral", "motorola", + "mountan", "mountain", + "movment", "movement", + "mucuous", "mucous", + "muesums", "museums", + "muliple", "multiple", + "mulsims", "muslims", + "multipe", "multiple", + "multipy", "multiply", + "munbers", "numbers", + "munchis", "munchies", + "murderd", "murdered", + "muscial", "musical", + "mushrom", "mushroom", + "musilms", "muslims", + "muslces", "muscles", + "musuems", "museums", + "mutatin", "mutation", + "mypsace", "myspace", + "mysapce", "myspace", + "napolen", "napoleon", + "narhwal", "narwhal", + "natique", "antique", + "nativey", "natively", + "natrual", "natural", + "naugthy", "naughty", + "nauseos", "nauseous", + "nautils", "nautilus", + "nautral", "natural", + "nautres", "natures", + "nectode", "netcode", + "needels", "needles", + "neruons", "neurons", + "neslave", "enslave", + "netocde", "netcode", + "netowrk", "network", + "netural", "neutral", + "neturon", "neutron", + "netwrok", "network", + "neurton", "neutron", + "neuterd", "neutered", + "nighlty", "nightly", + "nigthly", "nightly", + "nihilim", "nihilism", + "ninties", "1990s", + "niverse", "inverse", + "nocture", "nocturne", + "nominae", "nominate", + "nominet", "nominate", + "nonsene", "nonsense", + "noramls", "normals", + "norhern", "northern", + "normaly", "normally", + "normany", "normandy", + "northen", "northern", + "nostris", "nostrils", + "notario", "ontario", + "notebok", "notebook", + "nothern", "northern", + "nowdays", "nowadays", + "nrivana", "nirvana", + "nuaghty", "naughty", + "nubmers", "numbers", + "nucelar", "nuclear", + "nucelus", "nucleus", + "nuclean", "unclean", + "nuclues", "nucleus", + "nucular", "nuclear", + "nuerons", "neurons", + "nuetral", "neutral", + "nuetron", "neutron", + "nulcear", "nuclear", + "nullfiy", "nullify", + "nusance", "nuisance", + "nutriet", "nutrient", + "oarcles", "oracles", + "obivous", "obvious", + "obvoius", "obvious", + "ocarnia", "ocarina", + "ocasion", "occasion", + "occured", "occurred", + "ocotber", "october", + "ocotpus", "octopus", + "ocraina", "ocarina", + "ocuntry", "country", + "ocurred", "occurred", + "ofcoure", "ofcourse", + "offcers", "officers", + "offical", "official", + "offisde", "offside", + "oftenly", "often", + "ogrilla", "gorilla", + "olmypic", "olympic", + "olreans", "orleans", + "olympis", "olympics", + "olypmic", "olympic", + "omision", "omission", + "omiting", "omitting", + "omlette", "omelette", + "ommited", "omitted", + "onatrio", "ontario", + "onbaord", "onboard", + "onborad", "onboard", + "ontairo", "ontario", + "ontraio", "ontario", + "opartor", "operator", + "openess", "openness", + "opitcal", "optical", + "opitmal", "optimal", + "oponent", "opponent", + "oposite", "opposite", + "oppenly", "openly", + "opponet", "opponent", + "oprhans", "orphans", + "optimim", "optimism", + "oracels", "oracles", + "oragnes", "oranges", + "oragsms", "orgasms", + "oralces", "oracles", + "orbtial", "orbital", + "orcales", "oracles", + "orelans", "orleans", + "organes", "organise", + "organie", "organise", + "organim", "organism", + "orginal", "original", + "orhpans", "orphans", + "oribtal", "orbital", + "orlenas", "orleans", + "orpahns", "orphans", + "orthodx", "orthodox", + "outfied", "outfield", + "outsidr", "outsider", + "overhal", "overhaul", + "overpad", "overpaid", + "oversue", "overuse", + "overtun", "overturn", + "ownders", "wonders", + "owuldve", "wouldve", + "oylmpic", "olympic", + "pacakge", "package", + "pacifit", "pacifist", + "packade", "packaged", + "pacthes", "patches", + "pahntom", "phantom", + "paitent", "patient", + "palcebo", "placebo", + "pallete", "palette", + "palster", "plaster", + "palyboy", "playboy", + "pamflet", "pamphlet", + "pamplet", "pamphlet", + "pancaks", "pancakes", + "pandroa", "pandora", + "panthen", "pantheon", + "paradim", "paradigm", + "paradse", "parades", + "paralel", "parallel", + "paranoa", "paranoia", + "parises", "praises", + "parites", "parties", + "partice", "particle", + "partick", "patrick", + "partiel", "particle", + "partiot", "patriot", + "partols", "patrols", + "passabe", "passable", + "passivs", "passives", + "pasuing", "pausing", + "pateint", "patient", + "pathces", "patches", + "patiens", "patients", + "patirot", "patriot", + "patrcik", "patrick", + "patrios", "patriots", + "patroit", "patriot", + "peaples", "peoples", + "pebbels", "pebbles", + "peirced", "pierced", + "penatly", "penalty", + "pendulm", "pendulum", + "penguis", "penguins", + "penicls", "pencils", + "penison", "pension", + "penisse", "penises", + "penitum", "pentium", + "pensies", "penises", + "pensino", "pension", + "pentuim", "pentium", + "peopels", "peoples", + "percise", "precise", + "perdict", "predict", + "perfers", "prefers", + "perhasp", "perhaps", + "perhpas", "perhaps", + "perisan", "persian", + "perjery", "perjury", + "permade", "premade", + "permier", "premier", + "permise", "premise", + "permium", "premium", + "peroids", "periods", + "peronal", "personal", + "perpaid", "prepaid", + "perphas", "perhaps", + "persain", "persian", + "persets", "presets", + "persits", "persist", + "persued", "pursued", + "persuit", "pursuit", + "pervail", "prevail", + "perview", "preview", + "pharoah", "pharaoh", + "phatnom", "phantom", + "phsyics", "physics", + "phyiscs", "physics", + "physcis", "physics", + "physiqe", "physique", + "picthed", "pitched", + "picther", "pitcher", + "picthes", "pitches", + "piegons", "pigeons", + "piglrim", "pilgrim", + "pigoens", "pigeons", + "pilgirm", "pilgrim", + "pilrgim", "pilgrim", + "pinoeer", "pioneer", + "pinpoit", "pinpoint", + "pionere", "pioneer", + "pireced", "pierced", + "pithces", "pitches", + "plantes", "planets", + "plastis", "plastics", + "plastre", "plaster", + "plataeu", "plateau", + "plateua", "plateau", + "playabe", "playable", + "playofs", "playoffs", + "plesant", "pleasant", + "pligrim", "pilgrim", + "ploygon", "polygon", + "ploymer", "polymer", + "podemso", "podemos", + "podmeos", "podemos", + "poeples", "peoples", + "poignat", "poignant", + "poineer", "pioneer", + "pointes", "pointers", + "poisond", "poisoned", + "polgyon", "polygon", + "polical", "political", + "polishs", "polishes", + "polisse", "polishes", + "politey", "politely", + "poluted", "polluted", + "polutes", "pollutes", + "popluar", "popular", + "populer", "popular", + "populos", "populous", + "porpose", "propose", + "porshan", "portion", + "porshon", "portion", + "portait", "portrait", + "portary", "portray", + "portras", "portrays", + "portrat", "portrait", + "posions", "poisons", + "positon", "position", + "positve", "positive", + "possibe", "possible", + "possiby", "possibly", + "postdam", "potsdam", + "postion", "position", + "postive", "positive", + "potatos", "potatoes", + "potical", "optical", + "potrait", "portrait", + "powderd", "powdered", + "poweful", "powerful", + "poylgon", "polygon", + "poylmer", "polymer", + "practie", "practise", + "praisse", "praises", + "praries", "prairies", + "prasied", "praised", + "prasies", "praises", + "pratice", "practice", + "preamde", "premade", + "preceed", "precede", + "precice", "precise", + "preests", "presets", + "prehaps", "perhaps", + "preimer", "premier", + "preimum", "premium", + "preists", "priests", + "preivew", "preview", + "premeir", "premier", + "premiee", "premiere", + "premire", "premier", + "premits", "permits", + "premius", "premiums", + "premuim", "premium", + "prepair", "prepare", + "preriod", "period", + "presens", "presents", + "presest", "presets", + "presist", "persist", + "prestes", "presets", + "presude", "presumed", + "pretene", "pretense", + "pretens", "pretends", + "preveiw", "preview", + "prevert", "pervert", + "previal", "prevail", + "previes", "previews", + "previos", "previous", + "priased", "praised", + "priases", "praises", + "printes", "printers", + "pristen", "pristine", + "probabe", "probable", + "probaly", "probably", + "probelm", "problem", + "procede", "proceed", + "procees", "proceeds", + "procesd", "proceeds", + "proclam", "proclaim", + "produly", "proudly", + "produse", "produces", + "progidy", "prodigy", + "progrom", "pogrom", + "prohibt", "prohibit", + "prohpet", "prophet", + "prologe", "prologue", + "promose", "promotes", + "promots", "promotes", + "prompty", "promptly", + "promtps", "prompts", + "pronous", "pronouns", + "prooved", "proved", + "propeht", "prophet", + "prophey", "prophecy", + "propper", "proper", + "protals", "portals", + "protecs", "protects", + "protess", "protests", + "protocl", "protocol", + "protray", "portray", + "prouldy", "proudly", + "provded", "provided", + "provine", "province", + "prusuit", "pursuit", + "pryamid", "pyramid", + "pscyhed", "psyched", + "ptiched", "pitched", + "pticher", "pitcher", + "puasing", "pausing", + "publicy", "publicly", + "publsih", "publish", + "puhsups", "pushups", + "punishs", "punishes", + "punisse", "punishes", + "pursiut", "pursuit", + "pursude", "pursued", + "purused", "pursued", + "pushpus", "pushups", + "pyarmid", "pyramid", + "pyramis", "pyramids", + "pyrmaid", "pyramid", + "pysched", "psyched", + "qaulify", "qualify", + "qaulity", "quality", + "qauntum", "quantum", + "quailfy", "qualify", + "quailty", "quality", + "queires", "queries", + "queitly", "quietly", + "quereis", "queries", + "quicket", "quickest", + "quielty", "quietly", + "quitely", "quietly", + "qunatum", "quantum", + "qunetin", "quentin", + "racisst", "racists", + "racthet", "ratchet", + "radaint", "radiant", + "radiane", "radiance", + "radicas", "radicals", + "radiers", "raiders", + "raelism", "realism", + "raidant", "radiant", + "railrod", "railroad", + "rainbos", "rainbows", + "raoches", "roaches", + "raoming", "roaming", + "raptros", "raptors", + "raputre", "rapture", + "rathcet", "ratchet", + "ratpure", "rapture", + "reacing", "reaching", + "reagrds", "regards", + "realies", "realise", + "realsie", "realise", + "realsim", "realism", + "realtes", "relates", + "reamins", "remains", + "reapirs", "repairs", + "rebouns", "rebounds", + "rebulit", "rebuilt", + "recalim", "reclaim", + "receips", "receipts", + "recided", "resided", + "reciept", "receipt", + "recievd", "recieved", + "recieve", "receive", + "recitfy", "rectify", + "recived", "received", + "reclami", "reclaim", + "recliam", "reclaim", + "recorre", "recorder", + "recoves", "recovers", + "recpies", "recipes", + "redeemd", "redeemed", + "redners", "renders", + "refelct", "reflect", + "referal", "referral", + "refered", "referred", + "referig", "refering", + "referrs", "refers", + "reflexs", "reflexes", + "refrers", "refers", + "refroms", "reforms", + "refusla", "refusal", + "regerts", "regrets", + "regiems", "regimes", + "regimet", "regiment", + "registy", "registry", + "regluar", "regular", + "regrest", "regrets", + "regulae", "regulate", + "regulas", "regulars", + "regulsr", "regulars", + "reigmes", "regimes", + "reigons", "regions", + "reitres", "retires", + "reivews", "reviews", + "reknown", "renown", + "relaise", "realise", + "relapes", "relapse", + "relaspe", "relapse", + "relatie", "relative", + "relatin", "relation", + "relcaim", "reclaim", + "releive", "relieve", + "releses", "releases", + "relfect", "reflect", + "reliabe", "reliable", + "relient", "reliant", + "relized", "realised", + "relpase", "relapse", + "remaind", "remained", + "remaing", "remaining", + "remakrs", "remarks", + "remannt", "remnant", + "remeber", "remember", + "remians", "remains", + "remnans", "remnants", + "renderd", "rendered", + "renegae", "renegade", + "renmant", "remnant", + "rentors", "renters", + "rentres", "renters", + "renuion", "reunion", + "repaird", "repaired", + "repalys", "replays", + "repblic", "republic", + "repeast", "repeats", + "repects", "respects", + "repitle", "reptile", + "replase", "replaces", + "replayd", "replayed", + "reponse", "response", + "repostd", "reposted", + "repsawn", "respawn", + "repsond", "respond", + "repsots", "reposts", + "reptiel", "reptile", + "reptils", "reptiles", + "repubic", "republic", + "republi", "republic", + "repulic", "republic", + "reqiuem", "requiem", + "requeim", "requiem", + "requime", "requiem", + "requred", "required", + "resapwn", "respawn", + "rescuse", "rescues", + "resembe", "resemble", + "reslove", "resolve", + "resolvs", "resolves", + "resonet", "resonate", + "resouce", "resource", + "resovle", "resolve", + "respest", "respects", + "respone", "response", + "respwan", "respawn", + "ressits", "resists", + "restord", "restored", + "resuced", "rescued", + "resuces", "rescues", + "retrive", "retrieve", + "returnd", "returned", + "reuinon", "reunion", + "reveald", "revealed", + "reveiws", "reviews", + "revelas", "reveals", + "reveral", "reversal", + "reviere", "reviewer", + "reviewd", "reviewed", + "reviewr", "reviewer", + "revolvr", "revolver", + "revolvs", "revolves", + "rewirte", "rewrite", + "reworkd", "reworked", + "rewriet", "rewrite", + "reynols", "reynolds", + "rhapsoy", "rhapsody", + "rhythem", "rhythm", + "rhythim", "rhythm", + "rhytmic", "rhythmic", + "riaders", "raiders", + "ritlain", "ritalin", + "ritoers", "rioters", + "rivarly", "rivalry", + "rivlary", "rivalry", + "roahces", "roaches", + "robotis", "robotics", + "rococco", "rococo", + "roestta", "rosetta", + "roiters", "rioters", + "roleply", "roleplay", + "romaina", "romania", + "romaing", "roaming", + "romanin", "romanian", + "romanna", "romanian", + "roomate", "roommate", + "rotuers", "routers", + "rugters", "rutgers", + "rulebok", "rulebook", + "rumorus", "rumours", + "rumuors", "rumours", + "runnung", "running", + "ruslted", "rustled", + "russina", "russian", + "russion", "russian", + "rusteld", "rustled", + "rythmic", "rhythmic", + "rythyms", "rhythms", + "sacrasm", "sarcasm", + "saddnes", "saddens", + "sadistc", "sadistic", + "sadning", "sanding", + "salaris", "salaries", + "salavge", "salvage", + "salvery", "slavery", + "salying", "slaying", + "sampels", "samples", + "samruai", "samurai", + "samuari", "samurai", + "samuria", "samurai", + "sandlas", "sandals", + "sandnig", "sanding", + "sanlder", "sandler", + "santorm", "santorum", + "sapphie", "sapphire", + "sarcams", "sarcasm", + "sargant", "sergeant", + "sasuage", "sausage", + "satifsy", "satisfy", + "satsify", "satisfy", + "satsohi", "satoshi", + "savanha", "savannah", + "savannh", "savannah", + "saveing", "saving", + "sawnsea", "swansea", + "sawnson", "swanson", + "scandas", "scandals", + "scannig", "scanning", + "scartch", "scratch", + "scheems", "schemes", + "schoold", "schooled", + "sciense", "sciences", + "scinece", "science", + "scootes", "scooters", + "scorpin", "scorpion", + "scpeter", "scepter", + "scracth", "scratch", + "scrambe", "scramble", + "scritps", "scripts", + "scrolld", "scrolled", + "scrpits", "scripts", + "scyhter", "scyther", + "seached", "searched", + "seaches", "searches", + "seahaws", "seahawks", + "seantor", "senator", + "searchd", "searched", + "searchs", "searches", + "sebrian", "serbian", + "secerts", "secrets", + "secpter", "scepter", + "secrest", "secrets", + "secrety", "secretly", + "seflies", "selfies", + "seguoys", "segues", + "seinors", "seniors", + "selifes", "selfies", + "senoirs", "seniors", + "sensure", "censure", + "sentaor", "senator", + "sentris", "sentries", + "serbain", "serbian", + "sergeat", "sergeant", + "sergent", "sergeant", + "seriban", "serbian", + "servans", "servants", + "sesnors", "sensors", + "settins", "settings", + "severly", "severely", + "sexualy", "sexually", + "seziure", "seizure", + "shaddow", "shadow", + "shanghi", "shanghai", + "shaprie", "sharpie", + "shaprly", "sharply", + "sharipe", "sharpie", + "shcemes", "schemes", + "sheelpe", "sheeple", + "sheepel", "sheeple", + "shephed", "shepherd", + "sherlok", "sherlock", + "shetler", "shelter", + "shevles", "shelves", + "shfiter", "shifter", + "shieldd", "shielded", + "shiping", "shipping", + "shirely", "shirley", + "shitfer", "shifter", + "shledon", "sheldon", + "shleter", "shelter", + "shoudln", "should", + "shouldt", "shouldnt", + "shoutot", "shoutout", + "showede", "showered", + "showerd", "showered", + "shperes", "spheres", + "shriley", "shirley", + "siblins", "siblings", + "sidelen", "sideline", + "sideral", "sidereal", + "siezing", "seizing", + "siezure", "seizure", + "signfiy", "signify", + "signins", "signings", + "signles", "singles", + "silders", "sliders", + "silenty", "silently", + "similir", "similiar", + "simliar", "similar", + "simplet", "simplest", + "simpley", "simply", + "simplfy", "simplify", + "simpliy", "simplify", + "simposn", "simpson", + "simspon", "simpson", + "singals", "signals", + "singels", "singles", + "singify", "signify", + "singsog", "singsong", + "sitmuli", "stimuli", + "skecthy", "sketchy", + "skeletl", "skeletal", + "skeptis", "skeptics", + "sketchs", "sketches", + "sketpic", "skeptic", + "skpetic", "skeptic", + "sktechy", "sketchy", + "skwyard", "skyward", + "slavage", "salvage", + "slayign", "slaying", + "sldiers", "sliders", + "slefies", "selfies", + "slighly", "slightly", + "slighty", "slightly", + "slippes", "slippers", + "slippey", "slippery", + "smaples", "samples", + "smartre", "smarter", + "smaurai", "samurai", + "snadler", "sandler", + "snigles", "singles", + "snippes", "snippets", + "snodwen", "snowden", + "snwoden", "snowden", + "snycing", "syncing", + "snyergy", "synergy", + "socialy", "socially", + "sofware", "software", + "soildly", "solidly", + "soldies", "soldiers", + "soldily", "solidly", + "somaila", "somalia", + "someons", "someones", + "somethn", "somethin", + "southen", "southern", + "soveits", "soviets", + "spacebr", "spacebar", + "spainsh", "spanish", + "spansih", "spanish", + "spanwed", "spawned", + "sparkel", "sparkle", + "spartas", "spartans", + "spartsn", "spartans", + "sparyed", "sprayed", + "spawend", "spawned", + "spawnig", "spawning", + "specail", "special", + "specfic", "specific", + "specias", "specials", + "specisl", "specials", + "spectum", "spectrum", + "speechs", "speeches", + "spehres", "spheres", + "speical", "special", + "speices", "species", + "spellig", "spelling", + "spindel", "spindle", + "spiritd", "spirited", + "splaton", "splatoon", + "splittr", "splitter", + "spoiles", "spoilers", + "spoitfy", "spotify", + "spolied", "spoiled", + "sponser", "sponsor", + "sporles", "sproles", + "sporuts", "sprouts", + "spotfiy", "spotify", + "sprinke", "sprinkle", + "sproels", "sproles", + "spwaned", "spawned", + "sqaures", "squares", + "sqeuaky", "squeaky", + "sqiushy", "squishy", + "squarey", "squarely", + "squirel", "squirtle", + "squirle", "squirrel", + "squirrl", "squirrel", + "squirte", "squirtle", + "squsihy", "squishy", + "sriraca", "sriracha", + "srpouts", "sprouts", + "sryians", "syrians", + "sryinge", "syringe", + "stadius", "stadiums", + "staduim", "stadium", + "stagnat", "stagnant", + "staidum", "stadium", + "stakler", "stalker", + "stalkes", "stalkers", + "stamnia", "stamina", + "staoshi", "satoshi", + "starins", "strains", + "startde", "startled", + "startus", "startups", + "statits", "statist", + "statsit", "statist", + "statuer", "stature", + "statuse", "statutes", + "statuts", "statutes", + "stautes", "statues", + "stealty", "stealthy", + "steeles", "steelers", + "steorid", "steroid", + "steriel", "sterile", + "sterlie", "sterile", + "stickes", "stickers", + "stiring", "stirring", + "stirker", "striker", + "stirrig", "stirring", + "stitchs", "stitches", + "stlaker", "stalker", + "stlyish", "stylish", + "storeis", "stories", + "storise", "stories", + "stormde", "stormed", + "straigt", "straight", + "straind", "strained", + "streamd", "streamed", + "stregth", "strength", + "strengh", "strength", + "streoid", "steroid", + "stresss", "stresses", + "strians", "strains", + "stricty", "strictly", + "striekr", "striker", + "stromed", "stormed", + "stubbon", "stubborn", + "studing", "studying", + "stuidos", "studios", + "stunami", "tsunami", + "stupidr", "stupider", + "stupidy", "stupidly", + "stupire", "stupider", + "suasage", "sausage", + "subisdy", "subsidy", + "subjest", "subjects", + "subtiel", "subtitle", + "succede", "succeed", + "succeds", "succeeds", + "succees", "succeeds", + "succesd", "succeeds", + "suceeds", "succeeds", + "suddeny", "suddenly", + "suefull", "usefull", + "sufferd", "suffered", + "summonr", "summoner", + "summore", "summoner", + "sunggle", "snuggle", + "sunifre", "sunfire", + "superme", "supreme", + "suposed", "supposed", + "suposes", "supposes", + "suppoed", "supposed", + "suppost", "supports", + "suprass", "surpass", + "supress", "suppress", + "suprisd", "suprised", + "suprise", "surprise", + "suprize", "surprise", + "supsend", "suspend", + "suround", "surround", + "surpeme", "supreme", + "surroud", "surround", + "sweidsh", "swedish", + "swiflty", "swiftly", + "swiming", "swimming", + "switchs", "switches", + "switfly", "swiftly", + "swnasea", "swansea", + "sycning", "syncing", + "sycther", "scyther", + "syirans", "syrians", + "sykward", "skyward", + "syllabe", "syllable", + "symetry", "symmetry", + "symmety", "symmetry", + "symobls", "symbols", + "sympaty", "sympathy", + "symtpom", "symptom", + "synegry", "synergy", + "synoynm", "synonym", + "sypmtom", "symptom", + "syracue", "syracuse", + "syrains", "syrians", + "sysadmn", "sysadmin", + "systemc", "systemic", + "sytlish", "stylish", + "tabacco", "tobacco", + "tailban", "taliban", + "tailord", "tailored", + "talbian", "taliban", + "tallets", "tallest", + "tangeld", "tangled", + "tanlged", "tangled", + "targetd", "targeted", + "taryvon", "trayvon", + "teached", "taught", + "teaspon", "teaspoon", + "techeis", "techies", + "tehcies", "techies", + "temepst", "tempest", + "tempels", "temples", + "tempets", "tempest", + "templas", "templars", + "tempset", "tempest", + "tenacle", "tentacle", + "tendacy", "tendency", + "tequlia", "tequila", + "tesitfy", "testify", + "testice", "testicle", + "teusday", "tuesday", + "thankyu", "thankyou", + "thearpy", "therapy", + "theistc", "theistic", + "theives", "thieves", + "themsef", "themself", + "therefo", "thereof", + "therien", "therein", + "theroem", "theorem", + "thesits", "theists", + "thiests", "theists", + "thirldy", "thirdly", + "thirten", "thirteen", + "thirtsy", "thirsty", + "thoerem", "theorem", + "thorats", "throats", + "thornes", "thrones", + "thoruim", "thorium", + "thoughs", "thoughts", + "threadd", "threaded", + "threeof", "thereof", + "thridly", "thirdly", + "thristy", "thirsty", + "throast", "throats", + "throium", "thorium", + "thryoid", "thyroid", + "thyorid", "thyroid", + "thyriod", "thyroid", + "tigther", "tighter", + "tiolets", "toilets", + "tirdent", "trident", + "titanim", "titanium", + "tlaking", "talking", + "tobbaco", "tobacco", + "toliets", "toilets", + "tolkein", "tolkien", + "tomatos", "tomatoes", + "tongiht", "tonight", + "tonuges", "tongues", + "toppins", "toppings", + "torando", "tornado", + "torndao", "tornado", + "torpdeo", "torpedo", + "torrest", "torrents", + "tortila", "tortilla", + "toruney", "tourney", + "toubles", "troubles", + "touchda", "touchpad", + "tounrey", "tourney", + "tourisy", "touristy", + "tourits", "tourist", + "tournes", "tourneys", + "toursim", "tourism", + "toursit", "tourist", + "towords", "towards", + "trackes", "trackers", + "trailes", "trailers", + "traines", "trainers", + "trainig", "training", + "tralier", "trailer", + "tratior", "traitor", + "traveld", "traveled", + "travere", "traverse", + "travesy", "travesty", + "travles", "travels", + "treasue", "treasure", + "treatis", "treaties", + "tremelo", "tremolo", + "trendig", "trending", + "trialer", "trailer", + "triange", "triangle", + "triator", "traitor", + "trickey", "trickery", + "tridnet", "trident", + "trimuph", "triumph", + "trinkes", "trinkets", + "trinkst", "trinkets", + "trintiy", "trinity", + "triolgy", "trilogy", + "troleld", "trolled", + "troling", "trolling", + "tronado", "tornado", + "tropedo", "torpedo", + "trudnle", "trundle", + "truimph", "triumph", + "trukish", "turkish", + "trundel", "trundle", + "trunlde", "trundle", + "tryahrd", "tryhard", + "tryavon", "trayvon", + "tsamina", "stamina", + "tsnuami", "tsunami", + "tsuanmi", "tsunami", + "tsunmai", "tsunami", + "tuesdsy", "tuesdays", + "tunnles", "tunnels", + "turbins", "turbines", + "turksih", "turkish", + "turltes", "turtles", + "turrest", "turrets", + "turtels", "turtles", + "tuseday", "tuesday", + "tusnami", "tsunami", + "tutrles", "turtles", + "twiligt", "twilight", + "tyelnol", "tylenol", + "typcial", "typical", + "tyrhard", "tryhard", + "tyrrany", "tyranny", + "udpated", "updated", + "uesfull", "usefull", + "ugprade", "upgrade", + "ukarine", "ukraine", + "ukranie", "ukraine", + "ukriane", "ukraine", + "ultimae", "ultimate", + "umbrela", "umbrella", + "unahppy", "unhappy", + "unbannd", "unbanned", + "underog", "undergo", + "unfairy", "unfairly", + "ungoldy", "ungodly", + "unicors", "unicorns", + "uniquey", "uniquely", + "unknwon", "unknown", + "unkonwn", "unknown", + "unlcean", "unclean", + "unlcoks", "unlocks", + "unlcuky", "unlucky", + "unlikey", "unlikely", + "unopend", "unopened", + "unprone", "unproven", + "unusabe", "unusable", + "unworty", "unworthy", + "upgarde", "upgrade", + "upgrads", "upgrades", + "uplaods", "uploads", + "upsteam", "upstream", + "urainum", "uranium", + "uranuim", "uranium", + "uretrha", "urethra", + "urkaine", "ukraine", + "urnaium", "uranium", + "urugauy", "uruguay", + "usefull", "useful", + "usefuly", "usefully", + "utiltiy", "utility", + "utopain", "utopian", + "utpoian", "utopian", + "vaccins", "vaccines", + "vaccume", "vacuum", + "vageuly", "vaguely", + "vaguley", "vaguely", + "vairant", "variant", + "valenca", "valencia", + "valetta", "valletta", + "valkyre", "valkyrie", + "valuabe", "valuable", + "valuble", "valuable", + "vampirs", "vampires", + "vanguad", "vanguard", + "varaint", "variant", + "vareity", "variety", + "varians", "variants", + "varient", "variant", + "varisty", "varsity", + "varitey", "variety", + "varstiy", "varsity", + "vasalls", "vassals", + "vasslas", "vassals", + "vaugely", "vaguely", + "vecotrs", "vectors", + "vectros", "vectors", + "veitnam", "vietnam", + "veiwers", "viewers", + "vendeta", "vendetta", + "verbaly", "verbally", + "verical", "vertical", + "verious", "various", + "verison", "version", + "veritgo", "vertigo", + "versoin", "version", + "vertgio", "vertigo", + "vessles", "vessels", + "vetween", "between", + "viatmin", "vitamin", + "vibratr", "vibrator", + "vicitms", "victims", + "vientam", "vietnam", + "vigrins", "virgins", + "vikigns", "vikings", + "villian", "villain", + "villify", "vilify", + "virbate", "vibrate", + "virigns", "virgins", + "virtiol", "vitriol", + "virutal", "virtual", + "virutes", "virtues", + "visable", "visible", + "visably", "visibly", + "visbily", "visibly", + "visting", "visiting", + "vistors", "visitors", + "vitaliy", "vitality", + "vitamis", "vitamins", + "vitenam", "vietnam", + "vitirol", "vitriol", + "vitmain", "vitamin", + "vitroil", "vitriol", + "vitrual", "virtual", + "vitrues", "virtues", + "volatge", "voltage", + "volumne", "volume", + "votlage", "voltage", + "vrigins", "virgins", + "waclott", "walcott", + "wacther", "watcher", + "waitres", "waiters", + "waktins", "watkins", + "warcrat", "warcraft", + "wardobe", "wardrobe", + "wariwck", "warwick", + "warrany", "warranty", + "warrent", "warrant", + "warrios", "warriors", + "warwcik", "warwick", + "wathcer", "watcher", + "watiers", "waiters", + "waviers", "waivers", + "wawrick", "warwick", + "wayword", "wayward", + "webapge", "webpage", + "webiste", "website", + "webstie", "website", + "weigths", "weights", + "weilded", "wielded", + "weirldy", "weirdly", + "weirods", "weirdos", + "welathy", "wealthy", + "wendsay", "wednesday", + "wensday", "wednesday", + "wepbage", "webpage", + "weridly", "weirdly", + "weridos", "weirdos", + "werstle", "wrestle", + "wesbite", "website", + "whaeton", "wheaton", + "whipser", "whisper", + "whislte", "whistle", + "whistel", "whistle", + "whitsle", "whistle", + "whsiper", "whisper", + "wiaters", "waiters", + "wiavers", "waivers", + "widgest", "widgets", + "wieghts", "weights", + "wigdets", "widgets", + "windosr", "windsor", + "winnins", "winnings", + "winsdor", "windsor", + "wintson", "winston", + "wirting", "writing", + "wisnton", "winston", + "withces", "witches", + "witheld", "withheld", + "withing", "within", + "withold", "withhold", + "wlacott", "walcott", + "wokring", "working", + "workins", "workings", + "woudlnt", "wouldnt", + "woudlve", "wouldve", + "woulndt", "wouldnt", + "wreslte", "wrestle", + "wroking", "working", + "wtiches", "witches", + "wupport", "support", + "yaching", "yachting", + "younget", "youngest", + "youseff", "yousef", + "youself", "yourself", + "zaelots", "zealots", + "zealtos", "zealots", + "zelaots", "zealots", + "zelaous", "zealous", + "zimbabe", "zimbabwe", + "zionsim", "zionism", + "zionsit", "zionist", + "zoinism", "zionism", + "zoinist", "zionist", + "abbout", "about", + "abilty", "ability", + "absail", "abseil", + "abutts", "abuts", + "achive", "achieve", + "acused", "accused", + "addopt", "adopt", + "addres", "address", + "adress", "address", + "aeriel", "aerial", + "affort", "afford", + "agains", "against", + "aginst", "against", + "ahppen", "happen", + "aiport", "airport", + "aisian", "asian", + "albiet", "albeit", + "alchol", "alcohol", + "aledge", "allege", + "aleged", "alleged", + "allign", "align", + "almsot", "almost", + "alomst", "almost", + "alowed", "allowed", + "alwasy", "always", + "alwyas", "always", + "amking", "making", + "ammend", "amend", + "amoung", "among", + "aplied", "applied", + "appart", "apart", + "aquire", "acquire", + "aready", "already", + "arised", "arose", + "arival", "arrival", + "arrary", "array", + "artice", "article", + "asetic", "ascetic", + "asside", "aside", + "attemp", "attempt", + "attemt", "attempt", + "auther", "author", + "awared", "awarded", + "bedore", "before", + "beeing", "being", + "befoer", "before", + "beggin", "begin", + "beleif", "belief", + "belive", "believe", + "beteen", "between", + "betwen", "between", + "beween", "between", + "bianry", "binary", + "boyant", "buoyant", + "broady", "broadly", + "buddah", "buddha", + "buring", "burying", + "carcas", "carcass", + "casion", "caisson", + "casued", "caused", + "casues", "causes", + "ceasar", "caesar", + "cencus", "census", + "censur", "censor", + "cheifs", "chiefs", + "circut", "circuit", + "clasic", "classic", + "coform", "conform", + "comany", "company", + "coucil", "council", + "curent", "current", + "densly", "densely", + "deside", "decide", + "devels", "delves", + "devide", "divide", + "dieing", "dying", + "divice", "device", + "doulbe", "double", + "dreasm", "dreams", + "duting", "during", + "ealier", "earlier", + "eearly", "early", + "efford", "effort", + "emited", "emitted", + "emnity", "enmity", + "enduce", "induce", + "enlish", "english", + "erally", "orally", + "eratic", "erratic", + "ethose", "those", + "exampt", "exempt", + "excact", "exact", + "excell", "excel", + "exerpt", "excerpt", + "exinct", "extinct", + "expell", "expel", + "expoch", "epoch", + "extint", "extinct", + "facist", "fascist", + "faught", "fought", + "finaly", "finally", + "forsaw", "foresaw", + "fougth", "fought", + "fourty", "forty", + "foward", "forward", + "freind", "friend", + "fromed", "formed", + "fufill", "fulfill", + "futher", "further", + "gardai", "gardaí", + "geting", "getting", + "ghandi", "gandhi", + "glight", "flight", + "gloabl", "global", + "godess", "goddess", + "guilia", "giulia", + "guilio", "giulio", + "habeus", "habeas", + "harras", "harass", + "hatian", "haitian", + "heared", "heard", + "hertzs", "hertz", + "hieght", "height", + "higest", "highest", + "higway", "highway", + "honory", "honorary", + "howver", "however", + "hstory", "history", + "hunman", "human", + "husban", "husband", + "hvaing", "having", + "illess", "illness", + "ilness", "illness", + "imagin", "imagine", + "imense", "immense", + "includ", "include", + "inital", "initial", + "interm", "interim", + "intial", "initial", + "invlid", "invalid", + "iunior", "junior", + "jaques", "jacques", + "jospeh", "joseph", + "jouney", "journey", + "klenex", "kleenex", + "labled", "labelled", + "largst", "largest", + "larrry", "larry", + "lefted", "left", + "lenght", "length", + "lerans", "learns", + "liason", "liaison", + "libary", "library", + "lieing", "lying", + "lieved", "lived", + "littel", "little", + "livley", "lively", + "lonley", "lonely", + "mailny", "mainly", + "markes", "marks", + "mileau", "milieu", + "milion", "million", + "millon", "million", + "misile", "missile", + "missen", "mizzen", + "missle", "missile", + "mkaing", "making", + "moderm", "modem", + "moreso", "more", + "mounth", "month", + "myraid", "myriad", + "naieve", "naive", + "nestin", "nesting", + "nineth", "ninth", + "noveau", "nouveau", + "occour", "occur", + "occurr", "occur", + "offred", "offered", + "omited", "omitted", + "ouevre", "oeuvre", + "oxigen", "oxygen", + "p0enis", "penis", + "packge", "package", + "peaple", "people", + "pensle", "pencil", + "peopel", "people", + "peotry", "poetry", + "perade", "parade", + "persan", "person", + "persue", "pursue", + "plateu", "plateau", + "poenis", "penis", + "poisin", "poison", + "polute", "pollute", + "posess", "possess", + "posion", "poison", + "prairy", "prairie", + "prarie", "prairie", + "preiod", "period", + "privte", "private", + "proces", "process", + "proove", "prove", + "psuedo", "pseudo", + "psyhic", "psychic", + "pucini", "puccini", + "pumkin", "pumpkin", + "puting", "putting", + "pyscic", "psychic", + "quizes", "quizzes", + "quuery", "query", + "racaus", "raucous", + "radify", "ratify", + "raelly", "really", + "reacll", "recall", + "realyl", "really", + "reched", "reached", + "recide", "reside", + "recrod", "record", + "refect", "reflect", + "relaly", "really", + "renewl", "renewal", + "retuns", "returns", + "reveiw", "review", + "rhymme", "rhyme", + "rigeur", "rigueur", + "rocord", "record", + "rougly", "roughly", + "runing", "running", + "rythem", "rhythm", + "rythim", "rhythm", + "saftey", "safety", + "salery", "salary", + "satisy", "satisfy", + "satric", "satiric", + "saught", "sought", + "scince", "science", + "scirpt", "script", + "seceed", "succeed", + "seinor", "senior", + "sepina", "subpoena", + "sevice", "service", + "shamen", "shaman", + "sheild", "shield", + "shiped", "shipped", + "shorly", "shortly", + "shoudl", "should", + "shreak", "shriek", + "siezed", "seized", + "sixtin", "sistine", + "skiped", "skipped", + "sneeks", "sneaks", + "somene", "someone", + "soruce", "source", + "soudns", "sounds", + "sourth", "south", + "speach", "speech", + "spects", "aspects", + "spoace", "space", + "sqaure", "square", + "staion", "station", + "stange", "strange", + "stilus", "stylus", + "stirrs", "stirs", + "stopry", "story", + "strnad", "strand", + "studdy", "study", + "suceed", "succeed", + "sucess", "success", + "sucide", "suicide", + "sumary", "summary", + "suport", "support", + "supose", "suppose", + "surfce", "surface", + "surley", "surly", + "swaers", "swears", + "swepth", "swept", + "talekd", "talked", + "theese", "these", + "therby", "thereby", + "thigns", "things", + "thigsn", "things", + "thikns", "thinks", + "thiunk", "think", + "thnigs", "things", + "threee", "three", + "tkaing", "taking", + "tounge", "tongue", + "tourch", "torch", + "towrad", "toward", + "trafic", "traffic", + "troups", "troupes", + "truely", "truly", + "twelth", "twelfth", + "tyrany", "tyranny", + "unabel", "unable", + "unkown", "unknown", + "unmont", "unmount", + "unmout", "unmount", + "untill", "until", + "usally", "usually", + "useage", "usage", + "useing", "using", + "usualy", "usually", + "vaccum", "vacuum", + "variey", "variety", + "varing", "varying", + "varity", "variety", + "vasall", "vassal", + "vigeur", "vigueur", + "villin", "villain", + "vreity", "variety", + "vriety", "variety", + "whants", "wants", + "wheras", "whereas", + "wheter", "whether", + "wholey", "wholly", + "whther", "whether", + "wnated", "wanted", + "writen", "written", + "yaerly", "yearly", + "yotube", "youtube", + "zeebra", "zebra", + "abotu", "about", + "adres", "address", + "afair", "affair", + "agian", "again", + "agina", "again", + "agred", "agreed", + "alege", "allege", + "alsot", "also", + "altho", "although", + "amung", "among", + "anual", "annual", + "aroud", "around", + "arund", "around", + "asign", "assign", + "assit", "assist", + "asume", "assume", + "atain", "attain", + "autor", "author", + "baout", "about", + "blaim", "blame", + "boaut", "bout", + "boook", "book", + "borke", "broke", + "breif", "brief", + "caost", "coast", + "casue", "cause", + "chasr", "chaser", + "cheif", "chief", + "chuch", "church", + "claer", "clear", + "clera", "clear", + "coudl", "could", + "crowm", "crown", + "deram", "dram", + "diety", "deity", + "doens", "does", + "doign", "doing", + "donig", "doing", + "drnik", "drink", + "durig", "during", + "earnt", "earned", + "eigth", "eighth", + "eiter", "either", + "emtpy", "empty", + "endig", "ending", + "eveyr", "every", + "exept", "except", + "eyars", "years", + "eyasr", "years", + "fiels", "fields", + "firts", "flirts", + "fleed", "fled", + "fomed", "formed", + "foucs", "focus", + "foudn", "found", + "fouth", "fourth", + "frome", "from", + "ganes", "games", + "gaurd", "guard", + "gerat", "great", + "gogin", "going", + "goign", "going", + "gonig", "going", + "graet", "great", + "greif", "grief", + "gropu", "group", + "guage", "gauge", + "hapen", "happen", + "herad", "heard", + "heroe", "hero", + "higer", "higher", + "housr", "hours", + "htere", "there", + "htikn", "think", + "hting", "thing", + "htink", "think", + "hwihc", "which", + "hwile", "while", + "hwole", "whole", + "idaes", "ideas", + "idesa", "ideas", + "ihaca", "ithaca", + "knwos", "knows", + "konws", "knows", + "lastr", "last", + "lavae", "larvae", + "layed", "laid", + "leage", "league", + "leanr", "lean", + "leran", "learn", + "levle", "level", + "lible", "libel", + "liekd", "liked", + "liuke", "like", + "lmits", "limits", + "lonly", "lonely", + "lukid", "likud", + "lybia", "libya", + "maked", "marked", + "makse", "makes", + "mamal", "mammal", + "mileu", "milieu", + "mkaes", "makes", + "modle", "model", + "moent", "moment", + "moeny", "money", + "monts", "months", + "movei", "movie", + "muder", "murder", + "mysef", "myself", + "neice", "niece", + "ninty", "ninety", + "ocurr", "occur", + "oging", "going", + "opose", "oppose", + "orded", "ordered", + "orgin", "origin", + "otehr", "other", + "ouput", "output", + "owudl", "would", + "paide", "paid", + "palce", "place", + "pased", "passed", + "payed", "paid", + "peice", "piece", + "peoms", "poems", + "poety", "poetry", + "pwoer", "power", + "qtuie", "quite", + "qutie", "quite", + "realy", "really", + "repid", "rapid", + "rised", "raised", + "rulle", "rule", + "rwite", "write", + "rythm", "rhythm", + "safty", "safety", + "scoll", "scroll", + "seach", "search", + "seige", "siege", + "seing", "seeing", + "sence", "sense", + "sicne", "since", + "sieze", "seize", + "sinse", "sines", + "slowy", "slowly", + "snese", "sneeze", + "soley", "solely", + "sotry", "story", + "sotyr", "satyr", + "soudn", "sound", + "sould", "could", + "spred", "spread", + "stlye", "style", + "stong", "strong", + "stoyr", "story", + "strat", "start", + "stroy", "story", + "suppy", "supply", + "swaer", "swear", + "syrap", "syrup", + "sytem", "system", + "sytle", "style", + "tatoo", "tattoo", + "thast", "that", + "theif", "thief", + "theri", "their", + "thgat", "that", + "thier", "their", + "thign", "thing", + "thikn", "think", + "thnig", "thing", + "thrid", "third", + "thsoe", "those", + "thyat", "that", + "tihkn", "think", + "timne", "time", + "tiome", "time", + "tkaes", "takes", + "todya", "today", + "tyhat", "that", + "unsed", "used", + "weild", "wield", + "whant", "want", + "whcih", "which", + "whihc", "which", + "whith", "with", + "whlch", "which", + "wholy", "wholly", + "wierd", "weird", + "wille", "will", + "willk", "will", + "withh", "with", + "witht", "with", + "wiull", "will", + "wnats", "wants", + "wohle", "whole", + "worls", "world", + "woudl", "would", + "wriet", "write", + "wroet", "wrote", + "yaers", "years", + "yatch", "yacht", + "yearm", "year", + "yeasr", "years", + "yeild", "yield", + "yeras", "years", + "yersa", "years", + "agin", "again", + "agre", "agree", + "ahev", "have", + "ahve", "have", + "alse", "else", + "amke", "make", + "anbd", "and", + "andd", "and", + "apon", "upon", + "aslo", "also", + "awya", "away", + "bakc", "back", + "bcak", "back", + "clas", "class", + "cpoy", "coy", + "cxan", "cyan", + "daed", "dead", + "dael", "deal", + "diea", "idea", + "doub", "doubt", + "dyas", "dryas", + "eahc", "each", + "efel", "evil", + "eles", "eels", + "ened", "need", + "enxt", "next", + "esle", "else", + "eyar", "year", + "fatc", "fact", + "fidn", "find", + "fomr", "from", + "grwo", "grow", + "haev", "have", + "halp", "help", + "holf", "hold", + "hten", "then", + "htey", "they", + "htis", "this", + "hvae", "have", + "hvea", "have", + "inot", "into", + "iwll", "will", + "iwth", "with", + "jstu", "just", + "jsut", "just", + "knwo", "know", + "konw", "know", + "kwno", "know", + "liek", "like", + "loev", "love", + "lveo", "love", + "lvoe", "love", + "mkae", "make", + "mkea", "make", + "mroe", "more", + "nkow", "know", + "nkwo", "know", + "nmae", "name", + "noth", "north", + "nowe", "now", + "omre", "more", + "onot", "note", + "onyl", "only", + "owrk", "work", + "peom", "poem", + "pich", "pitch", + "rela", "real", + "sasy", "says", + "smae", "same", + "smoe", "some", + "soem", "some", + "sohw", "show", + "stpo", "stop", + "suop", "soup", + "syas", "says", + "tahn", "than", + "taht", "that", + "tast", "taste", + "tath", "that", + "tehy", "they", + "tghe", "the", + "ther", "there", + "thge", "the", + "thna", "than", + "thne", "then", + "thsi", "this", + "thta", "that", + "tiem", "time", + "tihs", "this", + "tjhe", "the", + "tkae", "take", + "tood", "todo", + "tust", "trust", + "twon", "town", + "twpo", "two", + "tyhe", "they", + "uise", "use", + "vell", "well", + "veyr", "very", + "vrey", "very", + "vyer", "very", + "vyre", "very", + "waht", "what", + "wass", "was", + "watn", "want", + "weas", "was", + "wehn", "when", + "whic", "which", + "whta", "what", + "wich", "which", + "wief", "wife", + "wiew", "view", + "wiht", "with", + "witn", "with", + "wnat", "want", + "wokr", "work", + "wrok", "work", + "wtih", "with", + "yaer", "year", + "yera", "year", + "yrea", "year", + "ytou", "you", + "adn", "and", + "ect", "etc", + "nto", "not", + "teh", "the", + "thn", "then", + "tje", "the", + "whn", "when", + "wih", "with", + "yuo", "you", +} + +// DictAmerican converts UK spellings to US spellings +var DictAmerican = []string{ + "institutionalisation", "institutionalization", + "internationalisation", "internationalization", + "professionalisation", "professionalization", + "compartmentalising", "compartmentalizing", + "institutionalising", "institutionalizing", + "internationalising", "internationalizing", + "compartmentalised", "compartmentalized", + "compartmentalises", "compartmentalizes", + "decriminalisation", "decriminalization", + "denationalisation", "denationalization", + "fictionalisations", "fictionalizations", + "institutionalised", "institutionalized", + "institutionalises", "institutionalizes", + "intellectualising", "intellectualizing", + "internationalised", "internationalized", + "internationalises", "internationalizes", + "pedestrianisation", "pedestrianization", + "professionalising", "professionalizing", + "archaeologically", "archeologically", + "compartmentalise", "compartmentalize", + "decentralisation", "decentralization", + "demilitarisation", "demilitarization", + "externalisations", "externalizations", + "fictionalisation", "fictionalization", + "institutionalise", "institutionalize", + "intellectualised", "intellectualized", + "intellectualises", "intellectualizes", + "internationalise", "internationalize", + "nationalisations", "nationalizations", + "palaeontologists", "paleontologists", + "professionalised", "professionalized", + "professionalises", "professionalizes", + "rationalisations", "rationalizations", + "sensationalising", "sensationalizing", + "sentimentalising", "sentimentalizing", + "acclimatisation", "acclimatization", + "bougainvillaeas", "bougainvilleas", + "commercialising", "commercializing", + "conceptualising", "conceptualizing", + "contextualising", "contextualizing", + "crystallisation", "crystallization", + "decriminalising", "decriminalizing", + "democratisation", "democratization", + "denationalising", "denationalizing", + "depersonalising", "depersonalizing", + "desensitisation", "desensitization", + "destabilisation", "destabilization", + "disorganisation", "disorganization", + "extemporisation", "extemporization", + "externalisation", "externalization", + "familiarisation", "familiarization", + "generalisations", "generalizations", + "hospitalisation", "hospitalization", + "individualising", "individualizing", + "industrialising", "industrializing", + "intellectualise", "intellectualize", + "internalisation", "internalization", + "manoeuvrability", "maneuverability", + "marginalisation", "marginalization", + "materialisation", "materialization", + "miniaturisation", "miniaturization", + "nationalisation", "nationalization", + "neighbourliness", "neighborliness", + "overemphasising", "overemphasizing", + "palaeontologist", "paleontologist", + "particularising", "particularizing", + "pedestrianising", "pedestrianizing", + "professionalise", "professionalize", + "psychoanalysing", "psychoanalyzing", + "rationalisation", "rationalization", + "reorganisations", "reorganizations", + "revolutionising", "revolutionizing", + "sensationalised", "sensationalized", + "sensationalises", "sensationalizes", + "sentimentalised", "sentimentalized", + "sentimentalises", "sentimentalizes", + "specialisations", "specializations", + "standardisation", "standardization", + "synchronisation", "synchronization", + "systematisation", "systematization", + "aggrandisement", "aggrandizement", + "anaesthetising", "anesthetizing", + "archaeological", "archeological", + "archaeologists", "archeologists", + "bougainvillaea", "bougainvillea", + "characterising", "characterizing", + "collectivising", "collectivizing", + "commercialised", "commercialized", + "commercialises", "commercializes", + "conceptualised", "conceptualized", + "conceptualises", "conceptualizes", + "contextualised", "contextualized", + "contextualises", "contextualizes", + "decentralising", "decentralizing", + "decriminalised", "decriminalized", + "decriminalises", "decriminalizes", + "dehumanisation", "dehumanization", + "demilitarising", "demilitarizing", + "demobilisation", "demobilization", + "demoralisation", "demoralization", + "denationalised", "denationalized", + "denationalises", "denationalizes", + "depersonalised", "depersonalized", + "depersonalises", "depersonalizes", + "disembowelling", "disemboweling", + "dramatisations", "dramatizations", + "editorialising", "editorializing", + "encyclopaedias", "encyclopedias", + "fictionalising", "fictionalizing", + "fraternisation", "fraternization", + "generalisation", "generalization", + "gynaecological", "gynecological", + "gynaecologists", "gynecologists", + "haematological", "hematological", + "haematologists", "hematologists", + "immobilisation", "immobilization", + "individualised", "individualized", + "individualises", "individualizes", + "industrialised", "industrialized", + "industrialises", "industrializes", + "liberalisation", "liberalization", + "monopolisation", "monopolization", + "naturalisation", "naturalization", + "neighbourhoods", "neighborhoods", + "neutralisation", "neutralization", + "organisational", "organizational", + "outmanoeuvring", "outmaneuvering", + "overemphasised", "overemphasized", + "overemphasises", "overemphasizes", + "paediatricians", "pediatricians", + "particularised", "particularized", + "particularises", "particularizes", + "pasteurisation", "pasteurization", + "pedestrianised", "pedestrianized", + "pedestrianises", "pedestrianizes", + "philosophising", "philosophizing", + "politicisation", "politicization", + "popularisation", "popularization", + "pressurisation", "pressurization", + "prioritisation", "prioritization", + "privatisations", "privatizations", + "propagandising", "propagandizing", + "psychoanalysed", "psychoanalyzed", + "psychoanalyses", "psychoanalyzes", + "regularisation", "regularization", + "reorganisation", "reorganization", + "revolutionised", "revolutionized", + "revolutionises", "revolutionizes", + "secularisation", "secularization", + "sensationalise", "sensationalize", + "sentimentalise", "sentimentalize", + "serialisations", "serializations", + "specialisation", "specialization", + "sterilisations", "sterilizations", + "stigmatisation", "stigmatization", + "transistorised", "transistorized", + "unrecognisable", "unrecognizable", + "visualisations", "visualizations", + "westernisation", "westernization", + "accessorising", "accessorizing", + "acclimatising", "acclimatizing", + "amortisations", "amortizations", + "amphitheatres", "amphitheaters", + "anaesthetised", "anesthetized", + "anaesthetises", "anesthetizes", + "anaesthetists", "anesthetists", + "archaeologist", "archeologist", + "backpedalling", "backpedaling", + "behaviourists", "behaviorists", + "breathalysers", "breathalyzers", + "breathalysing", "breathalyzing", + "callisthenics", "calisthenics", + "cannibalising", "cannibalizing", + "characterised", "characterized", + "characterises", "characterizes", + "circularising", "circularizing", + "clarinettists", "clarinetists", + "collectivised", "collectivized", + "collectivises", "collectivizes", + "commercialise", "commercialize", + "computerising", "computerizing", + "conceptualise", "conceptualize", + "contextualise", "contextualize", + "criminalising", "criminalizing", + "crystallising", "crystallizing", + "decentralised", "decentralized", + "decentralises", "decentralizes", + "decriminalise", "decriminalize", + "demilitarised", "demilitarized", + "demilitarises", "demilitarizes", + "democratising", "democratizing", + "denationalise", "denationalize", + "depersonalise", "depersonalize", + "desensitising", "desensitizing", + "destabilising", "destabilizing", + "disembowelled", "disemboweled", + "dishonourable", "dishonorable", + "dishonourably", "dishonorably", + "dramatisation", "dramatization", + "editorialised", "editorialized", + "editorialises", "editorializes", + "encyclopaedia", "encyclopedia", + "encyclopaedic", "encyclopedic", + "extemporising", "extemporizing", + "externalising", "externalizing", + "familiarising", "familiarizing", + "fertilisation", "fertilization", + "fictionalised", "fictionalized", + "fictionalises", "fictionalizes", + "formalisation", "formalization", + "fossilisation", "fossilization", + "globalisation", "globalization", + "gynaecologist", "gynecologist", + "haematologist", "hematologist", + "haemophiliacs", "hemophiliacs", + "haemorrhaging", "hemorrhaging", + "harmonisation", "harmonization", + "hospitalising", "hospitalizing", + "hypothesising", "hypothesizing", + "immortalising", "immortalizing", + "individualise", "individualize", + "industrialise", "industrialize", + "internalising", "internalizing", + "marginalising", "marginalizing", + "materialising", "materializing", + "mechanisation", "mechanization", + "memorialising", "memorializing", + "miniaturising", "miniaturizing", + "miscatalogued", "miscataloged", + "misdemeanours", "misdemeanors", + "multicoloured", "multicolored", + "nationalising", "nationalizing", + "neighbourhood", "neighborhood", + "normalisation", "normalization", + "organisations", "organizations", + "outmanoeuvred", "outmaneuvered", + "outmanoeuvres", "outmaneuvers", + "overemphasise", "overemphasize", + "paediatrician", "pediatrician", + "palaeontology", "paleontology", + "particularise", "particularize", + "passivisation", "passivization", + "patronisingly", "patronizingly", + "pedestrianise", "pedestrianize", + "personalising", "personalizing", + "philosophised", "philosophized", + "philosophises", "philosophizes", + "privatisation", "privatization", + "propagandised", "propagandized", + "propagandises", "propagandizes", + "proselytisers", "proselytizers", + "proselytising", "proselytizing", + "psychoanalyse", "psychoanalyze", + "pulverisation", "pulverization", + "rationalising", "rationalizing", + "reconnoitring", "reconnoitering", + "revolutionise", "revolutionize", + "romanticising", "romanticizing", + "serialisation", "serialization", + "socialisation", "socialization", + "stabilisation", "stabilization", + "standardising", "standardizing", + "sterilisation", "sterilization", + "subsidisation", "subsidization", + "synchronising", "synchronizing", + "systematising", "systematizing", + "tantalisingly", "tantalizingly", + "underutilised", "underutilized", + "victimisation", "victimization", + "visualisation", "visualization", + "vocalisations", "vocalizations", + "vulgarisation", "vulgarization", + "accessorised", "accessorized", + "accessorises", "accessorizes", + "acclimatised", "acclimatized", + "acclimatises", "acclimatizes", + "amortisation", "amortization", + "amphitheatre", "amphitheater", + "anaesthetics", "anesthetics", + "anaesthetise", "anesthetize", + "anaesthetist", "anesthetist", + "antagonising", "antagonizing", + "appetisingly", "appetizingly", + "backpedalled", "backpedaled", + "bastardising", "bastardizing", + "behaviourism", "behaviorism", + "behaviourist", "behaviorist", + "bowdlerising", "bowdlerizing", + "breathalysed", "breathalyzed", + "breathalyser", "breathalyzer", + "breathalyses", "breathalyzes", + "cannibalised", "cannibalized", + "cannibalises", "cannibalizes", + "capitalising", "capitalizing", + "caramelising", "caramelizing", + "categorising", "categorizing", + "centigrammes", "centigrams", + "centralising", "centralizing", + "centrepieces", "centerpieces", + "characterise", "characterize", + "circularised", "circularized", + "circularises", "circularizes", + "clarinettist", "clarinetist", + "collectivise", "collectivize", + "colonisation", "colonization", + "computerised", "computerized", + "computerises", "computerizes", + "criminalised", "criminalized", + "criminalises", "criminalizes", + "crystallised", "crystallized", + "crystallises", "crystallizes", + "decentralise", "decentralize", + "dehumanising", "dehumanizing", + "demilitarise", "demilitarize", + "demobilising", "demobilizing", + "democratised", "democratized", + "democratises", "democratizes", + "demoralising", "demoralizing", + "desensitised", "desensitized", + "desensitises", "desensitizes", + "destabilised", "destabilized", + "destabilises", "destabilizes", + "discolouring", "discoloring", + "dishonouring", "dishonoring", + "disorganised", "disorganized", + "editorialise", "editorialize", + "endeavouring", "endeavoring", + "equalisation", "equalization", + "evangelising", "evangelizing", + "extemporised", "extemporized", + "extemporises", "extemporizes", + "externalised", "externalized", + "externalises", "externalizes", + "familiarised", "familiarized", + "familiarises", "familiarizes", + "fictionalise", "fictionalize", + "finalisation", "finalization", + "fraternising", "fraternizing", + "generalising", "generalizing", + "haemophiliac", "hemophiliac", + "haemorrhaged", "hemorrhaged", + "haemorrhages", "hemorrhages", + "haemorrhoids", "hemorrhoids", + "homoeopathic", "homeopathic", + "homogenising", "homogenizing", + "hospitalised", "hospitalized", + "hospitalises", "hospitalizes", + "hypothesised", "hypothesized", + "hypothesises", "hypothesizes", + "idealisation", "idealization", + "immobilisers", "immobilizers", + "immobilising", "immobilizing", + "immortalised", "immortalized", + "immortalises", "immortalizes", + "immunisation", "immunization", + "initialising", "initializing", + "internalised", "internalized", + "internalises", "internalizes", + "jeopardising", "jeopardizing", + "legalisation", "legalization", + "legitimising", "legitimizing", + "liberalising", "liberalizing", + "manoeuvrable", "maneuverable", + "manoeuvrings", "maneuverings", + "marginalised", "marginalized", + "marginalises", "marginalizes", + "marvellously", "marvelously", + "materialised", "materialized", + "materialises", "materializes", + "maximisation", "maximization", + "memorialised", "memorialized", + "memorialises", "memorializes", + "metabolising", "metabolizing", + "militarising", "militarizing", + "milligrammes", "milligrams", + "miniaturised", "miniaturized", + "miniaturises", "miniaturizes", + "misbehaviour", "misbehavior", + "misdemeanour", "misdemeanor", + "mobilisation", "mobilization", + "moisturisers", "moisturizers", + "moisturising", "moisturizing", + "monopolising", "monopolizing", + "moustachioed", "mustachioed", + "nationalised", "nationalized", + "nationalises", "nationalizes", + "naturalising", "naturalizing", + "neighbouring", "neighboring", + "neutralising", "neutralizing", + "oesophaguses", "esophaguses", + "organisation", "organization", + "orthopaedics", "orthopedics", + "outmanoeuvre", "outmaneuver", + "palaeolithic", "paleolithic", + "pasteurising", "pasteurizing", + "personalised", "personalized", + "personalises", "personalizes", + "philosophise", "philosophize", + "plagiarising", "plagiarizing", + "ploughshares", "plowshares", + "polarisation", "polarization", + "politicising", "politicizing", + "popularising", "popularizing", + "pressurising", "pressurizing", + "prioritising", "prioritizing", + "propagandise", "propagandize", + "proselytised", "proselytized", + "proselytiser", "proselytizer", + "proselytises", "proselytizes", + "radicalising", "radicalizing", + "rationalised", "rationalized", + "rationalises", "rationalizes", + "realisations", "realizations", + "recognisable", "recognizable", + "recognisably", "recognizably", + "recognisance", "recognizance", + "reconnoitred", "reconnoitered", + "reconnoitres", "reconnoiters", + "regularising", "regularizing", + "reorganising", "reorganizing", + "revitalising", "revitalizing", + "rhapsodising", "rhapsodizing", + "romanticised", "romanticized", + "romanticises", "romanticizes", + "scandalising", "scandalizing", + "scrutinising", "scrutinizing", + "secularising", "secularizing", + "specialising", "specializing", + "squirrelling", "squirreling", + "standardised", "standardized", + "standardises", "standardizes", + "stigmatising", "stigmatizing", + "sympathisers", "sympathizers", + "sympathising", "sympathizing", + "synchronised", "synchronized", + "synchronises", "synchronizes", + "synthesisers", "synthesizers", + "synthesising", "synthesizing", + "systematised", "systematized", + "systematises", "systematizes", + "technicolour", "technicolor", + "theatregoers", "theatergoers", + "traumatising", "traumatizing", + "trivialising", "trivializing", + "unauthorised", "unauthorized", + "uncatalogued", "uncataloged", + "unfavourable", "unfavorable", + "unfavourably", "unfavorably", + "unionisation", "unionization", + "unrecognised", "unrecognized", + "untrammelled", "untrammeled", + "urbanisation", "urbanization", + "vaporisation", "vaporization", + "vocalisation", "vocalization", + "watercolours", "watercolors", + "westernising", "westernizing", + "accessorise", "accessorize", + "acclimatise", "acclimatize", + "agonisingly", "agonizingly", + "amortisable", "amortizable", + "anaesthesia", "anesthesia", + "anaesthetic", "anesthetic", + "anglicising", "anglicizing", + "antagonised", "antagonized", + "antagonises", "antagonizes", + "apologising", "apologizing", + "archaeology", "archeology", + "authorising", "authorizing", + "bastardised", "bastardized", + "bastardises", "bastardizes", + "bedevilling", "bedeviling", + "behavioural", "behavioral", + "belabouring", "belaboring", + "bowdlerised", "bowdlerized", + "bowdlerises", "bowdlerizes", + "breathalyse", "breathalyze", + "brutalising", "brutalizing", + "cannibalise", "cannibalize", + "capitalised", "capitalized", + "capitalises", "capitalizes", + "caramelised", "caramelized", + "caramelises", "caramelizes", + "carbonising", "carbonizing", + "cataloguing", "cataloging", + "categorised", "categorized", + "categorises", "categorizes", + "cauterising", "cauterizing", + "centigramme", "centigram", + "centilitres", "centiliters", + "centimetres", "centimeters", + "centralised", "centralized", + "centralises", "centralizes", + "centrefolds", "centerfolds", + "centrepiece", "centerpiece", + "channelling", "channeling", + "chequebooks", "checkbooks", + "circularise", "circularize", + "colourfully", "colorfully", + "colourizing", "colorizing", + "computerise", "computerize", + "councillors", "councilors", + "counselling", "counseling", + "counsellors", "counselors", + "criminalise", "criminalize", + "criticising", "criticizing", + "crystallise", "crystallize", + "customising", "customizing", + "defenceless", "defenseless", + "dehumanised", "dehumanized", + "dehumanises", "dehumanizes", + "demobilised", "demobilized", + "demobilises", "demobilizes", + "democratise", "democratize", + "demoralised", "demoralized", + "demoralises", "demoralizes", + "deodorising", "deodorizing", + "desensitise", "desensitize", + "destabilise", "destabilize", + "discoloured", "discolored", + "dishevelled", "disheveled", + "dishonoured", "dishonored", + "dramatising", "dramatizing", + "economising", "economizing", + "empathising", "empathizing", + "emphasising", "emphasizing", + "endeavoured", "endeavored", + "epitomising", "epitomizing", + "evangelised", "evangelized", + "evangelises", "evangelizes", + "extemporise", "extemporize", + "externalise", "externalize", + "factorising", "factorizing", + "familiarise", "familiarize", + "fantasising", "fantasizing", + "favouritism", "favoritism", + "fertilisers", "fertilizers", + "fertilising", "fertilizing", + "flavourings", "flavorings", + "flavourless", "flavorless", + "flavoursome", "flavorsome", + "formalising", "formalizing", + "fossilising", "fossilizing", + "fraternised", "fraternized", + "fraternises", "fraternizes", + "galvanising", "galvanizing", + "generalised", "generalized", + "generalises", "generalizes", + "ghettoising", "ghettoizing", + "globalising", "globalizing", + "gruellingly", "gruelingly", + "gynaecology", "gynecology", + "haematology", "hematology", + "haemoglobin", "hemoglobin", + "haemophilia", "hemophilia", + "haemorrhage", "hemorrhage", + "harmonising", "harmonizing", + "homoeopaths", "homeopaths", + "homoeopathy", "homeopathy", + "homogenised", "homogenized", + "homogenises", "homogenizes", + "hospitalise", "hospitalize", + "hybridising", "hybridizing", + "hypnotising", "hypnotizing", + "hypothesise", "hypothesize", + "immobilised", "immobilized", + "immobiliser", "immobilizer", + "immobilises", "immobilizes", + "immortalise", "immortalize", + "impanelling", "impaneling", + "imperilling", "imperiling", + "initialised", "initialized", + "initialises", "initializes", + "initialling", "initialing", + "instalments", "installments", + "internalise", "internalize", + "italicising", "italicizing", + "jeopardised", "jeopardized", + "jeopardises", "jeopardizes", + "kilogrammes", "kilograms", + "legitimised", "legitimized", + "legitimises", "legitimizes", + "liberalised", "liberalized", + "liberalises", "liberalizes", + "lionisation", "lionization", + "liquidisers", "liquidizers", + "liquidising", "liquidizing", + "magnetising", "magnetizing", + "manoeuvring", "maneuvering", + "marginalise", "marginalize", + "marshalling", "marshaling", + "materialise", "materialize", + "mechanising", "mechanizing", + "memorialise", "memorialize", + "mesmerising", "mesmerizing", + "metabolised", "metabolized", + "metabolises", "metabolizes", + "micrometres", "micrometers", + "militarised", "militarized", + "militarises", "militarizes", + "milligramme", "milligram", + "millilitres", "milliliters", + "millimetres", "millimeters", + "miniaturise", "miniaturize", + "modernising", "modernizing", + "moisturised", "moisturized", + "moisturiser", "moisturizer", + "moisturises", "moisturizes", + "monopolised", "monopolized", + "monopolises", "monopolizes", + "nationalise", "nationalize", + "naturalised", "naturalized", + "naturalises", "naturalizes", + "neighbourly", "neighborly", + "neutralised", "neutralized", + "neutralises", "neutralizes", + "normalising", "normalizing", + "orthopaedic", "orthopedic", + "ostracising", "ostracizing", + "oxidisation", "oxidization", + "paediatrics", "pediatrics", + "paedophiles", "pedophiles", + "paedophilia", "pedophilia", + "passivising", "passivizing", + "pasteurised", "pasteurized", + "pasteurises", "pasteurizes", + "patronising", "patronizing", + "personalise", "personalize", + "plagiarised", "plagiarized", + "plagiarises", "plagiarizes", + "ploughshare", "plowshare", + "politicised", "politicized", + "politicises", "politicizes", + "popularised", "popularized", + "popularises", "popularizes", + "praesidiums", "presidiums", + "pressurised", "pressurized", + "pressurises", "pressurizes", + "prioritised", "prioritized", + "prioritises", "prioritizes", + "privatising", "privatizing", + "proselytise", "proselytize", + "publicising", "publicizing", + "pulverising", "pulverizing", + "quarrelling", "quarreling", + "radicalised", "radicalized", + "radicalises", "radicalizes", + "randomising", "randomizing", + "rationalise", "rationalize", + "realisation", "realization", + "recognising", "recognizing", + "reconnoitre", "reconnoiter", + "regularised", "regularized", + "regularises", "regularizes", + "remodelling", "remodeling", + "reorganised", "reorganized", + "reorganises", "reorganizes", + "revitalised", "revitalized", + "revitalises", "revitalizes", + "rhapsodised", "rhapsodized", + "rhapsodises", "rhapsodizes", + "romanticise", "romanticize", + "scandalised", "scandalized", + "scandalises", "scandalizes", + "sceptically", "skeptically", + "scrutinised", "scrutinized", + "scrutinises", "scrutinizes", + "secularised", "secularized", + "secularises", "secularizes", + "sensitising", "sensitizing", + "serialising", "serializing", + "sermonising", "sermonizing", + "shrivelling", "shriveling", + "signalising", "signalizing", + "snorkelling", "snorkeling", + "snowploughs", "snowplow", + "socialising", "socializing", + "solemnising", "solemnizing", + "specialised", "specialized", + "specialises", "specializes", + "squirrelled", "squirreled", + "stabilisers", "stabilizers", + "stabilising", "stabilizing", + "standardise", "standardize", + "stencilling", "stenciling", + "sterilisers", "sterilizers", + "sterilising", "sterilizing", + "stigmatised", "stigmatized", + "stigmatises", "stigmatizes", + "subsidisers", "subsidizers", + "subsidising", "subsidizing", + "summarising", "summarizing", + "symbolising", "symbolizing", + "sympathised", "sympathized", + "sympathiser", "sympathizer", + "sympathises", "sympathizes", + "synchronise", "synchronize", + "synthesised", "synthesized", + "synthesiser", "synthesizer", + "synthesises", "synthesizes", + "systematise", "systematize", + "tantalising", "tantalizing", + "temporising", "temporizing", + "tenderising", "tenderizing", + "terrorising", "terrorizing", + "theatregoer", "theatergoer", + "traumatised", "traumatized", + "traumatises", "traumatizes", + "trivialised", "trivialized", + "trivialises", "trivializes", + "tyrannising", "tyrannizing", + "uncivilised", "uncivilized", + "unorganised", "unorganized", + "unravelling", "unraveling", + "utilisation", "utilization", + "vandalising", "vandalizing", + "verbalising", "verbalizing", + "victimising", "victimizing", + "visualising", "visualizing", + "vulgarising", "vulgarizing", + "watercolour", "watercolor", + "westernised", "westernized", + "westernises", "westernizes", + "worshipping", "worshiping", + "aeroplanes", "airplanes", + "amortising", "amortizing", + "anglicised", "anglicized", + "anglicises", "anglicizes", + "annualised", "annualized", + "antagonise", "antagonize", + "apologised", "apologized", + "apologises", "apologizes", + "appetisers", "appetizers", + "appetising", "appetizing", + "authorised", "authorized", + "authorises", "authorizes", + "bannisters", "banisters", + "bastardise", "bastardize", + "bedevilled", "bedeviled", + "behaviours", "behaviors", + "bejewelled", "bejeweled", + "belaboured", "belabored", + "bowdlerise", "bowdlerize", + "brutalised", "brutalized", + "brutalises", "brutalizes", + "canalising", "canalizing", + "cancelling", "canceling", + "canonising", "canonizing", + "capitalise", "capitalize", + "caramelise", "caramelize", + "carbonised", "carbonized", + "carbonises", "carbonizes", + "catalogued", "cataloged", + "catalogues", "catalogs", + "catalysing", "catalyzing", + "categorise", "categorize", + "cauterised", "cauterized", + "cauterises", "cauterizes", + "centilitre", "centiliter", + "centimetre", "centimeter", + "centralise", "centralize", + "centrefold", "centerfold", + "channelled", "channeled", + "chequebook", "checkbook", + "chiselling", "chiseling", + "civilising", "civilizing", + "clamouring", "clamoring", + "colonisers", "colonizers", + "colonising", "colonizing", + "colourants", "colorants", + "colourized", "colorized", + "colourizes", "colorizes", + "colourless", "colorless", + "connexions", "connections", + "councillor", "councilor", + "counselled", "counseled", + "counsellor", "counselor", + "criticised", "criticized", + "criticises", "criticizes", + "cudgelling", "cudgeling", + "customised", "customized", + "customises", "customizes", + "dehumanise", "dehumanize", + "demobilise", "demobilize", + "demonising", "demonizing", + "demoralise", "demoralize", + "deodorised", "deodorized", + "deodorises", "deodorizes", + "deputising", "deputizing", + "digitising", "digitizing", + "discolours", "discolors", + "dishonours", "dishonors", + "dramatised", "dramatized", + "dramatises", "dramatizes", + "drivelling", "driveling", + "economised", "economized", + "economises", "economizes", + "empathised", "empathized", + "empathises", "empathizes", + "emphasised", "emphasized", + "emphasises", "emphasizes", + "enamelling", "enameling", + "endeavours", "endeavors", + "energising", "energizing", + "epaulettes", "epaulets", + "epicentres", "epicenters", + "epitomised", "epitomized", + "epitomises", "epitomizes", + "equalisers", "equalizers", + "equalising", "equalizing", + "eulogising", "eulogizing", + "evangelise", "evangelize", + "factorised", "factorized", + "factorises", "factorizes", + "fantasised", "fantasized", + "fantasises", "fantasizes", + "favourable", "favorable", + "favourably", "favorably", + "favourites", "favorites", + "feminising", "feminizing", + "fertilised", "fertilized", + "fertiliser", "fertilizer", + "fertilises", "fertilizes", + "fibreglass", "fiberglass", + "finalising", "finalizing", + "flavouring", "flavoring", + "formalised", "formalized", + "formalises", "formalizes", + "fossilised", "fossilized", + "fossilises", "fossilizes", + "fraternise", "fraternize", + "fulfilment", "fulfillment", + "funnelling", "funneling", + "galvanised", "galvanized", + "galvanises", "galvanizes", + "gambolling", "gamboling", + "gaolbreaks", "jailbreaks", + "generalise", "generalize", + "ghettoised", "ghettoized", + "ghettoises", "ghettoizes", + "globalised", "globalized", + "globalises", "globalizes", + "gonorrhoea", "gonorrhea", + "grovelling", "groveling", + "harbouring", "harboring", + "harmonised", "harmonized", + "harmonises", "harmonizes", + "homoeopath", "homeopath", + "homogenise", "homogenize", + "honourable", "honorable", + "honourably", "honorably", + "humanising", "humanizing", + "humourless", "humorless", + "hybridised", "hybridized", + "hybridises", "hybridizes", + "hypnotised", "hypnotized", + "hypnotises", "hypnotizes", + "idealising", "idealizing", + "immobilise", "immobilize", + "immunising", "immunizing", + "impanelled", "impaneled", + "imperilled", "imperiled", + "inflexions", "inflections", + "initialise", "initialize", + "initialled", "initialed", + "instalment", "installment", + "ionisation", "ionization", + "italicised", "italicized", + "italicises", "italicizes", + "jeopardise", "jeopardize", + "kilogramme", "kilogram", + "kilometres", "kilometers", + "lacklustre", "lackluster", + "legalising", "legalizing", + "legitimise", "legitimize", + "liberalise", "liberalize", + "liquidised", "liquidized", + "liquidiser", "liquidizer", + "liquidises", "liquidizes", + "localising", "localizing", + "magnetised", "magnetized", + "magnetises", "magnetizes", + "manoeuvred", "maneuvered", + "manoeuvres", "maneuvers", + "marshalled", "marshaled", + "marvelling", "marveling", + "marvellous", "marvelous", + "maximising", "maximizing", + "mechanised", "mechanized", + "mechanises", "mechanizes", + "memorising", "memorizing", + "mesmerised", "mesmerized", + "mesmerises", "mesmerizes", + "metabolise", "metabolize", + "micrometre", "micrometer", + "militarise", "militarize", + "millilitre", "milliliter", + "millimetre", "millimeter", + "minimising", "minimizing", + "mobilising", "mobilizing", + "modernised", "modernized", + "modernises", "modernizes", + "moisturise", "moisturize", + "monopolise", "monopolize", + "moralising", "moralizing", + "mouldering", "moldering", + "moustached", "mustached", + "moustaches", "mustaches", + "naturalise", "naturalize", + "neighbours", "neighbors", + "neutralise", "neutralize", + "normalised", "normalized", + "normalises", "normalizes", + "oesophagus", "esophagus", + "optimising", "optimizing", + "organisers", "organizers", + "organising", "organizing", + "ostracised", "ostracized", + "ostracises", "ostracizes", + "paederasts", "pederasts", + "paediatric", "pediatric", + "paedophile", "pedophile", + "panellists", "panelists", + "paralysing", "paralyzing", + "parcelling", "parceling", + "passivised", "passivized", + "passivises", "passivizes", + "pasteurise", "pasteurize", + "patronised", "patronized", + "patronises", "patronizes", + "penalising", "penalizing", + "pencilling", "penciling", + "plagiarise", "plagiarize", + "polarising", "polarizing", + "politicise", "politicize", + "popularise", "popularize", + "practising", "practicing", + "praesidium", "presidium", + "pressurise", "pressurize", + "prioritise", "prioritize", + "privatised", "privatized", + "privatises", "privatizes", + "programmes", "programs", + "publicised", "publicized", + "publicises", "publicizes", + "pulverised", "pulverized", + "pulverises", "pulverizes", + "pummelling", "pummeled", + "quarrelled", "quarreled", + "radicalise", "radicalize", + "randomised", "randomized", + "randomises", "randomizes", + "realisable", "realizable", + "recognised", "recognized", + "recognises", "recognizes", + "refuelling", "refueling", + "regularise", "regularize", + "remodelled", "remodeled", + "remoulding", "remolding", + "reorganise", "reorganize", + "revitalise", "revitalize", + "rhapsodise", "rhapsodize", + "ritualised", "ritualized", + "sanitising", "sanitizing", + "satirising", "satirizing", + "scandalise", "scandalize", + "scepticism", "skepticism", + "scrutinise", "scrutinize", + "secularise", "secularize", + "sensitised", "sensitized", + "sensitises", "sensitizes", + "sepulchres", "sepulchers", + "serialised", "serialized", + "serialises", "serializes", + "sermonised", "sermonized", + "sermonises", "sermonizes", + "shovelling", "shoveling", + "shrivelled", "shriveled", + "signalised", "signalized", + "signalises", "signalizes", + "signalling", "signaling", + "snivelling", "sniveling", + "snorkelled", "snorkeled", + "snowplough", "snowplow", + "socialised", "socialized", + "socialises", "socializes", + "sodomising", "sodomizing", + "solemnised", "solemnized", + "solemnises", "solemnizes", + "specialise", "specialize", + "spiralling", "spiraling", + "splendours", "splendors", + "stabilised", "stabilized", + "stabiliser", "stabilizer", + "stabilises", "stabilizes", + "stencilled", "stenciled", + "sterilised", "sterilized", + "steriliser", "sterilizer", + "sterilises", "sterilizes", + "stigmatise", "stigmatize", + "subsidised", "subsidized", + "subsidiser", "subsidizer", + "subsidises", "subsidizes", + "succouring", "succoring", + "sulphurous", "sulfurous", + "summarised", "summarized", + "summarises", "summarizes", + "swivelling", "swiveling", + "symbolised", "symbolized", + "symbolises", "symbolizes", + "sympathise", "sympathize", + "synthesise", "synthesize", + "tantalised", "tantalized", + "tantalises", "tantalizes", + "temporised", "temporized", + "temporises", "temporizes", + "tenderised", "tenderized", + "tenderises", "tenderizes", + "terrorised", "terrorized", + "terrorises", "terrorizes", + "theorising", "theorizing", + "traumatise", "traumatize", + "travellers", "travelers", + "travelling", "traveling", + "tricolours", "tricolors", + "trivialise", "trivialize", + "tunnelling", "tunneling", + "tyrannised", "tyrannized", + "tyrannises", "tyrannizes", + "unequalled", "unequaled", + "unionising", "unionizing", + "unravelled", "unraveled", + "unrivalled", "unrivaled", + "urbanising", "urbanizing", + "utilisable", "utilizable", + "vandalised", "vandalized", + "vandalises", "vandalizes", + "vaporising", "vaporizing", + "verbalised", "verbalized", + "verbalises", "verbalizes", + "victimised", "victimized", + "victimises", "victimizes", + "visualised", "visualized", + "visualises", "visualizes", + "vocalising", "vocalizing", + "vulcanised", "vulcanized", + "vulgarised", "vulgarized", + "vulgarises", "vulgarizes", + "weaselling", "weaseling", + "westernise", "westernize", + "womanisers", "womanizers", + "womanising", "womanizing", + "worshipped", "worshiped", + "worshipper", "worshiper", + "aeroplane", "airplane", + "aetiology", "etiology", + "agonising", "agonizing", + "almanacks", "almanacs", + "aluminium", "aluminum", + "amortised", "amortized", + "amortises", "amortizes", + "analogues", "analogs", + "analysing", "analyzing", + "anglicise", "anglicize", + "apologise", "apologize", + "appetiser", "appetizer", + "armourers", "armorers", + "armouries", "armories", + "artefacts", "artifacts", + "authorise", "authorize", + "baptising", "baptizing", + "behaviour", "behavior", + "belabours", "belabors", + "brutalise", "brutalize", + "callipers", "calipers", + "canalised", "canalized", + "canalises", "canalizes", + "cancelled", "canceled", + "canonised", "canonized", + "canonises", "canonizes", + "carbonise", "carbonize", + "carolling", "caroling", + "catalogue", "catalog", + "catalysed", "catalyzed", + "catalyses", "catalyzes", + "cauterise", "cauterize", + "cavilling", "caviling", + "chequered", "checkered", + "chiselled", "chiseled", + "civilised", "civilized", + "civilises", "civilizes", + "clamoured", "clamored", + "colonised", "colonized", + "coloniser", "colonizer", + "colonises", "colonizes", + "colourant", "colorant", + "coloureds", "coloreds", + "colourful", "colorful", + "colouring", "coloring", + "colourize", "colorize", + "connexion", "connection", + "criticise", "criticize", + "cruellest", "cruelest", + "cudgelled", "cudgeled", + "customise", "customize", + "demeanour", "demeanor", + "demonised", "demonized", + "demonises", "demonizes", + "deodorise", "deodorize", + "deputised", "deputized", + "deputises", "deputizes", + "dialogues", "dialogs", + "diarrhoea", "diarrhea", + "digitised", "digitized", + "digitises", "digitizes", + "discolour", "discolor", + "disfavour", "disfavor", + "dishonour", "dishonor", + "dramatise", "dramatize", + "drivelled", "driveled", + "economise", "economize", + "empathise", "empathize", + "emphasise", "emphasize", + "enamelled", "enameled", + "enamoured", "enamored", + "endeavour", "endeavor", + "energised", "energized", + "energises", "energizes", + "epaulette", "epaulet", + "epicentre", "epicenter", + "epitomise", "epitomize", + "equalised", "equalized", + "equaliser", "equalizer", + "equalises", "equalizes", + "eulogised", "eulogized", + "eulogises", "eulogizes", + "factorise", "factorize", + "fantasise", "fantasize", + "favouring", "favoring", + "favourite", "favorite", + "feminised", "feminized", + "feminises", "feminizes", + "fertilise", "fertilize", + "finalised", "finalized", + "finalises", "finalizes", + "flautists", "flutists", + "flavoured", "flavored", + "formalise", "formalize", + "fossilise", "fossilize", + "funnelled", "funneled", + "galvanise", "galvanize", + "gambolled", "gamboled", + "gaolbirds", "jailbirds", + "gaolbreak", "jailbreak", + "ghettoise", "ghettoize", + "globalise", "globalize", + "gravelled", "graveled", + "grovelled", "groveled", + "gruelling", "grueling", + "harboured", "harbored", + "harmonise", "harmonize", + "honouring", "honoring", + "humanised", "humanized", + "humanises", "humanizes", + "humouring", "humoring", + "hybridise", "hybridize", + "hypnotise", "hypnotize", + "idealised", "idealized", + "idealises", "idealizes", + "idolising", "idolizing", + "immunised", "immunized", + "immunises", "immunizes", + "inflexion", "inflection", + "italicise", "italicize", + "itemising", "itemizing", + "jewellers", "jewelers", + "jewellery", "jewelry", + "kilometre", "kilometer", + "labelling", "labeling", + "labourers", "laborers", + "labouring", "laboring", + "legalised", "legalized", + "legalises", "legalizes", + "leukaemia", "leukemia", + "levellers", "levelers", + "levelling", "leveling", + "libelling", "libeling", + "libellous", "libelous", + "licencing", "licensing", + "lionising", "lionizing", + "liquidise", "liquidize", + "localised", "localized", + "localises", "localizes", + "magnetise", "magnetize", + "manoeuvre", "maneuver", + "marvelled", "marveled", + "maximised", "maximized", + "maximises", "maximizes", + "mechanise", "mechanize", + "mediaeval", "medieval", + "memorised", "memorized", + "memorises", "memorizes", + "mesmerise", "mesmerize", + "minimised", "minimized", + "minimises", "minimizes", + "mobilised", "mobilized", + "mobilises", "mobilizes", + "modellers", "modelers", + "modelling", "modeling", + "modernise", "modernize", + "moralised", "moralized", + "moralises", "moralizes", + "motorised", "motorized", + "mouldered", "moldered", + "mouldiest", "moldiest", + "mouldings", "moldings", + "moustache", "mustache", + "neighbour", "neighbor", + "normalise", "normalize", + "odourless", "odorless", + "oestrogen", "estrogen", + "optimised", "optimized", + "optimises", "optimizes", + "organised", "organized", + "organiser", "organizer", + "organises", "organizes", + "ostracise", "ostracize", + "oxidising", "oxidizing", + "paederast", "pederast", + "panelling", "paneling", + "panellist", "panelist", + "paralysed", "paralyzed", + "paralyses", "paralyzes", + "parcelled", "parceled", + "passivise", "passivize", + "patronise", "patronize", + "pedalling", "pedaling", + "penalised", "penalized", + "penalises", "penalizes", + "pencilled", "penciled", + "ploughing", "plowing", + "ploughman", "plowman", + "ploughmen", "plowmen", + "polarised", "polarized", + "polarises", "polarizes", + "practised", "practiced", + "practises", "practices", + "pretences", "pretenses", + "primaeval", "primeval", + "privatise", "privatize", + "programme", "program", + "publicise", "publicize", + "pulverise", "pulverize", + "pummelled", "pummel", + "randomise", "randomize", + "ravelling", "raveling", + "realising", "realizing", + "recognise", "recognize", + "refuelled", "refueled", + "remoulded", "remolded", + "revellers", "revelers", + "revelling", "reveling", + "rivalling", "rivaling", + "saltpetre", "saltpeter", + "sanitised", "sanitized", + "sanitises", "sanitizes", + "satirised", "satirized", + "satirises", "satirizes", + "savouries", "savories", + "savouring", "savoring", + "sceptical", "skeptical", + "sensitise", "sensitize", + "sepulchre", "sepulcher", + "serialise", "serialize", + "sermonise", "sermonize", + "shovelled", "shoveled", + "signalise", "signalize", + "signalled", "signaled", + "snivelled", "sniveled", + "socialise", "socialize", + "sodomised", "sodomized", + "sodomises", "sodomizes", + "solemnise", "solemnize", + "spiralled", "spiraled", + "splendour", "splendor", + "stabilise", "stabilize", + "sterilise", "sterilize", + "subsidise", "subsidize", + "succoured", "succored", + "sulphates", "sulfates", + "sulphides", "sulfides", + "summarise", "summarize", + "swivelled", "swiveled", + "symbolise", "symbolize", + "syphoning", "siphoning", + "tantalise", "tantalize", + "tasselled", "tasseled", + "temporise", "temporize", + "tenderise", "tenderize", + "terrorise", "terrorize", + "theorised", "theorized", + "theorises", "theorizes", + "towelling", "toweling", + "travelled", "traveled", + "traveller", "traveler", + "trialling", "trialing", + "tricolour", "tricolor", + "tunnelled", "tunneled", + "tyrannise", "tyrannize", + "unionised", "unionized", + "unionises", "unionizes", + "unsavoury", "unsavory", + "urbanised", "urbanized", + "urbanises", "urbanizes", + "utilising", "utilizing", + "vandalise", "vandalize", + "vaporised", "vaporized", + "vaporises", "vaporizes", + "verbalise", "verbalize", + "victimise", "victimize", + "visualise", "visualize", + "vocalised", "vocalized", + "vocalises", "vocalizes", + "vulgarise", "vulgarize", + "weaselled", "weaseled", + "womanised", "womanized", + "womaniser", "womanizer", + "womanises", "womanizes", + "yodelling", "yodeling", + "yoghourts", "yogurts", + "agonised", "agonized", + "agonises", "agonizes", + "almanack", "almanac", + "amortise", "amortize", + "analogue", "analog", + "analysed", "analyzed", + "analyses", "analyzes", + "armoured", "armored", + "armourer", "armorer", + "artefact", "artifact", + "baptised", "baptized", + "baptises", "baptizes", + "baulking", "balking", + "belabour", "belabor", + "bevelled", "beveled", + "calibres", "calibers", + "calliper", "caliper", + "canalise", "canalize", + "canonise", "canonize", + "carolled", "caroled", + "catalyse", "catalyze", + "cavilled", "caviled", + "civilise", "civilize", + "clamours", "clamors", + "clangour", "clangor", + "colonise", "colonize", + "coloured", "colored", + "cosiness", "coziness", + "crueller", "crueler", + "defences", "defenses", + "demonise", "demonize", + "deputise", "deputize", + "dialling", "dialing", + "dialogue", "dialog", + "digitise", "digitize", + "draughty", "drafty", + "duelling", "dueling", + "energise", "energize", + "enthrals", "enthralls", + "equalise", "equalize", + "eulogise", "eulogize", + "favoured", "favored", + "feminise", "feminize", + "finalise", "finalize", + "flautist", "flutist", + "flavours", "flavors", + "foetuses", "fetuses", + "fuelling", "fueling", + "gaolbird", "jailbird", + "gryphons", "griffins", + "harbours", "harbors", + "honoured", "honored", + "humanise", "humanize", + "humoured", "humored", + "idealise", "idealize", + "idolised", "idolized", + "idolises", "idolizes", + "immunise", "immunize", + "ionisers", "ionizers", + "ionising", "ionizing", + "itemised", "itemized", + "itemises", "itemizes", + "jewelled", "jeweled", + "jeweller", "jeweler", + "labelled", "labeled", + "laboured", "labored", + "labourer", "laborer", + "legalise", "legalize", + "levelled", "leveled", + "leveller", "leveler", + "libelled", "libeled", + "licenced", "licensed", + "licences", "licenses", + "lionised", "lionized", + "lionises", "lionizes", + "localise", "localize", + "maximise", "maximize", + "memorise", "memorize", + "minimise", "minimize", + "misspelt", "misspelled", + "mobilise", "mobilize", + "modelled", "modeled", + "modeller", "modeler", + "moralise", "moralize", + "moulders", "molders", + "mouldier", "moldier", + "moulding", "molding", + "moulting", "molting", + "offences", "offenses", + "optimise", "optimize", + "organise", "organize", + "oxidised", "oxidized", + "oxidises", "oxidizes", + "panelled", "paneled", + "paralyse", "paralyze", + "parlours", "parlors", + "pedalled", "pedaled", + "penalise", "penalize", + "philtres", "filters", + "ploughed", "plowed", + "polarise", "polarize", + "practise", "practice", + "pretence", "pretense", + "ravelled", "raveled", + "realised", "realized", + "realises", "realizes", + "remoulds", "remolds", + "revelled", "reveled", + "reveller", "reveler", + "rivalled", "rivaled", + "rumoured", "rumored", + "sanitise", "sanitize", + "satirise", "satirize", + "saviours", "saviors", + "savoured", "savored", + "sceptics", "skeptics", + "sceptres", "scepters", + "sodomise", "sodomize", + "spectres", "specters", + "succours", "succors", + "sulphate", "sulfate", + "sulphide", "sulfide", + "syphoned", "siphoned", + "theatres", "theaters", + "theorise", "theorize", + "towelled", "toweled", + "toxaemia", "toxemia", + "trialled", "trialed", + "unionise", "unionize", + "urbanise", "urbanize", + "utilised", "utilized", + "utilises", "utilizes", + "vaporise", "vaporize", + "vocalise", "vocalize", + "womanise", "womanize", + "yodelled", "yodeled", + "yoghourt", "yogurt", + "yoghurts", "yogurts", + "agonise", "agonize", + "anaemia", "anemia", + "anaemic", "anemic", + "analyse", "analyze", + "arbours", "arbors", + "armoury", "armory", + "baptise", "baptize", + "baulked", "balked", + "behoved", "behooved", + "behoves", "behooves", + "calibre", "caliber", + "candour", "candor", + "centred", "centered", + "centres", "centers", + "cheques", "checks", + "clamour", "clamor", + "colours", "colors", + "cosiest", "coziest", + "defence", "defense", + "dialled", "dialed", + "distils", "distills", + "duelled", "dueled", + "enthral", "enthrall", + "favours", "favors", + "fervour", "fervor", + "flavour", "flavor", + "fuelled", "fueled", + "fulfils", "fulfills", + "gaolers", "jailers", + "gaoling", "jailing", + "gipsies", "gypsies", + "glueing", "gluing", + "goitres", "goiters", + "grammes", "grams", + "groynes", "groins", + "gryphon", "griffin", + "harbour", "harbor", + "honours", "honors", + "humours", "humors", + "idolise", "idolize", + "instals", "installs", + "instils", "instills", + "ionised", "ionized", + "ioniser", "ionizer", + "ionises", "ionizes", + "itemise", "itemize", + "labours", "labors", + "licence", "license", + "lionise", "lionize", + "louvred", "louvered", + "louvres", "louvers", + "moulded", "molded", + "moulder", "molder", + "moulted", "molted", + "offence", "offense", + "oxidise", "oxidize", + "parlour", "parlor", + "philtre", "filter", + "ploughs", "plows", + "pyjamas", "pajamas", + "rancour", "rancor", + "realise", "realize", + "remould", "remold", + "rigours", "rigors", + "rumours", "rumors", + "saviour", "savior", + "savours", "savors", + "savoury", "savory", + "sceptic", "skeptic", + "sceptre", "scepter", + "spectre", "specter", + "storeys", "stories", + "succour", "succor", + "sulphur", "sulfur", + "syphons", "siphons", + "theatre", "theater", + "tumours", "tumors", + "utilise", "utilize", + "vapours", "vapors", + "waggons", "wagons", + "yoghurt", "yogurt", + "ageing", "aging", + "appals", "appalls", + "arbour", "arbor", + "ardour", "ardor", + "baulks", "balks", + "behove", "behoove", + "centre", "center", + "cheque", "check", + "chilli", "chili", + "colour", "color", + "cosier", "cozier", + "cosies", "cozies", + "cosily", "cozily", + "distil", "distill", + "edoema", "edema", + "enrols", "enrolls", + "faecal", "fecal", + "faeces", "feces", + "favour", "favor", + "fibres", "fibers", + "foetal", "fetal", + "foetid", "fetid", + "foetus", "fetus", + "fulfil", "fulfill", + "gaoled", "jailed", + "gaoler", "jailer", + "goitre", "goiter", + "gramme", "gram", + "groyne", "groin", + "honour", "honor", + "humour", "humor", + "instal", "install", + "instil", "instill", + "ionise", "ionize", + "labour", "labor", + "litres", "liters", + "lustre", "luster", + "meagre", "meager", + "metres", "meters", + "mitres", "miters", + "moulds", "molds", + "mouldy", "moldy", + "moults", "molts", + "odours", "odors", + "plough", "plow", + "pyjama", "pajama", + "rigour", "rigor", + "rumour", "rumor", + "savour", "savor", + "storey", "story", + "syphon", "siphon", + "tumour", "tumor", + "valour", "valor", + "vapour", "vapor", + "vigour", "vigor", + "waggon", "wagon", + "appal", "appall", + "baulk", "balk", + "enrol", "enroll", + "fibre", "fiber", + "gaols", "jails", + "litre", "liter", + "metre", "meter", + "mitre", "miter", + "mould", "mold", + "moult", "molt", + "odour", "odor", + "tyres", "tires", + "cosy", "cozy", + "gaol", "jail", + "tyre", "tire", +} + +// DictBritish converts US spellings to UK spellings +var DictBritish = []string{ + "institutionalization", "institutionalisation", + "internationalization", "internationalisation", + "professionalization", "professionalisation", + "compartmentalizing", "compartmentalising", + "institutionalizing", "institutionalising", + "internationalizing", "internationalising", + "compartmentalized", "compartmentalised", + "compartmentalizes", "compartmentalises", + "decriminalization", "decriminalisation", + "denationalization", "denationalisation", + "fictionalizations", "fictionalisations", + "institutionalized", "institutionalised", + "institutionalizes", "institutionalises", + "intellectualizing", "intellectualising", + "internationalized", "internationalised", + "internationalizes", "internationalises", + "pedestrianization", "pedestrianisation", + "professionalizing", "professionalising", + "compartmentalize", "compartmentalise", + "decentralization", "decentralisation", + "demilitarization", "demilitarisation", + "externalizations", "externalisations", + "fictionalization", "fictionalisation", + "institutionalize", "institutionalise", + "intellectualized", "intellectualised", + "intellectualizes", "intellectualises", + "internationalize", "internationalise", + "nationalizations", "nationalisations", + "professionalized", "professionalised", + "professionalizes", "professionalises", + "rationalizations", "rationalisations", + "sensationalizing", "sensationalising", + "sentimentalizing", "sentimentalising", + "acclimatization", "acclimatisation", + "commercializing", "commercialising", + "conceptualizing", "conceptualising", + "contextualizing", "contextualising", + "crystallization", "crystallisation", + "decriminalizing", "decriminalising", + "democratization", "democratisation", + "denationalizing", "denationalising", + "depersonalizing", "depersonalising", + "desensitization", "desensitisation", + "disorganization", "disorganisation", + "extemporization", "extemporisation", + "externalization", "externalisation", + "familiarization", "familiarisation", + "generalizations", "generalisations", + "hospitalization", "hospitalisation", + "individualizing", "individualising", + "industrializing", "industrialising", + "intellectualize", "intellectualise", + "internalization", "internalisation", + "maneuverability", "manoeuvrability", + "materialization", "materialisation", + "miniaturization", "miniaturisation", + "nationalization", "nationalisation", + "overemphasizing", "overemphasising", + "paleontologists", "palaeontologists", + "particularizing", "particularising", + "pedestrianizing", "pedestrianising", + "professionalize", "professionalise", + "psychoanalyzing", "psychoanalysing", + "rationalization", "rationalisation", + "reorganizations", "reorganisations", + "revolutionizing", "revolutionising", + "sensationalized", "sensationalised", + "sensationalizes", "sensationalises", + "sentimentalized", "sentimentalised", + "sentimentalizes", "sentimentalises", + "specializations", "specialisations", + "standardization", "standardisation", + "synchronization", "synchronisation", + "systematization", "systematisation", + "aggrandizement", "aggrandisement", + "characterizing", "characterising", + "collectivizing", "collectivising", + "commercialized", "commercialised", + "commercializes", "commercialises", + "conceptualized", "conceptualised", + "conceptualizes", "conceptualises", + "contextualized", "contextualised", + "contextualizes", "contextualises", + "decentralizing", "decentralising", + "decriminalized", "decriminalised", + "decriminalizes", "decriminalises", + "dehumanization", "dehumanisation", + "demilitarizing", "demilitarising", + "demobilization", "demobilisation", + "demoralization", "demoralisation", + "denationalized", "denationalised", + "denationalizes", "denationalises", + "depersonalized", "depersonalised", + "depersonalizes", "depersonalises", + "dramatizations", "dramatisations", + "editorializing", "editorialising", + "fictionalizing", "fictionalising", + "fraternization", "fraternisation", + "generalization", "generalisation", + "immobilization", "immobilisation", + "individualized", "individualised", + "individualizes", "individualises", + "industrialized", "industrialised", + "industrializes", "industrialises", + "liberalization", "liberalisation", + "monopolization", "monopolisation", + "naturalization", "naturalisation", + "neighborliness", "neighbourliness", + "neutralization", "neutralisation", + "organizational", "organisational", + "outmaneuvering", "outmanoeuvring", + "overemphasized", "overemphasised", + "overemphasizes", "overemphasises", + "paleontologist", "palaeontologist", + "particularized", "particularised", + "particularizes", "particularises", + "pasteurization", "pasteurisation", + "pedestrianized", "pedestrianised", + "pedestrianizes", "pedestrianises", + "philosophizing", "philosophising", + "politicization", "politicisation", + "popularization", "popularisation", + "pressurization", "pressurisation", + "prioritization", "prioritisation", + "privatizations", "privatisations", + "propagandizing", "propagandising", + "psychoanalyzed", "psychoanalysed", + "psychoanalyzes", "psychoanalyses", + "reconnoitering", "reconnoitring", + "regularization", "regularisation", + "reorganization", "reorganisation", + "revolutionized", "revolutionised", + "revolutionizes", "revolutionises", + "secularization", "secularisation", + "sensationalize", "sensationalise", + "sentimentalize", "sentimentalise", + "serializations", "serialisations", + "specialization", "specialisation", + "sterilizations", "sterilisations", + "stigmatization", "stigmatisation", + "transistorized", "transistorised", + "unrecognizable", "unrecognisable", + "visualizations", "visualisations", + "westernization", "westernisation", + "accessorizing", "accessorising", + "acclimatizing", "acclimatising", + "amortizations", "amortisations", + "amphitheaters", "amphitheatres", + "anesthetizing", "anaesthetising", + "archeologists", "archaeologists", + "breathalyzers", "breathalysers", + "breathalyzing", "breathalysing", + "cannibalizing", "cannibalising", + "characterized", "characterised", + "characterizes", "characterises", + "circularizing", "circularising", + "collectivized", "collectivised", + "collectivizes", "collectivises", + "commercialize", "commercialise", + "computerizing", "computerising", + "conceptualize", "conceptualise", + "contextualize", "contextualise", + "criminalizing", "criminalising", + "crystallizing", "crystallising", + "decentralized", "decentralised", + "decentralizes", "decentralises", + "decriminalize", "decriminalise", + "demilitarized", "demilitarised", + "demilitarizes", "demilitarises", + "democratizing", "democratising", + "denationalize", "denationalise", + "depersonalize", "depersonalise", + "desensitizing", "desensitising", + "destabilizing", "destabilising", + "disemboweling", "disembowelling", + "dramatization", "dramatisation", + "editorialized", "editorialised", + "editorializes", "editorialises", + "extemporizing", "extemporising", + "externalizing", "externalising", + "familiarizing", "familiarising", + "fertilization", "fertilisation", + "fictionalized", "fictionalised", + "fictionalizes", "fictionalises", + "formalization", "formalisation", + "fossilization", "fossilisation", + "globalization", "globalisation", + "gynecological", "gynaecological", + "gynecologists", "gynaecologists", + "harmonization", "harmonisation", + "hematological", "haematological", + "hematologists", "haematologists", + "hospitalizing", "hospitalising", + "hypothesizing", "hypothesising", + "immortalizing", "immortalising", + "individualize", "individualise", + "industrialize", "industrialise", + "internalizing", "internalising", + "marginalizing", "marginalising", + "materializing", "materialising", + "mechanization", "mechanisation", + "memorializing", "memorialising", + "miniaturizing", "miniaturising", + "nationalizing", "nationalising", + "neighborhoods", "neighbourhoods", + "normalization", "normalisation", + "organizations", "organisations", + "outmaneuvered", "outmanoeuvred", + "overemphasize", "overemphasise", + "particularize", "particularise", + "passivization", "passivisation", + "patronizingly", "patronisingly", + "pedestrianize", "pedestrianise", + "pediatricians", "paediatricians", + "personalizing", "personalising", + "philosophized", "philosophised", + "philosophizes", "philosophises", + "privatization", "privatisation", + "propagandized", "propagandised", + "propagandizes", "propagandises", + "proselytizers", "proselytisers", + "proselytizing", "proselytising", + "psychoanalyze", "psychoanalyse", + "pulverization", "pulverisation", + "rationalizing", "rationalising", + "reconnoitered", "reconnoitred", + "revolutionize", "revolutionise", + "romanticizing", "romanticising", + "serialization", "serialisation", + "socialization", "socialisation", + "standardizing", "standardising", + "sterilization", "sterilisation", + "subsidization", "subsidisation", + "synchronizing", "synchronising", + "systematizing", "systematising", + "tantalizingly", "tantalisingly", + "underutilized", "underutilised", + "victimization", "victimisation", + "visualization", "visualisation", + "vocalizations", "vocalisations", + "vulgarization", "vulgarisation", + "accessorized", "accessorised", + "accessorizes", "accessorises", + "acclimatized", "acclimatised", + "acclimatizes", "acclimatises", + "amortization", "amortisation", + "amphitheater", "amphitheatre", + "anesthetists", "anaesthetists", + "anesthetized", "anaesthetised", + "anesthetizes", "anaesthetises", + "antagonizing", "antagonising", + "appetizingly", "appetisingly", + "archeologist", "archaeologist", + "backpedaling", "backpedalling", + "bastardizing", "bastardising", + "behaviorists", "behaviourists", + "bowdlerizing", "bowdlerising", + "breathalyzed", "breathalysed", + "breathalyzes", "breathalyses", + "cannibalized", "cannibalised", + "cannibalizes", "cannibalises", + "capitalizing", "capitalising", + "caramelizing", "caramelising", + "categorizing", "categorising", + "centerpieces", "centrepieces", + "centralizing", "centralising", + "characterize", "characterise", + "circularized", "circularised", + "circularizes", "circularises", + "clarinetists", "clarinettists", + "collectivize", "collectivise", + "colonization", "colonisation", + "computerized", "computerised", + "computerizes", "computerises", + "criminalized", "criminalised", + "criminalizes", "criminalises", + "crystallized", "crystallised", + "crystallizes", "crystallises", + "decentralize", "decentralise", + "dehumanizing", "dehumanising", + "demilitarize", "demilitarise", + "demobilizing", "demobilising", + "democratized", "democratised", + "democratizes", "democratises", + "demoralizing", "demoralising", + "desensitized", "desensitised", + "desensitizes", "desensitises", + "destabilized", "destabilised", + "destabilizes", "destabilises", + "disemboweled", "disembowelled", + "dishonorable", "dishonourable", + "dishonorably", "dishonourably", + "disorganized", "disorganised", + "editorialize", "editorialise", + "equalization", "equalisation", + "evangelizing", "evangelising", + "extemporized", "extemporised", + "extemporizes", "extemporises", + "externalized", "externalised", + "externalizes", "externalises", + "familiarized", "familiarised", + "familiarizes", "familiarises", + "fictionalize", "fictionalise", + "finalization", "finalisation", + "fraternizing", "fraternising", + "generalizing", "generalising", + "gynecologist", "gynaecologist", + "hematologist", "haematologist", + "hemophiliacs", "haemophiliacs", + "hemorrhaging", "haemorrhaging", + "homogenizing", "homogenising", + "hospitalized", "hospitalised", + "hospitalizes", "hospitalises", + "hypothesized", "hypothesised", + "hypothesizes", "hypothesises", + "idealization", "idealisation", + "immobilizers", "immobilisers", + "immobilizing", "immobilising", + "immortalized", "immortalised", + "immortalizes", "immortalises", + "immunization", "immunisation", + "initializing", "initialising", + "installments", "instalments", + "internalized", "internalised", + "internalizes", "internalises", + "jeopardizing", "jeopardising", + "legalization", "legalisation", + "legitimizing", "legitimising", + "liberalizing", "liberalising", + "maneuverable", "manoeuvrable", + "maneuverings", "manoeuvrings", + "marginalized", "marginalised", + "marginalizes", "marginalises", + "materialized", "materialised", + "materializes", "materialises", + "maximization", "maximisation", + "memorialized", "memorialised", + "memorializes", "memorialises", + "metabolizing", "metabolising", + "militarizing", "militarising", + "miniaturized", "miniaturised", + "miniaturizes", "miniaturises", + "miscataloged", "miscatalogued", + "misdemeanors", "misdemeanours", + "mobilization", "mobilisation", + "moisturizers", "moisturisers", + "moisturizing", "moisturising", + "monopolizing", "monopolising", + "multicolored", "multicoloured", + "nationalized", "nationalised", + "nationalizes", "nationalises", + "naturalizing", "naturalising", + "neighborhood", "neighbourhood", + "neutralizing", "neutralising", + "organization", "organisation", + "outmaneuvers", "outmanoeuvres", + "paleontology", "palaeontology", + "pasteurizing", "pasteurising", + "pediatrician", "paediatrician", + "personalized", "personalised", + "personalizes", "personalises", + "philosophize", "philosophise", + "plagiarizing", "plagiarising", + "polarization", "polarisation", + "politicizing", "politicising", + "popularizing", "popularising", + "pressurizing", "pressurising", + "prioritizing", "prioritising", + "propagandize", "propagandise", + "proselytized", "proselytised", + "proselytizer", "proselytiser", + "proselytizes", "proselytises", + "radicalizing", "radicalising", + "rationalized", "rationalised", + "rationalizes", "rationalises", + "realizations", "realisations", + "recognizable", "recognisable", + "recognizably", "recognisably", + "recognizance", "recognisance", + "reconnoiters", "reconnoitres", + "regularizing", "regularising", + "reorganizing", "reorganising", + "revitalizing", "revitalising", + "rhapsodizing", "rhapsodising", + "romanticized", "romanticised", + "romanticizes", "romanticises", + "scandalizing", "scandalising", + "scrutinizing", "scrutinising", + "secularizing", "secularising", + "standardized", "standardised", + "standardizes", "standardises", + "stigmatizing", "stigmatising", + "sympathizers", "sympathisers", + "sympathizing", "sympathising", + "synchronized", "synchronised", + "synchronizes", "synchronises", + "synthesizing", "synthesising", + "systematized", "systematised", + "systematizes", "systematises", + "theatergoers", "theatregoers", + "traumatizing", "traumatising", + "trivializing", "trivialising", + "unauthorized", "unauthorised", + "unionization", "unionisation", + "unrecognized", "unrecognised", + "urbanization", "urbanisation", + "vaporization", "vaporisation", + "vocalization", "vocalisation", + "westernizing", "westernising", + "accessorize", "accessorise", + "acclimatize", "acclimatise", + "agonizingly", "agonisingly", + "amortizable", "amortisable", + "anesthetics", "anaesthetics", + "anesthetist", "anaesthetist", + "anesthetize", "anaesthetise", + "anglicizing", "anglicising", + "antagonized", "antagonised", + "antagonizes", "antagonises", + "apologizing", "apologising", + "backpedaled", "backpedalled", + "bastardized", "bastardised", + "bastardizes", "bastardises", + "behaviorism", "behaviourism", + "behaviorist", "behaviourist", + "bowdlerized", "bowdlerised", + "bowdlerizes", "bowdlerises", + "brutalizing", "brutalising", + "cannibalize", "cannibalise", + "capitalized", "capitalised", + "capitalizes", "capitalises", + "caramelized", "caramelised", + "caramelizes", "caramelises", + "carbonizing", "carbonising", + "categorized", "categorised", + "categorizes", "categorises", + "cauterizing", "cauterising", + "centerfolds", "centrefolds", + "centerpiece", "centrepiece", + "centiliters", "centilitres", + "centimeters", "centimetres", + "centralized", "centralised", + "centralizes", "centralises", + "circularize", "circularise", + "clarinetist", "clarinettist", + "computerize", "computerise", + "criminalize", "criminalise", + "criticizing", "criticising", + "crystallize", "crystallise", + "customizing", "customising", + "defenseless", "defenceless", + "dehumanized", "dehumanised", + "dehumanizes", "dehumanises", + "demobilized", "demobilised", + "demobilizes", "demobilises", + "democratize", "democratise", + "demoralized", "demoralised", + "demoralizes", "demoralises", + "deodorizing", "deodorising", + "desensitize", "desensitise", + "destabilize", "destabilise", + "discoloring", "discolouring", + "dishonoring", "dishonouring", + "dramatizing", "dramatising", + "economizing", "economising", + "empathizing", "empathising", + "emphasizing", "emphasising", + "endeavoring", "endeavouring", + "epitomizing", "epitomising", + "esophaguses", "oesophaguses", + "evangelized", "evangelised", + "evangelizes", "evangelises", + "extemporize", "extemporise", + "externalize", "externalise", + "factorizing", "factorising", + "familiarize", "familiarise", + "fantasizing", "fantasising", + "fertilizers", "fertilisers", + "fertilizing", "fertilising", + "formalizing", "formalising", + "fossilizing", "fossilising", + "fraternized", "fraternised", + "fraternizes", "fraternises", + "fulfillment", "fulfilment", + "galvanizing", "galvanising", + "generalized", "generalised", + "generalizes", "generalises", + "ghettoizing", "ghettoising", + "globalizing", "globalising", + "harmonizing", "harmonising", + "hemophiliac", "haemophiliac", + "hemorrhaged", "haemorrhaged", + "hemorrhages", "haemorrhages", + "hemorrhoids", "haemorrhoids", + "homogenized", "homogenised", + "homogenizes", "homogenises", + "hospitalize", "hospitalise", + "hybridizing", "hybridising", + "hypnotizing", "hypnotising", + "hypothesize", "hypothesise", + "immobilized", "immobilised", + "immobilizer", "immobiliser", + "immobilizes", "immobilises", + "immortalize", "immortalise", + "initialized", "initialised", + "initializes", "initialises", + "installment", "instalment", + "internalize", "internalise", + "italicizing", "italicising", + "jeopardized", "jeopardised", + "jeopardizes", "jeopardises", + "legitimized", "legitimised", + "legitimizes", "legitimises", + "liberalized", "liberalised", + "liberalizes", "liberalises", + "lionization", "lionisation", + "liquidizers", "liquidisers", + "liquidizing", "liquidising", + "magnetizing", "magnetising", + "maneuvering", "manoeuvring", + "marginalize", "marginalise", + "marvelously", "marvellously", + "materialize", "materialise", + "mechanizing", "mechanising", + "memorialize", "memorialise", + "mesmerizing", "mesmerising", + "metabolized", "metabolised", + "metabolizes", "metabolises", + "militarized", "militarised", + "militarizes", "militarises", + "milliliters", "millilitres", + "millimeters", "millimetres", + "miniaturize", "miniaturise", + "misbehavior", "misbehaviour", + "misdemeanor", "misdemeanour", + "modernizing", "modernising", + "moisturized", "moisturised", + "moisturizer", "moisturiser", + "moisturizes", "moisturises", + "monopolized", "monopolised", + "monopolizes", "monopolises", + "nationalize", "nationalise", + "naturalized", "naturalised", + "naturalizes", "naturalises", + "neighboring", "neighbouring", + "neutralized", "neutralised", + "neutralizes", "neutralises", + "normalizing", "normalising", + "orthopedics", "orthopaedics", + "ostracizing", "ostracising", + "outmaneuver", "outmanoeuvre", + "oxidization", "oxidisation", + "pasteurized", "pasteurised", + "pasteurizes", "pasteurises", + "patronizing", "patronising", + "personalize", "personalise", + "plagiarized", "plagiarised", + "plagiarizes", "plagiarises", + "politicized", "politicised", + "politicizes", "politicises", + "popularized", "popularised", + "popularizes", "popularises", + "pressurized", "pressurised", + "pressurizes", "pressurises", + "prioritized", "prioritised", + "prioritizes", "prioritises", + "privatizing", "privatising", + "proselytize", "proselytise", + "publicizing", "publicising", + "pulverizing", "pulverising", + "radicalized", "radicalised", + "radicalizes", "radicalises", + "randomizing", "randomising", + "rationalize", "rationalise", + "realization", "realisation", + "recognizing", "recognising", + "reconnoiter", "reconnoitre", + "regularized", "regularised", + "regularizes", "regularises", + "reorganized", "reorganised", + "reorganizes", "reorganises", + "revitalized", "revitalised", + "revitalizes", "revitalises", + "rhapsodized", "rhapsodised", + "rhapsodizes", "rhapsodises", + "romanticize", "romanticise", + "scandalized", "scandalised", + "scandalizes", "scandalises", + "scrutinized", "scrutinised", + "scrutinizes", "scrutinises", + "secularized", "secularised", + "secularizes", "secularises", + "sensitizing", "sensitising", + "serializing", "serialising", + "sermonizing", "sermonising", + "signalizing", "signalising", + "skeptically", "sceptically", + "socializing", "socialising", + "solemnizing", "solemnising", + "specialized", "specialised", + "specializes", "specialises", + "squirreling", "squirrelling", + "stabilizers", "stabilisers", + "stabilizing", "stabilising", + "standardize", "standardise", + "sterilizers", "sterilisers", + "sterilizing", "sterilising", + "stigmatized", "stigmatised", + "stigmatizes", "stigmatises", + "subsidizers", "subsidisers", + "subsidizing", "subsidising", + "summarizing", "summarising", + "symbolizing", "symbolising", + "sympathized", "sympathised", + "sympathizer", "sympathiser", + "sympathizes", "sympathises", + "synchronize", "synchronise", + "synthesized", "synthesised", + "synthesizes", "synthesises", + "systematize", "systematise", + "tantalizing", "tantalising", + "temporizing", "temporising", + "tenderizing", "tenderising", + "terrorizing", "terrorising", + "theatergoer", "theatregoer", + "traumatized", "traumatised", + "traumatizes", "traumatises", + "trivialized", "trivialised", + "trivializes", "trivialises", + "tyrannizing", "tyrannising", + "uncataloged", "uncatalogued", + "uncivilized", "uncivilised", + "unfavorable", "unfavourable", + "unfavorably", "unfavourably", + "unorganized", "unorganised", + "untrammeled", "untrammelled", + "utilization", "utilisation", + "vandalizing", "vandalising", + "verbalizing", "verbalising", + "victimizing", "victimising", + "visualizing", "visualising", + "vulgarizing", "vulgarising", + "watercolors", "watercolours", + "westernized", "westernised", + "westernizes", "westernises", + "amortizing", "amortising", + "anesthesia", "anaesthesia", + "anesthetic", "anaesthetic", + "anglicized", "anglicised", + "anglicizes", "anglicises", + "annualized", "annualised", + "antagonize", "antagonise", + "apologized", "apologised", + "apologizes", "apologises", + "appetizers", "appetisers", + "appetizing", "appetising", + "archeology", "archaeology", + "authorizes", "authorises", + "bastardize", "bastardise", + "bedeviling", "bedevilling", + "behavioral", "behavioural", + "belaboring", "belabouring", + "bowdlerize", "bowdlerise", + "brutalized", "brutalised", + "brutalizes", "brutalises", + "canalizing", "canalising", + "canonizing", "canonising", + "capitalize", "capitalise", + "caramelize", "caramelise", + "carbonized", "carbonised", + "carbonizes", "carbonises", + "cataloging", "cataloguing", + "catalyzing", "catalysing", + "categorize", "categorise", + "cauterized", "cauterised", + "cauterizes", "cauterises", + "centerfold", "centrefold", + "centiliter", "centilitre", + "centimeter", "centimetre", + "centralize", "centralise", + "channeling", "channelling", + "checkbooks", "chequebooks", + "civilizing", "civilising", + "colonizers", "colonisers", + "colonizing", "colonising", + "colorfully", "colourfully", + "colorizing", "colourizing", + "councilors", "councillors", + "counselors", "counsellors", + "criticized", "criticised", + "criticizes", "criticises", + "customized", "customised", + "customizes", "customises", + "dehumanize", "dehumanise", + "demobilize", "demobilise", + "demonizing", "demonising", + "demoralize", "demoralise", + "deodorized", "deodorised", + "deodorizes", "deodorises", + "deputizing", "deputising", + "digitizing", "digitising", + "discolored", "discoloured", + "disheveled", "dishevelled", + "dishonored", "dishonoured", + "dramatized", "dramatised", + "dramatizes", "dramatises", + "economized", "economised", + "economizes", "economises", + "empathized", "empathised", + "empathizes", "empathises", + "emphasized", "emphasised", + "emphasizes", "emphasises", + "endeavored", "endeavoured", + "energizing", "energising", + "epicenters", "epicentres", + "epitomized", "epitomised", + "epitomizes", "epitomises", + "equalizers", "equalisers", + "equalizing", "equalising", + "eulogizing", "eulogising", + "evangelize", "evangelise", + "factorized", "factorised", + "factorizes", "factorises", + "fantasized", "fantasised", + "fantasizes", "fantasises", + "favoritism", "favouritism", + "feminizing", "feminising", + "fertilized", "fertilised", + "fertilizer", "fertiliser", + "fertilizes", "fertilises", + "fiberglass", "fibreglass", + "finalizing", "finalising", + "flavorings", "flavourings", + "flavorless", "flavourless", + "flavorsome", "flavoursome", + "formalized", "formalised", + "formalizes", "formalises", + "fossilized", "fossilised", + "fossilizes", "fossilises", + "fraternize", "fraternise", + "galvanized", "galvanised", + "galvanizes", "galvanises", + "generalize", "generalise", + "ghettoized", "ghettoised", + "ghettoizes", "ghettoises", + "globalized", "globalised", + "globalizes", "globalises", + "gruelingly", "gruellingly", + "gynecology", "gynaecology", + "harmonized", "harmonised", + "harmonizes", "harmonises", + "hematology", "haematology", + "hemoglobin", "haemoglobin", + "hemophilia", "haemophilia", + "hemorrhage", "haemorrhage", + "homogenize", "homogenise", + "humanizing", "humanising", + "hybridized", "hybridised", + "hybridizes", "hybridises", + "hypnotized", "hypnotised", + "hypnotizes", "hypnotises", + "idealizing", "idealising", + "immobilize", "immobilise", + "immunizing", "immunising", + "impaneling", "impanelling", + "imperiling", "imperilling", + "initialing", "initialling", + "initialize", "initialise", + "ionization", "ionisation", + "italicized", "italicised", + "italicizes", "italicises", + "jeopardize", "jeopardise", + "kilometers", "kilometres", + "lackluster", "lacklustre", + "legalizing", "legalising", + "legitimize", "legitimise", + "liberalize", "liberalise", + "liquidized", "liquidised", + "liquidizer", "liquidiser", + "liquidizes", "liquidises", + "localizing", "localising", + "magnetized", "magnetised", + "magnetizes", "magnetises", + "maneuvered", "manoeuvred", + "marshaling", "marshalling", + "maximizing", "maximising", + "mechanized", "mechanised", + "mechanizes", "mechanises", + "memorizing", "memorising", + "mesmerized", "mesmerised", + "mesmerizes", "mesmerises", + "metabolize", "metabolise", + "militarize", "militarise", + "milliliter", "millilitre", + "millimeter", "millimetre", + "minimizing", "minimising", + "mobilizing", "mobilising", + "modernized", "modernised", + "modernizes", "modernises", + "moisturize", "moisturise", + "monopolize", "monopolise", + "moralizing", "moralising", + "naturalize", "naturalise", + "neighborly", "neighbourly", + "neutralize", "neutralise", + "normalized", "normalised", + "normalizes", "normalises", + "optimizing", "optimising", + "organizers", "organisers", + "organizing", "organising", + "orthopedic", "orthopaedic", + "ostracized", "ostracised", + "ostracizes", "ostracises", + "paralyzing", "paralysing", + "pasteurize", "pasteurise", + "patronized", "patronised", + "patronizes", "patronises", + "pedophiles", "paedophiles", + "pedophilia", "paedophilia", + "penalizing", "penalising", + "plagiarize", "plagiarise", + "plowshares", "ploughshares", + "polarizing", "polarising", + "politicize", "politicise", + "popularize", "popularise", + "prioritize", "prioritise", + "privatized", "privatised", + "privatizes", "privatises", + "publicized", "publicised", + "publicizes", "publicises", + "pulverized", "pulverised", + "pulverizes", "pulverises", + "quarreling", "quarrelling", + "radicalize", "radicalise", + "randomized", "randomised", + "randomizes", "randomises", + "realizable", "realisable", + "recognized", "recognised", + "recognizes", "recognises", + "regularize", "regularise", + "remodeling", "remodelling", + "reorganize", "reorganise", + "revitalize", "revitalise", + "rhapsodize", "rhapsodise", + "ritualized", "ritualised", + "sanitizing", "sanitising", + "satirizing", "satirising", + "scandalize", "scandalise", + "scrutinize", "scrutinise", + "secularize", "secularise", + "sensitized", "sensitised", + "sensitizes", "sensitises", + "sepulchers", "sepulchres", + "serialized", "serialised", + "serializes", "serialises", + "sermonized", "sermonised", + "sermonizes", "sermonises", + "shriveling", "shrivelling", + "signalized", "signalised", + "signalizes", "signalises", + "skepticism", "scepticism", + "socialized", "socialised", + "socializes", "socialises", + "sodomizing", "sodomising", + "solemnized", "solemnised", + "solemnizes", "solemnises", + "specialize", "specialise", + "squirreled", "squirrelled", + "stabilized", "stabilised", + "stabilizer", "stabiliser", + "stabilizes", "stabilises", + "stenciling", "stencilling", + "sterilized", "sterilised", + "sterilizer", "steriliser", + "sterilizes", "sterilises", + "stigmatize", "stigmatise", + "subsidized", "subsidised", + "subsidizer", "subsidiser", + "subsidizes", "subsidises", + "summarized", "summarised", + "summarizes", "summarises", + "symbolized", "symbolised", + "symbolizes", "symbolises", + "sympathize", "sympathise", + "tantalized", "tantalised", + "tantalizes", "tantalises", + "temporized", "temporised", + "temporizes", "temporises", + "tenderized", "tenderised", + "tenderizes", "tenderises", + "terrorized", "terrorised", + "terrorizes", "terrorises", + "theorizing", "theorising", + "traumatize", "traumatise", + "trivialize", "trivialise", + "tyrannized", "tyrannised", + "tyrannizes", "tyrannises", + "unionizing", "unionising", + "unraveling", "unravelling", + "urbanizing", "urbanising", + "utilizable", "utilisable", + "vandalized", "vandalised", + "vandalizes", "vandalises", + "vaporizing", "vaporising", + "verbalized", "verbalised", + "verbalizes", "verbalises", + "victimized", "victimised", + "victimizes", "victimises", + "visualized", "visualised", + "visualizes", "visualises", + "vocalizing", "vocalising", + "vulcanized", "vulcanised", + "vulgarized", "vulgarised", + "vulgarizes", "vulgarises", + "watercolor", "watercolour", + "westernize", "westernise", + "womanizers", "womanisers", + "womanizing", "womanising", + "worshiping", "worshipping", + "agonizing", "agonising", + "airplanes", "aeroplanes", + "amortized", "amortised", + "amortizes", "amortises", + "analyzing", "analysing", + "apologize", "apologise", + "appetizer", "appetiser", + "artifacts", "artefacts", + "baptizing", "baptising", + "bedeviled", "bedevilled", + "behaviors", "behaviours", + "bejeweled", "bejewelled", + "belabored", "belaboured", + "brutalize", "brutalise", + "canalized", "canalised", + "canalizes", "canalises", + "canonized", "canonised", + "canonizes", "canonises", + "carbonize", "carbonise", + "cataloged", "catalogued", + "catalyzed", "catalysed", + "catalyzes", "catalyses", + "cauterize", "cauterise", + "channeled", "channelled", + "checkbook", "chequebook", + "checkered", "chequered", + "chiseling", "chiselling", + "civilized", "civilised", + "civilizes", "civilises", + "clamoring", "clamouring", + "colonized", "colonised", + "colonizer", "coloniser", + "colonizes", "colonises", + "colorants", "colourants", + "colorized", "colourized", + "colorizes", "colourizes", + "colorless", "colourless", + "councilor", "councillor", + "counseled", "counselled", + "counselor", "counsellor", + "criticize", "criticise", + "cudgeling", "cudgelling", + "customize", "customise", + "demonized", "demonised", + "demonizes", "demonises", + "deodorize", "deodorise", + "deputized", "deputised", + "deputizes", "deputises", + "digitized", "digitised", + "digitizes", "digitises", + "discolors", "discolours", + "dishonors", "dishonours", + "dramatize", "dramatise", + "driveling", "drivelling", + "economize", "economise", + "empathize", "empathise", + "emphasize", "emphasise", + "enameling", "enamelling", + "endeavors", "endeavours", + "energized", "energised", + "energizes", "energises", + "enthralls", "enthrals", + "epicenter", "epicentre", + "epitomize", "epitomise", + "equalized", "equalised", + "equalizer", "equaliser", + "equalizes", "equalises", + "eulogized", "eulogised", + "eulogizes", "eulogises", + "factorize", "factorise", + "fantasize", "fantasise", + "favorable", "favourable", + "favorably", "favourably", + "favorites", "favourites", + "feminized", "feminised", + "feminizes", "feminises", + "fertilize", "fertilise", + "finalized", "finalised", + "finalizes", "finalises", + "flavoring", "flavouring", + "formalize", "formalise", + "fossilize", "fossilise", + "funneling", "funnelling", + "galvanize", "galvanise", + "gamboling", "gambolling", + "ghettoize", "ghettoise", + "globalize", "globalise", + "gonorrhea", "gonorrhoea", + "groveling", "grovelling", + "harboring", "harbouring", + "harmonize", "harmonise", + "honorably", "honourably", + "humanized", "humanised", + "humanizes", "humanises", + "hybridize", "hybridise", + "hypnotize", "hypnotise", + "idealized", "idealised", + "idealizes", "idealises", + "idolizing", "idolising", + "immunized", "immunised", + "immunizes", "immunises", + "impaneled", "impanelled", + "imperiled", "imperilled", + "initialed", "initialled", + "italicize", "italicise", + "itemizing", "itemising", + "kilometer", "kilometre", + "legalized", "legalised", + "legalizes", "legalises", + "lionizing", "lionising", + "liquidize", "liquidise", + "localized", "localised", + "localizes", "localises", + "magnetize", "magnetise", + "maneuvers", "manoeuvres", + "marshaled", "marshalled", + "marveling", "marvelling", + "marvelous", "marvellous", + "maximized", "maximised", + "maximizes", "maximises", + "mechanize", "mechanise", + "memorized", "memorised", + "memorizes", "memorises", + "mesmerize", "mesmerise", + "minimized", "minimised", + "minimizes", "minimises", + "mobilized", "mobilised", + "mobilizes", "mobilises", + "modernize", "modernise", + "moldering", "mouldering", + "moralized", "moralised", + "moralizes", "moralises", + "motorized", "motorised", + "mustached", "moustached", + "mustaches", "moustaches", + "neighbors", "neighbours", + "normalize", "normalise", + "optimized", "optimised", + "optimizes", "optimises", + "organized", "organised", + "organizer", "organiser", + "organizes", "organises", + "ostracize", "ostracise", + "oxidizing", "oxidising", + "panelists", "panellists", + "paralyzed", "paralysed", + "paralyzes", "paralyses", + "parceling", "parcelling", + "patronize", "patronise", + "pedophile", "paedophile", + "penalized", "penalised", + "penalizes", "penalises", + "penciling", "pencilling", + "plowshare", "ploughshare", + "polarized", "polarised", + "polarizes", "polarises", + "practiced", "practised", + "pretenses", "pretences", + "privatize", "privatise", + "publicize", "publicise", + "pulverize", "pulverise", + "quarreled", "quarrelled", + "randomize", "randomise", + "realizing", "realising", + "recognize", "recognise", + "refueling", "refuelling", + "remodeled", "remodelled", + "remolding", "remoulding", + "saltpeter", "saltpetre", + "sanitized", "sanitised", + "sanitizes", "sanitises", + "satirized", "satirised", + "satirizes", "satirises", + "sensitize", "sensitise", + "sepulcher", "sepulchre", + "serialize", "serialise", + "sermonize", "sermonise", + "shoveling", "shovelling", + "shriveled", "shrivelled", + "signaling", "signalling", + "signalize", "signalise", + "skeptical", "sceptical", + "sniveling", "snivelling", + "snorkeled", "snorkelled", + "socialize", "socialise", + "sodomized", "sodomised", + "sodomizes", "sodomises", + "solemnize", "solemnise", + "spiraling", "spiralling", + "splendors", "splendours", + "stabilize", "stabilise", + "stenciled", "stencilled", + "sterilize", "sterilise", + "subsidize", "subsidise", + "succoring", "succouring", + "sulfurous", "sulphurous", + "summarize", "summarise", + "swiveling", "swivelling", + "symbolize", "symbolise", + "tantalize", "tantalise", + "temporize", "temporise", + "tenderize", "tenderise", + "terrorize", "terrorise", + "theorized", "theorised", + "theorizes", "theorises", + "travelers", "travellers", + "traveling", "travelling", + "tricolors", "tricolours", + "tunneling", "tunnelling", + "tyrannize", "tyrannise", + "unequaled", "unequalled", + "unionized", "unionised", + "unionizes", "unionises", + "unraveled", "unravelled", + "unrivaled", "unrivalled", + "urbanized", "urbanised", + "urbanizes", "urbanises", + "utilizing", "utilising", + "vandalize", "vandalise", + "vaporized", "vaporised", + "vaporizes", "vaporises", + "verbalize", "verbalise", + "victimize", "victimise", + "visualize", "visualise", + "vocalized", "vocalised", + "vocalizes", "vocalises", + "vulgarize", "vulgarise", + "weaseling", "weaselling", + "womanized", "womanised", + "womanizer", "womaniser", + "womanizes", "womanises", + "worshiped", "worshipped", + "worshiper", "worshipper", + "agonized", "agonised", + "agonizes", "agonises", + "airplane", "aeroplane", + "aluminum", "aluminium", + "amortize", "amortise", + "analyzed", "analysed", + "analyzes", "analyses", + "armorers", "armourers", + "armories", "armouries", + "artifact", "artefact", + "baptized", "baptised", + "baptizes", "baptises", + "behavior", "behaviour", + "behooved", "behoved", + "behooves", "behoves", + "belabors", "belabours", + "calibers", "calibres", + "canalize", "canalise", + "canonize", "canonise", + "catalogs", "catalogues", + "catalyze", "catalyse", + "caviling", "cavilling", + "centered", "centred", + "chiseled", "chiselled", + "civilize", "civilise", + "clamored", "clamoured", + "colonize", "colonise", + "colorant", "colourant", + "coloreds", "coloureds", + "colorful", "colourful", + "coloring", "colouring", + "colorize", "colourize", + "coziness", "cosiness", + "cruelest", "cruellest", + "cudgeled", "cudgelled", + "defenses", "defences", + "demeanor", "demeanour", + "demonize", "demonise", + "deputize", "deputise", + "diarrhea", "diarrhoea", + "digitize", "digitise", + "disfavor", "disfavour", + "dishonor", "dishonour", + "distills", "distils", + "driveled", "drivelled", + "enameled", "enamelled", + "enamored", "enamoured", + "endeavor", "endeavour", + "energize", "energise", + "epaulets", "epaulettes", + "equalize", "equalise", + "estrogen", "oestrogen", + "etiology", "aetiology", + "eulogize", "eulogise", + "favoring", "favouring", + "favorite", "favourite", + "feminize", "feminise", + "finalize", "finalise", + "flavored", "flavoured", + "flutists", "flautists", + "fulfills", "fulfils", + "funneled", "funnelled", + "gamboled", "gambolled", + "graveled", "gravelled", + "groveled", "grovelled", + "grueling", "gruelling", + "harbored", "harboured", + "honoring", "honouring", + "humanize", "humanise", + "humoring", "humouring", + "idealize", "idealise", + "idolized", "idolised", + "idolizes", "idolises", + "immunize", "immunise", + "ionizing", "ionising", + "itemized", "itemised", + "itemizes", "itemises", + "jewelers", "jewellers", + "labeling", "labelling", + "laborers", "labourers", + "laboring", "labouring", + "legalize", "legalise", + "leukemia", "leukaemia", + "levelers", "levellers", + "leveling", "levelling", + "libeling", "libelling", + "libelous", "libellous", + "lionized", "lionised", + "lionizes", "lionises", + "localize", "localise", + "louvered", "louvred", + "maneuver", "manoeuvre", + "marveled", "marvelled", + "maximize", "maximise", + "memorize", "memorise", + "minimize", "minimise", + "mobilize", "mobilise", + "modelers", "modellers", + "modeling", "modelling", + "moldered", "mouldered", + "moldiest", "mouldiest", + "moldings", "mouldings", + "moralize", "moralise", + "mustache", "moustache", + "neighbor", "neighbour", + "odorless", "odourless", + "offenses", "offences", + "optimize", "optimise", + "organize", "organise", + "oxidized", "oxidised", + "oxidizes", "oxidises", + "paneling", "panelling", + "panelist", "panellist", + "paralyze", "paralyse", + "parceled", "parcelled", + "pedaling", "pedalling", + "penalize", "penalise", + "penciled", "pencilled", + "polarize", "polarise", + "pretense", "pretence", + "pummeled", "pummelling", + "raveling", "ravelling", + "realized", "realised", + "realizes", "realises", + "refueled", "refuelled", + "remolded", "remoulded", + "revelers", "revellers", + "reveling", "revelling", + "rivaling", "rivalling", + "sanitize", "sanitise", + "satirize", "satirise", + "savories", "savouries", + "savoring", "savouring", + "scepters", "sceptres", + "shoveled", "shovelled", + "signaled", "signalled", + "skeptics", "sceptics", + "sniveled", "snivelled", + "sodomize", "sodomise", + "specters", "spectres", + "spiraled", "spiralled", + "splendor", "splendour", + "succored", "succoured", + "sulfates", "sulphates", + "sulfides", "sulphides", + "swiveled", "swivelled", + "tasseled", "tasselled", + "theaters", "theatres", + "theorize", "theorise", + "toweling", "towelling", + "traveler", "traveller", + "trialing", "trialling", + "tricolor", "tricolour", + "tunneled", "tunnelled", + "unionize", "unionise", + "unsavory", "unsavoury", + "urbanize", "urbanise", + "utilized", "utilised", + "utilizes", "utilises", + "vaporize", "vaporise", + "vocalize", "vocalise", + "weaseled", "weaselled", + "womanize", "womanise", + "yodeling", "yodelling", + "agonize", "agonise", + "analyze", "analyse", + "appalls", "appals", + "armored", "armoured", + "armorer", "armourer", + "baptize", "baptise", + "behoove", "behove", + "belabor", "belabour", + "beveled", "bevelled", + "caliber", "calibre", + "caroled", "carolled", + "caviled", "cavilled", + "centers", "centres", + "clamors", "clamours", + "clangor", "clangour", + "colored", "coloured", + "coziest", "cosiest", + "crueler", "crueller", + "defense", "defence", + "dialing", "dialling", + "dialogs", "dialogues", + "distill", "distil", + "dueling", "duelling", + "enrolls", "enrols", + "epaulet", "epaulette", + "favored", "favoured", + "flavors", "flavours", + "flutist", "flautist", + "fueling", "fuelling", + "fulfill", "fulfil", + "goiters", "goitres", + "harbors", "harbours", + "honored", "honoured", + "humored", "humoured", + "idolize", "idolise", + "ionized", "ionised", + "ionizes", "ionises", + "itemize", "itemise", + "jeweled", "jewelled", + "jeweler", "jeweller", + "jewelry", "jewellery", + "labeled", "labelled", + "labored", "laboured", + "laborer", "labourer", + "leveled", "levelled", + "leveler", "leveller", + "libeled", "libelled", + "lionize", "lionise", + "louvers", "louvres", + "modeled", "modelled", + "modeler", "modeller", + "molders", "moulders", + "moldier", "mouldier", + "molding", "moulding", + "molting", "moulting", + "offense", "offence", + "oxidize", "oxidise", + "pajamas", "pyjamas", + "paneled", "panelled", + "parlors", "parlours", + "pedaled", "pedalled", + "plowing", "ploughing", + "plowman", "ploughman", + "plowmen", "ploughmen", + "realize", "realise", + "remolds", "remoulds", + "reveled", "revelled", + "reveler", "reveller", + "rivaled", "rivalled", + "rumored", "rumoured", + "saviors", "saviours", + "savored", "savoured", + "scepter", "sceptre", + "skeptic", "sceptic", + "specter", "spectre", + "succors", "succours", + "sulfate", "sulphate", + "sulfide", "sulphide", + "theater", "theatre", + "toweled", "towelled", + "toxemia", "toxaemia", + "trialed", "trialled", + "utilize", "utilise", + "yodeled", "yodelled", + "anemia", "anaemia", + "anemic", "anaemic", + "appall", "appal", + "arbors", "arbours", + "armory", "armoury", + "candor", "candour", + "center", "centre", + "clamor", "clamour", + "colors", "colours", + "cozier", "cosier", + "cozies", "cosies", + "cozily", "cosily", + "dialed", "dialled", + "drafty", "draughty", + "dueled", "duelled", + "favors", "favours", + "fervor", "fervour", + "fibers", "fibres", + "flavor", "flavour", + "fueled", "fuelled", + "goiter", "goitre", + "harbor", "harbour", + "honors", "honours", + "humors", "humours", + "labors", "labours", + "liters", "litres", + "louver", "louvre", + "luster", "lustre", + "meager", "meagre", + "miters", "mitres", + "molded", "moulded", + "molder", "moulder", + "molted", "moulted", + "pajama", "pyjama", + "parlor", "parlour", + "plowed", "ploughed", + "rancor", "rancour", + "remold", "remould", + "rigors", "rigours", + "rumors", "rumours", + "savors", "savours", + "savory", "savoury", + "succor", "succour", + "tumors", "tumours", + "vapors", "vapours", + "aging", "ageing", + "arbor", "arbour", + "ardor", "ardour", + "armor", "armour", + "chili", "chilli", + "color", "colour", + "edema", "edoema", + "favor", "favour", + "fecal", "faecal", + "feces", "faeces", + "fiber", "fibre", + "honor", "honour", + "humor", "humour", + "labor", "labour", + "liter", "litre", + "miter", "mitre", + "molds", "moulds", + "moldy", "mouldy", + "molts", "moults", + "odors", "odours", + "plows", "ploughs", + "rigor", "rigour", + "rumor", "rumour", + "savor", "savour", + "valor", "valour", + "vapor", "vapour", + "vigor", "vigour", + "cozy", "cosy", + "mold", "mould", + "molt", "moult", + "odor", "odour", + "plow", "plough", +} diff --git a/vendor/github.com/golangci/prealloc/LICENSE b/vendor/github.com/golangci/prealloc/LICENSE new file mode 100644 index 000000000..9310fbcff --- /dev/null +++ b/vendor/github.com/golangci/prealloc/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Alex Kohler + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/golangci/prealloc/README.md b/vendor/github.com/golangci/prealloc/README.md new file mode 100644 index 000000000..162ede3ba --- /dev/null +++ b/vendor/github.com/golangci/prealloc/README.md @@ -0,0 +1,198 @@ +# prealloc + +prealloc is a Go static analysis tool to find slice declarations that could potentially be preallocated. + +## Installation + + go get -u github.com/alexkohler/prealloc + +## Usage + +Similar to other Go static analysis tools (such as golint, go vet), prealloc can be invoked with one or more filenames, directories, or packages named by its import path. Prealloc also supports the `...` wildcard. + + prealloc [flags] files/directories/packages + +### Flags +- **-simple** (default true) - Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. Setting this to false may increase false positives. +- **-rangeloops** (default true) - Report preallocation suggestions on range loops. +- **-forloops** (default false) - Report preallocation suggestions on for loops. This is false by default due to there generally being weirder things happening inside for loops (at least from what I've observed in the Standard Library). +- **-set_exit_status** (default false) - Set exit status to 1 if any issues are found. + +## Purpose + +While the [Go *does* attempt to avoid reallocation by growing the capacity in advance](https://github.com/golang/go/blob/87e48c5afdcf5e01bb2b7f51b7643e8901f4b7f9/src/runtime/slice.go#L100-L112), this sometimes isn't enough for longer slices. If the size of a slice is known at the time of its creation, it should be specified. + +Consider the following benchmark: (this can be found in prealloc_test.go in this repo) + +```Go +import "testing" + +func BenchmarkNoPreallocate(b *testing.B) { + existing := make([]int64, 10, 10) + b.ResetTimer() + for i := 0; i < b.N; i++ { + // Don't preallocate our initial slice + var init []int64 + for _, element := range existing { + init = append(init, element) + } + } +} + +func BenchmarkPreallocate(b *testing.B) { + existing := make([]int64, 10, 10) + b.ResetTimer() + for i := 0; i < b.N; i++ { + // Preallocate our initial slice + init := make([]int64, 0, len(existing)) + for _, element := range existing { + init = append(init, element) + } + } +} +``` + +```Bash +$ go test -bench=. -benchmem +goos: linux +goarch: amd64 +BenchmarkNoPreallocate-4 3000000 510 ns/op 248 B/op 5 allocs/op +BenchmarkPreallocate-4 20000000 111 ns/op 80 B/op 1 allocs/op +``` + +As you can see, not preallocating can cause a performance hit, primarily due to Go having to reallocate the underlying array. The pattern benchmarked above is common in Go: declare a slice, then write some sort of range or for loop that appends or indexes into it. The purpose of this tool is to flag slice/loop declarations like the one in `BenchmarkNoPreallocate`. + +## Example + +Some examples from the Go 1.9.2 source: + +```Bash +$ prealloc go/src/.... +archive/tar/reader_test.go:854 Consider preallocating ss +archive/zip/zip_test.go:201 Consider preallocating all +cmd/api/goapi.go:301 Consider preallocating missing +cmd/api/goapi.go:476 Consider preallocating files +cmd/asm/internal/asm/endtoend_test.go:345 Consider preallocating extra +cmd/cgo/main.go:60 Consider preallocating ks +cmd/cgo/ast.go:149 Consider preallocating pieces +cmd/compile/internal/ssa/flagalloc.go:64 Consider preallocating oldSched +cmd/compile/internal/ssa/regalloc.go:719 Consider preallocating phis +cmd/compile/internal/ssa/regalloc.go:718 Consider preallocating oldSched +cmd/compile/internal/ssa/regalloc.go:1674 Consider preallocating oldSched +cmd/compile/internal/ssa/gen/rulegen.go:145 Consider preallocating ops +cmd/compile/internal/ssa/gen/rulegen.go:145 Consider preallocating ops +cmd/dist/build.go:893 Consider preallocating all +cmd/dist/build.go:1246 Consider preallocating plats +cmd/dist/build.go:1264 Consider preallocating results +cmd/dist/buildgo.go:59 Consider preallocating list +cmd/doc/pkg.go:363 Consider preallocating names +cmd/fix/typecheck.go:219 Consider preallocating b +cmd/go/internal/base/path.go:34 Consider preallocating out +cmd/go/internal/get/get.go:175 Consider preallocating out +cmd/go/internal/load/pkg.go:1894 Consider preallocating dirent +cmd/go/internal/work/build.go:2402 Consider preallocating absOfiles +cmd/go/internal/work/build.go:2731 Consider preallocating absOfiles +cmd/internal/objfile/pe.go:48 Consider preallocating syms +cmd/internal/objfile/pe.go:38 Consider preallocating addrs +cmd/internal/objfile/goobj.go:43 Consider preallocating syms +cmd/internal/objfile/elf.go:35 Consider preallocating syms +cmd/link/internal/ld/lib.go:1070 Consider preallocating argv +cmd/vet/all/main.go:91 Consider preallocating pp +database/sql/sql.go:66 Consider preallocating list +debug/macho/file.go:506 Consider preallocating all +internal/trace/order.go:55 Consider preallocating batches +mime/quotedprintable/reader_test.go:191 Consider preallocating outcomes +net/dnsclient_unix_test.go:954 Consider preallocating confLines +net/interface_solaris.go:85 Consider preallocating ifat +net/interface_linux_test.go:91 Consider preallocating ifmat4 +net/interface_linux_test.go:100 Consider preallocating ifmat6 +net/internal/socktest/switch.go:34 Consider preallocating st +os/os_windows_test.go:766 Consider preallocating args +runtime/pprof/internal/profile/filter.go:77 Consider preallocating lines +runtime/pprof/internal/profile/profile.go:554 Consider preallocating names +text/template/parse/node.go:189 Consider preallocating decl +``` + +```Go +// cmd/api/goapi.go:301 +var missing []string +for feature := range optionalSet { + missing = append(missing, feature) +} + +// cmd/fix/typecheck.go:219 +var b []ast.Expr +for _, x := range a { + b = append(b, x) +} + +// net/internal/socktest/switch.go:34 +var st []Stat +sw.smu.RLock() +for _, s := range sw.stats { + ns := *s + st = append(st, ns) +} +sw.smu.RUnlock() + +// cmd/api/goapi.go:301 +var missing []string +for feature := range optionalSet { + missing = append(missing, feature) +} +``` + +Even if the size the slice is being preallocated to is small, there's still a performance gain to be had in explicitly specifying the capacity rather than leaving it up to `append` to discover that it needs to preallocate. Of course, preallocation doesn't need to be done *everywhere*. This tool's job is just to help suggest places where one should consider preallocating. + +## How do I fix prealloc's suggestions? + +During the declaration of your slice, rather than using the zero value of the slice with `var`, initialize it with Go's built-in `make` function, passing the appropriate type and length. This length will generally be whatever you are ranging over. Fixing the examples from above would look like so: + +```Go +// cmd/api/goapi.go:301 +missing := make([]string, 0, len(optionalSet)) +for feature := range optionalSet { + missing = append(missing, feature) +} + +// cmd/fix/typecheck.go:219 +b := make([]ast.Expr, 0, len(a)) +for _, x := range a { + b = append(b, x) +} + +// net/internal/socktest/switch.go:34 +st := make([]Stat, 0, len(sw.stats)) +sw.smu.RLock() +for _, s := range sw.stats { + ns := *s + st = append(st, ns) +} +sw.smu.RUnlock() + +// cmd/api/goapi.go:301 +missing := make ([]string, 0, len(optionalSet)) +for feature := range optionalSet { + missing = append(missing, feature) +} +``` + + + +## TODO + +- Configuration on whether or not to run on test files +- Support for embedded ifs (currently, prealloc will only find breaks/returns/continues/gotos if they are in a single if block, I'd like to expand this to supporting multiple if blocks in the future). +- Globbing support (e.g. prealloc *.go) + + +## Contributing + +Pull requests welcome! + + +## Other static analysis tools + +If you've enjoyed prealloc, take a look at my other static anaylsis tools! +- [nakedret](https://github.com/alexkohler/nakedret) - Finds naked returns. +- [unimport](https://github.com/alexkohler/unimport) - Finds unnecessary import aliases. diff --git a/vendor/github.com/golangci/prealloc/import.go b/vendor/github.com/golangci/prealloc/import.go new file mode 100644 index 000000000..b747965ee --- /dev/null +++ b/vendor/github.com/golangci/prealloc/import.go @@ -0,0 +1,310 @@ +package prealloc + +/* + +This file holds a direct copy of the import path matching code of +https://github.com/golang/go/blob/master/src/cmd/go/main.go. It can be +replaced when https://golang.org/issue/8768 is resolved. + +It has been updated to follow upstream changes in a few ways. + +*/ + +import ( + "fmt" + "go/build" + "log" + "os" + "path" + "path/filepath" + "regexp" + "runtime" + "strings" +) + +var buildContext = build.Default + +var ( + goroot = filepath.Clean(runtime.GOROOT()) + gorootSrc = filepath.Join(goroot, "src") +) + +// importPathsNoDotExpansion returns the import paths to use for the given +// command line, but it does no ... expansion. +func importPathsNoDotExpansion(args []string) []string { + if len(args) == 0 { + return []string{"."} + } + var out []string + for _, a := range args { + // Arguments are supposed to be import paths, but + // as a courtesy to Windows developers, rewrite \ to / + // in command-line arguments. Handles .\... and so on. + if filepath.Separator == '\\' { + a = strings.Replace(a, `\`, `/`, -1) + } + + // Put argument in canonical form, but preserve leading ./. + if strings.HasPrefix(a, "./") { + a = "./" + path.Clean(a) + if a == "./." { + a = "." + } + } else { + a = path.Clean(a) + } + if a == "all" || a == "std" { + out = append(out, allPackages(a)...) + continue + } + out = append(out, a) + } + return out +} + +// importPaths returns the import paths to use for the given command line. +func importPaths(args []string) []string { + args = importPathsNoDotExpansion(args) + var out []string + for _, a := range args { + if strings.Contains(a, "...") { + if build.IsLocalImport(a) { + out = append(out, allPackagesInFS(a)...) + } else { + out = append(out, allPackages(a)...) + } + continue + } + out = append(out, a) + } + return out +} + +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +func matchPattern(pattern string) func(name string) bool { + re := regexp.QuoteMeta(pattern) + re = strings.Replace(re, `\.\.\.`, `.*`, -1) + // Special case: foo/... matches foo too. + if strings.HasSuffix(re, `/.*`) { + re = re[:len(re)-len(`/.*`)] + `(/.*)?` + } + reg := regexp.MustCompile(`^` + re + `$`) + return func(name string) bool { + return reg.MatchString(name) + } +} + +// hasPathPrefix reports whether the path s begins with the +// elements in prefix. +func hasPathPrefix(s, prefix string) bool { + switch { + default: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == '/' { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == '/' && s[:len(prefix)] == prefix + } +} + +// treeCanMatchPattern(pattern)(name) reports whether +// name or children of name can possibly match pattern. +// Pattern is the same limited glob accepted by matchPattern. +func treeCanMatchPattern(pattern string) func(name string) bool { + wildCard := false + if i := strings.Index(pattern, "..."); i >= 0 { + wildCard = true + pattern = pattern[:i] + } + return func(name string) bool { + return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || + wildCard && strings.HasPrefix(name, pattern) + } +} + +// allPackages returns all the packages that can be found +// under the $GOPATH directories and $GOROOT matching pattern. +// The pattern is either "all" (all packages), "std" (standard packages) +// or a path including "...". +func allPackages(pattern string) []string { + pkgs := matchPackages(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +func matchPackages(pattern string) []string { + match := func(string) bool { return true } + treeCanMatch := func(string) bool { return true } + if pattern != "all" && pattern != "std" { + match = matchPattern(pattern) + treeCanMatch = treeCanMatchPattern(pattern) + } + + have := map[string]bool{ + "builtin": true, // ignore pseudo-package that exists only for documentation + } + if !buildContext.CgoEnabled { + have["runtime/cgo"] = true // ignore during walk + } + var pkgs []string + + // Commands + cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator) + filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() || path == cmd { + return nil + } + name := path[len(cmd):] + if !treeCanMatch(name) { + return filepath.SkipDir + } + // Commands are all in cmd/, not in subdirectories. + if strings.Contains(name, string(filepath.Separator)) { + return filepath.SkipDir + } + + // We use, e.g., cmd/gofmt as the pseudo import path for gofmt. + name = "cmd/" + name + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + _, err = buildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + pkgs = append(pkgs, name) + return nil + }) + + for _, src := range buildContext.SrcDirs() { + if (pattern == "std" || pattern == "cmd") && src != gorootSrc { + continue + } + src = filepath.Clean(src) + string(filepath.Separator) + root := src + if pattern == "cmd" { + root += "cmd" + string(filepath.Separator) + } + filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() || path == src { + return nil + } + + // Avoid .foo, _foo, testdata and vendor directory trees. + _, elem := filepath.Split(path) + if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" || elem == "vendor" { + return filepath.SkipDir + } + + name := filepath.ToSlash(path[len(src):]) + if pattern == "std" && (strings.Contains(name, ".") || name == "cmd") { + // The name "std" is only the standard library. + // If the name is cmd, it's the root of the command tree. + return filepath.SkipDir + } + if !treeCanMatch(name) { + return filepath.SkipDir + } + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + _, err = buildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); noGo { + return nil + } + } + pkgs = append(pkgs, name) + return nil + }) + } + return pkgs +} + +// allPackagesInFS is like allPackages but is passed a pattern +// beginning ./ or ../, meaning it should scan the tree rooted +// at the given directory. There are ... in the pattern too. +func allPackagesInFS(pattern string) []string { + pkgs := matchPackagesInFS(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +func matchPackagesInFS(pattern string) []string { + // Find directory to begin the scan. + // Could be smarter but this one optimization + // is enough for now, since ... is usually at the + // end of a path. + i := strings.Index(pattern, "...") + dir, _ := path.Split(pattern[:i]) + + // pattern begins with ./ or ../. + // path.Clean will discard the ./ but not the ../. + // We need to preserve the ./ for pattern matching + // and in the returned import paths. + prefix := "" + if strings.HasPrefix(pattern, "./") { + prefix = "./" + } + match := matchPattern(pattern) + + var pkgs []string + filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() { + return nil + } + if path == dir { + // filepath.Walk starts at dir and recurses. For the recursive case, + // the path is the result of filepath.Join, which calls filepath.Clean. + // The initial case is not Cleaned, though, so we do this explicitly. + // + // This converts a path like "./io/" to "io". Without this step, running + // "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io + // package, because prepending the prefix "./" to the unclean path would + // result in "././io", and match("././io") returns false. + path = filepath.Clean(path) + } + + // Avoid .foo, _foo, testdata and vendor directory trees, but do not avoid "." or "..". + _, elem := filepath.Split(path) + dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." + if dot || strings.HasPrefix(elem, "_") || elem == "testdata" || elem == "vendor" { + return filepath.SkipDir + } + + name := prefix + filepath.ToSlash(path) + if !match(name) { + return nil + } + if _, err = build.ImportDir(path, 0); err != nil { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + pkgs = append(pkgs, name) + return nil + }) + return pkgs +} diff --git a/vendor/github.com/golangci/prealloc/prealloc.go b/vendor/github.com/golangci/prealloc/prealloc.go new file mode 100644 index 000000000..1235ad363 --- /dev/null +++ b/vendor/github.com/golangci/prealloc/prealloc.go @@ -0,0 +1,403 @@ +package prealloc + +import ( + "errors" + "flag" + "fmt" + "go/ast" + "go/build" + "go/parser" + "go/token" + "log" + "os" + "path/filepath" + "strings" +) + +// Support: (in order of priority) +// * Full make suggestion with type? +// * Test flag +// * Embedded ifs? +// * Use an import rather than the duplcated import.go + +const ( + pwd = "./" +) + +func usage() { + log.Printf("Usage of %s:\n", os.Args[0]) + log.Printf("\nprealloc [flags] # runs on package in current directory\n") + log.Printf("\nprealloc [flags] [packages]\n") + log.Printf("Flags:\n") + flag.PrintDefaults() +} + +type sliceDeclaration struct { + name string + // sType string + genD *ast.GenDecl +} + +type returnsVisitor struct { + // flags + simple bool + includeRangeLoops bool + includeForLoops bool + // visitor fields + sliceDeclarations []*sliceDeclaration + preallocHints []Hint + returnsInsideOfLoop bool + arrayTypes []string +} + +func NoMain() { + + // Remove log timestamp + log.SetFlags(0) + + simple := flag.Bool("simple", true, "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them") + includeRangeLoops := flag.Bool("rangeloops", true, "Report preallocation suggestions on range loops") + includeForLoops := flag.Bool("forloops", false, "Report preallocation suggestions on for loops") + setExitStatus := flag.Bool("set_exit_status", false, "Set exit status to 1 if any issues are found") + flag.Usage = usage + flag.Parse() + + hints, err := checkForPreallocations(flag.Args(), simple, includeRangeLoops, includeForLoops) + if err != nil { + log.Println(err) + } + + for _, hint := range hints { + log.Println(hint) + } + if *setExitStatus && len(hints) > 0 { + os.Exit(1) + } +} + +func checkForPreallocations(args []string, simple, includeRangeLoops *bool, includeForLoops *bool) ([]Hint, error) { + + fset := token.NewFileSet() + + files, err := parseInput(args, fset) + if err != nil { + return nil, fmt.Errorf("could not parse input %v", err) + } + + if simple == nil { + return nil, errors.New("simple nil") + } + + if includeRangeLoops == nil { + return nil, errors.New("includeRangeLoops nil") + } + + if includeForLoops == nil { + return nil, errors.New("includeForLoops nil") + } + + hints := []Hint{} + for _, f := range files { + retVis := &returnsVisitor{ + simple: *simple, + includeRangeLoops: *includeRangeLoops, + includeForLoops: *includeForLoops, + } + ast.Walk(retVis, f) + // if simple is true, then we actually have to check if we had returns + // inside of our loop. Otherwise, we can just report all messages. + if !retVis.simple || !retVis.returnsInsideOfLoop { + hints = append(hints, retVis.preallocHints...) + } + } + + return hints, nil +} + +func Check(files []*ast.File, simple, includeRangeLoops, includeForLoops bool) []Hint { + hints := []Hint{} + for _, f := range files { + retVis := &returnsVisitor{ + simple: simple, + includeRangeLoops: includeRangeLoops, + includeForLoops: includeForLoops, + } + ast.Walk(retVis, f) + + // if simple is true, then we actually have to check if we had returns + // inside of our loop. Otherwise, we can just report all messages. + if !retVis.simple || !retVis.returnsInsideOfLoop { + hints = append(hints, retVis.preallocHints...) + } + } + + return hints +} + +func parseInput(args []string, fset *token.FileSet) ([]*ast.File, error) { + var directoryList []string + var fileMode bool + files := make([]*ast.File, 0) + + if len(args) == 0 { + directoryList = append(directoryList, pwd) + } else { + for _, arg := range args { + if strings.HasSuffix(arg, "/...") && isDir(arg[:len(arg)-len("/...")]) { + + for _, dirname := range allPackagesInFS(arg) { + directoryList = append(directoryList, dirname) + } + + } else if isDir(arg) { + directoryList = append(directoryList, arg) + + } else if exists(arg) { + if strings.HasSuffix(arg, ".go") { + fileMode = true + f, err := parser.ParseFile(fset, arg, nil, 0) + if err != nil { + return nil, err + } + files = append(files, f) + } else { + return nil, fmt.Errorf("invalid file %v specified", arg) + } + } else { + + //TODO clean this up a bit + imPaths := importPaths([]string{arg}) + for _, importPath := range imPaths { + pkg, err := build.Import(importPath, ".", 0) + if err != nil { + return nil, err + } + var stringFiles []string + stringFiles = append(stringFiles, pkg.GoFiles...) + // files = append(files, pkg.CgoFiles...) + stringFiles = append(stringFiles, pkg.TestGoFiles...) + if pkg.Dir != "." { + for i, f := range stringFiles { + stringFiles[i] = filepath.Join(pkg.Dir, f) + } + } + + fileMode = true + for _, stringFile := range stringFiles { + f, err := parser.ParseFile(fset, stringFile, nil, 0) + if err != nil { + return nil, err + } + files = append(files, f) + } + + } + } + } + } + + // if we're not in file mode, then we need to grab each and every package in each directory + // we can to grab all the files + if !fileMode { + for _, fpath := range directoryList { + pkgs, err := parser.ParseDir(fset, fpath, nil, 0) + if err != nil { + return nil, err + } + + for _, pkg := range pkgs { + for _, f := range pkg.Files { + files = append(files, f) + } + } + } + } + + return files, nil +} + +func isDir(filename string) bool { + fi, err := os.Stat(filename) + return err == nil && fi.IsDir() +} + +func exists(filename string) bool { + _, err := os.Stat(filename) + return err == nil +} + +func contains(slice []string, item string) bool { + for _, s := range slice { + if s == item { + return true + } + } + + return false +} + +func (v *returnsVisitor) Visit(node ast.Node) ast.Visitor { + + v.sliceDeclarations = nil + v.returnsInsideOfLoop = false + + switch n := node.(type) { + case *ast.TypeSpec: + if _, ok := n.Type.(*ast.ArrayType); ok { + if n.Name != nil { + v.arrayTypes = append(v.arrayTypes, n.Name.Name) + } + } + case *ast.FuncDecl: + if n.Body != nil { + for _, stmt := range n.Body.List { + switch s := stmt.(type) { + // Find non pre-allocated slices + case *ast.DeclStmt: + genD, ok := s.Decl.(*ast.GenDecl) + if !ok { + continue + } + if genD.Tok == token.TYPE { + for _, spec := range genD.Specs { + tSpec, ok := spec.(*ast.TypeSpec) + if !ok { + continue + } + + if _, ok := tSpec.Type.(*ast.ArrayType); ok { + if tSpec.Name != nil { + v.arrayTypes = append(v.arrayTypes, tSpec.Name.Name) + } + } + } + } else if genD.Tok == token.VAR { + for _, spec := range genD.Specs { + vSpec, ok := spec.(*ast.ValueSpec) + if !ok { + continue + } + var isArrType bool + switch val := vSpec.Type.(type) { + case *ast.ArrayType: + isArrType = true + case *ast.Ident: + isArrType = contains(v.arrayTypes, val.Name) + } + if isArrType { + if vSpec.Names != nil { + /*atID, ok := arrayType.Elt.(*ast.Ident) + if !ok { + continue + }*/ + + // We should handle multiple slices declared on same line e.g. var mySlice1, mySlice2 []uint32 + for _, vName := range vSpec.Names { + v.sliceDeclarations = append(v.sliceDeclarations, &sliceDeclaration{name: vName.Name /*sType: atID.Name,*/, genD: genD}) + } + } + } + } + } + + case *ast.RangeStmt: + if v.includeRangeLoops { + if len(v.sliceDeclarations) == 0 { + continue + } + if s.Body != nil { + v.handleLoops(s.Body) + } + } + + case *ast.ForStmt: + if v.includeForLoops { + if len(v.sliceDeclarations) == 0 { + continue + } + if s.Body != nil { + v.handleLoops(s.Body) + } + } + + default: + } + } + } + } + return v +} + +// handleLoops is a helper function to share the logic required for both *ast.RangeLoops and *ast.ForLoops +func (v *returnsVisitor) handleLoops(blockStmt *ast.BlockStmt) { + + for _, stmt := range blockStmt.List { + switch bodyStmt := stmt.(type) { + case *ast.AssignStmt: + asgnStmt := bodyStmt + for _, expr := range asgnStmt.Rhs { + callExpr, ok := expr.(*ast.CallExpr) + if !ok { + continue // should this be break? comes back to multi-call support I think + } + ident, ok := callExpr.Fun.(*ast.Ident) + if !ok { + continue + } + if ident.Name == "append" { + // see if this append is appending the slice we found + for _, lhsExpr := range asgnStmt.Lhs { + lhsIdent, ok := lhsExpr.(*ast.Ident) + if !ok { + continue + } + for _, sliceDecl := range v.sliceDeclarations { + if sliceDecl.name == lhsIdent.Name { + // This is a potential mark, we just need to make sure there are no returns/continues in the + // range loop. + // now we just need to grab whatever we're ranging over + /*sxIdent, ok := s.X.(*ast.Ident) + if !ok { + continue + }*/ + + v.preallocHints = append(v.preallocHints, Hint{ + Pos: sliceDecl.genD.Pos(), + DeclaredSliceName: sliceDecl.name, + }) + } + } + } + + } + } + case *ast.IfStmt: + ifStmt := bodyStmt + if ifStmt.Body != nil { + for _, ifBodyStmt := range ifStmt.Body.List { + // TODO should probably handle embedded ifs here + switch /*ift :=*/ ifBodyStmt.(type) { + case *ast.BranchStmt, *ast.ReturnStmt: + v.returnsInsideOfLoop = true + default: + } + } + } + + default: + + } + } + +} + +// Hint stores the information about an occurence of a slice that could be +// preallocated. +type Hint struct { + Pos token.Pos + DeclaredSliceName string +} + +func (h Hint) String() string { + return fmt.Sprintf("%v: Consider preallocating %v", h.Pos, h.DeclaredSliceName) +} diff --git a/vendor/github.com/golangci/revgrep/.gitignore b/vendor/github.com/golangci/revgrep/.gitignore new file mode 100644 index 000000000..0540fe2ca --- /dev/null +++ b/vendor/github.com/golangci/revgrep/.gitignore @@ -0,0 +1 @@ +testdata/git diff --git a/vendor/github.com/golangci/revgrep/.travis.yml b/vendor/github.com/golangci/revgrep/.travis.yml new file mode 100644 index 000000000..d16d8b5bd --- /dev/null +++ b/vendor/github.com/golangci/revgrep/.travis.yml @@ -0,0 +1,7 @@ +language: go +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -service=travis-ci + diff --git a/vendor/github.com/golangci/revgrep/LICENSE b/vendor/github.com/golangci/revgrep/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/vendor/github.com/golangci/revgrep/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/golangci/revgrep/README.md b/vendor/github.com/golangci/revgrep/README.md new file mode 100644 index 000000000..31faefee9 --- /dev/null +++ b/vendor/github.com/golangci/revgrep/README.md @@ -0,0 +1,58 @@ +# Overview + +[![Build Status](https://travis-ci.org/bradleyfalzon/revgrep.svg?branch=master)](https://travis-ci.org/bradleyfalzon/revgrep) [![Coverage +Status](https://coveralls.io/repos/github/bradleyfalzon/revgrep/badge.svg?branch=master)](https://coveralls.io/github/bradleyfalzon/revgrep?branch=master) [![GoDoc](https://godoc.org/github.com/bradleyfalzon/revgrep?status.svg)](https://godoc.org/github.com/bradleyfalzon/revgrep) + +`revgrep` is a CLI tool used to filter static analysis tools to only lines changed based on a commit reference. + +# Install + +```bash +go get -u github.com/bradleyfalzon/revgrep/... +``` + +# Usage + +In the scenario below, a change was made causing a warning in `go vet` on line 5, but `go vet` will show all warnings. +Using `revgrep`, you can show only warnings for lines of code that have been changed (in this case, hiding line 6). + +```bash +[user@host dir (master)]$ go vet +main.go:5: missing argument for Sprintf("%s"): format reads arg 1, have only 0 args +main.go:6: missing argument for Sprintf("%s"): format reads arg 1, have only 0 args +[user@host dir (master)]$ go vet |& revgrep +main.go:5: missing argument for Sprintf("%s"): format reads arg 1, have only 0 args +``` + +`|&` is shown above as many static analysis programs write to `stderr`, not `stdout`, `|&` combines both `stderr` and +`stdout`. It could also be achieved with `go vet 2>&1 | revgrep`. + +`revgrep` CLI tool will return an exit status of 1 if any issues match, else it will return 0. Consider using +`${PIPESTATUS[0]}` for the exit status of the `go vet` command in the above example. + +``` +Usage: revgrep [options] [from-rev] [to-rev] + +from-rev filters issues to lines changed since (and including) this revision + to-rev filters issues to lines changed since (and including) this revision, requires + + If no revisions are given, and there are unstaged changes or untracked files, only those changes are shown + If no revisions are given, and there are no unstaged changes or untracked files, only changes in HEAD~ are shown + If from-rev is given and to-rev is not, only changes between from-rev and HEAD are shown. + + -d Show debug output + -regexp string + Regexp to match path, line number, optional column number, and message +``` + +# Other Examples + +Issues between branches: +```bash +[user@host dir (feature/branch)]$ go vet |& revgrep master +``` + +Issues since last push: +```bash +[user@host dir (master)]$ go vet |& revgrep origin/master +``` diff --git a/vendor/github.com/golangci/revgrep/revgrep.go b/vendor/github.com/golangci/revgrep/revgrep.go new file mode 100644 index 000000000..1a56dcf4e --- /dev/null +++ b/vendor/github.com/golangci/revgrep/revgrep.go @@ -0,0 +1,395 @@ +package revgrep + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "regexp" + "strconv" + "strings" +) + +// Checker provides APIs to filter static analysis tools to specific commits, +// such as showing only issues since last commit. +type Checker struct { + // Patch file (unified) to read to detect lines being changed, if nil revgrep + // will attempt to detect the VCS and generate an appropriate patch. Auto + // detection will search for uncommitted changes first, if none found, will + // generate a patch from last committed change. File paths within patches + // must be relative to current working directory. + Patch io.Reader + // NewFiles is a list of file names (with absolute paths) where the entire + // contents of the file is new. + NewFiles []string + // Debug sets the debug writer for additional output. + Debug io.Writer + // RevisionFrom check revision starting at, leave blank for auto detection + // ignored if patch is set. + RevisionFrom string + // RevisionTo checks revision finishing at, leave blank for auto detection + // ignored if patch is set. + RevisionTo string + // Regexp to match path, line number, optional column number, and message. + Regexp string + // AbsPath is used to make an absolute path of an issue's filename to be + // relative in order to match patch file. If not set, current working + // directory is used. + AbsPath string + + // Calculated changes for next calls to IsNewIssue + changes map[string][]pos +} + +// Issue contains metadata about an issue found. +type Issue struct { + // File is the name of the file as it appeared from the patch. + File string + // LineNo is the line number of the file. + LineNo int + // ColNo is the column number or 0 if none could be parsed. + ColNo int + // HunkPos is position from file's first @@, for new files this will be the + // line number. + // + // See also: https://developer.github.com/v3/pulls/comments/#create-a-comment + HunkPos int + // Issue text as it appeared from the tool. + Issue string + // Message is the issue without file name, line number and column number. + Message string +} + +func (c *Checker) preparePatch() error { + // Check if patch is supplied, if not, retrieve from VCS + if c.Patch == nil { + var err error + c.Patch, c.NewFiles, err = GitPatch(c.RevisionFrom, c.RevisionTo) + if err != nil { + return fmt.Errorf("could not read git repo: %s", err) + } + if c.Patch == nil { + return errors.New("no version control repository found") + } + } + + return nil +} + +type InputIssue interface { + FilePath() string + Line() int +} + +type simpleInputIssue struct { + filePath string + lineNumber int +} + +func (i simpleInputIssue) FilePath() string { + return i.filePath +} + +func (i simpleInputIssue) Line() int { + return i.lineNumber +} + +func (c *Checker) Prepare() error { + returnErr := c.preparePatch() + c.changes = c.linesChanged() + return returnErr +} + +func (c Checker) IsNewIssue(i InputIssue) (hunkPos int, isNew bool) { + fchanges, ok := c.changes[i.FilePath()] + if !ok { // file wasn't changed + return 0, false + } + + var ( + fpos pos + changed bool + ) + // found file, see if lines matched + for _, pos := range fchanges { + if pos.lineNo == int(i.Line()) { + fpos = pos + changed = true + break + } + } + + if changed || fchanges == nil { + // either file changed or it's a new file + hunkPos := fpos.lineNo + if changed { // existing file changed + hunkPos = fpos.hunkPos + } + + return hunkPos, true + } + + return 0, false +} + +// Check scans reader and writes any lines to writer that have been added in +// Checker.Patch. +// +// Returns issues written to writer when no error occurs. +// +// If no VCS could be found or other VCS errors occur, all issues are written +// to writer and an error is returned. +// +// File paths in reader must be relative to current working directory or +// absolute. +func (c Checker) Check(reader io.Reader, writer io.Writer) (issues []Issue, err error) { + returnErr := c.Prepare() + writeAll := returnErr != nil + + // file.go:lineNo:colNo:message + // colNo is optional, strip spaces before message + lineRE := regexp.MustCompile(`(.*?\.go):([0-9]+):([0-9]+)?:?\s*(.*)`) + if c.Regexp != "" { + lineRE, err = regexp.Compile(c.Regexp) + if err != nil { + return nil, fmt.Errorf("could not parse regexp: %v", err) + } + } + + // TODO consider lazy loading this, if there's nothing in stdin, no point + // checking for recent changes + c.debugf("lines changed: %+v", c.changes) + + absPath := c.AbsPath + if absPath == "" { + absPath, err = os.Getwd() + if err != nil { + returnErr = fmt.Errorf("could not get current working directory: %s", err) + } + } + + // Scan each line in reader and only write those lines if lines changed + scanner := bufio.NewScanner(reader) + for scanner.Scan() { + line := lineRE.FindSubmatch(scanner.Bytes()) + if line == nil { + c.debugf("cannot parse file+line number: %s", scanner.Text()) + continue + } + + if writeAll { + fmt.Fprintln(writer, scanner.Text()) + continue + } + + // Make absolute path names relative + path := string(line[1]) + if rel, err := filepath.Rel(absPath, path); err == nil { + c.debugf("rewrote path from %q to %q (absPath: %q)", path, rel, absPath) + path = rel + } + + // Parse line number + lno, err := strconv.ParseUint(string(line[2]), 10, 64) + if err != nil { + c.debugf("cannot parse line number: %q", scanner.Text()) + continue + } + + // Parse optional column number + var cno uint64 + if len(line[3]) > 0 { + cno, err = strconv.ParseUint(string(line[3]), 10, 64) + if err != nil { + c.debugf("cannot parse column number: %q", scanner.Text()) + // Ignore this error and continue + } + } + + // Extract message + msg := string(line[4]) + + c.debugf("path: %q, lineNo: %v, colNo: %v, msg: %q", path, lno, cno, msg) + i := simpleInputIssue{ + filePath: path, + lineNumber: int(lno), + } + hunkPos, changed := c.IsNewIssue(i) + if changed { + issue := Issue{ + File: path, + LineNo: int(lno), + ColNo: int(cno), + HunkPos: hunkPos, + Issue: scanner.Text(), + Message: msg, + } + issues = append(issues, issue) + fmt.Fprintln(writer, scanner.Text()) + } else { + c.debugf("unchanged: %s", scanner.Text()) + } + } + if err := scanner.Err(); err != nil { + returnErr = fmt.Errorf("error reading standard input: %s", err) + } + return issues, returnErr +} + +func (c Checker) debugf(format string, s ...interface{}) { + if c.Debug != nil { + fmt.Fprint(c.Debug, "DEBUG: ") + fmt.Fprintf(c.Debug, format+"\n", s...) + } +} + +type pos struct { + lineNo int // line number + hunkPos int // position relative to first @@ in file +} + +// linesChanges returns a map of file names to line numbers being changed. +// If key is nil, the file has been recently added, else it contains a slice +// of positions that have been added. +func (c Checker) linesChanged() map[string][]pos { + type state struct { + file string + lineNo int // current line number within chunk + hunkPos int // current line count since first @@ in file + changes []pos // position of changes + } + + var ( + s state + changes = make(map[string][]pos) + ) + + for _, file := range c.NewFiles { + changes[file] = nil + } + + if c.Patch == nil { + return changes + } + + scanner := bufio.NewScanner(c.Patch) + for scanner.Scan() { + line := scanner.Text() // TODO scanner.Bytes() + c.debugf(line) + s.lineNo++ + s.hunkPos++ + switch { + case strings.HasPrefix(line, "+++ ") && len(line) > 4: + if s.changes != nil { + // record the last state + changes[s.file] = s.changes + } + // 6 removes "+++ b/" + s = state{file: line[6:], hunkPos: -1, changes: []pos{}} + case strings.HasPrefix(line, "@@ "): + // @@ -1 +2,4 @@ + // chdr ^^^^^^^^^^^^^ + // ahdr ^^^^ + // cstart ^ + chdr := strings.Split(line, " ") + ahdr := strings.Split(chdr[2], ",") + // [1:] to remove leading plus + cstart, err := strconv.ParseUint(ahdr[0][1:], 10, 64) + if err != nil { + panic(err) + } + s.lineNo = int(cstart) - 1 // -1 as cstart is the next line number + case strings.HasPrefix(line, "-"): + s.lineNo-- + case strings.HasPrefix(line, "+"): + s.changes = append(s.changes, pos{lineNo: s.lineNo, hunkPos: s.hunkPos}) + } + + } + if err := scanner.Err(); err != nil { + fmt.Fprintln(os.Stderr, "reading standard input:", err) + } + // record the last state + changes[s.file] = s.changes + + return changes +} + +// GitPatch returns a patch from a git repository, if no git repository was +// was found and no errors occurred, nil is returned, else an error is returned +// revisionFrom and revisionTo defines the git diff parameters, if left blank +// and there are unstaged changes or untracked files, only those will be returned +// else only check changes since HEAD~. If revisionFrom is set but revisionTo +// is not, untracked files will be included, to exclude untracked files set +// revisionTo to HEAD~. It's incorrect to specify revisionTo without a +// revisionFrom. +func GitPatch(revisionFrom, revisionTo string) (io.Reader, []string, error) { + var patch bytes.Buffer + + // check if git repo exists + if err := exec.Command("git", "status").Run(); err != nil { + // don't return an error, we assume the error is not repo exists + return nil, nil, nil + } + + // make a patch for untracked files + var newFiles []string + ls, err := exec.Command("git", "ls-files", "-o").CombinedOutput() + if err != nil { + return nil, nil, fmt.Errorf("error executing git ls-files: %s", err) + } + for _, file := range bytes.Split(ls, []byte{'\n'}) { + if len(file) == 0 || bytes.HasSuffix(file, []byte{'/'}) { + // ls-files was sometimes showing directories when they were ignored + // I couldn't create a test case for this as I couldn't reproduce correctly + // for the moment, just exclude files with trailing / + continue + } + newFiles = append(newFiles, string(file)) + } + + if revisionFrom != "" { + cmd := exec.Command("git", "diff", "--relative", revisionFrom) + if revisionTo != "" { + cmd.Args = append(cmd.Args, revisionTo) + } + cmd.Stdout = &patch + if err := cmd.Run(); err != nil { + return nil, nil, fmt.Errorf("error executing git diff %q %q: %s", revisionFrom, revisionTo, err) + } + + if revisionTo == "" { + return &patch, newFiles, nil + } + return &patch, nil, nil + } + + // make a patch for unstaged changes + // use --no-prefix to remove b/ given: +++ b/main.go + cmd := exec.Command("git", "diff", "--relative") + cmd.Stdout = &patch + if err := cmd.Run(); err != nil { + return nil, nil, fmt.Errorf("error executing git diff: %s", err) + } + unstaged := patch.Len() > 0 + + // If there's unstaged changes OR untracked changes (or both), then this is + // a suitable patch + if unstaged || newFiles != nil { + return &patch, newFiles, nil + } + + // check for changes in recent commit + + cmd = exec.Command("git", "diff", "--relative", "HEAD~") + cmd.Stdout = &patch + if err := cmd.Run(); err != nil { + return nil, nil, fmt.Errorf("error executing git diff HEAD~: %s", err) + } + + return &patch, nil, nil +} diff --git a/vendor/github.com/golangci/unconvert/LICENSE b/vendor/github.com/golangci/unconvert/LICENSE new file mode 100644 index 000000000..744875676 --- /dev/null +++ b/vendor/github.com/golangci/unconvert/LICENSE @@ -0,0 +1,27 @@ +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. diff --git a/vendor/github.com/golangci/unconvert/README b/vendor/github.com/golangci/unconvert/README new file mode 100644 index 000000000..dbaea4f57 --- /dev/null +++ b/vendor/github.com/golangci/unconvert/README @@ -0,0 +1,36 @@ +About: + +The unconvert program analyzes Go packages to identify unnecessary +type conversions; i.e., expressions T(x) where x already has type T. + +Install: + + $ go get github.com/mdempsky/unconvert + +Usage: + + $ unconvert -v bytes fmt + GOROOT/src/bytes/reader.go:117:14: unnecessary conversion + abs = int64(r.i) + offset + ^ + GOROOT/src/fmt/print.go:411:21: unnecessary conversion + p.fmt.integer(int64(v), 16, unsigned, udigits) + ^ + +Flags: + +Using the -v flag, unconvert will also print the source line and a +caret to indicate the unnecessary conversion's position therein. + +Using the -apply flag, unconvert will rewrite the Go source files +without the unnecessary type conversions. + +Using the -all flag, unconvert will analyze the Go packages under all +possible GOOS/GOARCH combinations, and only identify conversions that +are unnecessary in all cases. + +E.g., syscall.Timespec's Sec and Nsec fields are int64 under +linux/amd64 but int32 under linux/386. An int64(ts.Sec) conversion +that appears in a linux/amd64-only file will be identified as +unnecessary, but it will be preserved if it occurs in a file that's +compiled for both linux/amd64 and linux/386. diff --git a/vendor/github.com/golangci/unconvert/unconvert.go b/vendor/github.com/golangci/unconvert/unconvert.go new file mode 100644 index 000000000..38737d39f --- /dev/null +++ b/vendor/github.com/golangci/unconvert/unconvert.go @@ -0,0 +1,665 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Unconvert removes redundant type conversions from Go packages. +package unconvert + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/build" + "go/format" + "go/parser" + "go/token" + "go/types" + "io/ioutil" + "log" + "os" + "reflect" + "runtime/pprof" + "sort" + "sync" + "unicode" + + "github.com/kisielk/gotool" + "golang.org/x/text/width" + "golang.org/x/tools/go/loader" +) + +// Unnecessary conversions are identified by the position +// of their left parenthesis within a source file. + +type editSet map[token.Position]struct{} + +type fileToEditSet map[string]editSet + +func apply(file string, edits editSet) { + if len(edits) == 0 { + return + } + + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, file, nil, parser.ParseComments) + if err != nil { + log.Fatal(err) + } + + // Note: We modify edits during the walk. + v := editor{edits: edits, file: fset.File(f.Package)} + ast.Walk(&v, f) + if len(edits) != 0 { + log.Printf("%s: missing edits %s", file, edits) + } + + // TODO(mdempsky): Write to temporary file and rename. + var buf bytes.Buffer + err = format.Node(&buf, fset, f) + if err != nil { + log.Fatal(err) + } + + err = ioutil.WriteFile(file, buf.Bytes(), 0) + if err != nil { + log.Fatal(err) + } +} + +type editor struct { + edits editSet + file *token.File +} + +func (e *editor) Visit(n ast.Node) ast.Visitor { + if n == nil { + return nil + } + v := reflect.ValueOf(n).Elem() + for i, n := 0, v.NumField(); i < n; i++ { + switch f := v.Field(i).Addr().Interface().(type) { + case *ast.Expr: + e.rewrite(f) + case *[]ast.Expr: + for i := range *f { + e.rewrite(&(*f)[i]) + } + } + } + return e +} + +func (e *editor) rewrite(f *ast.Expr) { + call, ok := (*f).(*ast.CallExpr) + if !ok { + return + } + + pos := e.file.Position(call.Lparen) + if _, ok := e.edits[pos]; !ok { + return + } + *f = call.Args[0] + delete(e.edits, pos) +} + +var ( + cr = []byte{'\r'} + nl = []byte{'\n'} +) + +func print(conversions []token.Position) { + var file string + var lines [][]byte + + for _, pos := range conversions { + fmt.Printf("%s:%d:%d: unnecessary conversion\n", pos.Filename, pos.Line, pos.Column) + if *flagV { + if pos.Filename != file { + buf, err := ioutil.ReadFile(pos.Filename) + if err != nil { + log.Fatal(err) + } + file = pos.Filename + lines = bytes.Split(buf, nl) + } + + line := bytes.TrimSuffix(lines[pos.Line-1], cr) + fmt.Printf("%s\n", line) + + // For files processed by cgo, Column is the + // column location after cgo processing, which + // may be different than the source column + // that we want here. In lieu of a better + // heuristic for detecting this case, at least + // avoid panicking if column is out of bounds. + if pos.Column <= len(line) { + fmt.Printf("%s^\n", rub(line[:pos.Column-1])) + } + } + } +} + +// Rub returns a copy of buf with all non-whitespace characters replaced +// by spaces (like rubbing them out with white out). +func rub(buf []byte) []byte { + // TODO(mdempsky): Handle combining characters? + var res bytes.Buffer + for _, r := range string(buf) { + if unicode.IsSpace(r) { + res.WriteRune(r) + continue + } + switch width.LookupRune(r).Kind() { + case width.EastAsianWide, width.EastAsianFullwidth: + res.WriteString(" ") + default: + res.WriteByte(' ') + } + } + return res.Bytes() +} + +var ( + flagAll = flag.Bool("unconvert.all", false, "type check all GOOS and GOARCH combinations") + flagApply = flag.Bool("unconvert.apply", false, "apply edits to source files") + flagCPUProfile = flag.String("unconvert.cpuprofile", "", "write CPU profile to file") + // TODO(mdempsky): Better description and maybe flag name. + flagSafe = flag.Bool("unconvert.safe", false, "be more conservative (experimental)") + flagV = flag.Bool("unconvert.v", false, "verbose output") +) + +func usage() { + fmt.Fprintf(os.Stderr, "usage: unconvert [flags] [package ...]\n") + flag.PrintDefaults() +} + +func nomain() { + flag.Usage = usage + flag.Parse() + + if *flagCPUProfile != "" { + f, err := os.Create(*flagCPUProfile) + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + } + + importPaths := gotool.ImportPaths(flag.Args()) + if len(importPaths) == 0 { + return + } + + var m fileToEditSet + if *flagAll { + m = mergeEdits(importPaths) + } else { + m = computeEdits(importPaths, build.Default.GOOS, build.Default.GOARCH, build.Default.CgoEnabled) + } + + if *flagApply { + var wg sync.WaitGroup + for f, e := range m { + wg.Add(1) + f, e := f, e + go func() { + defer wg.Done() + apply(f, e) + }() + } + wg.Wait() + } else { + var conversions []token.Position + for _, positions := range m { + for pos := range positions { + conversions = append(conversions, pos) + } + } + sort.Sort(byPosition(conversions)) + print(conversions) + if len(conversions) > 0 { + os.Exit(1) + } + } +} + +func Run(prog *loader.Program) []token.Position { + m := computeEditsFromProg(prog) + var conversions []token.Position + for _, positions := range m { + for pos := range positions { + conversions = append(conversions, pos) + } + } + return conversions +} + +var plats = [...]struct { + goos, goarch string +}{ + // TODO(mdempsky): buildall.bash also builds linux-386-387 and linux-arm-arm5. + {"android", "386"}, + {"android", "amd64"}, + {"android", "arm"}, + {"android", "arm64"}, + {"darwin", "386"}, + {"darwin", "amd64"}, + {"darwin", "arm"}, + {"darwin", "arm64"}, + {"dragonfly", "amd64"}, + {"freebsd", "386"}, + {"freebsd", "amd64"}, + {"freebsd", "arm"}, + {"linux", "386"}, + {"linux", "amd64"}, + {"linux", "arm"}, + {"linux", "arm64"}, + {"linux", "mips64"}, + {"linux", "mips64le"}, + {"linux", "ppc64"}, + {"linux", "ppc64le"}, + {"linux", "s390x"}, + {"nacl", "386"}, + {"nacl", "amd64p32"}, + {"nacl", "arm"}, + {"netbsd", "386"}, + {"netbsd", "amd64"}, + {"netbsd", "arm"}, + {"openbsd", "386"}, + {"openbsd", "amd64"}, + {"openbsd", "arm"}, + {"plan9", "386"}, + {"plan9", "amd64"}, + {"plan9", "arm"}, + {"solaris", "amd64"}, + {"windows", "386"}, + {"windows", "amd64"}, +} + +func mergeEdits(importPaths []string) fileToEditSet { + m := make(fileToEditSet) + for _, plat := range plats { + for f, e := range computeEdits(importPaths, plat.goos, plat.goarch, false) { + if e0, ok := m[f]; ok { + for k := range e0 { + if _, ok := e[k]; !ok { + delete(e0, k) + } + } + } else { + m[f] = e + } + } + } + return m +} + +type noImporter struct{} + +func (noImporter) Import(path string) (*types.Package, error) { + panic("golang.org/x/tools/go/loader said this wouldn't be called") +} + +func computeEdits(importPaths []string, os, arch string, cgoEnabled bool) fileToEditSet { + ctxt := build.Default + ctxt.GOOS = os + ctxt.GOARCH = arch + ctxt.CgoEnabled = cgoEnabled + + var conf loader.Config + conf.Build = &ctxt + conf.TypeChecker.Importer = noImporter{} + for _, importPath := range importPaths { + conf.Import(importPath) + } + prog, err := conf.Load() + if err != nil { + log.Fatal(err) + } + + return computeEditsFromProg(prog) +} + +func computeEditsFromProg(prog *loader.Program) fileToEditSet { + type res struct { + file string + edits editSet + } + ch := make(chan res) + var wg sync.WaitGroup + for _, pkg := range prog.InitialPackages() { + for _, file := range pkg.Files { + pkg, file := pkg, file + wg.Add(1) + go func() { + defer wg.Done() + v := visitor{pkg: pkg, file: prog.Fset.File(file.Package), edits: make(editSet)} + ast.Walk(&v, file) + ch <- res{v.file.Name(), v.edits} + }() + } + } + go func() { + wg.Wait() + close(ch) + }() + + m := make(fileToEditSet) + for r := range ch { + m[r.file] = r.edits + } + return m +} + +type step struct { + n ast.Node + i int +} + +type visitor struct { + pkg *loader.PackageInfo + file *token.File + edits editSet + path []step +} + +func (v *visitor) Visit(node ast.Node) ast.Visitor { + if node != nil { + v.path = append(v.path, step{n: node}) + } else { + n := len(v.path) + v.path = v.path[:n-1] + if n >= 2 { + v.path[n-2].i++ + } + } + + if call, ok := node.(*ast.CallExpr); ok { + v.unconvert(call) + } + return v +} + +func (v *visitor) unconvert(call *ast.CallExpr) { + // TODO(mdempsky): Handle useless multi-conversions. + + // Conversions have exactly one argument. + if len(call.Args) != 1 || call.Ellipsis != token.NoPos { + return + } + ft, ok := v.pkg.Types[call.Fun] + if !ok { + fmt.Println("Missing type for function") + return + } + if !ft.IsType() { + // Function call; not a conversion. + return + } + at, ok := v.pkg.Types[call.Args[0]] + if !ok { + fmt.Println("Missing type for argument") + return + } + if !types.Identical(ft.Type, at.Type) { + // A real conversion. + return + } + if isUntypedValue(call.Args[0], &v.pkg.Info) { + // Workaround golang.org/issue/13061. + return + } + if *flagSafe && !v.isSafeContext(at.Type) { + // TODO(mdempsky): Remove this message. + fmt.Println("Skipped a possible type conversion because of -safe at", v.file.Position(call.Pos())) + return + } + if v.isCgoCheckPointerContext() { + // cmd/cgo generates explicit type conversions that + // are often redundant when introducing + // _cgoCheckPointer calls (issue #16). Users can't do + // anything about these, so skip over them. + return + } + + v.edits[v.file.Position(call.Lparen)] = struct{}{} +} + +func (v *visitor) isCgoCheckPointerContext() bool { + ctxt := &v.path[len(v.path)-2] + if ctxt.i != 1 { + return false + } + call, ok := ctxt.n.(*ast.CallExpr) + if !ok { + return false + } + ident, ok := call.Fun.(*ast.Ident) + if !ok { + return false + } + return ident.Name == "_cgoCheckPointer" +} + +// isSafeContext reports whether the current context requires +// an expression of type t. +// +// TODO(mdempsky): That's a bad explanation. +func (v *visitor) isSafeContext(t types.Type) bool { + ctxt := &v.path[len(v.path)-2] + switch n := ctxt.n.(type) { + case *ast.AssignStmt: + pos := ctxt.i - len(n.Lhs) + if pos < 0 { + fmt.Println("Type conversion on LHS of assignment?") + return false + } + if n.Tok == token.DEFINE { + // Skip := assignments. + return true + } + // We're a conversion in the pos'th element of n.Rhs. + // Check that the corresponding element of n.Lhs is of type t. + lt, ok := v.pkg.Types[n.Lhs[pos]] + if !ok { + fmt.Println("Missing type for LHS expression") + return false + } + return types.Identical(t, lt.Type) + case *ast.BinaryExpr: + if n.Op == token.SHL || n.Op == token.SHR { + if ctxt.i == 1 { + // RHS of a shift is always safe. + return true + } + // For the LHS, we should inspect up another level. + fmt.Println("TODO(mdempsky): Handle LHS of shift expressions") + return true + } + var other ast.Expr + if ctxt.i == 0 { + other = n.Y + } else { + other = n.X + } + ot, ok := v.pkg.Types[other] + if !ok { + fmt.Println("Missing type for other binop subexpr") + return false + } + return types.Identical(t, ot.Type) + case *ast.CallExpr: + pos := ctxt.i - 1 + if pos < 0 { + // Type conversion in the function subexpr is okay. + return true + } + ft, ok := v.pkg.Types[n.Fun] + if !ok { + fmt.Println("Missing type for function expression") + return false + } + sig, ok := ft.Type.(*types.Signature) + if !ok { + // "Function" is either a type conversion (ok) or a builtin (ok?). + return true + } + params := sig.Params() + var pt types.Type + if sig.Variadic() && n.Ellipsis == token.NoPos && pos >= params.Len()-1 { + pt = params.At(params.Len() - 1).Type().(*types.Slice).Elem() + } else { + pt = params.At(pos).Type() + } + return types.Identical(t, pt) + case *ast.CompositeLit, *ast.KeyValueExpr: + fmt.Println("TODO(mdempsky): Compare against value type of composite literal type at", v.file.Position(n.Pos())) + return true + case *ast.ReturnStmt: + // TODO(mdempsky): Is there a better way to get the corresponding + // return parameter type? + var funcType *ast.FuncType + for i := len(v.path) - 1; funcType == nil && i >= 0; i-- { + switch f := v.path[i].n.(type) { + case *ast.FuncDecl: + funcType = f.Type + case *ast.FuncLit: + funcType = f.Type + } + } + var typeExpr ast.Expr + for i, j := ctxt.i, 0; j < len(funcType.Results.List); j++ { + f := funcType.Results.List[j] + if len(f.Names) == 0 { + if i >= 1 { + i-- + continue + } + } else { + if i >= len(f.Names) { + i -= len(f.Names) + continue + } + } + typeExpr = f.Type + break + } + if typeExpr == nil { + fmt.Println(ctxt) + } + pt, ok := v.pkg.Types[typeExpr] + if !ok { + fmt.Println("Missing type for return parameter at", v.file.Position(n.Pos())) + return false + } + return types.Identical(t, pt.Type) + case *ast.StarExpr, *ast.UnaryExpr: + // TODO(mdempsky): I think these are always safe. + return true + case *ast.SwitchStmt: + // TODO(mdempsky): I think this is always safe? + return true + default: + // TODO(mdempsky): When can this happen? + fmt.Printf("... huh, %T at %v\n", n, v.file.Position(n.Pos())) + return true + } +} + +func isUntypedValue(n ast.Expr, info *types.Info) (res bool) { + switch n := n.(type) { + case *ast.BinaryExpr: + switch n.Op { + case token.SHL, token.SHR: + // Shifts yield an untyped value if their LHS is untyped. + return isUntypedValue(n.X, info) + case token.EQL, token.NEQ, token.LSS, token.GTR, token.LEQ, token.GEQ: + // Comparisons yield an untyped boolean value. + return true + case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, + token.AND, token.OR, token.XOR, token.AND_NOT, + token.LAND, token.LOR: + return isUntypedValue(n.X, info) && isUntypedValue(n.Y, info) + } + case *ast.UnaryExpr: + switch n.Op { + case token.ADD, token.SUB, token.NOT, token.XOR: + return isUntypedValue(n.X, info) + } + case *ast.BasicLit: + // Basic literals are always untyped. + return true + case *ast.ParenExpr: + return isUntypedValue(n.X, info) + case *ast.SelectorExpr: + return isUntypedValue(n.Sel, info) + case *ast.Ident: + if obj, ok := info.Uses[n]; ok { + if obj.Pkg() == nil && obj.Name() == "nil" { + // The universal untyped zero value. + return true + } + if b, ok := obj.Type().(*types.Basic); ok && b.Info()&types.IsUntyped != 0 { + // Reference to an untyped constant. + return true + } + } + case *ast.CallExpr: + if b, ok := asBuiltin(n.Fun, info); ok { + switch b.Name() { + case "real", "imag": + return isUntypedValue(n.Args[0], info) + case "complex": + return isUntypedValue(n.Args[0], info) && isUntypedValue(n.Args[1], info) + } + } + } + + return false +} + +func asBuiltin(n ast.Expr, info *types.Info) (*types.Builtin, bool) { + for { + paren, ok := n.(*ast.ParenExpr) + if !ok { + break + } + n = paren.X + } + + ident, ok := n.(*ast.Ident) + if !ok { + return nil, false + } + + obj, ok := info.Uses[ident] + if !ok { + return nil, false + } + + b, ok := obj.(*types.Builtin) + return b, ok +} + +type byPosition []token.Position + +func (p byPosition) Len() int { + return len(p) +} + +func (p byPosition) Less(i, j int) bool { + if p[i].Filename != p[j].Filename { + return p[i].Filename < p[j].Filename + } + if p[i].Line != p[j].Line { + return p[i].Line < p[j].Line + } + return p[i].Column < p[j].Column +} + +func (p byPosition) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} diff --git a/vendor/github.com/gostaticanalysis/analysisutil/LICENSE b/vendor/github.com/gostaticanalysis/analysisutil/LICENSE new file mode 100644 index 000000000..bf7e33db8 --- /dev/null +++ b/vendor/github.com/gostaticanalysis/analysisutil/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 GoStaticAnalysis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/gostaticanalysis/analysisutil/README.md b/vendor/github.com/gostaticanalysis/analysisutil/README.md new file mode 100644 index 000000000..c031e16e2 --- /dev/null +++ b/vendor/github.com/gostaticanalysis/analysisutil/README.md @@ -0,0 +1,10 @@ +# analysisutil + +[![godoc.org][godoc-badge]][godoc] + +Utilities for x/tools/go/analysis package. + + +[godoc]: https://godoc.org/github.com/gostaticanalysis/analysisutil +[godoc-badge]: https://img.shields.io/badge/godoc-reference-4F73B3.svg?style=flat-square&label=%20godoc.org + diff --git a/vendor/github.com/gostaticanalysis/analysisutil/file.go b/vendor/github.com/gostaticanalysis/analysisutil/file.go new file mode 100644 index 000000000..2aeca1d9e --- /dev/null +++ b/vendor/github.com/gostaticanalysis/analysisutil/file.go @@ -0,0 +1,18 @@ +package analysisutil + +import ( + "go/ast" + "go/token" + + "golang.org/x/tools/go/analysis" +) + +// File finds *ast.File in pass.Files by pos. +func File(pass *analysis.Pass, pos token.Pos) *ast.File { + for _, f := range pass.Files { + if f.Pos() <= pos && pos <= f.End() { + return f + } + } + return nil +} diff --git a/vendor/github.com/gostaticanalysis/analysisutil/go.mod b/vendor/github.com/gostaticanalysis/analysisutil/go.mod new file mode 100644 index 000000000..7e3e55be1 --- /dev/null +++ b/vendor/github.com/gostaticanalysis/analysisutil/go.mod @@ -0,0 +1,5 @@ +module github.com/gostaticanalysis/analysisutil + +go 1.12 + +require golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5 diff --git a/vendor/github.com/gostaticanalysis/analysisutil/go.sum b/vendor/github.com/gostaticanalysis/analysisutil/go.sum new file mode 100644 index 000000000..16c8787c4 --- /dev/null +++ b/vendor/github.com/gostaticanalysis/analysisutil/go.sum @@ -0,0 +1,6 @@ +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5 h1:ZcPpqKMdoZeNQ/4GHlyY4COf8n8SmpPv6mcqF1+VPSM= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= diff --git a/vendor/github.com/gostaticanalysis/analysisutil/pkg.go b/vendor/github.com/gostaticanalysis/analysisutil/pkg.go new file mode 100644 index 000000000..c98710d18 --- /dev/null +++ b/vendor/github.com/gostaticanalysis/analysisutil/pkg.go @@ -0,0 +1,26 @@ +package analysisutil + +import ( + "go/types" + "strings" +) + +// RemoVendor removes vendoring infomation from import path. +func RemoveVendor(path string) string { + i := strings.Index(path, "vendor") + if i >= 0 { + return path[i+len("vendor")+1:] + } + return path +} + +// LookupFromImports finds an object from import paths. +func LookupFromImports(imports []*types.Package, path, name string) types.Object { + path = RemoveVendor(path) + for i := range imports { + if path == RemoveVendor(imports[i].Path()) { + return imports[i].Scope().Lookup(name) + } + } + return nil +} diff --git a/vendor/github.com/gostaticanalysis/analysisutil/ssa.go b/vendor/github.com/gostaticanalysis/analysisutil/ssa.go new file mode 100644 index 000000000..379158667 --- /dev/null +++ b/vendor/github.com/gostaticanalysis/analysisutil/ssa.go @@ -0,0 +1,31 @@ +package analysisutil + +import "golang.org/x/tools/go/ssa" + +// IfInstr returns *ssa.If which is contained in the block b. +// If the block b has not any if instruction, IfInstr returns nil. +func IfInstr(b *ssa.BasicBlock) *ssa.If { + if len(b.Instrs) == 0 { + return nil + } + + ifinstr, ok := b.Instrs[len(b.Instrs)-1].(*ssa.If) + if !ok { + return nil + } + + return ifinstr +} + +// Phi returns phi values which are contained in the block b. +func Phi(b *ssa.BasicBlock) (phis []*ssa.Phi) { + for _, instr := range b.Instrs { + if phi, ok := instr.(*ssa.Phi); ok { + phis = append(phis, phi) + } else { + // no more phi + break + } + } + return +} diff --git a/vendor/github.com/hashicorp/hcl/.gitignore b/vendor/github.com/hashicorp/hcl/.gitignore new file mode 100644 index 000000000..15586a2b5 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/.gitignore @@ -0,0 +1,9 @@ +y.output + +# ignore intellij files +.idea +*.iml +*.ipr +*.iws + +*.test diff --git a/vendor/github.com/hashicorp/hcl/.travis.yml b/vendor/github.com/hashicorp/hcl/.travis.yml new file mode 100644 index 000000000..cb63a3216 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/.travis.yml @@ -0,0 +1,13 @@ +sudo: false + +language: go + +go: + - 1.x + - tip + +branches: + only: + - master + +script: make test diff --git a/vendor/github.com/hashicorp/hcl/LICENSE b/vendor/github.com/hashicorp/hcl/LICENSE new file mode 100644 index 000000000..c33dcc7c9 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/hcl/Makefile b/vendor/github.com/hashicorp/hcl/Makefile new file mode 100644 index 000000000..84fd743f5 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/Makefile @@ -0,0 +1,18 @@ +TEST?=./... + +default: test + +fmt: generate + go fmt ./... + +test: generate + go get -t ./... + go test $(TEST) $(TESTARGS) + +generate: + go generate ./... + +updatedeps: + go get -u golang.org/x/tools/cmd/stringer + +.PHONY: default generate test updatedeps diff --git a/vendor/github.com/hashicorp/hcl/README.md b/vendor/github.com/hashicorp/hcl/README.md new file mode 100644 index 000000000..c8223326d --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/README.md @@ -0,0 +1,125 @@ +# HCL + +[![GoDoc](https://godoc.org/github.com/hashicorp/hcl?status.png)](https://godoc.org/github.com/hashicorp/hcl) [![Build Status](https://travis-ci.org/hashicorp/hcl.svg?branch=master)](https://travis-ci.org/hashicorp/hcl) + +HCL (HashiCorp Configuration Language) is a configuration language built +by HashiCorp. The goal of HCL is to build a structured configuration language +that is both human and machine friendly for use with command-line tools, but +specifically targeted towards DevOps tools, servers, etc. + +HCL is also fully JSON compatible. That is, JSON can be used as completely +valid input to a system expecting HCL. This helps makes systems +interoperable with other systems. + +HCL is heavily inspired by +[libucl](https://github.com/vstakhov/libucl), +nginx configuration, and others similar. + +## Why? + +A common question when viewing HCL is to ask the question: why not +JSON, YAML, etc.? + +Prior to HCL, the tools we built at [HashiCorp](http://www.hashicorp.com) +used a variety of configuration languages from full programming languages +such as Ruby to complete data structure languages such as JSON. What we +learned is that some people wanted human-friendly configuration languages +and some people wanted machine-friendly languages. + +JSON fits a nice balance in this, but is fairly verbose and most +importantly doesn't support comments. With YAML, we found that beginners +had a really hard time determining what the actual structure was, and +ended up guessing more often than not whether to use a hyphen, colon, etc. +in order to represent some configuration key. + +Full programming languages such as Ruby enable complex behavior +a configuration language shouldn't usually allow, and also forces +people to learn some set of Ruby. + +Because of this, we decided to create our own configuration language +that is JSON-compatible. Our configuration language (HCL) is designed +to be written and modified by humans. The API for HCL allows JSON +as an input so that it is also machine-friendly (machines can generate +JSON instead of trying to generate HCL). + +Our goal with HCL is not to alienate other configuration languages. +It is instead to provide HCL as a specialized language for our tools, +and JSON as the interoperability layer. + +## Syntax + +For a complete grammar, please see the parser itself. A high-level overview +of the syntax and grammar is listed here. + + * Single line comments start with `#` or `//` + + * Multi-line comments are wrapped in `/*` and `*/`. Nested block comments + are not allowed. A multi-line comment (also known as a block comment) + terminates at the first `*/` found. + + * Values are assigned with the syntax `key = value` (whitespace doesn't + matter). The value can be any primitive: a string, number, boolean, + object, or list. + + * Strings are double-quoted and can contain any UTF-8 characters. + Example: `"Hello, World"` + + * Multi-line strings start with `<- + echo %Path% + + go version + + go env + + go get -t ./... + +build_script: +- cmd: go test -v ./... diff --git a/vendor/github.com/hashicorp/hcl/decoder.go b/vendor/github.com/hashicorp/hcl/decoder.go new file mode 100644 index 000000000..bed9ebbe1 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/decoder.go @@ -0,0 +1,729 @@ +package hcl + +import ( + "errors" + "fmt" + "reflect" + "sort" + "strconv" + "strings" + + "github.com/hashicorp/hcl/hcl/ast" + "github.com/hashicorp/hcl/hcl/parser" + "github.com/hashicorp/hcl/hcl/token" +) + +// This is the tag to use with structures to have settings for HCL +const tagName = "hcl" + +var ( + // nodeType holds a reference to the type of ast.Node + nodeType reflect.Type = findNodeType() +) + +// Unmarshal accepts a byte slice as input and writes the +// data to the value pointed to by v. +func Unmarshal(bs []byte, v interface{}) error { + root, err := parse(bs) + if err != nil { + return err + } + + return DecodeObject(v, root) +} + +// Decode reads the given input and decodes it into the structure +// given by `out`. +func Decode(out interface{}, in string) error { + obj, err := Parse(in) + if err != nil { + return err + } + + return DecodeObject(out, obj) +} + +// DecodeObject is a lower-level version of Decode. It decodes a +// raw Object into the given output. +func DecodeObject(out interface{}, n ast.Node) error { + val := reflect.ValueOf(out) + if val.Kind() != reflect.Ptr { + return errors.New("result must be a pointer") + } + + // If we have the file, we really decode the root node + if f, ok := n.(*ast.File); ok { + n = f.Node + } + + var d decoder + return d.decode("root", n, val.Elem()) +} + +type decoder struct { + stack []reflect.Kind +} + +func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error { + k := result + + // If we have an interface with a valid value, we use that + // for the check. + if result.Kind() == reflect.Interface { + elem := result.Elem() + if elem.IsValid() { + k = elem + } + } + + // Push current onto stack unless it is an interface. + if k.Kind() != reflect.Interface { + d.stack = append(d.stack, k.Kind()) + + // Schedule a pop + defer func() { + d.stack = d.stack[:len(d.stack)-1] + }() + } + + switch k.Kind() { + case reflect.Bool: + return d.decodeBool(name, node, result) + case reflect.Float32, reflect.Float64: + return d.decodeFloat(name, node, result) + case reflect.Int, reflect.Int32, reflect.Int64: + return d.decodeInt(name, node, result) + case reflect.Interface: + // When we see an interface, we make our own thing + return d.decodeInterface(name, node, result) + case reflect.Map: + return d.decodeMap(name, node, result) + case reflect.Ptr: + return d.decodePtr(name, node, result) + case reflect.Slice: + return d.decodeSlice(name, node, result) + case reflect.String: + return d.decodeString(name, node, result) + case reflect.Struct: + return d.decodeStruct(name, node, result) + default: + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()), + } + } +} + +func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error { + switch n := node.(type) { + case *ast.LiteralType: + if n.Token.Type == token.BOOL { + v, err := strconv.ParseBool(n.Token.Text) + if err != nil { + return err + } + + result.Set(reflect.ValueOf(v)) + return nil + } + } + + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: unknown type %T", name, node), + } +} + +func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error { + switch n := node.(type) { + case *ast.LiteralType: + if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER { + v, err := strconv.ParseFloat(n.Token.Text, 64) + if err != nil { + return err + } + + result.Set(reflect.ValueOf(v).Convert(result.Type())) + return nil + } + } + + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: unknown type %T", name, node), + } +} + +func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error { + switch n := node.(type) { + case *ast.LiteralType: + switch n.Token.Type { + case token.NUMBER: + v, err := strconv.ParseInt(n.Token.Text, 0, 0) + if err != nil { + return err + } + + if result.Kind() == reflect.Interface { + result.Set(reflect.ValueOf(int(v))) + } else { + result.SetInt(v) + } + return nil + case token.STRING: + v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0) + if err != nil { + return err + } + + if result.Kind() == reflect.Interface { + result.Set(reflect.ValueOf(int(v))) + } else { + result.SetInt(v) + } + return nil + } + } + + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: unknown type %T", name, node), + } +} + +func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error { + // When we see an ast.Node, we retain the value to enable deferred decoding. + // Very useful in situations where we want to preserve ast.Node information + // like Pos + if result.Type() == nodeType && result.CanSet() { + result.Set(reflect.ValueOf(node)) + return nil + } + + var set reflect.Value + redecode := true + + // For testing types, ObjectType should just be treated as a list. We + // set this to a temporary var because we want to pass in the real node. + testNode := node + if ot, ok := node.(*ast.ObjectType); ok { + testNode = ot.List + } + + switch n := testNode.(type) { + case *ast.ObjectList: + // If we're at the root or we're directly within a slice, then we + // decode objects into map[string]interface{}, otherwise we decode + // them into lists. + if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice { + var temp map[string]interface{} + tempVal := reflect.ValueOf(temp) + result := reflect.MakeMap( + reflect.MapOf( + reflect.TypeOf(""), + tempVal.Type().Elem())) + + set = result + } else { + var temp []map[string]interface{} + tempVal := reflect.ValueOf(temp) + result := reflect.MakeSlice( + reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items)) + set = result + } + case *ast.ObjectType: + // If we're at the root or we're directly within a slice, then we + // decode objects into map[string]interface{}, otherwise we decode + // them into lists. + if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice { + var temp map[string]interface{} + tempVal := reflect.ValueOf(temp) + result := reflect.MakeMap( + reflect.MapOf( + reflect.TypeOf(""), + tempVal.Type().Elem())) + + set = result + } else { + var temp []map[string]interface{} + tempVal := reflect.ValueOf(temp) + result := reflect.MakeSlice( + reflect.SliceOf(tempVal.Type().Elem()), 0, 1) + set = result + } + case *ast.ListType: + var temp []interface{} + tempVal := reflect.ValueOf(temp) + result := reflect.MakeSlice( + reflect.SliceOf(tempVal.Type().Elem()), 0, 0) + set = result + case *ast.LiteralType: + switch n.Token.Type { + case token.BOOL: + var result bool + set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) + case token.FLOAT: + var result float64 + set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) + case token.NUMBER: + var result int + set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) + case token.STRING, token.HEREDOC: + set = reflect.Indirect(reflect.New(reflect.TypeOf(""))) + default: + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node), + } + } + default: + return fmt.Errorf( + "%s: cannot decode into interface: %T", + name, node) + } + + // Set the result to what its supposed to be, then reset + // result so we don't reflect into this method anymore. + result.Set(set) + + if redecode { + // Revisit the node so that we can use the newly instantiated + // thing and populate it. + if err := d.decode(name, node, result); err != nil { + return err + } + } + + return nil +} + +func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error { + if item, ok := node.(*ast.ObjectItem); ok { + node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} + } + + if ot, ok := node.(*ast.ObjectType); ok { + node = ot.List + } + + n, ok := node.(*ast.ObjectList) + if !ok { + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: not an object type for map (%T)", name, node), + } + } + + // If we have an interface, then we can address the interface, + // but not the slice itself, so get the element but set the interface + set := result + if result.Kind() == reflect.Interface { + result = result.Elem() + } + + resultType := result.Type() + resultElemType := resultType.Elem() + resultKeyType := resultType.Key() + if resultKeyType.Kind() != reflect.String { + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: map must have string keys", name), + } + } + + // Make a map if it is nil + resultMap := result + if result.IsNil() { + resultMap = reflect.MakeMap( + reflect.MapOf(resultKeyType, resultElemType)) + } + + // Go through each element and decode it. + done := make(map[string]struct{}) + for _, item := range n.Items { + if item.Val == nil { + continue + } + + // github.com/hashicorp/terraform/issue/5740 + if len(item.Keys) == 0 { + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: map must have string keys", name), + } + } + + // Get the key we're dealing with, which is the first item + keyStr := item.Keys[0].Token.Value().(string) + + // If we've already processed this key, then ignore it + if _, ok := done[keyStr]; ok { + continue + } + + // Determine the value. If we have more than one key, then we + // get the objectlist of only these keys. + itemVal := item.Val + if len(item.Keys) > 1 { + itemVal = n.Filter(keyStr) + done[keyStr] = struct{}{} + } + + // Make the field name + fieldName := fmt.Sprintf("%s.%s", name, keyStr) + + // Get the key/value as reflection values + key := reflect.ValueOf(keyStr) + val := reflect.Indirect(reflect.New(resultElemType)) + + // If we have a pre-existing value in the map, use that + oldVal := resultMap.MapIndex(key) + if oldVal.IsValid() { + val.Set(oldVal) + } + + // Decode! + if err := d.decode(fieldName, itemVal, val); err != nil { + return err + } + + // Set the value on the map + resultMap.SetMapIndex(key, val) + } + + // Set the final map if we can + set.Set(resultMap) + return nil +} + +func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error { + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + resultType := result.Type() + resultElemType := resultType.Elem() + val := reflect.New(resultElemType) + if err := d.decode(name, node, reflect.Indirect(val)); err != nil { + return err + } + + result.Set(val) + return nil +} + +func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error { + // If we have an interface, then we can address the interface, + // but not the slice itself, so get the element but set the interface + set := result + if result.Kind() == reflect.Interface { + result = result.Elem() + } + // Create the slice if it isn't nil + resultType := result.Type() + resultElemType := resultType.Elem() + if result.IsNil() { + resultSliceType := reflect.SliceOf(resultElemType) + result = reflect.MakeSlice( + resultSliceType, 0, 0) + } + + // Figure out the items we'll be copying into the slice + var items []ast.Node + switch n := node.(type) { + case *ast.ObjectList: + items = make([]ast.Node, len(n.Items)) + for i, item := range n.Items { + items[i] = item + } + case *ast.ObjectType: + items = []ast.Node{n} + case *ast.ListType: + items = n.List + default: + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("unknown slice type: %T", node), + } + } + + for i, item := range items { + fieldName := fmt.Sprintf("%s[%d]", name, i) + + // Decode + val := reflect.Indirect(reflect.New(resultElemType)) + + // if item is an object that was decoded from ambiguous JSON and + // flattened, make sure it's expanded if it needs to decode into a + // defined structure. + item := expandObject(item, val) + + if err := d.decode(fieldName, item, val); err != nil { + return err + } + + // Append it onto the slice + result = reflect.Append(result, val) + } + + set.Set(result) + return nil +} + +// expandObject detects if an ambiguous JSON object was flattened to a List which +// should be decoded into a struct, and expands the ast to properly deocode. +func expandObject(node ast.Node, result reflect.Value) ast.Node { + item, ok := node.(*ast.ObjectItem) + if !ok { + return node + } + + elemType := result.Type() + + // our target type must be a struct + switch elemType.Kind() { + case reflect.Ptr: + switch elemType.Elem().Kind() { + case reflect.Struct: + //OK + default: + return node + } + case reflect.Struct: + //OK + default: + return node + } + + // A list value will have a key and field name. If it had more fields, + // it wouldn't have been flattened. + if len(item.Keys) != 2 { + return node + } + + keyToken := item.Keys[0].Token + item.Keys = item.Keys[1:] + + // we need to un-flatten the ast enough to decode + newNode := &ast.ObjectItem{ + Keys: []*ast.ObjectKey{ + &ast.ObjectKey{ + Token: keyToken, + }, + }, + Val: &ast.ObjectType{ + List: &ast.ObjectList{ + Items: []*ast.ObjectItem{item}, + }, + }, + } + + return newNode +} + +func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error { + switch n := node.(type) { + case *ast.LiteralType: + switch n.Token.Type { + case token.NUMBER: + result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type())) + return nil + case token.STRING, token.HEREDOC: + result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type())) + return nil + } + } + + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: unknown type for string %T", name, node), + } +} + +func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error { + var item *ast.ObjectItem + if it, ok := node.(*ast.ObjectItem); ok { + item = it + node = it.Val + } + + if ot, ok := node.(*ast.ObjectType); ok { + node = ot.List + } + + // Handle the special case where the object itself is a literal. Previously + // the yacc parser would always ensure top-level elements were arrays. The new + // parser does not make the same guarantees, thus we need to convert any + // top-level literal elements into a list. + if _, ok := node.(*ast.LiteralType); ok && item != nil { + node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} + } + + list, ok := node.(*ast.ObjectList) + if !ok { + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node), + } + } + + // This slice will keep track of all the structs we'll be decoding. + // There can be more than one struct if there are embedded structs + // that are squashed. + structs := make([]reflect.Value, 1, 5) + structs[0] = result + + // Compile the list of all the fields that we're going to be decoding + // from all the structs. + type field struct { + field reflect.StructField + val reflect.Value + } + fields := []field{} + for len(structs) > 0 { + structVal := structs[0] + structs = structs[1:] + + structType := structVal.Type() + for i := 0; i < structType.NumField(); i++ { + fieldType := structType.Field(i) + tagParts := strings.Split(fieldType.Tag.Get(tagName), ",") + + // Ignore fields with tag name "-" + if tagParts[0] == "-" { + continue + } + + if fieldType.Anonymous { + fieldKind := fieldType.Type.Kind() + if fieldKind != reflect.Struct { + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: unsupported type to struct: %s", + fieldType.Name, fieldKind), + } + } + + // We have an embedded field. We "squash" the fields down + // if specified in the tag. + squash := false + for _, tag := range tagParts[1:] { + if tag == "squash" { + squash = true + break + } + } + + if squash { + structs = append( + structs, result.FieldByName(fieldType.Name)) + continue + } + } + + // Normal struct field, store it away + fields = append(fields, field{fieldType, structVal.Field(i)}) + } + } + + usedKeys := make(map[string]struct{}) + decodedFields := make([]string, 0, len(fields)) + decodedFieldsVal := make([]reflect.Value, 0) + unusedKeysVal := make([]reflect.Value, 0) + for _, f := range fields { + field, fieldValue := f.field, f.val + if !fieldValue.IsValid() { + // This should never happen + panic("field is not valid") + } + + // If we can't set the field, then it is unexported or something, + // and we just continue onwards. + if !fieldValue.CanSet() { + continue + } + + fieldName := field.Name + + tagValue := field.Tag.Get(tagName) + tagParts := strings.SplitN(tagValue, ",", 2) + if len(tagParts) >= 2 { + switch tagParts[1] { + case "decodedFields": + decodedFieldsVal = append(decodedFieldsVal, fieldValue) + continue + case "key": + if item == nil { + return &parser.PosError{ + Pos: node.Pos(), + Err: fmt.Errorf("%s: %s asked for 'key', impossible", + name, fieldName), + } + } + + fieldValue.SetString(item.Keys[0].Token.Value().(string)) + continue + case "unusedKeys": + unusedKeysVal = append(unusedKeysVal, fieldValue) + continue + } + } + + if tagParts[0] != "" { + fieldName = tagParts[0] + } + + // Determine the element we'll use to decode. If it is a single + // match (only object with the field), then we decode it exactly. + // If it is a prefix match, then we decode the matches. + filter := list.Filter(fieldName) + + prefixMatches := filter.Children() + matches := filter.Elem() + if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 { + continue + } + + // Track the used key + usedKeys[fieldName] = struct{}{} + + // Create the field name and decode. We range over the elements + // because we actually want the value. + fieldName = fmt.Sprintf("%s.%s", name, fieldName) + if len(prefixMatches.Items) > 0 { + if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil { + return err + } + } + for _, match := range matches.Items { + var decodeNode ast.Node = match.Val + if ot, ok := decodeNode.(*ast.ObjectType); ok { + decodeNode = &ast.ObjectList{Items: ot.List.Items} + } + + if err := d.decode(fieldName, decodeNode, fieldValue); err != nil { + return err + } + } + + decodedFields = append(decodedFields, field.Name) + } + + if len(decodedFieldsVal) > 0 { + // Sort it so that it is deterministic + sort.Strings(decodedFields) + + for _, v := range decodedFieldsVal { + v.Set(reflect.ValueOf(decodedFields)) + } + } + + return nil +} + +// findNodeType returns the type of ast.Node +func findNodeType() reflect.Type { + var nodeContainer struct { + Node ast.Node + } + value := reflect.ValueOf(nodeContainer).FieldByName("Node") + return value.Type() +} diff --git a/vendor/github.com/hashicorp/hcl/go.mod b/vendor/github.com/hashicorp/hcl/go.mod new file mode 100644 index 000000000..4debbbe35 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/go.mod @@ -0,0 +1,3 @@ +module github.com/hashicorp/hcl + +require github.com/davecgh/go-spew v1.1.1 diff --git a/vendor/github.com/hashicorp/hcl/go.sum b/vendor/github.com/hashicorp/hcl/go.sum new file mode 100644 index 000000000..b5e2922e8 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/go.sum @@ -0,0 +1,2 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/vendor/github.com/hashicorp/hcl/hcl.go b/vendor/github.com/hashicorp/hcl/hcl.go new file mode 100644 index 000000000..575a20b50 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl.go @@ -0,0 +1,11 @@ +// Package hcl decodes HCL into usable Go structures. +// +// hcl input can come in either pure HCL format or JSON format. +// It can be parsed into an AST, and then decoded into a structure, +// or it can be decoded directly from a string into a structure. +// +// If you choose to parse HCL into a raw AST, the benefit is that you +// can write custom visitor implementations to implement custom +// semantic checks. By default, HCL does not perform any semantic +// checks. +package hcl diff --git a/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go b/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go new file mode 100644 index 000000000..6e5ef654b --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go @@ -0,0 +1,219 @@ +// Package ast declares the types used to represent syntax trees for HCL +// (HashiCorp Configuration Language) +package ast + +import ( + "fmt" + "strings" + + "github.com/hashicorp/hcl/hcl/token" +) + +// Node is an element in the abstract syntax tree. +type Node interface { + node() + Pos() token.Pos +} + +func (File) node() {} +func (ObjectList) node() {} +func (ObjectKey) node() {} +func (ObjectItem) node() {} +func (Comment) node() {} +func (CommentGroup) node() {} +func (ObjectType) node() {} +func (LiteralType) node() {} +func (ListType) node() {} + +// File represents a single HCL file +type File struct { + Node Node // usually a *ObjectList + Comments []*CommentGroup // list of all comments in the source +} + +func (f *File) Pos() token.Pos { + return f.Node.Pos() +} + +// ObjectList represents a list of ObjectItems. An HCL file itself is an +// ObjectList. +type ObjectList struct { + Items []*ObjectItem +} + +func (o *ObjectList) Add(item *ObjectItem) { + o.Items = append(o.Items, item) +} + +// Filter filters out the objects with the given key list as a prefix. +// +// The returned list of objects contain ObjectItems where the keys have +// this prefix already stripped off. This might result in objects with +// zero-length key lists if they have no children. +// +// If no matches are found, an empty ObjectList (non-nil) is returned. +func (o *ObjectList) Filter(keys ...string) *ObjectList { + var result ObjectList + for _, item := range o.Items { + // If there aren't enough keys, then ignore this + if len(item.Keys) < len(keys) { + continue + } + + match := true + for i, key := range item.Keys[:len(keys)] { + key := key.Token.Value().(string) + if key != keys[i] && !strings.EqualFold(key, keys[i]) { + match = false + break + } + } + if !match { + continue + } + + // Strip off the prefix from the children + newItem := *item + newItem.Keys = newItem.Keys[len(keys):] + result.Add(&newItem) + } + + return &result +} + +// Children returns further nested objects (key length > 0) within this +// ObjectList. This should be used with Filter to get at child items. +func (o *ObjectList) Children() *ObjectList { + var result ObjectList + for _, item := range o.Items { + if len(item.Keys) > 0 { + result.Add(item) + } + } + + return &result +} + +// Elem returns items in the list that are direct element assignments +// (key length == 0). This should be used with Filter to get at elements. +func (o *ObjectList) Elem() *ObjectList { + var result ObjectList + for _, item := range o.Items { + if len(item.Keys) == 0 { + result.Add(item) + } + } + + return &result +} + +func (o *ObjectList) Pos() token.Pos { + // always returns the uninitiliazed position + return o.Items[0].Pos() +} + +// ObjectItem represents a HCL Object Item. An item is represented with a key +// (or keys). It can be an assignment or an object (both normal and nested) +type ObjectItem struct { + // keys is only one length long if it's of type assignment. If it's a + // nested object it can be larger than one. In that case "assign" is + // invalid as there is no assignments for a nested object. + Keys []*ObjectKey + + // assign contains the position of "=", if any + Assign token.Pos + + // val is the item itself. It can be an object,list, number, bool or a + // string. If key length is larger than one, val can be only of type + // Object. + Val Node + + LeadComment *CommentGroup // associated lead comment + LineComment *CommentGroup // associated line comment +} + +func (o *ObjectItem) Pos() token.Pos { + // I'm not entirely sure what causes this, but removing this causes + // a test failure. We should investigate at some point. + if len(o.Keys) == 0 { + return token.Pos{} + } + + return o.Keys[0].Pos() +} + +// ObjectKeys are either an identifier or of type string. +type ObjectKey struct { + Token token.Token +} + +func (o *ObjectKey) Pos() token.Pos { + return o.Token.Pos +} + +// LiteralType represents a literal of basic type. Valid types are: +// token.NUMBER, token.FLOAT, token.BOOL and token.STRING +type LiteralType struct { + Token token.Token + + // comment types, only used when in a list + LeadComment *CommentGroup + LineComment *CommentGroup +} + +func (l *LiteralType) Pos() token.Pos { + return l.Token.Pos +} + +// ListStatement represents a HCL List type +type ListType struct { + Lbrack token.Pos // position of "[" + Rbrack token.Pos // position of "]" + List []Node // the elements in lexical order +} + +func (l *ListType) Pos() token.Pos { + return l.Lbrack +} + +func (l *ListType) Add(node Node) { + l.List = append(l.List, node) +} + +// ObjectType represents a HCL Object Type +type ObjectType struct { + Lbrace token.Pos // position of "{" + Rbrace token.Pos // position of "}" + List *ObjectList // the nodes in lexical order +} + +func (o *ObjectType) Pos() token.Pos { + return o.Lbrace +} + +// Comment node represents a single //, # style or /*- style commment +type Comment struct { + Start token.Pos // position of / or # + Text string +} + +func (c *Comment) Pos() token.Pos { + return c.Start +} + +// CommentGroup node represents a sequence of comments with no other tokens and +// no empty lines between. +type CommentGroup struct { + List []*Comment // len(List) > 0 +} + +func (c *CommentGroup) Pos() token.Pos { + return c.List[0].Pos() +} + +//------------------------------------------------------------------- +// GoStringer +//------------------------------------------------------------------- + +func (o *ObjectKey) GoString() string { return fmt.Sprintf("*%#v", *o) } +func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) } diff --git a/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go b/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go new file mode 100644 index 000000000..ba07ad42b --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go @@ -0,0 +1,52 @@ +package ast + +import "fmt" + +// WalkFunc describes a function to be called for each node during a Walk. The +// returned node can be used to rewrite the AST. Walking stops the returned +// bool is false. +type WalkFunc func(Node) (Node, bool) + +// Walk traverses an AST in depth-first order: It starts by calling fn(node); +// node must not be nil. If fn returns true, Walk invokes fn recursively for +// each of the non-nil children of node, followed by a call of fn(nil). The +// returned node of fn can be used to rewrite the passed node to fn. +func Walk(node Node, fn WalkFunc) Node { + rewritten, ok := fn(node) + if !ok { + return rewritten + } + + switch n := node.(type) { + case *File: + n.Node = Walk(n.Node, fn) + case *ObjectList: + for i, item := range n.Items { + n.Items[i] = Walk(item, fn).(*ObjectItem) + } + case *ObjectKey: + // nothing to do + case *ObjectItem: + for i, k := range n.Keys { + n.Keys[i] = Walk(k, fn).(*ObjectKey) + } + + if n.Val != nil { + n.Val = Walk(n.Val, fn) + } + case *LiteralType: + // nothing to do + case *ListType: + for i, l := range n.List { + n.List[i] = Walk(l, fn) + } + case *ObjectType: + n.List = Walk(n.List, fn).(*ObjectList) + default: + // should we panic here? + fmt.Printf("unknown type: %T\n", n) + } + + fn(nil) + return rewritten +} diff --git a/vendor/github.com/hashicorp/hcl/hcl/parser/error.go b/vendor/github.com/hashicorp/hcl/hcl/parser/error.go new file mode 100644 index 000000000..5c99381df --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/parser/error.go @@ -0,0 +1,17 @@ +package parser + +import ( + "fmt" + + "github.com/hashicorp/hcl/hcl/token" +) + +// PosError is a parse error that contains a position. +type PosError struct { + Pos token.Pos + Err error +} + +func (e *PosError) Error() string { + return fmt.Sprintf("At %s: %s", e.Pos, e.Err) +} diff --git a/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go b/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go new file mode 100644 index 000000000..64c83bcfb --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go @@ -0,0 +1,532 @@ +// Package parser implements a parser for HCL (HashiCorp Configuration +// Language) +package parser + +import ( + "bytes" + "errors" + "fmt" + "strings" + + "github.com/hashicorp/hcl/hcl/ast" + "github.com/hashicorp/hcl/hcl/scanner" + "github.com/hashicorp/hcl/hcl/token" +) + +type Parser struct { + sc *scanner.Scanner + + // Last read token + tok token.Token + commaPrev token.Token + + comments []*ast.CommentGroup + leadComment *ast.CommentGroup // last lead comment + lineComment *ast.CommentGroup // last line comment + + enableTrace bool + indent int + n int // buffer size (max = 1) +} + +func newParser(src []byte) *Parser { + return &Parser{ + sc: scanner.New(src), + } +} + +// Parse returns the fully parsed source and returns the abstract syntax tree. +func Parse(src []byte) (*ast.File, error) { + // normalize all line endings + // since the scanner and output only work with "\n" line endings, we may + // end up with dangling "\r" characters in the parsed data. + src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1) + + p := newParser(src) + return p.Parse() +} + +var errEofToken = errors.New("EOF token found") + +// Parse returns the fully parsed source and returns the abstract syntax tree. +func (p *Parser) Parse() (*ast.File, error) { + f := &ast.File{} + var err, scerr error + p.sc.Error = func(pos token.Pos, msg string) { + scerr = &PosError{Pos: pos, Err: errors.New(msg)} + } + + f.Node, err = p.objectList(false) + if scerr != nil { + return nil, scerr + } + if err != nil { + return nil, err + } + + f.Comments = p.comments + return f, nil +} + +// objectList parses a list of items within an object (generally k/v pairs). +// The parameter" obj" tells this whether to we are within an object (braces: +// '{', '}') or just at the top level. If we're within an object, we end +// at an RBRACE. +func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) { + defer un(trace(p, "ParseObjectList")) + node := &ast.ObjectList{} + + for { + if obj { + tok := p.scan() + p.unscan() + if tok.Type == token.RBRACE { + break + } + } + + n, err := p.objectItem() + if err == errEofToken { + break // we are finished + } + + // we don't return a nil node, because might want to use already + // collected items. + if err != nil { + return node, err + } + + node.Add(n) + + // object lists can be optionally comma-delimited e.g. when a list of maps + // is being expressed, so a comma is allowed here - it's simply consumed + tok := p.scan() + if tok.Type != token.COMMA { + p.unscan() + } + } + return node, nil +} + +func (p *Parser) consumeComment() (comment *ast.Comment, endline int) { + endline = p.tok.Pos.Line + + // count the endline if it's multiline comment, ie starting with /* + if len(p.tok.Text) > 1 && p.tok.Text[1] == '*' { + // don't use range here - no need to decode Unicode code points + for i := 0; i < len(p.tok.Text); i++ { + if p.tok.Text[i] == '\n' { + endline++ + } + } + } + + comment = &ast.Comment{Start: p.tok.Pos, Text: p.tok.Text} + p.tok = p.sc.Scan() + return +} + +func (p *Parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) { + var list []*ast.Comment + endline = p.tok.Pos.Line + + for p.tok.Type == token.COMMENT && p.tok.Pos.Line <= endline+n { + var comment *ast.Comment + comment, endline = p.consumeComment() + list = append(list, comment) + } + + // add comment group to the comments list + comments = &ast.CommentGroup{List: list} + p.comments = append(p.comments, comments) + + return +} + +// objectItem parses a single object item +func (p *Parser) objectItem() (*ast.ObjectItem, error) { + defer un(trace(p, "ParseObjectItem")) + + keys, err := p.objectKey() + if len(keys) > 0 && err == errEofToken { + // We ignore eof token here since it is an error if we didn't + // receive a value (but we did receive a key) for the item. + err = nil + } + if len(keys) > 0 && err != nil && p.tok.Type == token.RBRACE { + // This is a strange boolean statement, but what it means is: + // We have keys with no value, and we're likely in an object + // (since RBrace ends an object). For this, we set err to nil so + // we continue and get the error below of having the wrong value + // type. + err = nil + + // Reset the token type so we don't think it completed fine. See + // objectType which uses p.tok.Type to check if we're done with + // the object. + p.tok.Type = token.EOF + } + if err != nil { + return nil, err + } + + o := &ast.ObjectItem{ + Keys: keys, + } + + if p.leadComment != nil { + o.LeadComment = p.leadComment + p.leadComment = nil + } + + switch p.tok.Type { + case token.ASSIGN: + o.Assign = p.tok.Pos + o.Val, err = p.object() + if err != nil { + return nil, err + } + case token.LBRACE: + o.Val, err = p.objectType() + if err != nil { + return nil, err + } + default: + keyStr := make([]string, 0, len(keys)) + for _, k := range keys { + keyStr = append(keyStr, k.Token.Text) + } + + return nil, &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf( + "key '%s' expected start of object ('{') or assignment ('=')", + strings.Join(keyStr, " ")), + } + } + + // key=#comment + // val + if p.lineComment != nil { + o.LineComment, p.lineComment = p.lineComment, nil + } + + // do a look-ahead for line comment + p.scan() + if len(keys) > 0 && o.Val.Pos().Line == keys[0].Pos().Line && p.lineComment != nil { + o.LineComment = p.lineComment + p.lineComment = nil + } + p.unscan() + return o, nil +} + +// objectKey parses an object key and returns a ObjectKey AST +func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { + keyCount := 0 + keys := make([]*ast.ObjectKey, 0) + + for { + tok := p.scan() + switch tok.Type { + case token.EOF: + // It is very important to also return the keys here as well as + // the error. This is because we need to be able to tell if we + // did parse keys prior to finding the EOF, or if we just found + // a bare EOF. + return keys, errEofToken + case token.ASSIGN: + // assignment or object only, but not nested objects. this is not + // allowed: `foo bar = {}` + if keyCount > 1 { + return nil, &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf("nested object expected: LBRACE got: %s", p.tok.Type), + } + } + + if keyCount == 0 { + return nil, &PosError{ + Pos: p.tok.Pos, + Err: errors.New("no object keys found!"), + } + } + + return keys, nil + case token.LBRACE: + var err error + + // If we have no keys, then it is a syntax error. i.e. {{}} is not + // allowed. + if len(keys) == 0 { + err = &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type), + } + } + + // object + return keys, err + case token.IDENT, token.STRING: + keyCount++ + keys = append(keys, &ast.ObjectKey{Token: p.tok}) + case token.ILLEGAL: + return keys, &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf("illegal character"), + } + default: + return keys, &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf("expected: IDENT | STRING | ASSIGN | LBRACE got: %s", p.tok.Type), + } + } + } +} + +// object parses any type of object, such as number, bool, string, object or +// list. +func (p *Parser) object() (ast.Node, error) { + defer un(trace(p, "ParseType")) + tok := p.scan() + + switch tok.Type { + case token.NUMBER, token.FLOAT, token.BOOL, token.STRING, token.HEREDOC: + return p.literalType() + case token.LBRACE: + return p.objectType() + case token.LBRACK: + return p.listType() + case token.COMMENT: + // implement comment + case token.EOF: + return nil, errEofToken + } + + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf("Unknown token: %+v", tok), + } +} + +// objectType parses an object type and returns a ObjectType AST +func (p *Parser) objectType() (*ast.ObjectType, error) { + defer un(trace(p, "ParseObjectType")) + + // we assume that the currently scanned token is a LBRACE + o := &ast.ObjectType{ + Lbrace: p.tok.Pos, + } + + l, err := p.objectList(true) + + // if we hit RBRACE, we are good to go (means we parsed all Items), if it's + // not a RBRACE, it's an syntax error and we just return it. + if err != nil && p.tok.Type != token.RBRACE { + return nil, err + } + + // No error, scan and expect the ending to be a brace + if tok := p.scan(); tok.Type != token.RBRACE { + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type), + } + } + + o.List = l + o.Rbrace = p.tok.Pos // advanced via parseObjectList + return o, nil +} + +// listType parses a list type and returns a ListType AST +func (p *Parser) listType() (*ast.ListType, error) { + defer un(trace(p, "ParseListType")) + + // we assume that the currently scanned token is a LBRACK + l := &ast.ListType{ + Lbrack: p.tok.Pos, + } + + needComma := false + for { + tok := p.scan() + if needComma { + switch tok.Type { + case token.COMMA, token.RBRACK: + default: + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf( + "error parsing list, expected comma or list end, got: %s", + tok.Type), + } + } + } + switch tok.Type { + case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC: + node, err := p.literalType() + if err != nil { + return nil, err + } + + // If there is a lead comment, apply it + if p.leadComment != nil { + node.LeadComment = p.leadComment + p.leadComment = nil + } + + l.Add(node) + needComma = true + case token.COMMA: + // get next list item or we are at the end + // do a look-ahead for line comment + p.scan() + if p.lineComment != nil && len(l.List) > 0 { + lit, ok := l.List[len(l.List)-1].(*ast.LiteralType) + if ok { + lit.LineComment = p.lineComment + l.List[len(l.List)-1] = lit + p.lineComment = nil + } + } + p.unscan() + + needComma = false + continue + case token.LBRACE: + // Looks like a nested object, so parse it out + node, err := p.objectType() + if err != nil { + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf( + "error while trying to parse object within list: %s", err), + } + } + l.Add(node) + needComma = true + case token.LBRACK: + node, err := p.listType() + if err != nil { + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf( + "error while trying to parse list within list: %s", err), + } + } + l.Add(node) + case token.RBRACK: + // finished + l.Rbrack = p.tok.Pos + return l, nil + default: + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf("unexpected token while parsing list: %s", tok.Type), + } + } + } +} + +// literalType parses a literal type and returns a LiteralType AST +func (p *Parser) literalType() (*ast.LiteralType, error) { + defer un(trace(p, "ParseLiteral")) + + return &ast.LiteralType{ + Token: p.tok, + }, nil +} + +// scan returns the next token from the underlying scanner. If a token has +// been unscanned then read that instead. In the process, it collects any +// comment groups encountered, and remembers the last lead and line comments. +func (p *Parser) scan() token.Token { + // If we have a token on the buffer, then return it. + if p.n != 0 { + p.n = 0 + return p.tok + } + + // Otherwise read the next token from the scanner and Save it to the buffer + // in case we unscan later. + prev := p.tok + p.tok = p.sc.Scan() + + if p.tok.Type == token.COMMENT { + var comment *ast.CommentGroup + var endline int + + // fmt.Printf("p.tok.Pos.Line = %+v prev: %d endline %d \n", + // p.tok.Pos.Line, prev.Pos.Line, endline) + if p.tok.Pos.Line == prev.Pos.Line { + // The comment is on same line as the previous token; it + // cannot be a lead comment but may be a line comment. + comment, endline = p.consumeCommentGroup(0) + if p.tok.Pos.Line != endline { + // The next token is on a different line, thus + // the last comment group is a line comment. + p.lineComment = comment + } + } + + // consume successor comments, if any + endline = -1 + for p.tok.Type == token.COMMENT { + comment, endline = p.consumeCommentGroup(1) + } + + if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE { + switch p.tok.Type { + case token.RBRACE, token.RBRACK: + // Do not count for these cases + default: + // The next token is following on the line immediately after the + // comment group, thus the last comment group is a lead comment. + p.leadComment = comment + } + } + + } + + return p.tok +} + +// unscan pushes the previously read token back onto the buffer. +func (p *Parser) unscan() { + p.n = 1 +} + +// ---------------------------------------------------------------------------- +// Parsing support + +func (p *Parser) printTrace(a ...interface{}) { + if !p.enableTrace { + return + } + + const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " + const n = len(dots) + fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column) + + i := 2 * p.indent + for i > n { + fmt.Print(dots) + i -= n + } + // i <= n + fmt.Print(dots[0:i]) + fmt.Println(a...) +} + +func trace(p *Parser, msg string) *Parser { + p.printTrace(msg, "(") + p.indent++ + return p +} + +// Usage pattern: defer un(trace(p, "...")) +func un(p *Parser) { + p.indent-- + p.printTrace(")") +} diff --git a/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go b/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go new file mode 100644 index 000000000..7c038d12a --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go @@ -0,0 +1,789 @@ +package printer + +import ( + "bytes" + "fmt" + "sort" + + "github.com/hashicorp/hcl/hcl/ast" + "github.com/hashicorp/hcl/hcl/token" +) + +const ( + blank = byte(' ') + newline = byte('\n') + tab = byte('\t') + infinity = 1 << 30 // offset or line +) + +var ( + unindent = []byte("\uE123") // in the private use space +) + +type printer struct { + cfg Config + prev token.Pos + + comments []*ast.CommentGroup // may be nil, contains all comments + standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node) + + enableTrace bool + indentTrace int +} + +type ByPosition []*ast.CommentGroup + +func (b ByPosition) Len() int { return len(b) } +func (b ByPosition) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b ByPosition) Less(i, j int) bool { return b[i].Pos().Before(b[j].Pos()) } + +// collectComments comments all standalone comments which are not lead or line +// comment +func (p *printer) collectComments(node ast.Node) { + // first collect all comments. This is already stored in + // ast.File.(comments) + ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { + switch t := nn.(type) { + case *ast.File: + p.comments = t.Comments + return nn, false + } + return nn, true + }) + + standaloneComments := make(map[token.Pos]*ast.CommentGroup, 0) + for _, c := range p.comments { + standaloneComments[c.Pos()] = c + } + + // next remove all lead and line comments from the overall comment map. + // This will give us comments which are standalone, comments which are not + // assigned to any kind of node. + ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { + switch t := nn.(type) { + case *ast.LiteralType: + if t.LeadComment != nil { + for _, comment := range t.LeadComment.List { + if _, ok := standaloneComments[comment.Pos()]; ok { + delete(standaloneComments, comment.Pos()) + } + } + } + + if t.LineComment != nil { + for _, comment := range t.LineComment.List { + if _, ok := standaloneComments[comment.Pos()]; ok { + delete(standaloneComments, comment.Pos()) + } + } + } + case *ast.ObjectItem: + if t.LeadComment != nil { + for _, comment := range t.LeadComment.List { + if _, ok := standaloneComments[comment.Pos()]; ok { + delete(standaloneComments, comment.Pos()) + } + } + } + + if t.LineComment != nil { + for _, comment := range t.LineComment.List { + if _, ok := standaloneComments[comment.Pos()]; ok { + delete(standaloneComments, comment.Pos()) + } + } + } + } + + return nn, true + }) + + for _, c := range standaloneComments { + p.standaloneComments = append(p.standaloneComments, c) + } + + sort.Sort(ByPosition(p.standaloneComments)) +} + +// output prints creates b printable HCL output and returns it. +func (p *printer) output(n interface{}) []byte { + var buf bytes.Buffer + + switch t := n.(type) { + case *ast.File: + // File doesn't trace so we add the tracing here + defer un(trace(p, "File")) + return p.output(t.Node) + case *ast.ObjectList: + defer un(trace(p, "ObjectList")) + + var index int + for { + // Determine the location of the next actual non-comment + // item. If we're at the end, the next item is at "infinity" + var nextItem token.Pos + if index != len(t.Items) { + nextItem = t.Items[index].Pos() + } else { + nextItem = token.Pos{Offset: infinity, Line: infinity} + } + + // Go through the standalone comments in the file and print out + // the comments that we should be for this object item. + for _, c := range p.standaloneComments { + // Go through all the comments in the group. The group + // should be printed together, not separated by double newlines. + printed := false + newlinePrinted := false + for _, comment := range c.List { + // We only care about comments after the previous item + // we've printed so that comments are printed in the + // correct locations (between two objects for example). + // And before the next item. + if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { + // if we hit the end add newlines so we can print the comment + // we don't do this if prev is invalid which means the + // beginning of the file since the first comment should + // be at the first line. + if !newlinePrinted && p.prev.IsValid() && index == len(t.Items) { + buf.Write([]byte{newline, newline}) + newlinePrinted = true + } + + // Write the actual comment. + buf.WriteString(comment.Text) + buf.WriteByte(newline) + + // Set printed to true to note that we printed something + printed = true + } + } + + // If we're not at the last item, write a new line so + // that there is a newline separating this comment from + // the next object. + if printed && index != len(t.Items) { + buf.WriteByte(newline) + } + } + + if index == len(t.Items) { + break + } + + buf.Write(p.output(t.Items[index])) + if index != len(t.Items)-1 { + // Always write a newline to separate us from the next item + buf.WriteByte(newline) + + // Need to determine if we're going to separate the next item + // with a blank line. The logic here is simple, though there + // are a few conditions: + // + // 1. The next object is more than one line away anyways, + // so we need an empty line. + // + // 2. The next object is not a "single line" object, so + // we need an empty line. + // + // 3. This current object is not a single line object, + // so we need an empty line. + current := t.Items[index] + next := t.Items[index+1] + if next.Pos().Line != t.Items[index].Pos().Line+1 || + !p.isSingleLineObject(next) || + !p.isSingleLineObject(current) { + buf.WriteByte(newline) + } + } + index++ + } + case *ast.ObjectKey: + buf.WriteString(t.Token.Text) + case *ast.ObjectItem: + p.prev = t.Pos() + buf.Write(p.objectItem(t)) + case *ast.LiteralType: + buf.Write(p.literalType(t)) + case *ast.ListType: + buf.Write(p.list(t)) + case *ast.ObjectType: + buf.Write(p.objectType(t)) + default: + fmt.Printf(" unknown type: %T\n", n) + } + + return buf.Bytes() +} + +func (p *printer) literalType(lit *ast.LiteralType) []byte { + result := []byte(lit.Token.Text) + switch lit.Token.Type { + case token.HEREDOC: + // Clear the trailing newline from heredocs + if result[len(result)-1] == '\n' { + result = result[:len(result)-1] + } + + // Poison lines 2+ so that we don't indent them + result = p.heredocIndent(result) + case token.STRING: + // If this is a multiline string, poison lines 2+ so we don't + // indent them. + if bytes.IndexRune(result, '\n') >= 0 { + result = p.heredocIndent(result) + } + } + + return result +} + +// objectItem returns the printable HCL form of an object item. An object type +// starts with one/multiple keys and has a value. The value might be of any +// type. +func (p *printer) objectItem(o *ast.ObjectItem) []byte { + defer un(trace(p, fmt.Sprintf("ObjectItem: %s", o.Keys[0].Token.Text))) + var buf bytes.Buffer + + if o.LeadComment != nil { + for _, comment := range o.LeadComment.List { + buf.WriteString(comment.Text) + buf.WriteByte(newline) + } + } + + // If key and val are on different lines, treat line comments like lead comments. + if o.LineComment != nil && o.Val.Pos().Line != o.Keys[0].Pos().Line { + for _, comment := range o.LineComment.List { + buf.WriteString(comment.Text) + buf.WriteByte(newline) + } + } + + for i, k := range o.Keys { + buf.WriteString(k.Token.Text) + buf.WriteByte(blank) + + // reach end of key + if o.Assign.IsValid() && i == len(o.Keys)-1 && len(o.Keys) == 1 { + buf.WriteString("=") + buf.WriteByte(blank) + } + } + + buf.Write(p.output(o.Val)) + + if o.LineComment != nil && o.Val.Pos().Line == o.Keys[0].Pos().Line { + buf.WriteByte(blank) + for _, comment := range o.LineComment.List { + buf.WriteString(comment.Text) + } + } + + return buf.Bytes() +} + +// objectType returns the printable HCL form of an object type. An object type +// begins with a brace and ends with a brace. +func (p *printer) objectType(o *ast.ObjectType) []byte { + defer un(trace(p, "ObjectType")) + var buf bytes.Buffer + buf.WriteString("{") + + var index int + var nextItem token.Pos + var commented, newlinePrinted bool + for { + // Determine the location of the next actual non-comment + // item. If we're at the end, the next item is the closing brace + if index != len(o.List.Items) { + nextItem = o.List.Items[index].Pos() + } else { + nextItem = o.Rbrace + } + + // Go through the standalone comments in the file and print out + // the comments that we should be for this object item. + for _, c := range p.standaloneComments { + printed := false + var lastCommentPos token.Pos + for _, comment := range c.List { + // We only care about comments after the previous item + // we've printed so that comments are printed in the + // correct locations (between two objects for example). + // And before the next item. + if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { + // If there are standalone comments and the initial newline has not + // been printed yet, do it now. + if !newlinePrinted { + newlinePrinted = true + buf.WriteByte(newline) + } + + // add newline if it's between other printed nodes + if index > 0 { + commented = true + buf.WriteByte(newline) + } + + // Store this position + lastCommentPos = comment.Pos() + + // output the comment itself + buf.Write(p.indent(p.heredocIndent([]byte(comment.Text)))) + + // Set printed to true to note that we printed something + printed = true + + /* + if index != len(o.List.Items) { + buf.WriteByte(newline) // do not print on the end + } + */ + } + } + + // Stuff to do if we had comments + if printed { + // Always write a newline + buf.WriteByte(newline) + + // If there is another item in the object and our comment + // didn't hug it directly, then make sure there is a blank + // line separating them. + if nextItem != o.Rbrace && nextItem.Line != lastCommentPos.Line+1 { + buf.WriteByte(newline) + } + } + } + + if index == len(o.List.Items) { + p.prev = o.Rbrace + break + } + + // At this point we are sure that it's not a totally empty block: print + // the initial newline if it hasn't been printed yet by the previous + // block about standalone comments. + if !newlinePrinted { + buf.WriteByte(newline) + newlinePrinted = true + } + + // check if we have adjacent one liner items. If yes we'll going to align + // the comments. + var aligned []*ast.ObjectItem + for _, item := range o.List.Items[index:] { + // we don't group one line lists + if len(o.List.Items) == 1 { + break + } + + // one means a oneliner with out any lead comment + // two means a oneliner with lead comment + // anything else might be something else + cur := lines(string(p.objectItem(item))) + if cur > 2 { + break + } + + curPos := item.Pos() + + nextPos := token.Pos{} + if index != len(o.List.Items)-1 { + nextPos = o.List.Items[index+1].Pos() + } + + prevPos := token.Pos{} + if index != 0 { + prevPos = o.List.Items[index-1].Pos() + } + + // fmt.Println("DEBUG ----------------") + // fmt.Printf("prev = %+v prevPos: %s\n", prev, prevPos) + // fmt.Printf("cur = %+v curPos: %s\n", cur, curPos) + // fmt.Printf("next = %+v nextPos: %s\n", next, nextPos) + + if curPos.Line+1 == nextPos.Line { + aligned = append(aligned, item) + index++ + continue + } + + if curPos.Line-1 == prevPos.Line { + aligned = append(aligned, item) + index++ + + // finish if we have a new line or comment next. This happens + // if the next item is not adjacent + if curPos.Line+1 != nextPos.Line { + break + } + continue + } + + break + } + + // put newlines if the items are between other non aligned items. + // newlines are also added if there is a standalone comment already, so + // check it too + if !commented && index != len(aligned) { + buf.WriteByte(newline) + } + + if len(aligned) >= 1 { + p.prev = aligned[len(aligned)-1].Pos() + + items := p.alignedItems(aligned) + buf.Write(p.indent(items)) + } else { + p.prev = o.List.Items[index].Pos() + + buf.Write(p.indent(p.objectItem(o.List.Items[index]))) + index++ + } + + buf.WriteByte(newline) + } + + buf.WriteString("}") + return buf.Bytes() +} + +func (p *printer) alignedItems(items []*ast.ObjectItem) []byte { + var buf bytes.Buffer + + // find the longest key and value length, needed for alignment + var longestKeyLen int // longest key length + var longestValLen int // longest value length + for _, item := range items { + key := len(item.Keys[0].Token.Text) + val := len(p.output(item.Val)) + + if key > longestKeyLen { + longestKeyLen = key + } + + if val > longestValLen { + longestValLen = val + } + } + + for i, item := range items { + if item.LeadComment != nil { + for _, comment := range item.LeadComment.List { + buf.WriteString(comment.Text) + buf.WriteByte(newline) + } + } + + for i, k := range item.Keys { + keyLen := len(k.Token.Text) + buf.WriteString(k.Token.Text) + for i := 0; i < longestKeyLen-keyLen+1; i++ { + buf.WriteByte(blank) + } + + // reach end of key + if i == len(item.Keys)-1 && len(item.Keys) == 1 { + buf.WriteString("=") + buf.WriteByte(blank) + } + } + + val := p.output(item.Val) + valLen := len(val) + buf.Write(val) + + if item.Val.Pos().Line == item.Keys[0].Pos().Line && item.LineComment != nil { + for i := 0; i < longestValLen-valLen+1; i++ { + buf.WriteByte(blank) + } + + for _, comment := range item.LineComment.List { + buf.WriteString(comment.Text) + } + } + + // do not print for the last item + if i != len(items)-1 { + buf.WriteByte(newline) + } + } + + return buf.Bytes() +} + +// list returns the printable HCL form of an list type. +func (p *printer) list(l *ast.ListType) []byte { + if p.isSingleLineList(l) { + return p.singleLineList(l) + } + + var buf bytes.Buffer + buf.WriteString("[") + buf.WriteByte(newline) + + var longestLine int + for _, item := range l.List { + // for now we assume that the list only contains literal types + if lit, ok := item.(*ast.LiteralType); ok { + lineLen := len(lit.Token.Text) + if lineLen > longestLine { + longestLine = lineLen + } + } + } + + haveEmptyLine := false + for i, item := range l.List { + // If we have a lead comment, then we want to write that first + leadComment := false + if lit, ok := item.(*ast.LiteralType); ok && lit.LeadComment != nil { + leadComment = true + + // Ensure an empty line before every element with a + // lead comment (except the first item in a list). + if !haveEmptyLine && i != 0 { + buf.WriteByte(newline) + } + + for _, comment := range lit.LeadComment.List { + buf.Write(p.indent([]byte(comment.Text))) + buf.WriteByte(newline) + } + } + + // also indent each line + val := p.output(item) + curLen := len(val) + buf.Write(p.indent(val)) + + // if this item is a heredoc, then we output the comma on + // the next line. This is the only case this happens. + comma := []byte{','} + if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { + buf.WriteByte(newline) + comma = p.indent(comma) + } + + buf.Write(comma) + + if lit, ok := item.(*ast.LiteralType); ok && lit.LineComment != nil { + // if the next item doesn't have any comments, do not align + buf.WriteByte(blank) // align one space + for i := 0; i < longestLine-curLen; i++ { + buf.WriteByte(blank) + } + + for _, comment := range lit.LineComment.List { + buf.WriteString(comment.Text) + } + } + + buf.WriteByte(newline) + + // Ensure an empty line after every element with a + // lead comment (except the first item in a list). + haveEmptyLine = leadComment && i != len(l.List)-1 + if haveEmptyLine { + buf.WriteByte(newline) + } + } + + buf.WriteString("]") + return buf.Bytes() +} + +// isSingleLineList returns true if: +// * they were previously formatted entirely on one line +// * they consist entirely of literals +// * there are either no heredoc strings or the list has exactly one element +// * there are no line comments +func (printer) isSingleLineList(l *ast.ListType) bool { + for _, item := range l.List { + if item.Pos().Line != l.Lbrack.Line { + return false + } + + lit, ok := item.(*ast.LiteralType) + if !ok { + return false + } + + if lit.Token.Type == token.HEREDOC && len(l.List) != 1 { + return false + } + + if lit.LineComment != nil { + return false + } + } + + return true +} + +// singleLineList prints a simple single line list. +// For a definition of "simple", see isSingleLineList above. +func (p *printer) singleLineList(l *ast.ListType) []byte { + buf := &bytes.Buffer{} + + buf.WriteString("[") + for i, item := range l.List { + if i != 0 { + buf.WriteString(", ") + } + + // Output the item itself + buf.Write(p.output(item)) + + // The heredoc marker needs to be at the end of line. + if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { + buf.WriteByte(newline) + } + } + + buf.WriteString("]") + return buf.Bytes() +} + +// indent indents the lines of the given buffer for each non-empty line +func (p *printer) indent(buf []byte) []byte { + var prefix []byte + if p.cfg.SpacesWidth != 0 { + for i := 0; i < p.cfg.SpacesWidth; i++ { + prefix = append(prefix, blank) + } + } else { + prefix = []byte{tab} + } + + var res []byte + bol := true + for _, c := range buf { + if bol && c != '\n' { + res = append(res, prefix...) + } + + res = append(res, c) + bol = c == '\n' + } + return res +} + +// unindent removes all the indentation from the tombstoned lines +func (p *printer) unindent(buf []byte) []byte { + var res []byte + for i := 0; i < len(buf); i++ { + skip := len(buf)-i <= len(unindent) + if !skip { + skip = !bytes.Equal(unindent, buf[i:i+len(unindent)]) + } + if skip { + res = append(res, buf[i]) + continue + } + + // We have a marker. we have to backtrace here and clean out + // any whitespace ahead of our tombstone up to a \n + for j := len(res) - 1; j >= 0; j-- { + if res[j] == '\n' { + break + } + + res = res[:j] + } + + // Skip the entire unindent marker + i += len(unindent) - 1 + } + + return res +} + +// heredocIndent marks all the 2nd and further lines as unindentable +func (p *printer) heredocIndent(buf []byte) []byte { + var res []byte + bol := false + for _, c := range buf { + if bol && c != '\n' { + res = append(res, unindent...) + } + res = append(res, c) + bol = c == '\n' + } + return res +} + +// isSingleLineObject tells whether the given object item is a single +// line object such as "obj {}". +// +// A single line object: +// +// * has no lead comments (hence multi-line) +// * has no assignment +// * has no values in the stanza (within {}) +// +func (p *printer) isSingleLineObject(val *ast.ObjectItem) bool { + // If there is a lead comment, can't be one line + if val.LeadComment != nil { + return false + } + + // If there is assignment, we always break by line + if val.Assign.IsValid() { + return false + } + + // If it isn't an object type, then its not a single line object + ot, ok := val.Val.(*ast.ObjectType) + if !ok { + return false + } + + // If the object has no items, it is single line! + return len(ot.List.Items) == 0 +} + +func lines(txt string) int { + endline := 1 + for i := 0; i < len(txt); i++ { + if txt[i] == '\n' { + endline++ + } + } + return endline +} + +// ---------------------------------------------------------------------------- +// Tracing support + +func (p *printer) printTrace(a ...interface{}) { + if !p.enableTrace { + return + } + + const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " + const n = len(dots) + i := 2 * p.indentTrace + for i > n { + fmt.Print(dots) + i -= n + } + // i <= n + fmt.Print(dots[0:i]) + fmt.Println(a...) +} + +func trace(p *printer, msg string) *printer { + p.printTrace(msg, "(") + p.indentTrace++ + return p +} + +// Usage pattern: defer un(trace(p, "...")) +func un(p *printer) { + p.indentTrace-- + p.printTrace(")") +} diff --git a/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go b/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go new file mode 100644 index 000000000..6617ab8e7 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go @@ -0,0 +1,66 @@ +// Package printer implements printing of AST nodes to HCL format. +package printer + +import ( + "bytes" + "io" + "text/tabwriter" + + "github.com/hashicorp/hcl/hcl/ast" + "github.com/hashicorp/hcl/hcl/parser" +) + +var DefaultConfig = Config{ + SpacesWidth: 2, +} + +// A Config node controls the output of Fprint. +type Config struct { + SpacesWidth int // if set, it will use spaces instead of tabs for alignment +} + +func (c *Config) Fprint(output io.Writer, node ast.Node) error { + p := &printer{ + cfg: *c, + comments: make([]*ast.CommentGroup, 0), + standaloneComments: make([]*ast.CommentGroup, 0), + // enableTrace: true, + } + + p.collectComments(node) + + if _, err := output.Write(p.unindent(p.output(node))); err != nil { + return err + } + + // flush tabwriter, if any + var err error + if tw, _ := output.(*tabwriter.Writer); tw != nil { + err = tw.Flush() + } + + return err +} + +// Fprint "pretty-prints" an HCL node to output +// It calls Config.Fprint with default settings. +func Fprint(output io.Writer, node ast.Node) error { + return DefaultConfig.Fprint(output, node) +} + +// Format formats src HCL and returns the result. +func Format(src []byte) ([]byte, error) { + node, err := parser.Parse(src) + if err != nil { + return nil, err + } + + var buf bytes.Buffer + if err := DefaultConfig.Fprint(&buf, node); err != nil { + return nil, err + } + + // Add trailing newline to result + buf.WriteString("\n") + return buf.Bytes(), nil +} diff --git a/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go new file mode 100644 index 000000000..624a18fe3 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go @@ -0,0 +1,652 @@ +// Package scanner implements a scanner for HCL (HashiCorp Configuration +// Language) source text. +package scanner + +import ( + "bytes" + "fmt" + "os" + "regexp" + "unicode" + "unicode/utf8" + + "github.com/hashicorp/hcl/hcl/token" +) + +// eof represents a marker rune for the end of the reader. +const eof = rune(0) + +// Scanner defines a lexical scanner +type Scanner struct { + buf *bytes.Buffer // Source buffer for advancing and scanning + src []byte // Source buffer for immutable access + + // Source Position + srcPos token.Pos // current position + prevPos token.Pos // previous position, used for peek() method + + lastCharLen int // length of last character in bytes + lastLineLen int // length of last line in characters (for correct column reporting) + + tokStart int // token text start position + tokEnd int // token text end position + + // Error is called for each error encountered. If no Error + // function is set, the error is reported to os.Stderr. + Error func(pos token.Pos, msg string) + + // ErrorCount is incremented by one for each error encountered. + ErrorCount int + + // tokPos is the start position of most recently scanned token; set by + // Scan. The Filename field is always left untouched by the Scanner. If + // an error is reported (via Error) and Position is invalid, the scanner is + // not inside a token. + tokPos token.Pos +} + +// New creates and initializes a new instance of Scanner using src as +// its source content. +func New(src []byte) *Scanner { + // even though we accept a src, we read from a io.Reader compatible type + // (*bytes.Buffer). So in the future we might easily change it to streaming + // read. + b := bytes.NewBuffer(src) + s := &Scanner{ + buf: b, + src: src, + } + + // srcPosition always starts with 1 + s.srcPos.Line = 1 + return s +} + +// next reads the next rune from the bufferred reader. Returns the rune(0) if +// an error occurs (or io.EOF is returned). +func (s *Scanner) next() rune { + ch, size, err := s.buf.ReadRune() + if err != nil { + // advance for error reporting + s.srcPos.Column++ + s.srcPos.Offset += size + s.lastCharLen = size + return eof + } + + // remember last position + s.prevPos = s.srcPos + + s.srcPos.Column++ + s.lastCharLen = size + s.srcPos.Offset += size + + if ch == utf8.RuneError && size == 1 { + s.err("illegal UTF-8 encoding") + return ch + } + + if ch == '\n' { + s.srcPos.Line++ + s.lastLineLen = s.srcPos.Column + s.srcPos.Column = 0 + } + + if ch == '\x00' { + s.err("unexpected null character (0x00)") + return eof + } + + if ch == '\uE123' { + s.err("unicode code point U+E123 reserved for internal use") + return utf8.RuneError + } + + // debug + // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) + return ch +} + +// unread unreads the previous read Rune and updates the source position +func (s *Scanner) unread() { + if err := s.buf.UnreadRune(); err != nil { + panic(err) // this is user fault, we should catch it + } + s.srcPos = s.prevPos // put back last position +} + +// peek returns the next rune without advancing the reader. +func (s *Scanner) peek() rune { + peek, _, err := s.buf.ReadRune() + if err != nil { + return eof + } + + s.buf.UnreadRune() + return peek +} + +// Scan scans the next token and returns the token. +func (s *Scanner) Scan() token.Token { + ch := s.next() + + // skip white space + for isWhitespace(ch) { + ch = s.next() + } + + var tok token.Type + + // token text markings + s.tokStart = s.srcPos.Offset - s.lastCharLen + + // token position, initial next() is moving the offset by one(size of rune + // actually), though we are interested with the starting point + s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen + if s.srcPos.Column > 0 { + // common case: last character was not a '\n' + s.tokPos.Line = s.srcPos.Line + s.tokPos.Column = s.srcPos.Column + } else { + // last character was a '\n' + // (we cannot be at the beginning of the source + // since we have called next() at least once) + s.tokPos.Line = s.srcPos.Line - 1 + s.tokPos.Column = s.lastLineLen + } + + switch { + case isLetter(ch): + tok = token.IDENT + lit := s.scanIdentifier() + if lit == "true" || lit == "false" { + tok = token.BOOL + } + case isDecimal(ch): + tok = s.scanNumber(ch) + default: + switch ch { + case eof: + tok = token.EOF + case '"': + tok = token.STRING + s.scanString() + case '#', '/': + tok = token.COMMENT + s.scanComment(ch) + case '.': + tok = token.PERIOD + ch = s.peek() + if isDecimal(ch) { + tok = token.FLOAT + ch = s.scanMantissa(ch) + ch = s.scanExponent(ch) + } + case '<': + tok = token.HEREDOC + s.scanHeredoc() + case '[': + tok = token.LBRACK + case ']': + tok = token.RBRACK + case '{': + tok = token.LBRACE + case '}': + tok = token.RBRACE + case ',': + tok = token.COMMA + case '=': + tok = token.ASSIGN + case '+': + tok = token.ADD + case '-': + if isDecimal(s.peek()) { + ch := s.next() + tok = s.scanNumber(ch) + } else { + tok = token.SUB + } + default: + s.err("illegal char") + } + } + + // finish token ending + s.tokEnd = s.srcPos.Offset + + // create token literal + var tokenText string + if s.tokStart >= 0 { + tokenText = string(s.src[s.tokStart:s.tokEnd]) + } + s.tokStart = s.tokEnd // ensure idempotency of tokenText() call + + return token.Token{ + Type: tok, + Pos: s.tokPos, + Text: tokenText, + } +} + +func (s *Scanner) scanComment(ch rune) { + // single line comments + if ch == '#' || (ch == '/' && s.peek() != '*') { + if ch == '/' && s.peek() != '/' { + s.err("expected '/' for comment") + return + } + + ch = s.next() + for ch != '\n' && ch >= 0 && ch != eof { + ch = s.next() + } + if ch != eof && ch >= 0 { + s.unread() + } + return + } + + // be sure we get the character after /* This allows us to find comment's + // that are not erminated + if ch == '/' { + s.next() + ch = s.next() // read character after "/*" + } + + // look for /* - style comments + for { + if ch < 0 || ch == eof { + s.err("comment not terminated") + break + } + + ch0 := ch + ch = s.next() + if ch0 == '*' && ch == '/' { + break + } + } +} + +// scanNumber scans a HCL number definition starting with the given rune +func (s *Scanner) scanNumber(ch rune) token.Type { + if ch == '0' { + // check for hexadecimal, octal or float + ch = s.next() + if ch == 'x' || ch == 'X' { + // hexadecimal + ch = s.next() + found := false + for isHexadecimal(ch) { + ch = s.next() + found = true + } + + if !found { + s.err("illegal hexadecimal number") + } + + if ch != eof { + s.unread() + } + + return token.NUMBER + } + + // now it's either something like: 0421(octal) or 0.1231(float) + illegalOctal := false + for isDecimal(ch) { + ch = s.next() + if ch == '8' || ch == '9' { + // this is just a possibility. For example 0159 is illegal, but + // 0159.23 is valid. So we mark a possible illegal octal. If + // the next character is not a period, we'll print the error. + illegalOctal = true + } + } + + if ch == 'e' || ch == 'E' { + ch = s.scanExponent(ch) + return token.FLOAT + } + + if ch == '.' { + ch = s.scanFraction(ch) + + if ch == 'e' || ch == 'E' { + ch = s.next() + ch = s.scanExponent(ch) + } + return token.FLOAT + } + + if illegalOctal { + s.err("illegal octal number") + } + + if ch != eof { + s.unread() + } + return token.NUMBER + } + + s.scanMantissa(ch) + ch = s.next() // seek forward + if ch == 'e' || ch == 'E' { + ch = s.scanExponent(ch) + return token.FLOAT + } + + if ch == '.' { + ch = s.scanFraction(ch) + if ch == 'e' || ch == 'E' { + ch = s.next() + ch = s.scanExponent(ch) + } + return token.FLOAT + } + + if ch != eof { + s.unread() + } + return token.NUMBER +} + +// scanMantissa scans the mantissa beginning from the rune. It returns the next +// non decimal rune. It's used to determine wheter it's a fraction or exponent. +func (s *Scanner) scanMantissa(ch rune) rune { + scanned := false + for isDecimal(ch) { + ch = s.next() + scanned = true + } + + if scanned && ch != eof { + s.unread() + } + return ch +} + +// scanFraction scans the fraction after the '.' rune +func (s *Scanner) scanFraction(ch rune) rune { + if ch == '.' { + ch = s.peek() // we peek just to see if we can move forward + ch = s.scanMantissa(ch) + } + return ch +} + +// scanExponent scans the remaining parts of an exponent after the 'e' or 'E' +// rune. +func (s *Scanner) scanExponent(ch rune) rune { + if ch == 'e' || ch == 'E' { + ch = s.next() + if ch == '-' || ch == '+' { + ch = s.next() + } + ch = s.scanMantissa(ch) + } + return ch +} + +// scanHeredoc scans a heredoc string +func (s *Scanner) scanHeredoc() { + // Scan the second '<' in example: '<= len(identBytes) && identRegexp.Match(s.src[lineStart:s.srcPos.Offset-s.lastCharLen]) { + break + } + + // Not an anchor match, record the start of a new line + lineStart = s.srcPos.Offset + } + + if ch == eof { + s.err("heredoc not terminated") + return + } + } + + return +} + +// scanString scans a quoted string +func (s *Scanner) scanString() { + braces := 0 + for { + // '"' opening already consumed + // read character after quote + ch := s.next() + + if (ch == '\n' && braces == 0) || ch < 0 || ch == eof { + s.err("literal not terminated") + return + } + + if ch == '"' && braces == 0 { + break + } + + // If we're going into a ${} then we can ignore quotes for awhile + if braces == 0 && ch == '$' && s.peek() == '{' { + braces++ + s.next() + } else if braces > 0 && ch == '{' { + braces++ + } + if braces > 0 && ch == '}' { + braces-- + } + + if ch == '\\' { + s.scanEscape() + } + } + + return +} + +// scanEscape scans an escape sequence +func (s *Scanner) scanEscape() rune { + // http://en.cppreference.com/w/cpp/language/escape + ch := s.next() // read character after '/' + switch ch { + case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"': + // nothing to do + case '0', '1', '2', '3', '4', '5', '6', '7': + // octal notation + ch = s.scanDigits(ch, 8, 3) + case 'x': + // hexademical notation + ch = s.scanDigits(s.next(), 16, 2) + case 'u': + // universal character name + ch = s.scanDigits(s.next(), 16, 4) + case 'U': + // universal character name + ch = s.scanDigits(s.next(), 16, 8) + default: + s.err("illegal char escape") + } + return ch +} + +// scanDigits scans a rune with the given base for n times. For example an +// octal notation \184 would yield in scanDigits(ch, 8, 3) +func (s *Scanner) scanDigits(ch rune, base, n int) rune { + start := n + for n > 0 && digitVal(ch) < base { + ch = s.next() + if ch == eof { + // If we see an EOF, we halt any more scanning of digits + // immediately. + break + } + + n-- + } + if n > 0 { + s.err("illegal char escape") + } + + if n != start && ch != eof { + // we scanned all digits, put the last non digit char back, + // only if we read anything at all + s.unread() + } + + return ch +} + +// scanIdentifier scans an identifier and returns the literal string +func (s *Scanner) scanIdentifier() string { + offs := s.srcPos.Offset - s.lastCharLen + ch := s.next() + for isLetter(ch) || isDigit(ch) || ch == '-' || ch == '.' { + ch = s.next() + } + + if ch != eof { + s.unread() // we got identifier, put back latest char + } + + return string(s.src[offs:s.srcPos.Offset]) +} + +// recentPosition returns the position of the character immediately after the +// character or token returned by the last call to Scan. +func (s *Scanner) recentPosition() (pos token.Pos) { + pos.Offset = s.srcPos.Offset - s.lastCharLen + switch { + case s.srcPos.Column > 0: + // common case: last character was not a '\n' + pos.Line = s.srcPos.Line + pos.Column = s.srcPos.Column + case s.lastLineLen > 0: + // last character was a '\n' + // (we cannot be at the beginning of the source + // since we have called next() at least once) + pos.Line = s.srcPos.Line - 1 + pos.Column = s.lastLineLen + default: + // at the beginning of the source + pos.Line = 1 + pos.Column = 1 + } + return +} + +// err prints the error of any scanning to s.Error function. If the function is +// not defined, by default it prints them to os.Stderr +func (s *Scanner) err(msg string) { + s.ErrorCount++ + pos := s.recentPosition() + + if s.Error != nil { + s.Error(pos, msg) + return + } + + fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg) +} + +// isHexadecimal returns true if the given rune is a letter +func isLetter(ch rune) bool { + return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) +} + +// isDigit returns true if the given rune is a decimal digit +func isDigit(ch rune) bool { + return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) +} + +// isDecimal returns true if the given rune is a decimal number +func isDecimal(ch rune) bool { + return '0' <= ch && ch <= '9' +} + +// isHexadecimal returns true if the given rune is an hexadecimal number +func isHexadecimal(ch rune) bool { + return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' +} + +// isWhitespace returns true if the rune is a space, tab, newline or carriage return +func isWhitespace(ch rune) bool { + return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' +} + +// digitVal returns the integer value of a given octal,decimal or hexadecimal rune +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch - '0') + case 'a' <= ch && ch <= 'f': + return int(ch - 'a' + 10) + case 'A' <= ch && ch <= 'F': + return int(ch - 'A' + 10) + } + return 16 // larger than any legal digit val +} diff --git a/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go new file mode 100644 index 000000000..5f981eaa2 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go @@ -0,0 +1,241 @@ +package strconv + +import ( + "errors" + "unicode/utf8" +) + +// ErrSyntax indicates that a value does not have the right syntax for the target type. +var ErrSyntax = errors.New("invalid syntax") + +// Unquote interprets s as a single-quoted, double-quoted, +// or backquoted Go string literal, returning the string value +// that s quotes. (If s is single-quoted, it would be a Go +// character literal; Unquote returns the corresponding +// one-character string.) +func Unquote(s string) (t string, err error) { + n := len(s) + if n < 2 { + return "", ErrSyntax + } + quote := s[0] + if quote != s[n-1] { + return "", ErrSyntax + } + s = s[1 : n-1] + + if quote != '"' { + return "", ErrSyntax + } + if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') { + return "", ErrSyntax + } + + // Is it trivial? Avoid allocation. + if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') { + switch quote { + case '"': + return s, nil + case '\'': + r, size := utf8.DecodeRuneInString(s) + if size == len(s) && (r != utf8.RuneError || size != 1) { + return s, nil + } + } + } + + var runeTmp [utf8.UTFMax]byte + buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. + for len(s) > 0 { + // If we're starting a '${}' then let it through un-unquoted. + // Specifically: we don't unquote any characters within the `${}` + // section. + if s[0] == '$' && len(s) > 1 && s[1] == '{' { + buf = append(buf, '$', '{') + s = s[2:] + + // Continue reading until we find the closing brace, copying as-is + braces := 1 + for len(s) > 0 && braces > 0 { + r, size := utf8.DecodeRuneInString(s) + if r == utf8.RuneError { + return "", ErrSyntax + } + + s = s[size:] + + n := utf8.EncodeRune(runeTmp[:], r) + buf = append(buf, runeTmp[:n]...) + + switch r { + case '{': + braces++ + case '}': + braces-- + } + } + if braces != 0 { + return "", ErrSyntax + } + if len(s) == 0 { + // If there's no string left, we're done! + break + } else { + // If there's more left, we need to pop back up to the top of the loop + // in case there's another interpolation in this string. + continue + } + } + + if s[0] == '\n' { + return "", ErrSyntax + } + + c, multibyte, ss, err := unquoteChar(s, quote) + if err != nil { + return "", err + } + s = ss + if c < utf8.RuneSelf || !multibyte { + buf = append(buf, byte(c)) + } else { + n := utf8.EncodeRune(runeTmp[:], c) + buf = append(buf, runeTmp[:n]...) + } + if quote == '\'' && len(s) != 0 { + // single-quoted must be single character + return "", ErrSyntax + } + } + return string(buf), nil +} + +// contains reports whether the string contains the byte c. +func contains(s string, c byte) bool { + for i := 0; i < len(s); i++ { + if s[i] == c { + return true + } + } + return false +} + +func unhex(b byte) (v rune, ok bool) { + c := rune(b) + switch { + case '0' <= c && c <= '9': + return c - '0', true + case 'a' <= c && c <= 'f': + return c - 'a' + 10, true + case 'A' <= c && c <= 'F': + return c - 'A' + 10, true + } + return +} + +func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) { + // easy cases + switch c := s[0]; { + case c == quote && (quote == '\'' || quote == '"'): + err = ErrSyntax + return + case c >= utf8.RuneSelf: + r, size := utf8.DecodeRuneInString(s) + return r, true, s[size:], nil + case c != '\\': + return rune(s[0]), false, s[1:], nil + } + + // hard case: c is backslash + if len(s) <= 1 { + err = ErrSyntax + return + } + c := s[1] + s = s[2:] + + switch c { + case 'a': + value = '\a' + case 'b': + value = '\b' + case 'f': + value = '\f' + case 'n': + value = '\n' + case 'r': + value = '\r' + case 't': + value = '\t' + case 'v': + value = '\v' + case 'x', 'u', 'U': + n := 0 + switch c { + case 'x': + n = 2 + case 'u': + n = 4 + case 'U': + n = 8 + } + var v rune + if len(s) < n { + err = ErrSyntax + return + } + for j := 0; j < n; j++ { + x, ok := unhex(s[j]) + if !ok { + err = ErrSyntax + return + } + v = v<<4 | x + } + s = s[n:] + if c == 'x' { + // single-byte string, possibly not UTF-8 + value = v + break + } + if v > utf8.MaxRune { + err = ErrSyntax + return + } + value = v + multibyte = true + case '0', '1', '2', '3', '4', '5', '6', '7': + v := rune(c) - '0' + if len(s) < 2 { + err = ErrSyntax + return + } + for j := 0; j < 2; j++ { // one digit already; two more + x := rune(s[j]) - '0' + if x < 0 || x > 7 { + err = ErrSyntax + return + } + v = (v << 3) | x + } + s = s[2:] + if v > 255 { + err = ErrSyntax + return + } + value = v + case '\\': + value = '\\' + case '\'', '"': + if c != quote { + err = ErrSyntax + return + } + value = rune(c) + default: + err = ErrSyntax + return + } + tail = s + return +} diff --git a/vendor/github.com/hashicorp/hcl/hcl/token/position.go b/vendor/github.com/hashicorp/hcl/hcl/token/position.go new file mode 100644 index 000000000..59c1bb72d --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/token/position.go @@ -0,0 +1,46 @@ +package token + +import "fmt" + +// Pos describes an arbitrary source position +// including the file, line, and column location. +// A Position is valid if the line number is > 0. +type Pos struct { + Filename string // filename, if any + Offset int // offset, starting at 0 + Line int // line number, starting at 1 + Column int // column number, starting at 1 (character count) +} + +// IsValid returns true if the position is valid. +func (p *Pos) IsValid() bool { return p.Line > 0 } + +// String returns a string in one of several forms: +// +// file:line:column valid position with file name +// line:column valid position without file name +// file invalid position with file name +// - invalid position without file name +func (p Pos) String() string { + s := p.Filename + if p.IsValid() { + if s != "" { + s += ":" + } + s += fmt.Sprintf("%d:%d", p.Line, p.Column) + } + if s == "" { + s = "-" + } + return s +} + +// Before reports whether the position p is before u. +func (p Pos) Before(u Pos) bool { + return u.Offset > p.Offset || u.Line > p.Line +} + +// After reports whether the position p is after u. +func (p Pos) After(u Pos) bool { + return u.Offset < p.Offset || u.Line < p.Line +} diff --git a/vendor/github.com/hashicorp/hcl/hcl/token/token.go b/vendor/github.com/hashicorp/hcl/hcl/token/token.go new file mode 100644 index 000000000..e37c0664e --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/token/token.go @@ -0,0 +1,219 @@ +// Package token defines constants representing the lexical tokens for HCL +// (HashiCorp Configuration Language) +package token + +import ( + "fmt" + "strconv" + "strings" + + hclstrconv "github.com/hashicorp/hcl/hcl/strconv" +) + +// Token defines a single HCL token which can be obtained via the Scanner +type Token struct { + Type Type + Pos Pos + Text string + JSON bool +} + +// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language) +type Type int + +const ( + // Special tokens + ILLEGAL Type = iota + EOF + COMMENT + + identifier_beg + IDENT // literals + literal_beg + NUMBER // 12345 + FLOAT // 123.45 + BOOL // true,false + STRING // "abc" + HEREDOC // < 0 { + // Pop the current item + n := len(frontier) + item := frontier[n-1] + frontier = frontier[:n-1] + + switch v := item.Val.(type) { + case *ast.ObjectType: + items, frontier = flattenObjectType(v, item, items, frontier) + case *ast.ListType: + items, frontier = flattenListType(v, item, items, frontier) + default: + items = append(items, item) + } + } + + // Reverse the list since the frontier model runs things backwards + for i := len(items)/2 - 1; i >= 0; i-- { + opp := len(items) - 1 - i + items[i], items[opp] = items[opp], items[i] + } + + // Done! Set the original items + list.Items = items + return n, true + }) +} + +func flattenListType( + ot *ast.ListType, + item *ast.ObjectItem, + items []*ast.ObjectItem, + frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { + // If the list is empty, keep the original list + if len(ot.List) == 0 { + items = append(items, item) + return items, frontier + } + + // All the elements of this object must also be objects! + for _, subitem := range ot.List { + if _, ok := subitem.(*ast.ObjectType); !ok { + items = append(items, item) + return items, frontier + } + } + + // Great! We have a match go through all the items and flatten + for _, elem := range ot.List { + // Add it to the frontier so that we can recurse + frontier = append(frontier, &ast.ObjectItem{ + Keys: item.Keys, + Assign: item.Assign, + Val: elem, + LeadComment: item.LeadComment, + LineComment: item.LineComment, + }) + } + + return items, frontier +} + +func flattenObjectType( + ot *ast.ObjectType, + item *ast.ObjectItem, + items []*ast.ObjectItem, + frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { + // If the list has no items we do not have to flatten anything + if ot.List.Items == nil { + items = append(items, item) + return items, frontier + } + + // All the elements of this object must also be objects! + for _, subitem := range ot.List.Items { + if _, ok := subitem.Val.(*ast.ObjectType); !ok { + items = append(items, item) + return items, frontier + } + } + + // Great! We have a match go through all the items and flatten + for _, subitem := range ot.List.Items { + // Copy the new key + keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys)) + copy(keys, item.Keys) + copy(keys[len(item.Keys):], subitem.Keys) + + // Add it to the frontier so that we can recurse + frontier = append(frontier, &ast.ObjectItem{ + Keys: keys, + Assign: item.Assign, + Val: subitem.Val, + LeadComment: item.LeadComment, + LineComment: item.LineComment, + }) + } + + return items, frontier +} diff --git a/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/vendor/github.com/hashicorp/hcl/json/parser/parser.go new file mode 100644 index 000000000..125a5f072 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/json/parser/parser.go @@ -0,0 +1,313 @@ +package parser + +import ( + "errors" + "fmt" + + "github.com/hashicorp/hcl/hcl/ast" + hcltoken "github.com/hashicorp/hcl/hcl/token" + "github.com/hashicorp/hcl/json/scanner" + "github.com/hashicorp/hcl/json/token" +) + +type Parser struct { + sc *scanner.Scanner + + // Last read token + tok token.Token + commaPrev token.Token + + enableTrace bool + indent int + n int // buffer size (max = 1) +} + +func newParser(src []byte) *Parser { + return &Parser{ + sc: scanner.New(src), + } +} + +// Parse returns the fully parsed source and returns the abstract syntax tree. +func Parse(src []byte) (*ast.File, error) { + p := newParser(src) + return p.Parse() +} + +var errEofToken = errors.New("EOF token found") + +// Parse returns the fully parsed source and returns the abstract syntax tree. +func (p *Parser) Parse() (*ast.File, error) { + f := &ast.File{} + var err, scerr error + p.sc.Error = func(pos token.Pos, msg string) { + scerr = fmt.Errorf("%s: %s", pos, msg) + } + + // The root must be an object in JSON + object, err := p.object() + if scerr != nil { + return nil, scerr + } + if err != nil { + return nil, err + } + + // We make our final node an object list so it is more HCL compatible + f.Node = object.List + + // Flatten it, which finds patterns and turns them into more HCL-like + // AST trees. + flattenObjects(f.Node) + + return f, nil +} + +func (p *Parser) objectList() (*ast.ObjectList, error) { + defer un(trace(p, "ParseObjectList")) + node := &ast.ObjectList{} + + for { + n, err := p.objectItem() + if err == errEofToken { + break // we are finished + } + + // we don't return a nil node, because might want to use already + // collected items. + if err != nil { + return node, err + } + + node.Add(n) + + // Check for a followup comma. If it isn't a comma, then we're done + if tok := p.scan(); tok.Type != token.COMMA { + break + } + } + + return node, nil +} + +// objectItem parses a single object item +func (p *Parser) objectItem() (*ast.ObjectItem, error) { + defer un(trace(p, "ParseObjectItem")) + + keys, err := p.objectKey() + if err != nil { + return nil, err + } + + o := &ast.ObjectItem{ + Keys: keys, + } + + switch p.tok.Type { + case token.COLON: + pos := p.tok.Pos + o.Assign = hcltoken.Pos{ + Filename: pos.Filename, + Offset: pos.Offset, + Line: pos.Line, + Column: pos.Column, + } + + o.Val, err = p.objectValue() + if err != nil { + return nil, err + } + } + + return o, nil +} + +// objectKey parses an object key and returns a ObjectKey AST +func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { + keyCount := 0 + keys := make([]*ast.ObjectKey, 0) + + for { + tok := p.scan() + switch tok.Type { + case token.EOF: + return nil, errEofToken + case token.STRING: + keyCount++ + keys = append(keys, &ast.ObjectKey{ + Token: p.tok.HCLToken(), + }) + case token.COLON: + // If we have a zero keycount it means that we never got + // an object key, i.e. `{ :`. This is a syntax error. + if keyCount == 0 { + return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) + } + + // Done + return keys, nil + case token.ILLEGAL: + return nil, errors.New("illegal") + default: + return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) + } + } +} + +// object parses any type of object, such as number, bool, string, object or +// list. +func (p *Parser) objectValue() (ast.Node, error) { + defer un(trace(p, "ParseObjectValue")) + tok := p.scan() + + switch tok.Type { + case token.NUMBER, token.FLOAT, token.BOOL, token.NULL, token.STRING: + return p.literalType() + case token.LBRACE: + return p.objectType() + case token.LBRACK: + return p.listType() + case token.EOF: + return nil, errEofToken + } + + return nil, fmt.Errorf("Expected object value, got unknown token: %+v", tok) +} + +// object parses any type of object, such as number, bool, string, object or +// list. +func (p *Parser) object() (*ast.ObjectType, error) { + defer un(trace(p, "ParseType")) + tok := p.scan() + + switch tok.Type { + case token.LBRACE: + return p.objectType() + case token.EOF: + return nil, errEofToken + } + + return nil, fmt.Errorf("Expected object, got unknown token: %+v", tok) +} + +// objectType parses an object type and returns a ObjectType AST +func (p *Parser) objectType() (*ast.ObjectType, error) { + defer un(trace(p, "ParseObjectType")) + + // we assume that the currently scanned token is a LBRACE + o := &ast.ObjectType{} + + l, err := p.objectList() + + // if we hit RBRACE, we are good to go (means we parsed all Items), if it's + // not a RBRACE, it's an syntax error and we just return it. + if err != nil && p.tok.Type != token.RBRACE { + return nil, err + } + + o.List = l + return o, nil +} + +// listType parses a list type and returns a ListType AST +func (p *Parser) listType() (*ast.ListType, error) { + defer un(trace(p, "ParseListType")) + + // we assume that the currently scanned token is a LBRACK + l := &ast.ListType{} + + for { + tok := p.scan() + switch tok.Type { + case token.NUMBER, token.FLOAT, token.STRING: + node, err := p.literalType() + if err != nil { + return nil, err + } + + l.Add(node) + case token.COMMA: + continue + case token.LBRACE: + node, err := p.objectType() + if err != nil { + return nil, err + } + + l.Add(node) + case token.BOOL: + // TODO(arslan) should we support? not supported by HCL yet + case token.LBRACK: + // TODO(arslan) should we support nested lists? Even though it's + // written in README of HCL, it's not a part of the grammar + // (not defined in parse.y) + case token.RBRACK: + // finished + return l, nil + default: + return nil, fmt.Errorf("unexpected token while parsing list: %s", tok.Type) + } + + } +} + +// literalType parses a literal type and returns a LiteralType AST +func (p *Parser) literalType() (*ast.LiteralType, error) { + defer un(trace(p, "ParseLiteral")) + + return &ast.LiteralType{ + Token: p.tok.HCLToken(), + }, nil +} + +// scan returns the next token from the underlying scanner. If a token has +// been unscanned then read that instead. +func (p *Parser) scan() token.Token { + // If we have a token on the buffer, then return it. + if p.n != 0 { + p.n = 0 + return p.tok + } + + p.tok = p.sc.Scan() + return p.tok +} + +// unscan pushes the previously read token back onto the buffer. +func (p *Parser) unscan() { + p.n = 1 +} + +// ---------------------------------------------------------------------------- +// Parsing support + +func (p *Parser) printTrace(a ...interface{}) { + if !p.enableTrace { + return + } + + const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " + const n = len(dots) + fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column) + + i := 2 * p.indent + for i > n { + fmt.Print(dots) + i -= n + } + // i <= n + fmt.Print(dots[0:i]) + fmt.Println(a...) +} + +func trace(p *Parser, msg string) *Parser { + p.printTrace(msg, "(") + p.indent++ + return p +} + +// Usage pattern: defer un(trace(p, "...")) +func un(p *Parser) { + p.indent-- + p.printTrace(")") +} diff --git a/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go new file mode 100644 index 000000000..fe3f0f095 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go @@ -0,0 +1,451 @@ +package scanner + +import ( + "bytes" + "fmt" + "os" + "unicode" + "unicode/utf8" + + "github.com/hashicorp/hcl/json/token" +) + +// eof represents a marker rune for the end of the reader. +const eof = rune(0) + +// Scanner defines a lexical scanner +type Scanner struct { + buf *bytes.Buffer // Source buffer for advancing and scanning + src []byte // Source buffer for immutable access + + // Source Position + srcPos token.Pos // current position + prevPos token.Pos // previous position, used for peek() method + + lastCharLen int // length of last character in bytes + lastLineLen int // length of last line in characters (for correct column reporting) + + tokStart int // token text start position + tokEnd int // token text end position + + // Error is called for each error encountered. If no Error + // function is set, the error is reported to os.Stderr. + Error func(pos token.Pos, msg string) + + // ErrorCount is incremented by one for each error encountered. + ErrorCount int + + // tokPos is the start position of most recently scanned token; set by + // Scan. The Filename field is always left untouched by the Scanner. If + // an error is reported (via Error) and Position is invalid, the scanner is + // not inside a token. + tokPos token.Pos +} + +// New creates and initializes a new instance of Scanner using src as +// its source content. +func New(src []byte) *Scanner { + // even though we accept a src, we read from a io.Reader compatible type + // (*bytes.Buffer). So in the future we might easily change it to streaming + // read. + b := bytes.NewBuffer(src) + s := &Scanner{ + buf: b, + src: src, + } + + // srcPosition always starts with 1 + s.srcPos.Line = 1 + return s +} + +// next reads the next rune from the bufferred reader. Returns the rune(0) if +// an error occurs (or io.EOF is returned). +func (s *Scanner) next() rune { + ch, size, err := s.buf.ReadRune() + if err != nil { + // advance for error reporting + s.srcPos.Column++ + s.srcPos.Offset += size + s.lastCharLen = size + return eof + } + + if ch == utf8.RuneError && size == 1 { + s.srcPos.Column++ + s.srcPos.Offset += size + s.lastCharLen = size + s.err("illegal UTF-8 encoding") + return ch + } + + // remember last position + s.prevPos = s.srcPos + + s.srcPos.Column++ + s.lastCharLen = size + s.srcPos.Offset += size + + if ch == '\n' { + s.srcPos.Line++ + s.lastLineLen = s.srcPos.Column + s.srcPos.Column = 0 + } + + // debug + // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) + return ch +} + +// unread unreads the previous read Rune and updates the source position +func (s *Scanner) unread() { + if err := s.buf.UnreadRune(); err != nil { + panic(err) // this is user fault, we should catch it + } + s.srcPos = s.prevPos // put back last position +} + +// peek returns the next rune without advancing the reader. +func (s *Scanner) peek() rune { + peek, _, err := s.buf.ReadRune() + if err != nil { + return eof + } + + s.buf.UnreadRune() + return peek +} + +// Scan scans the next token and returns the token. +func (s *Scanner) Scan() token.Token { + ch := s.next() + + // skip white space + for isWhitespace(ch) { + ch = s.next() + } + + var tok token.Type + + // token text markings + s.tokStart = s.srcPos.Offset - s.lastCharLen + + // token position, initial next() is moving the offset by one(size of rune + // actually), though we are interested with the starting point + s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen + if s.srcPos.Column > 0 { + // common case: last character was not a '\n' + s.tokPos.Line = s.srcPos.Line + s.tokPos.Column = s.srcPos.Column + } else { + // last character was a '\n' + // (we cannot be at the beginning of the source + // since we have called next() at least once) + s.tokPos.Line = s.srcPos.Line - 1 + s.tokPos.Column = s.lastLineLen + } + + switch { + case isLetter(ch): + lit := s.scanIdentifier() + if lit == "true" || lit == "false" { + tok = token.BOOL + } else if lit == "null" { + tok = token.NULL + } else { + s.err("illegal char") + } + case isDecimal(ch): + tok = s.scanNumber(ch) + default: + switch ch { + case eof: + tok = token.EOF + case '"': + tok = token.STRING + s.scanString() + case '.': + tok = token.PERIOD + ch = s.peek() + if isDecimal(ch) { + tok = token.FLOAT + ch = s.scanMantissa(ch) + ch = s.scanExponent(ch) + } + case '[': + tok = token.LBRACK + case ']': + tok = token.RBRACK + case '{': + tok = token.LBRACE + case '}': + tok = token.RBRACE + case ',': + tok = token.COMMA + case ':': + tok = token.COLON + case '-': + if isDecimal(s.peek()) { + ch := s.next() + tok = s.scanNumber(ch) + } else { + s.err("illegal char") + } + default: + s.err("illegal char: " + string(ch)) + } + } + + // finish token ending + s.tokEnd = s.srcPos.Offset + + // create token literal + var tokenText string + if s.tokStart >= 0 { + tokenText = string(s.src[s.tokStart:s.tokEnd]) + } + s.tokStart = s.tokEnd // ensure idempotency of tokenText() call + + return token.Token{ + Type: tok, + Pos: s.tokPos, + Text: tokenText, + } +} + +// scanNumber scans a HCL number definition starting with the given rune +func (s *Scanner) scanNumber(ch rune) token.Type { + zero := ch == '0' + pos := s.srcPos + + s.scanMantissa(ch) + ch = s.next() // seek forward + if ch == 'e' || ch == 'E' { + ch = s.scanExponent(ch) + return token.FLOAT + } + + if ch == '.' { + ch = s.scanFraction(ch) + if ch == 'e' || ch == 'E' { + ch = s.next() + ch = s.scanExponent(ch) + } + return token.FLOAT + } + + if ch != eof { + s.unread() + } + + // If we have a larger number and this is zero, error + if zero && pos != s.srcPos { + s.err("numbers cannot start with 0") + } + + return token.NUMBER +} + +// scanMantissa scans the mantissa beginning from the rune. It returns the next +// non decimal rune. It's used to determine wheter it's a fraction or exponent. +func (s *Scanner) scanMantissa(ch rune) rune { + scanned := false + for isDecimal(ch) { + ch = s.next() + scanned = true + } + + if scanned && ch != eof { + s.unread() + } + return ch +} + +// scanFraction scans the fraction after the '.' rune +func (s *Scanner) scanFraction(ch rune) rune { + if ch == '.' { + ch = s.peek() // we peek just to see if we can move forward + ch = s.scanMantissa(ch) + } + return ch +} + +// scanExponent scans the remaining parts of an exponent after the 'e' or 'E' +// rune. +func (s *Scanner) scanExponent(ch rune) rune { + if ch == 'e' || ch == 'E' { + ch = s.next() + if ch == '-' || ch == '+' { + ch = s.next() + } + ch = s.scanMantissa(ch) + } + return ch +} + +// scanString scans a quoted string +func (s *Scanner) scanString() { + braces := 0 + for { + // '"' opening already consumed + // read character after quote + ch := s.next() + + if ch == '\n' || ch < 0 || ch == eof { + s.err("literal not terminated") + return + } + + if ch == '"' { + break + } + + // If we're going into a ${} then we can ignore quotes for awhile + if braces == 0 && ch == '$' && s.peek() == '{' { + braces++ + s.next() + } else if braces > 0 && ch == '{' { + braces++ + } + if braces > 0 && ch == '}' { + braces-- + } + + if ch == '\\' { + s.scanEscape() + } + } + + return +} + +// scanEscape scans an escape sequence +func (s *Scanner) scanEscape() rune { + // http://en.cppreference.com/w/cpp/language/escape + ch := s.next() // read character after '/' + switch ch { + case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"': + // nothing to do + case '0', '1', '2', '3', '4', '5', '6', '7': + // octal notation + ch = s.scanDigits(ch, 8, 3) + case 'x': + // hexademical notation + ch = s.scanDigits(s.next(), 16, 2) + case 'u': + // universal character name + ch = s.scanDigits(s.next(), 16, 4) + case 'U': + // universal character name + ch = s.scanDigits(s.next(), 16, 8) + default: + s.err("illegal char escape") + } + return ch +} + +// scanDigits scans a rune with the given base for n times. For example an +// octal notation \184 would yield in scanDigits(ch, 8, 3) +func (s *Scanner) scanDigits(ch rune, base, n int) rune { + for n > 0 && digitVal(ch) < base { + ch = s.next() + n-- + } + if n > 0 { + s.err("illegal char escape") + } + + // we scanned all digits, put the last non digit char back + s.unread() + return ch +} + +// scanIdentifier scans an identifier and returns the literal string +func (s *Scanner) scanIdentifier() string { + offs := s.srcPos.Offset - s.lastCharLen + ch := s.next() + for isLetter(ch) || isDigit(ch) || ch == '-' { + ch = s.next() + } + + if ch != eof { + s.unread() // we got identifier, put back latest char + } + + return string(s.src[offs:s.srcPos.Offset]) +} + +// recentPosition returns the position of the character immediately after the +// character or token returned by the last call to Scan. +func (s *Scanner) recentPosition() (pos token.Pos) { + pos.Offset = s.srcPos.Offset - s.lastCharLen + switch { + case s.srcPos.Column > 0: + // common case: last character was not a '\n' + pos.Line = s.srcPos.Line + pos.Column = s.srcPos.Column + case s.lastLineLen > 0: + // last character was a '\n' + // (we cannot be at the beginning of the source + // since we have called next() at least once) + pos.Line = s.srcPos.Line - 1 + pos.Column = s.lastLineLen + default: + // at the beginning of the source + pos.Line = 1 + pos.Column = 1 + } + return +} + +// err prints the error of any scanning to s.Error function. If the function is +// not defined, by default it prints them to os.Stderr +func (s *Scanner) err(msg string) { + s.ErrorCount++ + pos := s.recentPosition() + + if s.Error != nil { + s.Error(pos, msg) + return + } + + fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg) +} + +// isHexadecimal returns true if the given rune is a letter +func isLetter(ch rune) bool { + return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) +} + +// isHexadecimal returns true if the given rune is a decimal digit +func isDigit(ch rune) bool { + return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) +} + +// isHexadecimal returns true if the given rune is a decimal number +func isDecimal(ch rune) bool { + return '0' <= ch && ch <= '9' +} + +// isHexadecimal returns true if the given rune is an hexadecimal number +func isHexadecimal(ch rune) bool { + return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' +} + +// isWhitespace returns true if the rune is a space, tab, newline or carriage return +func isWhitespace(ch rune) bool { + return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' +} + +// digitVal returns the integer value of a given octal,decimal or hexadecimal rune +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch - '0') + case 'a' <= ch && ch <= 'f': + return int(ch - 'a' + 10) + case 'A' <= ch && ch <= 'F': + return int(ch - 'A' + 10) + } + return 16 // larger than any legal digit val +} diff --git a/vendor/github.com/hashicorp/hcl/json/token/position.go b/vendor/github.com/hashicorp/hcl/json/token/position.go new file mode 100644 index 000000000..59c1bb72d --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/json/token/position.go @@ -0,0 +1,46 @@ +package token + +import "fmt" + +// Pos describes an arbitrary source position +// including the file, line, and column location. +// A Position is valid if the line number is > 0. +type Pos struct { + Filename string // filename, if any + Offset int // offset, starting at 0 + Line int // line number, starting at 1 + Column int // column number, starting at 1 (character count) +} + +// IsValid returns true if the position is valid. +func (p *Pos) IsValid() bool { return p.Line > 0 } + +// String returns a string in one of several forms: +// +// file:line:column valid position with file name +// line:column valid position without file name +// file invalid position with file name +// - invalid position without file name +func (p Pos) String() string { + s := p.Filename + if p.IsValid() { + if s != "" { + s += ":" + } + s += fmt.Sprintf("%d:%d", p.Line, p.Column) + } + if s == "" { + s = "-" + } + return s +} + +// Before reports whether the position p is before u. +func (p Pos) Before(u Pos) bool { + return u.Offset > p.Offset || u.Line > p.Line +} + +// After reports whether the position p is after u. +func (p Pos) After(u Pos) bool { + return u.Offset < p.Offset || u.Line < p.Line +} diff --git a/vendor/github.com/hashicorp/hcl/json/token/token.go b/vendor/github.com/hashicorp/hcl/json/token/token.go new file mode 100644 index 000000000..95a0c3eee --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/json/token/token.go @@ -0,0 +1,118 @@ +package token + +import ( + "fmt" + "strconv" + + hcltoken "github.com/hashicorp/hcl/hcl/token" +) + +// Token defines a single HCL token which can be obtained via the Scanner +type Token struct { + Type Type + Pos Pos + Text string +} + +// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language) +type Type int + +const ( + // Special tokens + ILLEGAL Type = iota + EOF + + identifier_beg + literal_beg + NUMBER // 12345 + FLOAT // 123.45 + BOOL // true,false + STRING // "abc" + NULL // null + literal_end + identifier_end + + operator_beg + LBRACK // [ + LBRACE // { + COMMA // , + PERIOD // . + COLON // : + + RBRACK // ] + RBRACE // } + + operator_end +) + +var tokens = [...]string{ + ILLEGAL: "ILLEGAL", + + EOF: "EOF", + + NUMBER: "NUMBER", + FLOAT: "FLOAT", + BOOL: "BOOL", + STRING: "STRING", + NULL: "NULL", + + LBRACK: "LBRACK", + LBRACE: "LBRACE", + COMMA: "COMMA", + PERIOD: "PERIOD", + COLON: "COLON", + + RBRACK: "RBRACK", + RBRACE: "RBRACE", +} + +// String returns the string corresponding to the token tok. +func (t Type) String() string { + s := "" + if 0 <= t && t < Type(len(tokens)) { + s = tokens[t] + } + if s == "" { + s = "token(" + strconv.Itoa(int(t)) + ")" + } + return s +} + +// IsIdentifier returns true for tokens corresponding to identifiers and basic +// type literals; it returns false otherwise. +func (t Type) IsIdentifier() bool { return identifier_beg < t && t < identifier_end } + +// IsLiteral returns true for tokens corresponding to basic type literals; it +// returns false otherwise. +func (t Type) IsLiteral() bool { return literal_beg < t && t < literal_end } + +// IsOperator returns true for tokens corresponding to operators and +// delimiters; it returns false otherwise. +func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end } + +// String returns the token's literal text. Note that this is only +// applicable for certain token types, such as token.IDENT, +// token.STRING, etc.. +func (t Token) String() string { + return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text) +} + +// HCLToken converts this token to an HCL token. +// +// The token type must be a literal type or this will panic. +func (t Token) HCLToken() hcltoken.Token { + switch t.Type { + case BOOL: + return hcltoken.Token{Type: hcltoken.BOOL, Text: t.Text} + case FLOAT: + return hcltoken.Token{Type: hcltoken.FLOAT, Text: t.Text} + case NULL: + return hcltoken.Token{Type: hcltoken.STRING, Text: ""} + case NUMBER: + return hcltoken.Token{Type: hcltoken.NUMBER, Text: t.Text} + case STRING: + return hcltoken.Token{Type: hcltoken.STRING, Text: t.Text, JSON: true} + default: + panic(fmt.Sprintf("unimplemented HCLToken for type: %s", t.Type)) + } +} diff --git a/vendor/github.com/hashicorp/hcl/lex.go b/vendor/github.com/hashicorp/hcl/lex.go new file mode 100644 index 000000000..d9993c292 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/lex.go @@ -0,0 +1,38 @@ +package hcl + +import ( + "unicode" + "unicode/utf8" +) + +type lexModeValue byte + +const ( + lexModeUnknown lexModeValue = iota + lexModeHcl + lexModeJson +) + +// lexMode returns whether we're going to be parsing in JSON +// mode or HCL mode. +func lexMode(v []byte) lexModeValue { + var ( + r rune + w int + offset int + ) + + for { + r, w = utf8.DecodeRune(v[offset:]) + offset += w + if unicode.IsSpace(r) { + continue + } + if r == '{' { + return lexModeJson + } + break + } + + return lexModeHcl +} diff --git a/vendor/github.com/hashicorp/hcl/parse.go b/vendor/github.com/hashicorp/hcl/parse.go new file mode 100644 index 000000000..1fca53c4c --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/parse.go @@ -0,0 +1,39 @@ +package hcl + +import ( + "fmt" + + "github.com/hashicorp/hcl/hcl/ast" + hclParser "github.com/hashicorp/hcl/hcl/parser" + jsonParser "github.com/hashicorp/hcl/json/parser" +) + +// ParseBytes accepts as input byte slice and returns ast tree. +// +// Input can be either JSON or HCL +func ParseBytes(in []byte) (*ast.File, error) { + return parse(in) +} + +// ParseString accepts input as a string and returns ast tree. +func ParseString(input string) (*ast.File, error) { + return parse([]byte(input)) +} + +func parse(in []byte) (*ast.File, error) { + switch lexMode(in) { + case lexModeHcl: + return hclParser.Parse(in) + case lexModeJson: + return jsonParser.Parse(in) + } + + return nil, fmt.Errorf("unknown config format") +} + +// Parse parses the given input and returns the root object. +// +// The input format can be either HCL or JSON. +func Parse(input string) (*ast.File, error) { + return parse([]byte(input)) +} diff --git a/vendor/github.com/inconshreveable/mousetrap/LICENSE b/vendor/github.com/inconshreveable/mousetrap/LICENSE new file mode 100644 index 000000000..5f0d1fb6a --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/LICENSE @@ -0,0 +1,13 @@ +Copyright 2014 Alan Shreve + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/inconshreveable/mousetrap/README.md b/vendor/github.com/inconshreveable/mousetrap/README.md new file mode 100644 index 000000000..7a950d177 --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/README.md @@ -0,0 +1,23 @@ +# mousetrap + +mousetrap is a tiny library that answers a single question. + +On a Windows machine, was the process invoked by someone double clicking on +the executable file while browsing in explorer? + +### Motivation + +Windows developers unfamiliar with command line tools will often "double-click" +the executable for a tool. Because most CLI tools print the help and then exit +when invoked without arguments, this is often very frustrating for those users. + +mousetrap provides a way to detect these invocations so that you can provide +more helpful behavior and instructions on how to run the CLI tool. To see what +this looks like, both from an organizational and a technical perspective, see +https://inconshreveable.com/09-09-2014/sweat-the-small-stuff/ + +### The interface + +The library exposes a single interface: + + func StartedByExplorer() (bool) diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_others.go b/vendor/github.com/inconshreveable/mousetrap/trap_others.go new file mode 100644 index 000000000..9d2d8a4ba --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/trap_others.go @@ -0,0 +1,15 @@ +// +build !windows + +package mousetrap + +// StartedByExplorer returns true if the program was invoked by the user +// double-clicking on the executable from explorer.exe +// +// It is conservative and returns false if any of the internal calls fail. +// It does not guarantee that the program was run from a terminal. It only can tell you +// whether it was launched from explorer.exe +// +// On non-Windows platforms, it always returns false. +func StartedByExplorer() bool { + return false +} diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go new file mode 100644 index 000000000..336142a5e --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go @@ -0,0 +1,98 @@ +// +build windows +// +build !go1.4 + +package mousetrap + +import ( + "fmt" + "os" + "syscall" + "unsafe" +) + +const ( + // defined by the Win32 API + th32cs_snapprocess uintptr = 0x2 +) + +var ( + kernel = syscall.MustLoadDLL("kernel32.dll") + CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot") + Process32First = kernel.MustFindProc("Process32FirstW") + Process32Next = kernel.MustFindProc("Process32NextW") +) + +// ProcessEntry32 structure defined by the Win32 API +type processEntry32 struct { + dwSize uint32 + cntUsage uint32 + th32ProcessID uint32 + th32DefaultHeapID int + th32ModuleID uint32 + cntThreads uint32 + th32ParentProcessID uint32 + pcPriClassBase int32 + dwFlags uint32 + szExeFile [syscall.MAX_PATH]uint16 +} + +func getProcessEntry(pid int) (pe *processEntry32, err error) { + snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0)) + if snapshot == uintptr(syscall.InvalidHandle) { + err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1) + return + } + defer syscall.CloseHandle(syscall.Handle(snapshot)) + + var processEntry processEntry32 + processEntry.dwSize = uint32(unsafe.Sizeof(processEntry)) + ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) + if ok == 0 { + err = fmt.Errorf("Process32First: %v", e1) + return + } + + for { + if processEntry.th32ProcessID == uint32(pid) { + pe = &processEntry + return + } + + ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) + if ok == 0 { + err = fmt.Errorf("Process32Next: %v", e1) + return + } + } +} + +func getppid() (pid int, err error) { + pe, err := getProcessEntry(os.Getpid()) + if err != nil { + return + } + + pid = int(pe.th32ParentProcessID) + return +} + +// StartedByExplorer returns true if the program was invoked by the user double-clicking +// on the executable from explorer.exe +// +// It is conservative and returns false if any of the internal calls fail. +// It does not guarantee that the program was run from a terminal. It only can tell you +// whether it was launched from explorer.exe +func StartedByExplorer() bool { + ppid, err := getppid() + if err != nil { + return false + } + + pe, err := getProcessEntry(ppid) + if err != nil { + return false + } + + name := syscall.UTF16ToString(pe.szExeFile[:]) + return name == "explorer.exe" +} diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go new file mode 100644 index 000000000..9a28e57c3 --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go @@ -0,0 +1,46 @@ +// +build windows +// +build go1.4 + +package mousetrap + +import ( + "os" + "syscall" + "unsafe" +) + +func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { + snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) + if err != nil { + return nil, err + } + defer syscall.CloseHandle(snapshot) + var procEntry syscall.ProcessEntry32 + procEntry.Size = uint32(unsafe.Sizeof(procEntry)) + if err = syscall.Process32First(snapshot, &procEntry); err != nil { + return nil, err + } + for { + if procEntry.ProcessID == uint32(pid) { + return &procEntry, nil + } + err = syscall.Process32Next(snapshot, &procEntry) + if err != nil { + return nil, err + } + } +} + +// StartedByExplorer returns true if the program was invoked by the user double-clicking +// on the executable from explorer.exe +// +// It is conservative and returns false if any of the internal calls fail. +// It does not guarantee that the program was run from a terminal. It only can tell you +// whether it was launched from explorer.exe +func StartedByExplorer() bool { + pe, err := getProcessEntry(os.Getppid()) + if err != nil { + return false + } + return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) +} diff --git a/vendor/github.com/jingyugao/rowserrcheck/LICENSE b/vendor/github.com/jingyugao/rowserrcheck/LICENSE new file mode 100644 index 000000000..6957f1889 --- /dev/null +++ b/vendor/github.com/jingyugao/rowserrcheck/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Seiji Takahashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go b/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go new file mode 100644 index 000000000..7b8c64f4c --- /dev/null +++ b/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go @@ -0,0 +1,319 @@ +package rowserr + +import ( + "fmt" + "go/ast" + "go/types" + "strconv" + + "github.com/gostaticanalysis/analysisutil" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/buildssa" + "golang.org/x/tools/go/ssa" +) + +func NewAnalyzer(sqlPkgs ...string) *analysis.Analyzer { + return &analysis.Analyzer{ + Name: "rowserrcheck", + Doc: Doc, + Run: NewRun(sqlPkgs...), + Requires: []*analysis.Analyzer{ + buildssa.Analyzer, + }, + } +} + +const ( + Doc = "rowserrcheck checks whether Rows.Err is checked" + errMethod = "Err" + rowsName = "Rows" +) + +type runner struct { + pass *analysis.Pass + rowsTyp *types.Pointer + rowsObj types.Object + skipFile map[*ast.File]bool + sqlPkgs []string +} + +func NewRun(pkgs ...string) func(pass *analysis.Pass) (interface{}, error) { + return func(pass *analysis.Pass) (interface{}, error) { + pkgs = append(pkgs, "database/sql") + for _, pkg := range pkgs { + r := new(runner) + r.sqlPkgs = pkgs + r.run(pass, pkg) + } + return nil, nil + } +} + +// run executes an analysis for the pass. The receiver is passed +// by value because this func is called in parallel for different passes. +func (r runner) run(pass *analysis.Pass, pkgPath string) (interface{}, error) { + r.pass = pass + pssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA) + funcs := pssa.SrcFuncs + + pkg := pssa.Pkg.Prog.ImportedPackage(pkgPath) + if pkg == nil { + // skip + return nil, nil + } + + r.rowsObj = pkg.Type(rowsName).Object() + if r.rowsObj == nil { + // skip checking + return nil, nil + } + + resNamed, ok := r.rowsObj.Type().(*types.Named) + if !ok { + return nil, nil + } + + r.rowsTyp = types.NewPointer(resNamed) + r.skipFile = map[*ast.File]bool{} + + for _, f := range funcs { + if r.noImportedDBSQL(f) { + // skip this + continue + } + + // skip if the function is just referenced + var isreffunc bool + + for i := 0; i < f.Signature.Results().Len(); i++ { + if types.Identical(f.Signature.Results().At(i).Type(), r.rowsTyp) { + isreffunc = true + } + } + + if isreffunc { + continue + } + + for _, b := range f.Blocks { + for i := range b.Instrs { + if r.notCheck(b, i) { + pass.Reportf(b.Instrs[i].Pos(), fmt.Sprintf("rows.Err must be checked")) + } + } + } + } + + return nil, nil +} + +func (r *runner) notCheck(b *ssa.BasicBlock, i int) bool { + call, ok := r.getReqCall(b.Instrs[i]) + if !ok { + return false + } + + for _, cRef := range *call.Referrers() { + val, ok := r.getResVal(cRef) + if !ok { + continue + } + + if len(*val.Referrers()) == 0 { + return true + } + + resRefs := *val.Referrers() + for _, resRef := range resRefs { + switch resRef := resRef.(type) { + case *ssa.Store: // Call in Closure function + if len(*resRef.Addr.Referrers()) == 0 { + return true + } + + for _, aref := range *resRef.Addr.Referrers() { + if c, ok := aref.(*ssa.MakeClosure); ok { + f := c.Fn.(*ssa.Function) + if r.noImportedDBSQL(f) { + // skip this + return false + } + called := r.isClosureCalled(c) + + return r.calledInFunc(f, called) + } + + } + case *ssa.Call: // Indirect function call + if r.isCloseCall(resRef) { + return false + } + if f, ok := resRef.Call.Value.(*ssa.Function); ok { + for _, b := range f.Blocks { + for i := range b.Instrs { + return r.notCheck(b, i) + } + } + } + case *ssa.FieldAddr: + for _, bRef := range *resRef.Referrers() { + bOp, ok := r.getBodyOp(bRef) + if !ok { + continue + } + + for _, ccall := range *bOp.Referrers() { + if r.isCloseCall(ccall) { + return false + } + } + } + } + } + } + + return true +} + +func (r *runner) getReqCall(instr ssa.Instruction) (*ssa.Call, bool) { + call, ok := instr.(*ssa.Call) + if !ok { + return nil, false + } + + res := call.Call.Signature().Results() + flag := false + + for i := 0; i < res.Len(); i++ { + flag = flag || types.Identical(res.At(i).Type(), r.rowsTyp) + } + + if !flag { + return nil, false + } + + return call, true +} + +func (r *runner) getResVal(instr ssa.Instruction) (ssa.Value, bool) { + switch instr := instr.(type) { + case *ssa.Call: + if len(instr.Call.Args) == 1 && types.Identical(instr.Call.Args[0].Type(), r.rowsTyp) { + return instr.Call.Args[0], true + } + case ssa.Value: + if types.Identical(instr.Type(), r.rowsTyp) { + return instr, true + } + } + + return nil, false +} + +func (r *runner) getBodyOp(instr ssa.Instruction) (*ssa.UnOp, bool) { + op, ok := instr.(*ssa.UnOp) + if !ok { + return nil, false + } + // fix: try to check type + // if op.Type() != r.rowsObj.Type() { + // return nil, false + // } + return op, true +} + +func (r *runner) isCloseCall(ccall ssa.Instruction) bool { + switch ccall := ccall.(type) { + case *ssa.Defer: + if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod { + return true + } + case *ssa.Call: + if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod { + return true + } + } + + return false +} + +func (r *runner) isClosureCalled(c *ssa.MakeClosure) bool { + for _, ref := range *c.Referrers() { + switch ref.(type) { + case *ssa.Call, *ssa.Defer: + return true + } + } + + return false +} + +func (r *runner) noImportedDBSQL(f *ssa.Function) (ret bool) { + obj := f.Object() + if obj == nil { + return false + } + + file := analysisutil.File(r.pass, obj.Pos()) + if file == nil { + return false + } + + if skip, has := r.skipFile[file]; has { + return skip + } + defer func() { + r.skipFile[file] = ret + }() + + for _, impt := range file.Imports { + path, err := strconv.Unquote(impt.Path.Value) + if err != nil { + continue + } + path = analysisutil.RemoveVendor(path) + for _, pkg := range r.sqlPkgs { + if pkg == path { + return false + } + } + } + + return true +} + +func (r *runner) calledInFunc(f *ssa.Function, called bool) bool { + for _, b := range f.Blocks { + for i, instr := range b.Instrs { + switch instr := instr.(type) { + case *ssa.UnOp: + for _, ref := range *instr.Referrers() { + if v, ok := ref.(ssa.Value); ok { + if vCall, ok := v.(*ssa.Call); ok { + if vCall.Call.Value != nil && vCall.Call.Value.Name() == errMethod { + if called { + return false + } + } + } + } + } + default: + if r.notCheck(b, i) || !called { + return true + } + } + } + } + return true +} + +// isNamedType reports whether t is the named type path.name. +func isNamedType(t types.Type, path, name string) bool { + n, ok := t.(*types.Named) + if !ok { + return false + } + obj := n.Obj() + return obj.Name() == name && obj.Pkg() != nil && obj.Pkg().Path() == path +} diff --git a/vendor/github.com/jirfag/go-printf-func-name/pkg/analyzer/analyzer.go b/vendor/github.com/jirfag/go-printf-func-name/pkg/analyzer/analyzer.go new file mode 100644 index 000000000..7937dd433 --- /dev/null +++ b/vendor/github.com/jirfag/go-printf-func-name/pkg/analyzer/analyzer.go @@ -0,0 +1,74 @@ +package analyzer + +import ( + "go/ast" + "strings" + + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" + + "golang.org/x/tools/go/analysis" +) + +var Analyzer = &analysis.Analyzer{ + Name: "goprintffuncname", + Doc: "Checks that printf-like functions are named with `f` at the end.", + Run: run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, +} + +func run(pass *analysis.Pass) (interface{}, error) { + inspector := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + nodeFilter := []ast.Node{ + (*ast.FuncDecl)(nil), + } + + inspector.Preorder(nodeFilter, func(node ast.Node) { + funcDecl := node.(*ast.FuncDecl) + + if res := funcDecl.Type.Results; res != nil && len(res.List) != 0 { + return + } + + params := funcDecl.Type.Params.List + if len(params) < 2 { // [0] must be format (string), [1] must be args (...interface{}) + return + } + + formatParamType, ok := params[len(params)-2].Type.(*ast.Ident) + if !ok { // first param type isn't identificator so it can't be of type "string" + return + } + + if formatParamType.Name != "string" { // first param (format) type is not string + return + } + + if formatParamNames := params[len(params)-2].Names; len(formatParamNames) == 0 || formatParamNames[len(formatParamNames)-1].Name != "format" { + return + } + + argsParamType, ok := params[len(params)-1].Type.(*ast.Ellipsis) + if !ok { // args are not ellipsis (...args) + return + } + + elementType, ok := argsParamType.Elt.(*ast.InterfaceType) + if !ok { // args are not of interface type, but we need interface{} + return + } + + if elementType.Methods != nil && len(elementType.Methods.List) != 0 { + return // has >= 1 method in interface, but we need an empty interface "interface{}" + } + + if strings.HasSuffix(funcDecl.Name.Name, "f") { + return + } + + pass.Reportf(node.Pos(), "printf-like formatting function '%s' should be named '%sf'", + funcDecl.Name.Name, funcDecl.Name.Name) + }) + + return nil, nil +} diff --git a/vendor/github.com/kisielk/gotool/.travis.yml b/vendor/github.com/kisielk/gotool/.travis.yml new file mode 100644 index 000000000..d1784e1e2 --- /dev/null +++ b/vendor/github.com/kisielk/gotool/.travis.yml @@ -0,0 +1,23 @@ +sudo: false +language: go +go: + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - 1.7 + - 1.8 + - 1.9 + - master +matrix: + allow_failures: + - go: master + fast_finish: true +install: + - # Skip. +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d .) + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/kisielk/gotool/LEGAL b/vendor/github.com/kisielk/gotool/LEGAL new file mode 100644 index 000000000..72b859cd6 --- /dev/null +++ b/vendor/github.com/kisielk/gotool/LEGAL @@ -0,0 +1,32 @@ +All the files in this distribution are covered under either the MIT +license (see the file LICENSE) except some files mentioned below. + +match.go, match_test.go: + + Copyright (c) 2009 The Go Authors. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/kisielk/gotool/LICENSE b/vendor/github.com/kisielk/gotool/LICENSE new file mode 100644 index 000000000..1cbf651e2 --- /dev/null +++ b/vendor/github.com/kisielk/gotool/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2013 Kamil Kisiel + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/kisielk/gotool/README.md b/vendor/github.com/kisielk/gotool/README.md new file mode 100644 index 000000000..6e4e92b2f --- /dev/null +++ b/vendor/github.com/kisielk/gotool/README.md @@ -0,0 +1,6 @@ +gotool +====== +[![GoDoc](https://godoc.org/github.com/kisielk/gotool?status.svg)](https://godoc.org/github.com/kisielk/gotool) +[![Build Status](https://travis-ci.org/kisielk/gotool.svg?branch=master)](https://travis-ci.org/kisielk/gotool) + +Package gotool contains utility functions used to implement the standard "cmd/go" tool, provided as a convenience to developers who want to write tools with similar semantics. diff --git a/vendor/github.com/kisielk/gotool/go.mod b/vendor/github.com/kisielk/gotool/go.mod new file mode 100644 index 000000000..503b37c6f --- /dev/null +++ b/vendor/github.com/kisielk/gotool/go.mod @@ -0,0 +1 @@ +module "github.com/kisielk/gotool" diff --git a/vendor/github.com/kisielk/gotool/go13.go b/vendor/github.com/kisielk/gotool/go13.go new file mode 100644 index 000000000..2dd9b3fdf --- /dev/null +++ b/vendor/github.com/kisielk/gotool/go13.go @@ -0,0 +1,15 @@ +// +build !go1.4 + +package gotool + +import ( + "go/build" + "path/filepath" + "runtime" +) + +var gorootSrc = filepath.Join(runtime.GOROOT(), "src", "pkg") + +func shouldIgnoreImport(p *build.Package) bool { + return true +} diff --git a/vendor/github.com/kisielk/gotool/go14-15.go b/vendor/github.com/kisielk/gotool/go14-15.go new file mode 100644 index 000000000..aa99a3227 --- /dev/null +++ b/vendor/github.com/kisielk/gotool/go14-15.go @@ -0,0 +1,15 @@ +// +build go1.4,!go1.6 + +package gotool + +import ( + "go/build" + "path/filepath" + "runtime" +) + +var gorootSrc = filepath.Join(runtime.GOROOT(), "src") + +func shouldIgnoreImport(p *build.Package) bool { + return true +} diff --git a/vendor/github.com/kisielk/gotool/go16-18.go b/vendor/github.com/kisielk/gotool/go16-18.go new file mode 100644 index 000000000..f25cec14a --- /dev/null +++ b/vendor/github.com/kisielk/gotool/go16-18.go @@ -0,0 +1,15 @@ +// +build go1.6,!go1.9 + +package gotool + +import ( + "go/build" + "path/filepath" + "runtime" +) + +var gorootSrc = filepath.Join(runtime.GOROOT(), "src") + +func shouldIgnoreImport(p *build.Package) bool { + return p == nil || len(p.InvalidGoFiles) == 0 +} diff --git a/vendor/github.com/kisielk/gotool/internal/load/path.go b/vendor/github.com/kisielk/gotool/internal/load/path.go new file mode 100644 index 000000000..74e15b9d3 --- /dev/null +++ b/vendor/github.com/kisielk/gotool/internal/load/path.go @@ -0,0 +1,27 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +package load + +import ( + "strings" +) + +// hasPathPrefix reports whether the path s begins with the +// elements in prefix. +func hasPathPrefix(s, prefix string) bool { + switch { + default: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == '/' { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == '/' && s[:len(prefix)] == prefix + } +} diff --git a/vendor/github.com/kisielk/gotool/internal/load/pkg.go b/vendor/github.com/kisielk/gotool/internal/load/pkg.go new file mode 100644 index 000000000..b937ede75 --- /dev/null +++ b/vendor/github.com/kisielk/gotool/internal/load/pkg.go @@ -0,0 +1,25 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +// Package load loads packages. +package load + +import ( + "strings" +) + +// isStandardImportPath reports whether $GOROOT/src/path should be considered +// part of the standard distribution. For historical reasons we allow people to add +// their own code to $GOROOT instead of using $GOPATH, but we assume that +// code will start with a domain name (dot in the first element). +func isStandardImportPath(path string) bool { + i := strings.Index(path, "/") + if i < 0 { + i = len(path) + } + elem := path[:i] + return !strings.Contains(elem, ".") +} diff --git a/vendor/github.com/kisielk/gotool/internal/load/search.go b/vendor/github.com/kisielk/gotool/internal/load/search.go new file mode 100644 index 000000000..17ed62dda --- /dev/null +++ b/vendor/github.com/kisielk/gotool/internal/load/search.go @@ -0,0 +1,354 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +package load + +import ( + "fmt" + "go/build" + "log" + "os" + "path" + "path/filepath" + "regexp" + "strings" +) + +// Context specifies values for operation of ImportPaths that would +// otherwise come from cmd/go/internal/cfg package. +// +// This is a construct added for gotool purposes and doesn't have +// an equivalent upstream in cmd/go. +type Context struct { + // BuildContext is the build context to use. + BuildContext build.Context + + // GOROOTsrc is the location of the src directory in GOROOT. + // At this time, it's used only in MatchPackages to skip + // GOOROOT/src entry from BuildContext.SrcDirs output. + GOROOTsrc string +} + +// allPackages returns all the packages that can be found +// under the $GOPATH directories and $GOROOT matching pattern. +// The pattern is either "all" (all packages), "std" (standard packages), +// "cmd" (standard commands), or a path including "...". +func (c *Context) allPackages(pattern string) []string { + pkgs := c.MatchPackages(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +// allPackagesInFS is like allPackages but is passed a pattern +// beginning ./ or ../, meaning it should scan the tree rooted +// at the given directory. There are ... in the pattern too. +func (c *Context) allPackagesInFS(pattern string) []string { + pkgs := c.MatchPackagesInFS(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +// MatchPackages returns a list of package paths matching pattern +// (see go help packages for pattern syntax). +func (c *Context) MatchPackages(pattern string) []string { + match := func(string) bool { return true } + treeCanMatch := func(string) bool { return true } + if !IsMetaPackage(pattern) { + match = matchPattern(pattern) + treeCanMatch = treeCanMatchPattern(pattern) + } + + have := map[string]bool{ + "builtin": true, // ignore pseudo-package that exists only for documentation + } + if !c.BuildContext.CgoEnabled { + have["runtime/cgo"] = true // ignore during walk + } + var pkgs []string + + for _, src := range c.BuildContext.SrcDirs() { + if (pattern == "std" || pattern == "cmd") && src != c.GOROOTsrc { + continue + } + src = filepath.Clean(src) + string(filepath.Separator) + root := src + if pattern == "cmd" { + root += "cmd" + string(filepath.Separator) + } + filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { + if err != nil || path == src { + return nil + } + + want := true + // Avoid .foo, _foo, and testdata directory trees. + _, elem := filepath.Split(path) + if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { + want = false + } + + name := filepath.ToSlash(path[len(src):]) + if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") { + // The name "std" is only the standard library. + // If the name is cmd, it's the root of the command tree. + want = false + } + if !treeCanMatch(name) { + want = false + } + + if !fi.IsDir() { + if fi.Mode()&os.ModeSymlink != 0 && want { + if target, err := os.Stat(path); err == nil && target.IsDir() { + fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) + } + } + return nil + } + if !want { + return filepath.SkipDir + } + + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + pkg, err := c.BuildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); noGo { + return nil + } + } + + // If we are expanding "cmd", skip main + // packages under cmd/vendor. At least as of + // March, 2017, there is one there for the + // vendored pprof tool. + if pattern == "cmd" && strings.HasPrefix(pkg.ImportPath, "cmd/vendor") && pkg.Name == "main" { + return nil + } + + pkgs = append(pkgs, name) + return nil + }) + } + return pkgs +} + +// MatchPackagesInFS returns a list of package paths matching pattern, +// which must begin with ./ or ../ +// (see go help packages for pattern syntax). +func (c *Context) MatchPackagesInFS(pattern string) []string { + // Find directory to begin the scan. + // Could be smarter but this one optimization + // is enough for now, since ... is usually at the + // end of a path. + i := strings.Index(pattern, "...") + dir, _ := path.Split(pattern[:i]) + + // pattern begins with ./ or ../. + // path.Clean will discard the ./ but not the ../. + // We need to preserve the ./ for pattern matching + // and in the returned import paths. + prefix := "" + if strings.HasPrefix(pattern, "./") { + prefix = "./" + } + match := matchPattern(pattern) + + var pkgs []string + filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() { + return nil + } + if path == dir { + // filepath.Walk starts at dir and recurses. For the recursive case, + // the path is the result of filepath.Join, which calls filepath.Clean. + // The initial case is not Cleaned, though, so we do this explicitly. + // + // This converts a path like "./io/" to "io". Without this step, running + // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io + // package, because prepending the prefix "./" to the unclean path would + // result in "././io", and match("././io") returns false. + path = filepath.Clean(path) + } + + // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". + _, elem := filepath.Split(path) + dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." + if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { + return filepath.SkipDir + } + + name := prefix + filepath.ToSlash(path) + if !match(name) { + return nil + } + + // We keep the directory if we can import it, or if we can't import it + // due to invalid Go source files. This means that directories containing + // parse errors will be built (and fail) instead of being silently skipped + // as not matching the pattern. Go 1.5 and earlier skipped, but that + // behavior means people miss serious mistakes. + // See golang.org/issue/11407. + if p, err := c.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + pkgs = append(pkgs, name) + return nil + }) + return pkgs +} + +// treeCanMatchPattern(pattern)(name) reports whether +// name or children of name can possibly match pattern. +// Pattern is the same limited glob accepted by matchPattern. +func treeCanMatchPattern(pattern string) func(name string) bool { + wildCard := false + if i := strings.Index(pattern, "..."); i >= 0 { + wildCard = true + pattern = pattern[:i] + } + return func(name string) bool { + return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || + wildCard && strings.HasPrefix(name, pattern) + } +} + +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +// Unfortunately, there are two special cases. Quoting "go help packages": +// +// First, /... at the end of the pattern can match an empty string, +// so that net/... matches both net and packages in its subdirectories, like net/http. +// Second, any slash-separted pattern element containing a wildcard never +// participates in a match of the "vendor" element in the path of a vendored +// package, so that ./... does not match packages in subdirectories of +// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. +// Note, however, that a directory named vendor that itself contains code +// is not a vendored package: cmd/vendor would be a command named vendor, +// and the pattern cmd/... matches it. +func matchPattern(pattern string) func(name string) bool { + // Convert pattern to regular expression. + // The strategy for the trailing /... is to nest it in an explicit ? expression. + // The strategy for the vendor exclusion is to change the unmatchable + // vendor strings to a disallowed code point (vendorChar) and to use + // "(anything but that codepoint)*" as the implementation of the ... wildcard. + // This is a bit complicated but the obvious alternative, + // namely a hand-written search like in most shell glob matchers, + // is too easy to make accidentally exponential. + // Using package regexp guarantees linear-time matching. + + const vendorChar = "\x00" + + if strings.Contains(pattern, vendorChar) { + return func(name string) bool { return false } + } + + re := regexp.QuoteMeta(pattern) + re = replaceVendor(re, vendorChar) + switch { + case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`): + re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)` + case re == vendorChar+`/\.\.\.`: + re = `(/vendor|/` + vendorChar + `/\.\.\.)` + case strings.HasSuffix(re, `/\.\.\.`): + re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?` + } + re = strings.Replace(re, `\.\.\.`, `[^`+vendorChar+`]*`, -1) + + reg := regexp.MustCompile(`^` + re + `$`) + + return func(name string) bool { + if strings.Contains(name, vendorChar) { + return false + } + return reg.MatchString(replaceVendor(name, vendorChar)) + } +} + +// replaceVendor returns the result of replacing +// non-trailing vendor path elements in x with repl. +func replaceVendor(x, repl string) string { + if !strings.Contains(x, "vendor") { + return x + } + elem := strings.Split(x, "/") + for i := 0; i < len(elem)-1; i++ { + if elem[i] == "vendor" { + elem[i] = repl + } + } + return strings.Join(elem, "/") +} + +// ImportPaths returns the import paths to use for the given command line. +func (c *Context) ImportPaths(args []string) []string { + args = c.ImportPathsNoDotExpansion(args) + var out []string + for _, a := range args { + if strings.Contains(a, "...") { + if build.IsLocalImport(a) { + out = append(out, c.allPackagesInFS(a)...) + } else { + out = append(out, c.allPackages(a)...) + } + continue + } + out = append(out, a) + } + return out +} + +// ImportPathsNoDotExpansion returns the import paths to use for the given +// command line, but it does no ... expansion. +func (c *Context) ImportPathsNoDotExpansion(args []string) []string { + if len(args) == 0 { + return []string{"."} + } + var out []string + for _, a := range args { + // Arguments are supposed to be import paths, but + // as a courtesy to Windows developers, rewrite \ to / + // in command-line arguments. Handles .\... and so on. + if filepath.Separator == '\\' { + a = strings.Replace(a, `\`, `/`, -1) + } + + // Put argument in canonical form, but preserve leading ./. + if strings.HasPrefix(a, "./") { + a = "./" + path.Clean(a) + if a == "./." { + a = "." + } + } else { + a = path.Clean(a) + } + if IsMetaPackage(a) { + out = append(out, c.allPackages(a)...) + continue + } + out = append(out, a) + } + return out +} + +// IsMetaPackage checks if name is a reserved package name that expands to multiple packages. +func IsMetaPackage(name string) bool { + return name == "std" || name == "cmd" || name == "all" +} diff --git a/vendor/github.com/kisielk/gotool/match.go b/vendor/github.com/kisielk/gotool/match.go new file mode 100644 index 000000000..4dbdbff47 --- /dev/null +++ b/vendor/github.com/kisielk/gotool/match.go @@ -0,0 +1,56 @@ +// Copyright (c) 2009 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build go1.9 + +package gotool + +import ( + "path/filepath" + + "github.com/kisielk/gotool/internal/load" +) + +// importPaths returns the import paths to use for the given command line. +func (c *Context) importPaths(args []string) []string { + lctx := load.Context{ + BuildContext: c.BuildContext, + GOROOTsrc: c.joinPath(c.BuildContext.GOROOT, "src"), + } + return lctx.ImportPaths(args) +} + +// joinPath calls c.BuildContext.JoinPath (if not nil) or else filepath.Join. +// +// It's a copy of the unexported build.Context.joinPath helper. +func (c *Context) joinPath(elem ...string) string { + if f := c.BuildContext.JoinPath; f != nil { + return f(elem...) + } + return filepath.Join(elem...) +} diff --git a/vendor/github.com/kisielk/gotool/match18.go b/vendor/github.com/kisielk/gotool/match18.go new file mode 100644 index 000000000..6d6b1368c --- /dev/null +++ b/vendor/github.com/kisielk/gotool/match18.go @@ -0,0 +1,317 @@ +// Copyright (c) 2009 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build !go1.9 + +package gotool + +import ( + "fmt" + "go/build" + "log" + "os" + "path" + "path/filepath" + "regexp" + "strings" +) + +// This file contains code from the Go distribution. + +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +func matchPattern(pattern string) func(name string) bool { + re := regexp.QuoteMeta(pattern) + re = strings.Replace(re, `\.\.\.`, `.*`, -1) + // Special case: foo/... matches foo too. + if strings.HasSuffix(re, `/.*`) { + re = re[:len(re)-len(`/.*`)] + `(/.*)?` + } + reg := regexp.MustCompile(`^` + re + `$`) + return reg.MatchString +} + +// matchPackages returns a list of package paths matching pattern +// (see go help packages for pattern syntax). +func (c *Context) matchPackages(pattern string) []string { + match := func(string) bool { return true } + treeCanMatch := func(string) bool { return true } + if !isMetaPackage(pattern) { + match = matchPattern(pattern) + treeCanMatch = treeCanMatchPattern(pattern) + } + + have := map[string]bool{ + "builtin": true, // ignore pseudo-package that exists only for documentation + } + if !c.BuildContext.CgoEnabled { + have["runtime/cgo"] = true // ignore during walk + } + var pkgs []string + + for _, src := range c.BuildContext.SrcDirs() { + if (pattern == "std" || pattern == "cmd") && src != gorootSrc { + continue + } + src = filepath.Clean(src) + string(filepath.Separator) + root := src + if pattern == "cmd" { + root += "cmd" + string(filepath.Separator) + } + filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() || path == src { + return nil + } + + // Avoid .foo, _foo, and testdata directory trees. + _, elem := filepath.Split(path) + if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { + return filepath.SkipDir + } + + name := filepath.ToSlash(path[len(src):]) + if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") { + // The name "std" is only the standard library. + // If the name is cmd, it's the root of the command tree. + return filepath.SkipDir + } + if !treeCanMatch(name) { + return filepath.SkipDir + } + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + _, err = c.BuildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); noGo { + return nil + } + } + pkgs = append(pkgs, name) + return nil + }) + } + return pkgs +} + +// importPathsNoDotExpansion returns the import paths to use for the given +// command line, but it does no ... expansion. +func (c *Context) importPathsNoDotExpansion(args []string) []string { + if len(args) == 0 { + return []string{"."} + } + var out []string + for _, a := range args { + // Arguments are supposed to be import paths, but + // as a courtesy to Windows developers, rewrite \ to / + // in command-line arguments. Handles .\... and so on. + if filepath.Separator == '\\' { + a = strings.Replace(a, `\`, `/`, -1) + } + + // Put argument in canonical form, but preserve leading ./. + if strings.HasPrefix(a, "./") { + a = "./" + path.Clean(a) + if a == "./." { + a = "." + } + } else { + a = path.Clean(a) + } + if isMetaPackage(a) { + out = append(out, c.allPackages(a)...) + continue + } + out = append(out, a) + } + return out +} + +// importPaths returns the import paths to use for the given command line. +func (c *Context) importPaths(args []string) []string { + args = c.importPathsNoDotExpansion(args) + var out []string + for _, a := range args { + if strings.Contains(a, "...") { + if build.IsLocalImport(a) { + out = append(out, c.allPackagesInFS(a)...) + } else { + out = append(out, c.allPackages(a)...) + } + continue + } + out = append(out, a) + } + return out +} + +// allPackages returns all the packages that can be found +// under the $GOPATH directories and $GOROOT matching pattern. +// The pattern is either "all" (all packages), "std" (standard packages), +// "cmd" (standard commands), or a path including "...". +func (c *Context) allPackages(pattern string) []string { + pkgs := c.matchPackages(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +// allPackagesInFS is like allPackages but is passed a pattern +// beginning ./ or ../, meaning it should scan the tree rooted +// at the given directory. There are ... in the pattern too. +func (c *Context) allPackagesInFS(pattern string) []string { + pkgs := c.matchPackagesInFS(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +// matchPackagesInFS returns a list of package paths matching pattern, +// which must begin with ./ or ../ +// (see go help packages for pattern syntax). +func (c *Context) matchPackagesInFS(pattern string) []string { + // Find directory to begin the scan. + // Could be smarter but this one optimization + // is enough for now, since ... is usually at the + // end of a path. + i := strings.Index(pattern, "...") + dir, _ := path.Split(pattern[:i]) + + // pattern begins with ./ or ../. + // path.Clean will discard the ./ but not the ../. + // We need to preserve the ./ for pattern matching + // and in the returned import paths. + prefix := "" + if strings.HasPrefix(pattern, "./") { + prefix = "./" + } + match := matchPattern(pattern) + + var pkgs []string + filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() { + return nil + } + if path == dir { + // filepath.Walk starts at dir and recurses. For the recursive case, + // the path is the result of filepath.Join, which calls filepath.Clean. + // The initial case is not Cleaned, though, so we do this explicitly. + // + // This converts a path like "./io/" to "io". Without this step, running + // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io + // package, because prepending the prefix "./" to the unclean path would + // result in "././io", and match("././io") returns false. + path = filepath.Clean(path) + } + + // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". + _, elem := filepath.Split(path) + dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." + if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { + return filepath.SkipDir + } + + name := prefix + filepath.ToSlash(path) + if !match(name) { + return nil + } + + // We keep the directory if we can import it, or if we can't import it + // due to invalid Go source files. This means that directories containing + // parse errors will be built (and fail) instead of being silently skipped + // as not matching the pattern. Go 1.5 and earlier skipped, but that + // behavior means people miss serious mistakes. + // See golang.org/issue/11407. + if p, err := c.BuildContext.ImportDir(path, 0); err != nil && shouldIgnoreImport(p) { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + pkgs = append(pkgs, name) + return nil + }) + return pkgs +} + +// isMetaPackage checks if name is a reserved package name that expands to multiple packages. +func isMetaPackage(name string) bool { + return name == "std" || name == "cmd" || name == "all" +} + +// isStandardImportPath reports whether $GOROOT/src/path should be considered +// part of the standard distribution. For historical reasons we allow people to add +// their own code to $GOROOT instead of using $GOPATH, but we assume that +// code will start with a domain name (dot in the first element). +func isStandardImportPath(path string) bool { + i := strings.Index(path, "/") + if i < 0 { + i = len(path) + } + elem := path[:i] + return !strings.Contains(elem, ".") +} + +// hasPathPrefix reports whether the path s begins with the +// elements in prefix. +func hasPathPrefix(s, prefix string) bool { + switch { + default: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == '/' { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == '/' && s[:len(prefix)] == prefix + } +} + +// treeCanMatchPattern(pattern)(name) reports whether +// name or children of name can possibly match pattern. +// Pattern is the same limited glob accepted by matchPattern. +func treeCanMatchPattern(pattern string) func(name string) bool { + wildCard := false + if i := strings.Index(pattern, "..."); i >= 0 { + wildCard = true + pattern = pattern[:i] + } + return func(name string) bool { + return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || + wildCard && strings.HasPrefix(name, pattern) + } +} diff --git a/vendor/github.com/kisielk/gotool/tool.go b/vendor/github.com/kisielk/gotool/tool.go new file mode 100644 index 000000000..c7409e11e --- /dev/null +++ b/vendor/github.com/kisielk/gotool/tool.go @@ -0,0 +1,48 @@ +// Package gotool contains utility functions used to implement the standard +// "cmd/go" tool, provided as a convenience to developers who want to write +// tools with similar semantics. +package gotool + +import "go/build" + +// Export functions here to make it easier to keep the implementations up to date with upstream. + +// DefaultContext is the default context that uses build.Default. +var DefaultContext = Context{ + BuildContext: build.Default, +} + +// A Context specifies the supporting context. +type Context struct { + // BuildContext is the build.Context that is used when computing import paths. + BuildContext build.Context +} + +// ImportPaths returns the import paths to use for the given command line. +// +// The path "all" is expanded to all packages in $GOPATH and $GOROOT. +// The path "std" is expanded to all packages in the Go standard library. +// The path "cmd" is expanded to all Go standard commands. +// The string "..." is treated as a wildcard within a path. +// When matching recursively, directories are ignored if they are prefixed with +// a dot or an underscore (such as ".foo" or "_foo"), or are named "testdata". +// Relative import paths are not converted to full import paths. +// If args is empty, a single element "." is returned. +func (c *Context) ImportPaths(args []string) []string { + return c.importPaths(args) +} + +// ImportPaths returns the import paths to use for the given command line +// using default context. +// +// The path "all" is expanded to all packages in $GOPATH and $GOROOT. +// The path "std" is expanded to all packages in the Go standard library. +// The path "cmd" is expanded to all Go standard commands. +// The string "..." is treated as a wildcard within a path. +// When matching recursively, directories are ignored if they are prefixed with +// a dot or an underscore (such as ".foo" or "_foo"), or are named "testdata". +// Relative import paths are not converted to full import paths. +// If args is empty, a single element "." is returned. +func ImportPaths(args []string) []string { + return DefaultContext.importPaths(args) +} diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/LICENSE b/vendor/github.com/konsorten/go-windows-terminal-sequences/LICENSE new file mode 100644 index 000000000..14127cd83 --- /dev/null +++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/LICENSE @@ -0,0 +1,9 @@ +(The MIT License) + +Copyright (c) 2017 marvin + konsorten GmbH (open-source@konsorten.de) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md new file mode 100644 index 000000000..949b77e30 --- /dev/null +++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md @@ -0,0 +1,40 @@ +# Windows Terminal Sequences + +This library allow for enabling Windows terminal color support for Go. + +See [Console Virtual Terminal Sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences) for details. + +## Usage + +```go +import ( + "syscall" + + sequences "github.com/konsorten/go-windows-terminal-sequences" +) + +func main() { + sequences.EnableVirtualTerminalProcessing(syscall.Stdout, true) +} + +``` + +## Authors + +The tool is sponsored by the [marvin + konsorten GmbH](http://www.konsorten.de). + +We thank all the authors who provided code to this library: + +* Felix Kollmann + +## License + +(The MIT License) + +Copyright (c) 2018 marvin + konsorten GmbH (open-source@konsorten.de) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod b/vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod new file mode 100644 index 000000000..716c61312 --- /dev/null +++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod @@ -0,0 +1 @@ +module github.com/konsorten/go-windows-terminal-sequences diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go new file mode 100644 index 000000000..ef18d8f97 --- /dev/null +++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go @@ -0,0 +1,36 @@ +// +build windows + +package sequences + +import ( + "syscall" + "unsafe" +) + +var ( + kernel32Dll *syscall.LazyDLL = syscall.NewLazyDLL("Kernel32.dll") + setConsoleMode *syscall.LazyProc = kernel32Dll.NewProc("SetConsoleMode") +) + +func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error { + const ENABLE_VIRTUAL_TERMINAL_PROCESSING uint32 = 0x4 + + var mode uint32 + err := syscall.GetConsoleMode(syscall.Stdout, &mode) + if err != nil { + return err + } + + if enable { + mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING + } else { + mode &^= ENABLE_VIRTUAL_TERMINAL_PROCESSING + } + + ret, _, err := setConsoleMode.Call(uintptr(unsafe.Pointer(stream)), uintptr(mode)) + if ret == 0 { + return err + } + + return nil +} diff --git a/vendor/github.com/magiconair/properties/.gitignore b/vendor/github.com/magiconair/properties/.gitignore new file mode 100644 index 000000000..e7081ff52 --- /dev/null +++ b/vendor/github.com/magiconair/properties/.gitignore @@ -0,0 +1,6 @@ +*.sublime-project +*.sublime-workspace +*.un~ +*.swp +.idea/ +*.iml diff --git a/vendor/github.com/magiconair/properties/.travis.yml b/vendor/github.com/magiconair/properties/.travis.yml new file mode 100644 index 000000000..f07376f9c --- /dev/null +++ b/vendor/github.com/magiconair/properties/.travis.yml @@ -0,0 +1,12 @@ +language: go +go: + - 1.4.x + - 1.5.x + - 1.6.x + - 1.7.x + - 1.8.x + - 1.9.x + - "1.10.x" + - "1.11.x" + - "1.12.x" + - tip diff --git a/vendor/github.com/magiconair/properties/CHANGELOG.md b/vendor/github.com/magiconair/properties/CHANGELOG.md new file mode 100644 index 000000000..176626a15 --- /dev/null +++ b/vendor/github.com/magiconair/properties/CHANGELOG.md @@ -0,0 +1,139 @@ +## Changelog + +### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019 + + * [PR #26](https://github.com/magiconair/properties/pull/35): Close body always after request + + This patch ensures that in `LoadURL` the response body is always closed. + + Thanks to [@liubog2008](https://github.com/liubog2008) for the patch. + +### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018 + + * [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading + + This adds the option to disable property expansion during loading. + + Thanks to [@kmala](https://github.com/kmala) for the patch. + +### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018 + + * [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases. + + See PR for an example. + + Thanks to [@yobert](https://github.com/yobert) for the fix. + +### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018 + + * [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value + + Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail + with a `circular reference error`. + + Thanks to [@yobert](https://github.com/yobert) for the fix. + +### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017 + + * [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces + + * [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled + + Thanks to [@mgurov](https://github.com/mgurov) for the fix. + +### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017 + + * [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically + * [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map + +### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017 + + * [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency + * [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc) + +### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017 + + * [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER` + * [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs + * [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy + * [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function + +### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016 + + * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL. + * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string. + * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe) + +### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015 + + * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags. + +### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015 + + * Vendored in gopkg.in/check.v1 + +### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015 + + * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs) + +### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015 + + * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references. + +### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015 + + * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) + +### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015 + + * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty + * Add clickable links to README + +### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014 + + * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with + [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration). + +### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014 + + * Added support for single and multi-line comments (reading, writing and updating) + * The order of keys is now preserved + * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry + * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method + * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1) + +### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014 + + * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one + +### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014 + + * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string + +### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014 + + * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys + * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties + +### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014 + +* Added support for time.Duration +* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom) +* Changed default of MustXXX() failure from panic to log.Fatal + +### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014 + +* Added MustGet... functions +* Added support for int and uint with range checks on 32 bit platforms + +### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014 + +* Renamed from goproperties to properties +* Added support for expansion of environment vars in + filenames and value expressions +* Fixed bug where value expressions were not at the + start of the string + +### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014 + +* Initial release diff --git a/vendor/github.com/magiconair/properties/LICENSE b/vendor/github.com/magiconair/properties/LICENSE new file mode 100644 index 000000000..b387087c5 --- /dev/null +++ b/vendor/github.com/magiconair/properties/LICENSE @@ -0,0 +1,25 @@ +goproperties - properties file decoder for Go + +Copyright (c) 2013-2018 - Frank Schroeder + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/magiconair/properties/README.md b/vendor/github.com/magiconair/properties/README.md new file mode 100644 index 000000000..42ed5c37c --- /dev/null +++ b/vendor/github.com/magiconair/properties/README.md @@ -0,0 +1,129 @@ +[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases) +[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties) +[![CircleCI Status](https://img.shields.io/circleci/project/github/magiconair/properties.svg?label=circle+ci&style=flat-square)](https://circleci.com/gh/magiconair/properties) +[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE) +[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) + +# Overview + +#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why. + +properties is a Go library for reading and writing properties files. + +It supports reading from multiple files or URLs and Spring style recursive +property expansion of expressions like `${key}` to their corresponding value. +Value expressions can refer to other keys like in `${key}` or to environment +variables like in `${USER}`. Filenames can also contain environment variables +like in `/home/${USER}/myapp.properties`. + +Properties can be decoded into structs, maps, arrays and values through +struct tags. + +Comments and the order of keys are preserved. Comments can be modified +and can be written to the output. + +The properties library supports both ISO-8859-1 and UTF-8 encoded data. + +Starting from version 1.3.0 the behavior of the MustXXX() functions is +configurable by providing a custom `ErrorHandler` function. The default has +changed from `panic` to `log.Fatal` but this is configurable and custom +error handling functions can be provided. See the package documentation for +details. + +Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) + +## Getting Started + +```go +import ( + "flag" + "github.com/magiconair/properties" +) + +func main() { + // init from a file + p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8) + + // or multiple files + p = properties.MustLoadFiles([]string{ + "${HOME}/config.properties", + "${HOME}/config-${USER}.properties", + }, properties.UTF8, true) + + // or from a map + p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"}) + + // or from a string + p = properties.MustLoadString("key=value\nabc=def") + + // or from a URL + p = properties.MustLoadURL("http://host/path") + + // or from multiple URLs + p = properties.MustLoadURL([]string{ + "http://host/config", + "http://host/config-${USER}", + }, true) + + // or from flags + p.MustFlag(flag.CommandLine) + + // get values through getters + host := p.MustGetString("host") + port := p.GetInt("port", 8080) + + // or through Decode + type Config struct { + Host string `properties:"host"` + Port int `properties:"port,default=9000"` + Accept []string `properties:"accept,default=image/png;image;gif"` + Timeout time.Duration `properties:"timeout,default=5s"` + } + var cfg Config + if err := p.Decode(&cfg); err != nil { + log.Fatal(err) + } +} + +``` + +## Installation and Upgrade + +``` +$ go get -u github.com/magiconair/properties +``` + +## License + +2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details. + +## ToDo + +* Dump contents with passwords and secrets obscured + +## Updated Git tags + +#### 13 Feb 2018 + +I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags +and I've only recently learned that this doesn't play well with `git describe` 😞 + +I have replaced all lightweight tags with signed tags using this script which should +retain the commit date, name and email address. Please run `git pull --tags` to update them. + +Worst case you have to reclone the repo. + +```shell +#!/bin/bash +tag=$1 +echo "Updating $tag" +date=$(git show ${tag}^0 --format=%aD | head -1) +email=$(git show ${tag}^0 --format=%aE | head -1) +name=$(git show ${tag}^0 --format=%aN | head -1) +GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag} +``` + +I apologize for the inconvenience. + +Frank + diff --git a/vendor/github.com/magiconair/properties/decode.go b/vendor/github.com/magiconair/properties/decode.go new file mode 100644 index 000000000..3ebf8049c --- /dev/null +++ b/vendor/github.com/magiconair/properties/decode.go @@ -0,0 +1,289 @@ +// Copyright 2018 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "reflect" + "strconv" + "strings" + "time" +) + +// Decode assigns property values to exported fields of a struct. +// +// Decode traverses v recursively and returns an error if a value cannot be +// converted to the field type or a required value is missing for a field. +// +// The following type dependent decodings are used: +// +// String, boolean, numeric fields have the value of the property key assigned. +// The property key name is the name of the field. A different key and a default +// value can be set in the field's tag. Fields without default value are +// required. If the value cannot be converted to the field type an error is +// returned. +// +// time.Duration fields have the result of time.ParseDuration() assigned. +// +// time.Time fields have the vaule of time.Parse() assigned. The default layout +// is time.RFC3339 but can be set in the field's tag. +// +// Arrays and slices of string, boolean, numeric, time.Duration and time.Time +// fields have the value interpreted as a comma separated list of values. The +// individual values are trimmed of whitespace and empty values are ignored. A +// default value can be provided as a semicolon separated list in the field's +// tag. +// +// Struct fields are decoded recursively using the field name plus "." as +// prefix. The prefix (without dot) can be overridden in the field's tag. +// Default values are not supported in the field's tag. Specify them on the +// fields of the inner struct instead. +// +// Map fields must have a key of type string and are decoded recursively by +// using the field's name plus ".' as prefix and the next element of the key +// name as map key. The prefix (without dot) can be overridden in the field's +// tag. Default values are not supported. +// +// Examples: +// +// // Field is ignored. +// Field int `properties:"-"` +// +// // Field is assigned value of 'Field'. +// Field int +// +// // Field is assigned value of 'myName'. +// Field int `properties:"myName"` +// +// // Field is assigned value of key 'myName' and has a default +// // value 15 if the key does not exist. +// Field int `properties:"myName,default=15"` +// +// // Field is assigned value of key 'Field' and has a default +// // value 15 if the key does not exist. +// Field int `properties:",default=15"` +// +// // Field is assigned value of key 'date' and the date +// // is in format 2006-01-02 +// Field time.Time `properties:"date,layout=2006-01-02"` +// +// // Field is assigned the non-empty and whitespace trimmed +// // values of key 'Field' split by commas. +// Field []string +// +// // Field is assigned the non-empty and whitespace trimmed +// // values of key 'Field' split by commas and has a default +// // value ["a", "b", "c"] if the key does not exist. +// Field []string `properties:",default=a;b;c"` +// +// // Field is decoded recursively with "Field." as key prefix. +// Field SomeStruct +// +// // Field is decoded recursively with "myName." as key prefix. +// Field SomeStruct `properties:"myName"` +// +// // Field is decoded recursively with "Field." as key prefix +// // and the next dotted element of the key as map key. +// Field map[string]string +// +// // Field is decoded recursively with "myName." as key prefix +// // and the next dotted element of the key as map key. +// Field map[string]string `properties:"myName"` +func (p *Properties) Decode(x interface{}) error { + t, v := reflect.TypeOf(x), reflect.ValueOf(x) + if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct { + return fmt.Errorf("not a pointer to struct: %s", t) + } + if err := dec(p, "", nil, nil, v); err != nil { + return err + } + return nil +} + +func dec(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error { + t := v.Type() + + // value returns the property value for key or the default if provided. + value := func() (string, error) { + if val, ok := p.Get(key); ok { + return val, nil + } + if def != nil { + return *def, nil + } + return "", fmt.Errorf("missing required key %s", key) + } + + // conv converts a string to a value of the given type. + conv := func(s string, t reflect.Type) (val reflect.Value, err error) { + var v interface{} + + switch { + case isDuration(t): + v, err = time.ParseDuration(s) + + case isTime(t): + layout := opts["layout"] + if layout == "" { + layout = time.RFC3339 + } + v, err = time.Parse(layout, s) + + case isBool(t): + v, err = boolVal(s), nil + + case isString(t): + v, err = s, nil + + case isFloat(t): + v, err = strconv.ParseFloat(s, 64) + + case isInt(t): + v, err = strconv.ParseInt(s, 10, 64) + + case isUint(t): + v, err = strconv.ParseUint(s, 10, 64) + + default: + return reflect.Zero(t), fmt.Errorf("unsupported type %s", t) + } + if err != nil { + return reflect.Zero(t), err + } + return reflect.ValueOf(v).Convert(t), nil + } + + // keydef returns the property key and the default value based on the + // name of the struct field and the options in the tag. + keydef := func(f reflect.StructField) (string, *string, map[string]string) { + _key, _opts := parseTag(f.Tag.Get("properties")) + + var _def *string + if d, ok := _opts["default"]; ok { + _def = &d + } + if _key != "" { + return _key, _def, _opts + } + return f.Name, _def, _opts + } + + switch { + case isDuration(t) || isTime(t) || isBool(t) || isString(t) || isFloat(t) || isInt(t) || isUint(t): + s, err := value() + if err != nil { + return err + } + val, err := conv(s, t) + if err != nil { + return err + } + v.Set(val) + + case isPtr(t): + return dec(p, key, def, opts, v.Elem()) + + case isStruct(t): + for i := 0; i < v.NumField(); i++ { + fv := v.Field(i) + fk, def, opts := keydef(t.Field(i)) + if !fv.CanSet() { + return fmt.Errorf("cannot set %s", t.Field(i).Name) + } + if fk == "-" { + continue + } + if key != "" { + fk = key + "." + fk + } + if err := dec(p, fk, def, opts, fv); err != nil { + return err + } + } + return nil + + case isArray(t): + val, err := value() + if err != nil { + return err + } + vals := split(val, ";") + a := reflect.MakeSlice(t, 0, len(vals)) + for _, s := range vals { + val, err := conv(s, t.Elem()) + if err != nil { + return err + } + a = reflect.Append(a, val) + } + v.Set(a) + + case isMap(t): + valT := t.Elem() + m := reflect.MakeMap(t) + for postfix := range p.FilterStripPrefix(key + ".").m { + pp := strings.SplitN(postfix, ".", 2) + mk, mv := pp[0], reflect.New(valT) + if err := dec(p, key+"."+mk, nil, nil, mv); err != nil { + return err + } + m.SetMapIndex(reflect.ValueOf(mk), mv.Elem()) + } + v.Set(m) + + default: + return fmt.Errorf("unsupported type %s", t) + } + return nil +} + +// split splits a string on sep, trims whitespace of elements +// and omits empty elements +func split(s string, sep string) []string { + var a []string + for _, v := range strings.Split(s, sep) { + if v = strings.TrimSpace(v); v != "" { + a = append(a, v) + } + } + return a +} + +// parseTag parses a "key,k=v,k=v,..." +func parseTag(tag string) (key string, opts map[string]string) { + opts = map[string]string{} + for i, s := range strings.Split(tag, ",") { + if i == 0 { + key = s + continue + } + + pp := strings.SplitN(s, "=", 2) + if len(pp) == 1 { + opts[pp[0]] = "" + } else { + opts[pp[0]] = pp[1] + } + } + return key, opts +} + +func isArray(t reflect.Type) bool { return t.Kind() == reflect.Array || t.Kind() == reflect.Slice } +func isBool(t reflect.Type) bool { return t.Kind() == reflect.Bool } +func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) } +func isMap(t reflect.Type) bool { return t.Kind() == reflect.Map } +func isPtr(t reflect.Type) bool { return t.Kind() == reflect.Ptr } +func isString(t reflect.Type) bool { return t.Kind() == reflect.String } +func isStruct(t reflect.Type) bool { return t.Kind() == reflect.Struct } +func isTime(t reflect.Type) bool { return t == reflect.TypeOf(time.Time{}) } +func isFloat(t reflect.Type) bool { + return t.Kind() == reflect.Float32 || t.Kind() == reflect.Float64 +} +func isInt(t reflect.Type) bool { + return t.Kind() == reflect.Int || t.Kind() == reflect.Int8 || t.Kind() == reflect.Int16 || t.Kind() == reflect.Int32 || t.Kind() == reflect.Int64 +} +func isUint(t reflect.Type) bool { + return t.Kind() == reflect.Uint || t.Kind() == reflect.Uint8 || t.Kind() == reflect.Uint16 || t.Kind() == reflect.Uint32 || t.Kind() == reflect.Uint64 +} diff --git a/vendor/github.com/magiconair/properties/doc.go b/vendor/github.com/magiconair/properties/doc.go new file mode 100644 index 000000000..f8822da2b --- /dev/null +++ b/vendor/github.com/magiconair/properties/doc.go @@ -0,0 +1,156 @@ +// Copyright 2018 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package properties provides functions for reading and writing +// ISO-8859-1 and UTF-8 encoded .properties files and has +// support for recursive property expansion. +// +// Java properties files are ISO-8859-1 encoded and use Unicode +// literals for characters outside the ISO character set. Unicode +// literals can be used in UTF-8 encoded properties files but +// aren't necessary. +// +// To load a single properties file use MustLoadFile(): +// +// p := properties.MustLoadFile(filename, properties.UTF8) +// +// To load multiple properties files use MustLoadFiles() +// which loads the files in the given order and merges the +// result. Missing properties files can be ignored if the +// 'ignoreMissing' flag is set to true. +// +// Filenames can contain environment variables which are expanded +// before loading. +// +// f1 := "/etc/myapp/myapp.conf" +// f2 := "/home/${USER}/myapp.conf" +// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) +// +// All of the different key/value delimiters ' ', ':' and '=' are +// supported as well as the comment characters '!' and '#' and +// multi-line values. +// +// ! this is a comment +// # and so is this +// +// # the following expressions are equal +// key value +// key=value +// key:value +// key = value +// key : value +// key = val\ +// ue +// +// Properties stores all comments preceding a key and provides +// GetComments() and SetComments() methods to retrieve and +// update them. The convenience functions GetComment() and +// SetComment() allow access to the last comment. The +// WriteComment() method writes properties files including +// the comments and with the keys in the original order. +// This can be used for sanitizing properties files. +// +// Property expansion is recursive and circular references +// and malformed expressions are not allowed and cause an +// error. Expansion of environment variables is supported. +// +// # standard property +// key = value +// +// # property expansion: key2 = value +// key2 = ${key} +// +// # recursive expansion: key3 = value +// key3 = ${key2} +// +// # circular reference (error) +// key = ${key} +// +// # malformed expression (error) +// key = ${ke +// +// # refers to the users' home dir +// home = ${HOME} +// +// # local key takes precedence over env var: u = foo +// USER = foo +// u = ${USER} +// +// The default property expansion format is ${key} but can be +// changed by setting different pre- and postfix values on the +// Properties object. +// +// p := properties.NewProperties() +// p.Prefix = "#[" +// p.Postfix = "]#" +// +// Properties provides convenience functions for getting typed +// values with default values if the key does not exist or the +// type conversion failed. +// +// # Returns true if the value is either "1", "on", "yes" or "true" +// # Returns false for every other value and the default value if +// # the key does not exist. +// v = p.GetBool("key", false) +// +// # Returns the value if the key exists and the format conversion +// # was successful. Otherwise, the default value is returned. +// v = p.GetInt64("key", 999) +// v = p.GetUint64("key", 999) +// v = p.GetFloat64("key", 123.0) +// v = p.GetString("key", "def") +// v = p.GetDuration("key", 999) +// +// As an alternative properties may be applied with the standard +// library's flag implementation at any time. +// +// # Standard configuration +// v = flag.Int("key", 999, "help message") +// flag.Parse() +// +// # Merge p into the flag set +// p.MustFlag(flag.CommandLine) +// +// Properties provides several MustXXX() convenience functions +// which will terminate the app if an error occurs. The behavior +// of the failure is configurable and the default is to call +// log.Fatal(err). To have the MustXXX() functions panic instead +// of logging the error set a different ErrorHandler before +// you use the Properties package. +// +// properties.ErrorHandler = properties.PanicHandler +// +// # Will panic instead of logging an error +// p := properties.MustLoadFile("config.properties") +// +// You can also provide your own ErrorHandler function. The only requirement +// is that the error handler function must exit after handling the error. +// +// properties.ErrorHandler = func(err error) { +// fmt.Println(err) +// os.Exit(1) +// } +// +// # Will write to stdout and then exit +// p := properties.MustLoadFile("config.properties") +// +// Properties can also be loaded into a struct via the `Decode` +// method, e.g. +// +// type S struct { +// A string `properties:"a,default=foo"` +// D time.Duration `properties:"timeout,default=5s"` +// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"` +// } +// +// See `Decode()` method for the full documentation. +// +// The following documents provide a description of the properties +// file format. +// +// http://en.wikipedia.org/wiki/.properties +// +// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 +// +package properties diff --git a/vendor/github.com/magiconair/properties/go.mod b/vendor/github.com/magiconair/properties/go.mod new file mode 100644 index 000000000..02a6f8655 --- /dev/null +++ b/vendor/github.com/magiconair/properties/go.mod @@ -0,0 +1 @@ +module github.com/magiconair/properties diff --git a/vendor/github.com/magiconair/properties/integrate.go b/vendor/github.com/magiconair/properties/integrate.go new file mode 100644 index 000000000..74d38dc67 --- /dev/null +++ b/vendor/github.com/magiconair/properties/integrate.go @@ -0,0 +1,34 @@ +// Copyright 2018 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import "flag" + +// MustFlag sets flags that are skipped by dst.Parse when p contains +// the respective key for flag.Flag.Name. +// +// It's use is recommended with command line arguments as in: +// flag.Parse() +// p.MustFlag(flag.CommandLine) +func (p *Properties) MustFlag(dst *flag.FlagSet) { + m := make(map[string]*flag.Flag) + dst.VisitAll(func(f *flag.Flag) { + m[f.Name] = f + }) + dst.Visit(func(f *flag.Flag) { + delete(m, f.Name) // overridden + }) + + for name, f := range m { + v, ok := p.Get(name) + if !ok { + continue + } + + if err := f.Value.Set(v); err != nil { + ErrorHandler(err) + } + } +} diff --git a/vendor/github.com/magiconair/properties/lex.go b/vendor/github.com/magiconair/properties/lex.go new file mode 100644 index 000000000..367166d58 --- /dev/null +++ b/vendor/github.com/magiconair/properties/lex.go @@ -0,0 +1,407 @@ +// Copyright 2018 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Parts of the lexer are from the template/text/parser package +// For these parts the following applies: +// +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file of the go 1.2 +// distribution. + +package properties + +import ( + "fmt" + "strconv" + "strings" + "unicode/utf8" +) + +// item represents a token or text string returned from the scanner. +type item struct { + typ itemType // The type of this item. + pos int // The starting position, in bytes, of this item in the input string. + val string // The value of this item. +} + +func (i item) String() string { + switch { + case i.typ == itemEOF: + return "EOF" + case i.typ == itemError: + return i.val + case len(i.val) > 10: + return fmt.Sprintf("%.10q...", i.val) + } + return fmt.Sprintf("%q", i.val) +} + +// itemType identifies the type of lex items. +type itemType int + +const ( + itemError itemType = iota // error occurred; value is text of error + itemEOF + itemKey // a key + itemValue // a value + itemComment // a comment +) + +// defines a constant for EOF +const eof = -1 + +// permitted whitespace characters space, FF and TAB +const whitespace = " \f\t" + +// stateFn represents the state of the scanner as a function that returns the next state. +type stateFn func(*lexer) stateFn + +// lexer holds the state of the scanner. +type lexer struct { + input string // the string being scanned + state stateFn // the next lexing function to enter + pos int // current position in the input + start int // start position of this item + width int // width of last rune read from input + lastPos int // position of most recent item returned by nextItem + runes []rune // scanned runes for this item + items chan item // channel of scanned items +} + +// next returns the next rune in the input. +func (l *lexer) next() rune { + if l.pos >= len(l.input) { + l.width = 0 + return eof + } + r, w := utf8.DecodeRuneInString(l.input[l.pos:]) + l.width = w + l.pos += l.width + return r +} + +// peek returns but does not consume the next rune in the input. +func (l *lexer) peek() rune { + r := l.next() + l.backup() + return r +} + +// backup steps back one rune. Can only be called once per call of next. +func (l *lexer) backup() { + l.pos -= l.width +} + +// emit passes an item back to the client. +func (l *lexer) emit(t itemType) { + i := item{t, l.start, string(l.runes)} + l.items <- i + l.start = l.pos + l.runes = l.runes[:0] +} + +// ignore skips over the pending input before this point. +func (l *lexer) ignore() { + l.start = l.pos +} + +// appends the rune to the current value +func (l *lexer) appendRune(r rune) { + l.runes = append(l.runes, r) +} + +// accept consumes the next rune if it's from the valid set. +func (l *lexer) accept(valid string) bool { + if strings.ContainsRune(valid, l.next()) { + return true + } + l.backup() + return false +} + +// acceptRun consumes a run of runes from the valid set. +func (l *lexer) acceptRun(valid string) { + for strings.ContainsRune(valid, l.next()) { + } + l.backup() +} + +// acceptRunUntil consumes a run of runes up to a terminator. +func (l *lexer) acceptRunUntil(term rune) { + for term != l.next() { + } + l.backup() +} + +// hasText returns true if the current parsed text is not empty. +func (l *lexer) isNotEmpty() bool { + return l.pos > l.start +} + +// lineNumber reports which line we're on, based on the position of +// the previous item returned by nextItem. Doing it this way +// means we don't have to worry about peek double counting. +func (l *lexer) lineNumber() int { + return 1 + strings.Count(l.input[:l.lastPos], "\n") +} + +// errorf returns an error token and terminates the scan by passing +// back a nil pointer that will be the next state, terminating l.nextItem. +func (l *lexer) errorf(format string, args ...interface{}) stateFn { + l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)} + return nil +} + +// nextItem returns the next item from the input. +func (l *lexer) nextItem() item { + i := <-l.items + l.lastPos = i.pos + return i +} + +// lex creates a new scanner for the input string. +func lex(input string) *lexer { + l := &lexer{ + input: input, + items: make(chan item), + runes: make([]rune, 0, 32), + } + go l.run() + return l +} + +// run runs the state machine for the lexer. +func (l *lexer) run() { + for l.state = lexBeforeKey(l); l.state != nil; { + l.state = l.state(l) + } +} + +// state functions + +// lexBeforeKey scans until a key begins. +func lexBeforeKey(l *lexer) stateFn { + switch r := l.next(); { + case isEOF(r): + l.emit(itemEOF) + return nil + + case isEOL(r): + l.ignore() + return lexBeforeKey + + case isComment(r): + return lexComment + + case isWhitespace(r): + l.ignore() + return lexBeforeKey + + default: + l.backup() + return lexKey + } +} + +// lexComment scans a comment line. The comment character has already been scanned. +func lexComment(l *lexer) stateFn { + l.acceptRun(whitespace) + l.ignore() + for { + switch r := l.next(); { + case isEOF(r): + l.ignore() + l.emit(itemEOF) + return nil + case isEOL(r): + l.emit(itemComment) + return lexBeforeKey + default: + l.appendRune(r) + } + } +} + +// lexKey scans the key up to a delimiter +func lexKey(l *lexer) stateFn { + var r rune + +Loop: + for { + switch r = l.next(); { + + case isEscape(r): + err := l.scanEscapeSequence() + if err != nil { + return l.errorf(err.Error()) + } + + case isEndOfKey(r): + l.backup() + break Loop + + case isEOF(r): + break Loop + + default: + l.appendRune(r) + } + } + + if len(l.runes) > 0 { + l.emit(itemKey) + } + + if isEOF(r) { + l.emit(itemEOF) + return nil + } + + return lexBeforeValue +} + +// lexBeforeValue scans the delimiter between key and value. +// Leading and trailing whitespace is ignored. +// We expect to be just after the key. +func lexBeforeValue(l *lexer) stateFn { + l.acceptRun(whitespace) + l.accept(":=") + l.acceptRun(whitespace) + l.ignore() + return lexValue +} + +// lexValue scans text until the end of the line. We expect to be just after the delimiter. +func lexValue(l *lexer) stateFn { + for { + switch r := l.next(); { + case isEscape(r): + if isEOL(l.peek()) { + l.next() + l.acceptRun(whitespace) + } else { + err := l.scanEscapeSequence() + if err != nil { + return l.errorf(err.Error()) + } + } + + case isEOL(r): + l.emit(itemValue) + l.ignore() + return lexBeforeKey + + case isEOF(r): + l.emit(itemValue) + l.emit(itemEOF) + return nil + + default: + l.appendRune(r) + } + } +} + +// scanEscapeSequence scans either one of the escaped characters +// or a unicode literal. We expect to be after the escape character. +func (l *lexer) scanEscapeSequence() error { + switch r := l.next(); { + + case isEscapedCharacter(r): + l.appendRune(decodeEscapedCharacter(r)) + return nil + + case atUnicodeLiteral(r): + return l.scanUnicodeLiteral() + + case isEOF(r): + return fmt.Errorf("premature EOF") + + // silently drop the escape character and append the rune as is + default: + l.appendRune(r) + return nil + } +} + +// scans a unicode literal in the form \uXXXX. We expect to be after the \u. +func (l *lexer) scanUnicodeLiteral() error { + // scan the digits + d := make([]rune, 4) + for i := 0; i < 4; i++ { + d[i] = l.next() + if d[i] == eof || !strings.ContainsRune("0123456789abcdefABCDEF", d[i]) { + return fmt.Errorf("invalid unicode literal") + } + } + + // decode the digits into a rune + r, err := strconv.ParseInt(string(d), 16, 0) + if err != nil { + return err + } + + l.appendRune(rune(r)) + return nil +} + +// decodeEscapedCharacter returns the unescaped rune. We expect to be after the escape character. +func decodeEscapedCharacter(r rune) rune { + switch r { + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + default: + return r + } +} + +// atUnicodeLiteral reports whether we are at a unicode literal. +// The escape character has already been consumed. +func atUnicodeLiteral(r rune) bool { + return r == 'u' +} + +// isComment reports whether we are at the start of a comment. +func isComment(r rune) bool { + return r == '#' || r == '!' +} + +// isEndOfKey reports whether the rune terminates the current key. +func isEndOfKey(r rune) bool { + return strings.ContainsRune(" \f\t\r\n:=", r) +} + +// isEOF reports whether we are at EOF. +func isEOF(r rune) bool { + return r == eof +} + +// isEOL reports whether we are at a new line character. +func isEOL(r rune) bool { + return r == '\n' || r == '\r' +} + +// isEscape reports whether the rune is the escape character which +// prefixes unicode literals and other escaped characters. +func isEscape(r rune) bool { + return r == '\\' +} + +// isEscapedCharacter reports whether we are at one of the characters that need escaping. +// The escape character has already been consumed. +func isEscapedCharacter(r rune) bool { + return strings.ContainsRune(" :=fnrt", r) +} + +// isWhitespace reports whether the rune is a whitespace character. +func isWhitespace(r rune) bool { + return strings.ContainsRune(whitespace, r) +} diff --git a/vendor/github.com/magiconair/properties/load.go b/vendor/github.com/magiconair/properties/load.go new file mode 100644 index 000000000..ab9532535 --- /dev/null +++ b/vendor/github.com/magiconair/properties/load.go @@ -0,0 +1,292 @@ +// Copyright 2018 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "io/ioutil" + "net/http" + "os" + "strings" +) + +// Encoding specifies encoding of the input data. +type Encoding uint + +const ( + // utf8Default is a private placeholder for the zero value of Encoding to + // ensure that it has the correct meaning. UTF8 is the default encoding but + // was assigned a non-zero value which cannot be changed without breaking + // existing code. Clients should continue to use the public constants. + utf8Default Encoding = iota + + // UTF8 interprets the input data as UTF-8. + UTF8 + + // ISO_8859_1 interprets the input data as ISO-8859-1. + ISO_8859_1 +) + +type Loader struct { + // Encoding determines how the data from files and byte buffers + // is interpreted. For URLs the Content-Type header is used + // to determine the encoding of the data. + Encoding Encoding + + // DisableExpansion configures the property expansion of the + // returned property object. When set to true, the property values + // will not be expanded and the Property object will not be checked + // for invalid expansion expressions. + DisableExpansion bool + + // IgnoreMissing configures whether missing files or URLs which return + // 404 are reported as errors. When set to true, missing files and 404 + // status codes are not reported as errors. + IgnoreMissing bool +} + +// Load reads a buffer into a Properties struct. +func (l *Loader) LoadBytes(buf []byte) (*Properties, error) { + return l.loadBytes(buf, l.Encoding) +} + +// LoadAll reads the content of multiple URLs or files in the given order into +// a Properties struct. If IgnoreMissing is true then a 404 status code or +// missing file will not be reported as error. Encoding sets the encoding for +// files. For the URLs see LoadURL for the Content-Type header and the +// encoding. +func (l *Loader) LoadAll(names []string) (*Properties, error) { + all := NewProperties() + for _, name := range names { + n, err := expandName(name) + if err != nil { + return nil, err + } + + var p *Properties + switch { + case strings.HasPrefix(n, "http://"): + p, err = l.LoadURL(n) + case strings.HasPrefix(n, "https://"): + p, err = l.LoadURL(n) + default: + p, err = l.LoadFile(n) + } + if err != nil { + return nil, err + } + all.Merge(p) + } + + all.DisableExpansion = l.DisableExpansion + if all.DisableExpansion { + return all, nil + } + return all, all.check() +} + +// LoadFile reads a file into a Properties struct. +// If IgnoreMissing is true then a missing file will not be +// reported as error. +func (l *Loader) LoadFile(filename string) (*Properties, error) { + data, err := ioutil.ReadFile(filename) + if err != nil { + if l.IgnoreMissing && os.IsNotExist(err) { + LogPrintf("properties: %s not found. skipping", filename) + return NewProperties(), nil + } + return nil, err + } + return l.loadBytes(data, l.Encoding) +} + +// LoadURL reads the content of the URL into a Properties struct. +// +// The encoding is determined via the Content-Type header which +// should be set to 'text/plain'. If the 'charset' parameter is +// missing, 'iso-8859-1' or 'latin1' the encoding is set to +// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the +// encoding is set to UTF-8. A missing content type header is +// interpreted as 'text/plain; charset=utf-8'. +func (l *Loader) LoadURL(url string) (*Properties, error) { + resp, err := http.Get(url) + if err != nil { + return nil, fmt.Errorf("properties: error fetching %q. %s", url, err) + } + defer resp.Body.Close() + + if resp.StatusCode == 404 && l.IgnoreMissing { + LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode) + return NewProperties(), nil + } + + if resp.StatusCode != 200 { + return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode) + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("properties: %s error reading response. %s", url, err) + } + + ct := resp.Header.Get("Content-Type") + var enc Encoding + switch strings.ToLower(ct) { + case "text/plain", "text/plain; charset=iso-8859-1", "text/plain; charset=latin1": + enc = ISO_8859_1 + case "", "text/plain; charset=utf-8": + enc = UTF8 + default: + return nil, fmt.Errorf("properties: invalid content type %s", ct) + } + + return l.loadBytes(body, enc) +} + +func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) { + p, err := parse(convert(buf, enc)) + if err != nil { + return nil, err + } + p.DisableExpansion = l.DisableExpansion + if p.DisableExpansion { + return p, nil + } + return p, p.check() +} + +// Load reads a buffer into a Properties struct. +func Load(buf []byte, enc Encoding) (*Properties, error) { + l := &Loader{Encoding: enc} + return l.LoadBytes(buf) +} + +// LoadString reads an UTF8 string into a properties struct. +func LoadString(s string) (*Properties, error) { + l := &Loader{Encoding: UTF8} + return l.LoadBytes([]byte(s)) +} + +// LoadMap creates a new Properties struct from a string map. +func LoadMap(m map[string]string) *Properties { + p := NewProperties() + for k, v := range m { + p.Set(k, v) + } + return p +} + +// LoadFile reads a file into a Properties struct. +func LoadFile(filename string, enc Encoding) (*Properties, error) { + l := &Loader{Encoding: enc} + return l.LoadAll([]string{filename}) +} + +// LoadFiles reads multiple files in the given order into +// a Properties struct. If 'ignoreMissing' is true then +// non-existent files will not be reported as error. +func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { + l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} + return l.LoadAll(filenames) +} + +// LoadURL reads the content of the URL into a Properties struct. +// See Loader#LoadURL for details. +func LoadURL(url string) (*Properties, error) { + l := &Loader{Encoding: UTF8} + return l.LoadAll([]string{url}) +} + +// LoadURLs reads the content of multiple URLs in the given order into a +// Properties struct. If IgnoreMissing is true then a 404 status code will +// not be reported as error. See Loader#LoadURL for the Content-Type header +// and the encoding. +func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) { + l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing} + return l.LoadAll(urls) +} + +// LoadAll reads the content of multiple URLs or files in the given order into a +// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will +// not be reported as error. Encoding sets the encoding for files. For the URLs please see +// LoadURL for the Content-Type header and the encoding. +func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) { + l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} + return l.LoadAll(names) +} + +// MustLoadString reads an UTF8 string into a Properties struct and +// panics on error. +func MustLoadString(s string) *Properties { + return must(LoadString(s)) +} + +// MustLoadFile reads a file into a Properties struct and +// panics on error. +func MustLoadFile(filename string, enc Encoding) *Properties { + return must(LoadFile(filename, enc)) +} + +// MustLoadFiles reads multiple files in the given order into +// a Properties struct and panics on error. If 'ignoreMissing' +// is true then non-existent files will not be reported as error. +func MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties { + return must(LoadFiles(filenames, enc, ignoreMissing)) +} + +// MustLoadURL reads the content of a URL into a Properties struct and +// panics on error. +func MustLoadURL(url string) *Properties { + return must(LoadURL(url)) +} + +// MustLoadURLs reads the content of multiple URLs in the given order into a +// Properties struct and panics on error. If 'ignoreMissing' is true then a 404 +// status code will not be reported as error. +func MustLoadURLs(urls []string, ignoreMissing bool) *Properties { + return must(LoadURLs(urls, ignoreMissing)) +} + +// MustLoadAll reads the content of multiple URLs or files in the given order into a +// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will +// not be reported as error. Encoding sets the encoding for files. For the URLs please see +// LoadURL for the Content-Type header and the encoding. It panics on error. +func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties { + return must(LoadAll(names, enc, ignoreMissing)) +} + +func must(p *Properties, err error) *Properties { + if err != nil { + ErrorHandler(err) + } + return p +} + +// expandName expands ${ENV_VAR} expressions in a name. +// If the environment variable does not exist then it will be replaced +// with an empty string. Malformed expressions like "${ENV_VAR" will +// be reported as error. +func expandName(name string) (string, error) { + return expand(name, []string{}, "${", "}", make(map[string]string)) +} + +// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string. +// For ISO-8859-1 we can convert each byte straight into a rune since the +// first 256 unicode code points cover ISO-8859-1. +func convert(buf []byte, enc Encoding) string { + switch enc { + case utf8Default, UTF8: + return string(buf) + case ISO_8859_1: + runes := make([]rune, len(buf)) + for i, b := range buf { + runes[i] = rune(b) + } + return string(runes) + default: + ErrorHandler(fmt.Errorf("unsupported encoding %v", enc)) + } + panic("ErrorHandler should exit") +} diff --git a/vendor/github.com/magiconair/properties/parser.go b/vendor/github.com/magiconair/properties/parser.go new file mode 100644 index 000000000..cdc4a8034 --- /dev/null +++ b/vendor/github.com/magiconair/properties/parser.go @@ -0,0 +1,95 @@ +// Copyright 2018 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "runtime" +) + +type parser struct { + lex *lexer +} + +func parse(input string) (properties *Properties, err error) { + p := &parser{lex: lex(input)} + defer p.recover(&err) + + properties = NewProperties() + key := "" + comments := []string{} + + for { + token := p.expectOneOf(itemComment, itemKey, itemEOF) + switch token.typ { + case itemEOF: + goto done + case itemComment: + comments = append(comments, token.val) + continue + case itemKey: + key = token.val + if _, ok := properties.m[key]; !ok { + properties.k = append(properties.k, key) + } + } + + token = p.expectOneOf(itemValue, itemEOF) + if len(comments) > 0 { + properties.c[key] = comments + comments = []string{} + } + switch token.typ { + case itemEOF: + properties.m[key] = "" + goto done + case itemValue: + properties.m[key] = token.val + } + } + +done: + return properties, nil +} + +func (p *parser) errorf(format string, args ...interface{}) { + format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format) + panic(fmt.Errorf(format, args...)) +} + +func (p *parser) expect(expected itemType) (token item) { + token = p.lex.nextItem() + if token.typ != expected { + p.unexpected(token) + } + return token +} + +func (p *parser) expectOneOf(expected ...itemType) (token item) { + token = p.lex.nextItem() + for _, v := range expected { + if token.typ == v { + return token + } + } + p.unexpected(token) + panic("unexpected token") +} + +func (p *parser) unexpected(token item) { + p.errorf(token.String()) +} + +// recover is the handler that turns panics into returns from the top level of Parse. +func (p *parser) recover(errp *error) { + e := recover() + if e != nil { + if _, ok := e.(runtime.Error); ok { + panic(e) + } + *errp = e.(error) + } + return +} diff --git a/vendor/github.com/magiconair/properties/properties.go b/vendor/github.com/magiconair/properties/properties.go new file mode 100644 index 000000000..cb3d1a332 --- /dev/null +++ b/vendor/github.com/magiconair/properties/properties.go @@ -0,0 +1,833 @@ +// Copyright 2018 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +// BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer. +// BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used. + +import ( + "fmt" + "io" + "log" + "os" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" +) + +const maxExpansionDepth = 64 + +// ErrorHandlerFunc defines the type of function which handles failures +// of the MustXXX() functions. An error handler function must exit +// the application after handling the error. +type ErrorHandlerFunc func(error) + +// ErrorHandler is the function which handles failures of the MustXXX() +// functions. The default is LogFatalHandler. +var ErrorHandler ErrorHandlerFunc = LogFatalHandler + +// LogHandlerFunc defines the function prototype for logging errors. +type LogHandlerFunc func(fmt string, args ...interface{}) + +// LogPrintf defines a log handler which uses log.Printf. +var LogPrintf LogHandlerFunc = log.Printf + +// LogFatalHandler handles the error by logging a fatal error and exiting. +func LogFatalHandler(err error) { + log.Fatal(err) +} + +// PanicHandler handles the error by panicking. +func PanicHandler(err error) { + panic(err) +} + +// ----------------------------------------------------------------------------- + +// A Properties contains the key/value pairs from the properties input. +// All values are stored in unexpanded form and are expanded at runtime +type Properties struct { + // Pre-/Postfix for property expansion. + Prefix string + Postfix string + + // DisableExpansion controls the expansion of properties on Get() + // and the check for circular references on Set(). When set to + // true Properties behaves like a simple key/value store and does + // not check for circular references on Get() or on Set(). + DisableExpansion bool + + // Stores the key/value pairs + m map[string]string + + // Stores the comments per key. + c map[string][]string + + // Stores the keys in order of appearance. + k []string +} + +// NewProperties creates a new Properties struct with the default +// configuration for "${key}" expressions. +func NewProperties() *Properties { + return &Properties{ + Prefix: "${", + Postfix: "}", + m: map[string]string{}, + c: map[string][]string{}, + k: []string{}, + } +} + +// Load reads a buffer into the given Properties struct. +func (p *Properties) Load(buf []byte, enc Encoding) error { + l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion} + newProperties, err := l.LoadBytes(buf) + if err != nil { + return err + } + p.Merge(newProperties) + return nil +} + +// Get returns the expanded value for the given key if exists. +// Otherwise, ok is false. +func (p *Properties) Get(key string) (value string, ok bool) { + v, ok := p.m[key] + if p.DisableExpansion { + return v, ok + } + if !ok { + return "", false + } + + expanded, err := p.expand(key, v) + + // we guarantee that the expanded value is free of + // circular references and malformed expressions + // so we panic if we still get an error here. + if err != nil { + ErrorHandler(fmt.Errorf("%s in %q", err, key+" = "+v)) + } + + return expanded, true +} + +// MustGet returns the expanded value for the given key if exists. +// Otherwise, it panics. +func (p *Properties) MustGet(key string) string { + if v, ok := p.Get(key); ok { + return v + } + ErrorHandler(invalidKeyError(key)) + panic("ErrorHandler should exit") +} + +// ---------------------------------------------------------------------------- + +// ClearComments removes the comments for all keys. +func (p *Properties) ClearComments() { + p.c = map[string][]string{} +} + +// ---------------------------------------------------------------------------- + +// GetComment returns the last comment before the given key or an empty string. +func (p *Properties) GetComment(key string) string { + comments, ok := p.c[key] + if !ok || len(comments) == 0 { + return "" + } + return comments[len(comments)-1] +} + +// ---------------------------------------------------------------------------- + +// GetComments returns all comments that appeared before the given key or nil. +func (p *Properties) GetComments(key string) []string { + if comments, ok := p.c[key]; ok { + return comments + } + return nil +} + +// ---------------------------------------------------------------------------- + +// SetComment sets the comment for the key. +func (p *Properties) SetComment(key, comment string) { + p.c[key] = []string{comment} +} + +// ---------------------------------------------------------------------------- + +// SetComments sets the comments for the key. If the comments are nil then +// all comments for this key are deleted. +func (p *Properties) SetComments(key string, comments []string) { + if comments == nil { + delete(p.c, key) + return + } + p.c[key] = comments +} + +// ---------------------------------------------------------------------------- + +// GetBool checks if the expanded value is one of '1', 'yes', +// 'true' or 'on' if the key exists. The comparison is case-insensitive. +// If the key does not exist the default value is returned. +func (p *Properties) GetBool(key string, def bool) bool { + v, err := p.getBool(key) + if err != nil { + return def + } + return v +} + +// MustGetBool checks if the expanded value is one of '1', 'yes', +// 'true' or 'on' if the key exists. The comparison is case-insensitive. +// If the key does not exist the function panics. +func (p *Properties) MustGetBool(key string) bool { + v, err := p.getBool(key) + if err != nil { + ErrorHandler(err) + } + return v +} + +func (p *Properties) getBool(key string) (value bool, err error) { + if v, ok := p.Get(key); ok { + return boolVal(v), nil + } + return false, invalidKeyError(key) +} + +func boolVal(v string) bool { + v = strings.ToLower(v) + return v == "1" || v == "true" || v == "yes" || v == "on" +} + +// ---------------------------------------------------------------------------- + +// GetDuration parses the expanded value as an time.Duration (in ns) if the +// key exists. If key does not exist or the value cannot be parsed the default +// value is returned. In almost all cases you want to use GetParsedDuration(). +func (p *Properties) GetDuration(key string, def time.Duration) time.Duration { + v, err := p.getInt64(key) + if err != nil { + return def + } + return time.Duration(v) +} + +// MustGetDuration parses the expanded value as an time.Duration (in ns) if +// the key exists. If key does not exist or the value cannot be parsed the +// function panics. In almost all cases you want to use MustGetParsedDuration(). +func (p *Properties) MustGetDuration(key string) time.Duration { + v, err := p.getInt64(key) + if err != nil { + ErrorHandler(err) + } + return time.Duration(v) +} + +// ---------------------------------------------------------------------------- + +// GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. +func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration { + s, ok := p.Get(key) + if !ok { + return def + } + v, err := time.ParseDuration(s) + if err != nil { + return def + } + return v +} + +// MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +func (p *Properties) MustGetParsedDuration(key string) time.Duration { + s, ok := p.Get(key) + if !ok { + ErrorHandler(invalidKeyError(key)) + } + v, err := time.ParseDuration(s) + if err != nil { + ErrorHandler(err) + } + return v +} + +// ---------------------------------------------------------------------------- + +// GetFloat64 parses the expanded value as a float64 if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. +func (p *Properties) GetFloat64(key string, def float64) float64 { + v, err := p.getFloat64(key) + if err != nil { + return def + } + return v +} + +// MustGetFloat64 parses the expanded value as a float64 if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +func (p *Properties) MustGetFloat64(key string) float64 { + v, err := p.getFloat64(key) + if err != nil { + ErrorHandler(err) + } + return v +} + +func (p *Properties) getFloat64(key string) (value float64, err error) { + if v, ok := p.Get(key); ok { + value, err = strconv.ParseFloat(v, 64) + if err != nil { + return 0, err + } + return value, nil + } + return 0, invalidKeyError(key) +} + +// ---------------------------------------------------------------------------- + +// GetInt parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. If the value does not fit into an int the +// function panics with an out of range error. +func (p *Properties) GetInt(key string, def int) int { + v, err := p.getInt64(key) + if err != nil { + return def + } + return intRangeCheck(key, v) +} + +// MustGetInt parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +// If the value does not fit into an int the function panics with +// an out of range error. +func (p *Properties) MustGetInt(key string) int { + v, err := p.getInt64(key) + if err != nil { + ErrorHandler(err) + } + return intRangeCheck(key, v) +} + +// ---------------------------------------------------------------------------- + +// GetInt64 parses the expanded value as an int64 if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. +func (p *Properties) GetInt64(key string, def int64) int64 { + v, err := p.getInt64(key) + if err != nil { + return def + } + return v +} + +// MustGetInt64 parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +func (p *Properties) MustGetInt64(key string) int64 { + v, err := p.getInt64(key) + if err != nil { + ErrorHandler(err) + } + return v +} + +func (p *Properties) getInt64(key string) (value int64, err error) { + if v, ok := p.Get(key); ok { + value, err = strconv.ParseInt(v, 10, 64) + if err != nil { + return 0, err + } + return value, nil + } + return 0, invalidKeyError(key) +} + +// ---------------------------------------------------------------------------- + +// GetUint parses the expanded value as an uint if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. If the value does not fit into an int the +// function panics with an out of range error. +func (p *Properties) GetUint(key string, def uint) uint { + v, err := p.getUint64(key) + if err != nil { + return def + } + return uintRangeCheck(key, v) +} + +// MustGetUint parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +// If the value does not fit into an int the function panics with +// an out of range error. +func (p *Properties) MustGetUint(key string) uint { + v, err := p.getUint64(key) + if err != nil { + ErrorHandler(err) + } + return uintRangeCheck(key, v) +} + +// ---------------------------------------------------------------------------- + +// GetUint64 parses the expanded value as an uint64 if the key exists. +// If key does not exist or the value cannot be parsed the default +// value is returned. +func (p *Properties) GetUint64(key string, def uint64) uint64 { + v, err := p.getUint64(key) + if err != nil { + return def + } + return v +} + +// MustGetUint64 parses the expanded value as an int if the key exists. +// If key does not exist or the value cannot be parsed the function panics. +func (p *Properties) MustGetUint64(key string) uint64 { + v, err := p.getUint64(key) + if err != nil { + ErrorHandler(err) + } + return v +} + +func (p *Properties) getUint64(key string) (value uint64, err error) { + if v, ok := p.Get(key); ok { + value, err = strconv.ParseUint(v, 10, 64) + if err != nil { + return 0, err + } + return value, nil + } + return 0, invalidKeyError(key) +} + +// ---------------------------------------------------------------------------- + +// GetString returns the expanded value for the given key if exists or +// the default value otherwise. +func (p *Properties) GetString(key, def string) string { + if v, ok := p.Get(key); ok { + return v + } + return def +} + +// MustGetString returns the expanded value for the given key if exists or +// panics otherwise. +func (p *Properties) MustGetString(key string) string { + if v, ok := p.Get(key); ok { + return v + } + ErrorHandler(invalidKeyError(key)) + panic("ErrorHandler should exit") +} + +// ---------------------------------------------------------------------------- + +// Filter returns a new properties object which contains all properties +// for which the key matches the pattern. +func (p *Properties) Filter(pattern string) (*Properties, error) { + re, err := regexp.Compile(pattern) + if err != nil { + return nil, err + } + + return p.FilterRegexp(re), nil +} + +// FilterRegexp returns a new properties object which contains all properties +// for which the key matches the regular expression. +func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties { + pp := NewProperties() + for _, k := range p.k { + if re.MatchString(k) { + // TODO(fs): we are ignoring the error which flags a circular reference. + // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) + pp.Set(k, p.m[k]) + } + } + return pp +} + +// FilterPrefix returns a new properties object with a subset of all keys +// with the given prefix. +func (p *Properties) FilterPrefix(prefix string) *Properties { + pp := NewProperties() + for _, k := range p.k { + if strings.HasPrefix(k, prefix) { + // TODO(fs): we are ignoring the error which flags a circular reference. + // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) + pp.Set(k, p.m[k]) + } + } + return pp +} + +// FilterStripPrefix returns a new properties object with a subset of all keys +// with the given prefix and the prefix removed from the keys. +func (p *Properties) FilterStripPrefix(prefix string) *Properties { + pp := NewProperties() + n := len(prefix) + for _, k := range p.k { + if len(k) > len(prefix) && strings.HasPrefix(k, prefix) { + // TODO(fs): we are ignoring the error which flags a circular reference. + // TODO(fs): since we are modifying keys I am not entirely sure whether we can create a circular reference + // TODO(fs): this function should probably return an error but the signature is fixed + pp.Set(k[n:], p.m[k]) + } + } + return pp +} + +// Len returns the number of keys. +func (p *Properties) Len() int { + return len(p.m) +} + +// Keys returns all keys in the same order as in the input. +func (p *Properties) Keys() []string { + keys := make([]string, len(p.k)) + copy(keys, p.k) + return keys +} + +// Set sets the property key to the corresponding value. +// If a value for key existed before then ok is true and prev +// contains the previous value. If the value contains a +// circular reference or a malformed expression then +// an error is returned. +// An empty key is silently ignored. +func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { + if key == "" { + return "", false, nil + } + + // if expansion is disabled we allow circular references + if p.DisableExpansion { + prev, ok = p.Get(key) + p.m[key] = value + if !ok { + p.k = append(p.k, key) + } + return prev, ok, nil + } + + // to check for a circular reference we temporarily need + // to set the new value. If there is an error then revert + // to the previous state. Only if all tests are successful + // then we add the key to the p.k list. + prev, ok = p.Get(key) + p.m[key] = value + + // now check for a circular reference + _, err = p.expand(key, value) + if err != nil { + + // revert to the previous state + if ok { + p.m[key] = prev + } else { + delete(p.m, key) + } + + return "", false, err + } + + if !ok { + p.k = append(p.k, key) + } + + return prev, ok, nil +} + +// SetValue sets property key to the default string value +// as defined by fmt.Sprintf("%v"). +func (p *Properties) SetValue(key string, value interface{}) error { + _, _, err := p.Set(key, fmt.Sprintf("%v", value)) + return err +} + +// MustSet sets the property key to the corresponding value. +// If a value for key existed before then ok is true and prev +// contains the previous value. An empty key is silently ignored. +func (p *Properties) MustSet(key, value string) (prev string, ok bool) { + prev, ok, err := p.Set(key, value) + if err != nil { + ErrorHandler(err) + } + return prev, ok +} + +// String returns a string of all expanded 'key = value' pairs. +func (p *Properties) String() string { + var s string + for _, key := range p.k { + value, _ := p.Get(key) + s = fmt.Sprintf("%s%s = %s\n", s, key, value) + } + return s +} + +// Write writes all unexpanded 'key = value' pairs to the given writer. +// Write returns the number of bytes written and any write error encountered. +func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) { + return p.WriteComment(w, "", enc) +} + +// WriteComment writes all unexpanced 'key = value' pairs to the given writer. +// If prefix is not empty then comments are written with a blank line and the +// given prefix. The prefix should be either "# " or "! " to be compatible with +// the properties file format. Otherwise, the properties parser will not be +// able to read the file back in. It returns the number of bytes written and +// any write error encountered. +func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error) { + var x int + + for _, key := range p.k { + value := p.m[key] + + if prefix != "" { + if comments, ok := p.c[key]; ok { + // don't print comments if they are all empty + allEmpty := true + for _, c := range comments { + if c != "" { + allEmpty = false + break + } + } + + if !allEmpty { + // add a blank line between entries but not at the top + if len(comments) > 0 && n > 0 { + x, err = fmt.Fprintln(w) + if err != nil { + return + } + n += x + } + + for _, c := range comments { + x, err = fmt.Fprintf(w, "%s%s\n", prefix, encode(c, "", enc)) + if err != nil { + return + } + n += x + } + } + } + } + + x, err = fmt.Fprintf(w, "%s = %s\n", encode(key, " :", enc), encode(value, "", enc)) + if err != nil { + return + } + n += x + } + return +} + +// Map returns a copy of the properties as a map. +func (p *Properties) Map() map[string]string { + m := make(map[string]string) + for k, v := range p.m { + m[k] = v + } + return m +} + +// FilterFunc returns a copy of the properties which includes the values which passed all filters. +func (p *Properties) FilterFunc(filters ...func(k, v string) bool) *Properties { + pp := NewProperties() +outer: + for k, v := range p.m { + for _, f := range filters { + if !f(k, v) { + continue outer + } + pp.Set(k, v) + } + } + return pp +} + +// ---------------------------------------------------------------------------- + +// Delete removes the key and its comments. +func (p *Properties) Delete(key string) { + delete(p.m, key) + delete(p.c, key) + newKeys := []string{} + for _, k := range p.k { + if k != key { + newKeys = append(newKeys, k) + } + } + p.k = newKeys +} + +// Merge merges properties, comments and keys from other *Properties into p +func (p *Properties) Merge(other *Properties) { + for k, v := range other.m { + p.m[k] = v + } + for k, v := range other.c { + p.c[k] = v + } + +outer: + for _, otherKey := range other.k { + for _, key := range p.k { + if otherKey == key { + continue outer + } + } + p.k = append(p.k, otherKey) + } +} + +// ---------------------------------------------------------------------------- + +// check expands all values and returns an error if a circular reference or +// a malformed expression was found. +func (p *Properties) check() error { + for key, value := range p.m { + if _, err := p.expand(key, value); err != nil { + return err + } + } + return nil +} + +func (p *Properties) expand(key, input string) (string, error) { + // no pre/postfix -> nothing to expand + if p.Prefix == "" && p.Postfix == "" { + return input, nil + } + + return expand(input, []string{key}, p.Prefix, p.Postfix, p.m) +} + +// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values. +// The function keeps track of the keys that were already expanded and stops if it +// detects a circular reference or a malformed expression of the form '(prefix)key'. +func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) { + if len(keys) > maxExpansionDepth { + return "", fmt.Errorf("expansion too deep") + } + + for { + start := strings.Index(s, prefix) + if start == -1 { + return s, nil + } + + keyStart := start + len(prefix) + keyLen := strings.Index(s[keyStart:], postfix) + if keyLen == -1 { + return "", fmt.Errorf("malformed expression") + } + + end := keyStart + keyLen + len(postfix) - 1 + key := s[keyStart : keyStart+keyLen] + + // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key) + + for _, k := range keys { + if key == k { + return "", fmt.Errorf("circular reference") + } + } + + val, ok := values[key] + if !ok { + val = os.Getenv(key) + } + new_val, err := expand(val, append(keys, key), prefix, postfix, values) + if err != nil { + return "", err + } + s = s[:start] + new_val + s[end+1:] + } + return s, nil +} + +// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters. +func encode(s string, special string, enc Encoding) string { + switch enc { + case UTF8: + return encodeUtf8(s, special) + case ISO_8859_1: + return encodeIso(s, special) + default: + panic(fmt.Sprintf("unsupported encoding %v", enc)) + } +} + +func encodeUtf8(s string, special string) string { + v := "" + for pos := 0; pos < len(s); { + r, w := utf8.DecodeRuneInString(s[pos:]) + pos += w + v += escape(r, special) + } + return v +} + +func encodeIso(s string, special string) string { + var r rune + var w int + var v string + for pos := 0; pos < len(s); { + switch r, w = utf8.DecodeRuneInString(s[pos:]); { + case r < 1<<8: // single byte rune -> escape special chars only + v += escape(r, special) + case r < 1<<16: // two byte rune -> unicode literal + v += fmt.Sprintf("\\u%04x", r) + default: // more than two bytes per rune -> can't encode + v += "?" + } + pos += w + } + return v +} + +func escape(r rune, special string) string { + switch r { + case '\f': + return "\\f" + case '\n': + return "\\n" + case '\r': + return "\\r" + case '\t': + return "\\t" + default: + if strings.ContainsRune(special, r) { + return "\\" + string(r) + } + return string(r) + } +} + +func invalidKeyError(key string) error { + return fmt.Errorf("unknown property: %s", key) +} diff --git a/vendor/github.com/magiconair/properties/rangecheck.go b/vendor/github.com/magiconair/properties/rangecheck.go new file mode 100644 index 000000000..b013a2e5e --- /dev/null +++ b/vendor/github.com/magiconair/properties/rangecheck.go @@ -0,0 +1,31 @@ +// Copyright 2018 Frank Schroeder. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package properties + +import ( + "fmt" + "math" +) + +// make this a var to overwrite it in a test +var is32Bit = ^uint(0) == math.MaxUint32 + +// intRangeCheck checks if the value fits into the int type and +// panics if it does not. +func intRangeCheck(key string, v int64) int { + if is32Bit && (v < math.MinInt32 || v > math.MaxInt32) { + panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) + } + return int(v) +} + +// uintRangeCheck checks if the value fits into the uint type and +// panics if it does not. +func uintRangeCheck(key string, v uint64) uint { + if is32Bit && v > math.MaxUint32 { + panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) + } + return uint(v) +} diff --git a/vendor/github.com/maratori/testpackage/LICENSE b/vendor/github.com/maratori/testpackage/LICENSE new file mode 100644 index 000000000..644d0b1c8 --- /dev/null +++ b/vendor/github.com/maratori/testpackage/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Marat Reymers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/maratori/testpackage/pkg/testpackage/testpackage.go b/vendor/github.com/maratori/testpackage/pkg/testpackage/testpackage.go new file mode 100644 index 000000000..cad24e1a5 --- /dev/null +++ b/vendor/github.com/maratori/testpackage/pkg/testpackage/testpackage.go @@ -0,0 +1,53 @@ +package testpackage + +import ( + "flag" + "regexp" + "strings" + + "golang.org/x/tools/go/analysis" +) + +const ( + SkipRegexpFlagName = "skip-regexp" + SkipRegexpFlagUsage = `regexp pattern to skip file by name. To not skip files use -skip-regexp="^$"` + SkipRegexpFlagDefault = `(export|internal)_test\.go` +) + +// NewAnalyzer returns Analyzer that makes you use a separate _test package +func NewAnalyzer() *analysis.Analyzer { + var ( + skipFileRegexp = SkipRegexpFlagDefault + fs flag.FlagSet + ) + + fs.StringVar(&skipFileRegexp, SkipRegexpFlagName, skipFileRegexp, SkipRegexpFlagUsage) + + return &analysis.Analyzer{ + Name: "testpackage", + Doc: "linter that makes you use a separate _test package", + Flags: fs, + Run: func(pass *analysis.Pass) (interface{}, error) { + skipFile, err := regexp.Compile(skipFileRegexp) + if err != nil { + return nil, err + } + + for _, f := range pass.Files { + fileName := pass.Fset.Position(f.Pos()).Filename + if skipFile.MatchString(fileName) { + continue + } + + if strings.HasSuffix(fileName, "_test.go") { + packageName := f.Name.Name + if !strings.HasSuffix(packageName, "_test") { + pass.Reportf(f.Name.Pos(), "package should be `%s_test` instead of `%s`", packageName, packageName) + } + } + } + + return nil, nil + }, + } +} diff --git a/vendor/github.com/matoous/godox/.gitignore b/vendor/github.com/matoous/godox/.gitignore new file mode 100644 index 000000000..30d94b102 --- /dev/null +++ b/vendor/github.com/matoous/godox/.gitignore @@ -0,0 +1,19 @@ +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib +.idea + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 +.glide/ + +.vscode/ +debug +debug.test diff --git a/vendor/github.com/matoous/godox/.golangci.yml b/vendor/github.com/matoous/godox/.golangci.yml new file mode 100644 index 000000000..3f0fcdb19 --- /dev/null +++ b/vendor/github.com/matoous/godox/.golangci.yml @@ -0,0 +1,71 @@ +linters-settings: + depguard: + list-type: blacklist + include-go-root: true + packages: + # we are using "github.com/json-iterator/go" instead of json encoder from stdlib + - "encoding/json" + dupl: + threshold: 100 + gocritic: + # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint` run to see all tags and checks. + # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags". + enabled-tags: + - performance + - diagnostic + - style + disabled-checks: + - emptyStringTest + - unnamedResult # it is experimental currently and doesn't handle typed channels correctly + gocyclo: + min-complexity: 14 # TODO go lower + golint: + min-confidence: 0 + govet: + check-shadowing: true + goconst: + min-len: 2 + min-occurrences: 3 + goimports: + local-prefixes: gitlab.skypicker.com/search-team/gonuts/conveyance-store + lll: + line-length: 140 + maligned: + suggest-new: true + misspell: + locale: US + +linters: + enable-all: true + disable: + # prealloc is not recommended by `golangci-lint` developers. + - prealloc + - gochecknoglobals + +issues: + exclude-rules: + - path: _test\.go + linters: + - goconst + - dupl + + - path: fixtures + linters: + - gocritic + - varcheck + - deadcode + - unused + +run: + modules-download-mode: readonly + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" + format: tab + + # print lines of code with issue, default is true + print-issued-lines: true + + # print linter name in the end of issue text, default is true + print-linter-name: true diff --git a/vendor/github.com/matoous/godox/.revive.toml b/vendor/github.com/matoous/godox/.revive.toml new file mode 100644 index 000000000..db0e4edb6 --- /dev/null +++ b/vendor/github.com/matoous/godox/.revive.toml @@ -0,0 +1,135 @@ +ignoreGeneratedHeader = false +severity = "warning" + +# confidence <= 0.2 generate a lot of errors from package-comments rule. It marks files that do not contain +# package-level comments as a warning irrespective of existing package-level coment in one file. +confidence = 0.25 +errorCode = 1 +warningCode = 1 + +# Rules block. +# ⚠ Make sure to sort rules alpabetically for readability! ⚠ + +# argument-limit rule is setting up a maximum number of parameters that can be passed to the functions/methods. +[rule.argument-limit] + arguments = [5] + +# atomic rule checks for commonly mistaken usages of the sync/atomic package. +[rule.atomic] + +# blank-imports rule disallows blank imports. +[rule.blank-imports] + +# bool-literal-in-expr suggests removing boolean literals from logic expressions like `bar == true`, `arg == false`, +# `r != true`, `false && boolExpr` and `boolExpr || true`. +[rule.bool-literal-in-expr] + +# constant-logical-expr rule warns on constant logical expressions, like `name == name`. +[rule.constant-logical-expr] + +# context-as-argument rule makes sure that context.Context is the first argument of a function. +[rule.context-as-argument] + +# context-keys-type rule disallows the usage of basic types in context.WithValue +[rule.context-keys-type] + +# confusing-naming rule warns on methods with names that differ only by capitalization. +[rule.confusing-naming] + +# confusing-results rule suggests to name potentially confusing function results. +[rule.confusing-results] + +# cyclomatic rule sets restriction for maximum Cyclomatic complexity. +[rule.cyclomatic] + arguments = [15] + +# deep-exit rule looks for program exits in funcs other than `main()` or `init()`. +[rule.deep-exit] + +# dot-imports rule forbids `.` imports. +[rule.dot-imports] + +# empty-block warns on empty code blocks. +[rule.empty-block] + +# error-return rule ensure that the error return parameter is the last. +[rule.error-return] + +# error-strings rule ensure conventions around error strings. +[rule.error-strings] + +# error-naming rule ensure naming of error variables (has `Err` or `err` prefix). +[rule.error-naming] + +# errorf rule warns on usage errors.New(fmt.Sprintf()) instead of fmt.Errorf() +[rule.errorf] + +# exported rule ensure naming and commenting conventions on exported symbols. +[rule.exported] + +# flag-parameter rule warns on boolean parameters that create a control coupling. +[rule.flag-parameter] + +# get-return rule warns on getters that do not yield any result. +[rule.get-return] + +# if-return rule warns redundant if when returning an error. +[rule.if-return] + +# increment-decrement rule forces to use `i++` and `i--` instead of `i += 1` and `i -= 1`. +[rule.increment-decrement] + +# indent-error-flow rule prevents redundant else statements. +[rule.indent-error-flow] + +# modifies-value-receiver warns on assignments to value-passed method receivers. +[rule.modifies-value-receiver] + +# package-comments rule ensures package commenting conventions. +[rule.package-comments] + +# range rule prevents redundant variables when iterating over a collection. +[rule.range] + +# range-val-in-closure warns if range value is used in a closure dispatched as goroutine. +[rule.range-val-in-closure] + +# receiver-naming ensures conventions around the naming of receivers. +[rule.receiver-naming] + +# redefines-builtin-id warns on redefinitions of built-in (constants, variables, function and types) identifiers, +# like `true := "false"` etc. +[rule.redefines-builtin-id] + +# rule.superfluous-else prevents redundant else statements (extends indent-error-flow). Checks for `if-then-else`where +# the then block ends with branching statement like `continue`, `break`, or `goto`. +[rule.superfluous-else] + +# rule.struct-tag checks common struct tags like `json`, `xml`, `yaml`. +[rule.struct-tag] + +# time-naming rule conventions around the naming of time variables. Like not to use unit suffixes (sec, min etc.) in +# naming variables of type `time.Time` or `time.Duration`. +[rule.time-naming] + +# unexported-return rule warns when a public return is from unexported type. +[rule.unexported-return] + +# unnecessary-stmt suggests removing or simplifying unnecessary statements like breaks at the end of cases or return at +# the end of bodies of functions returning nothing. +[rule.unnecessary-stmt] + +# unreachable-code rule warns on the unreachable code. +[rule.unreachable-code] + +# unused-parameter rule suggests to rename or remove unused function parameters. +[rule.unused-parameter] + +# var-declaration rule reduces redundancies around variable declaration. +[rule.var-declaration] + +# var-naming checks naming rules. +[rule.var-naming] + +# waitgroup-by-value rule warns on functions taking `sync.WaitGroup` as a by-value parameter. +[rule.waitgroup-by-value] diff --git a/vendor/github.com/matoous/godox/LICENSE b/vendor/github.com/matoous/godox/LICENSE new file mode 100644 index 000000000..49e1b1e3a --- /dev/null +++ b/vendor/github.com/matoous/godox/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Matous Dzivjak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/matoous/godox/README.md b/vendor/github.com/matoous/godox/README.md new file mode 100644 index 000000000..6d5f54fc6 --- /dev/null +++ b/vendor/github.com/matoous/godox/README.md @@ -0,0 +1,18 @@ +GoDoX +=== + +[![Tests](https://github.com/matoous/godox/workflows/.github/workflows/test.yml/badge.svg)](https://github.com/matoous/godox/actions) +[![Lint](https://github.com/matoous/godox/workflows/.github/workflows/lint.yml/badge.svg)](https://github.com/matoous/godox/actions) +[![GoDoc](https://godoc.org/github.com/matoous/godox?status.svg)](https://godoc.org/github.com/matoous/godox) +[![Go Report Card](https://goreportcard.com/badge/github.com/matoous/godox)](https://goreportcard.com/report/github.com/matoous/godox) +[![GitHub issues](https://img.shields.io/github/issues/matoous/godox.svg)](https://github.com/matoous/godox/issues) +[![License](https://img.shields.io/badge/license-MIT%20License-blue.svg)](https://github.com/matoous/godox/LICENSE) + +GoDoX extracts comments from Go code based on keywords. This repository is fork of https://github.com/766b/godox +but a lot of code has changed, this repository is updated and the code was adjusted for better integration with +https://github.com/golangci/golangci-lint. + +Installation +--- + + go get github.com/matoous/godox diff --git a/vendor/github.com/matoous/godox/go.mod b/vendor/github.com/matoous/godox/go.mod new file mode 100644 index 000000000..69b34f0e9 --- /dev/null +++ b/vendor/github.com/matoous/godox/go.mod @@ -0,0 +1,5 @@ +module github.com/matoous/godox + +go 1.13 + +require golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578 diff --git a/vendor/github.com/matoous/godox/go.sum b/vendor/github.com/matoous/godox/go.sum new file mode 100644 index 000000000..970cb25dd --- /dev/null +++ b/vendor/github.com/matoous/godox/go.sum @@ -0,0 +1,8 @@ +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578 h1:f0Gfd654rnnfXT1+BK1YHPTS1qQdKrPIaGQwWxNE44k= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/matoous/godox/godox.go b/vendor/github.com/matoous/godox/godox.go new file mode 100644 index 000000000..13f3f3bec --- /dev/null +++ b/vendor/github.com/matoous/godox/godox.go @@ -0,0 +1,84 @@ +package godox + +import ( + "bufio" + "bytes" + "fmt" + "go/ast" + "go/token" + "path/filepath" + "strings" +) + +var ( + defaultKeywords = []string{"TODO", "BUG", "FIXME"} +) + +// Message contains a message and position +type Message struct { + Pos token.Position + Message string +} + +func getMessages(c *ast.Comment, fset *token.FileSet, keywords []string) []Message { + commentText := c.Text + switch commentText[1] { + case '/': + commentText = commentText[2:] + if len(commentText) > 0 && commentText[0] == ' ' { + commentText = commentText[1:] + } + case '*': + commentText = commentText[2 : len(commentText)-2] + } + + b := bufio.NewReader(bytes.NewBufferString(commentText)) + var comments []Message + + for lineNum := 0; ; lineNum++ { + line, _, err := b.ReadLine() + if err != nil { + break + } + sComment := bytes.TrimSpace(line) + if len(sComment) < 4 { + continue + } + for _, kw := range keywords { + if bytes.EqualFold([]byte(kw), sComment[0:len(kw)]) { + pos := fset.Position(c.Pos()) + // trim the comment + if len(sComment) > 40 { + sComment = []byte(fmt.Sprintf("%s...", sComment[:40])) + } + comments = append(comments, Message{ + Pos: pos, + Message: fmt.Sprintf( + "%s:%d: Line contains %s: \"%s\"", + filepath.Join(pos.Filename), + pos.Line+lineNum, + strings.Join(keywords, "/"), + sComment, + ), + }) + break + } + } + } + return comments +} + +// Run runs the godox linter on given file. +// Godox searches for comments starting with given keywords and reports them. +func Run(file *ast.File, fset *token.FileSet, keywords ...string) []Message { + if len(keywords) == 0 { + keywords = defaultKeywords + } + var messages []Message + for _, c := range file.Comments { + for _, ci := range c.List { + messages = append(messages, getMessages(ci, fset, keywords)...) + } + } + return messages +} diff --git a/vendor/github.com/mattn/go-colorable/.travis.yml b/vendor/github.com/mattn/go-colorable/.travis.yml new file mode 100644 index 000000000..98db8f060 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - tip + +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -repotoken xnXqRGwgW3SXIguzxf90ZSK1GPYZPaGrw diff --git a/vendor/github.com/mattn/go-colorable/LICENSE b/vendor/github.com/mattn/go-colorable/LICENSE new file mode 100644 index 000000000..91b5cef30 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Yasuhiro Matsumoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md new file mode 100644 index 000000000..56729a92c --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -0,0 +1,48 @@ +# go-colorable + +[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) +[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) +[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master) +[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) + +Colorable writer for windows. + +For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) +This package is possible to handle escape sequence for ansi color on windows. + +## Too Bad! + +![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png) + + +## So Good! + +![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png) + +## Usage + +```go +logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) +logrus.SetOutput(colorable.NewColorableStdout()) + +logrus.Info("succeeded") +logrus.Warn("not correct") +logrus.Error("something error") +logrus.Fatal("panic") +``` + +You can compile above code on non-windows OSs. + +## Installation + +``` +$ go get github.com/mattn/go-colorable +``` + +# License + +MIT + +# Author + +Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go new file mode 100644 index 000000000..0b0aef837 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go @@ -0,0 +1,29 @@ +// +build appengine + +package colorable + +import ( + "io" + "os" + + _ "github.com/mattn/go-isatty" +) + +// NewColorable returns new instance of Writer which handles escape sequence. +func NewColorable(file *os.File) io.Writer { + if file == nil { + panic("nil passed instead of *os.File to NewColorable()") + } + + return file +} + +// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. +func NewColorableStdout() io.Writer { + return os.Stdout +} + +// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. +func NewColorableStderr() io.Writer { + return os.Stderr +} diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go new file mode 100644 index 000000000..3fb771dcc --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/colorable_others.go @@ -0,0 +1,30 @@ +// +build !windows +// +build !appengine + +package colorable + +import ( + "io" + "os" + + _ "github.com/mattn/go-isatty" +) + +// NewColorable returns new instance of Writer which handles escape sequence. +func NewColorable(file *os.File) io.Writer { + if file == nil { + panic("nil passed instead of *os.File to NewColorable()") + } + + return file +} + +// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. +func NewColorableStdout() io.Writer { + return os.Stdout +} + +// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. +func NewColorableStderr() io.Writer { + return os.Stderr +} diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go new file mode 100644 index 000000000..1bd628f25 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -0,0 +1,1005 @@ +// +build windows +// +build !appengine + +package colorable + +import ( + "bytes" + "io" + "math" + "os" + "strconv" + "strings" + "syscall" + "unsafe" + + "github.com/mattn/go-isatty" +) + +const ( + foregroundBlue = 0x1 + foregroundGreen = 0x2 + foregroundRed = 0x4 + foregroundIntensity = 0x8 + foregroundMask = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity) + backgroundBlue = 0x10 + backgroundGreen = 0x20 + backgroundRed = 0x40 + backgroundIntensity = 0x80 + backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) +) + +const ( + genericRead = 0x80000000 + genericWrite = 0x40000000 +) + +const ( + consoleTextmodeBuffer = 0x1 +) + +type wchar uint16 +type short int16 +type dword uint32 +type word uint16 + +type coord struct { + x short + y short +} + +type smallRect struct { + left short + top short + right short + bottom short +} + +type consoleScreenBufferInfo struct { + size coord + cursorPosition coord + attributes word + window smallRect + maximumWindowSize coord +} + +type consoleCursorInfo struct { + size dword + visible int32 +} + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") + procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute") + procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") + procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") + procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") + procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo") + procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo") + procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW") + procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer") +) + +// Writer provides colorable Writer to the console +type Writer struct { + out io.Writer + handle syscall.Handle + althandle syscall.Handle + oldattr word + oldpos coord + rest bytes.Buffer +} + +// NewColorable returns new instance of Writer which handles escape sequence from File. +func NewColorable(file *os.File) io.Writer { + if file == nil { + panic("nil passed instead of *os.File to NewColorable()") + } + + if isatty.IsTerminal(file.Fd()) { + var csbi consoleScreenBufferInfo + handle := syscall.Handle(file.Fd()) + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}} + } + return file +} + +// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. +func NewColorableStdout() io.Writer { + return NewColorable(os.Stdout) +} + +// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. +func NewColorableStderr() io.Writer { + return NewColorable(os.Stderr) +} + +var color256 = map[int]int{ + 0: 0x000000, + 1: 0x800000, + 2: 0x008000, + 3: 0x808000, + 4: 0x000080, + 5: 0x800080, + 6: 0x008080, + 7: 0xc0c0c0, + 8: 0x808080, + 9: 0xff0000, + 10: 0x00ff00, + 11: 0xffff00, + 12: 0x0000ff, + 13: 0xff00ff, + 14: 0x00ffff, + 15: 0xffffff, + 16: 0x000000, + 17: 0x00005f, + 18: 0x000087, + 19: 0x0000af, + 20: 0x0000d7, + 21: 0x0000ff, + 22: 0x005f00, + 23: 0x005f5f, + 24: 0x005f87, + 25: 0x005faf, + 26: 0x005fd7, + 27: 0x005fff, + 28: 0x008700, + 29: 0x00875f, + 30: 0x008787, + 31: 0x0087af, + 32: 0x0087d7, + 33: 0x0087ff, + 34: 0x00af00, + 35: 0x00af5f, + 36: 0x00af87, + 37: 0x00afaf, + 38: 0x00afd7, + 39: 0x00afff, + 40: 0x00d700, + 41: 0x00d75f, + 42: 0x00d787, + 43: 0x00d7af, + 44: 0x00d7d7, + 45: 0x00d7ff, + 46: 0x00ff00, + 47: 0x00ff5f, + 48: 0x00ff87, + 49: 0x00ffaf, + 50: 0x00ffd7, + 51: 0x00ffff, + 52: 0x5f0000, + 53: 0x5f005f, + 54: 0x5f0087, + 55: 0x5f00af, + 56: 0x5f00d7, + 57: 0x5f00ff, + 58: 0x5f5f00, + 59: 0x5f5f5f, + 60: 0x5f5f87, + 61: 0x5f5faf, + 62: 0x5f5fd7, + 63: 0x5f5fff, + 64: 0x5f8700, + 65: 0x5f875f, + 66: 0x5f8787, + 67: 0x5f87af, + 68: 0x5f87d7, + 69: 0x5f87ff, + 70: 0x5faf00, + 71: 0x5faf5f, + 72: 0x5faf87, + 73: 0x5fafaf, + 74: 0x5fafd7, + 75: 0x5fafff, + 76: 0x5fd700, + 77: 0x5fd75f, + 78: 0x5fd787, + 79: 0x5fd7af, + 80: 0x5fd7d7, + 81: 0x5fd7ff, + 82: 0x5fff00, + 83: 0x5fff5f, + 84: 0x5fff87, + 85: 0x5fffaf, + 86: 0x5fffd7, + 87: 0x5fffff, + 88: 0x870000, + 89: 0x87005f, + 90: 0x870087, + 91: 0x8700af, + 92: 0x8700d7, + 93: 0x8700ff, + 94: 0x875f00, + 95: 0x875f5f, + 96: 0x875f87, + 97: 0x875faf, + 98: 0x875fd7, + 99: 0x875fff, + 100: 0x878700, + 101: 0x87875f, + 102: 0x878787, + 103: 0x8787af, + 104: 0x8787d7, + 105: 0x8787ff, + 106: 0x87af00, + 107: 0x87af5f, + 108: 0x87af87, + 109: 0x87afaf, + 110: 0x87afd7, + 111: 0x87afff, + 112: 0x87d700, + 113: 0x87d75f, + 114: 0x87d787, + 115: 0x87d7af, + 116: 0x87d7d7, + 117: 0x87d7ff, + 118: 0x87ff00, + 119: 0x87ff5f, + 120: 0x87ff87, + 121: 0x87ffaf, + 122: 0x87ffd7, + 123: 0x87ffff, + 124: 0xaf0000, + 125: 0xaf005f, + 126: 0xaf0087, + 127: 0xaf00af, + 128: 0xaf00d7, + 129: 0xaf00ff, + 130: 0xaf5f00, + 131: 0xaf5f5f, + 132: 0xaf5f87, + 133: 0xaf5faf, + 134: 0xaf5fd7, + 135: 0xaf5fff, + 136: 0xaf8700, + 137: 0xaf875f, + 138: 0xaf8787, + 139: 0xaf87af, + 140: 0xaf87d7, + 141: 0xaf87ff, + 142: 0xafaf00, + 143: 0xafaf5f, + 144: 0xafaf87, + 145: 0xafafaf, + 146: 0xafafd7, + 147: 0xafafff, + 148: 0xafd700, + 149: 0xafd75f, + 150: 0xafd787, + 151: 0xafd7af, + 152: 0xafd7d7, + 153: 0xafd7ff, + 154: 0xafff00, + 155: 0xafff5f, + 156: 0xafff87, + 157: 0xafffaf, + 158: 0xafffd7, + 159: 0xafffff, + 160: 0xd70000, + 161: 0xd7005f, + 162: 0xd70087, + 163: 0xd700af, + 164: 0xd700d7, + 165: 0xd700ff, + 166: 0xd75f00, + 167: 0xd75f5f, + 168: 0xd75f87, + 169: 0xd75faf, + 170: 0xd75fd7, + 171: 0xd75fff, + 172: 0xd78700, + 173: 0xd7875f, + 174: 0xd78787, + 175: 0xd787af, + 176: 0xd787d7, + 177: 0xd787ff, + 178: 0xd7af00, + 179: 0xd7af5f, + 180: 0xd7af87, + 181: 0xd7afaf, + 182: 0xd7afd7, + 183: 0xd7afff, + 184: 0xd7d700, + 185: 0xd7d75f, + 186: 0xd7d787, + 187: 0xd7d7af, + 188: 0xd7d7d7, + 189: 0xd7d7ff, + 190: 0xd7ff00, + 191: 0xd7ff5f, + 192: 0xd7ff87, + 193: 0xd7ffaf, + 194: 0xd7ffd7, + 195: 0xd7ffff, + 196: 0xff0000, + 197: 0xff005f, + 198: 0xff0087, + 199: 0xff00af, + 200: 0xff00d7, + 201: 0xff00ff, + 202: 0xff5f00, + 203: 0xff5f5f, + 204: 0xff5f87, + 205: 0xff5faf, + 206: 0xff5fd7, + 207: 0xff5fff, + 208: 0xff8700, + 209: 0xff875f, + 210: 0xff8787, + 211: 0xff87af, + 212: 0xff87d7, + 213: 0xff87ff, + 214: 0xffaf00, + 215: 0xffaf5f, + 216: 0xffaf87, + 217: 0xffafaf, + 218: 0xffafd7, + 219: 0xffafff, + 220: 0xffd700, + 221: 0xffd75f, + 222: 0xffd787, + 223: 0xffd7af, + 224: 0xffd7d7, + 225: 0xffd7ff, + 226: 0xffff00, + 227: 0xffff5f, + 228: 0xffff87, + 229: 0xffffaf, + 230: 0xffffd7, + 231: 0xffffff, + 232: 0x080808, + 233: 0x121212, + 234: 0x1c1c1c, + 235: 0x262626, + 236: 0x303030, + 237: 0x3a3a3a, + 238: 0x444444, + 239: 0x4e4e4e, + 240: 0x585858, + 241: 0x626262, + 242: 0x6c6c6c, + 243: 0x767676, + 244: 0x808080, + 245: 0x8a8a8a, + 246: 0x949494, + 247: 0x9e9e9e, + 248: 0xa8a8a8, + 249: 0xb2b2b2, + 250: 0xbcbcbc, + 251: 0xc6c6c6, + 252: 0xd0d0d0, + 253: 0xdadada, + 254: 0xe4e4e4, + 255: 0xeeeeee, +} + +// `\033]0;TITLESTR\007` +func doTitleSequence(er *bytes.Reader) error { + var c byte + var err error + + c, err = er.ReadByte() + if err != nil { + return err + } + if c != '0' && c != '2' { + return nil + } + c, err = er.ReadByte() + if err != nil { + return err + } + if c != ';' { + return nil + } + title := make([]byte, 0, 80) + for { + c, err = er.ReadByte() + if err != nil { + return err + } + if c == 0x07 || c == '\n' { + break + } + title = append(title, c) + } + if len(title) > 0 { + title8, err := syscall.UTF16PtrFromString(string(title)) + if err == nil { + procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8))) + } + } + return nil +} + +// returns Atoi(s) unless s == "" in which case it returns def +func atoiWithDefault(s string, def int) (int, error) { + if s == "" { + return def, nil + } + return strconv.Atoi(s) +} + +// Write writes data on console +func (w *Writer) Write(data []byte) (n int, err error) { + var csbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) + + handle := w.handle + + var er *bytes.Reader + if w.rest.Len() > 0 { + var rest bytes.Buffer + w.rest.WriteTo(&rest) + w.rest.Reset() + rest.Write(data) + er = bytes.NewReader(rest.Bytes()) + } else { + er = bytes.NewReader(data) + } + var bw [1]byte +loop: + for { + c1, err := er.ReadByte() + if err != nil { + break loop + } + if c1 != 0x1b { + bw[0] = c1 + w.out.Write(bw[:]) + continue + } + c2, err := er.ReadByte() + if err != nil { + break loop + } + + switch c2 { + case '>': + continue + case ']': + w.rest.WriteByte(c1) + w.rest.WriteByte(c2) + er.WriteTo(&w.rest) + if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 { + break loop + } + er = bytes.NewReader(w.rest.Bytes()[2:]) + err := doTitleSequence(er) + if err != nil { + break loop + } + w.rest.Reset() + continue + // https://github.com/mattn/go-colorable/issues/27 + case '7': + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + w.oldpos = csbi.cursorPosition + continue + case '8': + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) + continue + case 0x5b: + // execute part after switch + default: + continue + } + + w.rest.WriteByte(c1) + w.rest.WriteByte(c2) + er.WriteTo(&w.rest) + + var buf bytes.Buffer + var m byte + for i, c := range w.rest.Bytes()[2:] { + if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { + m = c + er = bytes.NewReader(w.rest.Bytes()[2+i+1:]) + w.rest.Reset() + break + } + buf.Write([]byte(string(c))) + } + if m == 0 { + break loop + } + + switch m { + case 'A': + n, err = atoiWithDefault(buf.String(), 1) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.y -= short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'B': + n, err = atoiWithDefault(buf.String(), 1) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.y += short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'C': + n, err = atoiWithDefault(buf.String(), 1) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x += short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'D': + n, err = atoiWithDefault(buf.String(), 1) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x -= short(n) + if csbi.cursorPosition.x < 0 { + csbi.cursorPosition.x = 0 + } + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'E': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x = 0 + csbi.cursorPosition.y += short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'F': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x = 0 + csbi.cursorPosition.y -= short(n) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'G': + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + if n < 1 { + n = 1 + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + csbi.cursorPosition.x = short(n - 1) + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'H', 'f': + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + if buf.Len() > 0 { + token := strings.Split(buf.String(), ";") + switch len(token) { + case 1: + n1, err := strconv.Atoi(token[0]) + if err != nil { + continue + } + csbi.cursorPosition.y = short(n1 - 1) + case 2: + n1, err := strconv.Atoi(token[0]) + if err != nil { + continue + } + n2, err := strconv.Atoi(token[1]) + if err != nil { + continue + } + csbi.cursorPosition.x = short(n2 - 1) + csbi.cursorPosition.y = short(n1 - 1) + } + } else { + csbi.cursorPosition.y = 0 + } + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + case 'J': + n := 0 + if buf.Len() > 0 { + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + } + var count, written dword + var cursor coord + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + switch n { + case 0: + cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} + count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x) + case 1: + cursor = coord{x: csbi.window.left, y: csbi.window.top} + count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x) + case 2: + cursor = coord{x: csbi.window.left, y: csbi.window.top} + count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x) + } + procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + case 'K': + n := 0 + if buf.Len() > 0 { + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + var cursor coord + var count, written dword + switch n { + case 0: + cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} + count = dword(csbi.size.x - csbi.cursorPosition.x) + case 1: + cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y} + count = dword(csbi.size.x - csbi.cursorPosition.x) + case 2: + cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y} + count = dword(csbi.size.x) + } + procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + case 'X': + n := 0 + if buf.Len() > 0 { + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + var cursor coord + var written dword + cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} + procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + case 'm': + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + attr := csbi.attributes + cs := buf.String() + if cs == "" { + procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr)) + continue + } + token := strings.Split(cs, ";") + for i := 0; i < len(token); i++ { + ns := token[i] + if n, err = strconv.Atoi(ns); err == nil { + switch { + case n == 0 || n == 100: + attr = w.oldattr + case 1 <= n && n <= 5: + attr |= foregroundIntensity + case n == 7: + attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) + case n == 22 || n == 25: + attr |= foregroundIntensity + case n == 27: + attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) + case 30 <= n && n <= 37: + attr &= backgroundMask + if (n-30)&1 != 0 { + attr |= foregroundRed + } + if (n-30)&2 != 0 { + attr |= foregroundGreen + } + if (n-30)&4 != 0 { + attr |= foregroundBlue + } + case n == 38: // set foreground color. + if i < len(token)-2 && (token[i+1] == "5" || token[i+1] == "05") { + if n256, err := strconv.Atoi(token[i+2]); err == nil { + if n256foreAttr == nil { + n256setup() + } + attr &= backgroundMask + attr |= n256foreAttr[n256] + i += 2 + } + } else if len(token) == 5 && token[i+1] == "2" { + var r, g, b int + r, _ = strconv.Atoi(token[i+2]) + g, _ = strconv.Atoi(token[i+3]) + b, _ = strconv.Atoi(token[i+4]) + i += 4 + if r > 127 { + attr |= foregroundRed + } + if g > 127 { + attr |= foregroundGreen + } + if b > 127 { + attr |= foregroundBlue + } + } else { + attr = attr & (w.oldattr & backgroundMask) + } + case n == 39: // reset foreground color. + attr &= backgroundMask + attr |= w.oldattr & foregroundMask + case 40 <= n && n <= 47: + attr &= foregroundMask + if (n-40)&1 != 0 { + attr |= backgroundRed + } + if (n-40)&2 != 0 { + attr |= backgroundGreen + } + if (n-40)&4 != 0 { + attr |= backgroundBlue + } + case n == 48: // set background color. + if i < len(token)-2 && token[i+1] == "5" { + if n256, err := strconv.Atoi(token[i+2]); err == nil { + if n256backAttr == nil { + n256setup() + } + attr &= foregroundMask + attr |= n256backAttr[n256] + i += 2 + } + } else if len(token) == 5 && token[i+1] == "2" { + var r, g, b int + r, _ = strconv.Atoi(token[i+2]) + g, _ = strconv.Atoi(token[i+3]) + b, _ = strconv.Atoi(token[i+4]) + i += 4 + if r > 127 { + attr |= backgroundRed + } + if g > 127 { + attr |= backgroundGreen + } + if b > 127 { + attr |= backgroundBlue + } + } else { + attr = attr & (w.oldattr & foregroundMask) + } + case n == 49: // reset foreground color. + attr &= foregroundMask + attr |= w.oldattr & backgroundMask + case 90 <= n && n <= 97: + attr = (attr & backgroundMask) + attr |= foregroundIntensity + if (n-90)&1 != 0 { + attr |= foregroundRed + } + if (n-90)&2 != 0 { + attr |= foregroundGreen + } + if (n-90)&4 != 0 { + attr |= foregroundBlue + } + case 100 <= n && n <= 107: + attr = (attr & foregroundMask) + attr |= backgroundIntensity + if (n-100)&1 != 0 { + attr |= backgroundRed + } + if (n-100)&2 != 0 { + attr |= backgroundGreen + } + if (n-100)&4 != 0 { + attr |= backgroundBlue + } + } + procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr)) + } + } + case 'h': + var ci consoleCursorInfo + cs := buf.String() + if cs == "5>" { + procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + ci.visible = 0 + procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + } else if cs == "?25" { + procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + ci.visible = 1 + procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + } else if cs == "?1049" { + if w.althandle == 0 { + h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0) + w.althandle = syscall.Handle(h) + if w.althandle != 0 { + handle = w.althandle + } + } + } + case 'l': + var ci consoleCursorInfo + cs := buf.String() + if cs == "5>" { + procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + ci.visible = 1 + procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + } else if cs == "?25" { + procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + ci.visible = 0 + procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + } else if cs == "?1049" { + if w.althandle != 0 { + syscall.CloseHandle(w.althandle) + w.althandle = 0 + handle = w.handle + } + } + case 's': + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + w.oldpos = csbi.cursorPosition + case 'u': + procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) + } + } + + return len(data), nil +} + +type consoleColor struct { + rgb int + red bool + green bool + blue bool + intensity bool +} + +func (c consoleColor) foregroundAttr() (attr word) { + if c.red { + attr |= foregroundRed + } + if c.green { + attr |= foregroundGreen + } + if c.blue { + attr |= foregroundBlue + } + if c.intensity { + attr |= foregroundIntensity + } + return +} + +func (c consoleColor) backgroundAttr() (attr word) { + if c.red { + attr |= backgroundRed + } + if c.green { + attr |= backgroundGreen + } + if c.blue { + attr |= backgroundBlue + } + if c.intensity { + attr |= backgroundIntensity + } + return +} + +var color16 = []consoleColor{ + {0x000000, false, false, false, false}, + {0x000080, false, false, true, false}, + {0x008000, false, true, false, false}, + {0x008080, false, true, true, false}, + {0x800000, true, false, false, false}, + {0x800080, true, false, true, false}, + {0x808000, true, true, false, false}, + {0xc0c0c0, true, true, true, false}, + {0x808080, false, false, false, true}, + {0x0000ff, false, false, true, true}, + {0x00ff00, false, true, false, true}, + {0x00ffff, false, true, true, true}, + {0xff0000, true, false, false, true}, + {0xff00ff, true, false, true, true}, + {0xffff00, true, true, false, true}, + {0xffffff, true, true, true, true}, +} + +type hsv struct { + h, s, v float32 +} + +func (a hsv) dist(b hsv) float32 { + dh := a.h - b.h + switch { + case dh > 0.5: + dh = 1 - dh + case dh < -0.5: + dh = -1 - dh + } + ds := a.s - b.s + dv := a.v - b.v + return float32(math.Sqrt(float64(dh*dh + ds*ds + dv*dv))) +} + +func toHSV(rgb int) hsv { + r, g, b := float32((rgb&0xFF0000)>>16)/256.0, + float32((rgb&0x00FF00)>>8)/256.0, + float32(rgb&0x0000FF)/256.0 + min, max := minmax3f(r, g, b) + h := max - min + if h > 0 { + if max == r { + h = (g - b) / h + if h < 0 { + h += 6 + } + } else if max == g { + h = 2 + (b-r)/h + } else { + h = 4 + (r-g)/h + } + } + h /= 6.0 + s := max - min + if max != 0 { + s /= max + } + v := max + return hsv{h: h, s: s, v: v} +} + +type hsvTable []hsv + +func toHSVTable(rgbTable []consoleColor) hsvTable { + t := make(hsvTable, len(rgbTable)) + for i, c := range rgbTable { + t[i] = toHSV(c.rgb) + } + return t +} + +func (t hsvTable) find(rgb int) consoleColor { + hsv := toHSV(rgb) + n := 7 + l := float32(5.0) + for i, p := range t { + d := hsv.dist(p) + if d < l { + l, n = d, i + } + } + return color16[n] +} + +func minmax3f(a, b, c float32) (min, max float32) { + if a < b { + if b < c { + return a, c + } else if a < c { + return a, b + } else { + return c, b + } + } else { + if a < c { + return b, c + } else if b < c { + return b, a + } else { + return c, a + } + } +} + +var n256foreAttr []word +var n256backAttr []word + +func n256setup() { + n256foreAttr = make([]word, 256) + n256backAttr = make([]word, 256) + t := toHSVTable(color16) + for i, rgb := range color256 { + c := t.find(rgb) + n256foreAttr[i] = c.foregroundAttr() + n256backAttr[i] = c.backgroundAttr() + } +} diff --git a/vendor/github.com/mattn/go-colorable/go.mod b/vendor/github.com/mattn/go-colorable/go.mod new file mode 100644 index 000000000..ef3ca9d4c --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/go.mod @@ -0,0 +1,3 @@ +module github.com/mattn/go-colorable + +require github.com/mattn/go-isatty v0.0.8 diff --git a/vendor/github.com/mattn/go-colorable/go.sum b/vendor/github.com/mattn/go-colorable/go.sum new file mode 100644 index 000000000..2c12960ec --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/go.sum @@ -0,0 +1,4 @@ +github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go new file mode 100644 index 000000000..95f2c6be2 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/noncolorable.go @@ -0,0 +1,55 @@ +package colorable + +import ( + "bytes" + "io" +) + +// NonColorable holds writer but removes escape sequence. +type NonColorable struct { + out io.Writer +} + +// NewNonColorable returns new instance of Writer which removes escape sequence from Writer. +func NewNonColorable(w io.Writer) io.Writer { + return &NonColorable{out: w} +} + +// Write writes data on console +func (w *NonColorable) Write(data []byte) (n int, err error) { + er := bytes.NewReader(data) + var bw [1]byte +loop: + for { + c1, err := er.ReadByte() + if err != nil { + break loop + } + if c1 != 0x1b { + bw[0] = c1 + w.out.Write(bw[:]) + continue + } + c2, err := er.ReadByte() + if err != nil { + break loop + } + if c2 != 0x5b { + continue + } + + var buf bytes.Buffer + for { + c, err := er.ReadByte() + if err != nil { + break loop + } + if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { + break + } + buf.Write([]byte(string(c))) + } + } + + return len(data), nil +} diff --git a/vendor/github.com/mattn/go-isatty/.travis.yml b/vendor/github.com/mattn/go-isatty/.travis.yml new file mode 100644 index 000000000..5597e026d --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/.travis.yml @@ -0,0 +1,13 @@ +language: go +go: + - tip + +os: + - linux + - osx + +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -repotoken 3gHdORO5k5ziZcWMBxnd9LrMZaJs8m9x5 diff --git a/vendor/github.com/mattn/go-isatty/LICENSE b/vendor/github.com/mattn/go-isatty/LICENSE new file mode 100644 index 000000000..65dc692b6 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) Yasuhiro MATSUMOTO + +MIT License (Expat) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/mattn/go-isatty/README.md b/vendor/github.com/mattn/go-isatty/README.md new file mode 100644 index 000000000..1e69004bb --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/README.md @@ -0,0 +1,50 @@ +# go-isatty + +[![Godoc Reference](https://godoc.org/github.com/mattn/go-isatty?status.svg)](http://godoc.org/github.com/mattn/go-isatty) +[![Build Status](https://travis-ci.org/mattn/go-isatty.svg?branch=master)](https://travis-ci.org/mattn/go-isatty) +[![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master) +[![Go Report Card](https://goreportcard.com/badge/mattn/go-isatty)](https://goreportcard.com/report/mattn/go-isatty) + +isatty for golang + +## Usage + +```go +package main + +import ( + "fmt" + "github.com/mattn/go-isatty" + "os" +) + +func main() { + if isatty.IsTerminal(os.Stdout.Fd()) { + fmt.Println("Is Terminal") + } else if isatty.IsCygwinTerminal(os.Stdout.Fd()) { + fmt.Println("Is Cygwin/MSYS2 Terminal") + } else { + fmt.Println("Is Not Terminal") + } +} +``` + +## Installation + +``` +$ go get github.com/mattn/go-isatty +``` + +## License + +MIT + +## Author + +Yasuhiro Matsumoto (a.k.a mattn) + +## Thanks + +* k-takata: base idea for IsCygwinTerminal + + https://github.com/k-takata/go-iscygpty diff --git a/vendor/github.com/mattn/go-isatty/doc.go b/vendor/github.com/mattn/go-isatty/doc.go new file mode 100644 index 000000000..17d4f90eb --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/doc.go @@ -0,0 +1,2 @@ +// Package isatty implements interface to isatty +package isatty diff --git a/vendor/github.com/mattn/go-isatty/go.mod b/vendor/github.com/mattn/go-isatty/go.mod new file mode 100644 index 000000000..f310320c3 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/go.mod @@ -0,0 +1,3 @@ +module github.com/mattn/go-isatty + +require golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 diff --git a/vendor/github.com/mattn/go-isatty/go.sum b/vendor/github.com/mattn/go-isatty/go.sum new file mode 100644 index 000000000..426c8973c --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/vendor/github.com/mattn/go-isatty/isatty_android.go b/vendor/github.com/mattn/go-isatty/isatty_android.go new file mode 100644 index 000000000..d3567cb5b --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_android.go @@ -0,0 +1,23 @@ +// +build android + +package isatty + +import ( + "syscall" + "unsafe" +) + +const ioctlReadTermios = syscall.TCGETS + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} + +// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 +// terminal. This is also always false on this environment. +func IsCygwinTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go new file mode 100644 index 000000000..07e93039d --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -0,0 +1,24 @@ +// +build darwin freebsd openbsd netbsd dragonfly +// +build !appengine + +package isatty + +import ( + "syscall" + "unsafe" +) + +const ioctlReadTermios = syscall.TIOCGETA + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} + +// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 +// terminal. This is also always false on this environment. +func IsCygwinTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_others.go b/vendor/github.com/mattn/go-isatty/isatty_others.go new file mode 100644 index 000000000..ff714a376 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_others.go @@ -0,0 +1,15 @@ +// +build appengine js nacl + +package isatty + +// IsTerminal returns true if the file descriptor is terminal which +// is always false on js and appengine classic which is a sandboxed PaaS. +func IsTerminal(fd uintptr) bool { + return false +} + +// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2 +// terminal. This is also always false on this environment. +func IsCygwinTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go new file mode 100644 index 000000000..bdd5c79a0 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_solaris.go @@ -0,0 +1,22 @@ +// +build solaris +// +build !appengine + +package isatty + +import ( + "golang.org/x/sys/unix" +) + +// IsTerminal returns true if the given file descriptor is a terminal. +// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c +func IsTerminal(fd uintptr) bool { + var termio unix.Termio + err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) + return err == nil +} + +// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 +// terminal. This is also always false on this environment. +func IsCygwinTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go new file mode 100644 index 000000000..453b025d0 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go @@ -0,0 +1,19 @@ +// +build linux aix +// +build !appengine +// +build !android + +package isatty + +import "golang.org/x/sys/unix" + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + _, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) + return err == nil +} + +// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 +// terminal. This is also always false on this environment. +func IsCygwinTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go new file mode 100644 index 000000000..af51cbcaa --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go @@ -0,0 +1,94 @@ +// +build windows +// +build !appengine + +package isatty + +import ( + "strings" + "syscall" + "unicode/utf16" + "unsafe" +) + +const ( + fileNameInfo uintptr = 2 + fileTypePipe = 3 +) + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx") + procGetFileType = kernel32.NewProc("GetFileType") +) + +func init() { + // Check if GetFileInformationByHandleEx is available. + if procGetFileInformationByHandleEx.Find() != nil { + procGetFileInformationByHandleEx = nil + } +} + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var st uint32 + r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0) + return r != 0 && e == 0 +} + +// Check pipe name is used for cygwin/msys2 pty. +// Cygwin/MSYS2 PTY has a name like: +// \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master +func isCygwinPipeName(name string) bool { + token := strings.Split(name, "-") + if len(token) < 5 { + return false + } + + if token[0] != `\msys` && token[0] != `\cygwin` { + return false + } + + if token[1] == "" { + return false + } + + if !strings.HasPrefix(token[2], "pty") { + return false + } + + if token[3] != `from` && token[3] != `to` { + return false + } + + if token[4] != "master" { + return false + } + + return true +} + +// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2 +// terminal. +func IsCygwinTerminal(fd uintptr) bool { + if procGetFileInformationByHandleEx == nil { + return false + } + + // Cygwin/msys's pty is a pipe. + ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0) + if ft != fileTypePipe || e != 0 { + return false + } + + var buf [2 + syscall.MAX_PATH]uint16 + r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), + 4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)), + uintptr(len(buf)*2), 0, 0) + if r == 0 || e != 0 { + return false + } + + l := *(*uint32)(unsafe.Pointer(&buf)) + return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2]))) +} diff --git a/vendor/github.com/mitchellh/go-homedir/LICENSE b/vendor/github.com/mitchellh/go-homedir/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/go-homedir/README.md b/vendor/github.com/mitchellh/go-homedir/README.md new file mode 100644 index 000000000..d70706d5b --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/README.md @@ -0,0 +1,14 @@ +# go-homedir + +This is a Go library for detecting the user's home directory without +the use of cgo, so the library can be used in cross-compilation environments. + +Usage is incredibly simple, just call `homedir.Dir()` to get the home directory +for a user, and `homedir.Expand()` to expand the `~` in a path to the home +directory. + +**Why not just use `os/user`?** The built-in `os/user` package requires +cgo on Darwin systems. This means that any Go code that uses that package +cannot cross compile. But 99% of the time the use for `os/user` is just to +retrieve the home directory, which we can do for the current user without +cgo. This library does that, enabling cross-compilation. diff --git a/vendor/github.com/mitchellh/go-homedir/go.mod b/vendor/github.com/mitchellh/go-homedir/go.mod new file mode 100644 index 000000000..7efa09a04 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/go.mod @@ -0,0 +1 @@ +module github.com/mitchellh/go-homedir diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go new file mode 100644 index 000000000..25378537e --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/homedir.go @@ -0,0 +1,167 @@ +package homedir + +import ( + "bytes" + "errors" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync" +) + +// DisableCache will disable caching of the home directory. Caching is enabled +// by default. +var DisableCache bool + +var homedirCache string +var cacheLock sync.RWMutex + +// Dir returns the home directory for the executing user. +// +// This uses an OS-specific method for discovering the home directory. +// An error is returned if a home directory cannot be detected. +func Dir() (string, error) { + if !DisableCache { + cacheLock.RLock() + cached := homedirCache + cacheLock.RUnlock() + if cached != "" { + return cached, nil + } + } + + cacheLock.Lock() + defer cacheLock.Unlock() + + var result string + var err error + if runtime.GOOS == "windows" { + result, err = dirWindows() + } else { + // Unix-like system, so just assume Unix + result, err = dirUnix() + } + + if err != nil { + return "", err + } + homedirCache = result + return result, nil +} + +// Expand expands the path to include the home directory if the path +// is prefixed with `~`. If it isn't prefixed with `~`, the path is +// returned as-is. +func Expand(path string) (string, error) { + if len(path) == 0 { + return path, nil + } + + if path[0] != '~' { + return path, nil + } + + if len(path) > 1 && path[1] != '/' && path[1] != '\\' { + return "", errors.New("cannot expand user-specific home dir") + } + + dir, err := Dir() + if err != nil { + return "", err + } + + return filepath.Join(dir, path[1:]), nil +} + +// Reset clears the cache, forcing the next call to Dir to re-detect +// the home directory. This generally never has to be called, but can be +// useful in tests if you're modifying the home directory via the HOME +// env var or something. +func Reset() { + cacheLock.Lock() + defer cacheLock.Unlock() + homedirCache = "" +} + +func dirUnix() (string, error) { + homeEnv := "HOME" + if runtime.GOOS == "plan9" { + // On plan9, env vars are lowercase. + homeEnv = "home" + } + + // First prefer the HOME environmental variable + if home := os.Getenv(homeEnv); home != "" { + return home, nil + } + + var stdout bytes.Buffer + + // If that fails, try OS specific commands + if runtime.GOOS == "darwin" { + cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`) + cmd.Stdout = &stdout + if err := cmd.Run(); err == nil { + result := strings.TrimSpace(stdout.String()) + if result != "" { + return result, nil + } + } + } else { + cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + // If the error is ErrNotFound, we ignore it. Otherwise, return it. + if err != exec.ErrNotFound { + return "", err + } + } else { + if passwd := strings.TrimSpace(stdout.String()); passwd != "" { + // username:password:uid:gid:gecos:home:shell + passwdParts := strings.SplitN(passwd, ":", 7) + if len(passwdParts) > 5 { + return passwdParts[5], nil + } + } + } + } + + // If all else fails, try the shell + stdout.Reset() + cmd := exec.Command("sh", "-c", "cd && pwd") + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return "", err + } + + result := strings.TrimSpace(stdout.String()) + if result == "" { + return "", errors.New("blank output when reading home directory") + } + + return result, nil +} + +func dirWindows() (string, error) { + // First prefer the HOME environmental variable + if home := os.Getenv("HOME"); home != "" { + return home, nil + } + + // Prefer standard environment variable USERPROFILE + if home := os.Getenv("USERPROFILE"); home != "" { + return home, nil + } + + drive := os.Getenv("HOMEDRIVE") + path := os.Getenv("HOMEPATH") + home := drive + path + if drive == "" || path == "" { + return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank") + } + + return home, nil +} diff --git a/vendor/github.com/mitchellh/mapstructure/.travis.yml b/vendor/github.com/mitchellh/mapstructure/.travis.yml new file mode 100644 index 000000000..1689c7d73 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/.travis.yml @@ -0,0 +1,8 @@ +language: go + +go: + - "1.11.x" + - tip + +script: + - go test diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md new file mode 100644 index 000000000..3b3cb723f --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md @@ -0,0 +1,21 @@ +## 1.1.2 + +* Fix error when decode hook decodes interface implementation into interface + type. [GH-140] + +## 1.1.1 + +* Fix panic that can happen in `decodePtr` + +## 1.1.0 + +* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133] +* Support struct to struct decoding [GH-137] +* If source map value is nil, then destination map value is nil (instead of empty) +* If source slice value is nil, then destination slice value is nil (instead of empty) +* If source pointer is nil, then destination pointer is set to nil (instead of + allocated zero value of type) + +## 1.0.0 + +* Initial tagged stable release. diff --git a/vendor/github.com/mitchellh/mapstructure/LICENSE b/vendor/github.com/mitchellh/mapstructure/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/mapstructure/README.md b/vendor/github.com/mitchellh/mapstructure/README.md new file mode 100644 index 000000000..0018dc7d9 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/README.md @@ -0,0 +1,46 @@ +# mapstructure [![Godoc](https://godoc.org/github.com/mitchellh/mapstructure?status.svg)](https://godoc.org/github.com/mitchellh/mapstructure) + +mapstructure is a Go library for decoding generic map values to structures +and vice versa, while providing helpful error handling. + +This library is most useful when decoding values from some data stream (JSON, +Gob, etc.) where you don't _quite_ know the structure of the underlying data +until you read a part of it. You can therefore read a `map[string]interface{}` +and use this library to decode it into the proper underlying native Go +structure. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/mapstructure +``` + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure). + +The `Decode` function has examples associated with it there. + +## But Why?! + +Go offers fantastic standard libraries for decoding formats such as JSON. +The standard method is to have a struct pre-created, and populate that struct +from the bytes of the encoded format. This is great, but the problem is if +you have configuration or an encoding that changes slightly depending on +specific fields. For example, consider this JSON: + +```json +{ + "type": "person", + "name": "Mitchell" +} +``` + +Perhaps we can't populate a specific structure without first reading +the "type" field from the JSON. We could always do two passes over the +decoding of the JSON (reading the "type" first, and the rest later). +However, it is much simpler to just decode this into a `map[string]interface{}` +structure, read the "type" key, then use something like this library +to decode it into the proper structure. diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go new file mode 100644 index 000000000..1f0abc65a --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go @@ -0,0 +1,217 @@ +package mapstructure + +import ( + "errors" + "fmt" + "net" + "reflect" + "strconv" + "strings" + "time" +) + +// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. +func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { + // Create variables here so we can reference them with the reflect pkg + var f1 DecodeHookFuncType + var f2 DecodeHookFuncKind + + // Fill in the variables into this interface and the rest is done + // automatically using the reflect package. + potential := []interface{}{f1, f2} + + v := reflect.ValueOf(h) + vt := v.Type() + for _, raw := range potential { + pt := reflect.ValueOf(raw).Type() + if vt.ConvertibleTo(pt) { + return v.Convert(pt).Interface() + } + } + + return nil +} + +// DecodeHookExec executes the given decode hook. This should be used +// since it'll naturally degrade to the older backwards compatible DecodeHookFunc +// that took reflect.Kind instead of reflect.Type. +func DecodeHookExec( + raw DecodeHookFunc, + from reflect.Type, to reflect.Type, + data interface{}) (interface{}, error) { + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return f(from, to, data) + case DecodeHookFuncKind: + return f(from.Kind(), to.Kind(), data) + default: + return nil, errors.New("invalid decode hook signature") + } +} + +// ComposeDecodeHookFunc creates a single DecodeHookFunc that +// automatically composes multiple DecodeHookFuncs. +// +// The composed funcs are called in order, with the result of the +// previous transformation. +func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + var err error + for _, f1 := range fs { + data, err = DecodeHookExec(f1, f, t, data) + if err != nil { + return nil, err + } + + // Modify the from kind to be correct with the new data + f = nil + if val := reflect.ValueOf(data); val.IsValid() { + f = val.Type() + } + } + + return data, nil + } +} + +// StringToSliceHookFunc returns a DecodeHookFunc that converts +// string to []string by splitting on the given sep. +func StringToSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + if f != reflect.String || t != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + +// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts +// strings to time.Duration. +func StringToTimeDurationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Duration(5)) { + return data, nil + } + + // Convert it by parsing + return time.ParseDuration(data.(string)) + } +} + +// StringToIPHookFunc returns a DecodeHookFunc that converts +// strings to net.IP +func StringToIPHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IP{}) { + return data, nil + } + + // Convert it by parsing + ip := net.ParseIP(data.(string)) + if ip == nil { + return net.IP{}, fmt.Errorf("failed parsing ip %v", data) + } + + return ip, nil + } +} + +// StringToIPNetHookFunc returns a DecodeHookFunc that converts +// strings to net.IPNet +func StringToIPNetHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IPNet{}) { + return data, nil + } + + // Convert it by parsing + _, net, err := net.ParseCIDR(data.(string)) + return net, err + } +} + +// StringToTimeHookFunc returns a DecodeHookFunc that converts +// strings to time.Time. +func StringToTimeHookFunc(layout string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Time{}) { + return data, nil + } + + // Convert it by parsing + return time.Parse(layout, data.(string)) + } +} + +// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to +// the decoder. +// +// Note that this is significantly different from the WeaklyTypedInput option +// of the DecoderConfig. +func WeaklyTypedHook( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + dataVal := reflect.ValueOf(data) + switch t { + case reflect.String: + switch f { + case reflect.Bool: + if dataVal.Bool() { + return "1", nil + } + return "0", nil + case reflect.Float32: + return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil + case reflect.Int: + return strconv.FormatInt(dataVal.Int(), 10), nil + case reflect.Slice: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + if elemKind == reflect.Uint8 { + return string(dataVal.Interface().([]uint8)), nil + } + case reflect.Uint: + return strconv.FormatUint(dataVal.Uint(), 10), nil + } + } + + return data, nil +} diff --git a/vendor/github.com/mitchellh/mapstructure/error.go b/vendor/github.com/mitchellh/mapstructure/error.go new file mode 100644 index 000000000..47a99e5af --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/error.go @@ -0,0 +1,50 @@ +package mapstructure + +import ( + "errors" + "fmt" + "sort" + "strings" +) + +// Error implements the error interface and can represents multiple +// errors that occur in the course of a single decode. +type Error struct { + Errors []string +} + +func (e *Error) Error() string { + points := make([]string, len(e.Errors)) + for i, err := range e.Errors { + points[i] = fmt.Sprintf("* %s", err) + } + + sort.Strings(points) + return fmt.Sprintf( + "%d error(s) decoding:\n\n%s", + len(e.Errors), strings.Join(points, "\n")) +} + +// WrappedErrors implements the errwrap.Wrapper interface to make this +// return value more useful with the errwrap and go-multierror libraries. +func (e *Error) WrappedErrors() []error { + if e == nil { + return nil + } + + result := make([]error, len(e.Errors)) + for i, e := range e.Errors { + result[i] = errors.New(e) + } + + return result +} + +func appendErrors(errors []string, err error) []string { + switch e := err.(type) { + case *Error: + return append(errors, e.Errors...) + default: + return append(errors, e.Error()) + } +} diff --git a/vendor/github.com/mitchellh/mapstructure/go.mod b/vendor/github.com/mitchellh/mapstructure/go.mod new file mode 100644 index 000000000..d2a712562 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/go.mod @@ -0,0 +1 @@ +module github.com/mitchellh/mapstructure diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go new file mode 100644 index 000000000..256ee63fb --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go @@ -0,0 +1,1149 @@ +// Package mapstructure exposes functionality to convert an arbitrary +// map[string]interface{} into a native Go structure. +// +// The Go structure can be arbitrarily complex, containing slices, +// other structs, etc. and the decoder will properly decode nested +// maps and so on into the proper structures in the native Go struct. +// See the examples to see what the decoder is capable of. +package mapstructure + +import ( + "encoding/json" + "errors" + "fmt" + "reflect" + "sort" + "strconv" + "strings" +) + +// DecodeHookFunc is the callback function that can be used for +// data transformations. See "DecodeHook" in the DecoderConfig +// struct. +// +// The type should be DecodeHookFuncType or DecodeHookFuncKind. +// Either is accepted. Types are a superset of Kinds (Types can return +// Kinds) and are generally a richer thing to use, but Kinds are simpler +// if you only need those. +// +// The reason DecodeHookFunc is multi-typed is for backwards compatibility: +// we started with Kinds and then realized Types were the better solution, +// but have a promise to not break backwards compat so we now support +// both. +type DecodeHookFunc interface{} + +// DecodeHookFuncType is a DecodeHookFunc which has complete information about +// the source and target types. +type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) + +// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the +// source and target types. +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) + +// DecoderConfig is the configuration that is used to create a new decoder +// and allows customization of various aspects of decoding. +type DecoderConfig struct { + // DecodeHook, if set, will be called before any decoding and any + // type conversion (if WeaklyTypedInput is on). This lets you modify + // the values before they're set down onto the resulting struct. + // + // If an error is returned, the entire decode will fail with that + // error. + DecodeHook DecodeHookFunc + + // If ErrorUnused is true, then it is an error for there to exist + // keys in the original map that were unused in the decoding process + // (extra keys). + ErrorUnused bool + + // ZeroFields, if set to true, will zero fields before writing them. + // For example, a map will be emptied before decoded values are put in + // it. If this is false, a map will be merged. + ZeroFields bool + + // If WeaklyTypedInput is true, the decoder will make the following + // "weak" conversions: + // + // - bools to string (true = "1", false = "0") + // - numbers to string (base 10) + // - bools to int/uint (true = 1, false = 0) + // - strings to int/uint (base implied by prefix) + // - int to bool (true if value != 0) + // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, + // FALSE, false, False. Anything else is an error) + // - empty array = empty map and vice versa + // - negative numbers to overflowed uint values (base 10) + // - slice of maps to a merged map + // - single values are converted to slices if required. Each + // element is weakly decoded. For example: "4" can become []int{4} + // if the target type is an int slice. + // + WeaklyTypedInput bool + + // Metadata is the struct that will contain extra metadata about + // the decoding. If this is nil, then no metadata will be tracked. + Metadata *Metadata + + // Result is a pointer to the struct that will contain the decoded + // value. + Result interface{} + + // The tag name that mapstructure reads for field names. This + // defaults to "mapstructure" + TagName string +} + +// A Decoder takes a raw interface value and turns it into structured +// data, keeping track of rich error information along the way in case +// anything goes wrong. Unlike the basic top-level Decode method, you can +// more finely control how the Decoder behaves using the DecoderConfig +// structure. The top-level Decode method is just a convenience that sets +// up the most basic Decoder. +type Decoder struct { + config *DecoderConfig +} + +// Metadata contains information about decoding a structure that +// is tedious or difficult to get otherwise. +type Metadata struct { + // Keys are the keys of the structure which were successfully decoded + Keys []string + + // Unused is a slice of keys that were found in the raw value but + // weren't decoded since there was no matching field in the result interface + Unused []string +} + +// Decode takes an input structure and uses reflection to translate it to +// the output structure. output must be a pointer to a map or struct. +func Decode(input interface{}, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecode is the same as Decode but is shorthand to enable +// WeaklyTypedInput. See DecoderConfig for more info. +func WeakDecode(input, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// DecodeMetadata is the same as Decode, but is shorthand to +// enable metadata collection. See DecoderConfig for more info. +func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecodeMetadata is the same as Decode, but is shorthand to +// enable both WeaklyTypedInput and metadata collection. See +// DecoderConfig for more info. +func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// NewDecoder returns a new decoder for the given configuration. Once +// a decoder has been returned, the same configuration must not be used +// again. +func NewDecoder(config *DecoderConfig) (*Decoder, error) { + val := reflect.ValueOf(config.Result) + if val.Kind() != reflect.Ptr { + return nil, errors.New("result must be a pointer") + } + + val = val.Elem() + if !val.CanAddr() { + return nil, errors.New("result must be addressable (a pointer)") + } + + if config.Metadata != nil { + if config.Metadata.Keys == nil { + config.Metadata.Keys = make([]string, 0) + } + + if config.Metadata.Unused == nil { + config.Metadata.Unused = make([]string, 0) + } + } + + if config.TagName == "" { + config.TagName = "mapstructure" + } + + result := &Decoder{ + config: config, + } + + return result, nil +} + +// Decode decodes the given raw interface to the target pointer specified +// by the configuration. +func (d *Decoder) Decode(input interface{}) error { + return d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) +} + +// Decodes an unknown data type into a specific reflection value. +func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { + var inputVal reflect.Value + if input != nil { + inputVal = reflect.ValueOf(input) + + // We need to check here if input is a typed nil. Typed nils won't + // match the "input == nil" below so we check that here. + if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() { + input = nil + } + } + + if input == nil { + // If the data is nil, then we don't set anything, unless ZeroFields is set + // to true. + if d.config.ZeroFields { + outVal.Set(reflect.Zero(outVal.Type())) + + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + } + return nil + } + + if !inputVal.IsValid() { + // If the input value is invalid, then we just set the value + // to be the zero value. + outVal.Set(reflect.Zero(outVal.Type())) + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + return nil + } + + if d.config.DecodeHook != nil { + // We have a DecodeHook, so let's pre-process the input. + var err error + input, err = DecodeHookExec( + d.config.DecodeHook, + inputVal.Type(), outVal.Type(), input) + if err != nil { + return fmt.Errorf("error decoding '%s': %s", name, err) + } + } + + var err error + outputKind := getKind(outVal) + switch outputKind { + case reflect.Bool: + err = d.decodeBool(name, input, outVal) + case reflect.Interface: + err = d.decodeBasic(name, input, outVal) + case reflect.String: + err = d.decodeString(name, input, outVal) + case reflect.Int: + err = d.decodeInt(name, input, outVal) + case reflect.Uint: + err = d.decodeUint(name, input, outVal) + case reflect.Float32: + err = d.decodeFloat(name, input, outVal) + case reflect.Struct: + err = d.decodeStruct(name, input, outVal) + case reflect.Map: + err = d.decodeMap(name, input, outVal) + case reflect.Ptr: + err = d.decodePtr(name, input, outVal) + case reflect.Slice: + err = d.decodeSlice(name, input, outVal) + case reflect.Array: + err = d.decodeArray(name, input, outVal) + case reflect.Func: + err = d.decodeFunc(name, input, outVal) + default: + // If we reached this point then we weren't able to decode it + return fmt.Errorf("%s: unsupported type: %s", name, outputKind) + } + + // If we reached here, then we successfully decoded SOMETHING, so + // mark the key as used if we're tracking metainput. + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + + return err +} + +// This decodes a basic type (bool, int, string, etc.) and sets the +// value to "data" of that type. +func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { + if val.IsValid() && val.Elem().IsValid() { + return d.decode(name, data, val.Elem()) + } + + dataVal := reflect.ValueOf(data) + + // If the input data is a pointer, and the assigned type is the dereference + // of that exact pointer, then indirect it so that we can assign it. + // Example: *string to string + if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() { + dataVal = reflect.Indirect(dataVal) + } + + if !dataVal.IsValid() { + dataVal = reflect.Zero(val.Type()) + } + + dataValType := dataVal.Type() + if !dataValType.AssignableTo(val.Type()) { + return fmt.Errorf( + "'%s' expected type '%s', got '%s'", + name, val.Type(), dataValType) + } + + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + converted := true + switch { + case dataKind == reflect.String: + val.SetString(dataVal.String()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetString("1") + } else { + val.SetString("0") + } + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatInt(dataVal.Int(), 10)) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput, + dataKind == reflect.Array && d.config.WeaklyTypedInput: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + switch elemKind { + case reflect.Uint8: + var uints []uint8 + if dataKind == reflect.Array { + uints = make([]uint8, dataVal.Len(), dataVal.Len()) + for i := range uints { + uints[i] = dataVal.Index(i).Interface().(uint8) + } + } else { + uints = dataVal.Interface().([]uint8) + } + val.SetString(string(uints)) + default: + converted = false + } + default: + converted = false + } + + if !converted { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetInt(dataVal.Int()) + case dataKind == reflect.Uint: + val.SetInt(int64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetInt(int64(dataVal.Float())) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetInt(1) + } else { + val.SetInt(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits()) + if err == nil { + val.SetInt(i) + } else { + return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Int64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetInt(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Int: + i := dataVal.Int() + if i < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %d overflows uint", + name, i) + } + val.SetUint(uint64(i)) + case dataKind == reflect.Uint: + val.SetUint(dataVal.Uint()) + case dataKind == reflect.Float32: + f := dataVal.Float() + if f < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %f overflows uint", + name, f) + } + val.SetUint(uint64(f)) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetUint(1) + } else { + val.SetUint(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits()) + if err == nil { + val.SetUint(i) + } else { + return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Bool: + val.SetBool(dataVal.Bool()) + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Int() != 0) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Uint() != 0) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Float() != 0) + case dataKind == reflect.String && d.config.WeaklyTypedInput: + b, err := strconv.ParseBool(dataVal.String()) + if err == nil { + val.SetBool(b) + } else if dataVal.String() == "" { + val.SetBool(false) + } else { + return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetFloat(float64(dataVal.Int())) + case dataKind == reflect.Uint: + val.SetFloat(float64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetFloat(dataVal.Float()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetFloat(1) + } else { + val.SetFloat(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits()) + if err == nil { + val.SetFloat(f) + } else { + return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Float64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetFloat(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // By default we overwrite keys in the current map + valMap := val + + // If the map is nil or we're purposely zeroing fields, make a new map + if valMap.IsNil() || d.config.ZeroFields { + // Make a new map to hold our result + mapType := reflect.MapOf(valKeyType, valElemType) + valMap = reflect.MakeMap(mapType) + } + + // Check input type and based on the input type jump to the proper func + dataVal := reflect.Indirect(reflect.ValueOf(data)) + switch dataVal.Kind() { + case reflect.Map: + return d.decodeMapFromMap(name, dataVal, val, valMap) + + case reflect.Struct: + return d.decodeMapFromStruct(name, dataVal, val, valMap) + + case reflect.Array, reflect.Slice: + if d.config.WeaklyTypedInput { + return d.decodeMapFromSlice(name, dataVal, val, valMap) + } + + fallthrough + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + // Special case for BC reasons (covered by tests) + if dataVal.Len() == 0 { + val.Set(valMap) + return nil + } + + for i := 0; i < dataVal.Len(); i++ { + err := d.decode( + fmt.Sprintf("%s[%d]", name, i), + dataVal.Index(i).Interface(), val) + if err != nil { + return err + } + } + + return nil +} + +func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // Accumulate errors + errors := make([]string, 0) + + // If the input data is empty, then we just match what the input data is. + if dataVal.Len() == 0 { + if dataVal.IsNil() { + if !val.IsNil() { + val.Set(dataVal) + } + } else { + // Set to empty allocated value + val.Set(valMap) + } + + return nil + } + + for _, k := range dataVal.MapKeys() { + fieldName := fmt.Sprintf("%s[%s]", name, k) + + // First decode the key into the proper type + currentKey := reflect.Indirect(reflect.New(valKeyType)) + if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { + errors = appendErrors(errors, err) + continue + } + + // Next decode the data into the proper type + v := dataVal.MapIndex(k).Interface() + currentVal := reflect.Indirect(reflect.New(valElemType)) + if err := d.decode(fieldName, v, currentVal); err != nil { + errors = appendErrors(errors, err) + continue + } + + valMap.SetMapIndex(currentKey, currentVal) + } + + // Set the built up map to the value + val.Set(valMap) + + // If we had errors, return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + typ := dataVal.Type() + for i := 0; i < typ.NumField(); i++ { + // Get the StructField first since this is a cheap operation. If the + // field is unexported, then ignore it. + f := typ.Field(i) + if f.PkgPath != "" { + continue + } + + // Next get the actual value of this field and verify it is assignable + // to the map value. + v := dataVal.Field(i) + if !v.Type().AssignableTo(valMap.Type().Elem()) { + return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) + } + + tagValue := f.Tag.Get(d.config.TagName) + tagParts := strings.Split(tagValue, ",") + + // Determine the name of the key in the map + keyName := f.Name + if tagParts[0] != "" { + if tagParts[0] == "-" { + continue + } + keyName = tagParts[0] + } + + // If "squash" is specified in the tag, we squash the field down. + squash := false + for _, tag := range tagParts[1:] { + if tag == "squash" { + squash = true + break + } + } + if squash && v.Kind() != reflect.Struct { + return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + } + + switch v.Kind() { + // this is an embedded struct, so handle it differently + case reflect.Struct: + x := reflect.New(v.Type()) + x.Elem().Set(v) + + vType := valMap.Type() + vKeyType := vType.Key() + vElemType := vType.Elem() + mType := reflect.MapOf(vKeyType, vElemType) + vMap := reflect.MakeMap(mType) + + err := d.decode(keyName, x.Interface(), vMap) + if err != nil { + return err + } + + if squash { + for _, k := range vMap.MapKeys() { + valMap.SetMapIndex(k, vMap.MapIndex(k)) + } + } else { + valMap.SetMapIndex(reflect.ValueOf(keyName), vMap) + } + + default: + valMap.SetMapIndex(reflect.ValueOf(keyName), v) + } + } + + if val.CanAddr() { + val.Set(valMap) + } + + return nil +} + +func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { + // If the input data is nil, then we want to just set the output + // pointer to be nil as well. + isNil := data == nil + if !isNil { + switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() { + case reflect.Chan, + reflect.Func, + reflect.Interface, + reflect.Map, + reflect.Ptr, + reflect.Slice: + isNil = v.IsNil() + } + } + if isNil { + if !val.IsNil() && val.CanSet() { + nilValue := reflect.New(val.Type()).Elem() + val.Set(nilValue) + } + + return nil + } + + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + valType := val.Type() + valElemType := valType.Elem() + if val.CanSet() { + realVal := val + if realVal.IsNil() || d.config.ZeroFields { + realVal = reflect.New(valElemType) + } + + if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { + return err + } + + val.Set(realVal) + } else { + if err := d.decode(name, data, reflect.Indirect(val)); err != nil { + return err + } + } + return nil +} + +func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + dataVal := reflect.Indirect(reflect.ValueOf(data)) + if val.Type() != dataVal.Type() { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + sliceType := reflect.SliceOf(valElemType) + + valSlice := val + if valSlice.IsNil() || d.config.ZeroFields { + if d.config.WeaklyTypedInput { + switch { + // Slice and array we use the normal logic + case dataValKind == reflect.Slice, dataValKind == reflect.Array: + break + + // Empty maps turn into empty slices + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.MakeSlice(sliceType, 0, 0)) + return nil + } + // Create slice of maps of other sizes + return d.decodeSlice(name, []interface{}{data}, val) + + case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: + return d.decodeSlice(name, []byte(dataVal.String()), val) + + // All other types we try to convert to the slice type + // and "lift" it into it. i.e. a string becomes a string slice. + default: + // Just re-try this function with data as a slice. + return d.decodeSlice(name, []interface{}{data}, val) + } + } + + // Check input type + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + + } + + // If the input value is empty, then don't allocate since non-nil != nil + if dataVal.Len() == 0 { + return nil + } + + // Make a new slice to hold our result, same size as the original data. + valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) + } + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + for valSlice.Len() <= i { + valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) + } + currentField := valSlice.Index(i) + + fieldName := fmt.Sprintf("%s[%d]", name, i) + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the slice we built up + val.Set(valSlice) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + arrayType := reflect.ArrayOf(valType.Len(), valElemType) + + valArray := val + + if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { + // Check input type + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + if d.config.WeaklyTypedInput { + switch { + // Empty maps turn into empty arrays + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.Zero(arrayType)) + return nil + } + + // All other types we try to convert to the array type + // and "lift" it into it. i.e. a string becomes a string array. + default: + // Just re-try this function with data as a slice. + return d.decodeArray(name, []interface{}{data}, val) + } + } + + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + + } + if dataVal.Len() > arrayType.Len() { + return fmt.Errorf( + "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) + + } + + // Make a new array to hold our result, same size as the original data. + valArray = reflect.New(arrayType).Elem() + } + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + currentField := valArray.Index(i) + + fieldName := fmt.Sprintf("%s[%d]", name, i) + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the array we built up + val.Set(valArray) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + + // If the type of the value to write to and the data match directly, + // then we just set it directly instead of recursing into the structure. + if dataVal.Type() == val.Type() { + val.Set(dataVal) + return nil + } + + dataValKind := dataVal.Kind() + switch dataValKind { + case reflect.Map: + return d.decodeStructFromMap(name, dataVal, val) + + case reflect.Struct: + // Not the most efficient way to do this but we can optimize later if + // we want to. To convert from struct to struct we go to map first + // as an intermediary. + m := make(map[string]interface{}) + mval := reflect.Indirect(reflect.ValueOf(&m)) + if err := d.decodeMapFromStruct(name, dataVal, mval, mval); err != nil { + return err + } + + result := d.decodeStructFromMap(name, mval, val) + return result + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { + dataValType := dataVal.Type() + if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { + return fmt.Errorf( + "'%s' needs a map with string keys, has '%s' keys", + name, dataValType.Key().Kind()) + } + + dataValKeys := make(map[reflect.Value]struct{}) + dataValKeysUnused := make(map[interface{}]struct{}) + for _, dataValKey := range dataVal.MapKeys() { + dataValKeys[dataValKey] = struct{}{} + dataValKeysUnused[dataValKey.Interface()] = struct{}{} + } + + errors := make([]string, 0) + + // This slice will keep track of all the structs we'll be decoding. + // There can be more than one struct if there are embedded structs + // that are squashed. + structs := make([]reflect.Value, 1, 5) + structs[0] = val + + // Compile the list of all the fields that we're going to be decoding + // from all the structs. + type field struct { + field reflect.StructField + val reflect.Value + } + fields := []field{} + for len(structs) > 0 { + structVal := structs[0] + structs = structs[1:] + + structType := structVal.Type() + + for i := 0; i < structType.NumField(); i++ { + fieldType := structType.Field(i) + fieldKind := fieldType.Type.Kind() + + // If "squash" is specified in the tag, we squash the field down. + squash := false + tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") + for _, tag := range tagParts[1:] { + if tag == "squash" { + squash = true + break + } + } + + if squash { + if fieldKind != reflect.Struct { + errors = appendErrors(errors, + fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind)) + } else { + structs = append(structs, structVal.FieldByName(fieldType.Name)) + } + continue + } + + // Normal struct field, store it away + fields = append(fields, field{fieldType, structVal.Field(i)}) + } + } + + // for fieldType, field := range fields { + for _, f := range fields { + field, fieldValue := f.field, f.val + fieldName := field.Name + + tagValue := field.Tag.Get(d.config.TagName) + tagValue = strings.SplitN(tagValue, ",", 2)[0] + if tagValue != "" { + fieldName = tagValue + } + + rawMapKey := reflect.ValueOf(fieldName) + rawMapVal := dataVal.MapIndex(rawMapKey) + if !rawMapVal.IsValid() { + // Do a slower search by iterating over each key and + // doing case-insensitive search. + for dataValKey := range dataValKeys { + mK, ok := dataValKey.Interface().(string) + if !ok { + // Not a string key + continue + } + + if strings.EqualFold(mK, fieldName) { + rawMapKey = dataValKey + rawMapVal = dataVal.MapIndex(dataValKey) + break + } + } + + if !rawMapVal.IsValid() { + // There was no matching key in the map for the value in + // the struct. Just ignore. + continue + } + } + + // Delete the key we're using from the unused map so we stop tracking + delete(dataValKeysUnused, rawMapKey.Interface()) + + if !fieldValue.IsValid() { + // This should never happen + panic("field is not valid") + } + + // If we can't set the field, then it is unexported or something, + // and we just continue onwards. + if !fieldValue.CanSet() { + continue + } + + // If the name is empty string, then we're at the root, and we + // don't dot-join the fields. + if name != "" { + fieldName = fmt.Sprintf("%s.%s", name, fieldName) + } + + if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { + errors = appendErrors(errors, err) + } + } + + if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { + keys := make([]string, 0, len(dataValKeysUnused)) + for rawKey := range dataValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) + errors = appendErrors(errors, err) + } + + if len(errors) > 0 { + return &Error{errors} + } + + // Add the unused keys to the list of unused keys if we're tracking metadata + if d.config.Metadata != nil { + for rawKey := range dataValKeysUnused { + key := rawKey.(string) + if name != "" { + key = fmt.Sprintf("%s.%s", name, key) + } + + d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) + } + } + + return nil +} + +func getKind(val reflect.Value) reflect.Kind { + kind := val.Kind() + + switch { + case kind >= reflect.Int && kind <= reflect.Int64: + return reflect.Int + case kind >= reflect.Uint && kind <= reflect.Uint64: + return reflect.Uint + case kind >= reflect.Float32 && kind <= reflect.Float64: + return reflect.Float32 + default: + return kind + } +} diff --git a/vendor/github.com/nakabonne/nestif/.gitignore b/vendor/github.com/nakabonne/nestif/.gitignore new file mode 100644 index 000000000..df71a2ac7 --- /dev/null +++ b/vendor/github.com/nakabonne/nestif/.gitignore @@ -0,0 +1,16 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +/nestif + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/nakabonne/nestif/LICENSE b/vendor/github.com/nakabonne/nestif/LICENSE new file mode 100644 index 000000000..ddf4d71ed --- /dev/null +++ b/vendor/github.com/nakabonne/nestif/LICENSE @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2020, Ryo Nakao +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/nakabonne/nestif/README.md b/vendor/github.com/nakabonne/nestif/README.md new file mode 100644 index 000000000..ede411f73 --- /dev/null +++ b/vendor/github.com/nakabonne/nestif/README.md @@ -0,0 +1,122 @@ +# nestif + +[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](http://godoc.org/github.com/nakabonne/nestif) + +Reports deeply nested if statements in Go code, by calculating its complexities based on the rules defined by the [Cognitive Complexity white paper by G. Ann Campbell](https://www.sonarsource.com/docs/CognitiveComplexity.pdf). + +It helps you find if statements that make your code hard to read, and clarifies which parts to refactor. + +## Installation + +``` +go get github.com/nakabonne/nestif/cmd/nestif +``` + +## Usage + +### Quick Start + +```bash +nestif +``` + +The `...` glob operator is supported, and the above is an equivalent of: + +```bash +nestif ./... +``` + +One or more files and directories can be specified in a single command: + +```bash +nestif dir/foo.go dir2 dir3/... +``` + +Packages can be specified as well: + +```bash +nestif github.com/foo/bar example.com/bar/baz +``` + +### Options + +``` +usage: nestif [ ...] ... + -e, --exclude-dirs strings regexps of directories to be excluded for checking; comma-separated list + --json emit json format + --min int minimum complexity to show (default 1) + --top int show only the top N most complex if statements (default 10) + -v, --verbose verbose output +``` + +### Example + +Let's say you write: + +```go +package main + +func _() { + if foo { + if bar { + } + } + + if baz == "baz" { + if qux { + if quux { + } + } + } +} +``` + +And give it to nestif: + +```console +$ nestif foo.go +foo.go:9:2: `if baz == "baz"` is nested (complexity: 3) +foo.go:4:2: `if foo` is nested (complexity: 1) +``` + +Note that the results are sorted in descending order of complexity. In addition, it shows only the top 10 most complex if statements by default, and you can specify how many to show with `-top` flag. + +### Rules + +It calculates the complexities of if statements according to the nesting rules of Cognitive Complexity. +Since the more deeply-nested your code gets, the harder it can be to reason about, it assesses a nesting increment for it: + +```go +if condition1 { + if condition2 { // +1 + if condition3 { // +2 + if condition4 { // +3 + } + } + } +} +``` + +`else` and `else if` increase complexity by one wherever they are because the mental cost has already been paid when reading the if: + +```go +if condition1 { + if condition2 { // +1 + if condition3 { // +2 + } else if condition4 { // +1 + } else { // +1 + if condition5 { // +3 + } + } + } +} +``` + +## Inspired by + +- [uudashr/gocognit](https://github.com/uudashr/gocognit) +- [fzipp/gocyclo](https://github.com/fzipp/gocyclo) + +## Further reading + +Please see the [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) white paper by G. Ann Campbell for more detail on Cognitive Complexity. diff --git a/vendor/github.com/nakabonne/nestif/go.mod b/vendor/github.com/nakabonne/nestif/go.mod new file mode 100644 index 000000000..325901d59 --- /dev/null +++ b/vendor/github.com/nakabonne/nestif/go.mod @@ -0,0 +1,8 @@ +module github.com/nakabonne/nestif + +go 1.13 + +require ( + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.4.0 +) diff --git a/vendor/github.com/nakabonne/nestif/go.sum b/vendor/github.com/nakabonne/nestif/go.sum new file mode 100644 index 000000000..6d790ef35 --- /dev/null +++ b/vendor/github.com/nakabonne/nestif/go.sum @@ -0,0 +1,12 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/nakabonne/nestif/nestif.go b/vendor/github.com/nakabonne/nestif/nestif.go new file mode 100644 index 000000000..d458022fb --- /dev/null +++ b/vendor/github.com/nakabonne/nestif/nestif.go @@ -0,0 +1,148 @@ +// Copyright 2020 Ryo Nakao . +// +// All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package nestif provides an API to detect deeply nested if statements. +package nestif + +import ( + "bytes" + "fmt" + "go/ast" + "go/printer" + "go/token" + "io" +) + +// Issue represents an issue of root if statement that has nested ifs. +type Issue struct { + Pos token.Position + Complexity int + Message string +} + +// Checker represents a checker that finds nested if statements. +type Checker struct { + // Minimum complexity to report. + MinComplexity int + + // For debug mode. + debugWriter io.Writer + issues []Issue +} + +// Check inspects a single file and returns found issues. +func (c *Checker) Check(f *ast.File, fset *token.FileSet) []Issue { + c.issues = []Issue{} // refresh + ast.Inspect(f, func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok || fn.Body == nil { + return true + } + for _, stmt := range fn.Body.List { + c.checkFunc(&stmt, fset) + } + return true + }) + + return c.issues +} + +// checkFunc inspects a function and sets a list of issues if there are. +func (c *Checker) checkFunc(stmt *ast.Stmt, fset *token.FileSet) { + ast.Inspect(*stmt, func(n ast.Node) bool { + ifStmt, ok := n.(*ast.IfStmt) + if !ok { + return true + } + + c.checkIf(ifStmt, fset) + return false + }) +} + +// checkIf inspects a if statement and sets an issue if there is. +func (c *Checker) checkIf(stmt *ast.IfStmt, fset *token.FileSet) { + v := newVisitor() + ast.Walk(v, stmt) + if v.complexity < c.MinComplexity { + return + } + pos := fset.Position(stmt.Pos()) + c.issues = append(c.issues, Issue{ + Pos: pos, + Complexity: v.complexity, + Message: c.makeMessage(v.complexity, stmt.Cond, fset), + }) +} + +type visitor struct { + complexity int + nesting int + // To avoid adding complexity including nesting level to `else if`. + elseifs map[*ast.IfStmt]bool +} + +func newVisitor() *visitor { + return &visitor{ + elseifs: make(map[*ast.IfStmt]bool), + } +} + +// Visit traverses an AST in depth-first order by calling itself +// recursively, and calculates the complexities of if statements. +func (v *visitor) Visit(n ast.Node) ast.Visitor { + ifStmt, ok := n.(*ast.IfStmt) + if !ok { + return v + } + + v.incComplexity(ifStmt) + v.nesting++ + ast.Walk(v, ifStmt.Body) + v.nesting-- + + switch t := ifStmt.Else.(type) { + case *ast.BlockStmt: + v.complexity++ + v.nesting++ + ast.Walk(v, t) + v.nesting-- + case *ast.IfStmt: + v.elseifs[t] = true + ast.Walk(v, t) + } + + return nil +} + +func (v *visitor) incComplexity(n *ast.IfStmt) { + // In case of `else if`, increase by 1. + if v.elseifs[n] { + v.complexity++ + } else { + v.complexity += v.nesting + } +} + +func (c *Checker) makeMessage(complexity int, cond ast.Expr, fset *token.FileSet) string { + p := &printer.Config{} + b := new(bytes.Buffer) + if err := p.Fprint(b, fset, cond); err != nil { + c.debug("failed to convert condition into string: %v", err) + } + return fmt.Sprintf("`if %s` is deeply nested (complexity: %d)", b.String(), complexity) +} + +// DebugMode makes it possible to emit debug logs. +func (c *Checker) DebugMode(w io.Writer) { + c.debugWriter = w +} + +func (c *Checker) debug(format string, a ...interface{}) { + if c.debugWriter != nil { + fmt.Fprintf(c.debugWriter, format, a...) + } +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/.gitignore b/vendor/github.com/nbutton23/zxcvbn-go/.gitignore new file mode 100644 index 000000000..4bff1a28e --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/.gitignore @@ -0,0 +1,2 @@ +zxcvbn +debug.test diff --git a/vendor/github.com/nbutton23/zxcvbn-go/Gopkg.lock b/vendor/github.com/nbutton23/zxcvbn-go/Gopkg.lock new file mode 100644 index 000000000..b5a62a380 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/Gopkg.lock @@ -0,0 +1,27 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = ["assert"] + revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0" + version = "v1.1.4" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "b750880cdc8ce044e6f9bf3b331d8a392471c328107b8c3d42e3e11022d76858" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/nbutton23/zxcvbn-go/Gopkg.toml b/vendor/github.com/nbutton23/zxcvbn-go/Gopkg.toml new file mode 100644 index 000000000..c59386c0a --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/Gopkg.toml @@ -0,0 +1,26 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.1.4" diff --git a/vendor/github.com/nbutton23/zxcvbn-go/LICENSE.txt b/vendor/github.com/nbutton23/zxcvbn-go/LICENSE.txt new file mode 100644 index 000000000..e8f59e06d --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) Nathan Button + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/nbutton23/zxcvbn-go/Makefile b/vendor/github.com/nbutton23/zxcvbn-go/Makefile new file mode 100644 index 000000000..6aa13e006 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/Makefile @@ -0,0 +1,15 @@ +PKG_LIST = $$( go list ./... | grep -v /vendor/ | grep -v "zxcvbn-go/data" ) + +.DEFAULT_GOAL := help + +.PHONY: help +help: + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: test +test: ## Run `go test {Package list}` on the packages + go test $(PKG_LIST) + +.PHONY: lint +lint: ## Run `golint {Package list}` + golint $(PKG_LIST) \ No newline at end of file diff --git a/vendor/github.com/nbutton23/zxcvbn-go/README.md b/vendor/github.com/nbutton23/zxcvbn-go/README.md new file mode 100644 index 000000000..a9d2f7836 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/README.md @@ -0,0 +1,78 @@ +This is a goLang port of python-zxcvbn and [zxcvbn](https://github.com/dropbox/zxcvbn), which are python and JavaScript password strength +generators. zxcvbn attempts to give sound password advice through pattern +matching and conservative entropy calculations. It finds 10k common passwords, +common American names and surnames, common English words, and common patterns +like dates, repeats (aaa), sequences (abcd), and QWERTY patterns. + +Please refer to http://tech.dropbox.com/?p=165 for the full details and +motivation behind zxcbvn. The source code for the original JavaScript (well, +actually CoffeeScript) implementation can be found at: + +https://github.com/lowe/zxcvbn + +Python at: + +https://github.com/dropbox/python-zxcvbn + +For full motivation, see: + +http://tech.dropbox.com/?p=165 + +------------------------------------------------------------------------ +Use +------------------------------------------------------------------------ + +The zxcvbn module has the public method PasswordStrength() function. Import zxcvbn, and +call PasswordStrength(password string, userInputs []string). The function will return a +result dictionary with the following keys: + +Entropy # bits + +CrackTime # estimation of actual crack time, in seconds. + +CrackTimeDisplay # same crack time, as a friendlier string: + # "instant", "6 minutes", "centuries", etc. + +Score # [0,1,2,3,4] if crack time is less than + # [10^2, 10^4, 10^6, 10^8, Infinity]. + # (useful for implementing a strength bar.) + +MatchSequence # the list of patterns that zxcvbn based the + # entropy calculation on. + +CalcTime # how long it took to calculate an answer, + # in milliseconds. usually only a few ms. + +The userInputs argument is an splice of strings that zxcvbn +will add to its internal dictionary. This can be whatever list of +strings you like, but is meant for user inputs from other fields of the +form, like name and email. That way a password that includes the user's +personal info can be heavily penalized. This list is also good for +site-specific vocabulary. + +Bug reports and pull requests welcome! + +------------------------------------------------------------------------ +Project Status +------------------------------------------------------------------------ + +Use zxcvbn_test.go to check how close to feature parity the project is. + +------------------------------------------------------------------------ +Acknowledgment +------------------------------------------------------------------------ + +Thanks to Dan Wheeler (https://github.com/lowe) for the CoffeeScript implementation +(see above.) To repeat his outside acknowledgements (which remain useful, as always): + +Many thanks to Mark Burnett for releasing his 10k top passwords list: +http://xato.net/passwords/more-top-worst-passwords +and for his 2006 book, +"Perfect Passwords: Selection, Protection, Authentication" + +Huge thanks to Wiktionary contributors for building a frequency list +of English as used in television and movies: +http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists + +Last but not least, big thanks to xkcd :) +https://xkcd.com/936/ diff --git a/vendor/github.com/nbutton23/zxcvbn-go/adjacency/adjcmartix.go b/vendor/github.com/nbutton23/zxcvbn-go/adjacency/adjcmartix.go new file mode 100644 index 000000000..66ad30b82 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/adjacency/adjcmartix.go @@ -0,0 +1,108 @@ +package adjacency + +import ( + "encoding/json" + "log" + + "github.com/nbutton23/zxcvbn-go/data" +) + +// Graph holds information about different graphs +type Graph struct { + Graph map[string][]string + averageDegree float64 + Name string +} + +// GraphMap is a map of all graphs +var GraphMap = make(map[string]Graph) + +func init() { + GraphMap["qwerty"] = BuildQwerty() + GraphMap["dvorak"] = BuildDvorak() + GraphMap["keypad"] = BuildKeypad() + GraphMap["macKeypad"] = BuildMacKeypad() + GraphMap["l33t"] = BuildLeet() +} + +//BuildQwerty builds the Qwerty Graph +func BuildQwerty() Graph { + data, err := data.Asset("data/Qwerty.json") + if err != nil { + panic("Can't find asset") + } + return getAdjancencyGraphFromFile(data, "qwerty") +} + +//BuildDvorak builds the Dvorak Graph +func BuildDvorak() Graph { + data, err := data.Asset("data/Dvorak.json") + if err != nil { + panic("Can't find asset") + } + return getAdjancencyGraphFromFile(data, "dvorak") +} + +//BuildKeypad builds the Keypad Graph +func BuildKeypad() Graph { + data, err := data.Asset("data/Keypad.json") + if err != nil { + panic("Can't find asset") + } + return getAdjancencyGraphFromFile(data, "keypad") +} + +//BuildMacKeypad builds the Mac Keypad Graph +func BuildMacKeypad() Graph { + data, err := data.Asset("data/MacKeypad.json") + if err != nil { + panic("Can't find asset") + } + return getAdjancencyGraphFromFile(data, "mac_keypad") +} + +//BuildLeet builds the L33T Graph +func BuildLeet() Graph { + data, err := data.Asset("data/L33t.json") + if err != nil { + panic("Can't find asset") + } + return getAdjancencyGraphFromFile(data, "keypad") +} + +func getAdjancencyGraphFromFile(data []byte, name string) Graph { + + var graph Graph + err := json.Unmarshal(data, &graph) + if err != nil { + log.Fatal(err) + } + graph.Name = name + return graph +} + +// CalculateAvgDegree calclates the average degree between nodes in the graph +//on qwerty, 'g' has degree 6, being adjacent to 'ftyhbv'. '\' has degree 1. +//this calculates the average over all keys. +//TODO double check that i ported this correctly scoring.coffee ln 5 +func (adjGrp Graph) CalculateAvgDegree() float64 { + if adjGrp.averageDegree != float64(0) { + return adjGrp.averageDegree + } + var avg float64 + var count float64 + for _, value := range adjGrp.Graph { + + for _, char := range value { + if len(char) != 0 || char != " " { + avg += float64(len(char)) + count++ + } + } + + } + + adjGrp.averageDegree = avg / count + + return adjGrp.averageDegree +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/data/bindata.go b/vendor/github.com/nbutton23/zxcvbn-go/data/bindata.go new file mode 100644 index 000000000..f3a0c010c --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/data/bindata.go @@ -0,0 +1,444 @@ +// Code generated by go-bindata. +// sources: +// data/Dvorak.json +// data/English.json +// data/FemaleNames.json +// data/Keypad.json +// data/L33t.json +// data/MacKeypad.json +// data/MaleNames.json +// data/Passwords.json +// data/Qwerty.json +// data/Surnames.json +// DO NOT EDIT! + +package data + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindataFileInfo) Name() string { + return fi.name +} +func (fi bindataFileInfo) Size() int64 { + return fi.size +} +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} +func (fi bindataFileInfo) IsDir() bool { + return false +} +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _dataDvorakJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xb4\x98\x57\x57\x1b\x41\x0c\x85\xdf\xf9\x15\xb0\x74\x30\xbd\xf7\xde\x7b\x6f\xa6\x77\x30\xbd\x17\xf3\xdb\x33\x26\x39\x99\xef\x9e\x78\x96\x7d\x88\x5e\x72\xc6\x61\xf9\xa4\x95\xae\x34\xd7\x7c\x14\x14\x16\x46\x63\xf7\xfb\xb7\x67\x51\x67\x61\xee\x83\xfb\x58\xef\x8e\x5b\xdf\x47\xf7\xa1\xa3\x22\x4a\xfd\x39\x5f\x3f\x65\x32\xf9\xce\xd1\xd6\xc7\xdf\x67\xa2\xcc\xb4\x3f\xdf\x2f\x46\xdf\xc7\xed\xdf\xff\x13\x35\x10\xbc\xf7\xf5\x33\xb8\xb1\xdf\xc3\xca\xd3\x91\xfc\x82\x90\x1b\x49\x6e\x28\xfa\x99\xdc\x54\xec\xc9\xa9\x6e\x8d\x22\xe4\x26\x92\x91\x4f\x90\xdc\x5c\xe2\x69\xb5\xbd\x12\x45\xc0\xcd\x04\x23\x9d\x20\xb8\xa5\xd4\xc3\x6e\xe7\x25\x88\x80\x5b\x08\x46\x36\x41\x70\xeb\x8e\x87\xbd\x6d\x48\x10\x01\xb7\x12\x8c\x6c\x82\xe0\xb6\x32\x0f\x3b\x19\x95\x20\x02\x6e\x23\x18\xd9\x04\xc1\xed\x55\x1e\x76\x3a\x26\x41\x04\xdc\x4e\x30\xb2\x09\x82\xa1\xf6\xe8\x70\x48\x82\x08\xb8\x83\x60\x64\x13\x04\xd7\x57\xca\x58\x30\x88\x80\x8b\xcc\x46\xc4\xfd\xcc\xa3\x05\x81\x79\x11\x1c\xe7\x62\x7f\x20\x4c\x2e\xb6\x1a\x91\x12\xab\x11\x29\xb5\x1a\x91\x32\x2b\x25\x97\x5b\x35\xaf\xc2\x4a\xc9\x95\x56\xb7\x48\x95\xd5\x50\x57\x13\x5c\xd7\xe7\x1f\xdc\xce\xe6\x0d\x12\xa5\xd3\x9f\xf9\x7f\x50\xb3\xab\xe4\x14\xc9\x9c\x52\x69\x19\xef\x24\x8e\xc5\xcd\x9c\xb4\x52\xc8\x35\x24\x3f\x2c\xf9\x07\x99\x7f\x4f\xf5\xcf\x45\x7a\xdf\x54\x70\x2d\xc1\x14\x13\xb3\xe4\x20\x73\xde\x8e\x47\x24\x7b\x01\xd7\x11\xcc\x3e\xb3\xff\xa8\x38\xb3\xcf\x15\x36\x85\xb7\x15\x70\x67\x68\x44\x20\x7f\xa9\xe5\xdd\x42\xb0\x2c\x02\xee\xb2\x02\x77\x9b\xc9\xa2\xc7\x4c\xca\xbd\x56\xba\xe8\xb3\xd2\x45\xbf\x99\x37\x1c\x08\x09\x43\x7a\x49\x04\x7b\xd6\xd5\x19\xde\xca\x83\xcc\xf9\x75\xdd\xff\xd2\xd1\xb0\x3f\x9f\x8d\xfb\xf3\xd5\x4c\x32\xc9\x0d\x11\xcc\x0b\x87\x17\x11\x17\x26\x57\xfc\xe3\xb2\x04\x17\xf0\x30\xc1\xe7\x13\xf9\x8d\x1f\x03\x32\xfb\x83\x41\x7f\x76\x6f\x2b\xe0\x11\x82\x59\x3f\xce\x02\x45\xf6\xb4\xe2\xcf\x17\x93\x32\x95\x02\x1e\x25\x98\x97\x3a\x2f\x7b\x5a\x58\x66\xcf\x3e\xb8\xb7\x15\xf0\x18\xc1\x7c\x7d\xc2\x58\x6f\x5e\x4a\x2c\x8b\x0b\x22\xe0\x71\x82\x99\x01\x33\x23\x8c\x0d\x83\x42\x72\xf5\x16\xf0\x04\xc1\xac\x1f\xcb\xc2\x37\x61\x70\xca\xf3\x72\x4a\xc1\x93\x04\x63\x2d\xca\x26\x60\x40\x07\x48\xa4\xe3\x29\x82\xd9\x65\xc2\x28\x43\x64\x19\x0b\x9e\x26\x98\xe2\xa7\xef\xe1\x4a\xe2\x76\xe5\x05\x7c\x3d\xab\xa5\x98\x21\x98\x82\x67\xc7\xd9\xb0\x97\xb5\x64\x19\xcf\x12\x4c\x00\xb3\xe7\x42\x65\x96\xcf\xab\x12\x50\xc0\x73\x04\xf3\xae\xe3\x46\xe3\x14\xb2\xa9\x6c\xb6\xdb\x74\x02\x9e\x27\x98\x00\xde\x1b\xf4\xf2\x94\x21\x1b\xec\x02\x0a\x78\x81\x60\xec\x57\xd9\x1b\xcc\x12\xca\x89\xad\xf1\x22\xc1\x9c\x30\xae\x4a\x2a\x84\xf5\x76\x4a\x60\x83\x05\xbc\x44\x30\x1f\x24\x80\x12\xe3\x4d\xe7\x3c\x1b\x1b\x29\xe0\x65\x82\x29\x31\x66\x4f\x85\x30\x38\xa4\x97\xdb\x1b\x02\x5e\x21\x98\xb5\xe4\x0e\x66\xc3\x38\x85\x18\xef\x5c\xed\x05\xbc\x4a\x30\x33\x60\x66\xd4\x2e\x5e\x3f\xb6\x79\x6b\x04\x73\x0d\x72\x58\x18\x04\x43\x11\x0b\x5e\x27\x98\xaf\xc6\x57\xe6\xaa\xc4\xd8\xc7\x82\x37\x08\x66\x5d\x39\x14\xbc\xa6\xb8\x9b\x19\xdc\x0d\x8b\x80\x37\x09\xe6\xec\xb3\xae\x90\x58\xc8\x23\xfd\x93\xf1\x16\xc1\x18\x84\xa0\xc9\xa2\x93\xa3\xbe\x9d\xee\x05\x9c\x4e\x93\x9c\xe0\x9b\x4c\xe2\x94\xb7\x09\xc6\x46\x4f\x02\x13\xf3\xe9\xd2\x17\xf0\x8e\xd5\xdf\xc9\x76\xad\xbe\xec\xed\x05\x8c\x6c\x10\x10\x63\xa3\x05\xbc\x6f\xe6\x90\x0f\xac\x1c\xf2\xa1\x95\x43\x3e\xb2\x72\xc8\xc7\x56\x0e\xf9\xc4\xca\x21\x9f\x5a\x39\xe4\x33\x2b\x87\x7c\x6e\xe5\x90\x2f\xac\x1c\xf2\xa5\x95\x43\xce\x58\x39\xe4\x2b\x2b\x87\x7c\x6d\xe5\x90\x6f\xac\x1c\xf2\xad\x95\x43\xbe\xb3\x72\xc8\xf7\x56\x0e\xf9\xc1\xca\x21\x3f\x5a\x39\xe4\x27\x2b\x87\xfc\x6c\xe5\x90\x5f\xac\x1c\xf2\xab\x95\x43\x7e\xb3\x72\xc8\xef\x56\x0e\xf9\xc3\xca\x21\x7f\x5a\x19\xe4\xac\x95\x41\xfe\xfa\xef\x76\xd3\xfd\x9b\x2d\xc8\x16\xfc\x0a\x00\x00\xff\xff\xd5\xc4\xca\x21\xce\x20\x00\x00") + +func dataDvorakJsonBytes() ([]byte, error) { + return bindataRead( + _dataDvorakJson, + "data/Dvorak.json", + ) +} + +func dataDvorakJson() (*asset, error) { + bytes, err := dataDvorakJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/Dvorak.json", size: 8398, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dataEnglishJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x5c\xbd\x4b\x9a\xe3\xca\x0e\x34\xb6\x15\x7f\x9a\xf4\xe4\xae\xc0\x6b\xf0\x0e\x3c\x4a\x92\x29\x31\x4b\x24\x93\x87\x0f\xa9\xd4\xde\xbc\x81\x88\x40\x52\xfd\x0f\xee\xed\xea\x3e\x55\x2a\x32\x1f\x78\x04\x02\x81\xff\xef\xf6\xff\x94\xfd\xb8\xfd\xdf\xff\xef\xff\x75\xfb\xd4\xf3\xf6\xbf\x5b\xb1\xff\x1d\xd5\xff\x6f\xcc\xf6\xff\xc9\xff\xb7\x0c\xf8\x7b\x3a\xfc\xbf\xfb\xff\xd5\xbb\xfd\xdf\xec\xff\xfd\xad\x7f\xdd\xfd\xff\x16\x7c\x1b\xbe\x7e\x2e\xf5\xed\xff\xf4\x67\xb6\xff\xbf\xd7\xcd\xfe\x7f\xf1\x4f\x1d\xd3\xcb\x7f\x6c\xfe\xd8\xff\x0d\x75\xf9\xe3\x3f\xfc\x73\xee\x07\xfe\xfb\x81\x7f\xb4\xff\xeb\xfc\x7b\xaa\x7f\x9c\x3d\x94\xff\xec\x3b\xf9\x87\xbe\x33\x1e\xe0\x0f\xbe\x2e\xc7\x68\x7f\xec\xf8\xf6\xd3\x7f\x32\x4d\x13\xbe\x07\x7f\xa4\xcd\xbf\x17\xaf\x50\xfd\xfb\x52\x57\xf1\x4d\x5b\x79\x8c\x07\x3f\xf7\x0f\xbe\xe5\x91\x0f\x7c\x23\xfe\xc2\xef\x79\xd4\xb2\x3c\xec\xcf\xa9\x3c\xfd\x1f\x3f\x39\xf9\x27\x94\x3b\xbf\xcf\x7f\x29\x3e\xb7\x4f\xfe\x80\xe7\x8a\xc7\x5b\x0e\xbe\xfb\xf2\xd4\x52\xe1\x21\xb9\x08\x0f\xbc\x78\xf1\x95\xc0\x62\x8d\xfa\x57\xfe\x88\x7e\xf3\xe2\xff\x3f\x94\x01\x6b\xea\xab\xb3\x67\xfc\x92\x8a\x65\x7e\xd4\xca\x3d\xc8\xfe\x9f\xb6\x6c\xef\xea\x5f\x70\x55\xea\x39\xf9\x7f\x9c\x6a\x7d\xe2\xa7\x33\xf6\xa1\x70\x7f\x0a\x96\xa3\x3e\x93\x7f\x7f\x97\xfa\x27\x9f\x1c\x0b\x3f\x67\xbc\xc2\xc1\x25\x2b\x7f\xf0\xc7\x7d\xab\x33\xde\xf4\x83\xd5\xd4\x3a\xe2\x75\x7a\xfd\x26\x7b\x4c\x7e\xc0\x27\xef\x78\xb5\x1d\x7b\x86\xdf\x8b\xad\xde\xed\xa9\x7d\x31\x1e\x78\x1e\xee\x68\x9f\xce\x3d\xeb\xbf\xe1\x20\xe8\x85\xfc\x87\x76\x3c\x1d\x1e\xff\x48\x58\x74\x3c\xd8\x1b\xff\x7c\xee\xd8\x8b\xe3\x98\x70\x72\xf8\xdf\x97\x9c\x07\xac\xcb\xb2\x24\xfc\xf5\x85\x9d\x79\x67\xee\xea\x51\x2b\xf7\x09\xcf\x5d\xfe\xe0\xd0\xed\x27\xff\xdb\x98\xfd\x05\xe7\xca\x85\xe7\x0f\xf2\x98\xed\x75\xdb\x3e\x5c\xc3\x2d\x4e\x37\x3e\x61\xca\xb1\xbf\xfe\x4a\x09\x3f\x9f\x3e\x38\xa6\x43\x7d\x2f\xf8\xeb\x82\xb7\xf2\xef\x3e\xfd\xbc\xd8\xe7\x62\xc9\x3f\xb1\xcb\xf8\xa0\x7d\xd4\x1a\xa6\xe5\x13\x1f\xb7\x27\x6c\xfb\x7c\xf6\x23\xff\x03\xde\xf7\xee\x1f\x6e\xaf\x85\x45\xbd\xdf\xf1\x9b\xf8\xfd\x76\xbc\x70\xcc\x1e\xe5\xc5\xa3\x33\xf1\x77\xd4\x93\x67\x7b\xcc\x93\x1f\xca\xe3\x8d\x6b\x9c\x26\xff\xde\x35\xd7\x75\xe2\x49\xf2\xdf\xb5\x1f\x3c\x17\xef\x84\xfb\x5c\x16\x5c\xf9\x7b\xc1\x4d\xb7\x8b\x18\x2f\xfa\x48\x71\xa9\x97\x87\xd6\x01\xaf\x31\xd4\xbc\xf3\x08\xf4\xbc\x76\x47\xc5\x5b\x3d\xec\x68\x1e\xd8\xee\x3b\x97\xb7\xcb\xc7\x81\x05\xd6\x06\x2d\xba\x7f\xfe\x0e\xfe\x0b\xb8\xc5\xf7\xb2\xed\xfc\xb1\xa9\x64\xbe\xd4\xc1\xab\x76\xcf\x79\xd2\x4f\xb7\xf5\x7a\xd7\xcd\x5f\xc9\xaf\x30\xbe\xd7\x1e\x1b\x27\x8a\x07\x2b\xdd\xf9\x0b\xa7\xb4\xeb\x82\xe1\xd8\x0d\xf8\x45\xcf\x9c\x57\x3d\xbe\x2f\x0a\xed\xc6\x56\xcf\x85\x8b\x52\x57\x5d\x32\x9e\xa2\xf2\x07\xef\x74\xfa\x4f\x16\xbd\x6f\x9a\xec\x91\x79\x22\xf7\x23\xf3\x94\x2e\x07\x0e\xe3\xbc\xf1\xbb\x71\x27\x70\x06\x6c\x4f\xf0\xcb\xbb\x02\x7b\x82\x1b\x3f\xa6\x75\xcd\x4b\x1e\x62\x23\x79\x85\xf9\xe1\xc7\xf6\xe1\x2b\x3e\xb9\x13\xef\xad\x6a\xc7\x37\xdf\x5c\x6d\x27\xbf\x65\x4e\x03\x2f\xc2\x1b\x0b\xc7\x7f\x7c\x9c\x79\xe7\x95\xc4\xd6\x70\x0b\x70\xd3\x66\xdc\xea\x2d\xcf\x79\xee\xb0\x3e\x66\xf8\x0e\xad\x67\xfe\xa3\x3d\xb4\x7f\xe3\xb2\x0f\xf8\x99\x29\xd3\x5a\xaf\x53\xea\xfd\x4f\x5b\xa6\x6c\x1b\x45\x7f\x00\xb3\xa3\x35\xe9\x8f\x53\x16\x69\xcc\x69\xc3\xef\xc4\xb9\x5f\x0a\x7e\xee\x9e\xf4\xb1\x79\xa2\x09\x38\x92\xec\x3f\x2e\x59\xd2\xd2\xda\x37\x15\xff\x2e\x33\x33\x1b\xbe\x6f\xd6\x61\x99\xb9\x1a\x59\x57\x2a\x2f\xb1\x18\x1b\x7f\x25\x9e\xbe\x4f\x73\x98\x17\x7e\xae\x9f\x0f\x1a\x3f\x5c\xd0\x7b\x9a\xcb\xc4\xcb\x5d\x27\x9a\x98\x38\x64\x76\x73\x76\xfd\x84\xfd\xe2\xc9\xef\x5a\x19\x32\x5c\xdf\xfe\xc4\xea\xe2\x28\xcd\xf4\x53\x66\x92\xb9\x6e\xb5\x99\xdd\x38\x97\x34\x02\xef\xb1\xe0\x26\x9b\xe3\xd8\x7c\x33\xb6\x8a\xb5\x9f\xf2\xdd\x7f\xfc\xc9\x1d\x3b\x6a\x5c\x05\xb7\xe6\x78\x70\x18\x90\xba\x62\x57\xf5\x32\xfc\xe3\x9d\xe1\x5e\x4e\xd8\xe5\x79\xd6\x21\xf2\x77\x59\x37\xdb\x45\x78\x8b\x04\x9f\x52\x36\x7c\x54\xa1\x97\x82\x9f\xb9\x6f\x25\x63\xf9\xd2\x64\xbf\x69\xe0\x37\xeb\x98\x2d\xf9\x97\x0b\xbf\xc1\xd9\xfc\xd4\x0e\x9f\x59\xbb\x89\x26\xb2\x2c\xe7\x81\x0d\xd4\x0d\xb1\x9b\x37\xf1\xe0\x9a\xa3\xe3\x47\xb8\x43\xe7\xf6\xf9\xd6\x0f\x78\x85\x05\xbe\x63\x4e\xba\xfa\xf3\x47\x8b\xda\x5f\x47\x26\xff\xda\xa1\xe1\x89\x49\x2f\x19\x9b\x51\xbf\x3c\x75\xfa\x0f\x7e\x51\x78\x3e\x71\x0c\xc7\x73\x83\x91\xa8\xb0\xab\x15\xfe\xdf\xd6\x1a\x9b\x69\xdb\x45\x7f\x70\x1c\xd8\xb7\x89\x67\x60\x2f\x0b\x4e\x60\xfe\xed\xcf\x38\x7a\xf8\x90\x27\xed\xdf\xc8\x47\xf6\xa3\x82\xf7\xaa\x34\x13\x3d\x0e\x71\x2c\xd7\xb9\x98\xb5\xbc\x31\xe4\x60\x84\xe0\x57\x1e\xd7\x8c\x47\xc0\xfe\x0a\x2f\xf4\x81\x97\xd8\xe9\x08\x07\x6e\xeb\x41\xaf\x5c\xf9\x1c\x0f\x3e\x96\x1b\x4d\x9a\x8c\xba\x2d\x72\x02\xe7\xba\x9a\xb1\x18\xda\x8e\xed\x5c\x52\x1a\xa6\x13\x0e\x60\xae\x38\x80\x27\xbf\xed\x2d\x67\xb5\xe7\xbe\x62\x77\x56\xbe\xda\x44\xb7\x70\x6c\x27\x23\xa4\x7e\xac\x15\x8e\x9d\x97\xd8\x0c\x33\x63\x1e\xfb\x06\x98\x87\xd3\x16\x89\x56\x23\x27\x9c\xdb\xcb\x53\xe3\x48\x7a\x28\xe7\xff\xf5\xce\x73\x6b\xb7\x4d\xc7\x9d\x2e\xca\xae\x13\x5c\x02\x7f\xa6\x37\x93\x86\x5f\xb3\x9d\xf0\x8a\xf5\xc5\xab\xf6\xe1\x8b\xaf\x66\x3f\xf0\xa1\xdd\x27\x2e\x6b\x57\xb1\xc8\xc3\xa6\x23\x84\x25\xa4\x2b\x9c\x0b\x1e\x6b\x4e\x9b\xad\x08\xde\xd0\x3c\x20\x5e\x31\xe9\x64\xa5\x30\x86\x19\xaf\x64\xbf\x87\x0e\x65\xa6\x17\x5d\x47\xfe\x5a\xdb\x49\xfe\xda\x21\xcd\x0b\xee\x2c\x16\xd2\xaf\x2e\x42\x97\x8d\x9f\xd2\x27\xbc\xc3\x71\x6e\x38\x76\x65\x87\x91\xa9\xb6\x49\x1b\xae\xd2\xb3\x60\x57\x6c\xe1\x68\x08\xc6\xcc\x70\xca\xde\xf9\x81\x53\x86\x6d\xf0\x87\xe3\xb3\x28\xc4\xb8\x73\x43\xcc\x9a\xd2\x23\xd1\x1e\x99\x71\xd6\xbd\x49\xdc\x4c\xbd\xca\x87\x16\xd4\xe3\x1c\xfc\xb2\xeb\x15\xd3\xc2\x87\x0d\xb3\x65\x66\x99\xf7\x84\xbf\x0f\x61\xe6\x4e\xe7\xd4\xe5\x74\x1e\xe5\x7e\xfa\xbe\x3f\x68\xc4\x6d\xfb\xf1\xd0\x5b\xfa\xfb\xd1\x61\xc1\xe9\x61\x40\xcf\x9b\x96\xee\x1b\x63\x11\x73\xdb\x6f\x1e\xe3\x32\xaf\x75\x3b\x18\xdf\x6e\xb4\x83\x77\x6c\xed\xb3\xe8\x10\xf2\x06\x1c\xd8\xb1\xc7\x94\x9a\xa5\x56\x48\xcb\x07\xda\xdd\x5b\xe2\xbd\x60\x53\xf6\xf8\x26\xed\x7e\x57\x68\x59\x4f\x06\x29\x76\xa6\x7c\x51\x72\xd1\x9b\xce\x1b\x0f\x60\xd6\xd1\x1b\x92\x87\x3a\x8c\xf8\x18\x4c\x67\xdc\x47\x33\xd7\x38\x27\x70\x54\x58\xab\x9c\x10\xfd\x58\x4c\x5b\x18\x06\x54\x06\xa8\x38\x2e\xfd\x44\xf7\x3c\xd2\xa3\xd9\xfe\xf8\xb3\xfc\x67\x3e\xf4\x28\x38\x2e\x87\xce\xdd\x3d\x31\x09\x41\x28\xe5\xa1\xe7\xce\x37\x61\x38\x19\xde\xc8\x22\x6e\xc4\x46\xe5\x7e\xb7\x70\x6f\x09\x33\x93\x69\x14\xf7\xb5\x98\xf3\xe6\xc1\xd0\x5b\x9b\x45\x96\x0f\x78\xe7\x61\x90\x1d\x18\x19\x94\x74\x34\x6b\x45\xb7\xe6\x9e\xb1\x7b\xe1\x7c\x3d\x2d\xa0\x9f\xe7\xbf\x56\x58\x82\x8f\x2f\x1a\xfc\x83\xc7\x75\x5a\xaa\xb2\x2c\x58\x0b\xc4\x72\xb1\x7f\xb8\x1d\xe3\xb9\x77\x49\xae\x41\xa6\x65\xc5\x89\xb2\x83\xf6\x66\xf4\xc5\xb0\xd8\xc2\x4f\x3a\xf2\xcc\x80\xdf\x3c\x18\xd2\x01\xb3\xbd\x30\x4f\xe3\x65\xd7\xc7\x04\x4b\xbf\x97\xa1\x39\xd4\x1b\x82\x0f\xae\xc7\x3e\x31\x00\xdb\x68\xd8\xde\x57\x5c\xec\x76\x99\x26\x91\x19\x81\x7b\x1c\xfc\x87\xca\x87\x5d\x0b\xee\x1a\x32\x0b\x2d\x34\x7c\x54\x97\xf9\x02\x48\x04\x07\x5e\x85\x89\x3b\x63\xf7\x83\x2e\x95\x0f\xf1\xb5\xd9\xf8\xe0\xbc\x95\x7a\xf2\xb2\x8c\x0c\x30\x6c\x7d\xf8\xdc\x63\xc1\x8e\x26\xd9\x5f\xbb\x0a\xc8\xac\xaa\x1f\x2b\x5e\xaa\xbb\x36\x6e\xe5\x9d\xee\xb1\x69\xff\x9d\x05\xbf\x7f\x39\x15\x63\x8d\x8a\xac\x76\x3e\xbc\xa5\xae\x13\x6f\x24\xdc\x3a\x43\xe5\xa5\xea\x34\x3c\x18\x94\xba\xeb\x62\x56\xc0\xa4\x25\xe7\x19\x87\xbf\x2c\x0a\xb1\xdc\xbe\x33\x68\x0c\xb3\x78\xae\x3a\xcf\x69\xc3\x77\xcc\x99\x7e\x12\x9e\xa7\xdb\x22\x2f\xf0\x8f\xc2\x12\xd2\xc6\xa6\x3b\xd7\x4a\xee\x17\xbb\xb9\xc9\xe1\x86\x6d\xf2\x08\x90\xff\xd9\xd2\x42\xee\xe0\x58\x69\x3a\x5f\x5c\xf8\x5d\xe6\xc9\xec\xbd\x3c\x59\x3f\xd1\x82\xd9\x12\x31\xe1\xe2\x4f\xdc\xf3\x84\x9f\x2f\xbf\x58\x36\xbf\x20\xb8\x2d\x1b\x73\xe6\xd4\xed\x75\x32\xcb\x40\xd7\x5f\xdf\x4c\x33\xd2\xa0\x8b\x52\xb4\x18\x0b\x03\xc3\x4c\x83\xc4\x10\x01\xbb\xb9\xe6\xbe\xe0\x7a\x75\x7c\xf9\x89\x19\xb3\x9d\xf9\x3f\xbc\x88\x71\xc1\x26\x5c\x29\xdb\xc5\xe9\x46\xbf\xa1\x7b\xc2\x87\xb6\x35\xd2\x3d\x54\xc8\x73\x4f\xe7\x44\x97\x4f\x7b\xa3\x98\xbf\xf2\x98\x76\xc8\x0d\x66\x5b\x9a\x71\xd7\x51\xe3\xc3\xc0\xec\x4c\x8c\x1f\x7e\x72\xe4\x50\x4f\x5e\x9b\xcd\x8c\xe1\x8c\x4c\x51\x5b\x6f\x46\x54\x59\xe8\x11\x27\x30\xe1\x29\x2c\x24\xd8\x0b\x4d\x81\x6d\xf7\x2e\x44\x60\xa5\x77\x33\x93\xa6\x6c\xb9\x02\xe3\xf0\x93\x8d\x6f\xb5\xdf\x4f\xc8\xa6\x1e\x3a\x33\x8f\xb6\xcb\xf6\xa8\x1b\xc2\x81\x76\xf5\xe0\x5e\xd3\x43\x7e\x72\x2a\x7f\x71\x77\xcc\xd6\xdb\x93\x30\xee\x5c\x26\xc6\x07\x7b\xfe\xe5\x26\x20\x4b\x34\x33\xc8\x2c\xc6\x9e\x01\xbe\x95\x87\x71\xf7\xb4\x63\xe0\x8d\x3d\x94\x71\x9b\xe1\xd4\x69\x61\x6e\xb4\x0c\xfc\x16\x7a\x4e\x19\x34\x33\xfd\xda\xfe\xfc\x6b\x57\x17\x89\xa7\xbb\x38\x3d\x78\x36\x2f\x54\x98\xea\xee\xe5\x81\xc5\xaf\x70\x2d\x5b\x36\x8f\x6b\xf6\x7a\x1f\xcb\xaa\x93\x89\xdf\x92\x10\x05\x4f\xf1\xf3\x63\xa5\x0d\xf3\x18\x41\xe9\xfd\xfd\xd4\x03\xbe\x2d\xf1\x80\xeb\x3e\x69\x64\xe2\xde\x7a\x24\x80\xc7\xf3\x18\x08\x9b\x58\x19\x99\x3c\x19\x99\x98\x33\x85\xa5\x09\x97\xe1\xff\x56\xbb\x97\xdb\x15\xa6\x1a\x55\x8e\x68\xe5\xeb\x78\xdc\x17\xc7\x6b\xce\xf1\x18\x9e\xdd\xb9\x13\xdb\x0f\xf3\xbe\xbc\xaa\x3d\x03\xcb\x3b\xad\x8b\x3b\x59\xd8\x00\x9e\xe9\x45\x9e\x75\xe3\xa5\x90\x5b\x44\xb0\xe0\xa9\x2b\x13\x7b\x8b\x27\x68\x4e\x13\xa3\xc4\x49\x9f\x3c\x6c\x48\x72\x7b\x0b\x59\x2b\x8d\x02\xf6\xb8\x2f\x07\xa3\xb0\x0c\x70\xc3\x1c\xe6\x41\x8f\x73\x78\xf2\x81\x98\x78\xe2\xee\xed\xe7\xb6\x6e\x74\xa6\x05\x37\xd8\x7c\x85\xa7\x8d\x8c\xdc\x56\xfa\x57\x8f\xac\xf4\xeb\xe1\x59\x7f\xfb\xbc\x02\x5a\x43\xe8\xf0\xf9\x23\x78\x70\x50\xb0\x78\x28\xd8\xb1\xeb\xbc\xf9\x3d\x86\x15\xcd\xba\xd3\xda\x72\x4b\x31\xe5\x95\x3b\x1c\x4d\x26\xf0\x8c\xe2\xcb\xac\x0c\x63\x8c\x5c\x92\xc1\x8e\xad\x02\x63\x60\x5b\xe9\x32\x10\x71\x98\xd3\x5f\xc1\x28\x58\x08\x07\x51\x16\x9e\x39\xbe\xf0\x16\xc9\x6a\x59\x5e\x75\xa2\x95\xb3\x57\x84\x75\x58\x4b\xee\x15\x33\x63\x4d\x91\x74\x0d\xf6\x94\xbc\x09\x34\x47\x0a\xd7\xea\xab\xf0\x68\x21\xb3\xe8\x15\x20\x59\x88\xb3\x30\x6d\xd5\x9d\x32\xdf\x6e\x3f\x46\x17\x08\xd7\x78\x17\x8e\xe9\x3f\x20\x30\x80\x6b\x37\x98\x75\x97\xad\xaa\x8c\xbf\xf1\x3e\x85\x19\xec\x82\x75\x67\x7c\x9d\x26\x3d\x00\xdf\x93\xa9\x4e\x1a\x66\x04\x0b\x4a\xef\x70\xf3\x4f\xd9\x9d\x91\x0f\x99\x5f\xc8\x73\x86\x6c\xce\xa6\xe8\x2e\xfa\xe9\x22\xb8\x6b\x89\xc3\x1c\x5b\xe0\x71\x35\x8e\x66\x46\x1c\x6f\x3e\xe6\xc9\x84\x7d\x67\x6e\xe2\x3e\x8c\x40\x42\x9d\x26\x66\xc1\x47\xe1\x9d\x77\x48\x4b\xa9\xe3\xc9\x7c\x19\xbe\x5f\x5e\x84\xdf\xb2\xf8\x37\xdf\x10\x7f\xe1\xb0\x4e\xa7\x27\xa6\x8b\xa5\x7a\x3c\x81\x48\x95\x78\x9f\xfc\xb4\x96\x39\x3d\xe8\xf2\xef\x5c\x8e\x3e\xc9\xe5\x75\x93\x12\xe9\x63\x63\x86\x60\xe7\x48\xbf\xea\x9e\x5e\x58\xb2\xe4\x91\xb0\xc2\x13\x47\x1e\x70\xe8\xb3\x99\x44\x9a\x5d\xf7\x66\x48\x19\xec\x04\x2c\xba\x58\xb8\x8b\x5b\xda\x4b\x66\x9a\x38\xa5\x5f\xbc\xbc\x5d\x6e\xac\x4e\xea\xfb\xb0\x9d\x6f\x1a\x68\x5b\x74\x3a\xb0\x99\xd7\xc4\x02\x98\x9d\x26\xd7\x97\x4c\x0f\x64\x89\x59\x15\x1a\x97\x3d\xd4\x96\x75\xe5\x73\x2c\xdd\xbe\xe2\xec\x0b\x11\x9e\x2b\xd3\x3b\xbb\x30\x8f\x85\xde\x70\x36\x1f\x87\xef\x6d\xe9\xcc\x96\x19\xad\xec\xa3\x50\x3a\xde\xee\x8d\x3e\x86\x0e\x9a\x01\x4e\x12\x62\x40\x9b\x70\x30\x5e\xb9\xdb\xe6\xe1\x9e\x9a\x95\xc6\x99\xf5\x00\x52\x21\xd1\xc6\x50\xc7\x31\xb3\x95\x9b\xa6\xe0\x63\x13\x74\xbb\xdd\x14\xae\x5e\x6f\x47\x7b\xf5\x93\x98\x4d\xdb\x0f\x5c\x60\x97\x47\xae\xd3\xb9\xf0\x8e\xb8\x7f\x2c\xf8\x98\x2c\xab\xf5\xb0\xed\x33\x2f\xc4\x14\xfa\xa0\x0f\x1e\xeb\xca\x9f\xb7\x2c\x2f\x77\x11\x8a\xef\x8c\x68\xed\x15\xb1\xbc\x6b\x5a\xe9\xb6\x1b\x7e\xb6\x0a\x06\x38\x72\x5c\xc7\x1b\x5c\x49\xc3\x49\x6c\xaf\x4e\x38\xab\x07\x51\x91\xae\x98\x11\x21\x2e\xb0\x0b\x8f\x85\x9d\x25\x26\x51\x22\xf8\xb6\x35\x26\xa0\xec\xd1\x3f\x4e\x37\x0d\xef\x9d\x07\x8f\xae\x20\x62\x8d\xbe\xec\xb2\x65\xa7\x45\x5d\x82\x93\x96\xac\x40\x8f\x89\xe7\x4b\x0e\xcb\xac\x91\xac\x1b\x20\x37\xfe\x5e\x47\x1f\x75\x8e\xf0\x81\x16\xcd\xbe\x08\x18\xfb\xc9\xc3\xcf\xf5\xc4\x6e\xcc\xa4\xef\xfb\xd7\xa9\xd2\xdd\x33\xfb\xee\xbb\x60\x21\x2b\x43\x47\x07\x28\xe4\xec\xb6\x2a\xd4\x21\x7c\x6f\xc7\x48\x15\x86\xbe\x30\xfe\x5a\x64\x08\x2c\x85\x72\x84\xb5\x3d\x37\xd3\x25\x22\x72\xcb\x95\xbf\x21\x29\xb9\x23\xf4\xdb\x60\xd7\xf1\x79\x2b\xef\x88\xbb\x13\xde\x1b\xdf\xd9\x66\x61\x62\x5d\xdc\x69\x32\xeb\xe0\x99\x92\xff\x41\x9a\x8a\x7f\x71\x50\x57\xf0\x67\xb9\x33\x2c\x54\x36\xb2\x9e\x71\xdb\xcd\x78\xc2\xb3\x73\x21\x2b\x2a\x49\xa7\x2e\x5e\x2c\xf3\xa4\x4f\x59\xdc\xd0\xc1\x64\x9e\x42\x1b\xde\x9f\xdc\x4c\xc5\xad\xc5\x22\x37\xa6\x18\x3b\xce\xf4\xef\x8d\xf0\x5b\x3b\x46\xf7\x89\xae\xd0\xbc\x7c\xa0\x9f\x0d\xc4\x46\xdc\xe5\x21\x16\x17\xc0\x7d\xe7\x88\x53\xf8\x8b\xad\x20\x54\xfe\x73\xf2\x08\x5b\x74\x6f\xbf\x0d\x36\x74\xa7\x35\xb1\x74\x0a\x05\x34\x45\x87\x8c\x34\x88\xa0\xfb\xc1\x0e\x23\xa4\x57\x37\x6b\x44\x07\xd2\x4d\x2d\xcc\x20\x5e\xe1\x29\x06\x83\xaf\xc5\x7e\xe5\x1e\x3f\xe9\x2f\x85\x5f\x63\xbe\xf2\x86\x22\x8f\x9d\x1c\x5e\x80\x89\x31\x9e\x9d\x9a\x9e\x01\xae\xbc\xc4\x7e\x30\x72\xda\xf2\xca\xec\x22\x92\x60\x62\x41\x45\xf0\x3a\x2e\xc8\x2e\x6f\xd3\x25\x9c\xad\xc8\x4e\x86\x7a\x76\xc7\x2d\x70\x75\x41\x4c\x0d\xed\xee\xeb\xca\x83\x4e\xfc\xde\x5f\x60\x53\xf6\x76\xde\xef\x78\x84\xa9\x1d\x83\x7e\x9c\x2a\x7e\x2f\x53\x9c\x7d\x1c\xf1\x68\x3d\xb1\x8a\x89\x7f\xcc\xca\x60\x7e\xaa\x42\x33\xfc\xab\xd9\x1e\x16\xdc\x6c\x67\xcc\x4b\x32\xd8\x2f\x17\xe4\xb5\x0c\x58\xc3\x2d\x07\x48\x14\xa1\xed\xc3\x2e\xf2\xc1\x25\x7a\xea\x3e\xd8\x7b\x45\x0e\xee\x09\x34\xf3\x08\xcb\x2b\x26\xfc\xd6\x27\xfd\x95\x39\x21\x5a\x52\x33\x7e\x93\x5c\xc5\xac\xe3\xbd\x9e\xdd\x54\xfa\x1b\xc1\x4e\xc6\x24\xfb\x44\xfb\xa6\xec\x15\x8b\xdf\xf3\xba\x4d\xb4\xcc\x1e\x5a\xe9\xda\xba\x57\xc6\x51\x18\x5e\x3c\xe3\x1e\x75\x12\x15\x5e\x89\xf3\x58\x4e\x2c\x1b\x7a\xc2\xe6\xf8\x25\x60\xc0\xdb\xde\xf9\xdc\x03\xdb\x77\x0b\x4f\x97\xd7\xd5\x9d\x89\xb3\xb9\xdd\xe5\x2a\x96\x32\x87\x5e\x6a\xcf\x63\x3d\x54\x7f\xf6\xed\xa4\xd7\xee\x11\x6e\xc1\x8d\xaa\xf8\x51\x88\x40\xd9\x65\xc6\x59\x6a\xf5\x08\xa4\x4f\xb2\x89\x40\x1e\x36\x9e\x21\x5f\x42\xee\x39\x22\x00\x9c\x33\x54\x7b\x16\x02\x95\x5d\xc5\x96\xa4\xb5\x4e\xf5\xc1\x34\x66\x57\x8e\x6d\xd6\x91\x3f\x99\xfa\x8d\xcf\xbe\x57\x1d\x95\xb4\xc9\x51\x98\x69\x93\x2f\x88\x2a\x2d\x8e\xe9\x48\x67\x39\x64\x0f\x88\x4b\xd4\x43\xe2\xb5\x17\xd5\x9e\xce\x07\xe3\x20\x7b\x72\x05\xed\x63\x6d\x31\x04\x3d\x7d\x7a\xd3\x19\xaf\x0e\x04\x32\xef\xf0\x10\x3e\x60\xf4\xe5\xa1\x9d\xb0\xab\xc5\xa0\x93\xdb\xea\xa0\x02\xde\x8a\x39\x33\x76\x62\x08\xfc\xbe\x1e\xdc\x58\xbb\xc1\x0f\x0b\x5c\x4f\x65\x42\x78\xb1\x92\x61\xea\x16\x65\x79\x9e\xa3\xda\x9f\xaf\xb2\x07\xd6\x16\xbe\xa4\xff\x33\xd7\x45\x3b\xc0\xa0\x0d\x11\xad\xee\x24\x33\xca\x44\xcf\x48\x57\x62\xbe\xfc\xcd\xeb\x72\x27\xb4\xec\xa5\x06\x3e\xf3\xcc\x87\x76\xa8\x81\xff\xb0\x66\x25\xda\x33\xdd\xa4\xb2\x42\x6c\x81\xec\x11\xf0\x6b\x25\x86\x8c\x33\x6c\x0b\x36\xe2\xbd\xf6\xb0\xf2\x07\x2d\x5c\xd8\xea\x5f\x1c\x50\x8b\x8f\x33\x2b\xaf\x7f\x92\x58\x06\x04\xb8\xb9\x44\xe7\x16\xa7\x89\xb8\x37\x51\x2a\xbe\xb1\xf2\x5c\xa6\x26\x16\x20\x14\x19\xaa\x27\xcd\x1a\x6e\x9b\x3f\x90\xad\x69\x87\xb5\xf3\x7f\x20\x22\x51\xf6\xfe\xdc\x77\x9d\x5f\x45\xf6\xb8\xed\x77\x1e\x66\xf3\x6e\xb6\x01\xda\xf8\x7b\x52\x81\x47\xae\xcc\xce\x70\x65\xdd\x7c\xc5\x29\x1e\xcc\x57\xb3\x90\xff\xd0\x95\x31\x5b\xbb\xb1\xbe\x61\x06\x95\x60\x73\x52\x4e\x4a\x78\x68\xb7\xcb\x45\x4c\x90\xaf\x95\xb6\x99\x86\x51\x7b\x88\x25\x9d\xca\x8b\xd9\x47\x5f\x01\x69\x31\x05\x5d\xf9\x52\xb6\x31\xc5\x7c\x2a\xee\x6a\x6f\xf1\x5f\xe0\x0b\x85\x19\xca\xb0\x9d\x04\x64\x0e\xb3\xd7\xac\xe4\x38\xe6\x2f\x52\x07\x9e\x45\x15\xd0\x87\x80\xa8\x21\x7f\x85\xd0\x0b\x23\xf3\xfd\xf9\x09\x28\x1d\x3f\x69\xb6\x19\x7e\xd2\x16\x9e\x17\xd1\x7e\x0d\xf3\xe0\x4a\x78\xd2\x83\xd5\x9d\xb7\x83\xf9\x66\xfe\xb5\x57\xc7\x2f\x27\x3e\xae\x00\x81\xab\xf1\x88\x9a\xed\x5b\x15\x56\x8b\x86\x51\xf8\x71\xa8\x8e\xfe\x97\xe5\x27\x00\x65\x9e\xcc\xfa\x27\x7d\x56\x6d\x4a\xec\xe6\xa3\xc2\xea\x55\x58\x93\x73\x61\x0e\xec\x88\x77\x43\x5d\x3a\x95\x08\xde\x76\xa9\x85\x8b\x1c\xc2\x3f\x12\x4f\xf8\xcf\x39\xfb\x66\x9a\xa1\xd1\xfd\xdd\x6a\x65\xb1\x8b\x88\x06\x0e\x3a\x1d\xb0\xbf\x23\x03\x89\x4d\x50\xba\x1b\x0c\x12\x6d\x84\xf1\xd2\x99\xdb\xa6\xde\x98\xdd\xd2\x54\xbe\x05\xbf\x46\xca\xf1\xa0\xcf\x1a\xe2\x77\xee\xb4\x11\x9b\x17\x20\x0f\x78\x0c\x5f\x5e\x5a\xdd\xf9\xee\xf8\xbd\xce\x63\xe1\x45\x43\xe5\x82\xa1\x5a\xa1\xb7\x7e\xe9\xf2\xc0\xa4\x63\x3d\x3d\xe8\xe4\xfe\x02\x26\x87\x0d\x3e\x99\x72\x4e\x0d\xf3\xde\x67\x96\xdf\xa6\x14\x15\x59\x1a\xdc\x47\x1d\xfe\x10\xb2\x27\x72\xee\x3c\x0a\xd5\xd2\xf1\xef\xb8\x50\x6f\xa2\x08\xf9\xb7\x2f\x82\x7e\x99\x19\x98\xc5\x0d\xa7\xaf\x98\x86\x05\x5b\xbf\xc8\xa8\x2a\xc3\xea\xf1\xe9\x95\x30\xfe\xba\x0f\xe4\x01\x74\xa8\x10\xe1\x85\xdf\x7f\x6d\x09\x5c\x8f\x39\xd1\x03\x85\xd8\x85\xc7\x81\xd7\xcf\xff\x43\x72\x04\x06\xff\xe9\x1e\x30\x09\x13\x5c\x41\x0f\x4a\x60\x70\x75\x1d\xbb\x25\xea\xa4\xaa\x74\x47\x32\x06\x1d\x89\x98\x49\xaa\xa7\xf9\x72\xeb\x09\xbc\x82\xce\xeb\x9c\x59\x15\x21\x32\x6a\x66\x4e\xe4\x8d\x24\x6c\x38\xc2\x74\xbc\xb7\x2a\xc3\x85\xfe\xd7\xb1\x3b\xe2\x1a\x87\x2a\x75\x66\x14\x56\x7c\xfa\xc9\xbd\xf6\xaa\x27\x39\x3c\x99\xb5\xab\xad\xe8\xa2\xbf\xb4\xc4\x5b\xc5\x6f\xd9\xcc\x22\x55\xbc\x05\x3f\x68\xcc\x48\xbc\x2c\xff\xe3\x96\xcc\xd9\x5e\x66\xe9\x09\x09\x45\x86\x07\x63\x81\x6a\x11\x21\x2e\xfc\x13\x42\x9e\xaa\xd3\x34\x05\xe6\x40\xc3\xfd\x22\x18\xce\xd2\x8c\x67\x53\x74\x22\x27\xd3\xb8\x3a\xb0\x08\xe8\xd6\x3f\xac\xfc\xe3\x94\x5f\x31\xeb\x87\xb3\xf6\x20\x34\xd6\x47\xe0\x0b\x00\x6c\x48\x3c\x5d\xc0\x37\xf1\x14\x69\xe5\xc3\x44\xbe\x22\x0c\x9d\x05\x32\xb7\x4e\x34\x32\xb6\x1e\x3d\xeb\x41\xb6\x41\x74\xc1\x15\xc1\x21\x2f\x1c\x52\x25\xbe\x2a\x68\x5d\x16\xed\x30\xc2\x64\x21\x8e\x16\x60\xc9\x2a\x44\xa8\xbc\x1a\x54\x27\x12\xbe\xc4\x5c\xd8\x12\xcf\xb6\x65\x47\x3b\x2f\x3e\x16\xca\xcd\x16\xf8\x62\x66\xcc\x19\xe4\x03\xfe\x0e\x5a\x8f\x25\x95\x83\x8c\x82\xfe\xed\xae\xeb\x25\xbb\xcb\x60\x03\xf7\x31\x92\xf0\x70\x72\x55\xe5\x1b\xfd\xfd\x38\x09\x9c\xdb\x6b\x92\x15\x13\x95\x17\xb3\x10\x5c\xbb\x33\x2a\xcf\x53\x7e\x60\x15\x5f\xe5\x59\xb0\x78\x83\x2e\x03\xbc\x3a\x49\x3b\xcf\x3a\x25\xbe\x88\x9d\x8c\xc4\x07\x9b\x6e\x51\x58\x55\x4c\x70\xb0\x92\xf7\x20\xf2\xb3\x90\xc9\x40\x0b\x77\x43\x34\x68\x0e\x05\x26\x5e\xd5\xf3\xc9\xd6\x20\x90\x2a\x2c\xf4\x23\xd3\xa3\xc1\xe2\xdf\xeb\x04\xcb\x4b\xc3\xe2\x67\xbf\x2c\x38\x39\xf7\xda\x9f\xbc\x67\xe4\x22\x58\x80\x89\x73\x9a\x11\x46\x7a\x2e\xa3\xa2\x7f\x3f\x29\xa2\x73\x7e\xc3\x9b\x57\x15\x11\xdd\xb9\x1d\xaa\x19\xc4\xfd\x4c\x02\x3a\xcc\xe1\xb3\x20\x86\x0a\x18\xbe\xc9\xc3\x54\xde\x6f\x40\x4b\xf8\x4e\x5d\x25\x3e\xda\x40\x63\x6c\x21\x0f\x5d\x8a\x6d\xec\x22\x67\x18\xb9\x4d\x9e\x57\x46\x07\xf2\x5a\x24\x4d\xbe\x69\x40\x7c\x99\x71\x43\xde\x34\x0a\x4e\x1c\xd0\x2d\xa2\xb3\xf3\x6a\x47\x20\x66\x01\x94\x09\xec\xde\xcf\xee\x87\xc9\xb4\x33\x7f\x80\x08\xd4\x99\xd9\x25\xf6\x74\x16\xec\x48\x87\xc3\x88\x2c\x91\xdc\x61\x0b\x75\x17\x93\xc0\xae\xc2\x43\xd4\x1a\xa0\xa0\xad\x22\xd2\xe3\x52\x9e\x0e\xfd\x99\x7b\x8c\x64\xcf\x8c\x7b\xd4\xd1\x11\x1e\xad\x49\xb7\xc6\x2d\x2c\xbd\x66\xfe\x54\xb9\xe7\x1c\xd4\xbc\x95\xa1\xa2\x83\x36\x11\xd1\x4d\x42\xfe\x19\xba\x00\x06\x64\x90\xa0\x5c\xdd\x0c\x0e\xfe\xe1\xde\x60\x73\xaf\x07\x64\x56\x1f\x7a\x87\xd0\x18\x2d\xda\xba\xf1\x08\xa4\xa5\xd7\x42\x65\x77\x52\xbe\xf5\xf6\xda\xca\x3e\x68\x42\x3d\xe9\xbf\x29\x84\xc7\x27\x0d\xf8\x8c\x44\x52\xe0\xf1\x76\xa7\xe7\xbf\xdc\xa2\x00\x5a\x66\x95\x3e\x68\x8e\xea\x9d\xd8\x93\x87\x7b\xac\x8f\xdb\x21\xca\x58\xe2\x45\x8e\xa1\xd8\x95\x83\x61\x71\x6c\x15\x36\x01\xc4\x16\xd4\xef\x70\x63\x76\x4b\x04\xf9\x48\x03\xd7\x0a\x9c\xb7\x56\x04\xb1\xd8\x8c\x1b\x75\xce\x64\x6c\x59\x0e\xb3\xf1\x37\xd4\xa8\x18\xe4\xbd\x27\x8e\x85\xdb\xb6\x47\x6d\x3e\x9d\x1b\x91\x40\xcf\x05\x04\xfd\x21\x7d\xf3\xef\x64\xbe\x9a\x86\xc0\x83\x9c\xcd\xc2\x83\x6b\x16\x2c\x18\x5e\x7b\xcf\x9b\x02\xa8\xa2\xd5\x27\x36\x82\x1d\x76\xe7\xf9\x44\x66\xca\xe9\xe4\xeb\x20\x4f\xa7\x52\x14\xa3\xc1\xc3\xdc\x38\x5d\xa4\x62\xe1\x32\x31\xb2\xda\xcf\x80\x7e\x7a\x0f\x2d\x89\x3c\x6f\x28\xdc\x9e\x73\x77\x13\xee\x7a\x47\x00\x73\xb7\xa3\xce\x9c\xf7\x41\x96\xeb\x08\x4a\xa7\xb8\x5b\x48\x27\x68\x34\xea\x9f\x5e\xe6\x91\x70\x25\x0f\x80\xdd\x6c\x9e\x13\x54\x57\x69\xf1\xbc\x4c\x71\x63\x14\xa3\xdc\x64\x62\x6a\x55\x36\x65\x93\x5d\x80\x9a\x79\xe9\x68\xe6\xeb\xc4\xe8\x79\x2a\x81\x90\xbe\x5b\x98\xa7\x9b\xe7\xc8\x81\x40\x38\x0b\xe2\x88\x2b\x3a\xc7\xb4\xc5\x4f\xab\x87\x78\x0a\xcb\xd2\xcc\x64\xd0\x56\xe6\xc9\xca\x91\x79\x24\x86\x19\xa2\xeb\xcd\x69\xc3\x81\x49\xf7\x3b\x81\x8a\x97\xc2\x95\x1c\x0c\x58\x62\x64\x3c\xbc\xa7\xd0\x4c\xde\x0a\xcf\xb5\x6f\x0a\xef\x02\xfc\x27\x4a\xb9\xa9\x50\x1c\xb9\x14\xc3\x40\x82\x7e\xfe\xe2\x13\xb6\xdd\xae\xb8\x1d\x21\x40\x5f\x53\x9f\xfe\xe2\x95\xcd\xf0\xcd\x6b\x7a\x2c\x72\xd5\x8b\xdb\x07\x92\x23\x3c\x51\x25\x0d\xca\x92\xd3\xe0\x10\x79\x95\x00\x56\xe6\x15\xe0\x6e\xe0\xdb\xa3\xce\x75\xd4\x28\xf8\xd6\x67\x1c\x60\xf3\xc9\xab\x2a\x87\x00\x45\x6f\xf0\x4c\xbe\x05\x24\xa7\x82\x8c\x88\x75\xae\xef\xa5\x21\x62\x7c\x88\x1b\x6a\xeb\x84\xcb\x65\x72\x27\x85\x32\x76\x60\x08\x50\x25\x50\xa8\x76\xf8\x96\xe1\x3c\x14\x50\xc1\x57\x10\x8e\xd8\x62\x6b\x87\x7c\x57\x9d\xf9\xd9\xea\x19\xf9\x41\xf4\xc0\x31\x24\xb9\x4d\xa2\xc4\xeb\xe6\x40\x1b\x2f\x8f\xaf\xde\x20\xa2\x75\xc7\xd3\x69\x81\x45\x23\x14\xe3\x01\xcd\xc8\x47\x85\xa8\xd8\x8f\x72\xbf\x3c\x3c\x90\xc3\x8f\x7a\x65\x37\xd1\x3b\x9c\x0f\x3e\xbf\x45\x7a\xeb\xb5\x8e\xbb\xee\x6d\x64\xf7\xbb\xc2\xd6\x4e\xd0\x7e\x4f\x0c\xc3\x9f\x97\x18\x26\x00\x6f\x06\xf3\x01\xd4\x5b\xc8\x9c\x3b\x9d\x57\xfb\x39\x33\xb1\x49\x25\x8b\x25\x90\xc3\x81\x39\x3e\x9d\x07\xaf\x01\xd2\x38\x73\xc0\x07\x2b\xd7\x0e\xf5\x90\x13\xef\x96\x43\xbb\x17\x41\x08\x31\x98\xa3\x06\x13\x17\xee\x90\xa5\xae\x53\xf5\x11\x07\x05\xb9\x52\x1e\x6c\xc8\x53\x6c\xf5\x6e\x87\xa9\xd4\xb0\x98\x49\xf6\x03\x48\x3c\x76\xe3\x17\xc7\xda\x32\xbc\xe2\x9f\x84\x47\x7d\xd9\x63\xf3\x6e\xc1\x89\x37\xce\xe9\x9e\xe6\x82\xd5\xc2\x91\xaa\xc1\xbd\xc5\x37\x01\xdf\xec\xb2\x80\xa0\xe5\xd1\xd6\x95\xbb\x68\xdf\x83\x0f\x57\x46\x27\xe6\x95\xd6\x9b\x1f\x93\x10\x3e\xce\xd7\x06\xae\x1e\x33\x89\x78\xb5\xb1\x68\xcc\x5f\xd5\x18\xcd\x2a\xd9\xb7\x4a\x21\x7d\x6e\xab\x8d\x35\x2a\xad\xd3\x4d\x09\x57\x38\x19\x75\xbf\x29\x53\x8a\xd4\xc8\xd6\x4a\xdc\x24\xcb\xc1\x68\x9d\xba\x0a\x2b\xaa\x56\x07\xf3\xd6\xf9\x15\x75\x06\xcb\x34\xcc\xcb\xf2\xd0\x4f\x55\x5c\xbb\x17\xed\xce\x98\x07\xda\x0d\x42\xa4\x8c\xf3\x56\xa5\x8c\x3a\xdf\x7a\x26\xbb\x2d\xd3\xd9\xb2\x33\x3b\x17\xb4\x80\x93\x02\xb3\xad\x15\x67\xca\xec\x30\x43\x44\x0c\x66\x1f\x9c\xb9\x17\x24\xa0\x2a\xaa\x06\xcc\x0d\x43\x1e\xd4\x2f\x08\xab\x04\x85\xdc\x19\x1c\xcc\x2e\x16\x7e\x0a\x3c\x2a\x2d\xf7\xc8\xb2\x9e\x19\x7e\x7c\xd0\x4f\x92\x15\x18\xc9\x79\x11\x8c\xd2\xf8\x08\x7c\xf4\x97\x57\x3f\x1e\x0d\x1f\xef\x58\x92\x63\x6e\x74\x53\xf5\x2b\x36\x91\x4c\x4a\x3b\x85\xac\x72\x6c\x65\x96\xff\x7e\x34\x33\x01\x9a\x24\x0c\x74\xb1\x15\x9a\xaf\x83\x5b\x49\x9d\x6a\x81\xe2\xfd\x34\x5f\xc7\x17\xae\x57\xaa\x10\xd0\x8c\xae\x7b\x0b\xc7\xbd\x54\xb9\x3c\x78\xce\x09\x55\x5a\x74\x4c\x72\x6f\xc2\xc9\xdb\x05\x6b\x34\xfe\x1c\x2d\x80\xff\x15\xbf\xc4\xa1\xdc\x96\x1e\x1c\x39\x5c\xfc\xf5\x9d\x23\xdd\xa5\x7f\x5f\x8b\x96\x18\xe2\x56\x3b\x1c\x34\x08\x20\xf2\x2b\xa2\xb4\x54\x66\xd3\x69\xb0\x3d\xb7\x7d\x1c\x2b\xe2\x1a\xb7\x39\xb3\x38\xe6\x9b\x18\x08\x7f\x93\x18\x0f\x9e\x0f\xdb\xc9\x21\x5c\x9c\x45\xce\xb6\xb3\xca\xbc\xd1\x2e\x21\xec\xa2\x65\x6e\xfb\x78\x0b\xda\x28\xdf\x23\x62\x72\x3f\x8d\x8f\x85\x36\x84\xf1\x1c\xa1\x41\xad\xd8\x3d\xab\x56\xfc\x48\x8f\xf0\x2b\x02\x9e\xdd\xbf\xd1\x6c\x97\x25\xb2\xee\x70\x3e\xe7\xa6\xda\xf1\x73\x21\x7f\x15\x14\x3c\x22\x52\x89\xbc\x2b\xb2\xc5\x89\x0c\x30\x3d\x1f\x59\x8e\x76\x16\x07\xd3\xac\x6d\x68\xd5\x3b\x9c\xd5\xec\x2c\x66\xec\x3b\x92\x33\x9a\x51\x78\xd6\x87\xd3\x6d\xf9\xd2\x76\x4f\x11\xd7\x9e\xdb\x4b\xcc\x0d\x07\x5d\x64\x95\xb6\x38\x97\xa8\x1f\xea\xd5\x18\x57\x10\x60\x12\xa3\x30\x18\xfc\x7a\xbf\x7c\xda\x0e\xab\xfb\x48\xd6\x8a\x5d\x05\x8d\xf1\xa3\xe0\x6d\x73\xdb\x42\xa4\x7b\xfc\xec\x02\x00\xd3\xcb\x42\xb5\x76\xd1\xab\x19\x2a\x1e\xe3\xcc\x12\xa6\xb3\xf8\x79\x64\x56\x6e\xb3\x19\x03\xc4\xd9\x65\x77\xa6\x83\xbc\x75\x12\x65\x09\x2e\xa6\x5d\x71\xd2\xf4\x6e\xc8\x5e\x0e\x2e\xa8\x67\xd0\x2c\x67\x20\x27\x94\x1b\x75\x87\x2d\x74\xf4\x50\x79\xee\x60\x6e\x73\x30\xdb\xb7\x23\xc6\xcb\x6d\x1e\x9c\x39\x98\x08\x7d\x43\x5e\xb5\x44\xb3\xaa\x71\x64\xad\xf0\xd3\x7e\x4e\x5c\xfb\x05\xeb\x8a\xb7\x35\x67\xc7\xda\xa9\x20\x7f\xb7\x1a\x7f\x5a\x69\x54\xb7\xcc\xe2\xf4\x87\x70\xd2\xb3\xd9\x1b\x10\x92\x96\x56\x1f\xdb\x6a\x2f\xf2\x46\x89\x38\xab\x4b\x4a\xa5\x8e\x0f\x57\xd3\x99\x22\x00\x0f\x26\x46\x73\xbb\x5f\xdc\x24\x9f\xb7\x05\x3d\x22\x91\xf4\xce\x20\xcd\x89\x89\x2c\xee\x9f\x0b\xb3\x02\x6d\x8d\xf7\x0a\x71\x31\x97\x70\xde\x66\x01\xe1\x46\x82\x69\x4b\x54\x2d\x3d\x87\x14\x11\x05\x83\xe6\xbc\xc9\xa9\x46\x81\xd8\x41\xc5\x30\x72\x85\x79\x38\x00\xe1\xe0\x4f\xf4\x07\xe1\x4e\xe1\x45\x8e\xd6\xe2\xa2\x96\xad\x3f\x67\x7f\x03\x5d\x53\xf9\x5a\x1e\x05\xff\xa4\x20\x12\xa0\x89\xcb\x19\xd2\x3a\xa1\xbd\x62\x29\xda\xbe\x1b\x13\xbe\xc0\x5a\x0f\xdd\xff\xab\xb3\x44\x46\x70\x22\xf1\x03\xf9\x25\xa8\x78\x3c\x6a\xa2\x53\x88\x21\x3f\xc6\x39\x99\x89\x62\xd9\x6f\x67\x80\x4b\x27\x22\x4f\x3f\x7f\xdc\x62\x7e\x6e\xaa\x26\xd1\xf5\x58\x12\x73\x4e\x64\xf9\x17\x2e\xd0\x2b\x33\xd1\xd0\xa3\xf0\xec\x81\x2e\x97\xc4\x0b\x22\x40\x9a\xf6\xe6\x0d\xf7\xc0\xcc\xef\xe6\xe1\x19\xc5\x23\xfb\x13\xc4\x9a\x88\x21\xdd\xe3\x26\x58\xc8\xf3\x09\x2b\x22\xd7\x9f\x64\x32\x08\xef\x34\xb6\x43\xda\x3a\x2e\xef\x7b\x24\x24\x74\xf0\x3b\xd5\x50\x32\xa0\x9d\x68\x6f\x4c\xfc\xbd\x95\xce\x2c\x66\xcc\x17\xb3\x2e\xc2\xb0\xf8\xca\xbe\x29\xf0\x30\xaf\xa5\x25\x02\x50\x41\x62\xe2\xcd\x4d\xaf\xca\x6e\xb4\x80\xc2\xee\x41\x61\x06\xf7\x4d\x2e\x95\x95\x5c\x36\x95\x45\x5d\x84\x26\xe1\xa6\xde\x0e\x1c\x6b\x95\x0d\xa2\xa2\x35\x12\x66\xdb\xf0\xbb\xc8\x2e\x02\xb0\xf0\x05\xac\x37\x9b\xb5\xab\x9a\xb8\x7b\x4e\xab\x2e\xa2\x06\x48\xbe\x74\xc6\x19\x6f\x02\xed\x6b\x1e\x89\x2e\x8e\xe9\xb1\x45\x3a\x79\x4a\x45\xf7\x93\xbb\xa1\xa8\x53\x20\xde\xb2\xd0\xc2\xdd\xed\x1c\x46\x5a\xa3\xf6\x1e\xc7\x22\xbd\xb5\x4b\x19\xd5\x1e\xf1\x35\x37\x86\xe9\x9b\x1d\x4d\xe2\xe6\x2a\x1f\x32\x82\xc9\x2c\x75\x99\xa7\x7a\x28\x6a\xe8\x82\x48\x08\x5a\x17\x17\xa3\x55\x85\xdc\xea\x91\xf2\x51\xc9\xbf\xda\xc4\x14\x35\x73\x37\x85\x6b\x2b\x44\x3e\x09\xdf\xfa\x15\x72\xdf\x0e\xdb\x64\x51\x5e\x3a\x18\x73\x6c\x39\xff\xe5\x5d\x0b\x68\x9d\x34\x91\xbd\x8f\x0a\xd7\x4a\x0b\x9a\xf5\x16\x29\xf8\x20\x7b\x12\xb1\x21\x2b\x4c\x5c\x71\xc6\xce\xe5\xdf\x02\xc2\x9a\xb9\x32\x8b\x6c\xc0\x76\xc1\x94\x30\x76\xec\x98\x7d\xe7\x08\xbe\x1d\x14\x51\xf9\x31\xd0\xf4\x63\x6b\xc4\x37\x70\x9f\x18\x8c\x6d\x9b\x60\x7b\xe4\x61\xb0\xb2\x28\xc2\x04\x74\x60\x67\x6a\x5e\x55\x91\x51\x37\x86\x6d\x6d\xe6\xae\x32\x64\x71\x58\x9f\x89\x04\xd2\xc5\x62\xe6\x9e\x15\xc7\xcd\xdd\x2b\x3e\x65\xc9\x1e\xfe\xa9\x1d\xa2\x8b\x6a\x32\xa2\xee\x1b\x7b\x03\x58\x62\x73\x16\x24\xdf\xec\x37\xe2\x19\x33\x21\x20\xd6\x3b\x50\xbf\xc9\xaf\x01\x6a\xcf\xc1\x91\x42\xd9\x99\xf4\xf9\x87\xda\xca\x96\xfc\x99\x59\x9b\x7e\x93\x95\xcc\x02\x87\x5d\xc0\x67\x14\x70\xbf\xfd\x56\x25\xca\xf2\xfb\x15\xd7\xcb\x96\x78\x1c\xc3\x33\x6f\xb9\x38\xd9\xaf\x73\x62\xe7\x31\x0e\x0e\x4a\x24\x44\x21\x97\x86\xbc\xa3\x7e\xd0\xd8\xaf\x3c\xff\xf9\xf8\xaa\x0a\xdd\xd4\x44\x24\x72\xc3\x08\xd4\x77\xad\x8a\xa5\x67\x5b\x56\xb4\xee\x4e\x66\x52\x2e\x58\x59\xa7\x9c\xe5\x54\x92\x12\x1e\x8b\x1a\x5d\x9c\x3e\x07\xa4\xca\x2d\x99\x6d\xd4\x48\x2b\x7a\xef\xd0\x55\x9e\x54\xa1\x39\x48\x22\x31\x2b\x17\x3e\x24\xb7\x12\x66\x04\x3c\xbc\x2c\xa8\xf1\xaa\x0a\x5a\x96\x20\x9a\x33\xc3\x55\x5d\x74\xae\x03\x40\x64\x52\x24\xc2\x7c\x0c\x30\x44\x0f\x82\x59\x76\xa6\x93\x90\xae\x3b\x49\x53\x9e\xe1\x92\xe6\xe1\x79\xca\xad\x01\x1b\xa2\x3e\xa8\x48\xc6\xb4\x75\x7f\x06\xab\x83\x16\x4b\x09\xf3\x29\xee\xfd\x78\x8a\x6a\xd1\x8a\x8a\x40\x55\xdc\x6d\xa8\x60\x88\x55\x15\xe1\x0f\xc7\x8d\x9f\xeb\x2e\xf0\xc6\xd8\x63\x51\x75\x05\xc7\x08\xb9\x0d\xac\xac\x2a\x0b\xd8\x8a\x45\xa9\xad\x02\x4e\x7a\xba\x5d\xe7\xb2\xc5\x30\xdb\x29\x96\x2d\x0d\x91\x99\xc5\x53\x4e\xfa\x90\x11\x75\xd4\xb7\xf1\x72\x10\x16\x47\xc4\x36\x56\xb9\xb7\x16\xc3\x79\x6a\x2f\xab\xa1\xb2\xc6\xc3\x39\xc0\x3c\x92\xa9\x2b\xc4\x86\xdd\x7d\xb2\x6d\xaa\xbe\x85\x84\x6d\x16\x98\x25\xa6\x0e\x76\x57\xd9\xa5\x43\xe0\xfb\xf0\x10\x8c\xc0\x4d\x8a\x02\x42\x1c\xfc\x3a\x5c\xf1\xfc\x1c\xc0\xbd\xc5\xc5\x2b\xd9\xb2\x51\xcd\xb5\x53\xd2\x22\xba\x8d\x86\x68\x4e\x0f\x27\xf5\x22\xa6\x33\x0b\x78\xbb\x18\x76\xcc\xe7\x4f\x72\x86\xd8\x33\xf4\x47\x59\x66\xb8\x35\xcf\x46\xf3\xf1\x69\xab\xcc\x28\x8e\x71\x86\x9d\x3e\xf6\xdd\x31\x37\xf5\x92\xb4\x3d\x1a\xc9\x30\xe0\xa8\x32\x51\x47\x77\x0b\xbf\xc1\xdb\x11\x78\xfb\x80\xbc\x04\x58\xcf\x32\xd0\xb3\x0c\x4b\x52\x31\x6d\xff\xef\x64\x4c\x6d\x3e\xe8\x4f\x00\x33\x4b\x03\xf7\x71\x50\x57\x25\x63\x65\x5e\x5b\x65\x0a\x0c\x0b\x5d\x09\x7d\xd4\xcc\x98\xef\x60\xf3\x41\x12\xd1\x19\xc5\xfa\x88\x05\x36\x99\xb3\x74\x20\x9c\xe1\x13\x5a\x18\x7c\x72\x77\x19\xf3\x89\x3f\x6f\xe6\xeb\xe4\x69\xb3\x44\xc3\x0c\x73\xa0\xfb\x04\x20\xe1\x8e\xec\xea\xf1\x3b\x26\xd2\x88\xec\xc1\xed\x21\x60\x7c\x1b\xbf\xd6\x0e\x9d\xcc\x73\x77\x06\x35\x8d\x98\x5d\x9a\xa2\xbe\x8d\x05\x58\x68\x14\x17\x05\xa8\x8d\x94\xc0\x4a\x38\x8b\x40\x03\x8b\x30\xf6\x11\xc8\x85\x98\x04\x63\xd9\x40\x88\x55\x78\x43\xd6\x2e\x6e\x29\x02\x44\xb1\x96\xf6\xa2\xea\xc0\xbc\x88\xf1\xd5\xe1\x5c\x9c\x9e\x69\xb5\x87\x7d\x9c\xcd\x17\x1e\x0d\x6b\x33\xdb\xa2\xf0\x70\x8b\xa2\xb4\x53\xa4\xe0\x9c\xf3\xa0\x84\xdb\x63\x1f\xe1\x63\x9d\x02\x34\xb4\x83\x82\x6a\x44\x5c\x56\x6c\x53\x44\xa5\xda\x3b\x6c\x79\x02\x6e\x60\xf1\x64\xb9\x7b\x27\x68\xe2\xc5\xc0\x2b\xe7\x07\x62\x9a\x7c\x57\xeb\x97\x39\x81\x9e\xe2\x12\x8c\x6d\x5b\xe1\x8f\x1c\xaf\xe2\x7d\x1d\xc3\x79\x5d\xf2\x70\xad\x6d\x13\x23\x51\xc1\xc7\xea\x48\xa9\xea\xca\xa7\xf2\xce\xc3\x3f\xba\xbf\xe7\xc5\x23\x04\xe7\x82\xe1\xf7\xcc\xb2\xaa\x53\xcc\x26\x85\x10\x62\x31\xd2\x04\xe1\xf7\x9d\x1b\x2b\x7f\x3d\xab\x5c\x5c\x66\x1d\xb7\xb8\xd7\xe0\xf5\x71\x89\xde\xb0\xa2\xde\x0e\xc1\xb6\xfe\x7b\x14\xcd\x7a\xcb\x2a\xfa\x8b\xcd\xea\x06\x0c\x39\x2b\xe8\x8c\x5c\x56\x1c\xd8\x55\x98\xe7\x5e\x59\xba\xf1\x16\x6a\x6f\xef\x21\x43\x52\x6d\x64\x6b\x11\xa5\x91\x17\x6a\x8a\xa2\xe7\xc3\x92\x04\x11\x09\xc9\x11\x97\x05\xc7\x79\x37\x3f\xcd\xef\xaf\xe7\x41\xa2\xc4\xac\xf6\x48\x96\x34\x57\x11\x96\xe7\xf4\x89\xf8\x2b\x3d\x15\x93\x3e\x1e\x0d\xc5\xa0\xa5\xcb\xcb\x4f\x0d\x6c\x17\x3e\x03\xed\xe2\xc1\x04\x8d\x04\x5b\x25\x30\x4b\xdc\x32\x4b\xff\x8f\x45\x67\x6c\x6b\x11\x02\xf0\xe9\x41\xff\x95\x05\x86\xb2\x10\x72\xfc\x7c\xf3\x36\x36\xda\x60\x0b\xd2\x76\x6e\xde\x29\xa3\x2a\x32\x86\x97\x63\x2c\x1f\xe2\xdb\xdf\x27\x46\x80\xad\x9b\xbd\x3b\x8f\xa3\x8a\xca\xad\x7a\x49\xf9\x3d\x18\x1a\x1e\x2d\x8d\xa0\x33\xb0\xdf\x50\xb8\x70\x4c\xc4\x18\xa0\x7d\x5a\x82\x32\xa9\xe0\x90\xa2\x5d\x9b\xed\xa6\x7e\x4e\xdb\x06\xd7\xeb\x36\xde\xc5\xf8\x2d\x2a\x96\xdc\x65\x2f\x10\xef\xd1\x00\x2d\x00\x12\x82\xa6\x85\xfc\x07\xbf\x57\x38\xe6\x9d\xdd\xc8\x4e\xda\x73\xd3\xa7\x80\x7b\x9a\xc8\xfa\x71\x3c\x76\x4d\x37\x61\x1e\x0c\x47\x1d\xec\x2a\x77\xbe\x57\xdc\x15\x0f\xc0\x0e\x06\x91\x6c\x1f\x42\x7e\x08\xc4\xf7\xf1\xc1\xc5\xdd\xce\xcc\xce\x70\x26\x20\x5d\x55\x2c\xe3\xe7\x3c\xce\x97\xf3\x48\x93\x12\x5f\x98\x85\x46\x4a\x46\xdc\x87\xd5\x47\xf5\x16\x5f\x94\x8d\x0f\x09\x5e\x1a\xb1\xa5\x25\xf3\xf0\xdd\xc5\x21\xf1\x36\xe5\x1d\xab\x0a\x6b\x16\xd1\xd2\x61\xd9\x83\x1a\xd0\xbd\x70\xca\xe7\xde\x17\x66\xe4\x33\xb8\xd7\xf7\xb2\x51\x3d\x00\xd8\x24\xb9\xa1\xce\xcb\x98\x1b\x11\xfb\x95\x98\x63\xa9\x5a\xe0\x3c\x47\x50\x83\xf9\x61\x73\x1c\x0e\xb2\x5f\x70\xf6\x40\x3c\xe8\x1b\xc0\x76\xd8\x5a\xe0\x36\xbd\x83\x9a\xd4\x3b\x58\xa2\x3e\x84\xe8\xc3\x66\x88\x7d\xbb\x50\x50\xb9\xe2\xa9\x10\x0e\x6b\x2c\x46\x24\x3a\x57\x40\x42\x8c\x8d\xdc\x03\x17\x93\xa0\xe7\xdc\x48\x5e\x4d\xb3\x85\xf4\x8a\x73\xde\xde\x61\x4f\x6a\xd3\x7e\x61\xe5\x01\x00\xb0\xb2\x0b\xb7\xa3\x56\x26\x10\x61\x5a\x3e\x45\xd1\x95\x55\xf7\x6d\x4a\xde\xb0\xa6\x74\x75\xa6\x2d\x0b\xfa\x88\x97\xde\xf0\xba\xcf\xc2\xe6\x9d\x22\x1b\x15\x4d\xfa\xaa\xc7\xf8\x92\x07\xfe\x56\x57\xe5\xde\x20\xc3\x36\x07\xe4\xbc\xc2\x20\xd5\x17\x9e\x6f\x47\x9d\xc0\x1f\xf8\x6d\x3d\xe6\x5d\x36\xe7\xf1\x11\xc3\x09\x1d\xdf\x47\x03\xa1\x14\x8c\xf1\x7a\x12\x26\xc4\x39\x11\x8d\xc3\x02\x72\xc5\x0b\x8b\x7e\xd1\x5e\xd1\x78\x81\xf6\x28\x96\xc7\xd4\xc1\xca\x56\x42\x56\x73\x82\x37\x90\x17\xa5\x99\x13\xfb\x03\x50\xf5\xc3\x07\x9b\xd5\x51\xca\x03\xde\x49\xd0\x34\x67\xed\x05\xf0\xb2\x41\x74\x9b\x9e\xed\x34\x7b\xb3\x66\xf6\x55\xdb\x68\xae\xac\x59\xb5\xd8\xf1\xb3\x88\x89\x1a\xc7\xcd\x8e\x95\x1f\x9b\x86\x14\x74\xe9\x90\xa5\xf1\x07\xb3\xe5\x12\x8c\x67\x4b\xcb\xe0\xc6\x16\x6e\x8f\x34\x3b\x1d\xb4\xb6\x95\x3d\x21\xfe\x3b\x49\xf7\x50\x0d\x1e\x01\xcc\x39\xb3\x3c\x62\xdf\x04\xbb\x68\xa1\xd8\xc8\x2b\x1e\x2e\xd7\xfb\x54\x75\x32\x1c\x68\x46\x76\xe8\x40\xdb\x9e\x08\x96\x26\x51\xe2\xbc\x6b\x00\xb0\x44\x65\x43\xbf\xd9\x22\x82\x4f\x53\x40\xeb\xde\x67\xcc\x20\x05\x05\x7d\xf8\xd8\x73\xb8\x72\x75\x61\xbe\xa0\x2d\xd1\xc3\xee\x4c\xe8\x41\xca\x8a\xd4\x8e\x9c\x42\xd2\x3a\x83\x2d\x6b\x1f\xcc\x6a\xd3\x44\x26\x98\xa7\x00\xf6\x29\x64\x09\xda\xe3\xb3\x9c\xeb\xd5\xa6\xab\x79\x85\xec\x90\x65\x78\x53\xbe\xc4\xcf\x80\x32\x51\xca\xb6\x74\x8d\xe3\xd8\xa0\x9e\xb7\x87\x16\x0b\x8d\x93\xcb\xab\xfc\xa1\x95\x0f\xf7\x6b\x21\x3d\xfe\xc1\xf1\xa6\xa9\x65\x1c\x41\x77\x62\x4e\xc6\x02\x70\x60\xfa\x02\x2b\xdf\xea\x38\x29\x4a\x19\xd1\x0a\x48\x62\x40\x3f\x7d\x7f\x93\x3a\xb0\xfe\x3b\xa3\x88\xcc\x7a\xc1\xac\x7e\x27\xd5\x16\xc5\x52\x8c\xc7\xca\xd1\xfe\x73\x8a\x8a\xe2\xaf\xaf\x37\x73\xc2\x54\x00\xc8\xc3\x43\xe7\x10\x4c\x87\x68\xa0\x24\x57\x12\x68\x4c\xf6\xa6\x7e\x98\x81\x73\x8b\x46\x88\x20\xba\xd2\x9b\x22\x10\xe3\xee\xa3\xa2\x83\xe6\x86\x20\x7b\x90\x4d\x09\xaa\x11\x0b\x49\xe7\xb4\xb4\x52\x4b\xa7\x06\xc1\xe1\x02\x23\x9c\x97\x25\x3c\xc0\x8d\xcd\x5f\x72\x27\xcc\x02\x7b\x32\x82\x93\xb5\x46\xc1\x7a\xe1\x0b\x3e\x05\xc1\x1d\x42\x0e\x9f\x4b\x0e\x44\x41\xa2\x39\x9b\x36\xad\xf3\x0c\x1b\x9b\x15\xc4\x3f\x5b\x93\x17\xd9\x78\x43\x56\x2b\xd4\xb9\x04\x9d\xc4\xc5\x3f\xf0\x73\x3f\x35\x6a\x22\x0a\x12\xf1\xbc\x22\xd1\x6d\x8c\x46\x5f\xe1\xd8\x5d\x38\x20\x3a\xb2\xa8\x9b\x83\xff\xce\x84\xf8\x21\x78\xde\x42\xa7\x5b\x04\x3c\x3c\xdf\x71\x64\x40\x8c\xf3\x5f\xea\xb9\x53\xc8\x49\xfc\x0a\xa7\xb6\x5f\xcf\xb6\x2b\x88\x1a\xd0\xd1\xdb\xdd\xe5\x81\x7c\x8a\xaf\x7e\x54\xb2\x2d\x2d\x4a\x62\x89\x77\x53\xdc\x65\x9e\x07\x2f\x6d\x29\x9a\x5e\xab\x35\x9e\x98\x7b\x3d\x4a\x6b\x77\x8a\x04\x98\xcc\x3a\x44\xa1\x70\x6a\x21\xd8\x50\xff\x32\xb4\x51\xc6\xac\x27\x75\x00\x82\x66\x0c\x3d\x82\x84\x3b\xec\x93\x36\x5e\xc8\x88\x93\xc8\x9d\xb9\xa1\xe1\x5d\x70\xce\xf6\xd2\x51\x9b\x5a\xa8\xd6\xb7\xae\x8d\x97\xa5\x43\x65\x13\x1f\xb5\x45\x47\xce\x82\x52\xf7\x21\x71\x99\x57\x62\x81\x56\x1f\x6e\x16\x57\xce\x2b\x51\xae\x43\x95\x0e\x2c\x5f\x11\x74\xa0\x05\xf3\x03\x7e\xa3\xbf\x0e\x25\x32\xe1\xf9\x43\xa8\x21\x2d\x17\xba\xd8\x49\xd7\x81\x67\x3a\x48\x04\x0d\xaa\x54\x33\x26\x2a\xae\x61\xa9\x1e\x1b\xfb\x14\x9c\x49\x1c\xac\x37\x12\x2b\x0f\x09\x35\x74\x96\x6c\xdc\x5a\xa3\x23\x8f\xa6\xad\xd8\xe7\x4d\x70\x89\xdd\x63\xea\x5b\x40\xb6\x86\xd2\xfd\x29\x2c\xe2\x55\x36\x46\xf7\xa3\x84\x06\x2c\x54\xb6\xd5\x10\xa4\xec\x80\x69\xec\xb3\x73\x61\xb0\x68\x1b\xa9\x3f\xa2\x8d\xf2\xf6\x9a\x57\x9a\xeb\x8d\x34\x40\x54\xfe\x0a\x3f\x7e\x8a\x7b\xf0\x56\xc7\x6a\xee\xc7\xa5\x15\x08\x98\x1c\x71\x69\x26\xc9\xbe\x2c\xbf\xb1\x8d\x3c\xee\xf0\xd8\xd1\xf2\x56\x24\x97\x02\x96\x86\x02\x88\x7d\x54\xd7\x2b\xca\x86\x03\x6f\x6d\x94\xa0\xdd\x4d\x73\x91\x08\xb0\xa0\x19\xfe\xca\xfa\xed\xcf\x0f\xd0\x0f\x0b\x39\xb0\x6b\x1e\x2d\xca\xbc\x55\xf5\x29\x6d\xdc\x95\x8e\xa4\x4f\x75\x0a\x39\x1d\xdd\xdb\xe0\x14\x9b\xf7\x16\x73\xca\x54\xba\x49\xe6\x3f\xae\xa4\x82\x2e\x76\x02\x74\x26\xee\x28\xa6\xca\xc0\x39\x4f\x27\xb4\x6e\x2c\x6a\xb2\x45\x61\x60\x38\x15\xe1\x16\x43\x11\x99\xb4\x6b\xb4\x2d\x08\x4c\xa9\x9e\x1d\xd1\xd0\x77\x7f\xff\x17\x8a\xa2\xd3\x05\xe9\x31\x1e\x54\xdc\xbb\xc2\x1e\xe6\xad\xfe\x7e\x64\x95\x54\x6a\xb1\xdc\xb8\x35\x90\x4f\x61\x51\xdf\x4c\xc4\x6b\xb7\xb7\x72\xc7\x46\x2e\xfd\xe1\x95\x09\x55\x39\xc8\x57\x62\x58\xe5\x94\x03\x7d\x4c\xbe\x0b\x44\x85\x4c\xc5\x9f\x88\x57\x1b\x62\xbc\x65\x31\x1a\x9c\xfb\x13\x4a\x64\xe2\x80\x14\x42\xd3\x54\x7d\x68\xd0\x61\xb0\x1a\x8b\xf8\xde\xe7\x12\x3c\x25\x05\x0c\x68\x40\x65\xf6\xb5\xd1\xee\xce\x6a\xe4\xbc\x23\xc0\xbc\x85\xe1\xc4\x07\xa0\x94\xa5\xde\x5e\xaf\xed\x32\xaf\x18\x53\x84\x74\x0c\x7b\xe2\xd6\x45\x51\x48\x00\x4a\xe3\x20\xab\x8d\x78\x52\xbd\xae\x17\xd6\x14\xdd\xe9\x8e\x6c\x36\x53\x89\xab\xce\x78\x1a\x66\x9f\xc4\x8b\xab\xab\xd3\xad\x85\x3b\x6b\x55\x11\x3b\x69\x82\xa4\x1e\xb4\x3f\xc1\x66\x82\x85\xd5\xfb\x85\x87\xf6\xdc\x59\x26\xa4\x57\x73\x0a\xd8\x05\x30\x36\x08\x46\xf0\x71\x30\xe9\x1f\x5a\x2e\xb6\xe8\xc9\x42\x4b\x87\x6a\x39\x45\xd8\x13\x78\x0b\xbd\xaf\x3f\x2d\xfd\x53\xe9\x03\x0f\x4c\xbc\x73\x0b\x6d\xbf\x57\xa9\x71\xee\x47\x02\xff\xcc\xc2\x1b\xac\xe6\x14\x5f\x2c\xb9\x6a\xd4\xdb\x45\xeb\x74\xe7\x72\xa8\xe2\x3e\xd5\x0f\xfe\x74\xa5\x03\x25\xcb\xde\x06\x45\x6b\x31\xf1\xf2\xb3\xff\x74\x62\x17\xd0\x5f\x87\x33\xd3\xd4\xd7\xb1\x32\xb3\x60\x0c\x1e\x5d\xb0\x08\x68\xf7\x8f\x6d\x46\x3a\xb6\x12\x44\x3a\x7e\x58\x11\x7c\x83\xb0\xc9\x65\xba\x06\x3c\x60\x11\x45\x4f\x64\x4b\x65\x5e\x04\x12\x24\x8b\x64\x31\x3a\xfe\xf9\x2f\x9f\x30\x20\xa7\x9b\x3a\x0f\xb4\xf1\x27\x65\x34\xa3\x6e\x61\x31\x38\x44\x9b\x16\xcb\x0d\x05\xe8\xcb\xc1\xf5\x66\xae\x5b\xbc\x2f\x50\x87\x31\x63\x99\xc2\x13\x1d\x65\xd7\xb3\xb0\x9b\xff\x52\x1a\x90\x92\x84\xd7\xcb\x3c\x47\xbb\x85\x84\x59\x63\x42\x9d\xb6\x59\xe4\x34\x79\xfd\x38\x73\x95\xc4\xab\x40\x23\x02\x76\xcd\x23\x62\x4a\x16\xfc\x77\x96\x55\x81\x5d\x97\x88\x62\xb9\x34\x13\x3b\xce\xd1\x1f\xa7\x68\x85\x6c\x48\xdd\x87\x70\xec\x7e\xc8\x61\x9a\xc4\x2e\xa3\x15\x9d\x52\x27\x35\x01\x4f\x2f\xb6\x12\x38\x9f\x7a\xa9\xb6\x59\xc5\x2d\x36\xa8\xd3\x61\xf7\x59\xf6\x7c\x38\x17\x88\xe3\x7a\xbf\x0b\xe9\xfa\x7e\x9c\xaa\xea\x57\x0e\xbb\x34\x2d\x2e\x80\x76\x38\xcb\x7f\xa9\x02\xf2\x6c\xd9\xdf\x0f\x7f\xd7\x28\xb7\x9a\x3a\x4a\x23\x9d\x8b\x74\x6c\xaf\x1a\xbb\x36\xc7\x2e\x1d\xda\xe6\xc9\x93\xdf\x69\x9f\x10\xdb\x04\xe6\xa8\x56\x96\xa8\xf8\x6f\xaf\xa8\x32\x7b\xc0\xde\x5f\xdc\xcf\x49\xac\x10\xa4\xb0\x8a\x64\x5a\xe8\xa2\x7e\x63\xa6\xa2\x57\x2b\xdc\x02\x25\xb9\x47\x5c\x2a\xb6\xfa\xa4\xd3\x96\x68\x0b\xb6\xb0\x7d\x40\x99\xa6\x56\xb9\x78\x6b\xf9\xf3\xa6\x22\xbe\x87\x16\x1b\xa3\x2c\xea\xaf\x28\x8b\xa0\x2b\x74\x3e\x0f\xe1\xfc\x8e\x54\x9c\x1a\x5c\x79\xef\x22\x26\x2f\x0d\x68\xf2\xbb\x21\xe9\xe8\xf2\x62\xbd\x9d\x06\xc0\x73\x25\x9a\x33\xa7\x84\xe1\x7d\x2b\xbf\x15\xc7\x1d\xb6\xe9\x3a\xda\x1e\x9f\x0b\x61\x9c\xbd\x66\x4a\xbb\x6c\xe1\xd1\x12\x11\x2c\xea\x70\x24\xbb\xb3\xa1\xd9\x09\xc5\x2a\x80\x86\x14\x4e\xf2\xf8\xb5\x06\xe4\x36\xe8\x2a\x21\xb2\x91\xd5\x0e\xf5\x2f\xfd\x50\x54\x1f\x3c\x72\x1f\xc4\x68\xa4\xb0\xef\x18\x19\x92\xb7\x0b\xf3\x9c\xda\x6d\xd8\x5a\x74\x52\xd7\x20\xc9\x7a\xb7\x53\x73\x19\x8b\x5a\x36\xc0\x4f\xa2\x33\xde\x5e\x82\xbf\xf6\x74\x46\x52\x3f\x97\xc0\xa1\x42\xe8\x07\x04\x06\xf8\x09\xb6\xe2\x82\x6a\x26\x13\x3c\x31\xce\x93\xb6\x8f\x52\xa0\x53\xec\x51\xa7\x97\x20\x7e\x26\x97\x4e\xf5\x8d\x65\xbf\x2b\xbf\x03\x91\x5c\xe9\xfc\xc2\x1e\x27\x18\x11\xa9\xd6\x84\xe2\x1a\xdd\xa6\xed\x2a\x43\x3e\x54\x8e\xbc\x43\xf7\x08\xb3\xbe\x05\xcc\x76\x46\x57\x2f\xdc\x49\x57\xd0\x32\x4c\x13\xbd\x5a\x42\x8d\x02\x81\xca\x17\x1e\xfa\xe2\x98\x14\xe1\x87\x4e\x8e\xd9\x5a\x5b\x40\x24\x58\x53\x6e\x6a\x83\x11\xe0\x38\x8d\x41\x98\x41\xbf\xa9\x13\x23\x88\x72\xf0\xdf\xfc\x34\xca\x35\x8e\x39\x6a\x32\x51\x53\x7f\xa8\x4f\xd6\x3e\x98\xc4\xac\xb4\x3f\xc3\x72\x04\x36\xc5\xa8\xa7\xaa\x3b\xbe\x48\xea\xcd\xcc\x89\x50\x18\x34\x96\xe2\x01\xfd\x32\x6c\x4c\x66\x13\x5b\x43\xf0\x06\xe9\x62\xe7\x7b\xcf\x17\x93\xf9\x9f\xd3\xad\xe1\xc5\x8d\xfa\x22\x51\x3d\x0a\xd9\xc9\xcc\xd9\xc0\x86\xe1\x66\xb5\x1e\x2e\x8b\xf9\xa8\xd9\x1b\xb8\xf1\x76\x52\x56\x54\x8a\x52\x7f\x68\x36\x24\xf9\xe7\x4c\xe2\x99\xc6\x01\x20\xe2\x29\xd9\xe0\x6d\x3e\x71\x96\x59\x1e\xc4\x5a\x2f\x49\xd2\x71\xbd\x52\xfd\x59\x28\x49\x5a\xaa\x84\xb3\xd3\x4d\xd8\x55\xf0\x6b\x8e\xd0\xeb\xb0\x3b\x5e\x42\xbe\x35\xd4\x5e\xd0\xb2\x87\xeb\x0e\xf9\x86\x9d\x09\x02\xef\xba\x88\x8b\x01\x19\x95\xb0\x4a\xad\xce\x2a\x92\x88\x5a\x23\x64\x3e\xb6\x1c\x5a\xb2\xfb\xc8\xf8\xd3\xcb\x96\x6c\xcc\x35\xc7\xaf\x4f\x40\x17\x44\x95\x24\x04\xb7\x07\xd8\xb6\x64\x5c\x9c\x38\x7b\x0b\xcd\x52\x46\x90\x5b\x3c\x88\xa7\x92\x8b\x40\x89\xb3\x45\x5e\xde\x5c\xb2\xc8\x28\x0e\x59\xa0\x96\xed\xaf\xb4\xcb\x8e\x10\x36\x89\xf6\x30\x77\xda\xa4\xc2\x81\xc9\xe9\x2c\x0f\xcf\xe2\x98\x97\xa0\xd6\x4e\xa0\xd0\x7e\x3f\x9c\x3c\x9a\x90\x59\x52\x20\x0a\xc9\xad\x20\xb3\x4a\x3f\x76\x2e\x21\x4a\x7b\x48\x7b\x95\xe5\x7b\x5e\x84\xd5\xd2\x7e\x75\xec\x47\x66\xe9\xf9\x3f\x3e\x4b\x64\x81\x1b\x91\x45\x72\x03\x4e\x95\xbc\xa6\x41\x1c\x02\x67\xdb\xea\x2e\x29\xab\x5d\xcb\xb7\x9a\x18\xe3\xbf\x70\x16\x2e\x74\xde\x7a\x84\x0f\xd2\x68\x67\xa8\xdb\x82\xcd\xea\x4f\xf9\x02\x1d\xa1\x88\x3a\x77\xa8\x5d\x7e\x37\x57\x42\x0e\xcd\x54\xbb\x8e\x30\xc8\xc8\x4b\xf3\x87\xc2\xdd\x0f\x56\x98\xf3\xaf\xbb\x21\xb2\x6c\xa0\xbc\x69\xee\x66\xa6\xf4\x2c\x09\x45\x92\x9e\xba\x27\xb5\x24\x75\x11\xc8\x74\xd4\x26\x17\x67\xc9\xc3\x81\xee\xdc\x70\x5a\x91\x3c\x31\x88\xff\x43\x35\xfe\xee\x8c\x3c\x41\x41\x1b\xf8\x7e\x83\x58\x98\x51\x63\x82\x85\x62\xa2\x30\x47\x0f\x05\xf5\x66\xb2\x8a\xee\xc8\x89\xa2\x94\x39\x52\x8e\xc5\x99\x5f\x2c\x27\x29\xe7\xf3\xb8\x8b\x26\xf0\xa7\x9e\x6a\xfd\xbe\x13\x0f\x90\x6f\xa7\x4f\x3a\xd7\x55\x75\xef\x2d\x51\x49\x6e\x5a\x89\xef\xa3\x56\xc8\x2d\x37\x2b\x3e\x07\x33\xd9\xfb\x97\xa2\xbd\x21\x93\x6d\x76\x15\xb4\xcd\x46\x4e\x2d\x3c\x69\x7b\xb6\xb2\x2d\x48\x35\x7b\x5a\x07\x95\xb1\xb0\x40\x2f\xf6\xcc\xd1\x85\x25\x42\x5f\xc7\xd7\x61\xc2\x43\xd3\xed\xf7\xe1\x1e\xb7\x38\xbd\x66\x1f\xcf\x49\x46\x40\x57\xcc\xfe\x08\x91\xbb\xff\xce\x44\x8f\x75\x09\xb4\xac\x28\xad\xc2\x32\x56\xdd\x0d\x08\x4f\x04\xe1\x21\x0d\x20\xee\x6f\x0c\x15\xf6\x88\xc3\xc1\xea\x21\x1c\x87\xc0\x1a\xfc\x18\x6e\x70\x34\x5f\x28\xf9\x32\x6b\x5b\x61\x1a\x48\x27\x9c\x12\x63\x28\x08\xa2\x30\xf5\x60\xd9\x54\x04\x65\x5e\x11\x6c\x62\x12\x6e\xee\x5c\x9f\x3f\xa8\x89\x91\x39\x19\x9f\x2f\xc5\xb4\x49\x94\x29\xc7\xd1\xe9\x7b\xbd\xf6\x4c\xa8\x07\xc8\x66\x14\x7e\xd5\x08\x06\x5f\x86\x15\x76\xb8\x4e\xa5\x59\x51\x2f\xf0\x53\x9f\x55\x67\xc5\x42\xd6\x4e\xca\x1b\x7b\xd0\xc4\x42\x6f\x8d\xd5\xcd\xd8\xd2\x84\x9a\xdb\x04\xd3\x61\x61\x4d\xb4\x50\xf4\xe7\x26\x9c\xbb\xa3\xb1\xc9\x51\x9e\x38\xd8\x5a\xcd\x0a\xb2\x62\x49\x69\x32\xbb\xa0\x16\x5d\x38\xfa\x2d\x43\x28\xdc\xfc\x57\x94\x18\x7b\xc1\x05\x5d\xc6\xc5\x8e\xb2\xd4\xc9\x03\xdd\xd5\x5f\x85\x33\x13\x53\x42\x33\x96\x83\x50\x71\x66\x2b\xf8\x26\x25\x87\x9e\x91\x0e\x44\x0e\xed\x41\x24\x6d\x6f\x31\x49\x89\xfe\x94\x60\xff\x87\x18\xf5\x43\xb9\xff\xbb\xac\x82\x87\x1f\x59\x4d\x8e\x96\x97\x32\xed\x3b\xb2\xc2\x84\xc5\x1c\x3c\xdb\xaf\x88\x7a\x4f\x82\x9a\x54\x1d\x85\xd1\x34\x4b\x45\x3b\x00\xdf\x41\xe3\xad\x35\x24\x85\xb4\xb0\x81\xae\xb0\x47\x4c\xa8\xba\x28\xef\x2e\xcc\xa4\xe3\xee\x5a\xf9\xcc\x82\x9c\x26\x2e\x72\xb7\xc7\x24\x96\x7c\xb1\x41\xa6\xc7\x7e\x20\xe3\x22\xc2\x70\xf7\xd6\x84\xf0\xcb\x66\x60\xc9\x0e\x3b\xde\xa2\x16\xda\x77\x37\x7e\xae\xfd\x45\x2a\xd3\xa8\xf9\x88\x01\x8c\xc2\x98\xe2\x4f\x8a\x96\xf2\xac\x45\xfb\xe9\x22\x55\xbd\x47\x48\x37\xee\x35\x91\xe5\xf1\xb8\x3a\x44\x1a\xcf\x18\xa6\x20\xbd\x49\x83\x5c\x3c\x5e\x64\xaa\x5a\xd9\xcf\xbe\xd3\xe5\xad\x22\x5b\xb1\xc3\xef\x2e\x3a\x31\x53\xc5\x9b\xc4\x86\x64\x55\x14\x4b\x7b\xc9\x2e\x88\x70\x59\x2b\x33\xa6\xab\xde\x89\x72\x9a\xae\xeb\x98\x24\x25\x3b\x4d\x6f\x69\x30\x4f\x77\x7e\x45\x1e\x1a\x33\xaf\x5d\x3d\x98\xae\xe5\x7c\xb2\xf9\x7a\x40\x20\xf7\x08\x7e\xa4\x3a\xf0\xf0\x24\x70\xfa\x6c\xb0\xde\xb9\xd4\xfd\x53\x8a\x08\xfb\x67\x5e\x0f\x62\xff\x22\x57\xa0\x0d\x4d\x8d\x2d\x54\xbf\x1b\xe2\xe3\x28\x35\x51\x1e\xc9\xb5\xe1\x79\x18\xa0\x6f\xc1\x43\xc3\xce\x49\xdc\x5c\x0f\xc5\xab\xae\xda\x07\x0f\xff\xc6\x22\xda\x71\x3f\xe1\xca\x24\x76\x39\x65\x2a\x7c\xdb\x41\x08\xe8\x52\x1d\x23\x20\x0b\xb7\x45\x83\x3c\xb8\x58\x2a\x95\x92\xa4\x10\x72\x69\x35\x23\x11\x77\xfd\x32\x88\x73\x36\x4a\xe6\xfb\xff\xe4\x7f\xcf\x2e\x26\x26\x31\x1a\xdb\x6c\xe6\x30\xe4\xf8\x8f\x04\x69\xdc\x10\x2b\xef\xc5\x92\x22\x2e\xbb\xb3\x61\x95\x3d\xd8\x55\x6d\x28\xab\x52\x8c\x4b\x50\xd1\xf2\xc1\x18\x6c\xb1\xb9\xcf\xf3\x0f\x87\x4a\x3a\xcf\xa5\x27\x1b\xd7\xc5\xc1\xb5\x5b\x8e\x88\xeb\x46\xcd\x88\x80\x7b\x26\xb3\x90\x81\x11\x96\xaa\xf2\x8d\x9c\xb6\x3c\x91\x52\xea\x81\x1e\x0b\x2c\x14\xe4\xa0\x78\xe5\x8d\x14\x11\xe5\x7b\x54\xbe\xa5\x75\x28\x7d\xf0\x64\xf3\x9d\x4e\x61\xaf\x8c\xbd\x00\xb2\xc2\x57\x31\x73\x5c\x1a\x42\xf7\x41\x88\x82\x24\x4d\xa7\xf5\x1d\xfa\x39\x13\xd1\x0f\x74\x84\x32\x0d\x20\xff\x42\x3d\x20\x6a\xea\xb2\xdf\x7b\xb6\x38\xdb\x35\x7d\x18\xa8\x4c\x74\xb2\x66\xd5\xbb\x16\xfa\x8a\xcf\x5c\x24\x15\x94\x86\x1a\x05\xab\xcf\x9f\x10\x19\x8c\x8a\xb1\x4a\x7b\x61\xf8\xb4\x5d\xd9\xd2\x03\x1c\x5c\xf3\x6f\xa1\xc2\x87\xec\x46\x38\xc5\x1a\xa4\x7a\x04\xe5\x28\x5c\x06\x9e\x63\x7e\x65\x52\x23\x22\x5a\xb3\x14\x68\x65\x32\x62\x9d\x5a\x48\xe8\xf0\xa0\x36\x26\x59\x60\x52\x12\x9e\x97\x12\xf5\x8a\x70\x53\x68\x6a\xc0\xe5\x3f\xaf\xec\x85\x74\xf4\xa0\xb7\x22\x70\x3c\x59\x35\x87\xbe\x80\x07\x3b\x8a\x14\xee\x8d\x17\xab\xa4\x96\xbf\x28\x84\x36\xba\x4e\x5d\x07\x80\x1d\xc2\x11\x6b\x00\x92\x97\x64\x9a\xb3\xb4\x45\xa4\xa0\xb6\xc7\x07\x12\x5f\x60\x7b\xbe\x4a\xa5\x48\xa0\xc8\x9f\x0d\x48\x45\x4a\xb5\xf3\x55\x08\xdb\x43\x88\xd7\xc1\x2c\x44\x83\xca\xad\xb0\x5f\x7f\x5d\x02\x00\x07\x3d\x8a\x07\x2b\xf1\x22\x36\x26\xba\xe0\x86\x48\xcb\x93\xb4\x66\x83\xc2\x60\xbf\x96\x81\xbb\xfb\x1d\x26\x41\xaf\xdc\xdb\x5d\xa2\xc1\x75\x58\x82\xa2\x06\xe6\x84\x35\xce\xc5\x4e\x10\x6f\x0e\x3b\xda\x1b\xd8\xe6\x18\x12\x03\xa6\x43\x39\x89\x77\x1f\x52\xa0\x22\xe4\xe4\xf9\x18\x20\x40\x85\xe6\x42\xf0\xa3\xd9\xc0\x52\x33\x05\x54\x49\xad\xc1\x67\x58\xc6\x7d\xc4\xc3\xec\x3c\x43\x3d\x19\x14\x5e\xf0\xbc\x05\xcb\x36\x6c\x64\x3b\xee\x30\x0b\x64\xc2\x67\x6f\x65\x67\x60\xfd\x0a\xaa\xcf\x21\xc9\xa5\x83\x89\xe1\xde\x34\x8a\xc8\xb4\x24\x35\xaf\xd9\x43\x21\xca\x34\x56\xce\x2f\xfe\xa3\x72\x07\x7b\x48\xcf\x46\x60\x8e\x56\x0b\xbb\x09\x5c\xa5\x7b\x13\x5b\xcb\xbf\x3a\xa4\x87\xfa\x6b\xfa\xea\xbd\xe9\xaa\x56\xaf\xd1\x69\xe5\x11\x38\xbd\x28\x6c\x2a\xe3\xb4\x2d\x04\xd8\x1a\xd9\x97\xd1\x34\xe3\x77\xd1\x98\x7c\x3f\x1a\x95\xda\xb3\x77\x3a\xe5\x70\xe0\x5f\xea\x84\x04\xad\xf7\x5b\xab\x62\x33\x98\x60\x40\x63\xa7\x4a\xdc\xd7\x14\x42\xa6\x76\xf0\xe1\xc0\x68\x20\x3b\x17\x2f\x54\xc7\x04\x13\xab\x95\x15\x67\x4f\x42\xe5\xfa\x08\xc5\x90\xd0\x72\x93\xf4\xd0\xff\x01\x6b\xdd\xd4\x8a\xc4\x0e\x63\x8a\x97\x32\x13\xbe\x9b\x93\x02\x0e\x37\x21\x4f\x0a\x0a\xd0\xd2\x9a\xa1\xec\x52\xad\x5f\x12\xaa\xd8\x0b\x73\xa3\x89\x6d\x84\xf1\x34\x99\x9b\x8f\x36\x23\x24\xe3\x0c\xcf\xa7\xe0\x3e\xd8\xcd\xbe\x78\x92\x60\x75\x6b\xa0\x88\xad\x63\xfd\x50\xcb\xc7\x1c\x54\x54\x4a\xf0\xea\x5e\x23\x21\xf9\xc8\x23\xab\xbe\x50\x8a\x63\x25\xb8\xff\xa3\xd8\xc2\xcb\x04\x22\x94\xf7\x81\xc0\x0c\x9b\xbf\x8b\xa3\x93\xa1\x12\xc5\x23\x6f\x7e\xe8\x3f\x16\x70\xb7\x56\xcf\x6a\xcc\x03\x65\xd8\x99\xb8\x06\x42\x38\x4f\x9a\x50\x99\x4b\xd4\xce\x5f\x52\xf8\xfe\xe5\xbc\xa9\xad\x99\xa7\x42\x2c\x05\x4a\x43\x08\x7b\x2d\x82\xfc\xc8\x7e\xa4\x2d\xdb\x43\xc8\x80\x12\x61\xd1\xcf\xf4\x4a\x60\x52\x88\x0b\x81\x6b\x18\x91\xbb\xd4\x49\x78\x43\xd9\x36\x4c\x93\x7b\x94\xbf\x92\x4e\x9f\xd4\x8d\xd0\x69\xb2\xc5\x46\xce\x53\x28\x4a\x01\xfa\xfa\xcd\xfd\x79\x04\xa1\x7a\x11\x7f\xed\xa8\xe1\x2c\x85\xa5\x25\xb5\x3e\x8e\x69\xeb\xc2\xed\x3b\x5e\x43\xc7\x8b\xd4\x87\x6d\x23\xba\xa3\xa4\x6c\x49\x6e\x5b\x78\x2c\x79\x72\xfe\x3e\x27\xc3\x80\xb9\x86\xe2\xd7\x6c\x29\x52\xe0\x6d\x35\x93\x8a\x18\x85\x21\x28\x2f\xe3\xab\x4f\x28\x02\x89\xab\x12\x6d\xdc\x94\x98\xe7\xdb\x04\xe7\xcd\x35\x90\x83\xdb\x63\x0e\x41\xb7\x1f\x6a\x2d\x2a\x27\x7c\x1a\xd4\x5e\xf6\x56\xe7\x52\x55\x4f\x35\x7a\x2f\x35\x47\xcf\xc9\x40\x4b\x62\x77\xa5\x92\x15\xc6\x29\x7c\x45\x24\x68\x50\x1e\x35\x02\x45\x52\xd1\x5e\x62\x50\x67\x4b\x76\xde\xfb\xa6\x25\x39\x32\x3e\xd0\x36\xc3\xd5\xa9\xfe\x34\x23\x03\xcf\xb2\x89\x80\xba\x30\x82\xe4\xc0\x0e\x42\x2f\xfd\x33\xb2\xe1\x43\xd1\x9d\x46\xf1\x49\x9d\x91\x74\x31\xe6\x1e\x6b\xd9\x29\x7e\x02\x0d\x73\xe1\x2f\x0b\xe9\x20\x76\xb0\x37\xbe\xe0\x7a\x95\x96\x78\xe9\xd8\x00\xca\x68\x5d\x34\x59\x33\x06\x21\xa5\xb4\x65\xd7\x08\x14\x18\xb0\x49\xdd\xd3\x23\xc1\x18\x4c\xb4\x9c\x31\x9a\x60\xca\x6c\xfb\xf0\xaa\x43\x50\x4c\xfb\xcb\x3b\x10\x87\xeb\x32\xb3\x71\x0c\xe5\xc2\x99\xfe\x85\x90\xc0\x28\x29\x67\x1e\x5e\x8b\xa6\x49\x05\x2b\x33\x9f\x5a\x45\x1a\x9a\x8b\x22\xc6\xbc\x8b\xe5\xf3\x58\x17\xa6\xeb\x24\x5e\x5c\x45\x10\xb6\x82\xc4\xaf\x76\xb0\x47\xb0\x4b\xa8\x10\xc3\x09\xf1\x96\x68\xda\x90\x4a\xac\x38\xff\x27\x41\x27\x08\xb5\xed\xd8\x6f\x46\x11\x1e\x7f\x45\x8b\xbd\x1d\x33\xd5\x2e\xe2\x25\x59\x62\x9c\x14\x5f\x76\x1e\x4a\x44\xed\xfa\x14\xca\x2e\xc9\x16\xe1\x38\xd3\x57\x39\x15\xb9\x9d\xb3\xa8\x19\x43\x4e\x93\x04\x40\xc6\x68\x52\xdc\xa2\x72\x94\x3e\xe4\x39\x8c\x41\x02\x83\x05\x46\x25\x31\x34\x96\xa8\x91\xac\x92\xd8\x2d\x4a\x9a\x6e\x0e\x2e\x70\xc2\x4f\x1d\x7e\x2b\x3a\x1b\x2e\x8e\x96\x7c\x59\x08\xf6\x65\x8d\x20\x09\x11\x6e\x3d\xe0\x3b\x82\x65\x92\x9a\xcd\x85\x3a\x72\xc9\xda\x08\xa6\x7b\x6c\x22\xfe\x59\xca\xe9\xec\x1b\x8d\x46\x58\xc4\x00\x71\x82\xba\xc2\xbe\x31\x54\xb1\x9b\xe0\x0b\xa3\xad\xad\x15\x79\x0f\xc5\x34\x2e\x36\xad\x54\xd7\x6b\xad\x8c\xba\xc0\x26\x50\x09\xe3\xc8\xdc\xa4\x05\xe3\x6e\x1e\x31\xf9\xe7\x47\xc5\x98\x3b\xed\xa2\xf9\x20\x09\x7e\xf5\xad\x6e\x1d\x43\x2f\x58\x7d\x20\x3e\xa5\xb1\x77\x22\xa5\x47\x91\xee\xa6\x3a\xbf\xaf\xc9\x7f\x67\x55\x75\xca\xcc\x44\xff\x91\xfa\x08\x55\x50\xbe\x98\x7d\xac\xad\xbd\x5a\x14\x11\x55\x24\x35\x49\x0a\xb6\x1b\x94\x36\x23\xc4\x93\x1b\x82\x32\xb1\x48\xd6\x85\x71\x00\x4a\x6c\x98\x50\x72\x34\xfe\xa4\x39\x1e\x75\xda\x51\x7b\x62\x68\xef\xa0\x1b\xbf\xb4\xd0\xda\xc9\x42\x4d\x4e\x93\x1a\xe2\xa1\x34\x93\x25\x62\xe3\x8d\x81\xbf\xb7\x86\x7e\xde\x22\x09\x67\x08\x57\xa5\x03\x65\x1b\x10\x4a\xdd\xa9\x17\x11\x16\xbf\xeb\xc7\xfd\x7b\x9f\x54\xed\x78\x95\xd6\x4a\x4b\x68\x45\xba\xef\xfe\xe1\x6d\x8a\x50\x6f\x07\x50\x64\x2a\xb3\x98\x78\x43\x9a\xd3\x80\x2b\x1c\xba\x10\xf5\xbd\xe5\xb4\x3f\xa9\x0b\x79\xf7\xa2\x2a\xe1\xe0\xdf\x46\xd7\x9f\x53\x93\x07\xe6\x83\x80\x6b\x0c\xa0\xaf\x0e\xb2\x26\x94\x9d\x56\x5c\x84\xfb\xa5\xb8\x23\x92\x7d\xe2\x06\xed\xdf\xbb\x4b\x91\xde\x89\x87\x0c\xa6\x2d\x76\xd4\xec\x2c\xbd\x20\x24\x0f\x9b\x16\x5c\x62\x92\x83\xa9\x6e\xcc\x03\x34\x70\x68\x43\x1f\x5c\x9a\x54\x0e\x92\x0d\x54\xc7\x09\x74\xb9\xb0\xe0\xb5\x69\x20\x79\x67\x1e\x4b\x1f\x16\xbd\xb0\x3f\xa2\x78\x1d\xb8\x55\xbe\xdc\xbe\xa6\xa6\x0a\xe2\xfd\x06\x3a\x15\x3e\xee\x4c\x79\x4e\x7a\x6d\x95\xb0\x07\x05\x24\xd4\x10\xdb\x9a\xc0\x54\x79\x6e\x3a\x27\x4d\x4c\x10\x89\xf2\xa8\xe2\xc5\xb2\x07\x93\xfa\x20\x28\xb8\x06\x8d\xaf\xfe\x7e\x1e\x70\x6d\x3e\xaa\x90\xe3\x75\x5c\xe8\x8c\xdd\x05\x85\x65\x64\x86\x8a\x44\xdb\xda\x89\x13\xbb\x62\x59\x2c\x76\xee\x23\x56\x05\x79\x80\xe0\xf3\x97\x68\x9a\xbf\x08\x51\x4f\x06\xbf\x78\x80\x09\x3d\x20\x76\xa0\xd3\x62\xb9\x59\xb4\xc0\x69\x9a\x4d\x65\xfd\xb5\xfe\x59\x32\x7f\xf9\x7c\x8a\xe6\xe4\xb1\xdb\x19\x59\x33\xe2\xa1\xa0\x82\xc3\xa1\x7c\xcc\xa6\x92\x2f\x4b\x0f\x71\x91\xc0\xef\x32\x1d\x90\x55\xfd\x42\x8f\xba\x14\xf2\xc2\x39\x45\x70\x9b\x3a\x62\x1d\xe6\xd0\x65\x2d\xdf\x0d\xe0\x15\x5d\xe3\xce\xc5\xda\x72\x50\x68\x57\x4e\xb7\xec\x4e\xea\x90\x27\x94\xe2\x30\xc0\x91\x1a\x36\xd4\xd9\x8d\xb3\x1b\x11\xdd\x7c\xb5\x00\xf7\xb2\x65\x29\xc4\x7f\x49\xe0\x29\xad\xaf\xdd\xc5\x1e\xa4\x97\xfe\xab\xba\x75\xb6\xeb\x6a\xee\xb7\x9d\xa0\x41\xed\x17\xd0\x1f\x90\xb5\x71\x2a\x0d\x0f\xbc\x57\x9b\x95\xa5\x77\xb5\x52\x1f\xfa\xcd\xda\xee\x2e\x48\xb7\x77\x4d\x50\xa5\x9c\xf6\xbc\x93\xfa\x5c\x24\x3a\x96\x96\xd1\x2b\x1c\xe2\x7e\x5d\x38\x6c\x28\xe7\x42\x36\x19\x27\x04\xcd\x4a\xda\x19\x8e\x50\x76\x98\xbd\x0a\x6f\x15\x8b\x75\xf7\x36\x96\x9d\xda\xe4\x8d\x55\xf3\xa0\x6f\xc1\xc4\xc5\x38\x16\x98\x36\xc4\xd2\xb3\x9c\xab\x8b\x0f\xd3\x47\xec\x4f\xce\x40\xb9\xd4\x4e\x07\x56\x8a\x86\x96\xe5\x31\x2b\x38\x97\x2f\xa1\xa1\xdd\x2b\x77\x33\xb1\x56\x4a\xf8\x2d\xbd\x98\x2c\xb3\x07\x7e\x79\x52\x95\x76\xdb\x55\x90\xf0\xcb\xa9\x03\x04\x0e\x33\x0f\x0a\xe1\xae\x63\x83\x4e\xb4\x3c\x51\x1b\x63\x18\xdd\xf8\x2e\x72\x7e\x4a\xe5\x5c\x75\x4c\xc4\x7d\x61\x56\x4f\xdd\x7b\x81\x37\xd3\xf9\x54\x5f\x47\x52\x71\xa6\x8b\xf9\x48\x80\x09\x23\xea\x01\xfe\xce\xb7\x99\x6a\x12\x6a\x43\x08\x9f\xda\xc2\x64\x08\xdc\x69\x5e\x21\x08\x14\xdc\x94\xf5\x94\xd1\x9d\x4a\xf7\xe5\xc1\xcd\x6a\xac\x2e\xca\x85\xbf\x4c\x6d\x0a\xae\x84\xab\xd4\xc2\x62\x01\x1c\xbb\x37\x82\x2a\x2f\xd9\x62\x75\xcc\x2c\x12\xbf\x93\xba\x97\x9c\x8a\xfd\xfa\x00\xe0\x43\x41\x60\xd8\x24\x1c\x0b\x89\x09\xde\xc5\xdc\xc6\x6a\xf9\x99\x25\x32\xe9\x1d\xde\x61\x0c\x43\x0d\x7f\x6f\x83\x69\xd4\x04\x5d\x64\xce\x9c\x9d\x12\xe5\xc7\x36\xd9\x66\x0b\xef\xd6\x9f\x7f\x79\x1e\x74\xe3\x2d\x48\x4e\xca\xc9\xfb\x88\x5d\x64\x91\xd4\x28\xd2\xab\x64\xa8\x59\x38\xbc\x89\x76\xb7\xd8\x0d\xc3\xe6\x27\xf0\x6c\x82\x8b\xa5\x1a\xa7\x37\xef\xb7\xb4\x19\xb0\xbd\xea\x7f\x54\xbf\x77\x1d\x59\x78\x84\x81\x87\xd7\x7b\x9c\x68\xf2\x04\xdb\xbb\x78\xba\x54\xaa\x38\x7e\xe6\xb1\x91\xae\x70\x8f\x30\xce\x1c\x26\x60\x85\x83\x4d\x6d\x0e\x70\x6f\x34\x65\xd0\xd7\xc0\x53\x48\x6d\xfa\xa3\x85\x69\xb0\x1d\xef\x50\x7f\x46\xb3\x9f\x25\xa7\x7a\x54\x7b\x4b\xa7\xa4\x08\x6f\xb0\xbc\x68\x2b\x9c\xaa\x88\x38\xbd\xe9\xbf\xaa\x48\x16\xb7\x12\x2a\x46\x41\xba\x5d\xf3\xd5\x01\x74\xa3\x2e\xe3\xd5\xbc\xfe\x93\xa2\xdd\x17\xc3\x6f\x14\x59\x46\x93\xcb\xe8\x24\xef\x2a\xbc\xfa\x1e\x53\x28\xcc\xc8\xb7\x36\xe2\x4d\xe0\x70\xba\x8b\xf0\xec\xe2\x80\x38\x30\x2d\x74\xf2\xb2\x58\xd5\x98\x93\x98\xb8\xe0\x7f\x32\x10\x75\x90\xb8\x69\xc4\xaf\xa4\x8d\xb8\xed\x3f\x4a\x0c\xad\x6c\x3a\x51\xef\x00\x8f\x2c\x10\xfc\xef\xa4\xa1\xda\x3f\x73\x57\xc5\xc6\x96\x6a\xc2\x9a\x34\x50\xcc\x2d\x31\xa5\x1b\x65\xc2\x52\x04\x61\x54\x78\x9e\xa3\x94\xf5\xe1\x08\x82\xa3\x29\xba\xef\x92\xf1\xd9\x13\xb5\x4b\x37\xa9\x77\x78\xf5\x97\xa6\xc4\x7c\x6c\x63\x90\xb2\xa9\x60\x0c\x4e\x9d\xe7\x80\x9e\x01\xd2\xb6\x02\x29\x9d\xce\xfe\xa3\x94\x21\x4d\x02\x9b\xae\xb8\xa4\xf3\xbc\x43\x7c\xc1\x16\xbd\xde\x38\xaa\x47\xb8\xc0\xf9\x78\x68\x90\x5a\x15\x75\x7d\x17\xfd\xeb\x6b\x05\x6f\x68\xd6\xc7\x8f\x7c\x82\x6c\x2e\x09\x0a\x68\x05\xf3\x79\x38\xd5\x95\x91\x05\xe5\x07\x1a\x1f\x76\xd7\x5f\x1e\xa2\x96\xbc\x23\x8a\x06\x83\x86\x3f\xbe\x5f\x26\x1b\x71\x1a\x3e\xe8\xbf\xd3\x1b\x86\x8b\x1a\x1f\x1e\xb7\x7f\xc4\xcd\xe4\x2f\xff\x25\x22\x36\x39\xb6\x9b\xc2\xe4\xa5\xb4\xb4\x9d\x17\x16\x5e\xcd\xf9\xc9\xaa\xd9\xc5\x0c\xa0\x89\x24\x01\xfc\x50\x73\xd5\x76\xfc\xd0\xcc\x74\x0b\xf5\x15\x95\xc4\xef\xed\x61\xfb\xb4\xdd\x79\x4c\x9c\x24\xc1\x66\xa0\xee\x32\x09\x6c\xb5\xd7\x89\x98\x04\x2f\x4d\x0d\x8d\xf9\x49\x72\x01\x16\x06\x37\xec\x1c\x18\xc6\xd7\xe4\x4f\x94\xaf\xd4\x5d\x97\x1d\xfe\x56\x3c\x33\xf5\xac\x10\x99\xf9\xde\x35\x7e\xd1\xce\x7f\xc8\x6e\x86\x4c\x1f\x46\x6b\x84\xb6\x48\x21\x14\x19\xa0\x1e\x8f\x8e\x86\xe8\xf5\x6c\x23\xdb\x62\xa5\xbe\xa9\x32\xe9\x0d\xc9\x06\x0d\xe3\xa7\x4b\xa4\xe4\x22\x23\x99\xfd\xa4\x82\x67\x6b\xdd\x38\x54\x64\xa2\x04\x94\xe6\x25\xad\xda\x40\x59\x2d\xbb\xf8\x1d\x23\xcf\xe8\xf9\xe5\xf3\x38\xdd\x58\xc8\x04\xa3\xb0\x08\x3e\xf1\x08\x90\xeb\xe4\x1d\x70\x25\x09\x5d\x2c\x3b\xfe\x3b\x9b\x4f\x51\x8f\x60\xce\x4e\x5d\x22\x5b\x62\xf5\xca\x59\x48\x94\x42\xfb\x7e\x91\x6c\x96\xf7\x45\x4b\xb2\xb4\xf6\xd1\xb6\xed\x6a\x44\xbc\x04\x2f\x26\x89\xce\xea\x7b\xe8\xd5\x2e\xbd\x16\x1e\x2d\xd2\xf4\xfd\xa3\xc8\x70\x44\xfe\x12\x2c\x48\xc1\x38\x7e\xe2\xa3\xe7\xde\x52\x27\xc1\x2a\x28\x95\xee\xd1\x2c\xc7\x2a\x1c\x31\x46\xa7\xd8\xe8\xa9\xca\xde\x86\x8d\x85\x3a\x1f\x41\x0a\x5f\x47\xc6\x54\x0f\xc9\x07\x6f\x6a\xad\x53\x2f\xce\x57\xc2\x8c\x75\x98\xc9\x47\xb0\x2b\xb9\xcb\x3e\x69\xbe\x41\x5a\xaa\xcf\xf0\xe5\x4e\x0f\xaa\x70\xdb\xa1\x55\x61\xd2\xe7\x96\x70\x35\x1e\xad\xc8\x69\x17\x97\xb8\x01\x05\x29\xf8\x35\xe5\x5b\x60\x97\x02\x07\xfc\x02\xe1\xd1\xd9\xa3\x9b\xe9\x7c\x27\x31\x0e\x42\x33\xc9\x05\x68\x39\xac\xb8\xbc\xfc\x47\x53\xcc\x55\xab\x6a\xb2\xe2\x8c\x1b\x8b\xbb\x73\x3a\x6f\x82\xbd\x63\x7a\xad\x48\x79\x89\x48\x8e\xd3\x2c\x06\xe1\x7c\x14\xd6\xb2\x5f\xa2\x64\xda\x22\x5f\xcc\x28\xaf\x95\xa7\x31\xc2\x6d\x22\x00\xde\x24\x1f\x36\xcf\xac\x7b\x58\x19\x0b\xbf\x81\x29\xc5\xee\xea\x7e\xcc\xdd\x45\xdf\x76\xf5\xd8\x4e\x83\x7a\x91\x42\xbc\x52\xcc\xc1\xd9\xb2\x1c\x49\x2b\xcd\x98\xb5\x4d\xaa\xb9\x38\x1f\xee\x86\x6a\xef\xe1\xb2\x74\x2b\xca\xb0\xe9\xd3\xb5\x78\xe7\x1f\x99\x2e\x9f\xee\x09\x75\xe0\x4b\xf0\x26\x99\x09\xa2\x71\x70\x10\x86\xfe\xd5\x11\xd4\xab\x47\xd2\x17\xa1\x0b\x40\x2b\x6d\xcf\x28\x0a\xba\xb2\x89\x4a\x17\x49\xfd\x40\xfb\x11\x4a\x5b\xe5\x57\x43\xb5\x55\x47\xf5\x01\x2e\x53\xd6\x04\x19\x6a\x96\x2a\x4a\x90\x9e\xa5\xd9\x4f\x4d\x67\xf0\x0b\x91\x85\xd5\x5a\x66\xd3\xe9\xec\xd6\xab\x7d\x02\x83\x99\xed\x53\x6a\x8c\x40\xd4\x18\x3c\x68\x90\xf3\xa8\x99\x23\xde\x22\xc2\x3a\x02\xe1\x84\xe9\xde\x9a\x96\xe4\xcc\x9c\x11\x24\x2e\x6c\xfd\x03\xe1\xa4\x22\x5e\x0e\x38\x9f\xce\x6e\xd7\x19\x46\x85\x20\xc4\xc3\x97\x50\x97\x04\xae\xad\x25\x79\x5c\x0c\x0f\xc6\xf2\xfe\x09\xb6\x8d\xea\xef\x83\xfd\xe6\x82\xb9\x89\x52\x3b\xa1\x25\x39\x83\xb8\xcd\xec\x8e\x08\xe4\x8a\x36\x04\x44\x23\xd9\xd3\xfb\xc4\xce\x54\xb3\xdd\xf0\x23\x7d\xd0\x6b\x45\x85\xbe\x11\x9f\x9f\xb9\xf0\x48\xcf\x98\x91\x0d\x27\x8b\x8c\x13\x23\x72\x8c\x7b\x0c\x1a\x97\x93\x09\x9a\x1e\x0d\x75\xba\xf6\x7f\x4e\x94\xdc\x2f\x2d\x01\xd1\xd8\x1f\xcd\xc3\x53\x96\x1d\x55\x1f\x8b\xc4\x34\xb4\x84\x3b\xd7\x5a\xb6\xfd\x2f\xb7\xab\x46\x7d\x63\xc4\xf1\x6f\x54\xc9\xb8\x60\x78\x52\xbc\x53\x53\x2c\xbf\x36\x13\x1b\x86\x68\xfb\x1a\x0b\x14\x3d\x5f\x20\xba\xb4\xfe\xb4\x90\x2a\x88\x49\xbd\x5a\xe8\x92\xef\x1a\x5c\xee\x6c\x23\x86\x44\xf6\x40\x0c\x60\x88\x49\x6f\x6a\xb1\xdc\xc2\xc7\xac\xe5\xc1\xa8\x9a\xd8\xa7\x6d\x40\x08\xcb\x33\xbd\x63\x45\x07\xcd\x13\xb7\xff\x49\xb5\x1a\xd9\x2c\x14\xde\x15\x14\x7a\xab\x12\xad\xd5\x67\x55\xbd\x74\x85\x71\xde\x38\xe5\xc6\xf3\x34\xea\xfb\x34\x4e\xc7\x2c\x2b\x13\x44\xc3\x62\x51\x05\xd6\xcd\x91\x78\x16\x7e\x9a\x5e\x09\x6f\xb1\xd4\xcb\x43\x8b\x3e\xcd\x51\x14\x4f\xd3\x81\x4d\x47\x73\x23\xd7\x53\x7a\xa1\x4c\x5d\xca\xa2\x19\x6d\xde\xbc\xcb\x2d\x91\xf4\x50\x6f\x81\x25\x83\x9f\x43\xc2\x80\xec\xad\xc3\x6f\xda\x9f\x92\x9a\x51\xa1\x3e\xda\x0b\xe9\xe2\x28\xc4\x2e\x5c\x6e\x54\x05\x13\x43\xbc\x98\xd5\x06\x0f\xfb\xef\xdf\x8f\x36\x8a\x23\x15\x38\xf7\xb4\x0b\x3e\xb2\x0f\xe4\xda\x55\xd0\x03\xc9\x3d\xd8\x6d\x9b\x86\x87\x6d\x79\x84\x85\xa6\x38\xdf\x75\x66\x89\x4d\xf8\xe8\x1f\x66\xa3\x53\xe6\x0b\x10\xb0\x53\xe2\xf7\x25\xd5\x8f\x4a\x7c\x50\x14\x2c\x98\x68\x87\xcf\x5c\xe9\x9d\x3c\x21\xd4\xe3\x84\x2d\x34\x6f\xf0\x64\xa5\x83\x60\x99\xc3\x42\x1c\x35\x89\x34\x31\xba\x7f\x42\x44\xd4\x8b\x01\x73\x54\x30\x1c\x8a\x1b\xb8\x67\xa3\xba\x14\x58\xc3\x13\x76\x90\x34\x35\x3d\xa2\x0a\x9d\xf2\x45\x23\xc2\xa6\x13\x73\x05\x3a\x75\xa6\x1c\xe4\x5c\xa0\xa2\x26\xba\x1e\x29\x77\xa7\xa4\xf1\x49\x29\xf6\x82\xcb\x57\xf1\x51\x6a\xaa\x78\xcc\x91\x75\xe1\xbb\xf3\x7c\x02\x43\x76\x7e\x61\x2f\x3f\x1c\xcd\xac\x1e\xf2\xf3\xd4\xb7\xc1\x75\x7c\x22\x11\x33\x16\xf1\x3f\xbd\x6b\x1b\x12\xa6\x81\x56\xd9\xb2\x23\x6e\xa1\x4c\x4e\x6b\x22\x0f\x72\xa3\x10\x41\x9c\xb1\x72\xe8\x9e\x5e\xd6\xc8\x5f\x00\x86\xa1\x47\x90\x66\x1e\x4e\x2b\x09\x84\x5e\x97\x06\xc7\xd9\xe7\xfa\x30\xf5\x29\x40\x29\xa2\xd6\x1f\xbd\xbc\x64\x81\xe9\xa5\xcd\xee\xd1\x22\xf7\x13\x67\x29\x7c\x38\x44\x49\x1d\x62\xef\x36\x6d\xe6\x38\x3b\x26\x88\x2d\x32\xda\x29\x52\xbb\x12\xb7\x5f\xe9\xe6\x16\x0d\x61\x1b\x13\x87\x9f\x4f\x4d\xb1\xad\xf5\xe8\xe2\xc6\x4b\xbd\x26\xdd\xd1\xed\x79\x8b\xde\x47\xa6\x14\x73\x89\x8a\xe9\x9b\x0a\x7a\x39\x08\x36\x97\xac\xbc\xff\x0d\x23\x29\x89\xbc\x9d\xd2\x81\xf1\xb1\x59\xbc\x69\xc1\x9b\xdf\x92\x04\x5e\x96\x4f\x6b\xc1\x13\x47\xdd\xa5\x38\xb1\x23\xb3\x9d\xaa\xc2\x1e\x02\x34\x4c\x30\x42\xab\x0a\x14\xb6\x43\x63\x2d\x29\x04\xe4\xc5\xec\xd0\xb8\x8f\x59\xe7\x5d\xdb\x51\xef\xc0\xe0\x9c\xa9\x50\xea\x25\xc6\xb3\x50\xd8\x57\xba\x41\x16\x08\x94\x86\xed\xfb\xfc\x4f\x5f\x05\xc2\xd6\xbf\x57\x8b\xe4\xb9\x5c\x31\x88\xcf\x9a\xc3\x33\x9f\xd0\xb8\x37\xc3\x57\x1f\x12\x89\x0d\x9c\xde\x25\x35\x74\xf8\x99\x20\x91\x76\x29\x3a\x6b\xfa\x48\xdd\xb7\x27\x31\x43\x8a\x1c\xab\x57\x6c\x14\xd3\x8f\x27\x04\xc2\xa3\x61\xc1\xce\xab\x78\xae\x96\x9f\x57\xce\x17\xdc\x17\xc6\x55\xdb\xd5\xe7\x71\x69\xba\x36\xca\x30\x1a\x0e\xc2\x3f\xf6\x4d\xf7\x73\x9d\x44\x47\x27\xf9\xc1\x21\x20\x11\x30\x50\x41\x82\x43\xca\x98\xbe\xee\xff\x7a\x2e\x40\x0c\x55\x6c\x73\xaf\x4e\x7b\x87\x9e\x8b\xe1\xeb\x71\x83\x55\xf0\xcd\xd5\xa9\x6b\xb9\x26\x52\xb1\x7a\x49\xfd\x31\x14\x8d\x61\x59\x3d\xea\xa3\xe4\x7e\x21\x76\x87\x31\x2d\x54\x44\xdf\xa5\x5f\x0c\x8e\xeb\x4d\x7e\xe8\x86\x21\xc6\xb0\x4e\xff\xd1\x70\x0d\xae\x40\xd9\xbc\xee\xa1\x5a\x33\x14\x77\x77\xa8\x1e\xfb\x03\x17\x01\xf2\x4e\xcd\x67\xcf\xde\xd3\x4c\x02\x63\x9b\x31\x10\x9b\xf1\x6b\xd5\x5b\xdb\x55\x16\xb4\x85\xc6\x31\xbe\xa5\x2a\xb0\xd1\x00\xb3\xcb\x70\x88\x6a\xed\x7a\xce\x81\x44\xda\x97\xc2\x21\x6b\x0c\xdc\x8c\x40\x0a\x8d\x4e\x39\x8a\x19\xcf\x80\x01\x89\x31\xce\xe4\x2f\x5b\xda\x3d\x7d\xc8\x0d\xf8\x48\x35\xce\xf5\x36\xf1\x6b\x44\x03\xd8\xdb\x99\x93\x4b\x6a\xca\x73\x13\xdb\x04\x5c\xae\xe0\x2b\x7e\x89\x68\x1d\x97\x3c\x09\x3e\x7f\x4a\xb0\xa4\x4d\x4d\xc4\x81\x80\x68\x0e\xe1\xcd\x12\x38\xd8\xbb\x70\xa2\xe6\x51\x67\x30\x34\x18\x50\xc4\x10\x15\xc0\x6e\xec\x24\x8b\x11\x3d\xff\x4c\x15\x09\x2a\xf1\x4a\x31\x87\xfc\x13\x4b\xda\x1a\x65\x34\xfe\x3e\x06\xb3\x0a\x15\x1a\x04\xf8\x42\x06\x53\x5b\x9d\x43\x80\xa0\xab\xbc\xd6\x16\x2e\x0c\x0c\x4c\x11\x4d\xb8\xce\x36\x16\xe0\x27\x11\x12\xfd\xd6\xda\xa4\x65\xc2\x12\x17\x16\x9d\xca\x2a\x08\x29\x84\x06\x35\xf8\xb6\xd1\x75\xa2\x9f\xcf\x1b\xa8\xff\xe9\x2c\xe2\x35\xf0\x99\x37\x62\x50\xf4\xca\xec\xa1\xc4\x79\x6b\x92\x50\x58\x3e\x33\xf5\x96\xda\xd3\x59\x8a\x40\xe1\x45\x45\xe7\x9f\x70\x04\x11\xd9\x87\xe4\xff\x9c\x31\x93\x66\xa8\x12\x33\xd8\xc2\xce\xe1\xc3\xc0\xbe\xe3\xc7\x72\xcb\x90\x65\xa1\x35\x3a\x12\x12\x2d\xf8\x03\xf4\x5c\x3e\xbf\x65\x02\x7a\xd9\x9f\x33\x44\xb4\x1c\x9e\x0b\xbc\xd5\x8b\x31\x41\x25\xba\x73\x0c\x43\x5e\xfe\x8a\xe2\xfe\xfa\xea\x0d\x0f\xdb\xc8\x84\x36\x40\xe5\xd0\x2c\x94\x50\x2c\x59\x2c\xe6\xc2\x48\x80\x74\x31\x41\xec\xbd\x5b\x14\x05\xfb\x4d\x53\xcc\x9b\xda\x35\x70\xae\x9b\x2e\xe9\x7f\xc7\xc2\x18\x88\x96\x67\x54\x69\xcf\x2d\x09\x32\x44\x4e\x1b\x85\x2a\xfe\x8d\x87\x46\x63\xd9\x86\xf4\x2a\x41\x2a\x0d\xf9\xe0\xaf\xf9\x9b\xe4\x3a\x2c\xde\x4a\xc7\xa9\x20\xef\x72\xfc\xcd\x5b\x9b\xdb\xfa\x22\x47\x59\xf2\xa5\xeb\xf9\xf7\x2f\x33\xc9\x33\x6f\xf0\x01\xde\x9a\x18\x8a\xc7\xba\x5e\xe0\x85\x66\xea\x70\x47\x35\x0b\x93\xcd\x99\x51\xad\x71\x07\x50\xdf\xb5\x4b\xe9\x28\xbf\x6b\xca\xdd\x30\x33\x28\x0a\xdb\x55\xb2\x70\xde\x48\xfd\x05\x85\xf4\xce\xea\x96\x66\x94\x8f\x24\xc2\xbf\xa1\x1d\x93\x31\xb2\x25\xaa\xbd\xc8\x67\x6a\x33\xb4\xdc\x7b\xf9\x0c\x29\x8e\x77\xd3\x45\xea\x85\x32\xbb\x5a\xe8\xd9\x58\x1c\x95\x80\x4d\xaf\x69\x59\xe8\x3b\xa1\x11\x70\x88\xbc\xf9\x52\x28\x10\x69\xff\x22\x04\xb2\x74\x99\xb4\x16\x07\xfd\x90\xaf\xa4\x46\xae\xc7\x88\x3b\x42\x5b\x79\x79\x91\x3d\xc7\x74\x33\xc6\x87\xff\xd1\xf3\x1f\xe4\xe2\x45\xc5\x77\xaf\x77\x46\x5c\xa5\x41\x3e\xc8\xa5\x71\xa7\x31\x5e\x97\x26\xfc\x31\x2a\x18\x1e\x68\x69\x35\x56\x96\x5d\x0c\x79\xba\xd3\x0f\x78\xff\x41\x0d\x4d\xd1\xac\x29\xcd\x07\xc5\x8b\x24\x71\xea\x20\x32\x7f\xf1\x9c\xdf\xd4\x44\xdc\x3e\x7a\x3c\x0d\x22\xdd\x63\xb1\x6e\x0c\xd9\x71\x6d\x30\x4f\x3b\x72\x1d\xb6\xc6\xbc\xa5\xc2\x13\x64\x79\xe5\xe7\x67\xa8\xcf\x1c\xd1\x27\x88\xce\x5f\x62\x07\xae\xbf\x26\x53\x1e\xc2\x04\xe9\x57\x39\x12\x0d\x86\x77\x1d\x65\xa6\x83\xa9\x0d\x54\xb9\xa7\x72\x8c\x74\x35\x9d\x3c\xab\x68\xab\x7f\x0b\xbb\x61\xc5\x00\x7f\xa7\x6b\xb0\x39\xa1\x30\xdd\x7b\x52\x16\xa1\x97\xc1\xb0\x35\xbb\xec\x4b\x20\x0a\x99\xb2\x15\x21\x57\xbe\xc5\xd0\x0a\x94\xc3\x9a\x20\xce\x91\xd4\xa6\xe3\xaa\xa7\x02\xe0\x0e\x0e\x66\xc6\x3a\xd2\xf2\x39\x25\xf8\xa6\x6e\x7f\xbd\x99\xc8\xb0\x31\x37\x3e\xa6\x7d\xee\x78\xf6\x47\x9a\xbb\x4b\x71\x87\x0a\x81\xb8\x09\x1d\x18\xac\x75\xf7\xe1\x05\xa4\xbe\xaa\x66\x21\x2e\x11\x4f\x3f\x94\x17\x02\xb6\x94\x6e\x9a\x8f\x11\x0a\xac\x86\x8d\x34\xed\x8d\xbc\x27\x65\x66\x29\x68\x6d\xde\x66\xcb\xae\x95\xe2\xb1\x64\xe5\xa6\x5c\xaa\xbc\x54\x83\x94\x04\x41\xcc\xd8\x60\xb8\xf9\x83\x26\x31\x97\x5b\x8e\xec\x46\x0d\x63\xf5\x21\x73\xe1\x26\x7c\x8f\xcb\x10\x08\x93\x10\xfc\xef\x29\x13\x9d\x32\x6c\xbf\x84\xaa\x8b\x38\x6a\xb0\xc6\x4e\xee\x75\x75\x10\xa1\x0d\x23\x13\xd2\x0b\x3a\x87\x59\x66\xa2\xe9\x57\xd5\x01\x01\x2f\xe9\xfb\x80\xe5\x19\xdf\x37\x6d\x88\x5e\x38\x03\x0a\x65\xff\x44\x56\x01\x19\x36\x60\x8e\xab\x8e\x60\xb8\xe7\xd8\xf0\xb1\x11\xa7\x6b\x78\x52\xc4\xc1\xf5\x8c\xac\xbf\xcd\xb8\x65\x6a\xd4\xa4\x85\x34\x40\xe6\x21\x90\x43\xe2\x34\xaa\x44\xfa\x93\x33\xe5\x77\x95\xe5\x5e\xf1\x17\xd5\xbb\x60\x70\xa3\xe3\xc3\xfb\xc9\xaf\xbc\xae\x91\xab\x59\xed\x88\xb2\x21\x06\x19\xcf\x1f\xcd\x72\x75\xbe\x3a\x41\xdb\xca\x62\xaf\x03\xde\xfd\x29\x6a\x9f\x32\x68\x87\x4f\x88\x12\xd8\x7f\x9c\x35\x6f\x44\x42\xab\x31\xc2\x9a\x29\x64\xa7\x42\x62\x30\xf1\xc0\x93\x5b\x19\x98\x60\xb8\x91\xf8\xb5\x30\x5c\x49\x4a\xc4\x80\x9f\xa2\x4f\x8c\x41\xb4\xfe\x76\x57\x0a\x6e\x67\x8e\x5d\x3c\x03\xf7\x0b\xd0\xf1\x8d\x55\x2c\x78\x96\x56\xf3\xa0\x0c\x29\xcd\x74\x14\xc2\x2c\xda\x91\x09\x9b\xcb\x35\xb2\x65\x0a\x6a\xd0\x52\x08\xc3\x63\x0c\x3e\xcd\xa8\x1c\x00\x24\xe0\x42\xde\x91\x53\x1d\x89\xf5\x2c\x7d\x5c\xf2\x5e\x54\x29\x47\x82\x58\x4e\x1d\x54\x1a\xdc\x17\x35\x3e\xc4\xa0\xd6\xe8\xd6\x96\x35\x25\x77\xa3\x31\xa0\x96\xca\x11\x93\x4d\x78\x0c\xf7\x28\x31\x40\x92\x9b\xf1\xcf\x66\x25\x00\xa0\xcd\xc3\x4e\x6f\x68\xa2\x16\x7f\x26\x9e\x01\x7b\xc5\xa1\xcd\xca\x92\x68\x80\x52\x37\x8f\x6e\xa6\x12\xcd\xea\xaf\x88\x4a\x91\xfa\x37\xb0\xd9\x1c\xe1\xe4\x6c\x0a\x8e\xac\x48\x31\xf3\x20\x06\xa9\x3a\x53\x57\xfe\xa6\xbc\xda\x9c\x9e\x73\x1a\xc8\xe3\xd9\xcd\x05\xd3\xb0\x1d\x81\x8d\xba\xae\x6b\x12\xeb\xf3\x64\x5f\xab\x4f\x37\x60\x8d\x27\x75\x59\xf0\x9a\x03\x0c\x11\x05\x4f\x64\xae\x02\xab\x6f\xea\x31\xa0\x62\x6c\x5f\x43\x1c\xbe\x26\x35\x39\xee\x81\x38\xcd\x0c\xae\xa0\xb2\x2e\x2b\x91\xa3\xae\x97\x1a\x90\x62\xe3\xde\x31\xf6\x0d\x82\x61\xec\x73\x84\xb4\x4b\x0b\xe0\xa4\xd5\x27\xa3\x42\x59\x58\x90\xb3\xfc\x8b\x05\x30\xd9\x12\x63\x0f\x42\xa3\x84\x5f\x0f\xcd\x18\xb9\x50\x17\x22\x5c\x56\x4d\xd0\x7a\x5b\x42\xaf\x54\xfa\x74\xd2\xb8\x29\xca\x92\xf6\x26\xb9\x6a\xa1\x2c\x7b\xaa\xa3\x47\xc5\xfe\xee\x41\x1e\x77\x9c\xb3\xbd\xef\xd1\x36\x81\x49\x70\x41\x56\xb2\x48\xc2\x8e\x81\x50\xa0\x35\xab\x64\x13\x92\xb4\x6c\x48\x25\x34\x1f\x83\xf1\x26\x1f\x63\xcb\xda\xaf\x67\x2b\xea\xf5\x68\x2c\x94\xab\xb3\x00\x81\xf0\xb6\x7f\x5f\x0c\xd8\xb4\xf4\xa5\x9b\x84\x1a\xa2\xce\x08\x74\xb2\x18\xd7\x61\xdc\x7e\x2f\x6a\x46\xac\xc9\xd7\xc8\xb1\xc8\x03\x9d\x1d\x8d\xe4\x81\x52\x12\x5f\xf3\x7b\x1e\x8f\x4b\x55\x06\xbd\xe2\xc4\x1d\x26\xb6\x5b\x64\x2f\x42\xe8\x3c\xf8\x2c\xfa\xb6\x90\x6a\x4c\x8f\x44\x6e\x49\x9a\xcb\x80\xb1\xae\x38\xd3\xd2\x56\x22\x97\x11\x07\xef\x52\x77\x1a\xce\x28\x7e\xb9\x51\xc6\x0e\xa7\x4f\x5c\xea\x21\x80\x03\xf5\x06\x07\x3d\x87\xfd\xb0\xac\x0b\x3a\xb9\x51\x04\x7f\x41\xe1\xe9\x0c\x45\x8d\x70\x32\x2f\x8a\x53\x84\x0c\x37\x0c\x28\xf8\x58\x5b\x24\xc8\x98\x42\x41\x33\x10\x8f\xaf\x5e\x4a\x0c\x00\x6d\x69\x7c\xd4\x05\x24\x3d\x0b\xe5\x2f\x6e\xd4\xb6\xd2\x4b\x08\x85\xde\x6b\x97\x23\xcc\x8a\xc4\xd7\x89\xa3\xf5\x6b\xbc\x93\xf0\x14\x4b\x58\xa8\x51\x8a\x81\x44\xf4\x5f\xad\x82\x0e\x7e\x88\xea\xd3\xa8\x32\xe7\xa6\xaf\x09\xe0\x60\x6b\xd5\x6b\xfd\x2d\x49\x8a\xfc\x2b\x59\xea\x95\xde\x39\x39\x50\xd3\x0c\xde\x42\x0e\xbd\xa9\xbc\xd9\xa6\x13\x93\x70\xe3\x18\xcf\xa5\x0d\x6c\xf4\x20\x21\x24\x30\x29\x21\xc8\x08\x5c\x27\xf8\x8f\xb7\xe9\x4c\x95\xfb\xb4\xff\x13\xbe\xc9\x8c\x4f\x5e\x10\x42\xba\xb2\x9d\xd4\xc3\xf1\x30\x3c\x32\xd7\x60\x9e\xbf\xd3\x43\x83\x66\xbf\x64\x30\x70\xa1\xe2\xce\x5e\x7d\x29\xce\x22\xb8\x08\x18\x3e\x23\x6f\xf9\x03\x4f\x2b\xb5\x96\x87\xe0\x8c\xbb\xc4\x06\x07\x47\xa1\x5b\xcd\xf8\x1f\x9a\x63\xdc\x40\x41\x2b\xda\xdb\x3d\x02\x5b\xb3\x3c\xbb\x36\x4c\x73\x5c\xc1\x6a\x99\x88\x28\xfb\xc8\xf1\x00\x9c\x73\xda\xa2\x15\x05\xd8\x42\xf4\x91\xa3\x75\x8b\x7d\x12\xd3\x94\x56\xae\xd0\xb9\xca\x8f\xec\xd7\x2c\x80\x99\xc9\xa0\x5d\x6a\xb5\xc2\x50\xfb\x0c\x66\x9e\x12\x69\x50\x83\x69\x05\xe3\xb3\x0d\x47\xec\xc3\x47\xf8\x84\x19\x75\xe9\xd1\xdf\x3a\x02\x41\x5c\x27\x8a\xbe\x2b\x47\x98\x00\x4d\x07\x21\xf8\xd6\xd2\x20\x4a\xab\x22\x1b\x61\xff\x1c\x71\xa3\x35\x46\x7f\xbb\x85\x66\x55\x3f\xbf\x6e\x01\x55\xd4\x96\x50\x83\x6b\x7e\x9c\x97\xc2\x97\x47\x23\xc8\xf3\xcd\xd2\x6b\xda\xf0\x17\xf0\x89\x8b\xe3\xb3\xc6\x83\x0e\x50\x8b\xd8\x7d\xd0\x33\x55\x16\x19\x32\xc7\xf6\xbb\x79\x4d\xfc\x42\xac\x91\x62\xbb\xf0\x62\x0c\xdb\x62\xbb\xad\x0e\x6d\x5d\x58\xa0\xf4\xc8\x7e\x69\x8a\xe9\xb0\x2c\x4c\x67\x7a\xdf\xd1\xa6\xd3\xe2\xa9\x0f\x8d\x88\xb7\xa1\xf1\x88\x2a\xfa\x52\xd0\x37\xfc\x50\xe9\x12\xba\x90\xf4\x72\x55\x74\x88\x26\xf4\x23\xde\xa7\xf4\x15\x10\x84\x20\xf7\xfd\x52\x15\x62\x2b\x18\x89\xa4\x6e\xdd\xf3\xc9\x1b\xff\x13\xbe\xeb\x1e\x33\xf2\x4a\xf8\xde\x7b\xd0\xd2\xfa\xd1\x73\x5a\x75\x33\x45\xa0\x78\xe3\x38\x30\x06\x9a\xcf\xca\xa9\xd9\xa2\xe7\x95\xaf\xca\x8b\x96\xa0\xb4\xc9\x3b\x88\x00\xcb\x15\x9a\x37\x71\x2a\x0e\x74\x9c\xbe\x1b\x05\x61\x3f\xda\x7c\x77\xbb\xda\xeb\x28\x7d\xa7\xe3\x6c\x45\xab\x33\xf4\x9f\x36\x44\x6d\x5e\x54\xd6\xcd\xf5\x58\xa2\xb5\x4d\xd8\x82\x8f\x84\x7f\x3c\x53\xbe\x51\xa9\x47\xb1\xb0\x6f\x0f\x38\xb4\x4d\x9f\xb2\x67\x9b\x73\x3f\x4e\x55\x78\xf2\x54\x30\x47\x26\x75\xa1\xa9\xe9\xf9\x24\xaa\x18\xf5\xf9\x41\xe3\xfa\x18\x42\xfe\x4e\xe0\x0a\xd2\x1c\x87\x5e\xf9\x43\x29\xe8\x20\x77\x6e\x3e\x67\xe0\xc4\x33\x5f\xf2\xa7\xe6\xcf\x37\x52\x22\xb3\x37\x86\x40\x16\x5b\xa0\xbf\x39\xdd\xf7\x29\x17\x0b\xeb\x18\xb9\xdf\x9b\x63\x34\x53\xa8\xc2\xa3\xe4\x06\xe2\x18\xb5\x16\xe3\x77\x51\xe3\x97\x65\x2b\x2c\x60\x35\xd5\x50\xac\xe1\x40\x3c\x68\x5d\x5b\x56\xeb\xbf\x34\x0c\x20\x06\xde\xa8\x06\x97\x21\x14\x51\xb6\x86\x89\x4e\xac\x3c\x08\xf0\x97\x14\xf4\x07\xe3\xd4\x29\xe8\xe8\x5f\x41\xbf\xe6\xee\xbc\x2d\xa6\x1f\x1c\x65\xd5\xf4\x06\xae\x76\xfd\xdc\x07\x0e\xef\x79\x3b\x35\x96\x62\x68\x80\xaa\x0e\x97\xb6\xef\x16\xaa\x62\x71\xf0\xf1\x97\x36\x26\xc2\x15\xfb\xb9\x01\x98\x91\xbf\x91\x10\x77\xf2\xb2\xfc\xc8\xec\x5d\x09\x25\x75\xde\x49\xe0\xd5\xa0\x1d\x33\xe4\x6d\xd4\xc7\x68\x5e\x6f\x61\xf4\x3b\xb6\xa9\x69\xa2\xc6\x13\x1d\x22\xe6\xa8\x5c\x2f\x75\x5b\x78\x80\x68\xee\x3a\x41\xf1\xe9\x1a\x4f\xbc\x3b\x91\xc8\xbf\xa9\x04\x35\xe5\xac\xea\x2f\x9a\x52\x60\x8f\xc6\x32\xd5\x5d\xe7\xdf\xb9\x8e\xa4\x95\x7a\x1f\x26\x53\xa3\x81\x4c\x98\x21\xf7\x93\xf8\x59\xa7\x63\x73\xd4\x55\xd8\xb8\xf6\x87\x2a\xc8\xfb\xd9\xd1\x62\xc2\x11\x78\x76\x11\x46\x82\xa4\x3b\xaa\x79\x4c\xe4\xb8\x4e\x49\x8c\xcc\x91\x7a\x4b\x3c\x27\xee\xe8\x0e\x4a\x13\x0d\xad\xbb\xfd\x9e\xaf\x0e\xcd\x50\x51\x09\x89\x4b\xcc\xda\xa0\x5f\x96\x1c\x86\xff\x9a\x06\x79\xff\x2b\xd3\xe0\xdf\xf6\xc9\xa0\x45\x56\xa8\x0b\xb8\x81\x9d\xa3\xac\x0c\x7e\x3d\x0d\x9e\x73\xf4\xe1\x1d\xf3\xc3\x42\x1c\x75\x7e\x38\xe4\xbd\x2c\xc4\x58\xe7\xf4\x13\xda\x59\x93\x8b\x8e\xb0\x6c\xad\x09\xa7\x25\x84\xb4\x25\xe0\xc4\x44\xd4\xe7\x4e\x36\x37\x1c\xda\x7e\x24\xbb\x9c\xd0\x62\xd1\x3c\xcd\xcc\x55\x7b\x16\xcb\x84\x9e\x85\x07\xc8\x3d\x81\x62\xb5\x93\x47\x2f\xa3\xdf\xff\xe2\x90\x59\x50\xc6\x36\x75\xea\x53\xea\x01\x60\x12\x99\xea\xad\x4d\x84\x4c\xba\x6f\x9b\xb8\x9c\x21\x67\x80\xbf\x41\xd5\x88\x0f\xc5\xb6\xd2\x18\xf7\x86\x15\xf2\xd3\xbe\x28\xaf\xf4\xf3\x19\xed\x35\x52\x26\x3c\x17\xb6\xea\xb3\x82\x1a\xe6\xd7\x0f\xe7\x5f\x42\x50\x10\x36\x69\x14\x2a\x4e\x52\xe5\x81\x8d\xd9\x58\x7e\xec\x71\xa2\xce\x98\x91\xd5\x48\x36\xbb\xea\x5d\x5e\x20\x27\x6b\x9b\xb2\xc0\x37\x58\xe4\x5d\x6b\xb9\x72\x7a\xca\x58\x73\x97\x15\x0b\x1f\x9a\x23\x29\xb9\xdf\xe8\x60\xad\x11\x69\xcf\x62\xb7\xb8\xa0\x89\x68\xe1\xe5\xe2\x14\x8c\x1e\x80\xf3\xfa\x9d\x64\x30\xd7\x98\x12\x09\x36\x59\x1c\xb5\x87\x34\x17\x2e\x66\x57\x6a\x9d\xf4\x3e\xc7\x4c\x78\x14\x04\x72\xa2\xd9\xd9\xd1\xa2\x45\xfb\xee\xb7\x73\x55\x5c\xdd\x5d\x43\x39\x81\x1b\xb7\xbf\x52\x31\x4b\x49\x33\xdb\xa0\x69\x4e\x78\x7b\xee\x12\x83\x53\x0f\x5c\x23\x5d\xe1\xc9\xd2\xa6\x9c\xc6\x5d\x66\x0a\x06\xc2\x91\x62\x66\xe2\x1e\xf2\x6d\x53\xe8\x45\x5a\x64\x99\x7a\xb9\x0f\xf7\xa8\x72\x1a\xe8\x2e\xa5\x91\xda\x6a\x61\x17\xec\x4b\x7f\x0a\x3e\x88\x9c\x28\x9c\xc7\x14\x22\x15\xfc\xca\xa5\xc1\xb4\xf3\xf5\x73\x95\xb0\xba\x48\x91\xbb\x14\x60\x5c\xbc\x82\x7c\x4c\x1b\x98\xfb\x6e\x4d\xc5\x9e\x61\x4a\xe1\x0d\xfd\x1a\xac\x1e\xb8\x23\x57\x08\x9c\xdb\xa8\x84\x77\xce\x51\x68\xbe\xf6\x97\xe0\xe9\x3e\xa6\xb7\xc0\x6b\xc8\x51\x81\x8c\x2c\xdf\xe4\x40\xfa\x4a\xf5\xb7\x15\xc9\xa6\xbb\x87\xb7\x19\xeb\xd8\x88\xe9\x69\x41\x3d\xdb\x13\xe7\x90\xa4\x1e\x85\x8b\x4d\x92\x1b\x81\xc6\xba\x80\xb1\x2d\xba\x3b\x7d\x22\xa6\x2a\x34\x48\x3a\xf8\xd5\x9c\xfe\x8a\x6e\x9c\x19\x9e\x36\x60\x96\x14\x55\x39\x7c\x9d\x8d\x88\x49\xbc\x8e\x49\xaf\x4d\x35\xf3\x28\x8e\xc1\xb1\x7c\x2c\x7b\x57\xaf\x4a\xab\x44\xdf\xd0\x0b\x96\x03\x14\x12\x14\xc6\x8e\xa6\x60\x8a\x0c\x7f\x3e\xbc\xb9\x67\x24\x86\xd0\x72\xdd\x2f\x8b\x82\xed\x9a\xcc\xcd\x44\x5b\x4e\x44\x0c\x0e\xa9\xe0\x8f\x41\x53\xe9\x24\xf7\x0b\x97\xf5\xca\x8f\x7c\x34\x78\x3f\x91\xad\x24\x17\x8c\x4d\x59\xb7\x6b\x90\xe4\xea\x06\xa6\x34\x13\x10\xb0\x69\x95\x88\x61\x54\x72\x97\xaa\x11\x89\x7f\xb9\xa2\x3f\xa2\x01\xab\x71\xdb\x25\xd9\x5f\xd1\x8d\xa4\x52\xe9\x3d\x68\x44\x13\xb8\xb6\xea\x5e\xdc\xa3\x31\x07\xaf\x1d\xe5\x1a\x47\xc2\x71\xc9\x28\x60\xc0\x2b\x05\x27\xf2\x91\xc0\x97\x47\x3b\x2c\x0f\xb4\xa1\xc1\xcc\x9d\x97\x7a\xf7\x8b\xd1\x87\x9e\x4d\x12\xcc\x9f\x62\xae\x1c\x68\xdb\xe2\xca\x58\xc4\xf1\xf9\x2b\xd3\x0b\x77\xe9\xaa\x19\x37\xce\x02\xf0\x6f\x6f\x03\x3c\x91\x89\x60\x2c\x15\x7e\x72\x50\xe4\xe7\xa2\x76\x16\x91\x07\x1a\x6a\x8b\x1a\x9c\x12\x86\x95\xa1\xbd\xd1\x92\x69\x85\xd5\xa0\xdc\x69\xeb\x26\x86\x0d\xa4\x92\x09\x83\x3a\x66\x8b\x0a\x46\x96\x03\xde\xe8\x18\xf3\x97\x3e\x11\x58\x38\x91\x32\x9a\x1e\xf0\x7a\x3c\xb5\x77\xb1\x49\xa3\x54\xe0\xdc\x6c\xf5\x89\x78\x97\xd1\x16\x4d\xa9\xae\xdd\x89\x57\x63\x24\xd7\x3a\x5d\xf2\xd4\x16\x71\x50\xa3\x5f\xcf\x26\x0a\xb3\xe1\x9b\x02\x24\x54\xd0\xe5\xe5\xfb\xef\x19\x5e\x28\xa6\xca\x1c\xfc\x92\x10\xf2\x4c\xad\x50\x61\x57\x80\xc7\xef\xbf\xb3\x48\x24\xc6\xac\xb9\xc4\x2c\x2d\xae\x03\xd2\xd8\x2e\xba\x70\x57\xf3\x8e\x1d\x71\xaf\xe8\xe0\x13\x14\x49\xb5\xdf\x74\x0d\x24\xbb\x27\xae\x76\x5e\xa2\x70\xe4\x83\x7d\xde\x5a\xbf\x41\x64\x03\x79\x44\x5f\x6a\xa6\x10\x5d\x0c\xf8\xf1\x15\xee\xd1\x6d\x48\xa5\x63\x36\xc8\x40\x44\x40\xca\xf0\x63\x1b\xb8\x24\x51\x8b\x2b\x7a\x0d\xde\x36\x98\x8e\x76\x56\xd9\xa8\xf0\xf2\x26\x33\xce\x87\x44\x6c\xc5\xa5\x9e\x1a\x6c\xaf\xf4\x63\x60\x6e\x30\x94\xf4\x58\xaa\x06\x60\xe9\x9e\xa3\xca\x19\x81\xa5\xda\x03\xca\xa6\xa3\x96\x94\x05\xf9\xbc\xb5\x8e\x03\xeb\x5f\x29\x30\x67\x78\xf1\x48\x5d\x38\x0e\x7b\x2b\xec\x58\xd8\x44\x24\x5e\x5d\x8f\xa3\x25\x76\x2e\x46\xd3\x5e\xa2\xc9\xd8\xc7\xf0\x02\xe2\xcd\x73\xb1\x0c\x5a\x12\x01\x3e\x48\x27\x22\x42\xef\x54\x68\xc2\x6c\x8b\xb8\x01\xc7\xce\x31\x73\x75\x13\x62\xbf\x6b\x78\xda\xa6\xa9\x67\x4d\x6e\xdc\x4f\xca\xcc\xa9\x85\xda\x3a\xf4\x09\xde\xa0\xc9\x45\x93\xcf\xd9\xa0\x88\x09\x4a\x48\xa7\x78\xf7\xa6\xf4\x82\x7f\xc7\x42\x1d\xd8\xfc\x82\x77\x66\x3b\xef\x19\x73\xc5\x5c\xf7\x9e\xba\xea\x57\xfb\xb5\xce\x76\x12\xfc\xa5\xa9\x02\xe6\xb0\x9e\xf2\x8d\x27\xa7\x7b\x1f\x63\xe6\xac\xdf\xb3\x25\x82\x51\xd5\xb7\x6b\xef\x53\xfa\x69\x52\xa0\xf6\xd5\x8a\x72\xea\x38\x64\x1b\x63\x24\x6c\x18\xa7\xcb\xb8\xa7\x69\x88\xb1\xae\x89\x57\x94\xec\xf6\x36\x4b\x32\x71\x04\x53\x7f\x24\x55\x11\x48\x6c\x30\x76\x79\xa2\xee\xa1\xfe\xf6\x88\x37\x6e\x21\xea\x4d\x6c\xc8\x20\x15\x00\xcc\xdb\xf5\xfe\xd2\x51\xf4\x4c\x25\x3a\xb4\xb6\x69\xd0\x84\xa9\x7d\x6e\x7d\x82\xf9\xf7\x8c\x01\xd5\x19\x83\x4e\x65\xcf\xf6\x4c\xe5\x0f\x14\xea\x79\x48\x30\xb4\x98\xf0\xad\xe3\x4d\x02\x42\x9f\x39\x28\xbb\x0d\x71\x19\xb0\xa9\xe1\x26\xb6\x45\x96\xa9\xb7\x67\x81\x53\xdc\xc4\x46\xc8\xdb\xa6\x0a\x7a\xeb\x57\x6f\x6c\xe9\x36\x11\xc0\x41\xfd\x9b\x2c\x2a\x83\x97\x4e\x23\xd9\xd3\xfb\x1f\x81\x28\x19\xab\xb9\x83\x3c\x23\x1e\x1e\xed\x6d\x38\xa6\x6c\x61\x88\x11\xf0\x18\x2b\x11\xb7\x3c\x8a\x96\x67\xd7\x35\x2b\x76\x11\x84\x6e\x5f\x72\x39\x5f\xc6\xe0\xc9\x2f\x52\xa8\xb5\x84\xe0\x3c\xd1\xc4\x8a\x52\x59\x9e\x3b\x4d\x40\x70\xd1\x1c\x71\x65\x5a\x81\x12\x13\x89\xa2\x7e\x4a\x7a\xc4\xb3\x41\x44\x79\x57\x37\x1e\x55\x2e\xe2\xca\x62\x79\x23\x66\xc5\x5d\xc5\xdc\x50\xc2\x44\x01\x20\xcf\x16\xe9\xe8\xf6\x7a\xef\x2d\x80\x38\x07\x7c\xb0\x0d\x16\x5a\x06\xaf\x63\x3b\x94\xe9\xd9\xb7\x55\x96\x80\x04\xc8\x12\x4a\xc9\x79\x6b\x23\xab\xcc\x80\xee\xd0\x08\x71\xa9\x0f\x8e\x9d\xa0\xee\xdc\xb9\x5c\x63\x48\xdb\x92\xaa\x58\xe6\xd8\x2c\x9f\xe4\x7b\xb0\x8d\xe0\xba\x80\x0e\x77\x61\x5c\x47\x7e\xc0\x1d\x9f\xbf\xa7\xd2\x7d\x89\x9f\x3f\x3f\x9a\x1a\x6e\xde\xa4\xb4\x12\xc1\x0d\x11\xd7\x4d\x79\x04\xaf\x4e\xf4\x4d\x3d\x8a\x6a\xa7\x8f\x58\x39\xf3\x98\x30\xff\x3c\x70\xd8\x1a\x0b\xc7\x28\xfe\xa3\x46\x3e\x50\x64\x70\x98\x3a\xaf\xbb\xab\x95\x3a\x6c\x22\xc6\x74\x97\xe8\xf8\xa3\x6f\xd9\x9f\x21\xce\x39\x6a\x74\x90\xb7\xb5\x47\xe0\x08\xcd\x3c\x4e\x09\x60\x2f\xfb\x21\xae\x65\x48\x60\xad\xca\x8e\xe8\xba\xe6\xab\x67\x7a\x72\x8d\x55\xfc\x20\x9a\xe5\x70\xcf\x2c\xe8\xda\x6f\x5f\xba\x85\x32\x8e\x9f\x2c\xd1\x7d\x5e\xa1\xf1\xdc\x4b\xda\x5b\xf1\x44\x72\xe9\xe6\x72\xd6\x50\xc5\x4d\x85\x82\x5d\x3e\xbf\x83\x49\x39\x9b\xcb\x14\xbe\x8f\x12\x85\xdb\xa3\x21\x05\x43\x2b\x03\xeb\xff\x51\xda\xb5\x86\x5c\xbd\xeb\xdd\x53\x05\xe5\x6f\xc1\x56\x4c\x32\x45\x13\x27\xaa\x31\x9e\x8d\x8c\xa2\x6b\x2d\x9c\x4e\x21\xd3\xe0\x0d\x52\x30\xd9\xbb\xac\xa9\x6d\x40\x8b\xb7\x78\x3c\x2f\xee\x6a\xc1\x80\x59\xa2\xe5\x98\x18\x02\x59\x8a\x6e\xb1\xc8\x7e\x66\x4b\x44\x3b\xf9\x58\x4b\x6a\x7d\x30\xee\xc2\xb8\x97\x4b\x3f\xc1\xb5\xed\xba\x8e\xf7\x42\x43\xc7\x70\x43\x3d\xa0\xa7\xc1\xac\x00\x79\xc6\x4a\xfa\xf3\xab\x3c\x79\xfe\x5e\x89\x93\x07\x7d\x1c\x94\xba\xf2\x3a\x80\x8d\xab\xba\xb4\x95\x4f\x8a\x43\xdc\x2d\x35\xa6\xf8\xcc\x4a\x1a\x5d\xf6\x87\xe5\x55\x8f\x5c\x10\xfb\x3c\xa4\x9b\x78\x57\x55\xdf\xcb\xdb\xec\x53\x19\xed\x79\x58\xf8\x82\x49\x0b\x64\xad\x6b\xe4\x02\xce\x4c\xa0\x09\x21\x9c\x0d\xa5\x79\xec\xa3\xa2\x6f\x8b\x07\x7a\xe9\x90\x36\x3d\x8e\x19\xd9\xc5\xf7\xb1\x0a\x50\x1c\x40\x51\x59\x82\xe3\x36\xab\x55\xd7\xf6\xb5\x46\xc4\xd2\xf6\x92\x8b\x4a\x42\xc2\x69\x8e\xab\xc4\x70\x4b\xf3\xcb\x8c\xda\x3b\x16\x3c\x8e\xab\xcd\x4c\x09\xe4\x26\xeb\xe8\x93\x22\xe5\x8c\x2e\xc6\x06\x2d\xf0\x94\x2e\xa2\x77\x70\xe0\x2e\x78\x66\xdd\x94\x61\xa8\xbc\x78\x64\x46\x99\xb8\x9e\xf6\x00\x5f\x1a\xa1\xd5\x6c\x93\x3e\xc9\x82\x59\x80\xe0\x7e\x7b\xd1\x3d\x58\xa4\x6e\xa0\x86\x03\x80\x2e\x51\xfd\x69\x60\xf7\x40\xa0\x5b\x73\x83\xb6\xfe\x6c\x03\x08\xd9\x08\x38\x50\x85\xb4\x05\x8c\x6f\x4a\xb4\xb8\xf6\x3b\x03\xea\x6b\xf2\x22\x67\xa9\x7c\xae\x3c\x1a\x11\x88\xa7\x32\xa3\x86\x02\x7e\xb0\x1a\x6f\xcd\x2f\xc6\x84\xce\x2f\x97\x14\x4e\xe8\xfe\x35\x4c\x02\xd4\xb0\xc0\x56\x3f\x04\x68\x96\x65\xff\x4c\x96\x36\x80\x6d\xe0\x31\xde\x14\xf7\x25\xb0\x1a\xc7\x2e\x10\x81\x59\x54\xb8\x0f\x0d\x44\x32\x07\xbd\x97\x28\xf3\xbb\xf8\xad\x60\xaf\xab\x88\xd5\x6f\x67\x1f\xaa\x5e\x6c\x35\xd2\xd4\x52\xf3\x1a\x48\xc7\x91\xcd\x25\x5e\x9b\xbd\x84\xc4\xe7\x7a\x71\x9a\x40\x78\x6b\x5c\x40\x76\xd7\xef\x3d\x3b\x0a\xfd\x5e\xea\xb5\x76\x0d\x7a\xde\x28\xf9\xb8\xd4\xab\x6c\xc4\xa0\xbb\x78\xa9\xe8\xaa\x62\x73\x01\xd9\xbf\x82\xaf\x1a\x90\x3e\xa0\xac\x1f\x75\xc7\xef\x12\x14\x30\x04\x69\x60\x75\xac\x37\x36\x40\x5b\x44\xd2\xf5\x62\xb8\x47\x1b\x78\x2f\x1a\x54\xcb\x64\xdf\x31\xcb\x09\xa2\x5f\x3c\xcf\x12\xa3\xed\xbd\xca\x79\x8b\xfa\xf8\x4d\xb2\x03\xba\x2a\x8e\x0b\x21\x6c\x38\x1f\x8d\x20\xec\xa3\xc6\x64\xbc\xf7\x5e\xa3\x78\x3d\xd6\x7b\x7e\xe2\x8b\xb8\x85\xa1\x61\x5f\x87\x0f\xc6\x98\xf9\x13\x2e\xbf\x1a\x52\xae\xfe\x62\x26\xc6\x6e\x60\xf8\xa0\xa3\xb8\x99\x4d\xc0\x80\xe9\x5c\xd8\xdd\x1b\xe5\x43\xf7\x5b\xc8\x88\xd2\x4f\x94\xa5\xe9\x1b\x37\x49\x09\x0a\xdf\xc5\x80\x90\xa3\xf6\x55\xda\xf1\x2f\x89\x62\x3d\xd2\x46\x68\xc2\x4f\x0f\xe7\xb1\xf9\x65\xc2\x4a\x33\x76\x53\x5b\x58\x72\x20\xec\x86\x4e\xad\xfa\xc8\x8a\x79\x35\x7f\x88\x30\x94\x27\xad\x43\xf0\xb8\xec\xf8\x9c\x5b\x64\xc4\xb2\xba\x5b\xbd\x7f\xc9\x48\x44\x34\xe2\x50\xbc\xf9\x98\xc9\xfe\xa4\x4c\x31\x32\x6c\x56\x86\x81\xb8\x9e\x22\xf5\x6e\xf2\x82\x3e\x3c\x15\xfb\x91\x33\xe9\xe4\x9c\xae\x4b\x1f\x8b\x29\x27\xca\x0c\x1a\x43\x01\x11\x85\x1d\xaa\x4a\xa4\x40\xe4\xaa\xa1\xb6\xc6\x56\x4c\x0c\x2f\x91\x00\x46\xc4\xce\x7e\xc0\xa0\x35\x05\xb7\x0d\xf3\x03\xf1\x64\x9d\x77\xaf\xb5\xab\xd5\x95\x98\xb2\x1b\x86\xd5\x85\xe4\xdd\x8f\x47\xcd\x08\xcb\xe4\x12\x56\x21\x70\x69\xc7\x6d\x23\x6b\xab\xc1\x5a\x7b\x18\x0b\x95\xb9\xa1\x43\x1e\x88\x8f\x08\xec\xde\xcb\xa9\x00\x92\xfc\x20\x4b\xb6\xb9\x67\xa3\xbd\x2f\xc6\xfa\xfb\xd7\x19\x8c\x25\x1e\x57\xdb\x01\x51\x47\x9a\x30\x36\x1a\x24\x9a\x54\xca\x45\x20\x68\xd0\xa4\x28\xb7\x5d\xb0\x2b\xb5\x90\x2e\xbd\x22\x5e\x7f\x54\xbc\xdd\xbf\x0d\x51\xfc\xde\x02\x6b\xf4\x3a\x8d\x7c\xd4\x36\x7e\x8e\x91\x04\x14\x74\x38\x04\xe3\x33\xaf\x2d\xc6\x5e\x4f\xea\x05\xef\x24\xf1\xa6\x0f\x54\x8e\x6f\x5f\x8d\x87\x42\x1d\xfb\x11\x70\x17\x22\x5f\x45\x7f\x9e\x2c\x26\xcd\x73\xf9\x39\x5d\x8e\x91\x04\xf6\x3a\x6a\xec\xc9\x2c\xe4\xf6\xe1\x42\xe6\x94\x3b\x71\xc6\xb1\x46\xac\xed\x31\x75\x20\x12\x20\x0c\x36\xe3\x9d\x76\x30\x5b\x89\xbe\x26\x9e\x63\x8f\x43\x12\xde\x9c\xc2\xc3\x52\x43\x85\x1d\xad\xb7\xfd\x5c\x48\xf8\x15\x0c\xd3\xf9\x3d\xc7\x8a\x21\x78\xfb\x2c\x83\x14\xb0\xb6\x16\x93\xaf\x9a\x16\x00\x09\x25\x29\xcd\x60\x53\x98\x6e\x53\xb2\x47\x1b\xc7\x46\x37\x1c\xe1\x12\x92\x76\x7d\xfd\x27\xb2\xf3\xaf\x4b\xaa\x38\xa4\x90\xee\xce\x93\x39\xaf\xbf\x95\x73\x50\x26\x45\xec\xf6\xa1\x9e\xf8\xb0\x3f\xde\x3b\xbb\x43\x2a\x84\x2c\x04\xc0\x36\xa9\x93\xf1\x7f\x27\x35\x13\x14\xbe\x06\xfc\x06\x6f\x3e\x9b\xef\x8f\x36\x2a\x87\x53\xe3\x8e\xc0\xd3\x2d\x0b\xc1\xff\x53\x89\x65\x3b\xa7\x56\x4f\xde\x63\xca\x93\x97\x11\xff\x8f\x2c\x95\x77\xac\xf8\x0c\x26\xe2\x0b\x1a\x06\xca\xb3\x9d\x5b\x3a\x3e\x24\x3a\x3f\x0c\xc4\x08\x52\x85\x25\xe5\xda\xc8\x81\x4a\xeb\x5e\xa0\x80\xdc\x40\xe8\x3b\xd8\x72\xb3\x69\xa9\xc9\xbd\x1c\x68\xb1\x8e\xa1\xf6\xa3\x5c\xef\x25\xf7\xe2\xf5\x3c\x29\xa7\xee\x54\x64\x85\x0e\xe4\xce\xd3\x78\x69\xae\x09\x79\x71\x35\x43\xee\xe3\x10\x33\xe6\x8e\x28\x35\xf4\xae\xca\xcd\x9a\x45\x6a\x35\x4b\xe9\xb1\xa2\x66\xf7\x7b\x95\xe7\xbe\x48\x7c\xb4\xbf\x73\x84\x5f\xae\x45\x90\x35\x76\x52\xb8\x32\x3c\xc1\x49\x62\x48\xda\xa8\x84\x18\xc0\xf9\xeb\x1a\x75\xdc\xf8\x0b\x0c\x44\xb6\x8b\xfc\xba\x4a\x53\xcb\xb5\xff\x20\xfa\x55\x45\xca\x38\x5c\x90\x3c\xb2\x9c\xe2\xc5\x41\x6e\x50\xa8\x3f\xf8\x03\xb0\x12\x47\xe1\x8d\xd6\x73\xc1\x70\xa4\x35\xdf\x31\xef\x09\x63\x4a\x39\x69\x66\x1f\x02\xd2\x5e\x59\x90\x8f\x03\x56\x4d\x7e\x19\x7f\x06\xc5\xe6\x48\x61\x78\x42\xe5\x85\x2c\x18\x6a\x68\x2d\xb5\x46\xa2\x3b\x0a\x2d\xdf\x33\x98\xb5\x90\x4c\xf8\xfb\x92\xc4\x85\xc7\x59\x0f\xbd\xb4\xc3\x80\x0f\x69\x91\x37\xe1\xf1\x9f\x5c\x57\x17\x83\xf8\x4b\x10\x6c\x51\xef\xa7\x26\xce\x6f\x7a\x70\x2a\x7c\xf0\x3d\x19\xa1\xa6\x7f\x7b\x60\xd4\xbb\x79\x86\x64\x51\x1f\x05\x16\xff\x31\x99\x56\x8f\xc6\x2e\x6a\x01\xbe\x38\xd1\x84\xa2\xd6\xe0\x73\x61\xdb\x63\xd4\x0e\x4e\xb5\xa1\xd6\x17\x55\x7f\xf7\x31\x96\x24\xb3\x9d\x76\x97\x62\xd1\x0e\x0e\x27\x53\x45\x6a\x83\xfd\xa4\x39\x71\x87\x4f\x5e\x12\xe7\x20\x10\x2c\x32\xb7\xce\xee\x6a\x0d\xf2\x2b\xdb\x57\x0f\xe1\x60\xbf\x9e\x90\x56\xb4\xed\x79\x70\xad\x7a\x7e\x57\xe7\x4e\x39\xa4\x9d\xb1\x18\x30\xe9\x84\xdf\xfd\xf8\x2a\x45\x37\x61\xb4\x97\x43\x9b\x88\x3e\x2d\x84\x67\x2c\x04\xc5\x27\xbe\x15\x95\x9d\x25\x59\xb2\xb3\x96\x03\x48\x8c\x7b\xc8\xe4\xd6\x81\xd3\x56\x75\xff\xd2\xf5\xc5\x2b\x15\x1c\x25\x9f\x8f\xca\x03\xfb\x42\x12\xca\xc6\x2c\x01\xd8\x51\x18\xc7\x76\x12\xc5\xfb\xee\x19\x92\x25\xf1\xf0\x28\xf6\xf2\x62\x85\x58\xd4\xd5\xc9\x3d\x86\x50\x9b\xc5\x49\xee\x8a\xdc\x7e\x0c\x73\x1b\xd8\x0b\xdb\x43\x7a\x1e\x99\x7a\x4d\x27\xf8\x0c\xf1\x13\x4c\xe1\xa4\xfd\x01\xef\xfc\xcd\x49\x48\x80\x9f\x3e\xdc\xda\xfb\x3f\x28\x57\x8e\x5a\x5c\x68\xeb\x71\x0c\x9c\xac\xa4\x6b\x0c\x33\xa1\x19\xa3\x66\xe6\x72\x5b\x18\xdb\x31\x9d\x08\x18\x5a\xad\x4b\x6f\xb3\x69\xd4\x93\x7d\xa1\x80\x07\x0d\xbc\xbd\xc6\x36\x51\x59\xbe\xe7\x14\x79\xae\x51\x7a\x53\x2b\x07\xca\xe5\x28\x60\x6b\xb6\x20\x03\x04\x17\x41\x8e\x0b\x1a\x0d\x7f\xa2\xee\x86\x1f\xb7\xe5\x6f\x7a\x37\x0a\x7d\x44\xb7\x15\xe8\xee\x6d\x9d\x6b\x11\xb5\x72\x66\x72\x4e\x84\x11\xc6\x35\x75\x20\xbe\x90\x63\x42\x4a\x89\x6f\x23\x2e\xcb\x03\x2a\x78\x8f\x44\x64\x29\x9c\x92\x37\x54\xc4\x40\x1c\x46\x8c\x1a\xf8\x14\x12\x05\x4d\xce\x70\xbf\x86\x90\xba\xf2\x43\x9b\xe4\x6f\x61\x9b\xa0\xe3\x6e\x93\xe1\x49\xcb\xe7\x52\x59\x77\xd8\x9a\x91\x91\x8f\x53\x51\xfa\x28\x40\xf7\xcd\x49\x1e\x66\x9b\xa9\x53\xba\xdb\xca\x5d\x85\x8c\xa3\x49\x92\x44\x23\x93\xa2\x68\x49\xaa\xde\xa2\x1b\x07\xf7\x78\x5b\xa5\xb1\x54\x29\xdb\x6f\x49\x97\x62\x87\x10\x5a\xe2\xe9\x6e\xac\xa7\xca\x52\x23\xc6\x48\x46\x0c\x21\xc9\xfe\xfc\xeb\x6a\x60\x25\x4a\x80\xea\x4b\xb8\x7d\x71\xc6\x14\x57\xa8\x82\x95\x36\xf6\xfa\xbe\x6a\x9b\xfc\x6e\x21\x84\x5a\x0f\xf7\x13\x1b\xde\x82\x42\x9c\xe7\xa9\x11\x23\x7d\x24\xab\xc8\xf0\x2d\x74\x1c\x2f\x5c\x6d\x3b\x9b\xde\x87\x39\x2b\x05\x8e\xf9\x5e\x94\x99\x79\x5a\x22\xa0\xfb\xa3\x74\x6d\x39\xc1\xac\x99\x6b\x93\x96\x74\x1e\xfd\xcf\x99\x20\xa9\x6c\x91\x04\xac\xd0\x8f\xc5\x8f\xdf\x6c\x30\xa1\x28\x3c\xd6\x0d\xd8\xbe\x81\xf9\x79\x8c\x16\x15\x23\x10\x1d\xb6\x82\x6b\xe7\x13\xd0\x75\xae\x06\x6f\x7e\x38\x32\x87\xcf\x40\xae\xf3\x12\xc6\x61\xc2\xd6\x41\x0f\x90\xb8\xed\xc5\xb9\xe2\x41\xe1\x71\x87\x11\x50\x84\x76\x04\x17\x05\x5c\x3e\x75\x02\x53\x45\xd8\xd6\xf1\x12\x0a\xa4\x58\x9b\xc7\x7c\x02\x55\xbe\xee\x86\xb2\x02\xf9\x05\x4f\xbf\x43\xd2\x41\xb5\x5e\x6f\x3d\x85\x7f\x3e\x17\x73\x87\x82\xbd\x55\x93\xc7\x7c\xf3\x2b\x8e\x8c\x3a\xc5\x5d\x64\x4a\x4c\x8e\xe5\x35\x18\x43\x94\xdd\xbe\x82\xa4\x40\x6f\xaf\x77\xf6\xf6\xbb\x10\x63\x6e\x6a\x65\xad\xa7\x65\x3e\xc8\x65\xe7\x53\x8d\x7a\xc3\x05\x5b\x38\x52\x87\x98\xc1\x42\xc9\x39\x9c\xdc\xc4\x86\x3c\x10\xe8\x02\x0a\x60\x97\x01\xb5\xf1\x34\x4c\x98\x21\xcc\x94\x7e\xa3\x60\xb3\xd0\xd8\xad\x27\x53\x42\x33\xf4\x23\x53\xf7\xab\x3d\x58\xfc\x6a\x07\x8c\x9b\xc8\xaa\x0f\xe8\x89\x40\xc4\xa5\x86\xdb\x78\x6d\x57\x71\x16\x1e\x9a\x1f\x74\x15\x24\x97\x80\x30\x19\x05\x62\x5e\x1a\x0d\x4e\x62\xd8\x7c\x29\x32\xf2\x5d\xc9\xb6\x62\x63\x8b\x37\xdf\x84\x44\x95\x72\x5f\xa2\xca\x51\x8f\xa2\xff\x5d\xe2\x13\x66\xd2\x05\x19\x60\x4d\x3c\xa5\x0f\x89\x35\xcc\x64\x8f\xdc\xd8\x07\x17\x25\xe4\x8d\xc0\xb9\x8f\xdb\xd7\x15\x9f\x75\x68\x67\x1a\xb3\xfe\x8b\xc6\xc6\xa8\x8b\xe3\x7b\xe5\xc8\xce\xab\x85\x4c\xbc\x34\x07\x7f\x57\x0d\x66\xf6\x8f\xe7\x77\x02\x75\x55\x85\x44\xbd\xe6\x4d\xd6\x43\x4d\xac\x50\xe1\x7e\x39\x8d\xe0\x7b\xe3\x08\x00\x0c\x0d\xaa\x59\xc1\x56\xd0\x8c\x2c\x0b\x41\x04\x13\x85\x2f\x50\xfe\x73\x43\x34\x22\x45\xe3\xa7\x8f\xd6\x50\x3c\x62\x8e\x45\x3c\x02\xf7\xdb\x37\x51\x1f\xf1\x67\x78\x40\x28\xb8\x28\x19\xbf\xfb\x95\x96\xdc\xf5\xd0\x2c\x7f\x0b\x3a\xa1\x3c\x01\x33\xe8\x80\xda\x2e\xf3\x2f\x21\x4f\xca\xfa\xf7\xed\xe0\xc4\xbc\xf6\x26\x9e\x17\x3a\x5f\x18\xd6\xfd\x50\x2d\x13\xe7\xd2\x0e\x48\xd9\xda\x6a\x86\x2c\xbd\x47\x9b\x08\x8b\x06\xf5\xd6\xbe\x32\x83\xed\xe3\xcd\xa6\xb6\x03\xf1\x3c\x63\xf8\xed\xd1\x46\xb2\x61\x80\x46\xcc\x11\x3a\xf6\x28\x71\x95\x16\x07\xad\x41\xbe\x0e\xd9\x6d\x0d\x88\x40\x52\x12\x53\xab\xda\xd8\x3e\x20\x72\x52\x93\xb0\x17\x99\xae\xd2\xf8\x22\xba\x65\x93\xee\xa3\x68\x9d\x5a\xbe\xb2\xa6\x89\x6b\xe6\x26\x63\xc0\x28\xfe\xf6\x82\x49\xed\x98\x5e\xcc\xd8\x1d\x9d\x2f\x6c\x06\xb8\xc6\xc9\x39\x1d\x29\xa4\x69\xd2\xf4\xe2\xda\xf8\x84\x02\xb5\x5a\xb4\x49\x39\x8d\x48\xb5\x36\x1e\x31\x68\x2f\xad\x44\x0e\x28\x86\xad\x03\x28\x79\x20\x74\xad\x6f\x67\x93\xdf\xd0\xbf\x7e\x93\x40\x77\x19\x5a\x79\x57\x3c\xf2\x6b\x5a\xd2\x4a\xb3\xe1\xe5\x28\x8a\x04\xf9\x85\x8e\x48\xb0\x5e\xe0\xa4\x8f\xc8\xeb\x34\x11\xae\x8f\x41\x59\x43\x8a\xc9\x38\x30\x57\x1d\xb4\x7f\xfd\x8b\x1a\x0d\xcb\xb8\x47\xd2\xd9\xc6\x02\x89\x3d\xc3\x81\x9a\x51\x6a\x04\x9b\x43\xf6\x5e\x13\x09\x28\xc1\xec\xad\x57\xaa\xc6\xba\x5a\x16\x6e\x93\x07\x24\x1a\xb2\x71\x5d\x87\x95\xd5\x10\x1f\xe9\xa2\xa4\x2e\xc6\x80\x53\xf3\x71\xaa\x7b\x0c\xf8\x65\xfd\x8d\xa1\xd3\xed\x5b\x10\x4e\x37\x26\x4b\xa9\xe0\xba\x2b\x89\xed\x28\xde\xc7\x70\x32\xcb\x12\x31\x9a\xf9\x0c\xca\x36\x61\x48\x6d\xab\x38\xde\x1f\xd7\xe1\x55\xd8\x31\x52\x39\x12\xfa\xa8\x4f\x4d\x1e\x8f\x5a\x12\x47\x63\xb3\xaf\x0a\x16\x64\x6f\x9b\x8a\xbf\x6a\x6e\x37\xfe\xca\xc1\x3d\x29\x7a\xeb\xb6\x1c\x62\x5f\x8a\x0e\x1a\x55\x3f\x5c\xe3\xfe\xd5\x62\x84\x71\xfd\x34\xb2\xde\x2b\x1a\x72\x28\x4e\xa4\xe5\xbe\x47\xb7\xf8\x33\x85\x1c\x17\x6e\xf6\x74\xfe\x70\x68\x68\xe2\xe8\xbb\x2f\x31\x96\xec\xc1\xbf\xfa\xee\x62\x0e\x4e\x5f\x39\x38\x27\x54\x1b\x83\x2a\x9e\x24\x24\x7b\x25\x71\xe7\xc2\x91\xfd\xf6\xd7\x4b\xb6\x8a\xc6\x73\x0e\x2d\xe4\x39\x37\x10\x5e\x2b\xbc\x7b\x2b\x93\xc6\x40\x2f\x90\x6e\x56\x41\x1a\xa4\xc6\x4e\xb1\xa2\xd7\xfd\xb9\x44\x8f\xef\xa2\x87\xa7\x49\x31\x67\x3e\x72\x5e\x04\x92\x1b\x0b\x9a\x17\x57\xd4\xd7\x61\x74\x06\x21\x74\x08\xd5\x8c\xa6\x4e\xdc\x53\x64\x5e\x8f\x27\x11\x5a\xc0\xa4\x9b\x9d\x51\xac\x76\xb7\xcc\x70\x8c\xee\x2f\x07\x9b\x34\xbd\xad\x3a\x57\x1c\xd7\x62\xaa\x75\x10\x85\x8e\x3d\x3b\xcc\x1d\xdf\x12\xfc\xb7\x3c\x34\xb2\xab\x98\xc8\x29\xae\xc8\xdb\x57\x1f\xff\xed\x94\x5a\xf5\x09\x69\xd2\xfd\xad\x0f\x71\xe6\x00\x43\xcc\xe6\xb5\x39\xc3\x33\x45\xae\x81\xbd\x27\x35\x68\xb2\x93\x2b\xc7\x5b\x1c\x5b\xc7\xf5\xf8\x6c\xec\x1f\xbe\xdc\x3e\x47\xaa\x45\x34\xed\xd5\xf8\xa0\x6d\xa3\x4a\xdf\x94\x31\x12\x8d\x46\xaf\x81\x3c\x9c\x60\x50\x76\x45\x88\x5e\x7b\xa3\xb1\x70\xef\x11\xa2\xd8\x9b\x79\xc6\xfe\xc6\xfa\x54\xe4\x19\x58\x5f\x52\xb3\x4f\xa7\x93\xe3\xab\x20\xdc\xb3\xbf\x6b\x0f\xd5\x43\xaf\xf7\x2b\x4c\x34\x8f\xf7\x72\xae\x36\xef\x88\xea\x51\xfb\x05\xfa\x6c\xd7\x14\x77\xcb\x21\xb4\x04\xab\x33\x3c\x17\xa2\xca\x2a\xc9\xba\xec\x25\x0a\x70\x80\x27\x6e\x08\xa0\x71\x98\xc6\x98\xe5\x36\x51\x55\x4d\xaa\x09\xc8\x25\x62\xa8\x52\x70\x5f\x02\x82\x77\x90\x99\x11\x26\x24\x3e\x6f\x52\x2d\x8c\x82\x55\x04\x95\x1b\xa8\x10\x11\x94\xec\x9c\x4a\xd9\xff\x51\xf1\x1d\xfa\x83\xa7\xc6\x31\x09\x97\x0e\x12\x9d\xc3\xed\x5d\xa9\x6a\xf1\xbf\x64\x28\xfc\x2f\x9d\x3b\xc3\xc8\x4f\xfb\xb1\x97\x4c\x9a\xc5\xa1\x4d\x63\xd8\xeb\x9d\xcc\x5a\x7d\x2c\x33\x56\x72\xbd\xee\x9c\x34\xde\x31\x4e\x90\xf9\x08\xf8\x14\xba\x62\x0d\x18\xf4\x22\x7c\x73\xc0\x07\x09\xa0\x18\x8c\x10\xec\x2d\xb7\xe0\x7c\xc0\x25\x6b\x75\x29\xdf\xa2\x58\x3d\x06\x17\xcf\x1a\x0a\xee\x3a\xbd\x43\x0a\xe4\x8d\xf5\xd2\x28\x05\x23\x34\x24\x08\x1a\x9a\xec\x1e\xf5\x61\x46\x80\xd7\x82\x7b\x69\x9e\x7b\x41\x27\xed\x57\xcc\x17\xf2\xd6\x63\x0d\x24\xce\x65\x5d\x74\x0a\x03\x9b\xea\x4e\x89\x15\x76\x27\xa5\xf5\xcf\xb9\xe9\x7b\x80\xca\xc2\x9c\x0f\x19\x3e\x96\x2f\x7d\x26\x29\x66\xec\xa3\x5a\x88\xa4\x36\x63\x67\x70\x90\x35\xc2\x3c\xa0\x5b\xe4\xb0\xca\xeb\x2e\x5d\x36\xe4\x49\x1c\x6e\xe2\xf6\xff\xe4\xa1\xd0\xb4\x6d\x2c\x0b\x4b\x51\x17\x34\xcc\x1c\xc0\x0c\xf6\x9d\x32\x29\xde\x2f\xe8\x27\xd3\x9c\x8b\x34\x5c\xbc\x41\x49\x89\x9e\xdf\x51\xe2\x20\x41\x21\xc5\x75\x9d\xa8\xa4\x60\x71\x23\xc7\x18\xfd\x8a\x30\xeb\x4e\x25\x04\xab\xca\xfe\x50\x0d\x3c\xa4\x25\x5a\xc5\x28\x7f\x51\xca\xc0\x85\x6a\x23\xde\x2c\x07\x24\xce\x7e\x4a\xf4\xd6\x69\x81\xc1\x17\xea\x38\x66\x36\x7d\x09\x1e\xbd\xa2\xe7\xc4\xc2\x41\x0e\x21\x31\x63\xde\x18\x95\x9c\xac\x83\x05\x35\x67\xf6\x66\xf6\x05\xb1\xa2\x4e\x52\x33\x97\xb2\x48\x45\xbd\x89\xf1\xf4\xea\x61\x8f\x8a\x48\x61\xd6\x61\xea\x29\xdc\xcc\xef\x07\x1d\xde\x93\xc6\x3b\x5b\x03\xb6\x45\x17\x1e\xc0\x27\x92\x67\x1f\xd3\x84\x73\x77\x55\xb6\xbd\x60\x17\x0c\xc7\xa1\xb4\xc1\x34\x0c\x16\x75\xb3\xf7\x50\xbb\x39\xb7\x6b\xde\xd7\xf0\x1d\x2f\x7f\x67\x20\xec\x21\xd0\x34\xc8\x4f\x62\xf5\xa1\xb8\xa2\x5c\xb4\x48\x43\x7a\x4e\x22\x2d\x0b\x52\x4a\x02\xdf\x5c\xe1\xa3\x72\x60\xae\x1d\x72\xba\xd2\x2e\xb8\x30\xfb\x21\xac\x60\x07\xdc\x82\xdb\xcc\x11\xf6\x5b\x06\x1f\xe2\x06\xf5\x9e\x51\x84\x4a\x8a\xc7\xec\xba\xb5\xee\xfd\x6f\x54\x63\x4d\xfc\x82\xfc\xc6\xfa\xc7\x59\xc3\x20\x13\xf2\x9a\xcc\xe9\x57\xdc\x6b\x33\x0f\x77\x99\x16\x8e\x86\xe9\x19\x66\x7a\x9f\x6d\xf8\xa0\xbb\xa6\x0a\x48\xf3\x1a\x0b\x56\x2f\x1a\x36\x7b\x7e\x55\xc8\xd8\x25\x04\xa4\x9b\xad\xde\xd7\xdc\xda\x8e\x29\x65\x2d\xac\xca\xee\xea\xd6\xcb\x3a\x74\x2e\x4b\x23\x24\x82\x01\x7f\x44\xe5\xce\x32\x44\x1a\xfb\x32\x33\x4e\x20\x42\xf4\x50\xfa\x1c\x3d\x9d\x07\xbc\x58\x4c\x10\x31\x74\x02\x65\x70\x7c\xc6\x13\x2b\xe9\x4d\x22\x20\x13\x26\xc7\x58\xc5\x7e\x93\xb8\x17\xaa\x6c\xcd\x32\x82\xe7\x2a\x56\xd9\xce\x7d\x5d\x59\xd8\xba\xb1\x0c\x6c\xbe\x5b\xdd\xe7\x2b\x3b\xac\x66\x08\xd2\x31\xc4\xf1\x77\x43\x8f\x21\x19\x69\x9c\x85\xc2\x30\xd3\xc2\x09\x8e\x91\x2d\xcb\xef\x4d\xfd\x19\xd0\xae\xf7\xba\x67\x76\x15\x5c\x31\xac\x01\x7d\x79\x14\x5b\x9a\x22\x54\x09\x4e\xd4\xc6\x0e\xc5\x89\xc5\x5c\x4c\xec\x68\x1c\xf0\x10\x84\x55\x76\x43\x41\x31\x5f\xbd\xa0\x66\x7e\x36\xea\x5c\xfb\x9c\x45\x49\x58\x65\x4e\x3c\xbe\x7c\xef\xdc\xc5\x40\xfb\x2f\x1d\x55\x12\x81\x23\xb7\x69\xb5\xae\xb5\x12\xd8\xfd\x2b\xc9\x24\x71\x2d\xa5\x02\xcc\x92\x02\x44\x7d\x19\xa6\xda\x1d\xd3\xa0\x26\xb5\x4e\x20\x04\x63\xdb\xe8\xa6\x29\x75\x9e\xaf\x9f\x57\x65\x62\x4d\xa1\x76\x35\x35\xda\xa8\x6d\x33\x2b\xd7\xd0\x12\x93\x6b\xc0\x3c\xfc\xf4\x6e\xbc\xf3\xde\x5c\x7a\xb8\xb6\xb7\x43\xc7\x81\xe4\x90\xe7\x68\x29\x1d\x37\xd9\x67\x64\xee\x6d\x21\x6e\xad\x21\x99\xa1\xb9\x0f\xe8\xd1\x11\x70\x59\x2f\xf9\xc1\x0f\x2a\x0c\xb3\x6d\x67\x84\x8f\x97\x4e\xbe\xeb\x61\xf0\xdb\x9e\x69\x5f\x2a\x18\x63\x1c\xa8\x27\x28\xa4\xf1\xe1\x95\xd0\x70\x4a\x51\xfb\x57\x0d\x48\xa6\x73\x92\x38\x3c\xb5\x8f\xf9\xe0\x21\x15\x19\x94\x6f\x82\x60\x1d\x8b\x9f\x88\x40\x24\x3f\x78\x43\x00\xab\xff\xec\x24\x19\x59\x59\x8f\x44\x86\xaa\xc9\x0b\xe8\x66\xb8\x89\xa6\x1f\x22\x33\x03\x47\xf1\xb3\x10\x70\x70\xd1\xea\xed\xd2\x80\x6a\x63\x15\x8e\xb3\x51\xf8\xcf\x5e\x3d\xba\xb4\x62\x67\xf7\x2d\x59\xbf\xfb\x7e\x89\x64\xe6\x42\xf1\xf4\xbb\xac\x9f\x39\x61\x26\xf8\x6c\x5b\x73\x22\x9b\xf3\x6f\x2d\x12\xe5\x8d\xf4\xc0\x01\x4e\x01\x3a\x06\x37\x28\x5d\xfb\x1f\xcf\x45\xeb\x24\x4d\xa9\x8d\x31\xb4\x5c\x8e\xac\x99\x12\x6a\xa7\x6f\xab\x55\x15\xb2\xbf\x4c\x8d\x08\x28\x50\x8d\x41\x78\xe2\x9d\x0a\xdc\x1e\x12\xc6\x31\xb4\xe0\x1d\x38\x50\x7f\x29\x8e\xb7\xce\x55\x86\x1d\xd1\x47\xe4\xb6\xf8\xa1\x14\x60\x7a\xc6\xb8\xe7\x65\xbf\xa2\xe6\xc3\x3c\xf8\x0d\x81\xf0\xa6\x04\x5a\x4d\x75\xb6\x20\xa8\xb2\xb2\x29\xbe\x8f\xdc\xb1\x8b\x49\xf6\xce\x09\x18\x44\x4c\x74\x01\xb4\x08\xda\x38\x55\xa2\x9e\x87\x08\x18\x9e\x2d\x60\x35\x5c\xce\x90\xef\x7e\x15\xa0\xa2\x55\x3b\xb5\xb4\xc0\x57\x9c\x5f\x0f\x4a\x26\xa5\xd6\xe0\x7a\x24\xe0\xd7\x4a\xfa\x5d\x72\x41\x21\xa2\x4b\xf3\xe1\xbc\x22\x61\x7b\x43\x99\x4e\x73\xe0\xb7\xa8\x20\xdf\x64\xf5\xf7\x5b\x33\xff\x3c\xbe\x12\x19\x21\x76\x5b\x66\x69\x92\xa7\x46\x1c\xe0\x4c\xd0\x1b\x7a\xe2\x5d\x10\xea\xe6\x83\xd6\x41\xc9\x7b\xa5\xfe\x44\xd9\xd0\xa1\x15\x16\x18\x03\x0f\x3d\x6c\x23\x19\x29\x27\x8e\x2c\xf4\x5c\x48\x0c\xb1\xd2\x1c\x83\xf7\x5e\x30\xf8\x63\xd1\x39\x37\x19\x64\x8d\xfb\xad\x14\xfa\x0e\xe6\xae\x0f\xfe\xe6\x7f\x26\x8c\xba\xaa\x60\x3f\x73\x66\x3e\x3a\x4a\x75\xfe\xec\x9d\x1e\x18\x66\xa8\x13\xa6\x6c\x6b\x92\x80\x43\x62\xca\xec\xeb\x35\xea\xe4\x0f\x28\xe1\x9e\xbf\x5a\x95\x73\x0e\x52\x59\x53\x1c\xe1\x19\x6d\x9c\x00\xff\x7a\xae\x96\x40\xfa\x2f\x7f\x95\xe7\x21\x72\xba\x19\xe9\x59\xef\xde\x2b\xc1\xb8\xe6\x8c\x66\x25\x0b\xe1\x70\xcd\x53\x3f\x46\x6f\x03\xc3\x7a\x94\x90\xc3\x3f\xa4\xe1\xea\xa3\x84\xc3\xe2\x69\x31\xc8\x6a\x5c\x27\xc9\xbe\xfa\x17\x14\x67\xe7\xf9\x7b\x2a\x8e\xf0\x48\x64\xa9\x20\x47\x2d\x3b\x0b\x1b\x65\x11\x3f\x90\x40\xd5\x4f\x8d\x01\x1b\xd7\x24\x48\xf3\xcc\x15\x72\xa8\xbf\xe9\xf1\xb8\x24\x94\x33\x66\x55\x37\xa9\x0b\xbb\xe5\xae\x73\x1d\xd5\x4e\x37\x6f\x0b\x2d\x9e\x4f\xf5\xda\xa2\xe9\xd8\x87\xd8\xb2\x8c\x7d\x8a\xdd\xa3\xb9\x23\xe1\x4d\x3c\xa0\xea\x2c\xb1\xc3\x1f\x2d\x28\xc0\x44\x79\xde\xe3\xe5\x13\xb5\xb7\x84\x4b\xe9\x48\x88\xb7\x6d\xf8\xa3\xfe\x05\xb2\x42\xb6\xc9\x1e\x17\x7b\x8a\xbe\xd1\xd6\x63\x67\x6b\x1d\x73\x04\xf7\x89\x51\xee\xaa\x86\x22\xa2\x5d\x5f\xad\x8b\x94\x5e\xc6\x89\x3a\x1b\xcf\xdb\x8b\x43\x84\xb2\xa6\x73\x0b\xad\xc8\x1a\xb2\xe1\xcd\xb7\xb6\x01\xf4\x9c\x28\x49\x2d\x66\xde\xca\x11\xd2\x6c\x0f\xd7\xdc\xc5\x8c\xc7\xed\x1a\x07\xfb\x48\x9a\x11\xed\x29\x49\x50\xa5\x21\x46\x86\xdf\xe8\xf2\xaa\xaa\x79\x7d\xcd\x39\xe3\x7f\xf2\xc1\x9b\x4c\x3d\x26\x8e\xb7\xe5\xac\x6f\x86\xcf\x5d\x92\xb0\xc3\x40\x91\xd4\x8f\xfe\xc6\x83\xbc\xc7\xcd\xdf\x8f\x10\x79\xa2\x38\x09\x6c\x00\xa7\x25\xf6\x3e\xb5\xe0\xc6\x22\xd5\x1a\x28\x1d\x21\x6b\xba\xb6\x32\x24\xa6\x29\x4a\xce\x9c\xf9\xa7\xb1\xf6\xea\xdd\xfe\xb6\x1f\xc2\xa1\x5c\xff\x75\x0e\xba\x29\x1f\xff\x03\xe9\x2a\x29\xd3\x1c\x9c\x2d\xce\xe4\x0a\xf3\xf3\x1e\xe5\xd5\x90\x2f\xbb\xd4\xe8\x77\xb9\xa9\x47\x0a\x77\x0c\x60\x92\x24\x0e\x79\xbb\xcc\x4c\xb9\x92\x2c\x0e\x42\x9e\xee\x31\x0d\xc0\x09\xb7\x3d\x75\x42\x97\xb7\xc4\x62\xf7\xc0\x61\xe4\xd6\xe6\x16\x76\xb6\xc2\x0b\x11\x8f\x67\x66\xae\x43\x63\x3e\xe7\x23\xad\xa3\xf8\xe9\x42\x48\x5d\xa5\x45\xd3\x0e\xa0\xea\xcb\xe6\xe8\x2f\xb9\x02\x0d\xd2\x48\x1e\xee\x91\xdb\x1a\x55\xcf\x7b\xeb\x08\xd4\x58\x5c\x5e\x25\x8f\xd7\xbb\xd4\x0c\x75\x93\x94\xc0\x1c\x9f\xe5\xd6\xaa\x32\xb2\xd8\x20\xba\x5a\x08\x10\xdd\xcc\x1e\x3a\x8a\xb4\x84\xc6\x13\x62\x62\xb3\xfc\x09\x35\x4d\xe6\x26\x6e\xe8\x08\x23\x9f\xd0\xcb\x0a\x9a\x97\xba\xcd\x9c\x9c\x69\x21\x4c\x12\x25\xa6\x81\xa7\x5e\xb3\x8c\x6a\x2b\xb5\x9d\xcc\x3b\xe6\xbe\x8f\xde\x90\x2c\x0b\xc6\x21\xdb\x20\xbe\x88\xb5\x15\xb3\x7e\x5c\x19\x4b\x60\xb2\x43\x03\xea\x1d\x78\x84\x82\x99\xf7\x8e\x7b\xe1\x94\x8b\x31\x67\x22\x65\xfd\x27\x54\x32\xbc\xe7\xc2\x73\xd2\xab\xdf\x59\x03\x5a\x5e\xf5\xc3\xb4\xba\x31\x61\x99\x27\x6f\x5d\x22\x2b\xe6\xdf\xf2\xa7\x8f\xfb\x17\x86\x0e\x9e\x32\xc6\xb5\x33\x71\x09\x6e\xec\x3e\x4a\x43\x95\xb3\xc0\x2c\xaa\x7d\x08\x40\x7d\x9c\xd3\xd7\x34\x87\x47\x00\xa6\x2e\xf6\x44\x4f\x35\x9d\x21\xb0\xe0\xf0\x90\x33\x28\x6e\x98\xed\x4c\x8d\x64\xef\xbe\x8a\x1e\x4f\x1e\xb1\x87\xaa\xa2\xee\x8d\xde\x1c\x6d\x82\x76\x43\xe1\xd1\x31\x6c\x85\xa3\x75\x99\xe3\x79\x2c\xac\xa9\x11\x70\x84\x90\xce\xe2\x1d\x47\x7e\x61\x17\xd7\xa7\x69\x9e\x84\x17\xbc\x67\x92\xcd\xc6\xa1\x77\xef\x31\x8d\xea\xbf\xef\xdc\xa9\xac\xef\xb2\xf0\x7b\x5c\xb4\x4b\x26\x6a\x6d\x22\xdd\xaa\x30\x91\xb5\xe9\x93\x5c\x88\xe7\x4c\xd1\xf6\xb7\xe7\x8b\xc8\xce\x60\x0a\x67\x04\x6d\x5f\x2e\xc1\x16\x7c\x58\x4f\xe6\x74\x80\x2e\x85\x00\x7f\x25\xcd\xfe\xb1\x50\x45\xf4\x0d\x80\xf5\xdf\x73\xa4\xa8\x32\xe8\x2b\x75\x8c\x91\x18\x2c\x1d\x5a\x12\x81\x93\x35\xe4\x1e\xf1\xb2\x97\x06\x6b\xdc\xca\xef\x3a\xdd\xc3\xfc\xc2\xaa\x60\x93\x33\x21\xef\xa5\xd3\x7c\xa9\x48\x3e\x2d\x9b\xf5\xff\x5f\x62\x3c\x07\x14\xf3\x04\x65\xac\xfc\x16\x8e\xc8\x60\x7c\x55\x59\xee\x3f\x2f\xa5\x0a\xf6\xf3\x47\x9c\x55\x63\xaa\xa1\x8c\x47\x27\x62\xe8\xac\x0a\xc7\xfb\x94\xc6\xdb\x74\x67\x6d\xf6\xed\xcd\x35\x38\xbc\x4a\x42\xc4\x99\xe1\x46\x1f\x55\xfd\xf8\xee\x67\xbf\x9a\x10\x30\xbe\x47\xa9\x66\xa1\x40\xa0\xd3\xa4\x46\x26\xbe\x76\xb9\xc0\xb5\x38\x00\x47\xd3\x74\x4a\x01\xcd\xc2\x60\x4a\x21\x7a\xf3\x10\xfe\x44\x45\x09\xa7\x7c\xff\xef\xc4\x25\x40\xb9\x00\x57\x9c\x1c\xdc\x31\xc6\xee\x7b\x52\x1e\x39\xf9\x49\x8b\xbe\xa8\x15\x6d\x66\x1d\x4d\x89\x1b\xb3\x87\x39\x7d\x04\x06\x16\x4b\x7a\x6e\x51\x5e\x6b\x94\xab\x73\xd2\x4e\x43\x3e\xe8\x19\xa3\xf1\x1f\x90\xf7\x86\xef\x0c\x95\x87\x7b\x65\xa3\x2e\x2e\x5a\x4c\x61\x24\x85\x5b\xda\x2f\x2f\xa1\x49\x31\x22\x36\x48\x94\xba\xe7\x6f\x0d\x8f\x3c\xc6\x53\xdd\x0c\x5b\x70\xfe\x87\xa0\x2e\x3a\x22\x21\xbb\xe7\x47\x40\xc8\x38\xe0\xeb\xe6\x3c\xe0\x4a\xf8\x5f\x1c\x81\x27\x37\x99\x97\x6d\xb1\x77\x1c\xd8\xcb\xb1\xe4\xf7\x2c\x11\xe0\xb9\x4d\x8a\xb2\xcc\x39\x58\x27\x49\x81\x94\x7b\x33\x76\x74\xea\x2f\xfe\x07\x0b\x16\xee\x20\x19\x0b\xdf\xaf\xe6\xc7\x3b\x07\x27\xdd\x1b\x4a\x32\xa8\x34\xe7\xca\x4a\x92\x39\x96\xbc\x04\x5d\xb0\x23\xd5\x58\x86\xe5\x9f\xe9\x15\x8d\x3c\xea\xb7\xb1\xfd\x45\x7f\x50\xfa\x54\xc5\xaa\xa8\xdf\xbf\x8a\x3c\xb5\xc7\x64\xb5\x49\x12\xd7\x4b\x61\xcd\xcd\x1c\xad\x87\x74\x44\xf6\x0a\xea\xb5\x1a\x2a\x72\x6e\x4a\xd2\x1b\x5a\xcc\x68\x65\xa1\x52\x02\x51\xa1\x55\x0d\xc8\x5e\xbe\x8e\xb4\x40\x54\x63\x69\xdb\x62\x93\xcc\x40\x7c\x0d\x0d\xb0\xc3\x87\x43\x98\x5d\x3a\x86\x91\x1c\x7a\x70\xa6\x90\xd3\x23\x22\x80\xaf\x52\x14\xf1\xa4\x8e\xfb\x50\xdb\xe7\x7d\x6a\xb3\x4c\xcb\x74\x50\xfe\xad\x4d\xad\xa2\x00\x9f\x1a\xaa\xf2\x10\xe3\xf8\x1d\x49\xa7\x8d\x18\xe8\xae\x9d\x1d\xac\xd5\xbf\x5f\xa3\x9b\x5d\x29\x89\x72\x71\xb9\x29\xe5\x11\xaf\xa2\x22\x59\x1c\xd2\xa6\xcb\x74\x7c\x75\x88\x73\x5a\x77\x6c\x44\xee\xca\xee\xa9\xc4\x5b\x8d\xda\xec\x5e\x51\x06\x4c\x00\xe8\x95\x22\x0f\x5e\x5b\xd8\x8c\xde\xbf\x36\x13\x2b\xaf\xad\x3d\x99\x62\x0b\xea\x04\x51\x61\x94\xc9\x88\x4e\x8a\x44\xd5\xc5\xb2\xdf\xf6\x10\xf7\xf9\x2d\x57\x72\xb1\x45\x3d\x85\x23\x6a\x82\x60\x44\x56\x51\x33\x66\x43\xb1\x2f\xaf\xd9\x6e\x3e\x9f\x1f\x35\xd1\x4d\x02\x1f\x88\x80\x62\xd2\x5c\xef\xd3\x8c\xb8\x94\x0e\x2a\x06\x2a\xac\xdb\xda\x9d\x0b\x8b\x08\x41\x1f\x65\xc4\xd3\x84\xff\x10\x0e\x54\xc2\x0c\x20\xe2\xd1\x1a\x26\x49\xc2\x7b\xca\x10\xc0\x47\xbd\xda\x87\xd1\x98\xe5\x5f\xb1\x1e\xc4\x09\x8c\x58\x99\x10\xe4\x71\x9d\x7f\x02\x0f\x2b\x75\x83\xfc\xd2\xab\xd0\xae\xd4\x7b\x81\xae\xf1\x92\x1f\x2d\x70\x9b\xff\x3c\x13\x5b\x63\x17\xef\x4c\x51\x13\x3d\x86\xd2\x42\xbf\x75\xb1\xf5\x13\xbf\x87\xda\x9e\x38\x9e\x76\xa1\xcf\x17\xb2\x09\x1f\xf4\xc2\x53\xe5\xfd\x45\x1a\xf9\x03\x0a\xad\x26\x6f\x6e\x30\x01\x5b\x1b\x03\xa4\xd6\x14\x9d\xaa\x2c\xe5\x84\x34\xe9\xe4\xa7\x61\x68\x2a\x21\x0e\xdb\x85\x5a\xa4\xe6\xd6\x9c\x18\xab\xb0\xd1\xa8\xed\x8e\xca\x60\xc5\x2e\x5a\xe2\x2a\x9f\xb4\x4f\x2a\xe9\x6c\xe3\x47\xda\xd7\x93\x88\xe7\x12\x2f\x26\xb2\x14\xf6\x51\xbd\x8c\x51\x83\x57\x1f\x8f\xd9\xcf\x10\x4e\x59\x05\xae\x79\xbd\x62\x00\xe0\x08\x89\x44\xe5\x33\x0b\x42\x25\x55\xe9\x1b\xbd\xe3\xe1\xcd\x45\xdb\x9d\x72\x6f\x1e\x70\x86\x9a\x7c\x54\x69\x39\xa2\x70\x55\xb4\x7e\x7c\x0f\xa0\xc7\x64\x1d\x40\xa6\xe8\xb9\xc5\xb2\x57\x96\x96\xee\x2e\xf2\x47\x57\x91\x3f\xb9\x13\x59\x6e\x10\x71\xd8\x51\x85\xdb\xff\xbe\xa4\x74\x95\x27\x07\x13\xa2\x44\x90\xd0\x37\xce\xd0\x16\x28\x19\xf4\x0e\x7e\xc9\xfd\x06\x56\xd1\x6b\x3a\x61\x9f\x84\x31\xf5\x0e\x27\x23\x14\xee\xec\x96\x1e\xa8\x4a\xa4\x97\xa5\xca\xd8\xc5\x4d\x79\xa9\x86\x5a\x7b\x08\xcf\x06\x53\x37\x55\x92\x21\xd1\x74\x44\xd5\x84\xb9\xab\x4e\x30\x8d\xb6\x8b\xfb\x9d\xa1\xdc\x5a\x86\x18\x08\xc4\x6c\x75\xcb\x8a\x8b\xb6\xc8\xd5\xd7\x73\x1f\xd5\x26\x16\x89\xc1\x8a\x7a\x12\xfe\x51\x52\x40\xfe\xaf\x75\x64\xe5\xdd\x75\x67\x10\x8c\x91\xb6\x3f\x17\x4d\x60\x6c\x23\x3d\x91\x32\xad\x59\x89\xe9\xd8\x46\x40\xb0\x09\x47\x32\x89\x1b\x11\x4c\x76\xd6\xee\x02\x17\x2c\x26\x5b\xb5\xcc\xf4\x7a\x96\xa2\x35\x19\x85\x26\x3d\xc9\x53\x1f\x03\x6e\xc1\xa5\xb8\x6b\x31\xf9\x07\x4d\x76\x0a\x64\xda\x8c\x02\x9a\x64\xde\xb2\x97\xef\x82\x3a\x2f\x13\xa4\x5c\x62\xca\xd2\xab\x16\xe0\x18\x47\xb1\x1c\x72\x94\x5d\xe1\xb5\xdc\xdf\x57\x69\xf8\xad\xb1\x00\x5e\x6b\xa0\x66\x81\x06\x88\x30\x45\x77\xaf\xb7\xf2\x86\x38\x1a\x88\xbd\x51\x97\x7d\x17\xfa\xa0\x3e\x9b\x19\x21\x6e\xf3\x8f\xa1\xe1\xc2\xd1\x1b\x25\x50\x46\x3b\x69\xb4\xc0\x54\xa3\x0a\x03\x5c\x64\x7f\xa3\x49\x80\x0c\x6d\x9e\x6a\xb1\xfd\x1c\x5e\x0c\x7d\xb4\xbe\x6e\x5f\x92\xc4\x93\x26\xff\x39\x01\x57\x4b\x79\x32\x95\xf1\xcc\x33\x6d\x8c\x23\xb2\x5b\x9b\x59\xab\x1a\x7e\x6a\x27\xfe\x6a\x81\x11\x9a\x9a\xbc\x17\x41\x8b\x72\x76\x6b\xcd\x20\xdf\xee\x9c\x41\x2b\xe7\x1f\x86\x17\xf2\x6f\x4c\xd2\x35\x6a\x91\x68\x0d\x79\x8d\x33\x59\xc4\xcf\x1c\xd6\xb2\x3c\x64\xdb\x30\x33\x8a\x63\xfc\xbd\x9d\x11\xde\x5c\xeb\x9b\x97\x6b\xd2\xec\x00\xa3\xef\xef\x4c\xfe\x56\x09\xdf\x85\x1e\x69\xce\x2d\xc1\x71\x2a\x9b\x1a\x1d\x7d\x42\x0b\x4f\x55\xa7\x0c\xde\x3c\x36\x3b\xb1\x3a\xe8\x80\xce\xec\x6b\x75\x22\x57\xb4\x6a\xf4\xde\xf0\xcd\x72\xd0\xba\x46\x9d\x20\xb9\x16\x40\x4c\xa6\xa4\xc7\x52\xa1\x44\xb9\xf8\x07\x7d\x58\xef\x2d\xc7\x5e\xc3\xfe\xd2\xea\xe1\x6f\x5f\x65\x29\xe1\xcb\x3b\xeb\xb3\xfb\xec\x3d\x83\x21\x01\xd2\x24\xb1\x38\x89\x9a\xfe\x0b\x94\x4a\x84\xfb\x17\x15\x70\x6a\x4a\x52\x6e\xd2\x77\x67\x8f\x22\xde\xca\xdb\x89\x35\xff\xb0\x84\x82\xfc\xac\x2f\x2b\x97\x26\x06\x86\xfb\x97\xeb\x06\xde\xd3\x42\x5d\xca\xd9\xd5\x6f\x61\x71\x2b\x63\x75\xfb\x13\x7a\x86\x0a\xb7\x44\xb3\x25\xa2\xe7\x8d\x17\xac\x7b\x7a\xdb\x50\x53\x6e\x85\x7e\x0c\xbd\xe8\x18\x39\xfc\x88\x0e\x8a\x1b\xb3\x00\x6c\xac\xfb\xc0\x98\x61\x82\x3a\x56\xb9\x1a\x87\xb6\x36\xa1\x45\x9d\x14\xbd\x05\x80\xd2\x17\xf3\xe6\x56\x39\x55\x17\xe9\x52\x8f\xa6\x0b\xd5\x68\x8a\xa5\x03\x93\x8a\x1f\xa0\xe5\x8a\x8d\x7b\x85\x30\x33\xc0\x7b\x5c\xe4\xc3\x12\xfd\xa6\x36\x26\x8d\x2a\x1a\xcd\xef\x4e\x05\x4d\x28\xbc\x98\x55\x1a\xc0\xcb\xb6\xb6\xe8\x31\xda\x34\x82\x97\xb0\x09\xde\xb8\x2e\xd1\xb8\x31\x47\xde\x7e\x89\xee\x7b\xdc\x40\xe0\x29\x6d\xad\x1b\x7e\xbf\x7d\x75\x60\x05\x27\xa9\x69\x15\x78\x7f\xf7\x50\x14\xce\x8d\xe7\xcc\x8b\xfd\xd8\x58\xe4\x7d\xb8\xc9\x60\x45\x86\x57\xff\x6b\x00\x90\x84\xa6\x88\x6d\xe6\xc1\x0c\xab\x46\xe1\x6c\x51\x2f\xb1\x5c\x29\x75\x8c\x17\xd4\xfb\x2d\x56\x93\xb6\x84\xa9\x2c\x1a\x9d\xf3\x15\xef\xf2\x1e\xa1\xda\xda\xf1\x29\xd2\x6f\x40\x59\xba\x37\x58\x8e\x1b\x78\xf1\xa1\x7e\x73\x8c\x96\xb4\xe1\xea\xa0\x01\xfa\xd6\x26\x8d\x45\x77\x25\xe6\x96\x2b\xfd\xa0\x84\x29\x01\x43\xf2\xe6\xb8\x75\x79\xe9\xb2\xd4\xc0\xf7\x35\x0a\x15\x6b\x3d\xa2\x9e\xb8\x8b\xa9\x2f\xf2\x5c\x14\xaf\xc9\xa4\x8b\x5c\x30\xa2\x70\x12\x0c\x6f\xa8\x9a\xe1\xff\x7b\x8d\x98\xd9\xea\x4b\xa9\x72\x59\x03\xa5\x0f\x36\x90\x3b\x4d\x42\x1b\x67\xc1\x35\x22\x72\xc1\x3a\xb5\xf7\x5a\xb0\x3b\x01\x32\xbc\xa4\x59\xe9\x0d\x7f\xd0\x7d\x03\xa5\x72\xfe\x49\x41\x1f\xdf\xd4\x4b\x98\x75\xac\xca\x04\xef\xf4\x56\x16\x0c\x08\xc7\xe0\x31\x71\x6a\x31\x99\xbb\x30\x85\x54\xb3\x12\x27\xa3\x63\x49\x97\xb3\x5e\x19\xb8\xa4\xf7\x74\x85\xe4\x57\xf7\xbd\xd9\xcb\x25\x90\xe2\x66\x17\x11\x64\x7b\x21\x94\xa5\x19\x8b\x2e\xb1\x71\xee\x39\xdd\x40\xbc\xdb\x0c\x77\x4a\xb8\x9c\x07\xcc\x07\xe5\x09\xb5\x6b\xf5\xf9\x07\x8a\xed\xfb\xd5\x2b\xea\x66\x2c\xbe\xac\xd2\xd6\x80\xd0\x4e\xe0\x75\x97\x7e\x63\xef\xc5\x4b\x5d\xcc\x74\x1c\x52\x59\xab\x77\x95\x4c\x5c\x3e\x9c\x2d\x8b\x11\x12\xce\x8b\x5a\x6a\xaf\x21\x3b\x37\x10\x09\xf0\x2a\x66\xc0\xae\x4b\xc7\x5f\x3c\x95\x19\xbc\x21\xff\xe4\x67\xea\xe9\x87\x5e\x0d\x73\x6d\x77\x90\x2e\xf8\xd4\x5c\xd6\x98\x42\x89\x2f\x6b\xe8\x25\x51\xec\x45\xd7\x88\xf3\x26\xed\x5e\xbd\x85\x35\x65\x47\xc6\x53\xa3\x79\x90\xdc\x21\xd3\x66\x5e\x52\xa9\xa5\xd7\x45\xbf\xc6\x06\xcc\x59\xb1\x83\xb3\xf9\x99\xb1\x78\x17\x2b\xf7\xf2\xd2\x03\xd2\x5f\xd3\xaa\xb4\xca\x7b\xd8\x82\x6f\xa8\x09\x6c\x9d\x0b\x9f\x47\x36\x1a\xba\x8c\xa9\x3b\x79\x54\x3e\xf5\xc1\x09\x93\x39\x56\xf2\x1d\x03\xca\xee\x77\x4d\x8c\x2d\xfe\x53\xb4\x9c\x3e\xd3\xc4\xff\xcd\xe2\x32\x97\x10\xc5\x47\x9c\xcb\xd7\xcc\x21\xe2\xfd\x89\x07\x97\x3c\x84\x7c\xfb\x5f\xd3\x45\xe1\x31\x48\xd2\x2b\xdd\x31\x00\x9e\xf7\xaf\xae\xba\x93\xd0\xf5\x0a\xa6\x6b\xcb\x5d\x31\x4a\x23\xb8\xe2\x31\xe0\x35\x22\x0c\x0b\x59\x7b\x9a\x59\x8c\x8a\x65\x69\xc9\x45\x82\x2e\x5d\x51\x73\xd9\x55\x97\xf6\x8f\x45\xc4\xd4\x7a\xcd\x6f\xfd\x29\x66\x88\x39\xbe\x55\x60\xd2\x14\x74\x70\xcc\xbf\x6c\xc1\xd4\x14\x00\xae\x67\x82\xa1\x70\xc3\x76\x7f\x8e\x89\xc6\xed\xf6\x76\x60\x81\xf4\x3f\x28\x23\x89\x4d\xe9\x87\x0a\xe0\x3f\x51\x21\xd4\xf0\x24\xb9\x5f\x6c\x11\x63\x14\xab\x34\x6d\x27\x21\xcb\x0b\x49\x72\x0f\xcb\x29\x9c\xbb\x13\x8e\xf3\x6a\x70\xb6\xc8\xfa\x04\x92\x96\x82\xb2\x4d\xb6\x72\xeb\x91\xae\x94\x16\x76\xa8\xe6\x12\x56\x6f\x43\x8e\xd9\x31\xd2\x8e\x5e\x6b\xa0\xb9\x02\x7a\x8f\xc4\xeb\x42\x69\x52\x1c\x2d\x7b\xec\x2a\x0c\x8e\x99\x8b\xd0\x0d\x18\x8b\xfd\x33\x21\x38\x4b\x8c\x42\x3c\x72\x8a\x59\x9f\xca\x27\x3e\xc8\x73\x43\xdf\xf8\x1d\x6a\x86\x8a\x0d\xbd\xa3\x9e\x9d\x93\xcd\x34\x40\x3b\x21\xc0\xac\xc3\x91\xc3\x98\xb5\x99\x37\xa7\x00\xe1\x54\x95\x2d\x62\xd3\xb5\x68\x74\x7a\xdd\x42\xc2\xd8\xdb\x82\x17\x8a\xc0\xba\xe6\xa8\x78\x3b\xab\x3a\x9a\xbd\x5b\x8e\x36\x66\xc9\xa7\x37\xe9\x40\xa6\x45\x5c\xd8\xfa\x0e\xa1\xc4\x8d\x41\x9f\x67\x43\x22\xaf\xc0\xe6\xfc\xa8\x05\x6d\xff\xca\x88\x1a\xad\xc1\x67\xb7\x48\xc1\x81\xaa\xc2\x96\xd0\x9d\x1a\xfb\x11\xed\x0a\xb7\x0b\x72\x61\xdb\xb1\xab\x87\x90\xc7\xb8\x29\xfb\x76\x91\x6c\x1c\x02\x4e\xce\x6a\x3a\xd9\x2c\xee\x92\x96\xcb\x96\x06\x8c\x71\x0a\x1e\x8c\x93\xc4\x98\x1b\x65\x3d\x86\x87\xcc\x9d\x90\x45\x8b\x63\x24\x82\x9a\xa5\x17\x45\xd1\x44\xfa\x0d\x2c\x61\x8f\x86\x7e\xd4\x24\x43\xcf\xce\xd9\x59\x64\x0e\x79\x19\x47\x43\xaa\xfc\x22\xf7\xa2\xa3\x25\x97\x9c\xae\x21\xa5\x3d\x42\xbc\x17\xe7\xc1\xeb\xe9\xcb\xdc\xa2\x81\x73\x0a\xe6\x47\x30\x42\xd0\x5f\x14\xb3\xda\x5c\xb2\xec\x86\x12\x10\xed\x1f\x3b\xdf\x37\x56\xd1\xbc\xfe\xc3\xc3\x70\x86\x4e\x4a\xd3\x65\x3a\xbc\xcc\x4a\x3f\xee\xca\x8b\xd1\x8c\x72\x88\x50\xe9\x75\xfc\x99\xda\x5a\xab\x72\xa7\xbd\xf5\x0a\xee\x44\x55\xd5\x96\xa6\x7f\x4b\x12\x93\x54\x56\x13\x59\x34\xd5\x8f\xa4\xab\xb9\xeb\x8c\x88\x04\x71\x21\x9a\x49\x62\x56\xe0\x5e\x32\xcf\x5b\xec\xf1\x80\x28\x79\x86\x57\xc3\x62\xf8\x7f\xf9\x29\xd2\xb6\x08\x09\xf5\x8b\x8a\xdf\xf4\x08\x6f\x6d\x18\xac\x70\xa3\x36\xe3\x7d\x8a\xd1\x65\x68\xff\x45\x76\xe8\xbd\x20\xbe\xfb\xbb\xc5\xc9\x81\x68\x44\x5a\x82\x54\x49\x49\x13\x32\x46\xd1\x0c\x8b\x67\x09\x28\xfc\xb8\x1b\x66\x24\xb8\x2d\x92\x0f\xb9\x6c\x7a\x34\x0f\x2b\xa3\x04\xed\xb7\xab\x4d\x99\xdc\x75\xc0\x29\x96\x62\x8e\x88\x96\xc6\xb1\x6a\xa5\x61\x1f\x0d\xcc\x7e\x87\xba\x98\x1d\x39\x0b\x45\xe5\xdf\x25\x5a\x4e\xd5\xd9\xd1\xee\x28\xf1\xaa\x36\x4b\x6e\xd1\xf4\xb6\x9e\x75\x35\x9f\xc5\x4f\x74\xdf\x32\x58\xc1\xfc\xc7\xd6\x70\xab\xa9\xe9\x23\x7b\x80\x7c\xf5\x14\x09\xf9\x71\x58\xda\xb1\x9c\x20\x28\xb7\xce\xbe\xc5\xb5\x67\x79\x76\x43\x25\x5d\xc5\xd0\x9c\x07\x4e\x2f\xc1\x0c\xcd\x1b\x1b\xfb\x14\x39\xcc\x7c\xdf\x14\x23\xe2\xbd\xae\x34\xb2\x87\x71\xce\x4e\x6b\x54\x25\x74\xfa\x0c\x59\x84\x1e\x2f\x65\xdd\x98\xf4\x53\xa5\x57\x01\x20\xc0\x02\x95\x5a\x7b\xc2\x47\x0f\xa7\xdf\xb0\xda\x45\xfc\xea\x2e\x09\xf6\xfc\xf8\x60\x61\x21\x12\x15\xb1\xc6\x57\x2b\x87\x33\xf0\xef\xb8\xe1\xef\x98\xfc\x23\x89\x1b\xc6\xf7\x8e\x4d\x52\xe5\xac\x2b\xa1\x7e\x3f\x62\x22\x25\x0b\xb2\xd1\xb8\xe3\x5a\x20\xbc\x50\x48\xf6\x26\x91\xef\xce\x45\x8d\x84\xde\xe6\x99\x18\x16\xa0\xda\x96\x44\xda\xb5\xef\x93\x8c\x51\x14\x3f\xa4\xcb\xce\x60\xde\xc2\xa5\xce\x9b\x77\xb1\xcf\x35\x44\xc8\x96\x90\x14\xee\x47\x22\x38\xc4\x66\x40\x22\xd1\x5e\x2a\x32\x7c\x45\x9b\x96\x6d\x60\x00\xdf\xfe\x5f\xff\x28\x37\xdb\xcf\x14\x7a\xd1\x9f\x3d\xc4\xc4\x67\xea\xf2\xb3\x88\xb3\x71\x1f\xe7\x60\x48\xce\x31\xfb\x79\x76\xc9\xd4\x99\xd5\x37\x9f\x41\x25\xfa\x3e\x0b\x55\x48\x36\x62\x26\x89\x2b\xee\x06\x71\xe3\xf9\xf0\x10\xff\x87\x70\xe1\x78\x4d\x97\x01\x51\xb5\x04\x7f\x24\x3a\xee\x1a\x63\x51\x5f\xa7\xe5\x9a\xf8\x5e\xcc\x4c\x69\x3a\x40\x3e\xc2\xad\xf4\xa7\x3a\xf4\xce\xb5\x44\x24\x5f\xa7\x6b\xfc\xf9\x1c\x4d\xbc\x50\xe0\x54\xa1\xaa\x3b\x27\xb0\x77\xec\x86\x1f\xc1\x09\xf5\xe4\x2d\x82\x42\x17\x7c\xa1\x0b\xdf\x53\xc8\xf1\x7b\x33\x2a\x08\xf7\xc9\x3f\x3f\xf4\x24\x49\x44\xe0\x37\x74\x9c\x85\xf1\xa1\xf4\x93\xcb\x70\xdd\xa8\x59\xce\x9c\xdb\x15\x6c\x59\x04\x1d\xda\xc4\xc6\x60\x81\xfa\xc2\xde\xfe\x47\x79\x35\xc5\x86\xb1\xe3\x47\x0a\x29\xf7\xd6\xc9\x0e\xa9\x50\x81\x9b\xcf\x8f\x42\x48\x0e\x70\x24\x64\x22\x12\x60\x3e\x14\x3b\xef\x5e\x46\x54\x7b\x4c\x93\x83\xdc\x30\x09\x67\xc3\x52\xde\xc4\x09\xcc\xa1\x95\xc7\x19\x8e\x5f\x3d\x54\x57\xdb\xec\x5a\x9d\x65\xb6\xf6\x2b\x0b\x82\x4b\xbe\xca\xd7\xce\x22\x69\x67\x25\x07\xb8\x30\x27\xde\xed\xa4\xbe\xa0\x91\x69\x9b\x39\x98\x67\x6b\x57\xc0\xa9\xc0\xbf\x22\x85\x7e\xa4\x05\x33\x3e\x08\x24\xdc\xf3\x14\xc3\xa2\xee\x12\xc2\xf2\x3e\x3d\x19\xc1\x26\x79\x15\xfd\x37\x29\xe2\x9f\xc1\x02\xdc\x81\x53\x3a\x37\xf2\x81\x06\x62\x35\x43\x5d\x4e\xda\x88\x87\x50\x33\xfe\x7f\x2f\xf1\x28\xca\xfd\x07\x5f\x9a\x20\xa2\xb2\x7f\x28\x2e\x07\xe4\x62\x87\x3a\xa8\xe3\x9d\x8c\xa8\x65\x19\x39\x2e\x70\xeb\x75\x23\xaf\xa8\x7f\xde\x55\x8e\x88\xaf\xfd\xd4\xb8\x2a\xc4\x8d\x4c\x5a\x42\x52\x17\xbf\x45\xa7\xb1\xbf\x7a\xf7\xa4\xe3\xf2\x72\x8a\xec\x8d\x6d\x14\x33\x29\xc7\xaf\xc2\x4c\xf0\xdc\xd8\x7b\xda\xb7\x16\xff\x73\x9e\xe1\x3e\x18\x20\xd0\xf4\x1c\x47\xad\x02\x12\xb6\x2f\x45\x6f\x9f\xc1\xc2\x6e\x3c\xb3\xc4\x3c\x49\x50\x46\xc6\x57\x5d\x1b\x48\xc3\xe0\x55\x82\xb0\xc2\x8c\xda\xf4\x02\xf9\x9a\xa5\x9d\x32\x32\xa1\x15\x25\xdc\xfe\xc7\x51\x4c\xcc\x57\xb2\x05\x58\x6c\x96\xf4\xc3\x26\xee\xc6\x4a\x39\x98\x43\xca\xc5\xf5\x26\x19\x8c\x1c\xe6\xa6\xc3\x01\x74\x8a\x5a\x04\xfe\x1e\x5b\x76\x85\x4c\x2e\x2a\xcc\xf2\x76\x3c\x17\x29\xa9\x3f\x43\xe0\x8c\xa3\xdc\x5a\x37\xb5\xb4\xd4\x34\xc9\x00\x62\xd5\x83\x97\xec\x24\x92\x15\xa3\xc8\x74\x46\xe4\xe8\x55\xf0\x5b\xaa\x19\x07\x65\xb6\x18\x59\xcd\x33\x97\xf6\x51\xcc\x97\x7e\x0b\xfb\xdd\x18\x1b\x6d\x10\xdc\x11\x05\x69\x9f\xa0\x06\x04\x81\xed\x42\xef\xb4\xad\x4a\x26\xbf\x06\x57\x93\x33\x76\xe1\xe3\x87\xf8\x14\x52\xdc\x14\xd9\xc4\xde\x5b\xb1\x2d\x74\xa7\xb4\x5b\x87\x4a\xf7\x6e\x3f\xc2\x26\xbb\x1a\x60\x69\x3d\x0c\x1a\x7d\x94\x09\x54\x51\xa0\x2c\xcb\x5a\x78\x55\x11\x5b\x15\x4d\x52\xeb\xd5\xc2\x1b\x49\x83\x45\x0d\xac\x15\xb0\x99\xe6\x41\xa7\xe1\x2a\x94\xbb\x27\x2e\xb4\x06\x66\x24\xde\xd1\xef\xc5\x14\x30\x26\xe5\x68\x7d\x4b\xc0\x9b\x4e\x2b\x9e\x38\x74\xd4\x1b\x8b\xba\x26\xe9\x70\xf6\x57\x48\xc0\xe9\xa7\x51\xc2\xd2\xc8\x34\x33\x0a\x92\xd2\x5d\x7e\xea\x27\xae\xb4\xc7\x20\xe2\x17\x7b\xb6\x76\xf2\x82\xef\x5f\xb3\x64\x3d\xea\x17\x46\xe1\xb5\x41\x0d\xc9\x5e\xa5\xfc\x13\xe3\x9f\xbf\x66\x74\xf9\x5c\xba\x20\x3f\xf4\x89\x39\x96\x43\xc1\x16\x94\x90\x0e\x3a\xa9\x1c\xf3\xe0\xf0\x4f\x91\x08\x5b\x93\xde\x39\x34\x25\x84\x36\xb8\x83\x20\x2d\x4c\xc2\x4c\x8f\x64\x07\xfc\x68\xf6\xe0\x85\x21\x91\x0c\x15\xcb\x31\x0e\x54\x1a\x79\xdb\x95\x22\xde\xf0\x66\xe8\xf4\xca\x63\x88\xc6\x52\x9b\xed\xc6\xa6\x5b\xbb\x5e\x41\x67\x58\x34\x53\xb0\xd1\x7c\xc9\xb9\x23\x1a\xcf\xaf\x1a\xf3\x69\x8a\xfa\xbd\x1b\x82\xb4\x8a\x96\x98\x04\xc4\x59\xb8\x69\xd9\x8b\x54\x4b\xbe\x7a\x4f\x27\x19\x01\x99\xc9\xf5\x54\x1b\x92\xb8\xc1\xf8\xd9\x4a\x25\x4e\x57\x26\x6f\x10\xc4\x9b\x11\xdc\xe2\xf5\x05\x89\xd3\xd6\xc2\xc3\xe4\x43\xc5\x05\x1b\x4f\x3c\x9a\x96\x31\x4a\xee\x7b\xe5\xb5\xd7\x0b\x3e\x31\x3d\x5b\x4f\xe5\xf9\x44\x23\x9d\x46\x85\x34\xd0\x64\x10\x6a\xd4\xab\x39\x86\x42\x17\x05\xf2\x1e\xe2\xbd\xab\x56\x07\x0a\x05\x72\x1c\x0d\xcb\x4a\x3b\xce\x62\xd0\x27\xd6\x51\xc4\x12\x33\x12\x13\xa7\x08\x8b\x10\x70\x23\xc4\xa0\x8e\x27\x65\x17\x38\x57\x9a\xe1\x10\x1a\xe9\x51\xa4\x12\x93\xdf\x5b\x8a\x62\x6c\xca\x21\x7e\x53\x17\x78\x50\x97\x46\x09\x5a\x9d\x4b\x7a\x99\x45\x8c\xbd\x7d\xbb\xd9\x65\x74\xe9\x79\x31\x00\x66\xe2\xfc\x64\x17\x97\x4b\xef\xb6\xcd\x44\x01\x94\x1c\xb5\x2c\x0b\x49\xf5\xcf\x87\xc7\x53\xb2\x16\x4f\xa9\x4c\xe7\x98\x0e\x00\x0d\x83\xd6\xe6\xe3\x73\xeb\xb9\xdf\x77\x85\x99\x2e\xb5\x96\x8f\x08\x1d\xee\x79\x53\xbf\xf7\xaa\xdc\xc2\x22\x00\x8e\xce\x61\x3f\x6e\xfe\x92\xdc\x5a\x4e\x16\x5a\x1d\x1a\xe7\x49\xc1\x71\x00\x13\x1c\x2d\x52\x38\x16\xa7\xc6\xd0\xd1\xdb\x79\xd8\xc1\xc3\xc1\xbc\x62\x9f\x65\x67\x98\x4a\xba\x8f\x91\xf1\x1f\x85\x83\xba\xee\x5a\x09\x95\x74\xca\xea\x99\xd1\x13\x7d\xe1\x51\xe9\x55\xf2\x6f\x2f\x70\x30\x4b\xd6\x6e\x38\xe7\xce\xfd\x11\x84\x72\x22\xb7\x98\x4a\x6b\x0c\x4c\xf3\x35\x07\xa7\x2b\xfd\xd4\xf0\xa3\x98\x27\x59\x67\x76\x26\x4d\x51\x07\xb4\x2f\x73\xf4\xa8\x8a\x56\x07\x11\xc8\xa0\x3e\xb2\x38\xa1\x79\xb1\xaa\xa0\x6b\x92\x2f\x0f\x87\x6d\x08\x45\x62\x6b\x53\xe7\x1a\x44\xe4\xf3\xa6\x97\x77\x89\x31\xf2\xe3\x4d\xec\xff\xda\xb1\xe2\x90\x5c\x7a\x48\x88\xc4\xa4\xb6\xd8\xd4\xed\x8e\x8a\x30\x9c\x95\x1e\x24\x88\xdd\x31\x14\xdc\xf5\x6c\x62\x2e\xc8\x30\xa0\x6a\xaf\x20\x24\x8e\x59\x2b\x73\x5c\x73\xc6\xd5\xeb\xbf\x40\xa6\x53\xf2\x3f\x2d\x48\xb3\x0b\x83\xef\xd6\xfd\x06\x14\x2a\xf6\x4a\xa2\x38\x06\x85\x11\xd5\xdc\xcd\x68\xde\xcb\xca\x9b\x4a\xf7\x68\xb1\x63\x7b\xc1\x56\xdb\x20\x8b\xb5\x8d\x56\x3f\x48\x3f\xd5\x01\x84\x52\xdb\x8d\xa9\x50\x63\x90\xaf\x8e\xe4\xac\xd7\xe4\xa5\x1e\x3a\x79\xf8\x71\x61\xa8\xd0\xfe\xb2\xcf\x16\x4c\xfa\x18\x3b\x3b\x7b\x23\xfd\xfc\xd2\x12\x07\xc7\x25\xa5\x6f\x33\xe5\x18\xb6\x04\x51\x17\x79\x3e\x9f\x5b\x5c\x32\x55\x5f\xbc\x08\xb9\x14\x21\x62\x1d\xe7\xd9\x50\xed\xe2\x47\xad\x95\x0e\xe4\x35\xc0\xdc\x87\x52\xaa\x2e\x31\x92\x00\x36\xd6\x4f\xc4\xcc\xfe\x74\x8f\x74\xe2\x91\xef\x16\xfc\x35\x65\x0b\x4b\x96\x21\xc3\xc9\x0e\xdf\xb8\x64\x50\x20\xbd\x45\x0b\x26\x4d\x13\x8c\x66\x73\x88\x64\x56\x80\x8a\xbf\xdf\x82\x75\xd3\x66\x2a\x07\x46\xaf\x98\x78\xfe\x9e\x01\x36\xd5\x4d\x63\x2a\x39\x7f\xb7\xd7\x68\x73\x73\xd2\xfd\x18\x73\xc9\xbc\x5d\x82\x35\xbb\xce\x96\x81\xf4\xbd\xed\xd1\xba\xcb\xd3\x1b\x07\x14\x82\xf0\xd4\x61\xcf\x53\xe3\xa2\x63\x70\x18\xbf\xf4\xde\x7f\xc6\x70\x2f\xb6\x3b\x46\xc5\x2c\xca\x2c\xe5\xd9\xa2\x20\x5a\x8e\x9d\x04\x8e\x7d\xe6\xa4\xed\x9d\x41\x38\x64\xba\x14\x3a\x21\x55\x52\x3f\x63\x6b\x10\xe5\x2c\x16\x02\x2a\x7e\x2d\x94\x6a\x5c\x33\x32\x55\x23\xfb\xff\xb9\xba\xb2\x34\xc5\x75\x25\xbd\x17\x5e\xea\xe5\x6e\x4a\x1e\xc0\x4e\x6c\xcb\xc7\x03\x14\xb9\xfa\xd6\x3f\x84\x4c\xf5\xed\xfe\x0e\x82\x24\x29\x12\xac\x50\x0c\xff\xf0\xc5\x01\x1a\x7d\x65\x85\x4c\x00\xe9\xcd\xaf\x80\x00\x0d\xfa\xf7\x65\xb9\xc6\x05\x30\x5b\xf2\xf6\xad\x3d\x96\xb8\x96\xe2\x6c\xe2\x3c\xda\x4e\x74\xfa\xc4\x07\x7e\xc4\x93\x68\x04\xcf\xd1\x3d\xf9\x1f\xc0\xb5\xdc\xdb\x10\xa1\x15\xa2\x90\x0a\x7b\x53\xb4\x54\xb0\xa9\x25\xfb\x45\x53\xe0\x80\xf2\xb7\x17\xb0\x94\x99\xf2\x54\x4d\x7a\x5f\x29\x6a\xf4\x0e\x26\x17\xee\x97\xad\x55\x75\x14\xe2\x60\x5c\x5a\x7d\x9d\x61\xe7\xb3\x0a\x88\x48\xcb\x21\x7e\x94\x4d\x4e\xb5\x4f\xd0\xd4\x19\x70\x6a\x95\xdb\xa4\xb6\x1d\xab\x7f\x11\x0e\x00\xc9\x8b\xdd\x84\x21\x26\x71\x70\xaa\x34\x15\xc6\x1b\x7c\xe2\x2e\xa2\xb9\x99\x80\x7e\x55\x62\x73\xcd\x59\xc6\x2d\xac\x3e\xfb\x52\x40\x5a\xe1\x00\x5f\x2e\x23\xcf\xc2\x92\x73\x9f\xd1\x74\x55\x83\x2d\x2a\x1d\xe0\x88\x79\x7d\xb8\xb7\xb4\xc5\xa4\x79\x1b\x0d\x74\x51\x65\xa2\x1a\xa8\x24\xa8\x86\xa4\x0a\x59\xaf\xc6\xc4\x7a\x5a\x13\xc0\xb8\x7a\x5d\x27\x6d\x78\x4d\x80\xdc\xef\xd6\xfc\xaa\x4b\x34\x82\x91\x9a\x34\xe3\x86\x61\x46\xf8\x05\xe2\x0a\xd0\x59\xcf\x02\x5b\xbb\x99\x89\x71\x17\x56\xea\xc1\x32\xc7\xb0\xf5\xd4\x04\xd6\xfd\xe8\x69\x6c\xb6\x68\x1b\xff\xf8\xb8\x00\x5a\xb9\x02\xdd\xa1\xa1\x27\xe2\x08\x7f\x34\xcf\x76\xff\x85\xa7\x98\xb4\x29\x1d\x46\xd9\x97\x37\xb2\xa9\x7c\x20\xb3\x7a\x73\x49\x1d\x79\xb5\x9f\x19\x7d\xfa\x40\xe6\x44\xea\x7a\x4f\x7f\x75\xa0\xfe\x3d\x2a\x00\xb6\x64\xed\x15\xb2\x57\xc9\x02\xf2\xd1\xc9\xef\x25\x38\xb8\xdd\x68\xb4\xbe\xfd\xba\xb6\x00\x9f\x43\x79\x3c\x0a\x6e\x34\x09\xe2\x34\xdd\x04\xb5\x4c\xfb\x99\x02\xb4\xd6\x7c\x1e\x39\x1a\x40\xbf\xbf\xd1\xaf\xdd\x02\xa2\xea\x4e\xac\x9c\x5b\xa2\x0d\xaf\x73\xd3\xcd\xe8\x77\xaf\xc0\x70\x61\x12\x38\x19\xb5\x5d\x31\xa9\x99\x1e\x55\x1f\xd1\x65\x86\x5c\xab\xcc\x0c\x21\x02\x15\x13\xde\xa3\x5f\x65\x6e\xae\xd8\xf4\xa5\x3f\xaf\xcb\xad\x3e\x02\x2d\xe2\xcd\x6c\xea\x52\x63\xc6\x20\x38\x5a\x7c\x67\x24\x5c\x59\x57\x0e\xda\x42\x65\xfb\xde\x42\xfa\x47\x5c\x71\x68\xe7\xc9\x01\x7a\xac\xf9\x46\x49\xb8\xfd\xca\x73\xbf\x05\x16\x09\x76\x32\xea\x90\xcc\xb0\x70\x9b\x54\x22\x94\xf4\x15\xcd\xdb\x53\x47\x93\xc3\x0a\xb5\x11\x74\x1a\x95\x5c\x2a\xc4\x83\xfa\xc5\x6d\xc1\xa1\xfe\x09\x8f\xbe\x67\x09\x4e\xb0\xb7\xa6\x73\xc6\x76\xf9\x8b\xf7\x88\xa6\x14\xfd\x1e\xcc\x6c\x2a\xd1\x14\x9a\x41\x24\xba\xa9\xc4\xbe\x49\xe0\x23\xb2\x55\x1e\x42\x02\x1e\x4f\x7d\x53\xfd\xb5\x49\xfe\xd4\x35\x92\x6c\xdb\x17\xa2\xe5\xfe\xea\x3b\xdb\x0d\x96\xf4\xc7\x85\x16\x34\x3d\x2f\x67\xe7\xb4\x3c\x5d\x41\x55\x46\xc7\xf1\xa9\x03\xb8\xb1\x01\xbe\x66\x64\xa4\xa9\x02\x0d\x80\x92\x3a\xc4\xb0\xa9\x51\xe1\xc8\x4b\x50\xb1\x4b\xb0\x35\x2f\xa7\xff\x1b\xce\xd5\x25\x32\x18\x49\xb1\xb7\x97\x26\x64\xa9\xa9\x30\x18\xf5\x64\xee\x6d\x2f\xbf\x12\x52\x50\x3d\x05\x71\x47\xa7\x1e\x29\xb5\xbe\x00\xda\xfa\x51\x02\xb5\xcf\xc4\x7a\x43\x5d\x72\x23\x9f\x84\xfb\xb8\xd4\x51\x75\xc0\x52\xd6\x5f\xf6\x45\x8c\x2c\xc2\x40\x19\x07\xed\x41\x70\xa9\x87\x3d\xb4\x6b\x43\x8c\x71\xea\x3d\x01\x0e\xde\xc1\x94\xaa\x23\xcb\x94\x42\x77\xb2\x1c\x50\x25\x4a\x58\xb9\xf4\x0c\xb6\xd5\x0f\xf7\x87\xcb\xfd\x64\x60\x30\x44\xfe\xcf\xf5\x8a\x41\xd6\x57\xc5\xa1\xf4\x70\x24\xa0\x08\x42\x1b\xa0\x89\xc7\xe4\xe6\xe8\x03\x2f\xa7\x3c\xc7\x20\x62\xbb\x1b\xc4\xdc\xd7\xad\x1a\x1c\xac\x67\xc4\x91\x7d\x0d\xdb\xb3\x1d\xe3\x08\x2b\xe0\x3d\x94\xc0\x0f\x51\x2b\x74\x1a\x66\x97\x3a\xad\xb7\xfa\x57\x49\x0b\xce\x2a\x22\x08\x5b\x38\xf5\xce\x61\xbc\x11\xd8\xe4\x50\x02\xe3\xc5\x57\xb2\xa4\x29\x62\x0c\xfe\xea\xfb\xe4\x28\xd4\x3b\x48\x2b\x2f\xdf\x28\x43\x78\xa3\x7e\xe4\x1e\x3d\x4c\x52\xbf\xaf\x0b\x72\xd2\xcc\x23\x8a\x8b\x5f\x0c\x97\xd4\x0a\xe0\x25\xc8\x93\xa2\x54\xf9\xda\xcf\x07\x1b\xf8\xd0\xd2\xbd\x5a\x40\x21\x93\x0d\x62\x9b\x35\xb5\xd6\xb2\x0d\x2b\xd2\x68\xaf\x72\x0b\xbb\x58\x35\xe5\x3b\xbe\xd2\xc5\x4b\x47\xfb\xd2\x79\xd8\x6b\x7f\x6f\x8e\x5e\x12\xca\xca\x9c\x62\xe4\x17\xec\x9e\xb0\xbf\xf5\xb9\x55\x51\x90\x4c\x92\xca\x21\x90\xef\x12\xd4\x5c\x95\x10\xbd\xbf\x21\x45\xf2\x96\x73\xbe\x44\x58\xc3\xa6\x16\x72\xee\xd4\x04\x80\xcb\x8f\x0a\x42\x31\x5e\xf7\xdb\xb7\xb7\xfb\x35\x4f\x8e\x91\xf9\x38\x7f\xd1\x2c\x70\xa7\x0d\x81\xbb\xb1\xc5\x7c\xb7\x24\xa8\x36\x59\x1f\xac\x33\xd1\x73\xc6\x02\x3c\x49\xc8\x4d\xc8\xa5\xd9\xc1\x6d\x0b\xf0\xc9\x23\x84\x2e\xa0\xcb\x8f\xf9\x4c\x5c\x7a\x8f\x73\x0f\xd9\x0d\x57\x89\xbd\x26\xdc\xb7\x6f\x8c\xe6\x78\x79\x99\xc7\xa9\xf6\x3b\x86\x33\xe5\x12\xd4\x4c\x39\xbf\xfb\x84\x53\x11\x40\x77\x93\xbe\xea\x64\x96\x38\xa2\x7a\x8f\xa6\x08\xce\xbb\x11\xa8\x5c\xab\xe0\xa4\x1c\xa3\x3a\x9c\x6c\x30\x72\xf1\x5a\x79\x95\x49\xbf\x6f\x59\x4c\x6d\x00\x7e\x46\x07\x23\x87\xd2\xbc\x54\x3b\x28\xf0\x79\x77\x8b\x95\xb9\xc5\xca\x9f\x67\x00\xf1\x95\xd4\xa9\x83\x7d\xfb\x9f\x9d\x4a\xa4\xef\x25\x48\x11\x28\xe7\x25\xf6\x24\x23\xde\x26\x5f\xcc\xe5\x63\x5d\xdd\x54\x39\xc2\x6f\x1c\xc4\xc5\xf0\x05\x01\x2f\x62\xab\x1d\x2c\x5e\xe5\x5b\xb6\x32\xfa\x91\xb3\xfa\xa1\x25\x1a\x59\xa7\x49\x43\x70\xf2\x7a\x14\x6f\xcf\x29\x5c\x92\x09\x5b\xc6\x6d\x8c\x94\x30\x12\xd9\x2a\xf2\xa6\xe4\x37\xad\xc1\xc6\x22\x8d\xb9\x97\x61\xa5\x17\x5e\xe9\x52\x09\x88\x51\x5b\x77\xfb\x9e\x98\xf0\x27\xc0\xd1\x8b\xfa\x37\x7d\xb5\x3c\x17\xe4\x36\xed\x44\x10\x3c\x91\x5c\x92\x4f\x80\xf3\xd8\x10\xc4\xaa\xc0\x6d\x00\x2e\xe9\x90\x4c\x8c\x9d\x99\xe5\xe3\x9e\x00\x62\x70\x7f\x83\x1a\xc8\x2e\x17\x47\xda\x5f\x9d\x84\x83\x0d\xa7\x8d\x9c\x6c\xec\x7d\x1f\x0d\x5d\xb8\x13\x61\xcf\xab\x32\x6b\xda\x61\xae\xb0\xc8\x66\x1e\x8e\x87\xad\xe8\x1c\x96\x17\xba\xc2\xcb\xe5\xac\x76\xf6\x76\x5e\x80\x55\x2b\x32\x34\xb5\xf7\x31\x55\x8c\x1d\xa2\x61\x04\xca\x68\x8c\x0f\x94\xfe\xad\x40\xae\xf8\x71\xdf\x3e\x6d\x2c\x59\x12\xb8\xc1\x92\x68\x38\xcf\x55\x42\x4c\x9a\xc4\x69\xbe\xa2\x4b\x2f\x34\x9c\x61\xa9\x1b\x2d\x87\x34\x29\x6c\x9a\x05\xa9\x0f\xe9\x93\x34\x9d\x33\x86\x0c\xee\x9b\x0a\xa0\xc7\x39\xd6\x06\x99\xf7\xba\xcc\x9c\xb5\xaf\x8f\x5c\x2e\x0f\x8f\x4f\xda\x18\x9c\x96\x65\x76\x3f\x63\xdc\xcc\x53\xdb\x57\xf9\x5d\xd1\xc1\x53\xb1\x16\xfa\x72\x92\x2f\x8c\x6c\x40\xd3\x35\x37\x35\xca\xb7\x13\x57\x1b\x8d\xdc\x74\x05\xf1\x50\xf5\xe1\x7e\x84\xcd\x99\x98\xa5\x96\xf2\xc3\xdb\x5a\x4a\xb9\xeb\x77\xb8\x94\xc3\x3c\x6d\x82\x03\x62\xcb\xdf\xcf\x90\x49\x9a\x47\x7b\x71\xcd\xde\x67\xcf\xcf\x92\x76\x35\xe8\x9e\x8b\xf6\x4f\x39\xcc\xd5\x08\x86\xd1\x69\xb5\x7f\x8e\x6a\x31\x8e\xf5\x52\xd7\x4c\x1e\x7b\x97\xb2\x91\x87\x71\xee\x6a\x2a\x7b\x87\x54\x9c\x4e\x54\x28\xaa\xda\xe4\x55\xbd\xb6\x9b\x9c\x87\x97\x36\xde\xff\x7d\x0c\xb3\xd5\x3b\x00\xcf\x46\xea\x1a\x31\xd7\x7d\xf6\x28\x46\x93\x06\x78\xda\xd3\xd2\xde\x7a\xd4\x1a\x9f\xb2\x50\x56\x2b\xbb\xf7\x15\xb9\x71\x86\x03\x4d\x6b\xfa\x91\xc1\x1c\xbf\xba\x2a\xbf\xf2\x8d\xe8\xbf\xe6\x0a\x3f\xd4\xe1\xd0\x5a\x6e\x99\xbe\x5a\x35\x9f\x23\xc7\x4d\xc7\xfb\x64\x36\x49\xb3\x55\xbc\x0d\x26\x64\xee\xd0\x8e\xdb\x31\x98\x28\xd9\x90\x75\xdd\x04\xa0\xa5\x41\x8b\x42\x90\x60\x36\xf5\x0c\x86\xbf\xe6\x7f\x37\x07\x5f\x5e\xb9\x54\xc7\x0d\x6d\xfd\x81\x43\xe2\x72\x53\x2e\x8c\x97\x9d\xd7\xf0\xd6\x8c\x42\x60\x1f\xa5\x6a\xc3\x97\x4f\xcf\xa9\xbe\x79\xcf\x5a\x52\x83\x22\xcc\x0a\x76\xa8\xfb\xf0\x0a\xc5\xeb\x45\x8b\x2d\x94\xd8\xff\x9f\x23\xf9\x7f\x92\x92\xd3\xe0\x9a\xaa\x9a\xda\x96\x40\xdd\x87\xbe\xe6\x16\xa0\x01\x78\x6a\x54\xb1\x23\x66\x52\xca\x46\xaf\x95\x12\x4f\xaa\xf0\xb4\x82\x08\x95\xd0\x28\xb8\x09\x8b\x96\x85\xd1\x5e\xa5\x4a\xed\x87\xe0\x5e\xda\xda\x90\x3e\x54\xe5\x0e\xcd\xb7\xb2\x35\xb3\x12\xd9\xae\x9b\x62\x04\x0d\x5d\xb2\x5d\xb0\xd7\xfc\x34\xfe\x55\x7d\x36\x95\x75\xd7\x0c\xca\xd0\x43\xd2\x2f\xbc\xe6\x00\x56\x66\xbf\x20\xe0\x5a\x30\x62\x48\x9f\xda\xfc\x78\xc0\x12\x51\xfd\x29\x5a\xc2\xba\x90\x99\x5e\xa6\x4d\xee\xe5\x80\x69\xbc\x37\x41\xa7\xc2\x09\xe5\x0c\x60\x8d\x0a\xb3\xe3\x97\xeb\xe6\xf0\xb6\xd5\x52\x1c\xc8\x73\x3f\x3a\x35\x51\xd3\xf6\xbd\x5b\x6b\xa4\xad\xa8\xad\x82\x84\xc9\x69\x65\x15\xe4\x6b\xd2\x6e\x69\x48\x9b\xdd\xa8\xca\x39\x04\x46\xd4\x64\x03\x9c\x76\xee\x0c\xb6\xd3\xf0\xf3\x73\xdd\x15\xdf\xce\xe5\xd2\xf0\x38\x46\xe6\xa6\xfb\x1b\x2d\x6b\x56\x34\x6f\x6e\x51\x5e\x4c\x6f\x9d\x9b\x1c\x15\xb8\x73\x12\x79\xe3\x8d\x35\xcd\xb4\xb2\xb9\xbe\x55\x84\xc1\x91\x4b\x25\xe5\x66\xc8\x1a\x67\x26\xdc\x54\x9d\x0e\xc2\x23\x56\x07\xa6\x3b\xd3\x20\x58\xf2\x1a\xe2\x80\x4f\xa3\x02\xd1\xe9\x1b\x8b\xf3\x39\xfd\x1b\x82\xb4\x33\x9f\xd3\x5b\xda\xff\xc6\x22\x5d\x57\xc3\x97\x55\xe9\xe4\x73\x7a\xd2\x1e\x9d\xaa\x25\xcd\x53\xf8\xf9\x67\x8f\xff\xfe\x28\xa2\xcb\x31\xd6\xc5\x34\xcd\x26\x16\x22\xd2\x3c\xae\x9c\x23\xd3\x44\x45\xaa\xe8\x51\x2e\x8c\x6e\x18\x6f\x55\x21\xd6\x60\xb4\x90\x80\x05\x7a\xa1\x9a\xc0\x7d\x9b\xd4\x54\x49\x1f\x27\x8f\x54\x23\xaf\x26\x0d\xf6\xf9\x8e\xc1\xe3\xf6\x31\x91\x87\xc4\x5c\x23\x99\x60\xea\xea\x0b\xc7\x72\xf9\x21\xf2\x55\x63\x58\xe7\x32\xb9\x4e\x43\x1d\xc2\xf8\x0d\x36\x3d\x1c\x51\x5e\x42\xac\x05\x6b\x4f\x2d\x11\x5b\xb6\x71\x6c\xa0\x39\xa5\xba\x63\x36\x86\xe6\xe1\x5a\x5e\x91\x20\x98\xf7\x07\x80\x7a\x5b\x88\x2b\x74\xbf\x72\xc9\xb5\xd1\xed\x62\x07\xa5\x65\x97\xe4\x9c\xa8\xee\x53\x52\xc9\xeb\x60\xd5\x25\x75\x97\x16\xfe\x24\x2a\x3b\xf9\xe3\x01\x60\x5d\x46\x33\x1f\xfa\x47\x35\xd5\x7a\xf5\xd3\x97\xee\x5c\x39\x7a\x0d\xc7\x2a\x5f\xf9\xea\xcb\xed\x16\x44\xbf\x68\x9e\xb0\x64\x8e\x6c\x2d\xd4\x99\xd7\x3c\x7d\x38\x9a\xba\xb1\x13\xc7\xdf\xea\x17\xef\x31\x81\x3f\x0c\x00\x83\x8e\x6c\x95\xc3\x84\xae\xae\xd0\x8d\xbd\x10\x07\xec\x9d\x85\xa3\xe1\xf1\x09\xae\x97\x82\xfd\x34\xda\x61\x6e\xea\xef\x47\xb6\x16\xc3\x4f\xb6\xf3\xc4\xcf\x38\x7b\x02\x3c\x7e\x95\xca\x8c\x4a\x73\x15\xb0\x18\xaa\x82\x51\x09\x4f\x4c\xd9\x06\xff\xfa\x00\xb4\x4c\x5e\x83\xf4\xd9\x7b\xac\x99\x2a\x8b\x79\x3b\x9a\xcd\x9a\xd4\xe5\x38\x47\x77\x85\xd3\xaf\x20\xdf\x6a\x88\x30\x85\xed\xde\x1d\xa8\xc3\x41\x73\xf5\xfb\x18\x0e\x1a\x6b\xed\xf8\x83\xe9\xec\x5e\xf0\x3d\x3c\xba\x5a\x20\x96\x63\xe4\x85\xe6\x4b\x5c\x9c\x55\x2d\x13\x50\x8a\xda\xc8\x09\x3d\x03\x55\x30\x53\xf8\x90\x0c\x62\x61\x35\x25\x3d\x72\xda\x97\x3a\xcf\x12\x42\x46\xa1\x01\xe9\x89\xe3\xbe\xb4\x92\x4a\xba\x94\xf8\x64\xbf\x96\x98\x4c\xa7\x80\xb0\x38\xbd\x7e\x4b\xba\xe9\x1d\x22\x0d\xef\x5e\xe4\xb7\x12\xd8\x9e\xb5\x4b\x54\xc5\x57\xa2\xcd\x97\xab\x06\xab\xfc\x1b\x7c\xc6\xfe\x63\xfc\x74\x78\xa6\x7b\x94\x78\x26\x76\x36\x2a\x04\x71\x45\x89\xb4\x71\x4d\xba\x9f\x0d\x74\x99\x16\xaf\x47\x0f\x2b\x92\x89\xdc\xa1\x50\x42\x61\x8b\x9b\x81\xba\x77\x6b\x71\x2d\x34\x7a\xd9\xab\xc4\xdf\xee\x1e\x77\xab\x0e\x3f\x28\xdf\xfa\xe2\xb9\xa7\x5d\xb7\x8c\x1c\x2e\xdc\xe8\x80\x8f\x67\xff\x77\xff\x3b\xff\x48\xcc\x65\xb5\xff\x1b\xe6\x65\x51\xa2\x57\x60\xec\xca\x3a\xa1\xd3\x1e\x68\x05\x74\xa2\x48\xe8\x47\x43\xb6\x45\x06\x76\x33\x4e\xf3\x08\xb3\xcf\x3e\xbf\x4c\x58\x46\x02\xab\x68\x9b\x03\x9b\x53\x2a\xa5\xcf\xe2\x2a\x12\x34\x31\xb3\x80\x5a\xf4\x63\x71\x81\xef\x41\x0f\x90\x36\xe0\xcd\x0a\xcc\xba\x74\x2d\x43\x7d\x13\x83\xce\xff\xcc\xc3\x46\x3f\x48\xe2\x6c\x86\x60\x7f\x0d\x20\xac\x84\x6f\x06\x5a\xc2\x0d\x17\x57\xe4\x2e\x63\xb6\xa0\xff\xa4\x98\x58\xf9\xca\x03\xfa\xac\x8d\xb6\x49\xd9\x2e\xa9\xfb\x72\x2d\xdb\xd8\x23\x69\x28\x37\xe2\x87\x92\xcd\x10\x9c\xb1\x09\xd1\x33\xf9\x54\x14\xd3\x56\xe8\xd0\x7f\x04\xa5\xa0\x65\xad\xbc\x6c\xea\xc3\x05\x61\xfc\xeb\x46\xe6\x3e\xa8\xca\xd9\xad\x36\x40\xf7\xf3\xc4\xaf\x73\x37\x45\xe4\x20\x7a\xba\x7c\xa9\x2a\x0e\xca\x39\x6c\xa7\x8d\x89\xd9\x6e\xf2\x3c\xc1\x8c\x3b\xe4\x64\x91\xf9\xad\xf1\x85\xe5\xf3\x90\x6b\x49\x89\x22\x5e\x34\x55\x33\xbb\x7c\x3a\xaa\x39\xdd\x1e\xd4\x89\xf9\x8e\x17\xf9\x21\xfd\xbd\xf6\x5c\x10\x45\x53\xa5\x9f\x1f\x1a\x63\xdc\xbe\xd9\x7a\x0c\x35\x25\x63\xe1\x5c\xe2\x31\x29\xd5\xba\xc6\x7e\x3e\x2c\x7d\x67\xea\xd5\x4e\xc1\x48\xdf\xdf\xd7\x4b\x29\x93\x28\x1b\xfa\x02\xaf\xba\xb3\xbc\xe9\xe8\xec\xb8\x57\x17\x33\xf7\x4b\xdd\x1a\x87\x6b\x05\xc2\x03\xc5\x63\x23\x90\x4c\x11\xd5\x8b\xfe\xaa\x6f\xdd\x69\x09\xf4\x8b\xe3\x6b\x3e\x86\x8b\x1c\xcc\x41\xfb\x8d\x70\xd1\xad\x37\x76\x20\xc9\x2b\x90\x23\xad\xdd\x22\xa0\x89\x3b\xdf\x7a\x98\x72\xca\xe4\x53\x4b\x26\x31\x31\x72\x97\xeb\xf6\x29\xc6\x8c\x54\xa6\x83\x3a\xb6\x55\x22\xa8\x6d\xb3\xae\xcd\x55\x76\x11\x0f\x4a\xfb\x8f\x84\xf8\x85\x40\x38\xae\x48\xa7\xe7\x37\xf0\xab\xb6\xfd\xda\x3e\x44\xc1\x4b\x14\x61\x30\x79\x3a\xa7\xda\x47\x9f\xab\x61\x1d\x81\x19\xba\xae\xb4\xf0\xc1\xb3\xe8\x7e\x34\xfc\x9c\xec\xd3\x7f\x40\x41\x64\x8e\x31\xf1\x8a\x0b\x26\x52\x3c\xb4\x97\x4e\xa7\x76\x5b\xff\x73\xda\xa3\x05\xea\x49\x39\x86\xee\x9c\x9d\x74\x8e\x30\x71\x04\xcf\xda\x03\xf3\x39\x9b\x98\xa4\x6a\x48\x45\xad\xf0\x3f\x63\x9d\x58\xcd\x3e\x01\xe7\x74\xd9\xff\x1f\x76\x2d\xdf\xcc\x66\x72\xee\x0e\x6c\xb6\x22\x92\xd0\x82\x37\x9a\x44\xf4\x31\xf9\xc5\x77\x58\x52\x4d\x09\xe0\x9d\xc6\x89\x80\x9c\xa8\x19\x23\xa5\x40\x70\xe9\x9e\x71\x5e\xe0\x57\x55\x02\x4f\xca\x65\xee\xd1\xcc\x80\x3f\xde\x7e\x0b\x9f\xbc\xa8\x11\xc6\xdf\x54\x25\xff\x89\x58\xd7\x58\x0e\x00\x93\xea\xc9\x32\xbc\x93\x69\x15\x12\x10\xf3\x29\xcb\x7c\x39\xc0\x27\xb5\x5c\xad\xa6\xf7\x3e\x7b\x79\xe5\xc7\x66\x78\x8d\x17\xc0\xc8\xde\xc8\x51\x58\x5b\x22\x32\x76\x4a\x95\x2b\xc2\x1d\x7c\x9b\x7b\x1d\x93\x3d\x9c\xba\x35\xa7\xf4\xb7\x44\x77\x6e\x00\xa2\x7c\x07\xd6\xa6\xb1\x16\x6f\x09\xac\xd2\x1f\x98\x68\xd1\x93\xee\x76\x8e\x7a\xa9\x35\x08\x2e\x97\x61\xe0\x09\xa0\x19\x95\xb7\x62\xcd\xdf\xe4\xb7\x59\x9b\x87\xe7\x22\xd6\xd5\xcd\xec\xa7\x8a\x67\x2a\x1f\xb9\x91\x6c\x30\x4d\xb4\xd5\x86\x6b\xa5\xc0\xb5\x6a\x53\x98\xa4\xb9\x97\x4b\x4f\xe7\x69\x0d\x32\x72\x90\x68\xed\x53\x1e\x03\x8d\x2b\xc1\x17\x1e\x0e\x2a\xef\xda\x18\x9e\xf5\xa9\x5c\xd6\xb9\x9b\x36\x6b\xd1\x56\xfd\x3d\x16\x3e\xb8\x2d\x5f\xb8\xde\x4d\x9a\xfa\xa0\x63\x58\x87\xda\x12\x09\x15\xaa\x2f\x8b\x16\xd7\x3e\x57\xdb\x90\x9a\xd1\x71\x6f\x4a\xd6\x64\x80\xac\xa4\x7f\x13\xa3\x70\x95\xd7\xa0\x65\x79\xdb\x06\xdb\xe6\x66\x77\x2c\x27\xa6\x3a\x83\xe7\x5e\x1a\x9c\xd0\xe1\xeb\x05\xc2\x9b\xdb\xf9\xdc\x04\xc6\xa2\x1a\xb3\x3b\x8e\x5f\xae\x1f\x73\x00\x77\xca\x77\xd5\x9f\x3e\xdf\x25\xe1\x09\x85\x21\x6e\xfe\x72\x30\x7c\x42\x06\x7c\x03\xb4\xfc\x2a\xaf\xa3\x97\xce\xb0\xbf\x89\xfa\x9e\x77\x15\x87\x0f\x0d\xa7\x09\x36\x08\xaf\x6f\xc0\x9d\xa6\x00\x7c\xb7\x97\x6c\x3c\xf8\x5d\x9e\xfd\xf7\xa8\x39\x25\x8c\x75\x59\x17\xf6\x2d\x87\xa9\x6d\x2c\xe5\xf8\x75\x4e\xee\x68\xe6\xcd\x1f\x1b\x27\x42\x97\x34\x74\x07\xd5\x6a\xe1\x5e\x1a\x19\x00\xd6\xce\x57\x7b\xf9\x37\xa2\x51\x1b\xc0\x85\x56\x4e\x35\xed\x64\x7c\xb1\x8c\x21\x3d\x10\x22\x40\x4b\x7b\xe6\x2b\x65\x08\x51\xa2\x26\x06\x23\x65\xaf\x94\x42\xdb\xed\xfa\x3a\x69\x4c\xe4\xb3\xd9\xbd\x3e\xea\x2e\x1d\x1d\x98\x7d\xd8\xd9\x9d\x26\x84\xdc\x68\x9d\x21\xd8\x12\x41\xe4\x43\xc4\x70\xdd\xa8\x70\xab\x9d\x75\x12\x53\x77\xae\x4e\x45\x4b\x12\xe2\x1d\x51\xbe\x6b\xde\xe4\x92\x31\xec\x9c\x19\x96\xf3\xad\x6e\x8e\x63\x10\x8f\x20\x5c\x00\xd8\x05\x85\x79\x0d\x37\x58\xf5\x39\xa4\x64\x8e\x6a\xe3\x92\x9d\xaa\xa5\xbe\x60\xcc\x84\x05\xe8\xfe\x15\x37\x1e\x29\x6f\x2f\x42\x74\x9b\xfd\xd7\xef\x61\x63\x9a\xe4\x6b\x65\xb2\x95\xb4\x24\x6e\xff\xbb\x6c\x2f\xab\x40\x21\x55\x1c\x32\x58\x01\x6e\x3c\x51\xbf\x8a\xff\x24\xa2\xb4\x39\x65\x6a\x85\x6e\x4a\xb0\x67\xa8\x1b\xbb\x83\x2e\x71\x26\x00\x23\x2a\x9f\x15\xf3\x4d\x7e\xcc\xcf\xde\x34\xeb\x9f\xfc\xc9\xb6\x53\x7a\xc1\x3a\xb6\xb9\x5c\x61\xb1\x61\x6f\xd6\xd8\x39\xeb\xe4\x59\x92\x3b\x5a\x41\x79\x48\x6a\x10\xf7\x34\xfb\x65\x18\x5d\xf5\xcc\xe9\x62\x9d\x96\x2f\xc5\x43\x4d\x0f\xd1\x4b\x26\xfb\x98\x2f\xa3\x55\x69\x21\xe9\xa0\x00\x39\x86\x7d\xac\x90\x85\xe3\x89\xb0\x19\xac\x6a\xe5\xcd\x9e\x95\xb3\xab\x31\xf7\xe0\xcc\x80\x52\x27\x34\x09\x8f\xd2\xae\x1e\x2f\xad\xee\x38\x95\x5c\x34\xec\x5a\xf3\xf2\x63\x8f\x2b\x1c\x0f\x4e\x92\x39\x66\x8f\x16\x6b\xda\xba\x90\x74\x68\x2a\x91\xa3\x99\x84\xe9\x9a\xc2\x12\x4a\xc2\xf2\x80\x23\xc9\xf3\x3b\x91\xd5\xa0\xb2\xcc\x06\x51\xae\x9b\x4b\x46\x02\xbe\xf4\xe6\x6b\x99\x3e\xb9\xd5\x52\xe5\x8d\xfa\x81\x68\xd6\x1b\x31\xcf\xea\x54\x22\xc1\xb6\xef\x55\x89\x63\xfc\x46\x5e\xc0\x0f\xf1\x22\xc3\x40\x4c\xc7\xc7\xe5\xa6\x54\x2a\xb7\x53\xa3\xf1\x63\xb3\x11\x6c\xb8\x92\x2a\x3b\x3a\x34\x68\xc2\xc6\x2c\xf1\x8e\xd7\x7b\xcd\xfa\x39\x50\x55\x66\x65\x8e\x96\xd3\xf4\xa3\xd4\x8d\xce\xb8\x94\xcb\x3f\x45\x00\xa2\xda\x68\xb4\xfb\xc9\x38\x7e\x79\xdc\xd4\xbf\xa5\xc0\x78\x13\xdc\x11\x6e\x97\x3c\x1c\x72\x18\x4c\x46\xed\x66\x0c\x7e\x00\x80\x25\xda\xe5\x4b\xfe\x5c\x43\x47\x9a\xa4\xaf\x98\x14\xf0\x44\xf3\x5a\x4a\xeb\x90\xe9\xb8\xac\x46\xdf\x3e\xb8\x78\xb6\xf0\x36\x1b\xa7\x54\xb1\x61\x6b\x8f\xba\x25\x49\xbf\x72\x72\x53\xad\xeb\xd4\x52\xdb\x62\x1a\x35\x86\x6e\x3f\x99\x7d\xc1\x40\xa4\x1b\x83\x76\x9b\xba\xff\xe2\x87\x07\x84\xf1\xa7\xb7\xaf\x4b\x10\xfc\x58\xe1\x7d\x1e\xa5\x38\xf0\xc4\x61\x85\x5c\x71\x0c\x5a\xd7\xfe\xbe\x9d\xa3\xc0\x45\xbf\x7d\x23\xcb\x25\x34\x63\x2c\x18\x66\x6c\x10\x1b\x6b\x3e\x01\xca\xc6\xc3\xc5\x60\x6d\x61\xff\x23\xec\x59\x70\x10\x65\xba\x4f\xd6\xa6\x48\x6d\x30\x00\xcf\x2a\x2c\x28\x9c\x63\x72\x6e\x44\x85\x88\x90\x1c\xbc\xb9\x9a\xb8\x7a\x9c\x25\xee\x73\x08\x4b\xfc\x1d\x9c\xbf\x04\x15\xb0\x76\x58\x9b\x20\xfa\xaf\xa9\x7c\x09\xc5\x2f\x49\xc0\xa6\xa9\xfd\x92\x5d\x85\x88\xa6\x60\x71\x99\x23\xba\x06\x6e\xb1\x1b\x79\xd7\xc9\xdf\xea\x2f\x72\x4b\x5e\xef\x0b\xca\x0f\xaa\x84\x18\x54\xf9\x06\x97\x58\xa1\x42\x7f\xb5\xfb\x70\x90\x5b\x8f\xe6\x16\x67\xa9\xaa\x54\x78\xd9\xc7\x75\x75\x80\x6b\xe6\x2c\x06\x0a\xab\xbe\xb8\x73\x40\xe5\x92\x65\xde\x25\x28\x17\x3a\xc4\x10\xe9\xae\x56\x41\x7c\x62\xae\x13\x1d\x8c\xfe\xa2\x13\x88\xa4\x49\xd6\x65\xb2\xc1\xb1\x81\x7e\xd9\x6e\x76\x15\xaa\x82\x80\xeb\xd9\x84\xe4\x16\x81\xf0\x36\xc8\xe9\x75\x20\xa1\x18\x68\x07\xbd\x93\x0c\x05\xc4\x87\x57\x74\x26\xbd\xd5\x9e\x70\xa7\xa5\xf4\xf9\x10\x1b\xe3\x7b\x9f\xf3\x05\xa4\x0c\xa7\xe7\x98\xac\x4d\x01\xd7\xaa\x42\x6a\x8c\xce\x95\xe1\x52\x3e\xf0\x3a\x14\xc4\x68\x07\x45\x62\x95\x41\xc0\x5a\xd1\x64\x38\xe7\x48\x57\xe8\x2e\x68\x6c\x00\x84\xfc\x8d\xc2\xdd\xe6\x40\x94\x57\xe5\x57\xb4\x7d\x55\x65\xab\x87\xa4\xeb\xf5\xe1\x63\x26\xe4\x67\x19\xf6\xa7\x50\x8e\xed\xb6\x52\x8b\xd8\x55\xa7\xcb\xbb\x3e\x0b\x58\xd8\x8a\x4b\x2c\x37\x9a\x48\x71\xaa\xc2\x79\xbf\x45\x77\xa2\xe4\x37\x15\xb5\x5b\x22\x21\x87\x21\x2d\x2d\x38\x3c\x37\xc3\xec\x34\x8e\x00\xe3\xf2\x03\xe3\x8b\x73\xd5\x75\x33\x46\x62\xf3\x17\xf1\xa8\x7c\x5c\xf3\xd2\xeb\x2a\xc6\xee\x54\x4a\x33\x55\x01\xe2\x66\x84\x66\x85\x2d\xcf\xa7\xc7\x68\x55\x04\x8d\x95\xed\x1b\xc1\xb8\x0f\xfc\x40\xe0\x41\xa9\xdd\x77\xfb\x5f\xb8\x30\x45\x4b\x65\xb2\x96\xf1\x05\xa6\x43\xab\x6e\xb6\x40\x87\x8a\x54\xc8\x1a\x31\x9c\xa3\x80\xae\xf5\x42\x8a\xd9\x4a\xc9\x2d\x59\xfd\x42\x62\x2a\x9a\x68\xa8\xbb\x44\x7c\x4b\x9f\x60\x56\x8e\x9e\x99\x8d\x92\x97\x41\x8e\x63\x34\x01\x60\xab\x8a\xeb\x90\x2e\x30\xdc\x1d\x9b\xc0\x54\x18\x61\xae\xb7\xb1\xeb\xaa\xfb\xc9\x3b\x20\x05\xc8\x6a\x34\xdf\x0d\xd8\x67\x25\x5e\xde\x54\x0a\xfc\x4a\xed\x2b\x76\x83\xa2\x75\x74\x74\x74\xc7\x9c\xb9\x52\x00\x3d\x2f\xb8\x4c\xe2\xb0\x82\x46\xb9\xd7\xb0\xcc\x35\x09\x02\xf6\x9c\x94\xec\x3f\xcb\x76\x56\x79\x86\xb4\x1e\xc8\x5b\x2e\xb7\x34\xb8\x34\x7e\x39\x72\x5b\x9a\xa6\x7e\x24\xe3\x9e\xa7\xaf\x06\xcf\x76\xfa\x4d\x13\x55\x03\xc5\xd4\x80\xaa\x4b\xf3\xca\xc3\xb3\x2c\x00\x8d\xbd\x5c\x19\xd9\xdf\x35\xd5\xf1\x65\x01\xb5\x6c\xba\x87\xf1\xce\xa4\xb6\x22\x94\x60\x79\x9f\x5c\xaf\xc8\xb2\xee\xc1\xed\xbd\xf7\x25\x19\xe6\xb6\x81\x95\x83\xd5\x9d\x08\x66\x5c\x9c\x16\x76\x23\x8a\x6c\x67\x45\x55\xeb\x27\x94\x67\x6e\xb5\x7e\xd6\xb5\x5f\x2f\x28\x61\x6f\x2c\xf9\xbf\xad\x6e\x69\xe7\x50\x30\xcc\x48\x06\xbb\xca\x30\x26\x34\xc8\xb3\xf4\x52\x14\xf3\x22\x87\x5d\xa5\xbe\xc4\xa6\x3a\x20\x43\xb5\x8f\xb8\x59\x6d\x8e\xe4\x1e\x24\xe5\x01\xc2\xf2\xa9\x41\x02\xcc\x8d\x54\x2e\x5c\x37\x84\xd3\x0a\xfc\xee\x47\x12\xcf\x04\xde\xe8\x1f\xfe\x15\xbd\xfe\x66\x83\x40\xb7\x96\xe1\xaa\xb9\x5a\x05\xe7\x35\x56\xce\x97\x1b\xad\x25\xb3\x09\x4c\x0d\x32\x43\x35\x31\x6c\x3d\x6f\x2f\x23\x38\x95\x5a\xf8\xcf\xc2\x11\x9a\xf1\x91\xad\xa0\x95\x12\x2b\xc8\x2f\xb6\x01\x5f\xcc\x1d\xbf\x29\xc0\x1d\x8d\x78\x28\x9f\x66\xb4\xaa\x78\x39\x70\xb7\xf4\xf6\x91\xbb\xf0\xb3\x5b\x0f\x9b\xa6\x0a\xbb\xf1\x61\x4b\x20\x84\xb0\x49\x5b\xcc\xb3\xe5\x64\x1e\xbf\x05\x90\xf4\x59\x4b\x63\x52\xce\xe2\x47\xc4\x8b\x42\xa9\x0c\x1d\xeb\xf1\x9a\x0a\xe9\x81\xfe\x56\x65\xcc\x76\x0f\xb2\x5f\x31\x9e\xec\x6b\xad\x87\x5a\xfb\xb8\x76\x16\xcd\x8b\xb0\x66\xe1\x91\xd5\x54\xce\x7f\x16\x99\x97\x2d\x25\xfc\x78\xb2\xbb\x64\x41\x27\x90\xf2\x5f\x70\x1e\xb2\x22\x5d\x7a\x94\x2d\xeb\xb4\xc9\x6d\xc6\x99\xa3\xe8\x09\x1a\xe4\xfd\x18\xd0\xc9\x6e\x12\x26\xf0\x1b\x79\x7d\xd3\xd0\xc7\xd3\x9f\x12\xf1\x46\x51\xea\x9d\x40\x97\x13\xed\x3a\x98\x20\x35\xa7\x07\x3d\x51\xf3\xd8\xa7\x27\xf8\x65\x48\xd5\xd6\xee\x61\x3e\xf5\x7d\xb3\x35\xdc\x08\x64\x0f\xb7\xe2\x8d\xf5\xb6\x5d\xa0\x4a\xe9\x61\xee\x72\xff\x77\x48\x95\x9b\x5c\x0e\xb4\x21\x0e\x17\x1c\x6e\xeb\x45\x31\x01\x9e\xd0\xc6\x6c\x64\x68\x57\xb7\x1b\x5a\xae\xdb\xd8\xbd\x4b\xf1\x9c\x7a\xde\x44\xcf\xaa\x56\x7c\x49\xad\xf9\x0a\x0d\x7a\x6d\x76\x97\x4c\x04\x3b\x73\x80\x79\xf6\x4b\x8e\x43\xa7\x8b\x43\x47\xe2\xdd\x4d\xaf\x4e\x1f\xc4\x1c\x6b\x1b\xb7\x7b\x54\x83\x98\xc0\x5d\x98\x9a\xd9\x61\x4c\xc9\xad\xf4\x4b\xf5\x61\x1d\x36\xd8\x61\x1c\xa2\xde\x38\x27\x3f\xea\xf4\x0b\x72\xfc\x97\xdb\x02\x1f\x50\x54\x3f\x97\x81\x32\x41\xc1\xf8\x4f\xae\xb7\xe7\x6c\xc3\xbb\x33\x94\xa2\x0e\x9c\x43\x2b\xe2\x01\xee\xf0\xd8\xbe\xd1\x9f\x0c\x88\x55\xa7\x5d\x65\xd3\xa5\x23\x7d\xac\x23\xd6\x5f\x2e\xba\xd4\x77\x7c\x68\x68\xba\x9e\x3a\xa6\x20\x87\x2c\xb5\x74\xd0\x3e\x7c\x9a\x81\xf9\x16\xd2\xa8\x83\x2e\xae\xfd\xab\x40\x04\xf8\x4d\xf9\x94\x8e\xaa\xd8\x4c\x77\x71\x8a\x4a\x2a\xce\x43\x4b\xf2\x88\xfa\x87\x30\x53\x4d\x06\x83\xe4\xcb\xe9\x1d\xca\x01\x74\x94\xab\xdd\x2c\x8b\xba\x52\xa6\x39\x26\x4c\xc1\x33\xc4\xdf\xcd\x9f\x06\x29\xc6\x9b\xee\xb1\x09\x13\x42\x91\x22\x6e\x2c\xbb\x2f\x1a\x0c\x62\x12\xc4\xf1\xd2\x06\x7b\x84\x12\x39\xa0\x73\xa6\x84\x47\x57\x77\xb4\x38\x46\x39\x4d\x1e\xea\xbc\xff\xe4\x20\x6c\xfd\x08\x57\x80\x8c\x4f\xd5\xfa\x3e\x2e\xe7\xc5\xb8\xda\x9d\x81\x83\x92\xdc\x7a\x02\x3b\x8f\x8f\x8a\xd7\x8c\x7a\xc5\xb9\x5f\xde\x66\x5d\x8f\x50\xa7\x49\x81\x83\xdf\xc2\x24\x62\xe9\xd6\xe4\x63\x4f\xac\xd2\x98\xb8\x1e\x43\x25\x37\xdd\x4d\xd1\xbf\x83\x60\xa8\x9e\x17\x07\x06\x87\x8e\xb7\x25\x58\x8b\xe2\xe3\x68\xdf\x75\x31\x71\xe8\xa4\x3d\x13\xfe\x84\x15\x52\x90\xac\x20\xd7\x8d\x8d\xce\x42\x44\xd7\x8f\x97\xab\xa7\x49\xf2\x2f\xec\x6e\x41\x67\x0f\xd1\x36\x00\x76\x03\xf4\xd7\x06\x4b\x9a\xd4\x68\xd7\x84\x80\xff\x99\x17\xd6\x9d\x15\x48\x45\xc9\xda\x3d\x1c\xb3\x19\x76\xae\xbc\xd1\xb2\x49\x16\x95\x83\x34\x47\xb9\x5c\xa4\x92\x60\x06\xf5\x58\x27\xbd\x56\x59\x64\x03\x72\x0f\x78\xf4\x76\x30\x77\x95\x18\x69\xa7\x55\x8a\xfa\x35\x91\x31\xa5\xee\xd8\xd7\x74\x20\x68\xd3\x49\xd4\xa2\x10\x44\x7f\xe5\xc0\xa1\xa2\x62\x55\x1a\xf9\x18\x11\xff\xd5\x58\x40\xec\x95\xa4\x42\xa7\x2f\xf7\xd8\x3c\x30\xa6\x51\x99\x91\xb9\x28\xcc\xdc\x37\x3a\x44\xc7\x3b\x06\xc9\x15\x97\xd4\x80\xbb\x41\xbf\xcb\x6d\x76\xd3\xa1\x7b\x64\x69\x7e\xd8\xb8\xe3\x0c\xb4\x60\x59\xb4\x29\x78\x92\x79\xd6\xf9\x3b\x5a\x22\x67\xff\x22\x94\xac\x75\x30\xb5\x2f\x55\x4f\x17\xd2\xa9\xba\x9a\xc5\x46\x51\x4c\x48\x73\xec\xf4\xaa\xa2\xea\x3b\xfd\xe5\x92\x8e\x29\x96\x4c\x0c\x27\x3b\xcc\x3c\x2e\x08\xf8\xfd\x74\xe3\xba\xd4\xbc\xe3\x1c\x31\x41\xa5\x5c\xd6\x98\x59\x93\x8f\xf5\xfc\xfd\x9d\xdc\xa3\xd8\x00\x25\x34\x0d\x2a\x40\xb2\xf6\x44\x64\xac\x98\x9c\x0b\xc3\x5c\xc8\x53\x0b\x69\x66\x5f\x4c\x06\x31\xc7\x1b\x05\x0b\x89\x44\xb0\xec\xbb\xdf\xf7\xd5\x4f\x5b\x3e\xbc\x20\xad\x62\x13\xb0\x54\x4a\x12\xad\xe6\x8a\x2f\x16\x24\x2f\x19\x2f\x34\x27\x16\x67\xbf\xad\xf0\x92\x93\x38\xe4\x4f\x98\xd6\x6e\x26\x8e\x3f\x7b\xe9\x4c\x7c\xf3\x13\xb8\xa3\x73\xc2\xc3\x0f\xa8\xb3\x6d\xc2\xfa\x70\x2b\xdd\x61\xa5\x24\x04\x78\x1c\x84\xdc\xa8\x0b\xed\x61\xd4\x81\x68\xa4\x53\xd0\x9d\xe2\x9b\xb0\x7a\x43\x97\x63\xaf\xbb\xae\xd2\x31\xa5\xa1\x6e\x35\x92\xc9\xdc\x17\x56\x89\x2d\xf1\xc2\x44\xff\x48\x99\xa0\x1c\xdd\xe6\x2a\x8c\xc6\xc5\xa1\xa9\x47\x41\x67\xcb\x73\xc7\x6a\x39\xbe\xc6\x3e\x10\xbc\xbc\x19\xa3\x5b\x9b\x83\x12\x05\xe6\x0a\x8a\x59\x7a\xee\x64\x01\xb8\xb6\x52\xd5\xaa\x9a\x8e\x4a\xbd\x4f\x1f\x69\xaf\xc7\x40\x18\xa4\x06\xda\x31\xa0\x9a\x69\x0b\x68\x21\x6c\x22\xa4\x79\x62\x21\x6b\xf2\x8f\x55\xe1\x65\x92\x96\xb8\x0d\x21\x9a\xc4\x8d\x07\xf5\x70\x95\x71\xda\x2a\x98\x03\xed\x92\x86\x11\x05\xf0\x6b\x76\x50\x9b\xd5\x3c\x6f\x71\xd1\xbb\x33\x75\xb0\xea\x69\x2b\x8c\xe8\xd3\x05\x30\x0e\x52\x99\x89\xe7\xa5\x54\x70\xb9\xda\xbe\xe4\x38\x4f\xbb\x07\x49\x11\xc7\x33\x9e\x61\x3e\x85\x3b\x2f\xaf\x48\x2d\x7b\x41\x2f\x6e\x91\xc8\xde\xfe\x67\xc3\x64\x67\xaf\xe8\xce\xd4\x2d\x68\x25\x11\xad\xc7\x50\x7c\x64\x33\xc7\xe7\x6d\xb4\x4b\x46\xfe\xe5\x9c\xb0\x8e\xd0\x5f\x0a\x2d\x69\x2a\x96\xcb\xb5\x15\x7d\x70\x03\x1d\xd6\xe9\xd4\x0b\x94\x45\x9d\xfa\x47\x64\x10\xa5\x42\x3c\x8a\x3b\x3d\x72\x9b\x5a\x14\x95\x93\x36\x1b\xd6\x95\xff\x90\x09\xc9\x3e\x0a\xcb\x62\x41\x01\xb8\x14\x75\xcc\xe8\x3a\x1b\x57\x76\x26\xe3\xcb\x08\x00\x38\xf5\xaa\x06\xb4\x9c\xea\xb7\x4c\x53\x6a\x74\x28\xeb\x1c\x9b\xa0\xe4\xcd\x1a\x33\x7d\x14\xcb\x9e\xc2\xb5\x3c\x47\x8b\x75\x3e\x91\x09\xa8\x03\x04\xf2\xe6\xc3\x5c\x6a\x40\xa1\xa6\x51\x60\x10\x1d\xcd\xc6\x13\x68\x29\x35\xb4\xbb\xcd\xbf\x28\xa4\x6c\xd8\x7b\x1c\xaf\xbd\x09\x43\x50\xfc\xf3\xf1\xb9\x6a\x5e\x54\x72\x54\x43\x32\x6d\x8a\xdd\x8d\xd2\x06\x7c\xc0\x4b\x43\x1b\x90\x22\xb9\x3a\x01\xc3\x46\xbe\x3d\x89\x5d\xd6\x96\xda\x73\xc8\xe0\xb7\xa1\xf9\x80\x48\x6e\x81\xa9\x72\xd0\x10\xbc\x59\xa2\xea\xb2\x5c\xfc\x1f\x03\x47\x74\x11\x00\xf9\x5b\xfd\x8c\x12\x19\x79\x7f\xe2\x24\xf3\x74\x67\xd3\x57\x98\x1a\x2b\x6f\x03\x88\x10\x94\xdd\xb2\x7d\x9e\x90\xfb\xe5\x12\xe9\x6b\x34\xfb\xde\x3a\x82\x4b\x6a\x67\x07\x73\xcc\x58\xff\xb0\x61\xf0\x4e\x3a\xfe\xb2\xfd\x7d\x80\x46\x10\x0e\xa7\x5a\x01\x9a\xd2\x08\xc1\x32\x1f\x51\x7b\xa8\x52\x9d\x15\x1a\x5b\x4e\x26\x4d\x04\xf7\x6a\xb2\x34\x5d\x33\x51\x3a\xea\x0a\x73\x9c\xd7\xcb\xd7\x74\x1f\xfc\x87\xcb\x70\x49\xbf\x56\x5b\x11\x68\x9a\x6f\x81\x35\xb0\x7b\xe4\x7f\xe7\xf8\x3b\x87\x7f\x06\xad\x64\x0d\x97\xb7\x7f\x2e\xf2\xf1\x0a\xf1\x10\x23\x3b\x76\xc9\x45\x60\x5d\x87\x52\x30\x94\xeb\xd3\xcc\xec\x29\xc2\x7e\x9e\xca\xb9\x1c\xae\xe5\x7d\x5c\xc8\x9c\x20\xd8\xad\xfc\x3c\x8e\x5b\x00\xec\xcd\xa9\x91\x56\x5a\xc0\x02\x99\x1f\x5a\x3b\x75\xfc\xfd\x1d\x43\xf4\x72\x12\xf2\xf8\x2e\xe5\xf0\xbe\x9c\x2f\x33\xbb\xbc\x01\x01\xe4\x6e\x50\x6f\xeb\xc9\x56\x04\x2e\xf7\x8e\xc8\x49\x58\x89\x2b\x99\x9c\xa6\x41\x97\xd8\xf0\x87\x4a\x12\x8f\x72\xf1\xf3\xd2\x47\x03\x5c\xfb\x81\x5d\x47\x5c\xea\x67\x25\xdd\x6e\x63\x24\x83\x40\xe0\x4b\xbf\xd7\x82\x0f\xae\xf0\x8c\x44\xc5\x51\x57\x43\xc2\x65\x0b\xc3\x27\x22\x5f\x72\x46\x5a\xd2\x2f\x7d\x3f\xdd\xfc\xba\x59\x34\x47\x9e\x05\xcb\x68\x27\xad\xf6\xb4\x05\xef\x65\x86\x44\x8c\x4e\xf5\x6e\x25\x9a\x59\x47\x89\x4c\x88\x13\x91\x88\x00\x25\x13\x86\x0a\x9f\x6a\x6e\x90\x7e\x11\x8a\xa6\x49\x17\x92\xb9\x0e\x39\xd0\x95\x00\x2b\x49\x8d\x12\x2b\x2b\xd0\x9f\xd6\x8d\xfd\xf4\x08\xb4\xc3\xed\x7f\x5f\xae\x71\xda\x49\xa7\x5b\xb1\x32\xcd\x77\x33\x65\x74\xd8\x7f\x0f\xf5\x04\x00\xb1\xc3\x6d\xf5\xf2\x2f\xa7\x67\xb5\xf4\xa3\x26\xae\x9b\xec\x21\x54\xa9\x83\x07\x33\xb9\xa4\x42\xaf\x1c\x50\xc0\x64\xa8\xed\x32\x90\xe1\xb5\x68\x57\xfd\x3d\x4c\x72\x51\x5f\xe6\x76\xe1\x79\xfa\x58\xa3\x0a\x0e\xe3\x5b\x70\x43\x04\xdb\x74\x0d\xd8\x07\xbe\xc1\xe7\x58\xd9\xaf\x97\x55\x3c\x34\xa0\xdc\xba\x91\x8c\x82\x9a\x36\xe5\x0b\x2a\x71\xdc\xed\x7b\x3b\xc6\x4c\xee\xb9\x97\x83\xda\xe0\xf5\x30\x30\x52\x69\x78\xd2\x3b\xb7\x94\x11\x39\xc4\xa4\xb6\xfc\xf7\x13\x3b\x74\x0b\x18\x81\x18\x03\x7b\x9c\x77\x57\xe7\xe5\xa7\x76\xa5\xcb\xe6\x85\x6d\xde\x2d\xd8\xf0\x4e\xf3\xb2\xf1\xb5\x6b\xdf\xbb\x9f\xb9\x32\x87\x5e\x53\xe6\xb6\x71\xe3\xdf\x07\x15\xd0\x69\xe4\x0a\xfe\xe1\x31\xca\x20\x36\x07\x04\x60\xce\x29\x0c\xba\xd2\x89\x78\x7c\x4a\x0c\x66\x72\xc3\xdf\xc8\xcd\x67\x2e\x07\x00\xed\xf3\xa7\xf3\x00\xd8\x6f\xdc\xd2\x7f\xb7\x6f\xf2\x60\x9d\x00\x94\x20\xea\x33\x10\x77\x42\x5e\x96\x16\x15\xda\xa4\x70\x43\xaa\xce\xc0\x56\x0b\x56\xef\xf3\xa3\x46\x1c\x75\xac\x7c\x65\x0c\xe4\x50\x99\xd4\xea\x37\x03\x71\x23\xb7\x63\xa0\x6d\x2c\x2d\xfb\x5e\x5e\x05\x8f\xfe\x49\xd9\x83\xfb\xa6\x54\x39\x70\x8e\x5c\x03\xd9\xa2\xc9\xc0\xdd\xde\x16\xc8\x49\xbd\xb5\xef\x81\xd5\x45\xba\x1d\x1e\xd0\x04\x21\x89\x22\x2b\x57\x54\x0d\x1b\x4c\x36\xe8\x4a\x54\xf2\x84\x6c\x97\x6c\x74\xcd\x46\xc3\x30\xee\xf2\x26\xd8\x3e\xbb\x4d\xfc\x49\xc6\xdf\x72\x30\x66\xcb\x53\x2a\x5f\xf1\xdc\x6c\xb3\xed\x23\x91\xcb\xbb\x85\x01\xa0\x9f\x47\x87\xa3\x1b\x1b\x3c\xc6\xd1\xb7\x43\xe8\xa4\xb7\xc9\x9a\x7a\x17\xc1\xac\x29\xa5\x46\x79\xe7\x9e\x3b\xcf\x01\xd0\xb3\xde\x56\xef\x33\x55\xb3\x5d\x82\x83\xc3\xb9\x13\x91\x2c\x31\xd5\xa0\x5a\x66\x85\xe3\x39\x0a\x93\x70\x3b\xc6\xa3\xa3\x4f\xad\x12\x22\x64\xf0\x8a\xc3\xf6\x3a\x61\xc3\xd6\x15\x15\xe5\x50\xd9\x4d\x6f\x83\xc2\x44\xbc\xd5\xe2\x19\x53\xba\x38\xef\x4f\xe1\xdd\xb3\xf8\xf8\x07\x9a\x76\x3e\x61\xa1\xd0\xbc\xab\xe3\x7a\xbf\xe7\xf6\xda\xc6\x96\x2e\x0c\x17\xde\x7b\x8e\x31\x39\x90\x6b\xd6\x88\xec\xd3\x5c\x41\xc3\x31\x96\x47\xf3\xe2\xad\xda\x84\xd0\x0b\x0d\xa9\xd1\x1d\x6a\x55\x3e\x06\x91\x80\x22\xf3\xdc\xd4\xd1\x94\x2e\xab\x90\x23\x2f\x71\x4c\x70\x0d\x23\xff\xea\x54\xba\xbf\xb0\x62\xee\xa7\xfe\x3a\x8d\x65\x4f\x9d\xa7\x73\x64\xad\x1e\x73\xbc\xcc\xfa\x5b\x7b\xf4\x7c\x31\x3d\xd2\x4f\x7a\x27\xaa\xaa\xf1\x30\x36\x9a\xac\xc7\x96\xa5\x8a\xb7\xc8\x61\xb1\x7c\x88\xb9\x44\xa5\x27\x71\x1d\x27\x34\x0a\x6f\x6a\xf9\x3c\xca\x09\x1c\x7a\xa4\xe3\xf1\xfb\x52\x39\x88\x5c\x32\xdc\xbe\xe7\x51\x04\x78\x71\xff\xc9\x71\x9f\xab\xd1\xb6\x1c\xa1\xb4\x6a\x4d\x5f\x2f\x81\x99\x19\xab\x8d\x65\x9f\x27\xc8\x86\xe4\xc9\x2d\x1c\x48\xff\xf4\x74\x2e\x20\xc4\xa9\xb2\x8b\x43\xd6\xfc\x56\xb9\x98\xfc\x65\x70\xda\x6d\x01\x52\xde\xa8\x95\xa2\x6b\xdf\x34\xb8\xed\x5c\x32\xdc\x11\xda\xbc\xd8\xd1\xe5\x91\xd3\x9f\x53\x67\xe1\x63\x54\xc7\xe5\x61\x16\x1f\x10\x70\xe7\xee\x33\x9e\x5d\x03\xcd\x4d\x2a\x8e\xa0\x44\x05\x62\xa3\xc7\xda\x37\xa2\x3a\x87\x68\x79\xf4\xb2\x44\xf3\x28\xdb\xc2\xbb\xdb\x38\xb1\xc3\x2a\xe7\xcd\x9d\xa4\xf6\xf2\x61\x28\x27\xb3\x82\x4c\x17\xca\x72\x6d\x68\x9b\x70\xd3\x7b\x4f\x87\x42\xe6\x4d\xe5\x24\x67\x8c\x25\x8c\x2f\x96\x6f\xb7\xed\x6b\xb6\xfd\x99\x1d\x00\x30\x74\x60\xc1\x9a\xca\xd3\x42\x3c\x86\x98\x22\x3a\xc7\x31\x14\x86\x6c\x5e\x85\xd7\x6a\x6b\xcf\x16\xe9\x4a\x30\xf5\x37\x7f\x6e\x7a\x00\xaa\xc2\x55\xff\x77\xe4\x96\xae\x42\x33\x43\x6c\x64\xa5\xc1\x52\xc8\x7b\x07\xc6\x18\x4a\x0f\x91\x25\x1e\x24\x9f\x1c\x25\x5f\x75\x17\x36\x2f\xee\x20\x42\xb9\xc9\x90\xc3\xc1\xd0\xbe\xfd\x53\xfe\x56\x99\xa9\x9c\x84\xe5\xa9\xef\xca\x92\x7d\xcf\xf7\x68\xc4\xf4\x53\xa9\xf8\x9f\x82\x41\x41\x6c\xd3\xb9\xef\x64\x7e\x28\xf7\xc0\x76\xea\xee\x36\xfa\x60\x55\x41\xbc\x95\x7c\xf5\x1d\xe5\x24\x38\x8e\x95\x82\x0f\x5a\x73\xa4\xc9\x6f\x95\x6e\xc8\x97\xd5\xce\xa2\x64\xb2\x07\x1c\xfb\x5e\x21\xb9\x82\x4b\x5b\xd1\x75\x2b\x61\x65\x22\x6c\x8a\x6c\x14\xe3\x2a\xec\x8c\xe3\x96\x6c\xe3\xaa\x56\x27\xb0\x3b\x2f\xe5\x15\x25\xcd\x06\x2c\xbc\xe6\xed\xe3\x52\xe1\xb8\x9d\x25\xdc\xca\x45\xcf\x1d\x09\x70\x88\x9a\xde\xa4\x0c\x18\x51\xf8\x18\xab\x4d\x11\x2a\x37\x8f\x04\x61\xae\x73\xba\xe6\xbb\xdc\x74\x42\x2a\x3e\x4e\x67\xe2\x4a\x8d\xb4\x12\xc4\x29\xce\xe1\x50\xdc\xbc\x99\xd1\xaa\x82\x61\x88\xb2\x78\xc8\x4b\xae\xfe\x22\x08\xe1\xdc\x7e\xae\x29\x73\x57\xa2\xec\x9e\x94\x6c\xdd\x3d\x5d\x26\x35\x66\x73\xcb\xb6\x9f\xb3\xd8\x31\x39\x4f\x65\xa3\x73\x2e\x04\xa2\xab\x90\x29\x58\xf0\x80\x96\x89\xa5\xd8\xae\xa8\x18\x0f\x1b\x5f\x8a\x08\xeb\x8e\x6f\xb9\x36\x6c\x6a\x46\x7c\x23\xdb\x17\xc2\x38\x02\xef\xa5\xb7\xd4\xb7\x94\x3b\x91\xb3\xc6\x56\x47\x99\xb9\x73\x23\x3b\x9c\xf4\x63\xc2\xf2\x08\x4f\x1a\x18\xc3\x97\x28\x10\x21\xaa\x3d\xb7\xcd\xde\x63\x44\x81\xfb\x6c\xb6\xdf\x64\xcc\x5e\x5a\x08\x62\x6a\xd8\x39\x87\x7d\x26\xb7\xeb\x19\x27\xf4\xb2\xe6\x67\x16\x2a\x17\xc6\x43\x56\xd7\x82\xb6\xfa\x91\x05\x82\x14\xca\x45\xe7\xf3\x19\x86\xb1\x9d\x6a\xa4\x7a\x1c\xab\xf9\x13\xa2\xd2\xa9\x95\x0b\x78\x05\x34\xee\xcc\x42\x94\xac\x77\xc4\x74\xe0\xb5\x25\xcf\xfa\x5b\x76\xb2\x86\x33\x5b\x30\x97\xdf\x8c\xe8\x37\x14\xb3\x2f\xfe\xb7\xad\x76\x1d\xfd\x72\x1a\x27\xa6\x72\x11\x6d\x04\x66\x86\x80\xcd\x6c\x2e\xd2\xce\xf5\x61\xb5\xe8\x73\xad\x1d\x79\x38\x30\x9d\x4a\xf7\x5b\xd7\x69\xc7\x9b\xd3\xff\xa3\xd4\x05\x77\x59\x4c\x6f\xb0\xab\x0e\xd4\x3e\x9b\x53\x0a\x13\x94\xf5\x62\x58\x81\x47\x98\xd8\x19\x18\x78\xa9\x39\x05\xc8\xbb\x9e\xd7\x07\x24\xa7\x0e\xe6\x0e\x90\x6d\x8d\xc9\x4c\x2a\xbf\x27\x77\x80\xcf\xf2\x31\x35\x2e\x09\x4a\x65\xaa\x24\x1d\xe4\x32\x2e\xa6\x88\x74\xbb\x0f\xe4\x5d\x21\x5f\x78\x05\xeb\xfd\x4b\xf5\x55\x87\x7f\x0a\x71\xac\xf4\x7a\x09\x85\x79\xca\xce\x0c\x6c\x2b\xb1\x3a\x53\xbb\x91\xa9\xac\x10\x73\x36\x8d\xc2\xff\x16\x82\x09\x63\x58\x13\x6e\x6e\x96\x63\xc4\x1b\xa9\x81\x11\x5c\x80\xb1\xe9\xd9\x16\x16\x99\x22\x2b\x40\xf1\xd3\xba\x26\xb8\xf3\x3b\x8f\x18\x75\x8c\x61\x99\xb9\xf2\x14\x87\x7e\xbc\xa6\xb6\xfd\x26\x74\x50\xaf\xde\x03\x5d\x15\x35\x7a\x55\xd0\x62\x26\x05\x08\x28\x07\xb4\xf0\xbb\x52\xb0\xb1\xe3\xdf\x1c\xa4\xbb\x59\xb4\x29\x8c\x09\x4e\xc7\x2c\x7c\x2f\x0a\x56\x0a\x44\x73\xd9\x3f\x65\xcb\x85\xb9\x67\x89\x5c\x31\xc0\x7d\x2c\x66\xa9\x52\x67\x38\x1a\x59\xd5\x4c\xf2\x67\x54\x8c\x7a\x05\x15\x40\xd8\xd1\x2c\x4a\x69\xd9\x2b\x25\x30\x07\xdb\x6b\xd4\x39\x3a\xc0\xb5\xc9\x50\xb8\xcd\x4e\xbd\x40\xe1\x86\x95\xd3\x90\xce\x2a\xe0\x36\x3a\x3f\x38\x17\xca\x4b\xdc\xe4\xbe\xbd\xbc\x55\xd7\x3c\x4c\xba\x85\x92\x36\xfd\x74\xb7\xda\x03\xa3\xac\x9b\xab\x06\x8c\xe4\x95\x29\x30\x01\xb9\x13\x63\x3e\x29\x44\xf1\xbf\x66\x93\xdd\x53\x30\x57\xab\xf2\x0b\x9a\x9b\x12\x13\x2c\x39\x50\x27\x5c\x5a\x77\xb9\x05\x42\x24\x8e\xca\x4d\xf9\x4b\xc2\xbd\x3f\xaa\x7e\x32\x0d\x64\x24\x9a\x9a\x34\x32\x2a\x1f\xcd\xb7\x5b\x5f\x09\x4a\x50\xb6\xa8\x84\x68\x54\xf5\x5e\x0f\x6a\x7c\xa7\x29\xc2\x43\x28\x3c\xe9\xf2\x6e\x4e\x4c\xa5\x9d\xdd\x0a\x7a\x7d\xa4\x0a\x51\xd5\x0c\xbc\x99\xa2\xfa\x6a\xc2\x68\xb8\x49\xd4\x70\x61\xf0\xd1\xf4\x07\xdd\x83\x14\x73\xb6\x74\x01\x4b\x4a\x5d\x70\x93\xd0\xbb\x9a\xd6\xf2\xb9\xf3\x7c\x49\x5d\x84\x87\x18\x93\xef\x21\x33\xc3\x78\x4b\x81\x04\xc3\x65\x4d\x89\xcd\x03\xc0\x54\xe9\x6c\x42\x6e\xb9\x6c\xbc\x43\xfd\x18\x29\x52\xbc\xad\x73\x04\x79\xf8\xde\x27\x58\x89\x29\x55\x92\x62\x84\x95\xbf\x31\x1e\xe9\xef\x5a\xa1\x4b\x47\x3d\x21\x76\x41\x02\x6a\x71\x10\x7d\xb9\xda\xdc\xa6\x6c\xbc\x5b\xe2\x9c\x3f\x44\x5c\xb8\xc2\x48\x13\x5d\xcf\x52\x84\x19\xb0\x3d\x60\xcf\xe2\x6f\xd4\xbd\x6a\x48\xba\xf7\x36\x26\xc0\x57\xe7\x3d\x07\x1f\x51\xc5\x95\x99\xe4\x2b\xc6\x87\x73\x51\x74\x78\x5c\x0d\x72\xe8\x98\x54\x80\x77\x6b\xc5\x3d\x4c\x1f\x35\x3c\x0e\x5e\x27\x00\xab\x61\xce\x1f\xe6\x40\x31\x3d\xcf\x9f\xf0\x8d\x25\x6a\xe3\x54\x78\xca\x13\x0d\x1f\xa4\xb6\xc2\xcb\xbc\xec\x5b\x76\x4a\xb9\x24\x24\x4f\xa8\xd6\xbc\x83\x4b\x27\x33\x9b\x09\x3e\x35\xf6\xb0\x01\x7f\x72\xb2\x9a\xc2\x4c\xe4\xaf\xf8\xbc\x40\x4f\x0d\xe5\x70\x3b\x5c\x3c\x2c\xa7\x5a\x3d\xbe\x73\xaf\x94\xc4\x72\xcf\xcd\xc2\xe9\x94\xfb\x8e\x88\xcd\xc0\x23\x0b\x63\x95\x93\x3e\x87\x52\xfb\x10\xc9\x30\x5e\x3e\x7b\xc3\xb9\x4d\xde\xfb\x2e\x18\x3c\x2c\x41\xd7\x0f\x90\x38\x6e\xef\x9e\x68\x69\xef\xef\xe8\x76\x2f\xb6\x9f\xa1\xcf\x28\x7f\x98\x42\xf8\x65\x9c\xfc\x4d\x2b\xcb\xf0\x9e\x06\x87\xc4\xa4\x0a\x9a\xa9\x6d\x1e\xdb\x75\x17\x28\xb2\xfb\x93\x00\x30\x10\x63\xa2\x35\x8f\x9f\x06\x29\x4e\x19\x16\xf2\xb8\x83\x3e\x31\x8d\x15\x2b\x9b\x2d\x30\xd0\x4e\x6c\x2d\x4c\xce\x25\xec\x10\x5b\x4e\x62\x37\x04\x77\x55\x02\x9c\xf9\x79\x74\x6d\x79\xd0\x18\x24\xa5\x50\x92\xe1\xf0\xd2\x08\x72\x68\x79\xa1\xa0\x66\xde\x3f\x87\x47\xe5\x51\x91\x1e\x40\x98\x2f\x76\x04\x34\xaa\x30\xc4\x8a\x9a\x3e\x82\xb6\xb3\x09\x26\x16\x79\xea\xd5\x34\x7f\x45\x8f\xef\x50\x22\x60\x7b\xc1\xf2\x55\xbe\xd5\x4d\x3f\xef\xb4\x05\xd5\x61\x72\x64\x95\x69\xd1\xe7\xa3\xda\xbe\x8e\x7c\xeb\xf9\xee\xef\xe0\xfa\xc6\x36\x0d\x35\x2e\xd5\x0c\x93\x7d\x1c\x26\xc3\xff\x08\x41\xd4\x69\x3d\x80\x5b\x7c\x88\x3f\x11\x81\x4b\xb2\x94\x3c\x7f\xf3\xc3\xdb\x84\xde\xcf\xb6\x7a\x1f\x75\x68\x6e\xe2\x53\x83\x14\xdb\xa9\x84\xef\xfa\x79\xad\xea\x1e\xbd\x41\x79\x74\x80\xaf\x30\x55\xaa\x7b\xf8\x4a\xb1\x9d\xb1\x9e\x35\xe0\x42\xcd\xab\x7d\x7f\x52\xeb\xde\x6c\x5e\x91\xa1\xf3\xf8\x95\xa2\xc7\x8d\xfd\x73\x7f\x47\xf3\xc9\x7d\xc6\x97\x74\x97\x4e\x2f\xdf\x69\x3f\x3d\x63\xd1\xea\x58\x4e\xa0\x78\x58\xfc\xb2\x02\x86\xcb\xa6\x61\xe3\x7c\xbc\x53\x49\x0d\x9b\x26\x9b\x28\xf7\xcc\x3f\x23\x37\x51\xe7\x76\xf8\xcf\x29\x64\x9a\xa0\x8b\x6a\xdc\x99\x99\xea\x4a\xc1\x14\x0e\x95\x10\x63\x55\xd7\x41\x57\xcf\x54\x23\xe3\xfd\x8e\xf8\x09\xf9\xd2\xc3\x29\x9c\x95\xe5\xc3\xe9\x60\x61\x44\x41\xd5\x2a\xc7\x6c\x4a\xe2\xd2\x95\x53\xf3\x98\x6c\x08\xfe\xa0\xf0\xd1\xc3\x14\x28\x55\x05\x98\x43\x56\xb5\xf2\xfb\x24\x34\xc7\x1d\x04\x2b\x15\x0d\xae\x24\xca\xc9\x6f\xbc\xa0\x7d\xad\x2a\x16\x0b\x41\x4a\xc9\x3d\x20\xff\x01\x15\xd9\x04\x1d\xd9\xf2\x14\x30\x90\x1d\x7b\xd1\x1e\x8a\xbd\x80\x90\x91\xe6\x5b\xfc\x4e\x7b\xf2\xdc\x02\x76\x75\xae\xd1\x56\x32\x94\xeb\xde\x8f\x1a\x2b\x7f\x19\x73\x77\xb4\x45\xa9\x4a\xc0\xe8\xf8\x05\x9b\xb0\x36\x5e\x41\xef\xd7\x01\x8f\x49\x06\x91\x11\x82\x10\x0b\x48\x5f\x89\x84\x1b\x13\x79\x88\x06\x97\x93\x7f\xe4\xd2\x1e\xc7\x25\x83\xaf\x50\x51\xe2\xbd\xee\xa2\x35\x35\x34\xe9\x69\xea\x47\xdd\x20\x4e\x88\x9e\x55\x36\x8a\xba\x8c\x09\x22\x36\xc6\x1f\x13\x31\xe2\xce\x01\xb0\x66\xf6\xb1\x25\xf7\x82\xd5\x88\xf3\xf4\x8f\x8e\xf4\xbf\x5f\x70\xb0\x8f\xdb\xf5\x6f\x50\x78\x2b\x20\x19\x12\xc5\xfd\x35\x4b\x73\x22\x73\xae\x21\x61\x7a\x62\x3e\x18\xa1\x04\x90\xc5\x0a\xcf\x94\x21\xca\x51\x4d\x7d\xd5\x4b\x10\xaa\x0b\x7a\x2b\xe5\xe0\xe5\x10\xbf\x7c\x5c\xe3\x52\x12\x9a\xf0\x66\x46\xdf\x8f\x81\x62\x35\x2f\x6d\x27\x64\x01\x5e\xac\xe1\xfb\x35\x55\x44\x66\xae\x4c\xf3\xe8\x67\x94\xed\x36\x59\xa6\x1d\xfd\x55\x93\x50\xa6\x20\x97\x83\x85\x66\xed\xc9\x6f\x7b\x0f\xfd\x74\x1d\xb6\xe4\xa8\xb2\x86\xb6\x04\x68\x9d\x25\x91\xae\x98\xe7\xae\xef\x2b\x50\xc4\x54\x96\x5a\x26\x95\x83\x76\x92\x22\x01\xea\x0f\xb5\x27\x3e\x81\x81\xc6\xe9\xdd\x44\xd3\x62\xac\xb8\xb2\xfd\xcb\xdb\x88\x8e\x88\xed\xc7\x77\x28\x21\xa3\xb5\x7b\xc7\x6b\x55\x65\x33\x89\xd2\xd1\x0c\xc8\x17\xb5\x93\x6a\x04\x33\xb8\x72\x55\xb1\x23\x8f\xa4\xce\x8d\x4a\xb6\xc1\x20\xd6\x82\xd9\x7b\xeb\x06\xa5\xc5\x2c\x43\xa2\x50\x49\xc6\x09\xd0\x8e\x40\xa2\xd4\x5c\xed\x18\x3b\x96\x8c\xf6\x9a\xc1\xa1\xf8\x7e\x1f\xea\xfe\xcd\x9f\x83\xc2\xd1\x02\xaa\xa8\x4b\x66\xbd\x1a\x85\xc0\xf2\x4f\xe6\x40\x66\x57\x02\xd8\x9c\x00\x5e\x1e\xd9\x2f\xba\x99\xc8\x60\xfc\x24\xa2\x21\x00\xbd\x66\x32\x8f\x97\xdc\x3f\x36\x9c\x71\xdc\x73\xa3\xce\x0a\x63\xa6\x36\x4a\xf4\x2d\xb7\xaa\x9d\xb8\xec\x11\x0d\x69\xbd\xed\xd2\x85\xd3\x2d\x0f\x00\x87\xcb\x32\x46\xfa\x6d\xc8\x8e\xca\x11\xc4\x5a\xf8\x21\x42\xf7\xc3\xf8\xbb\xc7\x20\x70\xd0\x43\x55\x95\x0c\xff\x9d\x9e\x94\xeb\xe5\x57\xfd\x94\x8f\xfb\x26\xb9\x33\xd1\x0d\xd0\x7d\x2d\x80\x64\xe3\xaa\x9c\x7c\x55\x32\xe7\x6f\x82\x38\x94\xa7\x17\xf8\x1a\x2a\x4d\xab\x7a\x63\x7b\x96\x5f\xc3\x01\xf2\xec\xc9\xb0\xf0\xc7\x68\xb7\x06\xb7\x39\xba\xfe\x95\x0d\xb5\xb9\x57\x94\x78\x5b\x22\x9c\x9a\x55\xdd\x9f\xdc\x9f\x2f\x7b\x8e\x12\x0a\xd0\xe6\x52\x6a\x54\x63\x10\xea\xdf\xa7\x2a\x6c\xb2\x07\x54\x96\x22\x27\x0e\x86\x53\xcc\xb8\xe0\xd2\x54\x62\x99\x9a\x24\xe8\xf3\x72\x51\x12\x97\x2e\x1e\x8c\xe6\x5a\x73\x56\x9b\xf2\xec\x4a\x1b\x04\x3b\x5b\x0b\x25\xab\x10\xb0\xc8\x6a\x52\xf3\xd9\x47\x4f\x37\x46\x52\x33\x18\xf7\x10\x8f\x63\xf8\x19\x26\xde\xa7\x7d\x87\x56\x8e\x5e\xac\xec\x68\xe4\x7a\x59\x94\xbc\x5e\xdc\x53\xfc\x4f\x75\x8d\x1d\x37\x68\x51\x4c\x56\xdc\x7b\x18\xad\xe0\x38\xee\xcf\xbc\xe2\x1d\xbc\xd3\xa4\xc1\xde\xeb\xf2\xda\x7d\xb1\xab\x8b\x17\x03\x15\xf5\x0a\x88\x15\x49\xbb\x40\x5f\xd1\x21\xd1\x32\x66\x62\x25\xd5\xd9\x07\xe8\xa3\x31\xe6\x6c\x9f\x94\x1a\x56\x89\x03\x4d\x94\xa0\x1d\x2d\x3a\x3f\x19\xda\xf8\x3e\x0c\x2d\xd8\x4e\x13\xf1\x36\x75\xaa\x76\x4b\x11\x93\x99\x57\x55\xaa\x7a\x28\xfa\x64\xf7\x42\x66\x25\x4c\x5d\xd7\xbb\x8d\x91\x27\xf7\x31\xe0\x76\xe3\x28\xf7\x38\xbf\x86\x9b\xe8\xbd\x56\x49\xc8\x10\x92\xfb\xef\xcc\xc7\x77\xa7\x55\xd1\xc4\xa0\x03\x45\x1b\x50\x56\x2b\xe3\x0e\xcd\x1e\x96\xe5\x8c\x24\x46\xf8\xe7\x79\x7c\xb0\x66\xc8\x92\x68\x59\x50\x12\xe7\x35\x22\xc9\x5d\x7c\x8f\x25\xa9\x81\x81\x3c\x9b\x83\x91\x9e\x56\x76\x9e\x62\x70\x7f\xa3\xa5\x20\x29\xf0\xb1\x69\x42\x9e\xf7\x25\xe0\x5b\x0c\xd6\x26\xe8\x48\xee\x8a\x0b\xb9\x5a\x16\x3c\xc3\xa1\x56\x2e\xb7\x5e\x85\x71\x8f\x07\xa1\x4b\x6e\xeb\x00\x04\x49\x0a\xe5\x5c\x91\x34\xed\x55\xd2\x57\xce\x68\xe3\xfc\x8f\xce\xf2\x70\x06\x3a\xa4\xb6\x38\xf8\x70\x32\x7a\x13\xed\x0c\x7e\x5f\x0f\x9b\x37\x3e\x90\x0a\x39\x8f\xea\x89\xe8\x0b\xc2\xec\x22\x3e\x4b\xc9\x99\x0e\xdd\xaa\xfd\x1a\x8a\x12\xf0\x91\xf5\x7c\xe2\x3e\x32\x43\xbc\xf7\xce\xb2\x4a\xd6\xcb\x7c\x09\x2a\x80\x6b\x38\x88\x75\xdc\x4a\xdd\xc7\xc3\x90\x77\x58\xf9\x71\x1e\x32\xdf\xf5\xd7\x40\x94\x61\xb9\xbc\x63\x8f\x1c\x6d\x5b\xc9\xbb\xf9\x70\xef\x7a\xd9\xc1\x80\x01\xca\x05\xd1\x83\x4a\x6f\x49\xae\xdd\xdb\x2b\x72\x70\x44\xea\xee\x47\x39\xf5\x3c\x42\xa9\x1f\x9a\xee\xce\xf9\x6b\x5d\xd1\x14\xe5\x92\x94\x5c\x66\x49\x8e\x77\xed\x60\x69\x9f\x4b\xa2\x33\x59\xba\x97\x72\x0d\xea\x76\x94\x04\x83\x88\x5b\x32\x46\xa4\xf9\xba\xcd\x56\x4c\x7a\xb3\x46\x85\xf9\x5e\x66\x82\x21\x92\x56\x4c\x50\xf8\x26\xba\xfa\x3d\x7e\xce\x27\xdf\xcf\xc7\x49\xc8\x3b\x84\x95\x06\x05\x27\xb5\x65\xdd\x4d\x2d\xdf\x95\xf2\x2f\xea\x13\xaa\xb3\xa9\x4d\x74\xfb\xd6\x75\x60\x3e\x34\x6c\xee\x83\x00\x00\x23\x24\x12\x2d\x78\x88\xab\x40\x19\x7e\x44\xff\xe7\xc0\x71\xa9\x96\x28\xfd\x6c\x0c\x9e\xfd\xd8\x72\xcc\xde\xdb\xe1\x97\xbe\x29\xd4\x48\x0d\xd9\xc1\xa2\xac\x93\x3c\xb5\xd6\xab\x79\x52\x72\x21\x62\x24\xf7\x3a\x2b\x90\xe5\x75\xd9\x34\x5f\x00\xa6\xa3\x96\x98\xe5\x8e\x84\x56\x77\x87\x67\x8c\x56\xdf\xbc\xc0\xb6\x5c\xc9\x19\x20\xbe\x45\x74\x79\x3a\xa4\x94\x74\xe6\x54\x9c\xd1\x25\x0f\x58\xa0\x73\x2f\x99\x3c\x56\x3e\x0a\x42\x4b\x64\x41\xa6\x74\x85\xf0\xac\x03\x0e\xe6\x20\x61\x50\x41\xa7\x01\x77\x55\x26\x09\x99\xac\x56\x0b\x1a\x6b\xdf\x70\x05\x88\xc3\xf8\x04\x18\x61\x1e\x6e\xb1\x22\xb2\x29\x54\xc9\xe4\xc2\x79\x52\x39\x62\x42\x4f\x92\x1c\x05\x56\xa3\x8b\xb8\x95\x4b\x15\xc3\x5c\xd2\x6b\x34\x29\x69\x29\x51\x06\x56\x1d\x5a\xcf\xbd\xe1\xb9\x7b\xaf\x43\x87\x52\x69\xbd\x82\xd8\x3b\x9d\x4f\xee\x13\x24\x40\xf5\x13\x9b\x71\x3e\xb2\x01\xab\x2c\x68\x0b\x12\x79\xf9\xfb\x0f\x51\xf9\x83\x01\x30\xa5\x4a\xe9\x5c\x57\x5e\xe0\x50\x29\x1a\x23\x8a\x49\xe1\xf1\xe6\x4c\xa7\xc2\x61\x81\xe6\xb8\xdf\xab\x6e\xad\x70\x1c\xc6\x43\x96\xa3\xbd\x1a\xa7\x61\xaa\x0b\x6c\x91\xfa\x30\x8c\xa9\xa5\x10\x14\x09\xb4\xd4\x01\x2f\x77\x6e\x61\xd4\x1b\xf9\x51\x12\xb7\x15\x15\x62\x85\xad\x95\x6b\x86\xb2\xbc\x49\x77\x7c\x71\x63\x10\x6c\x40\x10\x84\xc4\x0f\xed\xae\x07\xd9\x68\x37\x26\x56\x02\x84\x60\x0e\xf5\xc7\x05\x23\x82\xa0\x96\xed\x33\x82\x61\x05\x7b\xb9\xc5\xa5\x69\x93\x39\x73\x01\x1b\x2a\xd5\xe2\x76\xb6\xd5\xc9\x95\x8e\x69\xfe\xeb\xfb\x65\x88\x3e\xa8\x97\xb7\x4b\xd6\x1a\x4b\x18\x85\x8d\xce\xbe\xbb\x60\x4e\x76\x91\xbe\x83\x75\x87\xe2\x25\x09\x3e\x49\xae\x81\x9e\x01\x86\x41\x0d\x8b\x77\x29\x0a\x2a\x78\x36\x9b\x1c\x18\x3d\xc4\x68\xa9\xdf\xca\xc0\x76\xb6\xf1\x0f\xb4\x67\xa3\x51\x73\x39\x0c\x20\x08\x70\x53\xee\xd5\xef\x36\xdd\x08\xed\x61\xc5\x4f\x58\x59\x0c\x42\xc0\x40\xb8\xe3\x8f\xfb\x4e\x81\x2c\x81\x5e\xc7\x1c\x5a\xdb\xa4\x55\x6d\x4e\xce\x6c\x36\x6c\x02\x37\x1c\xb6\xf5\xbb\xe5\x80\xee\x75\xdb\x4d\x7d\xf4\xe3\x09\x53\x8b\xd3\xb6\xd9\xce\xe8\x11\x68\xa9\x6b\x86\x85\x73\x74\x9a\x07\xdb\x12\x41\x13\x21\xd4\x0e\x42\x11\x8c\xeb\x6e\xab\x72\x9d\xa1\xcd\xdd\x1b\x94\x0c\x82\xb2\xbe\xed\x92\x8a\xc4\x0e\x4c\xa5\x80\x6e\xac\xf6\x49\x0b\xe5\x12\x81\x42\x57\xe3\xcd\x12\x3b\xcf\x4e\xd9\x58\xf5\xbc\xfa\xa0\x26\xbe\x38\x6a\xc4\x02\x42\x34\xd6\xd5\x41\x39\xa4\x88\x5a\xa2\xa0\x54\xb7\xbf\x7c\x16\x8f\x1c\x7e\xa5\xe3\x31\x79\x10\x5e\x22\x8f\x43\xb0\xd8\x98\xa8\x49\x15\xab\x71\xb5\x2b\x81\xa6\xb1\x18\x6f\xc3\xcb\xf4\x34\x07\x9f\x91\x59\x8b\x10\xd5\x83\x39\xc6\xd0\x57\xd3\xd3\x71\x6b\x55\x68\xca\x63\x41\xc9\x5f\xb9\xa2\x85\x7c\x61\x97\x60\x47\xe9\xe1\x51\x33\xd7\x7d\xf2\x3a\xc7\xce\x17\xaf\x57\xcb\xf1\xab\xf9\x6d\x14\x2f\x2e\x1c\x34\xde\xfd\x0e\xfa\x49\xa6\x5a\x25\x7c\x9f\xd5\x74\x15\x32\xe1\x5e\xc2\xa1\x41\x9f\x98\x98\x9e\xa6\xb4\xeb\xf8\x13\x0e\x5c\x9f\xe2\x26\xfc\xca\x36\x76\x06\x84\x7f\xcb\xce\x6c\x3d\x8d\xef\xa3\x76\xbe\x6f\x81\x1a\x6f\xf9\xdf\x54\x65\x6f\x36\x29\x63\x73\x49\x74\x84\x45\x51\x8e\xcb\x83\x7b\xcb\x3f\x01\xaa\x00\xe5\x82\x91\xbc\x24\x43\xd9\x87\x6d\xa9\x7b\xff\x63\xd8\x5b\xc7\x29\xb9\x8f\x6e\xb4\x2e\x25\xa5\x9d\x85\x4a\x9e\xf7\x4f\x79\x63\x93\x79\xf4\x59\x7e\x49\x33\xca\xd8\xf6\x63\x67\xc1\x4b\x5e\x3a\x7a\x78\x7c\x25\xb4\xf2\x42\xf1\x92\xbc\xac\x24\x81\xa6\x29\x78\x02\x93\x54\xbf\xa6\x51\xae\x45\xa1\x16\x59\xea\x52\xe5\xa2\xe5\x0f\xc6\xe2\xe7\xd2\x8c\xf9\x29\x05\xb8\x57\xa5\xc6\xba\x82\xb8\x32\xcc\xfe\x45\xa0\xef\x77\x60\xf6\xb9\x37\x7c\xd6\x30\x02\x1b\x02\xa3\x82\xb8\xdc\x63\xdc\xa2\x12\xb6\xb1\x85\x02\xb4\xbc\xd4\xcf\x67\xac\xbe\xf7\x93\x06\x6d\xdb\x64\x4c\xc0\xb8\x49\x4b\x81\xd5\xec\x46\xf2\x05\x9a\x2b\x82\x9c\x03\x45\x00\xde\xda\x2d\x4a\x5b\x05\xe3\xb0\xe2\x08\x2d\x97\x9b\x66\x6d\x15\x96\x03\x94\x06\x53\x5a\x62\xd4\x95\xa3\xf6\xc7\xa9\x92\xd7\x6d\x33\x29\x06\x9c\x6e\x12\xf4\xff\x55\x05\xd4\x1e\x1e\xa6\xa1\x2a\xcc\xfa\xd8\x02\x47\xfb\x85\xd1\xc2\xfd\x3e\x2a\x4e\x44\xcc\x86\x3b\x05\x2e\x4b\x87\x6e\x1f\x02\xf1\xa9\xcb\xde\x66\x04\x23\x9b\x93\xa2\xbf\x17\x32\x30\xa8\xc3\x8f\xba\x6c\xbf\x44\xb3\xb1\x77\x0c\x24\x90\x35\x66\x2d\x79\x8d\xcd\xb5\x25\xd4\xd5\x1d\xb4\xa0\x76\xa9\x66\x8c\x16\x60\x2b\xd0\x3f\xa7\x8d\x81\x01\x4c\xf6\xae\x35\xd3\x84\xe8\x02\xc7\x60\x9b\xe6\xfd\xb1\x56\x2d\x4c\xa5\xdc\x2e\x0c\x42\x71\x03\xb6\x8d\x7e\x9a\x77\x3b\xe3\xd9\xa1\x77\x2c\x85\x0a\x78\x04\xaa\x9b\x31\xd2\xc9\x9b\x89\x75\x28\x39\x1c\x75\x79\x09\x8a\x6d\x76\x53\xcc\x05\x88\x90\xe9\x30\x1d\xa0\xdd\x31\xec\x8d\x71\x7f\xe7\xcc\x1e\x46\x60\x01\x6f\xe6\x96\xa9\x11\x78\x4e\x8f\x24\x2a\xb6\x8a\xfb\xf3\x30\x6e\xe4\x5c\xce\x9a\x9c\x9f\x0b\x7a\xec\x83\x1b\x83\xe5\x45\xcc\x1f\xe5\x90\x4e\x6f\x83\x1a\x1e\x1a\x1a\x18\x86\xe0\x67\x57\xed\x54\xbe\x3c\xc4\x95\x69\x18\xb3\xf9\x0e\x0b\xeb\xb7\x49\x23\x34\x20\x52\x8e\x6c\x94\x71\x17\x77\x4a\x3a\xdf\x2b\x50\x37\xa7\x98\xc3\x65\xb5\x02\xb3\xe0\x90\x8c\x04\xd7\xc1\x6f\xf9\x54\xd7\x9a\x85\x65\xcc\xfe\x04\xdd\x49\xe7\x3d\xb5\x04\x2b\x02\x11\x69\xb2\x23\x2a\x04\x70\x8c\x36\x84\x03\xf5\x6e\x37\xf3\x9c\xa7\xc7\xc8\xf1\xd6\x96\x67\x72\x71\xfd\xa1\x6c\x71\x1c\x20\x4b\x1e\x45\xab\xa1\xd9\x92\xf3\x65\x4b\xfc\xaa\xec\x86\xf0\xc7\x4d\x7c\xb5\xaa\x08\x7c\x9f\x7c\x1d\x6e\xb5\xa7\x03\x49\x7d\xb7\x3f\x56\x7e\xcd\xab\x69\x79\xa6\xd3\x38\x7f\xd6\xd1\xb2\xe6\x5c\xc5\x34\xfd\xe5\xac\xca\x71\x65\x60\x1c\x7d\x64\x80\x19\xdb\xa0\xad\x94\x03\x9a\x66\x11\x9e\x4a\x6e\x47\x08\x33\x2f\xe7\x56\x59\x6d\x9a\x87\x9b\xaf\xba\xf5\x7f\x18\x3b\xf3\xc2\xe4\x90\xe1\x73\x1e\x08\xee\x27\x5a\xd1\x93\xc5\xed\x69\x33\x41\xe2\xd7\xf4\xbc\x29\xdb\xcb\x87\x93\x10\xe5\x4b\x3f\xb9\xea\xde\xfe\xc8\x0b\x0e\xd0\x92\x7b\xe8\xaa\xde\xc7\x29\xa0\x56\x32\xda\x61\x40\x25\xf6\xf5\x08\xfc\xed\x70\x6a\xe8\x4c\x04\x82\x0d\xc4\x61\xec\x44\x3f\x89\x5e\x02\x64\x8f\xd0\xa7\xda\x82\xa1\x77\xdf\x20\xf9\xc5\xc7\x72\x0c\x07\xee\x79\xa2\xf3\x81\x03\x9d\xdc\x39\xca\x82\x5f\xe7\x9d\x82\x68\x0a\x7d\xb0\x53\xe5\xeb\xf6\x32\x35\x53\xe8\xe3\x57\xd4\xaf\x23\xd4\xe2\x15\xf7\xa8\xd6\xc8\xbc\x74\xa2\xa6\xd1\x70\x33\x4d\xe1\xc6\xac\xb4\x6f\xab\x51\x64\x27\x85\x9f\x71\x2f\x11\x7b\x39\xae\xb9\x87\x65\x87\x2e\xb5\x6d\x59\x87\xab\xe3\x37\x41\xb7\xab\xba\x7e\x8f\x9e\x6d\x95\x2c\xb5\x82\x9f\xc9\xbc\x3b\x1b\x87\xd5\x52\xa2\x84\xcf\xc5\x7a\x0d\x3d\x2a\xdd\xa0\x5d\x34\xf6\x94\xe1\x31\x9d\xfb\x95\x6e\x96\xec\xc0\x57\x14\x54\xb8\x77\x66\x5d\xca\x2d\xd1\x75\x17\xca\xa7\x39\xa7\xa7\xc2\x99\x52\xcb\x14\x9a\x35\x40\x3d\x03\x46\x48\x2a\x11\x6c\x06\x62\xbc\xd0\x48\x10\x22\x59\x36\xe5\xcd\xb9\x4a\x9a\xc5\xaa\x4c\xd3\x39\xd3\xb4\x2a\xe9\x63\xf2\x14\x94\x86\x2d\x41\x7d\x67\xe2\x88\x87\x7f\xfb\xa0\x2f\xc3\x1d\x43\x9b\x9c\x14\x78\xfd\x91\xaf\x72\xa9\x45\x58\xeb\x0f\x14\x74\xbb\xc6\xa2\xac\xd3\x2b\x39\x62\xef\x7b\xf1\x66\xe5\x25\xef\x80\x05\xb6\x73\xee\x38\xa6\x60\x50\x1b\xc2\x53\x04\xb1\x2c\x57\xc6\x44\x15\x03\x65\x1e\xaa\x4c\xb3\x52\x58\x0f\x7b\xdf\xb0\x1b\x90\x63\x4a\x5f\xee\x21\x9e\x5f\xc9\xea\x75\xff\xa6\xf4\x34\xaa\xe2\xa3\xc2\x1f\x8e\x64\x38\xe0\x91\x58\xd7\x7f\x16\xa9\x2d\x68\x5d\x35\xd3\xf6\xb7\x54\xe1\x61\x69\x3a\xb9\xcd\x40\x09\x3e\x33\x72\x6b\x5a\xea\xfc\x31\xe3\x83\xe1\x43\x39\x08\x15\x14\xc2\xeb\x15\xf4\xa0\xf8\x15\x49\x65\x32\x98\x60\x4f\xe0\xf3\xdd\x94\x15\xf2\x7c\x0f\xc8\x9e\x21\x54\xc6\x4e\x2d\x96\x71\x76\x95\xbb\xc2\xdf\x22\xf2\xc1\x9f\x6a\x1f\x00\x55\x8b\x4a\x84\x5d\xf3\xbb\xab\xaa\x5f\x46\x60\x67\x69\x2c\x2b\x9a\xb5\x21\x31\x8f\xce\xab\x46\x21\x4b\x1f\x71\x62\xbd\xe0\x59\x98\x81\x64\xeb\xf2\xa7\xca\xab\x2e\xd7\x3e\x03\xe1\x62\x63\xb5\x92\x78\x95\xe7\x99\xac\xaf\x22\xa3\xe3\xfa\xdc\xbe\xba\x08\xc2\x6f\x2b\x06\xbe\x6f\x41\xa2\x12\x59\x03\xa1\x5f\x91\x10\x4a\x96\x86\x60\x04\xab\x83\xed\x8d\x50\x56\x07\x48\x42\x83\xbb\x19\x26\xac\x4e\x33\xf3\xa9\x54\x66\xaa\x58\x25\x21\xca\x45\xae\xe2\x95\xfb\x63\x6a\x1b\xd5\xfc\x07\x37\x2f\xbb\xe0\x04\x8e\x5f\x94\x58\x48\x70\x88\x59\xcb\xf7\x5d\x2e\xbd\x24\x91\xa9\x21\x4f\x71\x3c\x4b\xea\xc1\x59\x64\x9a\x67\x7f\xda\x43\x9a\x68\x9a\x73\x23\x4a\xcb\x0b\x08\xdb\xf2\x23\x7c\x4c\x52\x38\x29\x05\x7d\xf5\x42\x2e\xdb\xea\x13\x12\x01\xbb\x84\x0c\xd0\xdd\x6c\x1d\x57\x01\x7d\xd5\xf6\xe2\x74\x38\x30\xa6\x6f\x27\x90\xf8\x90\x84\x4a\x4d\x27\x36\x58\xff\xa6\x6d\x2d\x28\xb0\xce\x56\xca\xd2\x7c\x3b\x4e\xfe\x63\x8c\x4c\xd5\x9c\x9b\xf4\xa5\x2a\xa0\x54\x49\x4f\x97\x5b\x33\x42\x36\x16\x18\xa6\x24\x97\x22\x24\xf4\x68\xcb\xa5\x46\x86\x8a\xa5\x02\xb8\xc2\xf4\xcb\x55\xf9\xa6\x32\x03\x2a\x01\x06\x80\x97\xa3\x1d\x40\x50\xad\xe1\x13\x18\xb2\x69\xc8\x31\x85\x3f\x4e\xe2\x28\xd3\x58\x56\xb9\xe4\x94\x2b\x8d\xcc\x28\x5b\x70\x0e\xb8\x6b\xdb\xaa\xc7\xce\x02\xdf\x95\x52\x3b\xc8\x08\x3c\xec\xb2\x34\xae\x2e\x79\xbd\x41\xbe\x94\x95\xf6\x4b\xaa\xea\xaf\xb2\xd0\x34\x10\x8c\x8a\x9e\xd5\xba\xbd\x6b\xf5\x58\x49\x3a\x23\x26\xe3\x26\x47\x4b\x45\xf6\x2f\xfa\xc5\x31\xb4\x6c\x9b\x74\xfa\xc2\x6b\x00\x2a\x13\xce\x8c\xf0\x31\x96\xf3\x81\x4d\xe9\x90\xdf\xff\xe3\x90\xa5\x76\x5c\x6a\xac\xed\x45\x00\xac\x80\xaf\xf6\xb0\x7c\xab\x34\x7b\x5b\xca\xff\x5d\x95\x4f\x5e\xa3\x9c\xe0\x97\xfe\xd7\xf4\x95\x13\x68\x2d\xcb\x50\x9e\x93\xe2\xcc\x61\x9a\xeb\x81\xd9\x72\x00\x90\x21\xf4\xff\xfc\x12\x88\xd3\x44\x26\x86\x06\xfb\xdb\x02\x9e\xef\xb2\x73\x85\xea\xdc\xdf\xc6\x80\x9d\xa8\xf8\xf6\xe3\x32\x74\xe4\x70\x3a\x96\x01\x0e\xaa\x5a\xd4\x37\xd6\xf3\x23\x67\x82\x3b\xa2\xd2\xae\xed\x51\x52\xca\xac\x9f\x0e\xe7\xfd\xae\x80\x09\xf9\x5d\x9b\x43\xf7\x1a\x26\x02\xbf\xea\x07\xd2\x5d\xb8\x2a\x33\xd6\x04\x34\x7b\x49\x63\x21\x75\xe1\x1f\xbc\x05\xfe\x1b\x00\x55\xdc\x94\x28\x0f\x29\xf9\x64\x7b\xbb\x29\x86\x39\x93\x36\x10\x27\x39\xa1\xbb\x6b\xc5\x82\x5a\x69\x97\xc3\x3a\x74\x47\x59\x73\x3a\x6d\x44\xc3\x5e\x51\xb4\x64\xf0\x81\xd6\x5b\x7b\x73\xa4\x34\x56\xae\x5e\xc0\xa8\x49\x55\x6c\x4f\xf6\x14\x5d\xce\x43\x57\x4c\xb5\x97\xe6\xfa\xb1\x65\x3e\x11\x46\xef\x8a\x9b\xbc\x4a\x60\x17\xa6\xc0\x28\x16\x7a\xf9\xa4\xcb\x55\x91\x0f\x4d\x80\x10\x2b\x2d\x55\x3d\x53\x1a\xf5\x16\x63\x64\xe3\x6b\xb6\x30\x86\x82\x0a\x5b\x28\x13\x05\x5e\x4d\x78\xb4\xc3\xb1\x34\x3c\xa4\x26\x94\x4a\xf6\xbf\x9f\x42\x52\x5e\xd6\x8f\x31\x41\x5a\xac\xae\x02\x25\x84\xe9\x0a\xa9\x3e\x5c\x0c\xd0\x77\x5f\x14\x05\x7a\xb0\xb3\xa8\xaa\xfb\xac\xfa\x5b\x43\x49\xe7\x71\xd2\x2b\xca\xce\xab\x5a\xa5\x13\x6d\x6e\xeb\xd0\x41\xce\x7b\x37\xba\xb5\x97\x60\x62\x1d\x5e\xd4\x12\x0c\x9a\x25\xdd\x66\x72\x20\xf4\x1b\x74\x1d\xa2\xda\xc6\xa7\x45\xff\x8a\x3d\x48\xaf\x04\xc8\x2b\x28\x2e\x8f\x54\xe3\xdf\x9b\xed\x44\x2e\xed\xe8\x03\x56\x8c\x78\xea\x55\x62\xe5\xe5\x32\x7c\xf7\x9c\xf0\x4a\x29\x75\x87\x63\x56\xff\x04\x28\x33\x01\xf8\x89\xb6\xa9\x49\xe7\x2b\xba\x45\x50\x78\xd8\xea\x10\x89\x7c\x44\xd6\xee\x16\x9a\x70\xf2\xea\x89\x8e\xb4\x29\x03\x99\x9f\xe7\x1a\xd7\x38\x30\x12\x23\x59\x4f\x9c\x4b\x32\x55\xf1\xff\x83\x88\xb9\x43\xb4\xc9\x01\xbc\x71\x26\xd0\xc6\x06\x02\x0a\xc7\xe6\x83\x78\x9f\x9e\x4a\x8f\xe5\x9a\xd4\xaa\x1b\x2f\xcf\xeb\x92\xa7\xda\xd7\x8a\x0d\x74\xc5\x45\xa2\x9e\x9a\xfc\xb6\x04\x5a\x36\x0d\x20\x87\x39\x61\x39\x8d\xab\x78\x2c\xe0\xa5\xda\x87\xf0\xc2\x84\x67\x2d\x47\x9c\xe9\x0d\xfa\x45\x80\xfc\x3e\x1a\x49\x97\xc8\xce\x58\xd8\xe9\xa4\x53\x55\xde\x2a\x1b\xea\x62\x5d\x3d\x59\xac\xb3\x7c\xcd\xab\xf0\x21\xfe\x02\x65\x8a\xc5\x27\x1c\xed\x2d\x8a\x45\xac\xad\x92\x5e\x24\xd2\x6e\x62\xbe\x07\x9a\x4b\x71\x99\x36\x49\xcc\x2e\x1d\xc2\x84\xc8\x03\x6a\x03\x41\x3d\x54\xc1\x75\x0d\xdb\x8a\x93\xb3\xda\xb5\x66\xc3\x24\xc4\x3a\xd1\xc5\x21\x51\xd2\x16\x75\x5c\x79\x25\xdd\x9c\xf6\xa2\xab\x1b\x34\x82\xe0\x0d\xfb\x0e\x00\x33\x6e\x44\x20\x27\x16\x95\x60\x83\xb2\x7a\xb4\xe1\x8e\xfc\x57\x8d\x15\x4c\x0e\x2a\xd7\x20\xba\xd3\xd8\x0f\xe5\xec\x3f\x6d\x25\x40\x2d\xcb\x52\xe4\xeb\xdf\xf0\x2c\xfc\x6c\x6a\xde\xcd\x2e\x6c\x0a\x31\xc7\x1d\xba\xcf\xea\x10\x40\xd0\xc9\x61\x9d\xe2\xe9\xba\x5c\xf7\x92\x1c\x9e\x3c\x6b\xf6\x3c\x50\x20\x1a\x94\x27\xfe\xa4\xec\xf3\xc3\x68\xc6\xda\x43\x18\xaa\x0e\x2d\xec\x70\x2f\xef\xa8\x93\x17\x02\xf2\x95\xe8\xb4\x5a\x07\x08\x8c\x44\xdc\x8c\x73\x23\xc1\x9f\x4d\x1a\x34\x14\xab\x52\x96\x2c\xd4\xb3\x96\xe3\x34\x46\x1f\xc0\x0a\x40\xb7\xaf\x7e\x2b\xd7\x83\xca\x32\x70\x17\xa7\xa9\x26\xce\x5b\x72\x5b\xb0\x7c\xdc\x4b\xe0\x21\x89\x7d\xaa\xc8\x23\xb0\x81\x83\xaf\x50\x8a\x2d\xb1\x99\xf3\xba\x8f\x52\x5c\x87\x22\xd1\xee\xba\x90\xb4\xbf\xca\xb2\x02\x6e\xb7\x5c\x93\xe7\x51\x01\x47\x86\x15\xdd\xfe\x57\x15\xac\xa3\x13\x7b\xf8\x28\x41\x73\xf6\x4b\x9e\xcc\xba\xa7\x58\x91\x0e\x8e\xbf\x00\x1e\xaa\x93\x1c\x89\xd9\xae\xe5\x63\x34\xf3\xd0\xf0\x4d\xc7\x89\xdb\x10\xfd\xc3\xe5\x32\x1a\xe8\x59\xe9\xf7\xcb\x5f\xf2\x3c\xfe\xad\x92\xbe\x78\xf5\x24\xca\x24\xfb\xbf\xed\x03\xfd\x38\x9f\x14\xdb\x8e\x06\xb1\xd9\x5b\x81\x6f\xf6\xfe\x9a\x65\x56\x32\x31\x1f\x28\x19\xee\x6a\xc1\x02\x60\xb5\x6d\xa8\x60\x69\x1b\xa3\x93\x60\xcc\x6b\x2d\x90\xc0\x90\x3e\x7b\x31\x51\x7e\xe4\xd2\x86\x41\xef\x65\xd1\x66\x9f\x26\x61\x35\x2b\x2d\x8c\x77\xfc\x14\xad\xb9\x2c\x69\x72\xef\x51\xd6\x48\x9f\x83\x98\xe3\x41\xc0\xb3\x5f\x42\xdf\x1b\xdf\x40\x49\xad\x79\xe1\x5a\x72\x6f\x13\x2f\xd8\xd4\x6d\x4a\xe8\x29\xd8\x97\x1f\x65\xa5\x41\xe5\x68\x3e\x35\x62\x84\xa6\x7d\x30\xb8\xb7\x14\x76\xa1\xa2\x71\x56\x50\x25\xd0\xda\xbb\xb9\xae\xf0\x32\x77\x3e\xf9\xe0\x1f\x79\xdf\x2e\x2b\xb9\x03\x4d\xfe\x6a\x0e\x36\x2a\xbc\x86\xa3\x31\xd7\xec\x5d\xf2\xc7\x62\x16\xdf\x78\xd6\x18\xa8\xbd\x7f\x09\x23\x02\x2e\x56\x01\xd8\x04\x37\x8d\x71\x66\xa5\xb7\x30\x13\x5d\x7a\x99\xf3\x1d\x58\x8f\xce\xc5\x7a\xe7\x91\x6a\x97\xe6\x5d\x87\xc0\xb9\x55\x53\xa7\xed\xf8\x04\x1e\xd4\x52\x7d\x71\xfa\x34\xe7\xfe\xc5\xd9\xe8\x2f\x5a\x19\xc8\x1c\x96\x61\xe2\x9d\x87\x1f\xbe\x39\x19\xbf\xfd\x4f\x52\x60\xba\x6e\xcb\x39\x93\xad\x25\x91\xb6\x58\x58\x3a\xd9\xf0\xa8\x79\x8d\x9e\xef\x68\x6e\x22\x3d\x5b\x74\xe8\x94\x77\x07\x2c\xd0\xcd\x79\xf9\x1e\x0b\x5b\x49\x99\x5f\xd0\xa0\x2d\xe5\x43\x09\x99\x8e\x5f\x10\x03\x24\xe5\xec\x10\xf5\xba\xfb\xa8\x28\x19\xfc\x13\xe9\x38\xbb\xde\x54\x35\xb7\x04\x4b\xc9\xb5\x1f\x01\xaa\xe2\xd4\xd1\x24\x92\x08\x9f\x49\x8e\x95\x58\xdd\x1f\x88\xaa\xbb\x68\x10\xe5\x25\x96\x72\x4a\xf6\xee\xe3\x51\x91\x82\x6f\x00\xaa\x38\x96\x07\xfc\xf4\x6a\x1b\x81\x6d\x12\xb8\x8a\xb2\xbd\x85\xf4\x7b\x63\x50\xc6\x53\x8c\x0a\x85\x42\x04\xbd\xf2\x1c\xd4\xd0\x97\xae\x54\xbe\x3f\xbd\xdc\x59\x9d\x15\xce\x65\xad\xbc\x8d\x13\x32\xf5\x50\xcb\x94\x49\x51\x17\x63\xbe\xd0\x43\x22\x56\x49\x27\x8e\x9c\x77\xb5\x73\x8e\xcc\x91\xe3\x31\x5e\xfd\x14\xb0\xe5\x66\xad\xdc\x0c\x39\xe1\xde\xa1\x43\x44\x62\x85\x7d\xdc\x89\xc1\x5f\x2d\x0e\x82\x7f\xcc\xb2\x5d\x3f\x0c\x0f\x8e\xc3\x62\xb4\xac\x1a\x36\x4d\x30\x29\x00\x66\xb0\x7e\xf8\xae\xf7\xb7\x0a\x0e\x8b\xb6\x77\x3d\x53\xf7\xe7\x68\x11\x57\x68\x67\x66\xdf\xea\x94\x1a\x48\x9a\xe6\x4a\xb2\x19\x35\x43\xda\xfb\x5e\xc2\x8b\xed\x00\x8d\x68\xbe\xe4\x9f\x18\xb2\x6d\x62\x90\xd3\x6c\xc4\x0f\x2c\xc4\x2f\x54\xdb\xf6\x57\xb4\x80\xfe\x19\xce\x84\xb1\x30\x97\xab\xd1\x63\x4b\xb4\x69\x60\xf6\x9e\x89\x2e\xb0\xed\xbb\x99\x77\x7d\x38\x8a\x97\x53\xeb\x99\x2b\x71\xc6\x43\xe8\x1b\xfb\x43\x5d\x28\x47\xcd\x1a\x64\x3b\x12\x58\x3b\xfe\x7a\x60\x3d\xcb\x75\xf0\x6b\x15\x1d\x11\x16\xae\x16\x52\x9c\x7b\x6c\xd0\x63\x2d\xf0\x70\xb9\x41\xdf\xc7\x23\xc5\x72\xb0\x3e\xad\x3a\x95\x30\x69\xe4\x39\xd6\x07\x56\x75\x25\x52\x47\x87\x6c\x59\x4b\xab\x82\xeb\xb4\x6b\xb3\xf3\x30\xe3\xf5\x59\x56\x34\xcb\xc0\x92\x96\x13\x10\x7e\xf4\x51\x74\x06\x98\x71\xae\xbd\x89\x12\xd3\xf0\x65\xeb\x00\x1a\x21\xff\x75\x88\x4f\x04\xa7\xe2\xcd\x13\x41\x74\x36\xcb\x93\xaa\x1a\x9c\x1c\x10\x82\x9a\x0c\xde\xa0\xcf\xaf\x07\x59\x49\xae\x81\x56\x3b\xf5\x4e\x30\x1a\xaa\x06\xf7\xf9\xc2\xd3\x65\xdd\xd4\x1e\xd4\x04\x71\x74\x8f\x31\x0f\x1b\x5c\x4c\x4e\x0b\x27\xc3\xcf\x9f\xe5\x92\xc0\xa7\xf8\x93\x87\x65\xb1\xe5\x59\x1f\x2b\x1c\x52\x63\x7b\xd1\x94\x45\x39\x68\xc5\xfc\x51\xef\x89\x64\x93\x41\xc6\x99\x30\xe5\x65\xcb\x89\xf0\x16\x35\x9f\x00\xa2\x97\x45\x22\xef\x7e\xe1\x5f\x4b\xa5\x7a\x36\xa1\x44\x89\xe5\x4d\xcd\x2a\x77\xaa\x1a\x1c\xac\x37\x76\xa7\x96\x60\x2c\x04\xef\x15\x4b\xdd\x8c\xee\x5b\xe9\x10\xe3\x11\x5e\xce\x32\xb2\xcc\xd9\xc3\x52\x97\xea\x13\x13\x4f\x78\x04\x86\x86\xdb\xbd\x5c\xcf\x54\x2f\x91\xea\x29\xe6\x10\xfd\x66\x9a\xd2\x08\xa1\xd0\xb7\x6d\xfb\x35\x0c\x05\xd0\x08\xd7\x56\x68\xcc\xd6\x23\x90\xa7\xde\x8a\x14\x07\x9b\xc4\xf5\x7d\x3f\xb0\xff\xff\x78\x2c\x99\x27\x20\x1a\x1a\x46\xfd\xa6\x7b\x30\xa1\x8d\xd1\x4b\x9a\x88\x52\x93\x57\x75\x17\x30\x2c\xec\xf4\xff\x49\x9b\xf9\xd0\x59\x83\x8f\x36\x33\x25\x51\xb3\x69\x0b\xd3\xfb\x96\x2e\x17\x37\xb7\xa9\x30\xc5\xaf\x78\xdf\x12\xe1\x42\xef\x00\x6a\x7f\x31\xfd\x6c\xcd\x6f\x74\x3f\x27\x87\x83\x68\x6b\x3e\x51\x39\xec\x64\x7a\x8f\x1a\xaa\x3f\x82\x46\x6e\x2c\x4c\x43\xe8\xb2\xc3\x1f\x95\x7b\x7d\xc2\x69\x4b\x35\x17\xe4\xb9\x51\x01\x93\x90\xbb\x72\x78\x09\xb0\x9e\x0a\xa5\xe9\x2c\xdf\xa6\xe8\x0e\x93\x9c\x7e\x21\x8e\xf4\x70\xd2\x5e\xb2\xd7\xc3\xc3\x83\xd4\xbd\x82\x47\x52\x96\xe8\x87\x59\x6f\x1a\x83\x5d\xc9\x2b\xd5\xa2\xcb\xa5\x96\xa1\xc3\xcd\x1e\x1a\xc1\x29\xf1\x0b\x79\x97\x8f\x4c\xe7\x99\xa4\x36\x65\xa5\x68\xdb\x4f\x24\xd2\x15\x3c\x7b\xae\x8d\x6c\x41\xce\xe5\x7b\xe4\x5b\x0e\x1b\x15\x3d\x55\xe1\x1a\xa9\xae\x35\x2f\x8e\xa8\x73\x0f\x93\x26\x34\x33\xc0\x9f\xe1\xae\x3f\xaa\x0c\x23\x52\x22\x29\xb3\xf6\x9f\x60\x91\x47\x30\xa5\x41\x85\x4f\x9a\x7a\xce\x21\x00\x86\x0e\xd6\xf2\x90\x7e\x0c\xc2\x75\xdc\xe2\x38\x51\x5f\x6a\x4d\xd2\xde\x54\x33\x73\x27\xf2\x4c\x8b\xe4\x5e\x23\x1a\x56\x84\xa5\x0c\x15\x30\x12\x56\x5f\x7b\x15\x58\xea\x7b\x9a\x72\xb3\x30\x62\x94\x7d\x4b\x72\x83\x1b\x50\xc7\x02\x15\xf0\xaf\x29\x40\x77\x86\x05\xab\x37\x55\x39\x04\xce\x2f\x8d\x7e\x54\x32\x00\x84\x5e\xc0\xcc\xcd\x56\x38\xb8\x30\xf0\x7d\x00\x40\xc3\xaa\x62\xef\xcf\x4e\xd6\x20\x99\x72\xc7\x26\x47\x6c\xd1\x38\xc7\xb9\x8a\xaa\x63\x8a\x02\xe8\x08\xac\xc6\x0a\x8e\x87\xbd\x41\xca\xd7\x23\x1d\xfa\x21\x1f\x6a\x61\x7b\xa2\x70\xdd\x17\xec\xf9\xbb\xee\xe1\x13\xa2\x27\xb5\x86\xa0\x37\x32\x65\x7c\x00\xa2\x52\x6c\xe3\x63\x74\x07\xa9\x7c\x6b\xd9\x96\xd3\x4b\xff\xde\xd5\x84\xba\x7d\x35\xc9\x74\x32\xc0\x5e\xd1\x34\xb1\xab\xd3\x5f\x96\xbd\x92\xcc\xb9\x47\x82\x19\xe8\xc1\x0f\xb4\x48\x74\x7d\x93\xc2\x19\x3a\x14\x5b\xb6\x35\x70\x5b\x75\xa8\x27\xb8\x3a\xdf\x28\xdf\x76\x23\x62\xc5\x17\x54\x65\x58\xf0\x59\x4f\x5e\x12\x3f\xa7\x80\xcf\x6a\x0b\x5f\x42\x52\xc1\x33\x93\xc4\x82\xeb\x95\x9f\xb3\x0a\xf4\x8e\xf3\x5a\x8d\x61\x87\x88\xbe\x97\x5e\xb7\x43\xb5\xa1\xb9\x83\x8f\x94\xc7\xe4\xce\xf8\xc3\x5a\x3b\x40\x0f\xfd\xb2\x92\xb0\xa8\x4d\x39\x55\x56\xf7\xbc\x4e\x8b\x79\x9b\x1f\x46\x38\xdf\xae\x79\xaf\x86\x02\x2b\x22\xe4\x43\x30\xbf\x07\x7d\x77\xf8\x37\x58\x01\x2e\xd4\x5a\x7b\xe0\x56\x07\x87\xec\xae\x6a\x80\x77\x15\x07\xd4\x6d\x31\xef\xef\x72\x4c\xa1\xbb\xcb\x16\x40\x98\xaa\xea\xbd\xa5\xa6\x18\xf9\x23\x5d\xfa\x20\x7a\xb3\x33\xf5\x51\x65\x53\x8e\x7f\x9b\xa8\x6c\x67\x28\x91\xb5\x61\xfe\x2c\xb8\x8a\x56\xaf\xd0\x4e\xb3\xd6\x69\x44\xe5\x8a\xb4\x8a\x10\xec\x8c\xcd\x00\x6e\x67\x09\x6d\xd6\x63\xed\x73\xf5\x80\xc0\x1e\xae\x2d\x7d\x47\x93\x1e\x2b\xf9\x15\x47\xad\xb7\xff\xd9\x41\xf2\x5f\xd6\xf9\x3b\xeb\xf3\x6a\x36\xf5\xa2\x81\x46\x51\xd0\x6c\xe4\x18\x51\x82\xb5\x41\x8a\x30\xfd\x53\xf5\xb0\x45\xad\x11\x23\x48\x75\xbc\xb4\xdc\x77\x8b\x8e\x04\xfc\x4f\x8f\x36\x54\x13\xbe\x51\xf7\xee\xa3\x1b\x87\x8d\x72\x86\xdd\x48\x5b\x1f\xb2\xf3\x8a\xf4\x94\x87\xcc\xb6\x46\x63\x16\x8a\x1a\x53\x35\x4b\xb1\xd2\xaa\x52\xef\xf7\xa5\x48\xf9\x1e\x3e\x7f\x36\x23\x06\x27\xdb\x97\xc2\xa7\x92\x2f\xfa\x42\x45\xf7\x69\x5c\x67\x8c\xe8\xd7\x28\x2c\x52\x07\xbd\x92\xfb\x8d\x68\xe1\x0a\x5e\xd7\x6d\x10\xdc\x8f\x37\x0e\x00\xa9\xc1\x94\x02\x78\xc1\xc4\xf4\xc6\xa0\x1e\xf6\x97\xcb\x1e\x7d\xb2\xc3\x73\x0e\x68\xe6\xf5\x6e\x61\x45\xba\xae\x66\x96\x13\x7c\x2a\x22\x13\xdc\xb8\x0b\x50\x5c\x6a\x6b\xfa\x5a\x96\x58\x3e\xee\xe9\x72\x01\x74\x84\x07\x7f\x5c\xa3\xb7\x72\x9a\x95\x0f\x2c\x14\x62\xa1\xd8\xef\x22\x63\xcd\x55\x9b\xa7\x5c\x17\x81\x62\xb4\x4f\x37\x1f\x5e\xc2\xf5\x69\xb9\xb8\xf4\xec\x65\xc4\x01\xb9\x57\x64\xd7\x8e\x71\xa2\x7b\x5c\xe3\xf4\xa2\xcd\x95\x06\x1b\xa3\x85\x65\xab\x5a\x28\x00\x87\xeb\x14\x12\x7c\x67\xe3\x85\x2b\x25\x50\x26\x93\x08\xbf\x6b\x34\xea\xfd\xa4\x2d\xc7\x28\x09\x36\xfe\xb1\xba\x57\x4d\xcd\xaa\x83\x89\x39\x05\xfb\x7d\x31\xe8\x10\x23\xbe\x54\x11\xf2\x29\x92\x6e\x90\x16\x98\x43\xeb\x7d\x6f\xc9\x54\xe2\xd4\x59\x92\x80\x40\xc4\xf0\xd8\xde\x07\x2b\xa3\xac\x12\xc1\x58\xa7\x6b\xd8\xe0\xf0\x3f\xee\x81\x34\x0f\x4d\xbe\x95\x3a\x7e\x21\xe7\xb1\x72\xe0\xac\xd7\xbb\x82\x72\x79\x4f\x31\xb4\xc7\xc4\x3a\x96\xb0\x38\xe1\xcc\x64\x84\x02\x87\xe7\x23\xf1\x35\x2c\x29\xec\xba\x31\xf1\xb2\x1d\xc3\x26\xd5\x4e\xd2\x49\xb9\xca\x96\xff\xb8\x1a\xe5\x73\xee\x02\x04\x3f\xd7\x5e\x70\xa9\x28\xdc\xaf\x4d\x55\x43\x8b\xde\xcd\x29\x7a\x61\x6d\xed\x8a\x39\xb5\xac\x4e\xf3\x59\x80\x9d\xe9\x7e\xc5\xfa\x49\x0c\xf1\x69\x0c\x26\x5e\x25\x9e\x4e\x69\xd5\x40\x45\xdd\xaa\xe7\xf8\x4a\x42\xb1\x1b\x5f\x23\x21\x42\xe9\xce\xc1\xc6\x77\xab\xd0\x6d\x40\x1f\x6d\x40\x60\xf4\x3a\x62\x5d\x8c\x52\xa6\x4e\x28\xf5\x51\xdd\xa6\xc1\xa6\x11\x32\x8b\x70\x8d\x60\x43\x63\xcb\xef\xab\x58\x48\x1d\xc4\x56\xf4\x3b\x9c\x68\xd7\xaa\xa0\x7c\x1e\x0e\x3a\x0f\x42\x50\x05\x2c\xa5\xf6\x48\xd8\x23\x62\x38\x13\xe8\xb6\x47\xf8\x1d\x82\xb2\x63\x04\xff\x23\x9d\x8c\x1a\x0f\x8c\x17\x38\xc4\x61\x6b\xdf\xee\x30\x1e\x80\x8f\x25\xd8\xe8\x4c\x07\xb6\x68\x72\x26\x8c\xb5\x2b\x0d\x9f\xfe\x16\xc4\xf3\x83\xfd\xa9\x59\xf8\xb6\x25\x0b\x97\x9c\x93\x8d\x24\xcb\x17\xbd\x47\x87\x55\xba\xa7\x25\x03\x1c\x5b\x4b\x0b\xbb\xe6\xb8\x71\x34\x9e\x14\xa5\xc1\x13\x8b\x81\x37\xdc\x23\x3d\xa5\x21\xd5\x47\x83\xee\x35\xc4\xbd\xe1\x76\x1f\xca\x93\x5d\x4f\xa5\x6c\xaf\xc1\x0c\x5f\xfc\x9b\x08\xc9\x30\x2d\xf6\xd9\x58\xea\x63\xb2\x09\xcf\x70\x02\x6d\x31\xf4\x14\x66\xb8\x75\x6b\x41\x06\x7d\x5e\x95\x53\xed\xe3\xa6\x53\x2b\xf7\x26\x61\x2f\xbf\xe8\x41\x38\xe7\x2c\xc1\xbf\xfa\x88\xe3\x81\x17\x03\x72\xf3\xb1\xe9\x33\x89\xee\x6c\x23\x16\xe3\xd0\xdf\xdd\x63\x2b\x6f\x25\x6b\xb5\xe5\x0a\xdd\x85\x4a\xeb\xe9\xf1\x78\x08\x3d\x94\xb3\x45\xfe\xec\x7b\x93\x05\x7a\x37\x16\x13\xb4\x46\x75\xd9\x44\x09\x6d\xc6\x0b\xe1\x80\x09\x8f\x58\xb5\xf6\xbf\x54\x9b\x6d\xb7\x00\x1f\x99\xda\x8a\xf1\x89\x51\x64\xd4\xb9\xf6\x30\x4c\xa6\xc2\x97\x3c\xcd\xe1\xa1\xfd\x9b\x7c\x8c\x7d\xb2\x95\x68\x3f\x89\xc1\xac\x5c\xa7\xb3\xfb\xcf\x14\x63\x14\xda\x3d\xa8\x87\xec\x10\xf1\xf5\xcb\x3d\xf8\x2e\x73\x25\xb6\x9a\x8d\x33\x17\x8a\x7e\x1d\x55\x64\xe5\xad\x36\xe3\xf1\xd2\x79\x24\x73\x62\x1c\x64\x8a\x7b\xc0\xc7\xe0\xc6\x9c\xeb\x23\xdf\x31\x31\x0b\xa1\x57\xd5\x24\xa6\x2d\x25\x15\x1e\x70\xd1\x51\x97\x8c\x78\x22\x2f\xfb\xad\x91\x72\x00\xa5\xc9\x3f\x3e\xd3\xa2\x1f\x75\xc8\x4c\x4a\x14\xee\xa3\x5f\x77\x9b\x3f\x33\x42\x61\xb5\xb3\x0e\xbb\xca\x16\x9d\x63\xc9\x06\x66\x7b\x3e\x21\x0e\x60\x79\xba\x76\xcc\xab\xd8\x28\x7b\x08\x54\xed\x93\xcf\x43\xd3\xc3\x55\xd3\x8c\x55\x07\x90\x23\x1b\x75\xc6\xca\xde\xd7\x3c\x1e\xc7\xa5\x88\x4f\x13\x8a\x7c\x03\x4b\x78\x74\x99\xd2\x42\x7c\xe7\x28\xff\x72\x62\x3c\xba\x68\x93\xed\xba\x4d\x82\x50\x22\x87\xe4\x4d\xd3\x84\xb9\x4f\x08\x6f\x40\x4f\x7d\x33\xe4\x73\x4a\x7f\x2f\x0e\xe6\x45\xe7\xe4\xb7\xfa\x5b\x7f\x72\x79\xbe\x28\x5d\xb8\xb1\x08\x12\x16\x14\x61\x91\x0a\x95\x06\x8a\x5b\x91\xf6\x6a\x7e\x9d\x62\xf3\x93\x53\xee\xb9\x4c\xde\x03\x3f\x9a\x5d\x0f\x4d\x95\x22\x5d\x5e\xdf\x8f\x55\x67\xbb\x5a\x08\xa9\x37\x76\xbf\x07\xc1\xfc\x72\x40\xe8\x6d\xe5\x65\x9d\xd4\xf2\x2d\x1d\x9f\x41\x4a\x56\x40\x09\xa8\x20\x3a\x43\x15\xca\x8a\x7c\xb5\xc2\xab\x9e\x39\xbc\x93\x07\xf5\xce\xca\x99\x62\x4c\x01\xd0\x76\x26\x43\x2c\x71\x66\x01\x88\xc5\xab\xcf\x56\x2a\x3a\xa7\x96\x46\x3a\x7e\x9a\xd5\x95\xdb\x21\x2c\x55\xe0\x1c\xa6\x24\x0f\x62\xb3\xbc\x59\xca\x35\xa3\x48\x5f\xd6\xcb\x38\x24\x01\x0c\xb6\x6b\x42\x54\xaa\x8b\xf9\xa3\x75\xe0\x07\xf2\x07\x3a\x0b\x96\xe1\x8d\x41\x80\xf3\xa2\x29\x7d\x34\x8d\x40\x59\x83\x2d\x04\xa1\xe6\xb0\xba\xfc\xc9\xfb\x10\xc8\x7f\x16\x2d\x16\xe8\xc0\x6b\xd8\x4e\xf2\x80\x4a\x7b\x54\x5a\x8e\xc2\x23\x53\x4f\xb4\xa3\xc2\xba\x65\xcd\x47\x08\x02\x22\x23\x48\x95\xd4\x55\x4d\xcb\xc7\x40\xbe\x6e\xb6\x2c\xb6\x0c\xe8\x45\x3c\x46\x7b\x21\x78\x03\xae\xd0\x7c\xd4\x96\x77\x8e\xf0\xad\x3e\xda\x67\xdd\xad\xc7\x7d\xa6\x12\x31\x15\x83\x1e\x80\x02\x48\x10\x04\x9c\xae\x89\xf3\xd2\x47\x06\x30\x50\x07\x64\xd9\xc3\xab\x4c\x2e\x65\x0a\x19\x99\x43\x52\xf3\x6c\x9a\x67\xd7\x83\x3c\xdf\x1e\x89\x7a\x2e\xf7\xbe\x37\x6f\xeb\xd3\x87\x72\x23\x35\x7d\x62\x08\xa4\x8f\x61\xae\x33\xcc\x7e\xf9\xcd\x9e\x29\x75\xc0\xf8\x06\xeb\x75\xf9\x82\x44\xf5\x32\xdf\x17\x1d\xbf\x3b\xeb\xb8\x8e\x6a\x55\xe6\x17\x40\xdd\xdc\x1b\xbd\x14\x75\x40\x6f\x4f\x01\x81\x18\x4b\x30\x73\xdf\x8c\xfe\x33\x31\x73\x90\x00\x58\xb6\xb5\xcc\xa5\x23\x59\x0e\xd2\x2c\xd8\xed\xbd\x0e\x8c\x88\x86\xd0\xad\xaf\x7e\x30\xd0\x82\xcd\x4f\xfd\xc4\x1b\xcb\x43\xcf\x28\x5a\x02\xdf\x19\x61\x00\x2b\xd3\xe6\xa5\x2e\x51\xf4\xf2\x72\x4c\xaf\x28\x70\x78\xf3\x71\xb9\x54\x08\x05\xb9\x8f\x7a\x73\xc4\x94\x39\xcd\xc1\x61\x2e\x72\x1d\x1d\x6c\x46\x03\x29\x36\x48\x5d\x3c\xfb\x7f\xee\x70\x9d\x23\x5c\xb4\x09\x66\x1a\x3a\xe1\x18\xbd\x5b\x06\x1d\x96\x89\x2e\xfe\x72\xb8\x88\x80\xd9\x7f\xe8\x16\x97\x01\xdb\x82\xa0\x3b\x1b\x59\x56\x0e\x45\x08\xe0\xd8\x13\x07\x79\xf9\xa0\xc2\xa6\xa1\x74\x40\x2c\x78\xbb\xc1\xc9\x80\xab\xe5\x27\xeb\x56\xc3\x27\xfa\x5e\xe9\xbc\x6d\x4c\x29\x7b\x8b\xe5\x45\xa3\xe9\xb0\x67\x07\x18\x2e\x85\xbe\x7a\x0e\x75\xd5\xf2\xe3\x26\x44\xe6\x89\x26\x33\x67\x2c\xfa\x82\x91\xbd\xff\x6b\xde\x8b\x67\x7f\x92\x8d\x06\x34\xad\x51\xf1\x89\xa4\x7a\xb2\x46\xda\x68\x1d\x16\x80\x2d\x24\xb8\x34\x1d\xce\xd3\xc2\x0a\x3e\xc6\x59\x2c\x42\xc5\x5a\x1b\xb9\x7d\xc2\xac\xe7\xc6\x76\xe2\x45\x53\x00\xfe\x78\x32\xee\x1d\x0a\x79\xab\xd3\x3c\xe0\x30\x21\xe0\xa5\x32\xd5\x84\x26\x34\xfd\x0c\xc7\x48\xe2\x51\x09\xff\x86\xb3\x7f\x0c\xe4\xef\x66\xd5\x0b\x9f\xc6\x3a\x73\xb7\xb1\x02\xdb\xb6\xe6\x6c\xc3\x08\x18\x38\x1d\xad\xa6\x90\x2f\xa8\xe6\xf2\x47\x12\x78\xc2\xb4\x94\x7d\x39\x55\xbb\x2e\xa5\x36\x90\x9c\x81\x8e\x46\x89\x36\xc7\x91\x0b\x06\xb2\x64\x9f\xbe\x2d\xa7\xc5\xab\x48\x61\x45\x8c\x5e\x89\x94\x19\x80\x42\x82\x07\x2c\x4f\xe7\xf0\xda\x2f\x0b\x69\x74\xef\x3e\xe9\x37\xc8\xcf\x51\x8f\x64\xcb\xbf\x96\x8d\xca\x6c\x66\x5b\x38\x2a\x60\x6a\x98\x5d\x65\xb7\x00\x01\xaf\x08\xce\xe5\x57\x93\xf2\xa6\x53\x79\xb5\x28\x0c\x8c\xc3\xfc\x74\xb7\x25\xe3\x1c\xde\x57\x98\x27\x4b\x0e\x26\xa4\x5d\x60\x5b\x7c\xd9\x61\x82\x5e\x35\xab\x23\x89\x53\xd8\xad\x1a\xc1\xc8\xd3\x97\x39\xbe\x67\x52\x9e\x46\x29\xf2\xe1\x40\xb6\x78\xcb\x18\x20\xb6\xd5\x73\xf3\x92\x10\xa5\x4a\x79\xf3\x57\x8f\x03\xb7\x1a\x90\x21\x93\xd3\x89\x8b\x0c\x65\xea\x09\xbe\x89\x1a\x54\xe7\x6d\x2d\xad\x16\xf3\xe8\x97\xbb\xcf\x52\x88\x5d\xf1\x63\x88\x35\xeb\x95\xa5\xca\x56\xcd\xe7\x11\x35\xd1\x7c\xb6\x83\xca\xd0\xd3\xbb\x77\xa6\x06\xab\x5b\x98\x18\x39\x08\x89\x35\xc3\x04\xe5\x46\x14\xdf\xe1\xa3\xf5\xe8\xc3\xc5\x3c\xa8\x71\x17\x74\xaf\xde\x4f\x8f\xaa\x18\x33\x85\x8f\x28\xef\x8d\x44\x8d\xc5\x58\xeb\x6d\xab\xb4\xb1\x62\xfb\xa7\x1c\xc8\x3e\x9c\x73\xf1\x20\x3e\x5b\x0d\xc0\x38\x8b\xbc\x99\x66\x8d\x47\x9e\x06\x52\x3f\x93\xb8\xe8\x3e\xb8\xab\x60\xc1\xcf\xb9\x31\x2c\x7c\x35\x3c\x7f\xce\xc9\x73\xf1\x1f\xb9\x90\x61\x2e\x16\x86\x0d\x3f\x08\x06\x77\x09\x9f\xfe\x44\x3f\x26\x20\x20\x37\xfb\x8e\x86\xb0\xc4\xf2\x8d\x5e\x1a\x69\xcb\x5c\x19\xdc\xf7\xb0\x9a\xfe\xc2\xd6\x52\x94\x7b\x5e\x0f\x64\xe5\x21\x67\x3a\xcc\xf3\x2c\x0d\x9b\xfb\xe1\x7a\xb5\xec\x00\x16\xa5\xd4\x98\xe0\x2f\x3e\x3a\x22\xb6\x59\xa6\xdc\x58\x9c\x72\xc6\xc6\x02\xf3\x12\x53\x2c\xa1\x7c\x3f\xdc\x47\x41\x58\x57\x21\x4b\x15\xd0\x3b\xe0\xfd\x3a\x99\x43\xba\x46\xad\xd7\xa3\x9a\xf3\xf6\xcb\xcb\x1a\x06\x9a\xe0\x05\xbf\x25\x48\x26\xd8\xa9\xa6\x0c\x77\x25\xef\x13\xcb\xa5\xdf\x4d\x64\xc1\x75\x79\xd1\x5a\xca\xbd\x20\x5a\x97\xe3\x37\x2a\x6b\xe1\x11\xa3\x91\xa2\x47\x5c\x39\x75\xe3\x3c\x56\xa7\xa6\x0e\xe2\x83\x6e\x85\x74\x63\xaa\xe8\xc4\x35\x57\xd4\xe2\x37\x03\x9c\x4a\x39\x5c\x60\xb0\xe8\x21\x17\xea\x5e\x4f\x77\x50\xde\xba\x6d\xfb\xea\x55\xa5\x32\x3a\xfb\xa4\x45\xdb\xb6\xd2\x08\xed\x05\x09\xa1\x4d\x41\xd2\xdb\xe9\x6a\xff\x0a\xd1\x6d\xf9\xb0\x4e\x12\xa0\x7b\x23\x33\xba\x04\x02\x6d\xaf\x02\x75\x72\xdf\xa0\x4d\x83\xa5\xb5\xda\xa4\xc9\x1a\x91\x3d\x66\x68\x8f\xf1\xba\x74\xab\xe2\x82\xc8\xc3\x46\xaa\x07\xe8\xd4\x4a\x20\xa3\x97\x8a\x5d\x93\x02\x77\x80\xfe\x27\xd3\x15\x09\xfe\xa7\xf3\x7b\xdc\xc1\xa3\x34\x98\xed\x12\x1e\x0b\xd7\x3a\xd4\x91\xac\x94\x13\xfc\x62\xc7\x90\x5e\x49\x10\xe5\xaf\xf0\x11\x72\xf2\xf5\xba\x38\x72\x83\x70\x91\x90\xb6\x7f\x88\x3a\xa4\x90\xa1\x8d\xef\x81\xff\xeb\xe0\x3b\x5e\xd6\xbf\x27\x31\x0d\xbf\xdf\x66\x40\x95\xc5\xe3\xdb\xae\x93\x8b\xa4\xca\xe1\xbe\x42\x47\x66\x03\x8a\x5e\x69\xc7\xf9\x37\x0b\x20\xc2\xfa\xb4\xad\x88\xc4\xd1\x03\xa1\xe3\x32\xef\x3e\xb2\x50\x7f\x07\xbc\x20\x1f\x5a\x2d\x2e\x82\xc3\x4d\xa0\x7a\xf8\x90\xf0\xd5\x88\x24\x4e\xbf\x03\xbb\xee\x13\xf8\xe0\x4c\xd2\x82\xa7\xf5\x1f\xd8\x3f\x30\x8f\x12\x10\xfc\x6d\xb5\xf8\x70\x48\x70\xb9\x2c\x13\xee\xfd\x6c\x70\x05\xb5\x95\xf6\x82\x23\xf9\x55\x3d\x6b\x03\xb2\x58\x62\xac\x5e\x03\xdc\xca\xd0\x41\x43\xbe\x2f\x93\x85\xa5\xdc\x1e\x72\x1b\xd8\xe7\x91\xe9\x1f\x55\x18\x55\xdc\x96\xb3\xbc\xab\xbd\xde\xa5\xb3\xbd\xed\x3c\x7f\xf9\xdc\x26\xad\x66\xb9\xe5\x95\x22\x40\xc4\x77\x40\xde\x46\x1d\xdf\x9c\x81\xfa\xf4\x36\x68\x0e\x22\x44\xe1\x7d\x84\xdc\xc9\xd8\x47\xd3\xca\xf3\x5b\x72\x8d\x39\x5c\x11\xb6\xdc\xc5\x81\x1b\xc2\xd6\x5b\xff\x45\xcf\xc5\xa9\xb9\x6d\xfd\xd7\x5d\x6c\xe8\xe8\x0e\x87\xbf\x29\x2c\xc9\x52\x1c\xe9\xa5\xe2\x48\xf6\xf9\x03\xbc\xb1\x3b\x85\xae\xf4\x80\x51\x4f\x67\xe3\x58\x6a\x48\x15\x8b\x44\xce\x7c\x89\x55\xfe\x86\xa1\xa2\xb2\xfb\x14\xff\x0b\x73\x1c\xaf\x5f\xf9\x59\xe1\xf3\x25\xfe\x86\xf4\x73\x73\x55\x06\x6b\x28\xe6\x73\xf6\x18\xb3\x46\x39\xb1\x78\x3a\xd9\xbb\x1e\x2f\x01\xf6\xea\x27\xad\x68\xcb\x4d\x6a\xcb\xac\xd6\xae\x5b\xc3\xd9\xa6\x7c\xc7\x6e\xca\xae\xe3\xc3\xa9\x40\x0c\x51\x57\xbe\xf3\xb2\x80\xa6\xbe\xdd\x9f\xca\xa5\x11\x0a\x12\x65\xbd\x8a\xaa\x9b\x37\x2b\x00\xe0\xf0\x07\xd2\x44\x7d\x04\x60\x2e\x33\x40\x8e\xd2\xc3\xaf\x79\xc9\x72\x86\x70\xf3\x92\xeb\x5f\x57\xc9\x4f\x2a\xc5\x23\xc1\x5a\xca\x4b\x34\x52\xba\x3c\xf7\x68\x44\xce\x00\x6c\xbb\x7f\x3d\x85\xb3\xcc\x0c\x72\x37\x1b\x17\xb1\x53\x29\x90\x82\x32\x70\xe9\x93\xd9\xf7\xb7\x40\xf9\x9b\x72\x35\x43\xcc\x39\x20\xff\x3a\xf9\x7d\x07\x3e\x42\x97\x35\x55\x53\xcf\xa3\xf2\xef\xf9\xcf\x98\x3c\x73\xc1\xf4\xb0\x43\xef\x46\x65\xfa\xd2\x91\x41\xc4\xb5\x95\xde\xa8\x1c\xc5\xdf\xfe\xc9\x53\x94\xe3\xa5\x06\x99\xb9\x64\x00\xd1\xaa\xbc\xd3\x90\xd6\xdc\x52\x38\xea\xdc\xd3\x71\x5e\x30\xce\xee\x9c\x1e\x17\x5b\x60\x47\x72\x1b\x3f\x0a\x79\x8f\x48\x03\xa4\xc9\xc9\xb6\xc0\x5c\xb5\xb9\x86\x72\xdd\xf3\x3c\x18\xce\x05\xb8\x1e\x7e\x32\x43\xc9\x73\xa2\x1d\x8e\x1d\xca\xbd\x3c\x60\xe4\xc0\x3a\xbe\x7c\x62\x84\xc5\xc0\x5c\x72\x37\x6f\x6b\x39\x9f\x4f\xbe\x0e\xb5\x3c\x59\x9c\xb3\x76\xbf\xa0\x31\x65\xbb\x50\xc1\x37\xd8\x5b\xa2\x74\x25\xb7\xb5\x1d\x1b\x1e\x25\xe1\x46\xee\x45\x01\xee\xd3\x0a\x67\x25\x79\x70\x4f\xef\x6e\x06\xe1\x7d\xfc\x6b\x6d\x2a\x26\xfe\x77\x97\xf8\x7d\x67\xf6\x2d\xab\xf9\xb1\x5a\x2e\x67\x68\x7e\x0a\x26\xa3\x57\xec\x4b\xd4\xd6\x26\xc1\x98\x7e\x0e\x15\x17\x16\xf7\x37\x53\xbd\x0c\x8c\x31\xd9\x84\xd3\x56\x65\x10\x12\xb7\xf2\xd4\xd6\x40\xc4\x2e\xb7\x21\x44\x88\x64\x02\xda\x19\x5e\xe7\xa6\xaf\xeb\xa5\xff\xb8\x82\xb3\xc7\x2c\x57\xfd\x23\x9b\x18\x36\x7c\xba\xad\xfa\x59\x3a\x1d\x93\xc0\xbf\x11\x35\xbb\xec\x2b\xe9\x6c\xff\x1b\x45\xba\x74\x06\xea\x14\xb7\x87\x77\x4a\x55\x13\x5e\xf6\xf0\x94\x45\x0d\xbf\x56\x78\x4d\x8f\xdc\x4f\xa9\x03\xd0\x86\xee\x7b\x4f\x9e\x10\xc0\xb2\x5d\xb7\xe5\xd7\x4e\xff\x92\xad\x87\x7a\x57\xfb\x4e\x7b\x5b\x5c\x58\x0b\x46\xd6\x37\x0e\x83\xb7\x2b\xf7\x00\xc2\x2d\x24\x8b\xa7\x6a\x47\x2d\x13\xea\x1b\x49\x64\xfd\x5c\x45\xfe\x12\xdb\x99\x29\xa4\x63\x84\x6d\x2d\xe7\x44\xf2\xa4\xf8\x9c\xa4\x6e\x5c\x0e\xaf\x98\xe4\x03\xbb\x3a\x56\x0d\x83\xa4\x5b\x4c\x6c\xd5\x40\x80\x7b\xa0\x16\x41\xc7\x6a\x66\x4a\xa4\x42\x0f\xd5\x42\x4e\x4d\xb2\x0f\x7d\x68\xfa\x97\x4c\x85\x19\xc3\xd9\x59\x1c\x10\xc0\x0b\x4b\x7a\x6d\x82\x83\x55\x85\x83\xdd\x77\xca\xc6\x43\x9b\x98\x78\x64\x15\xfb\x24\x8b\xaa\x09\x90\x2c\x47\x51\x5e\x37\xeb\x6d\x43\x3b\xb0\x84\xfd\x4d\x63\x20\xf1\xd5\xf8\xf9\x7f\x94\xd4\x7c\xbe\xa6\x47\xef\x51\x86\x45\x6f\x28\x11\x2a\x35\xa1\x75\xbe\x97\xe3\xd6\x39\x0b\x78\xa3\xd3\x63\x13\xfb\xe6\xaa\xf9\x5e\xbc\xa8\x6f\xae\xe2\x9f\x2e\xe2\xed\x99\xa8\x5c\xe2\x5d\xf6\xf5\x8d\x15\xfd\x8e\x39\xa2\x97\xbc\xa1\x30\x84\xab\x7c\x51\x2d\xf4\x2b\xb4\x10\x8d\x9a\x42\xd2\xe9\x6c\xf6\xe3\x13\x1f\xb5\xb2\x27\x20\x34\x6a\x6e\x4c\x68\x42\x56\xe7\x18\x36\xb6\xf8\x61\x64\xb3\x55\xaa\xf1\x66\x26\x82\xf3\xa7\x40\x16\x25\x55\x0d\x57\x1f\xa0\x56\x58\xfb\xea\x52\x18\x92\x5b\x4c\x26\xb2\x7a\xf7\xfe\x71\xc9\x55\x35\xb0\x1e\x65\xa9\xb9\x03\xc8\x6a\x63\x6f\x68\xaa\x3a\x9d\xd8\x64\x96\xcd\xb6\xbb\xe7\xc9\x9e\xe1\xed\x54\x3c\x16\x2b\x6e\x13\xc0\xac\x6c\x59\xd0\xaf\x1f\x92\x4e\xc8\x36\xfa\x1e\x1f\x32\xfa\x1e\xbb\xf1\x0b\x3d\xe9\xbb\x46\xb4\x5a\x85\x68\xab\xd0\x24\xce\x99\x2f\x14\x12\x7d\xf6\xf9\x2a\xb5\x93\x90\xac\xf7\x03\xf5\xb2\xc4\xdb\xf1\xaf\x24\x37\xd7\x13\x04\x20\x8f\x87\x4d\xad\x5f\xad\x0f\x4f\x76\xf3\x4d\x19\xc4\xd8\x99\xf0\x5c\x32\x4d\x04\x58\xeb\x37\x4c\x01\x36\x0b\xf0\x6a\xd0\x34\xa0\x51\xe8\xbc\x01\xc4\x29\x37\xed\x8f\x35\xb2\xe3\x75\x12\x73\x4e\xb3\x67\x61\x27\x57\x5a\x72\x28\x4f\xd8\x46\x43\x57\x57\x3e\x6a\x7e\xb4\x4f\xba\xe8\x20\x68\x09\xb6\x90\x27\xd3\xf4\xa1\xb8\x11\xc3\x14\x29\x5d\xbe\x4c\xf1\x11\x7c\x4c\xdd\x5f\xf2\xc1\xed\xb1\xd4\x91\x03\x78\xd3\x69\x92\x97\xfb\x92\xbf\x64\x0a\x60\xea\x27\x8d\x08\x52\x04\x85\x80\x5d\x9e\x7d\x18\x5e\x95\x1d\x94\xc5\x01\xd4\xfd\x29\xc6\xb0\xb3\xcd\x18\x4b\xaa\x20\x09\x9c\x39\x7d\x80\x99\xb2\xfb\xb1\x9a\xf4\x37\x4e\xa5\x35\x9c\x2e\xb9\x88\x82\x03\xc6\x84\xd3\x18\x92\xf5\xa3\xe4\x1e\xf5\xa4\x52\x31\x9a\x04\x38\xa2\x82\xd8\x9d\x24\x84\x87\xca\x13\x1c\x58\x7e\x99\x4f\xa1\x1c\x9e\x18\xd9\x61\xf1\x63\x8e\x1e\x34\x7d\x94\x2e\xf4\xe5\xab\xdc\xba\xb8\xc8\x7f\xd2\xef\xaf\x93\x82\x57\x15\x36\x82\x30\x5b\xa4\x0a\xdf\xdc\xae\x71\x19\x92\x0b\x7d\xe8\x05\x06\x91\xe3\x3e\xa5\xaf\x84\x81\x39\x30\xd6\x0f\x16\x1d\x63\x17\x6a\xdd\xd9\x07\x2f\x74\x27\x6d\x91\x46\x2d\x8a\xf1\x88\xe4\x60\x9a\x15\x76\x87\x12\x94\xcc\xd3\x2e\x4b\x13\x46\x06\xdb\x0d\x00\xd9\x60\x29\xf7\x01\x78\x24\x55\xbe\xa0\xd0\xb2\x91\xc0\x96\xaf\x72\x87\x33\xe2\x45\x49\x1d\xdc\x2c\xb8\xd8\x21\x7c\x4a\xce\xf7\x78\xbc\xd3\x40\xef\x31\x25\xfb\x4b\x6f\x21\x21\x74\xe9\xee\x1a\xf3\xcc\xac\x81\xba\x64\x77\xb6\xe2\xb5\x7a\x9c\x1a\x0a\x89\x0a\x49\xbf\x02\x2c\xb8\x65\x68\x31\xa4\xab\x11\x66\x80\x06\x9b\x94\x0c\xa2\xad\x69\x58\x29\x7c\x05\xe6\xd6\xf7\x18\xca\x6f\xd7\x98\x60\x32\x94\xaa\x9c\xcd\xe5\xa3\x90\x72\x9b\xb3\x82\x33\xd2\x8c\x2e\x30\x5f\xbf\xce\x28\x64\xd8\x02\x1b\x5b\x2a\x89\x74\xa3\x8d\xa9\x41\x9e\x04\xf8\xf3\x4b\x93\x63\x0b\x01\x4e\x73\xce\x4d\x40\x4f\xd1\xfb\xb7\xde\xb3\xb2\x0c\x5d\x54\x31\x38\xe7\x7a\xb3\x82\x09\xd9\xe5\x32\x1a\x33\x84\x06\xd7\xc4\xb9\x46\x76\xb1\xe5\x25\x7d\x29\x1a\xf5\x98\xfc\x06\xd8\x17\xbd\x88\xf5\xfa\xa1\x52\xcf\xc0\x8c\x59\x5c\x2e\xc4\xcd\x4b\x5a\x61\x87\x83\xbe\x1c\xdc\x8f\xc8\x11\xd4\x8c\xa0\x5b\x84\xd2\x00\x28\x99\x39\x21\xb0\x84\x4b\xf3\xe1\xd8\xd6\xbc\xc9\x73\x8f\x86\xc4\x19\x60\x5c\x12\x5a\x2e\xe5\xce\xa8\x4d\xe1\x78\xa8\x03\x7e\x5c\xa2\x39\x61\x6e\x25\x55\xcf\x4f\x7e\xd7\x65\x9d\xbd\x43\x1b\x9a\xa2\xfa\x44\x97\x1a\x5e\xc2\x48\x59\x0d\xff\x52\x62\x26\xe5\x04\x80\x10\x93\x99\x32\x4b\x6c\x59\x27\x7c\x0f\xf1\xf3\xcd\x4e\xc4\x77\x69\x83\x76\xa8\x63\x4f\xb7\x2c\x53\x97\xa3\x36\x4c\x1d\x38\xbf\x7b\x5d\xf9\x51\xba\x39\xb9\x93\xf5\x41\x1b\xe2\xc6\xc6\x7f\xb4\xfd\xde\xa3\xc1\x67\xb0\xf4\x90\x86\xa4\x72\x82\x19\xc8\xb9\x8f\x26\xf8\xa2\xec\xbc\xfb\x6e\xd2\x39\x0c\x61\x51\x6d\xd3\x37\xcd\x91\x04\x51\x3b\x27\xb4\xed\x6a\xe9\xf5\x32\xd6\x8b\x89\x04\xaf\x60\xc2\x9b\x75\x54\xbf\xbc\xfd\xce\x93\x16\x2e\xe7\x46\xf6\xc1\xe9\xa6\x18\xba\x54\x75\x80\x7c\x2e\x99\xba\x87\x49\x30\x81\x6a\xc2\x41\x78\x50\x40\xae\x6c\x1b\xae\xd5\xdd\xd4\x99\x00\xb9\x1e\x54\x3d\xc1\x37\x58\x47\x71\x25\x02\xe7\x63\xf8\x18\xdd\x86\x6d\xa3\x15\x14\xd5\xed\x10\x99\x8c\x71\xb3\x54\x74\x29\xe2\xde\x02\x1c\x7f\x20\x60\xae\x93\xfc\xe4\xf1\xee\x4f\x97\x70\x74\xf5\x2b\xce\xb0\x60\x81\xc5\xcc\x5f\x02\xd0\x8e\x00\x14\xed\x6b\xb8\xbe\x66\xcb\x97\xcc\x15\xfe\x36\x55\x65\xde\x7d\xfc\x5b\x3b\x91\x7b\x78\x48\xb2\xd1\x11\x08\xb6\x4b\x07\x75\x0e\x9c\xdc\x70\x09\xe9\x6d\x8f\x9e\xde\xb1\xbd\xcd\xea\xf7\x5e\xde\x13\xe1\xba\x60\x54\x74\x8a\x3c\x5b\x8d\xd5\x72\x51\x2d\x61\x95\x3e\xe7\x70\x97\xb5\x98\x2b\xfa\x16\xaf\xaa\x31\x5f\x2e\xb0\xbb\x10\x01\x54\x49\xd1\xef\xb4\xe3\x1a\xfc\xcf\xf4\xaa\x7d\x36\x9a\xcf\x5a\xe4\xfd\x5c\x25\x74\x42\xe1\xa7\xaf\xa1\x3f\x49\xfc\x22\x77\xc6\xb0\x78\xcd\x59\x82\x50\x95\xa7\xb5\x0e\xb9\x6f\x9c\x25\x54\xc8\xe9\x1a\xb8\x24\xd0\x3a\x4d\x5e\x81\x2f\x0d\x88\x38\xb7\x2a\x98\x12\xd3\xeb\xfc\x6b\xe6\x8b\x35\xe4\xdd\x61\x38\x8f\x2f\xcb\x75\x8c\xfd\x75\xb2\x67\x18\xe5\x10\x5d\x0c\xef\x54\xc7\x8b\x52\xa3\x0a\xf9\x86\xc2\x54\x5d\x06\xc7\xe5\x25\x2c\x0c\x96\x51\x3d\xed\x59\xca\xaf\x33\x00\x44\xd1\x5a\x28\x1b\xd3\x8c\xcd\x1c\x76\x7d\xbb\x0c\xaa\xb6\x3e\x7a\x0e\xce\x31\xe1\xdb\xd7\x7b\x9c\x2b\x7f\x0a\xfb\xe5\x98\x35\xb3\x41\x02\xd1\x26\x1d\xde\x3a\x73\x12\x5f\x6c\x3a\x57\x7b\xc0\xcf\x4d\x0a\x62\xcd\x2e\x10\x1a\x52\xb7\x0a\x7f\x93\xd2\x8b\xfa\x11\xcf\xaf\xdc\xc3\xaa\xbc\x6c\x43\xd4\x79\x44\x52\x7c\xff\x51\x50\xff\x71\x48\x42\x78\x34\x29\xdf\x7d\x06\x2a\xb1\x47\x66\x50\xc5\x5d\x90\x25\x60\xc8\x55\x9b\x0e\x06\x03\xc2\x93\xab\xfc\xa1\x15\x48\x30\x27\xfb\xfd\x0d\x1c\xa5\x75\xd2\x6c\x55\xbf\x73\x00\xaf\x18\x80\x77\xe5\x01\x4b\x57\xc2\x4f\x89\xf9\xfd\xdd\x77\xc5\xf8\xfc\x2c\x60\x17\x47\xdb\xe7\x01\x9e\x7a\x39\x0c\x7a\xf8\x54\x08\x48\x37\x64\xf5\x13\x2a\x68\x41\xc8\x39\xed\x5a\x10\x46\x9b\x8f\xa1\x01\xc4\x21\x69\x56\x87\xc1\x1a\x0f\x74\xd0\x46\xa4\xf7\x72\xc8\x31\x04\x42\xba\x37\x8b\x0a\x46\xef\xe0\xd3\x4f\xe1\xcd\xe9\xf5\xcd\x22\x83\x76\xf4\x92\x53\xc8\x9f\xaf\x34\xc0\xe3\x08\x8e\xf6\x08\x8d\x93\xa5\xbf\x54\xb9\x16\x1b\x80\xf0\xf9\xd5\xe0\x03\x1d\x00\x9e\x4c\x98\xf0\xef\x9a\x06\x94\x7f\xa1\x0e\xeb\x1f\x61\x13\x2a\x7d\x64\x80\xfa\x83\xdc\xd1\xc2\x6a\xd1\x5c\xd0\x15\x82\xb3\x0f\x0f\x09\x96\x9f\xf3\x91\x34\xa6\x87\xc5\x72\xa5\xf1\x44\x4d\x63\x7d\x98\x2a\x81\x60\xc3\xfd\x6c\x53\xe2\x01\xb5\xb5\xce\x62\xcc\x0d\xd0\x19\x53\x19\x10\xca\x30\xae\xce\xa9\x3c\xd8\x40\xa1\x54\xc7\x34\x52\x39\xc0\xd7\xf9\x3e\x5d\xd4\xeb\xdf\xd5\x3c\x10\x28\xfa\xac\xdb\x70\x30\xdf\x82\xf4\x06\x70\x5c\xa8\x35\x94\x12\xd9\x67\xf8\x49\xcc\x97\xea\x7d\x56\xa7\xcd\xf9\x78\xe8\x4c\x3f\x17\x65\xe6\xcd\x96\xcb\xd7\xf7\xda\x9f\xb2\x3a\xa9\x4e\x20\x8d\xfa\xd2\x4d\x06\xc3\xc1\x63\x5c\xd0\x58\x6d\x5d\x36\x55\x06\xd0\x19\x98\x74\xe8\xcd\x68\x71\x54\xae\xce\x31\x40\xcb\x58\x87\xfe\x5e\x45\x91\x58\xc3\x04\x67\x32\x79\xa2\x61\x13\x55\xfe\xda\xd4\x3f\x01\x9f\xe6\x71\x3f\xe0\x7f\x58\x00\xe8\x59\x2d\xd4\x1f\x25\xe8\xcf\x8b\xd5\x16\xe4\xa8\xa4\x9f\xfc\xb2\x5f\x58\xc2\xbb\xfc\x02\x40\x09\xd2\xe1\x20\x79\x42\x9d\xf9\x1b\xa2\x05\x69\xac\x25\x3b\x4c\x83\x1d\x4f\xde\x59\x72\x0c\x25\x47\x6a\x12\xf9\x76\xc0\x05\xac\xfe\x5b\xde\x66\xef\xbc\xc6\xe7\x73\xd4\x81\xdf\x57\xf1\x6a\xda\x0c\xe0\x1f\x3c\xd7\xae\xaa\x2d\xbc\x01\x82\x32\xe1\x35\x54\x5a\x6a\xe7\x60\x0f\x1d\x02\x42\x00\x6e\xd1\x0d\xc8\x3e\xdc\xeb\xbd\x9b\x99\x47\xb3\x94\xd2\x0f\xd5\xae\x00\x82\x2e\x5a\x5c\xc0\x7a\x68\xfc\xbe\x95\x03\x0c\x74\x61\xf2\xec\x03\x56\xca\x75\x69\x36\xed\x90\xe5\xbb\xc1\xc9\x08\xd9\x5f\x5c\x49\x48\xfa\x1f\x2f\x50\x0e\x49\xc2\x7f\xae\x94\x29\xa2\x48\x25\x17\xda\xa5\x0a\x21\xe2\xfd\xc4\x44\xb4\xff\xc7\x23\xde\x90\xc1\xf2\xf2\x87\x18\x84\x94\x29\xd3\xb9\x9b\x75\x19\xee\xf5\x5d\xee\xa1\x84\x52\x2e\x44\xdf\xa8\xed\xf0\x1b\x33\x18\x9b\x49\xaa\xf5\x10\x80\x87\xa1\x7c\x93\x8b\x91\x80\x2f\x43\x03\x17\x8b\xac\x5f\x84\xd2\x72\xcc\x57\x65\xc8\xea\x88\x0f\xad\x07\x73\x72\xed\x5e\xb2\xe5\xbf\xc8\x8f\xd5\x37\xe8\x6b\x3f\x73\x33\x18\x29\x8c\xe2\x4e\xf5\x15\xaa\xb4\xe3\x11\xb3\x06\xcc\x3e\x27\x1f\xe7\x8b\x50\x7e\x9e\x8d\xc6\xf8\xe0\x38\x61\xe3\xab\x43\x3e\x9c\xad\xaa\x8c\x4d\x49\x0c\x4a\x3c\x9e\x7d\xbc\x1f\x81\x0c\x5b\xab\x3c\xcd\x5a\xf6\x38\xf6\x13\x97\xf6\x21\xca\xaf\x8b\x97\x0e\x32\xab\x35\x45\xf2\x1a\xd0\xec\x5b\x60\x07\xb4\x0d\x81\x60\x67\xaf\x7c\x29\xa5\xca\x16\x88\xd7\x85\x1e\x32\xea\x0a\xcc\xee\x42\x2d\xfd\x5b\x98\x82\xf7\xce\x52\x41\x6b\x56\x82\x5c\xae\x49\xf6\xf7\xce\xb8\xec\x5f\x19\xe7\xb2\x4d\xae\x6f\xff\xe8\xfb\x08\x96\x4e\x8c\x80\x9e\xf7\x83\xbe\x98\xe1\x02\x00\x3b\xf5\xa2\x41\xed\x61\xbd\x35\x55\xb5\x0e\x08\x3a\xf0\x11\x9b\x38\xa1\xf0\x47\xbe\xa4\xd2\x7f\x3b\x3b\x05\x30\xb0\xda\x83\xdd\xf6\xec\x3f\xad\xbe\xf4\x27\x15\x1f\x03\x51\xfc\x73\x2e\xcf\xf0\xe8\x22\xd3\x91\xcf\xf9\x29\x67\x86\x73\xec\x9f\x4c\x0c\x19\x56\xfa\x50\x84\x02\x88\xf9\x3e\xed\xeb\xe3\x8e\xc4\xa8\xca\x97\x91\xff\x5e\x1a\x43\xc1\xb9\xd2\xb2\xec\x50\x0f\x16\xca\xe1\x77\xee\xf5\x57\x21\xfc\xc9\x05\xe8\xb1\x66\xdf\x22\x9b\x39\xc2\xb6\x07\x6d\xec\xac\x33\x69\x40\x45\xe0\x2f\x6b\x20\xc7\x84\xad\x16\x5c\x4d\x07\xef\x10\xb9\x3d\xe4\xd9\x74\x5c\x35\x1b\xe6\xa0\x9b\x94\x08\x37\xe9\x73\x1e\xf0\xef\xde\xd8\x75\x10\x26\x16\xe5\xc4\x85\x23\x7c\xc8\x5c\xac\x7c\x77\xd1\x9d\xf8\x96\x3f\xba\x91\xb0\xbb\x0f\xd9\x6e\x63\xb3\x6e\xc6\x45\xee\xd1\x96\xa5\xf0\x52\x3b\xfc\x91\x2d\x0a\xfb\x20\xac\xa3\xf1\x2c\xe9\x31\x56\xa5\xe5\x92\x61\xcc\xbd\x90\x30\xe5\x6f\x95\x6c\x52\x70\xda\xe9\xd7\x92\x64\x33\x38\x06\x09\xfb\x5e\xd3\xe1\x7b\x2f\x60\xf1\x5d\xe3\xfe\x3b\x45\x51\x9c\x6f\x98\x2a\x84\xae\x43\xb4\x2e\xca\xc7\x3f\x54\xff\xbe\x0a\x87\x70\xeb\xa1\x44\x2a\x8f\xf9\x4a\xe9\x80\xd8\x2f\xd1\xcf\xdb\x97\xb1\xcf\xd5\x87\xf8\xb4\x08\x57\x1d\x3f\xc0\x52\x9e\x3e\xd4\x26\xd8\x6b\x85\x8f\xd9\x45\x2f\xef\xbb\xb2\x24\x00\xf5\x66\x89\x26\xaa\x14\xdf\x84\x7b\x70\x43\xa2\xb7\x80\x06\x8a\xb3\xdd\xba\xf4\xd3\xa0\x1f\x4d\xa9\xdd\x32\xdb\xe2\x5d\xff\x05\x0b\xe9\xe2\xcd\x76\x7d\xcb\x7c\x21\x88\x6c\x81\xe6\x2f\xa5\x87\xb1\xfb\x50\xa1\x56\xe6\x53\xaa\xed\x26\x74\xf4\xd8\x76\x58\x42\xcf\x6e\x79\x20\xcf\xbf\x9a\x0e\xcc\x59\xf7\xdb\x77\x02\xe4\xbc\x67\x85\xad\x79\x45\xfc\x4f\xfd\x17\xfc\x5f\xa3\x10\x65\x42\x40\xf9\xf1\xa5\xd1\xb1\x71\x45\xc5\xe9\x85\x7e\x3e\xf4\x40\x15\xda\xd2\x39\x55\xaf\x22\x81\xfe\xec\xe2\x2c\x97\xa1\x0f\x8c\xb9\xb1\x38\x15\x84\x9b\xf2\x6a\xf7\x30\xbb\x69\x68\xc3\x17\x6c\xb6\x69\x7a\x48\x37\xae\x49\x31\xb2\xa2\x54\x06\x64\xe4\x02\xef\xb0\x23\x0d\x51\x6f\xc1\x60\x43\x2e\x3d\xf6\x34\x46\xe5\x26\x3e\x1b\x02\x7a\x0c\x1d\xae\xbb\xa3\xf9\xcd\xbf\x43\x3f\x06\x77\x17\xdd\x80\x87\x89\x66\xe8\x59\xe8\xc1\x71\x63\x73\xfd\x66\x62\xf3\x9e\xcc\x66\xce\x13\x3d\xe5\x5b\xe1\x99\x92\xbc\xb6\xdc\x85\xa7\x11\xf5\x3f\x9c\x39\xbd\x9d\x46\x14\x5c\xfd\x0b\x0d\xd5\x05\x55\x2c\xa6\x06\x99\xcb\x2f\x8d\x2b\x7f\xa1\x06\x86\xcd\xfd\x5b\x76\x32\xb3\x20\x6e\xfe\x4f\x85\x09\xbd\x09\x33\xa1\xde\xd4\x87\x8b\xa5\x66\x44\xe3\x64\xf6\xe6\x7b\xb0\xd1\x52\x0a\xc0\x46\xb2\x8c\xcc\x9b\x96\x96\x5e\x72\x46\xf9\x1a\x37\xbf\x5b\x60\x22\xd1\xa8\xc1\xb2\x77\x6a\x00\xab\xd9\xa9\xf6\x30\x28\x65\xae\xd5\xf8\x1a\xbb\xab\x83\x61\x42\xa8\x9f\x37\xf1\x8e\x22\xcb\xf1\x96\x40\x33\x62\xe9\xd3\x46\x38\x32\xbc\x76\x7b\x23\x04\xa8\x6d\x11\x10\x30\xb4\xb2\x6a\x07\x25\x47\x95\xaa\x8e\x9b\x40\x8e\x8c\x53\xb0\xb4\xd5\xe1\x80\xc2\x94\xa9\x73\xa0\x6d\x49\x9f\xaa\x9a\x39\x1d\xf6\x72\x72\x56\xc3\xd4\x61\xcd\xc6\x62\xef\xab\x13\x2a\xa8\x4e\xd9\x13\x6a\x0c\xbf\x97\x69\x54\x2b\xa2\x53\xdb\x84\xf9\x91\x33\x0f\xdb\x12\x80\x78\x2f\x63\xa5\x8d\xf5\x18\x7d\xf7\x85\x50\x44\x13\x47\x7d\x89\x44\x54\x10\xf5\x3c\xea\xa8\x03\x9c\x79\xe1\x30\xf6\x50\x26\xde\xfa\x9f\x4b\x77\xda\xa6\xac\x41\xe0\x96\xbc\x5b\x9d\x93\x9c\x5b\xa5\xec\x41\xe5\x5c\x2d\x03\x30\x21\x85\x8d\x2c\x75\xe9\x2c\xa0\x04\xa6\x90\x29\xf8\xd7\xf9\x4b\x6d\x87\xd9\xce\xf6\x25\x54\x08\xdb\xdc\x20\x2d\x44\x6f\x2b\xe8\xdb\x5a\xf2\x80\x8d\xa7\xb4\xf2\x87\x02\x6b\x2f\x08\x0e\x36\x4d\x59\xcb\x47\xa2\xc4\xc8\x02\xc2\xab\xbf\xae\x2a\x5a\x35\x1a\x4a\x89\xf5\xd3\xdc\x85\xcb\xd3\x6e\x4d\x9d\x3b\x20\xad\x99\x3d\xab\x69\x60\x79\x7b\xd9\xbe\x0e\xfe\xa0\x01\x79\xcb\x0d\x87\x37\x56\x02\x5d\x6a\x72\xcf\x56\x86\xeb\xb6\x12\x76\x5f\x79\x17\x4d\xe1\x75\x4d\x24\x60\x88\x27\x76\x9f\xa6\x24\xe3\x62\x6e\x9f\xec\xba\x7b\x64\x04\x16\xfd\x38\x37\xe3\x20\xfb\xc9\xba\xda\x27\xff\xeb\x3b\xe5\xc2\x0a\x80\xbd\xd1\x95\x7a\x5c\x98\xa5\xe9\x7c\x64\x9a\xbf\x4d\xe3\x5a\xde\x20\x16\xf0\x45\x6c\xe1\x57\x75\xc3\xe0\x43\x98\xfd\x67\xba\x93\x79\x4b\x42\x4b\x0a\x57\xbd\x7f\xfa\x4c\xe3\x22\xe7\x86\x3e\xee\x6c\x2f\x0d\xee\xd4\xb1\x48\xdf\xb6\x34\x74\xfa\x3a\x7d\x87\x00\xd8\x48\x5c\xbe\xa4\x5a\xc8\xd4\x9c\xfd\x2b\xd4\xbc\x32\x9f\x1c\xe8\x47\x76\xa8\x1c\xb4\x9c\xd9\x04\xf3\xcf\x34\x03\xe4\xf1\xa9\x11\x5c\x77\x20\xa7\x40\x7d\x3d\x2e\x2c\x70\x3b\xc3\xe7\x20\x60\x54\x03\xfb\xfb\x58\xa4\x5f\x4d\x3f\x3e\x24\xcf\xde\x94\xa9\x98\xfe\x34\xe0\x00\xe0\x2d\x79\x0e\xdb\x69\xf4\xf9\x03\x1a\x02\x81\xaa\x48\x0b\x1a\xb5\x76\x2c\x5f\xba\xe7\xd8\xf9\xf1\xff\xa7\xa7\x25\x2e\x61\xee\x76\x95\x69\x0f\x9e\x6d\x78\xea\xfd\x43\x3f\xaf\xb3\x3a\xd3\xde\x6d\x32\x52\x76\x9f\xb0\x9a\xfc\x92\xe1\xc4\x10\xbe\xd9\xc4\x5d\xf0\x29\xa3\x52\xe5\x3b\xd2\xff\x89\x28\xc4\x7b\xa3\x0b\xef\xee\x3a\xb3\xe4\x30\x25\x52\x73\xb6\xc2\xbb\x7f\xbf\xbc\xbd\x68\x86\x5e\x3f\x6b\xa0\xa6\x36\xcf\x45\x9a\x80\x36\xf7\x54\xa0\xea\x9f\x6c\x83\x9c\x9d\x05\xb6\xca\x7b\xc1\xe9\x2e\x00\x86\xde\x42\x97\xff\x11\x26\xdf\x2a\x0a\x5d\x62\x91\x37\x69\x79\x2d\xd7\x97\x87\xa4\x24\x1c\x77\xfa\xeb\xf3\xea\xbe\xc8\x50\x1d\x4d\x2c\x94\x16\x41\x7c\xd6\xa4\x43\x77\x4f\x40\xb4\x57\x3a\x41\x34\xe6\xa4\x41\x09\xa6\xe2\x72\x28\x13\x75\xbd\xcd\x19\xdc\xca\x98\xa3\x10\x9e\xe1\x06\x07\x00\xe1\x8b\x6c\xf3\xff\x45\xde\xb1\x75\x53\xe5\x7a\x29\x89\x72\x7e\x81\x38\xa0\x77\x50\x1b\x38\xff\xe8\x54\xa6\x00\x67\xb5\xd9\xc4\x0a\x7c\xba\xd5\x8d\xae\x6d\xdd\x64\x39\x5b\xe3\x3b\x91\xc6\x97\x2f\x95\xc3\x8e\xf3\x7e\x67\x0e\xd6\x40\xcd\x48\x59\xca\xe6\xd6\x6d\x93\x09\x8a\x6f\xb2\x35\xb8\x9b\x29\x9c\x26\x9b\xcb\xd7\xba\x01\x89\x81\x7c\x89\xf1\x87\xe7\x77\xd3\xf3\x8c\x56\xa7\xa5\x6c\xd0\x57\x94\x10\x8d\x35\xe8\x9a\x8b\x30\x4b\xc4\x05\x13\x89\x4d\xdc\xc5\xcb\x51\x16\x19\xde\x22\x4f\x6a\x6b\x80\xcd\x49\x9c\xbc\x34\x95\x5a\x65\x4b\x68\x07\x7e\x29\x57\xf2\x27\xcd\xf7\xe5\xf0\xce\x5b\x58\x30\x42\x43\xce\x28\x04\x38\x4e\x44\x49\xe8\x0e\x89\x32\x87\x98\xae\xa4\x8f\xe1\xc2\x65\xe5\xa2\xeb\x5d\x71\x95\xaf\x71\xf9\x70\x02\x02\x94\x94\xb7\xd2\x2b\x5d\xa0\xd4\x73\xdd\xdb\x64\xed\x4a\x9e\xe4\x97\xae\xfb\x6a\xc5\x61\xba\x4f\x50\x19\xac\xfe\x2c\xbd\x72\x95\xa8\xa6\x99\x7d\x68\xa1\x01\x36\x17\x13\x92\xc3\x79\xc3\xb2\x73\xce\xeb\x4e\xca\x29\x6b\x49\x28\x56\x0a\x34\x3a\xc7\x04\xa4\x9f\x9d\x28\x08\x33\xea\xd7\x09\x86\xcf\x91\xca\x49\x8f\x10\x60\x98\xc5\x5b\x07\x35\x11\x90\x55\x50\x0b\xf4\x4a\x9a\xb8\x7c\xdf\xb9\x31\xad\xa8\xe2\x63\x97\x1d\xa3\x68\x1d\x5c\x94\x3d\x68\xfe\x22\x47\x6f\xf1\xf3\x0c\x1f\x06\xbd\x40\x0e\xd7\x22\x19\xed\x6b\xf0\x02\x10\xe3\xc3\xc7\x16\xd2\x94\xf2\x35\xf5\x36\xd9\x97\xb4\x80\x7e\xc7\x56\x6c\xc0\xa2\x2a\x7b\x19\x05\x61\x26\x2d\xd3\x27\xe9\x9e\xcd\xfe\x9f\x2d\xfa\x40\xa9\x32\xf1\x4d\x77\x39\x88\xed\x52\x08\x53\x8f\x85\x1b\x66\xb1\xb0\x00\xf7\xad\x3e\x97\x96\xe6\xbb\x82\x87\xd4\xf3\x9e\xf8\x90\x1b\x89\x20\x4b\x60\x4b\x99\x0b\x29\x63\x09\x65\x1f\x8a\x6b\x8e\xf5\xb8\xf9\x76\xdf\x85\x7a\x59\xd2\x02\x18\x43\xab\x75\xd2\x88\xe3\x66\x68\xc8\xdf\xe0\x81\x7c\xda\x20\x63\xb6\xb3\x4c\xed\xde\x9d\x79\x9a\x86\x5f\xa1\xe5\xcc\x7e\xff\x7f\x27\xf1\x47\x14\xa9\x21\x47\xf3\x5b\x73\x0b\x53\x9b\x51\xad\x61\x78\xe0\xf1\x49\x44\x00\x71\xe1\x46\x50\x09\x64\x61\x1d\x40\x92\x26\x78\x1e\x56\x6d\x9e\x42\xa9\x67\x75\xfb\x66\x1d\x34\xc1\x89\x61\xd6\x8a\x81\x87\x61\xa7\xd4\xaa\x51\x02\x03\x19\xe1\xa3\xc2\x43\xc3\x77\xa1\x2c\x4b\x79\xad\xd6\x0f\xf4\x45\x99\x52\x72\x56\x18\xb0\xd2\x3f\xa8\x37\xc3\x0e\xb8\x6e\x5b\xd3\x48\x72\x1a\x9c\xe9\x98\x93\xb5\xf4\xef\x59\x79\xc3\xd2\x97\x7f\x25\x14\x36\xe6\x93\xca\x49\x66\x8b\x5c\xec\xc5\x72\x28\x9c\xd5\x34\x3c\x24\x9a\x94\xff\x54\x3f\x08\x65\x3f\x4b\x55\x3f\x6b\xa1\xca\x32\x75\x6e\xf9\x7c\xee\x93\x45\x5d\xe6\x04\x36\xff\x96\xac\xa8\xbf\xc8\x9e\x18\xb5\x91\xa6\x76\x13\xf6\xb4\x66\xc8\xd3\xc9\x63\x15\xe3\x9c\xcd\xda\x68\x2f\x6f\xfc\x29\x9f\x55\x89\xbf\x36\x63\xc0\xca\x95\x64\xcb\x34\x06\x23\x6f\x2a\xdf\xca\x63\x91\xf7\x53\xc9\xc4\xd5\x2e\x02\xf4\x0b\xb7\x7d\xef\x80\xf6\x73\xbe\xec\xe3\xd7\x99\x0c\x92\x2b\xc3\xf3\x38\xc7\x6a\x43\xca\x24\x37\x06\x3f\x4a\xa6\xa9\xf7\x3a\x7d\x63\x42\xb6\x80\x3c\x63\xd8\x73\x69\xb3\xca\xde\xb8\x9a\xf6\x7d\xf6\x60\x12\x56\x9d\xea\x1b\xa5\xff\xd7\x9a\xff\xbc\x3e\xb4\xf9\x61\xdb\x87\xa8\xb9\xd1\x7d\x19\x0f\x74\x98\x7b\x40\x34\x2d\xe0\x1e\x10\xb0\x77\x9b\xba\x94\x40\x74\x91\xaa\x5d\x90\xc7\x9f\xc5\xaf\x75\x3f\x8d\x30\xba\x67\xf7\x99\xa8\xf4\x1f\x2d\x97\x71\x16\x2f\x94\x9a\x3e\x41\x3a\xf9\x9b\xc2\xe5\xf4\xf8\xc5\x48\x5c\xd5\xee\x7d\xfc\xa2\x8e\x56\xa1\xf9\x3b\xfd\xaf\xd5\x7a\xf9\xf4\x76\x59\xef\xff\xe6\xe5\xa2\xa4\x1c\xea\x19\xc7\x84\x07\x12\x40\x91\xed\x93\x30\xbc\xc7\xf0\x1c\x04\x58\x79\x14\x40\x0c\xc8\xf8\x0f\xa1\x32\xb2\x73\x70\x14\x99\x55\x8b\x54\x83\x07\x0b\x61\x1a\x57\xea\x1f\x40\xa4\x37\xa9\x39\x03\xea\x89\xa9\xa2\x17\x3c\xa3\x24\x41\x53\xbe\xb2\xa1\x4a\x5f\xe9\xa9\xc6\x8f\x55\xfa\xfd\xad\xd4\xd0\x77\xe8\x96\x2e\x7f\xf8\x9a\x69\x5e\x7a\x83\x92\x3a\xc8\x9b\x84\xae\xd0\x1e\xb2\x42\x67\xab\x7f\xb3\xc5\x98\x65\xb2\x3a\xc3\x65\x47\xf0\x89\x7b\xa9\xd1\x71\x7b\xf9\x0e\xfa\x89\xec\x90\xd5\xfc\x66\x3e\x97\x4b\x00\xb5\x44\xef\xf8\x41\x75\x29\xc8\xae\x98\x68\x8b\x1f\x0b\x59\xc0\x80\x61\x2a\x1c\x38\x96\xd1\xa8\xb1\xdd\x21\x30\xca\x2d\x2e\xcd\x40\x72\xb4\xb4\x4f\x99\x42\xac\x1b\x7a\x3c\x76\xcd\xda\x9a\xb2\x05\x9c\xb4\xa5\x20\x0e\x34\xc1\x3f\x4d\x46\x9c\xf6\x68\xc9\x72\x99\x95\x44\xd1\x16\xcd\x9a\x45\xc8\x35\xbe\x9c\x0d\x76\xb7\x0b\x4a\xc6\x15\x9d\x9c\x26\x48\xbe\x30\x6b\xff\x44\x62\xd2\x54\x53\xe1\x86\xff\xb2\xb8\x90\x58\xab\x23\xf3\x1a\x89\x6e\x85\xa0\x3d\x5d\x6d\x6e\x6c\x03\x85\x08\x7a\x82\x10\x42\xf8\x55\xa2\xe3\x43\x85\xa8\xb4\x94\x23\x57\x7d\x97\xe5\xc1\xf1\x1b\x1a\x3b\x38\xa7\xb1\x7c\x5c\xd2\xc9\xa9\xa3\xfe\x3c\x56\xf8\xb2\xaa\x23\xdc\x6f\xf2\x67\xfe\xc9\xa7\x6e\x2f\xed\xdc\x8f\xcc\x5a\xdf\x5b\xf4\x76\x61\x2f\xe9\x86\x0c\x53\xff\x8a\x5e\xb5\xae\xdd\xe0\xb6\xcf\x5b\x13\xc1\x92\x66\xed\xe9\xad\xc5\xaa\x9b\x41\x0d\xd6\x37\xde\x1a\x53\xab\x72\xd9\x55\x48\xca\xb9\x4b\x74\xc2\x51\x8a\x57\xcb\xce\x05\x48\xe5\x6a\xc9\xc8\x4f\x49\x4b\xd9\x8a\x9d\x4b\xc3\x0f\x4c\x3d\x9b\xc7\x64\xd9\x6c\xb0\x06\x4b\xdc\x8d\xc2\x55\x93\x28\xd9\xdc\x64\xc0\xfe\xf8\xe0\xb8\x1e\xd9\x70\xd5\xfe\x82\xae\x42\xfe\xcf\x12\x4b\xd0\xca\xdf\x25\x06\x09\xb3\x06\x66\x50\x1f\x10\xd7\x85\xf3\x78\x57\xb2\x54\x59\x2a\x35\x3a\xb7\xeb\x40\x0e\x43\x31\x27\x15\x67\x73\x4c\xbd\x72\x95\xe3\x8c\xf6\x4d\x75\xfe\x87\x3a\x93\x52\x27\xb9\x7b\x7b\x6d\xd2\x2b\xf9\x70\xf5\x99\xe5\xad\x28\x7b\x59\x37\xb5\xe9\xe1\xce\xfb\x31\x52\xd6\xfc\x8d\x7d\xa9\xd6\x3a\xf3\x65\x17\xfe\x3c\xdd\x11\x92\x97\xcb\x18\xa9\xd3\xfb\xf2\xea\xf5\x44\x53\xe2\x15\x58\xb4\x84\xaa\xc8\x09\xa8\x64\xe0\x95\x35\xb4\x9d\xb3\x20\x79\xdb\x05\xc0\x83\xf3\xc3\x71\x50\x5d\x6f\xcc\x6e\xf0\xe0\xc2\xb6\xb8\xeb\x6a\x74\xb4\xed\xbf\xb5\x74\x56\x75\x81\x4e\x74\xb7\x5c\xc9\x42\x54\x22\x85\xb2\xba\x52\x8f\x2b\xc1\x12\xb3\x7d\xff\xa5\x4f\xde\x77\xe3\x4d\x28\xdb\x47\xbd\xe6\x37\xab\x36\x20\x8d\x8a\x47\xba\x9a\x40\x6e\xa8\x2d\xfa\xc3\x9d\xf8\xad\x6a\xfe\x96\x5c\xcb\xce\x49\x04\xc6\x58\x28\x6b\xfd\x00\xb0\x22\x9f\xb3\x73\x9a\x43\xfd\x72\x25\x3e\x4a\x58\xdd\x2a\x68\xbe\x49\xa4\x84\xe8\xdc\xfd\x6a\x42\xcd\xdc\x14\xe2\xeb\x54\x95\xa1\x95\x7f\xdc\xb9\xf5\xce\xe0\xc8\xdf\x57\xcb\x09\xb4\x78\x4d\xb6\xd7\x48\x70\x56\x78\xf5\x95\xc2\x8c\xa9\x9d\x93\x31\x83\x6c\x6c\x60\x14\x90\x56\x40\x6c\x02\x6c\x13\x21\x98\x6a\x82\x71\x3a\x33\x82\xf7\x81\xb5\xd9\xd8\xab\xa9\xf9\x2f\x72\xb7\x4d\xa8\x0a\xd0\x78\x76\xa5\x6b\x18\xff\x1b\xa5\xfb\x41\x92\x43\x4a\x0f\xc7\x6d\x18\x25\xbf\xe9\xed\xb1\xe8\xee\x6c\x4d\x8d\x1c\xc4\xb0\x85\x1d\xfc\xe8\x63\xe9\x8e\xf2\xaf\x73\x17\x53\x4a\x77\x1e\xf2\xd2\x15\x24\xc7\x98\x5e\x78\x6c\x3a\xf7\x72\x52\x77\x23\xf8\x66\x1b\x6d\x77\x14\xa2\x5f\x90\x2d\x2c\x79\xaf\xf3\x37\xe7\x6c\x7e\x95\xc4\xfe\x9a\x99\xc4\x69\x2b\x25\x6b\x95\xaa\x7a\xa8\xcc\xa0\x0e\x8b\xb5\x10\x99\x86\x95\xbc\x46\x30\x60\x11\x31\x27\xc3\x87\x45\x01\xe6\x62\x0a\xdd\x8e\x66\x24\xbc\x79\x4a\x6f\x35\xa5\x9e\xa7\x9c\xd6\x9e\x4b\xa0\x2d\x9e\x0c\x15\x3a\x81\x9f\x90\xf8\x71\x31\xfe\x73\x1a\x6f\xf6\x73\x76\x8f\x38\xc0\x21\xed\x71\xda\xae\x4e\x7a\x4d\x3f\x8a\xc5\x3f\xa0\x13\xfb\x71\xa6\x7a\x11\x7f\x30\xe3\x9b\xbe\x8c\x9a\x39\x24\xdf\x2b\x21\x58\x9a\x20\x95\x10\xcc\x56\xe9\xd5\x24\xe3\x36\x32\x54\x58\xa1\x1b\x5c\xb3\x25\xbe\xa2\x0b\x00\x54\x95\x19\xb7\x2c\x84\xc2\xf8\x8f\x0b\x3b\xa0\x41\x2c\xcf\x95\x7a\x3a\x0d\x44\xd7\x5a\x5d\x31\x78\x44\x01\x4b\x6c\xfe\x11\x3f\x9a\x20\xbd\x0f\x39\x64\x39\x4b\x51\x13\x7e\xd0\xfd\xb8\x55\x27\xa9\x0d\x5a\xc8\x6a\xae\x7d\x42\x77\x6f\xa0\x48\x1b\x64\x7a\xd9\x4a\x3b\xf9\xe2\x02\x15\x61\xb6\xa8\xac\x12\x4a\x00\xc2\x1d\x5d\x6e\xe1\x68\x9f\xd5\xbe\x4c\x89\x8d\x04\x14\xa3\x1b\x08\x5f\x2a\xb7\xcb\xa6\x7b\xa9\x14\x02\x62\x7c\x3e\xc6\xf8\x38\x98\xd4\x70\x41\x75\x6b\x26\xa3\xc0\xea\x3c\x2b\x04\xf9\x11\xcf\xc4\x18\xbd\xef\xab\x37\x15\x04\x7a\x77\xad\x36\x33\x9b\xaa\x5a\xcf\x7d\xac\x8e\xa8\xa3\x2f\x19\x0c\x0e\xa3\x5f\xa4\xb5\xf2\x59\x2b\x76\xf1\x29\x6c\x9e\xf8\xe1\xd1\x6a\xaa\x77\x77\x11\xfb\xbf\xeb\x65\x63\x07\x68\x53\xaa\xe8\x2e\xc9\x6f\x63\x71\xb2\xb7\x53\xbe\x5c\x9f\x52\x06\x2f\xf3\xd5\x89\x28\x8c\x4a\xb9\x1f\xef\x77\x4e\xbf\xc0\x6a\xe4\x4f\xd3\x66\xc5\x93\xd3\x64\xe9\xd3\xee\x07\x55\xcb\x52\x42\x25\x40\xe2\x6f\x75\xf4\xe8\x7f\x87\xf8\x66\xcf\x1a\x35\x8e\xd4\x73\x23\xd4\x95\x8c\xd7\x60\xe7\x3b\xa9\x97\xee\x26\x76\x63\x29\x8d\xf2\x1e\x86\x31\x07\x90\x94\x76\x26\xdc\xd9\x09\xe4\xd0\x53\xf9\x6f\xe4\xbd\x25\x05\xe6\x54\x12\x0a\x5d\x4c\xfc\x3e\x53\x54\xe4\x6d\xed\xc7\x95\x70\x27\x24\x1e\x84\xa5\x57\xe5\x66\x2d\x04\x93\x3f\x5a\xb4\x4f\x49\xb1\x50\xe3\x3f\x32\xd7\x60\x93\x2a\xdd\xdd\xba\x30\xe8\x5a\x3f\xb5\xcb\xb7\x9f\x97\xd5\xeb\x17\xd9\x3f\xc6\x98\x9e\x48\x56\xe4\x74\xcc\x2b\x25\x76\x6b\xa7\x00\xa5\xc2\x7d\x12\x6c\xa3\xc4\xff\xb2\xfd\xb6\x18\x33\xb6\x84\xdc\xc6\x6a\xd4\x9b\x1c\xa0\x76\x92\x6c\x21\xb0\x9a\x07\xda\xa2\x09\xdd\x3b\x78\xb5\xb5\x47\xd9\x45\xf7\x70\xea\x4c\xd9\x4a\x47\x15\x2e\x6f\xd3\x2a\xcc\x70\x10\xb8\xa6\x0a\x8d\x82\x3c\xb3\x0a\x37\xd0\xb5\x4c\xc7\xb2\x3a\xf3\x61\x32\x79\x5f\x65\x58\xf2\x2e\x43\x25\xd8\xde\x0c\x5a\xcc\x4d\x74\x09\x01\x7f\x31\x18\xa0\xe4\xd7\x6f\x75\x71\x9a\x28\xbf\xcb\xe1\xba\xde\x9c\x6d\x07\x6e\x7b\x4a\xbf\x91\x6b\x97\xb3\xa7\x4b\xee\x6c\x8e\xff\x34\x44\x60\xa2\xa3\x34\x7e\x4c\xbb\xfb\x95\x3b\x84\xc9\x6f\xec\x4c\x96\xff\xe7\xdf\xd8\x04\x30\xb1\xe4\x02\x5b\xfa\xb9\x99\x18\x96\xed\x64\x5a\xee\x24\x27\x4a\x82\x89\x69\x16\x0a\x07\xa3\x75\x1b\x2b\x09\x8b\x09\x7a\x1b\x04\xf7\x25\xfc\x49\x94\x7d\x4f\x6d\x26\x8e\x8b\x3f\x1b\x23\x0d\x06\xa4\xaf\x23\x38\x21\x51\x02\x0b\x9a\x31\x47\x68\x82\xa6\x2e\xd9\xe1\x2c\x04\x36\x79\x47\xbc\x58\xff\xf1\x25\x69\x17\x99\x0c\x7a\x05\xcc\xbc\x47\x18\x33\xec\xbd\x06\xa8\xc7\x30\xd8\xcc\x47\xa3\xce\x60\x91\x95\x7b\x46\x9d\x41\xc3\x90\xcf\xed\x61\xce\x6d\xbe\x59\x32\x1a\xf8\x1d\x00\xc9\x57\xf9\x8c\x4f\x1d\x10\xaf\x91\xdd\x5e\xbe\x43\x0c\x4a\x4b\x36\xb8\xfa\x39\xc9\xf6\xe9\xca\xce\xd7\xe9\x74\xf3\x4a\x86\x0a\x5e\x02\x05\x61\x23\x5f\xf5\x3f\x4b\x41\x16\xe2\xbb\x5f\xc9\x70\xc9\xde\xb3\xfb\x1c\xc7\x76\x39\xf9\x00\x54\x33\x84\x34\xcd\x2c\xd7\xea\xc9\xd4\x35\x8e\xcf\xba\xba\x8e\x5f\x4e\x21\x5d\x84\x2c\xc2\xbf\x5b\xb6\x97\xb1\xe5\xa3\xc9\xf9\xc3\x67\xcb\xea\xaf\xf6\x61\xf6\xa2\xc1\x6b\x0a\x3f\x92\xa3\xf7\x25\x74\xa4\x77\x67\x1d\x1c\x95\x05\x76\x4a\xf8\x50\x1e\x71\xbc\xaa\x01\x03\xd0\x62\x74\x4d\xcd\x3a\xc3\xce\x25\x90\x80\x4c\xff\xf0\x2d\x10\x48\xdc\xaf\xe0\xfd\x55\x73\xa1\xf7\xa8\xe7\xf5\x6b\x97\xd4\x19\x0d\x3f\x67\xb0\xf8\x08\x41\xcb\x5f\x1a\xdc\x98\x18\xe9\xcd\x3c\x8d\x20\x1f\xe7\xaa\xb8\xc9\x91\x99\xde\xd4\x50\x29\x38\xd4\xe4\xd6\x63\x39\x40\x6b\x38\x90\xf5\xdb\x0f\x41\xd3\xe7\xca\x79\x64\x8b\xd4\x7d\xd3\x61\xfc\xcd\x6b\xf9\x75\xc5\x89\xdd\xc3\xc4\x9d\x4c\x0f\xad\x8e\x71\x17\x18\x82\xe9\xf6\x27\xfd\xa1\xe5\x5c\x39\xac\x79\xbf\xc4\x0c\x61\xd5\x80\x3f\xb1\xb7\x71\xea\x9a\xb0\x2c\xdb\xe4\xcb\xbf\xd1\xb8\xb9\x0e\x96\xf3\x53\xed\x53\x22\x16\x54\x53\xac\xc1\xf9\x5f\xf2\xeb\x92\xbe\x9b\xae\x81\x32\x4b\x86\xa0\xe6\x3d\xfc\x5b\x1e\x3a\x1b\x2c\x9f\x5f\x55\x05\x16\xdc\xd8\x78\x94\x7a\xd8\xfb\x85\xa9\xef\x7d\xae\xd3\x52\xcf\x4c\xbe\x92\x8f\xb1\xf2\x50\x35\x71\x93\x43\x12\x7f\x01\xe5\x03\xab\xf8\x15\xc4\x09\xa4\xb8\x5c\x07\xe3\x3f\x34\xd1\xa4\xf2\xd3\x5e\x62\xe3\x3f\x21\x4e\x0b\x25\x80\x92\x90\x48\x91\x5c\xfa\x08\x66\xf1\x41\xa6\x9b\x55\x05\x26\x10\x37\x31\xf8\xa2\x6c\xd8\x8f\xd6\x1d\xc5\x15\x7b\x48\xd8\x3e\x9b\x5a\xaf\x06\x3f\x50\xc3\xf4\xa3\x85\xc4\xf1\x6d\x45\x11\x0d\x86\x15\xa5\x53\x4c\xaf\x2b\x04\xf0\x72\x5d\x8a\xfb\xa0\x40\x08\x91\x0e\xca\x9a\x94\x7f\x08\xe8\x63\x61\x91\x1d\xa6\x2c\xe9\x94\x87\x99\xff\x75\x81\xb9\x7c\x28\xed\x0a\x64\x7f\xf4\x7c\xc1\xae\x93\x14\x80\xcc\x52\xb5\xea\x05\xe2\xe7\xe4\x47\x28\xc0\x51\x5a\xe7\x49\x71\x08\xdd\x7c\xde\xb0\x90\x84\xe2\xad\x86\xe1\xd5\x18\x77\x3e\x9d\x02\xcc\x2c\xd7\xd0\x26\x3e\x43\xdc\x76\xf3\x41\x07\xab\x6f\xd1\x60\x4b\x0c\xfe\xe5\x8d\xa0\xd5\x7a\xde\x38\x8f\xa6\x15\x76\x6f\x49\x8c\x04\xfa\xdf\xc4\x81\xb6\x9d\x92\x09\x84\x7f\xc3\x38\xaa\x04\x8f\xa7\xd4\x07\x48\x52\x98\xa9\xe4\x3d\x53\xba\xeb\x46\x24\xe1\x70\x53\x99\xc1\x22\xe2\x6c\x47\x63\x09\x77\x4b\x90\x70\x19\x5a\x44\x06\x16\xbe\x97\x39\xbc\x38\xa2\x5d\x5f\xf2\xba\x2c\x7f\xf6\xe7\x96\xfb\x41\xdf\xc2\x73\xe3\x10\xd6\x35\x86\x3b\x01\x3f\x31\x6a\xfd\xf1\xeb\xfd\x8c\xcb\x5f\xbc\xfe\x0f\x86\x40\x38\x64\x7f\x04\xab\x29\x75\x86\xd3\x96\x9f\x74\x11\x27\x7f\x6a\x91\xcc\x66\x73\x1c\xb3\xd4\x1e\xb2\x3e\xc4\xb8\x30\xcb\xbf\x5d\x75\x45\x14\x19\x14\x34\x30\xd3\xc0\x66\x5d\xb2\x9b\xda\xbf\xcb\x8a\x57\x05\x51\xa3\xb4\x50\x9b\x05\xab\x64\x70\xf2\xa8\x93\xba\x54\x0b\xb3\x9b\xb8\xe5\x0a\xf6\xe0\x0d\x08\x2e\x78\xe8\x89\xaa\x08\x11\xf0\x0b\x3d\x58\x0e\x5c\x33\x12\x21\x3c\xeb\xa2\x22\x9d\xe6\x2b\xc6\x76\x1e\xd0\x44\x55\x20\x2b\xcb\xe8\x6a\x27\x02\xe1\x20\x67\xd0\xbf\xc2\xe2\x0a\x02\x33\x9c\xe2\x3f\xf8\xe5\x3d\x04\x3f\x94\x4b\x4b\x49\x50\x45\x6a\x74\xc7\x3a\xda\x49\x28\x07\xc6\x87\x07\x4a\xf7\x6c\x1b\xa7\xfb\x24\x27\xd8\x92\x0e\x6e\xd1\xb0\x46\x8e\x06\x85\x2c\xdc\xe9\xa4\xc2\x8b\x0f\xe3\xca\xe5\x65\x31\x17\xf7\xca\x1f\x9e\x2a\x82\xa6\xa7\x12\x54\x90\x15\x7e\xf2\x27\x80\x81\x60\x9a\x70\xea\x8e\xf1\xb7\xdb\xbe\xa7\x53\xe2\x4e\x82\xa5\xdd\xd9\xb8\x10\x84\x46\x1a\x1f\x61\x50\xe0\x73\x73\xd5\xb3\x1f\x77\xdb\xe6\x44\x4e\x4f\xfc\x44\x20\x89\xcb\x7d\x0a\x4a\x68\x59\x39\xf7\x1a\xde\x07\x2d\xa2\x95\x50\x53\xb5\x7b\xe9\x40\xe8\x8f\x01\xbe\x1f\xa1\xbe\x21\xf3\x63\xa8\x23\x44\x72\xbd\xc1\x5a\x53\x49\xf9\x18\xfa\x49\xa7\x08\x3a\xea\x1f\x99\x7c\xb8\xb9\xdd\x14\x34\x08\xc3\xa9\x91\xa6\x3b\x5d\xe7\x7f\x9d\xd4\x87\x2e\x7e\xa4\xea\x16\x58\x08\x30\x62\x0a\xce\x0f\x58\xdc\xa7\x47\xfe\x38\x0f\xc2\x1c\x17\x19\xfb\x5e\x3f\x02\x41\x0c\x5d\x30\x94\x0f\xea\xae\x0c\x3e\xa9\x5b\x3d\x86\xa6\x30\x75\xdb\x97\x00\x1d\x96\xfa\xa3\x65\xb7\x99\x00\x44\xe5\xc0\x25\x94\xb3\xad\x58\xd2\xf0\x3f\x4a\xcd\xe7\x35\x68\x93\x53\xab\xfc\xb4\x39\x75\x01\x41\x4b\xd1\x87\xa7\x52\x73\x25\xe4\xd9\x6d\x7f\xb0\x27\xd4\x45\x21\x65\xd2\x8f\xa5\x51\xd9\xf9\x5f\x67\xe9\xa7\xc6\x97\x50\x4f\x68\xc8\x90\x55\xb6\x7d\x22\x3d\x74\xc2\xcd\x06\xf8\x61\x5f\x82\xa6\xbc\x28\x33\xc8\x86\x17\x50\x83\xf1\x94\x12\xed\x0a\xc9\x81\x3d\x98\x3a\xdc\xd4\xe7\x65\xe2\x1b\xd2\x50\x7c\xf8\xe0\x3c\xf5\x6b\x19\x78\x48\x18\xf8\xf0\xfd\x95\x5c\x5d\x22\x8a\x1b\xf1\xfc\x14\x84\x5a\x2c\xde\x16\x32\x07\x4a\xbb\xbb\xb0\x16\x9b\xc9\x4f\xc1\x6a\xaa\x51\xa0\xfc\xb1\xae\xee\xd3\x20\xc1\x29\x9e\x48\xbf\x8c\x57\x6f\x22\xe8\xb0\x18\x15\x90\xdf\x63\x67\xd0\x21\x16\xf6\x15\x2b\xd9\xeb\x7b\x0c\x6c\x01\xf1\x7f\x6f\xd6\x38\x81\x3c\x14\x6a\xa5\xdc\xfa\x3e\x3b\xff\xaf\x91\xb6\x6e\x9b\xf2\x64\xbc\xe9\x17\xe7\x13\x49\x89\x30\x30\x89\x01\x44\xcc\xfc\x6f\x97\xe3\x7e\x03\x99\x40\xdf\x69\x25\x29\x05\x1b\xd9\xcd\x40\x77\x5e\xb5\x8a\x83\xe5\x13\xe5\x8c\x2a\x04\xa3\xd8\x45\x88\x55\x5f\xb9\x12\x4a\x72\x4b\xf1\xa7\x14\x56\x1e\x18\x3b\x26\x7b\xf6\x01\x78\xf7\x78\x99\x6a\x06\x03\xc6\xbf\xc0\xb8\x7a\x26\xe4\xa4\x66\x96\x29\x4e\x61\xe9\x0b\x63\x6a\x05\xe7\xff\x4e\x5e\x2b\x46\x84\x53\xdd\x80\xae\x96\x3b\x77\x4b\xee\xc3\x32\x33\x94\xa6\x4a\xe9\x64\x53\xb2\x2c\xb9\xce\x1d\xbd\x46\xfe\xc2\x4c\x71\x32\xbd\x12\xf7\x4b\xf4\xa9\xf3\xdb\x22\x8d\x65\x79\x46\x66\xdb\x83\x7c\xd6\x39\x91\x9d\x6a\x96\x2b\xeb\xd5\xbd\x27\x78\x3d\x54\x98\xa5\x9b\x68\x8d\x08\x81\x20\x87\x10\x43\xd5\x52\xb2\x64\x25\xb7\xe5\x3b\xb1\xca\x56\x02\x64\xa0\x7c\x1a\x34\x4a\xfb\x33\x9b\x2a\xb1\x39\xd7\xa2\x7e\xda\xf8\x2f\x4d\x43\xeb\xb9\xda\x60\x97\x34\x14\xc3\x2c\x2d\xc1\x50\xdf\xa2\x4d\xdd\x87\xe1\xd8\x3d\x70\x85\xa0\x15\x05\x87\x98\xda\x0c\x4e\xe0\x7a\xc8\x32\x2f\x4e\xd6\xcc\x58\xda\x7c\xaf\xcb\x97\x5c\xe3\xba\x19\xd7\x88\x3b\x4d\x1d\x78\x62\x50\x1f\x3d\x5f\x93\x85\x73\xc8\xe8\xc9\xa9\xb4\x64\x6b\xe3\x23\xab\xbd\x1b\xda\x8e\x79\x7b\xf7\x0f\x75\xef\x96\x6a\x2d\xb4\x8c\x7e\x53\x50\x5c\x2a\x7f\xe1\x31\x24\x71\x2f\xe0\x49\x77\x64\xf3\x2a\x69\x25\xee\x29\xfd\x18\xbd\xe9\x39\xf3\x93\x9d\x85\x8a\x98\xc7\xe9\x29\x2e\xe5\x2e\xaf\x05\xfa\xd3\xdc\x02\x75\xb8\xdb\xaf\x19\x3a\xd9\x65\x3f\x29\xc3\x2a\x57\x09\x12\x6e\xad\xc1\x05\xeb\xd5\x12\x1e\x63\x8a\x6f\xa3\x54\x4e\xeb\x53\xe7\xc1\xfd\x78\x4d\xe7\xf3\x53\x02\xcb\x19\x87\x0c\x1f\x2a\x67\x96\x25\x1d\xee\x3d\x40\x23\x7c\xb0\xb7\xd3\x59\x5a\x3c\x98\x7f\x12\x02\xff\x44\x55\x7f\x43\x3e\x65\xee\x10\x08\x18\xe6\xfe\x8d\x0c\xd5\x21\xc9\x8e\x7b\x31\x24\x81\xb2\x32\x9b\x91\xfc\x0d\x86\x08\x65\x97\x30\x33\xdb\x3a\xdb\xc5\xd3\x63\x93\x59\x49\x16\x77\x7a\xc8\x73\x23\x62\x65\x7e\x54\xc4\xa1\x92\x15\x96\x38\x82\x1c\x6a\x26\x5f\xce\x0d\xdd\x45\xe4\x8c\x3c\x66\x94\x08\xc7\x90\xee\x96\x76\x8a\x13\xfd\x61\x6c\xe0\xe3\x84\xf0\x44\x0a\x27\xe9\x1d\xa6\xc3\x4a\x10\xe8\x2b\x7d\x21\x0c\xb1\x28\x7f\x57\x24\x86\xf0\x1c\xa8\x7c\xe8\x92\xd9\xec\x9e\xaa\xdc\xcb\xe7\x4b\x24\x24\x66\xf0\xe0\x33\x18\x5c\x71\xaf\x4d\xcb\x92\x14\xbc\x55\x40\xdc\xe1\x6d\xe4\xae\x66\x1f\xdf\xcf\xbd\x8f\x79\xc8\xbd\x37\x2e\xef\x5e\x4a\x39\x4b\x38\xf0\x3c\xb5\x0a\x94\xf2\x9d\x73\x25\x03\x95\x2a\x50\xc0\x67\x6d\x61\xdf\x43\x24\x85\x90\x87\xec\x61\xa2\xa3\x25\xfe\xc4\x04\x0e\xb1\xcc\x7f\xa6\x98\x86\x9f\x34\xee\x87\xf8\x0b\x5b\xd8\x65\xf5\x54\x8a\xd9\x59\x6f\x1f\xbc\x57\x79\x59\xa3\x02\x64\xba\x92\xcb\x45\xab\x9f\x59\x03\xbd\x24\x3f\xd1\x33\x00\xe1\x3f\x0c\xac\xc7\x92\x10\x0d\x72\x3c\x50\x2f\x93\x2f\x03\xb3\x21\x3f\x17\xa2\x73\x7a\xec\x2e\x55\x36\xa5\x43\x7f\x4a\x96\xaf\xcc\x03\x47\xba\xd3\x0c\x34\x49\xea\x54\x7e\x5c\xce\x2f\x17\xec\xaa\x15\x62\x79\xa8\xe8\xda\x10\x9f\xb8\xbd\x02\xaa\x08\xbd\xca\xe8\xfe\x0b\xa0\x58\x5b\x92\x53\xff\xcf\xec\xfe\xff\xe5\x39\xf1\xef\x4e\x8e\x3b\xed\x3f\xb2\x51\xca\x6f\xc0\x76\x33\xd7\xd4\xb3\x38\x74\x26\x83\x7f\x59\xd6\x73\x9e\x43\x10\x22\xe0\x00\xec\x30\x9e\xfb\xed\x6a\x36\x8a\x4d\xb1\xb1\xb5\x75\x53\x57\x31\xe0\x87\xf9\xd3\x96\xd2\xe7\xf6\x3f\xe9\x44\xeb\x31\x34\x04\xa3\x37\xf8\x04\xf0\xe7\xa6\x1c\x24\xf8\x9f\x53\x9d\xb1\x41\x6f\xb2\x4e\x2e\x41\xbf\x38\xa7\xca\x01\x2d\x47\x19\x6f\x9b\xf1\xa8\x79\x77\x9d\xc1\xdf\xd8\xe1\xe3\x11\x9a\x66\xe9\x3a\x9a\x21\x1a\xfd\xbe\xd1\x78\x9a\x80\x19\x81\x58\xd1\x43\xcf\xd0\x94\x8b\x2a\x0e\x5d\xd5\x21\x2e\x39\xe7\x84\x03\xc4\xa4\xc8\xbf\x25\xce\x03\x77\x4a\xaa\x28\x53\x8a\xbc\x05\xdb\x80\xb4\x08\x86\x23\xd9\x71\x7b\x1c\xdf\x63\x4b\xd9\x4f\x8d\xb8\x17\xc2\xb4\x5f\xe8\x95\x6b\x67\x9f\x8a\xae\x22\x83\xf2\x81\xe5\xdd\x4f\xad\x8a\x16\x8c\xdf\x29\x4a\x61\x5f\xd4\x05\x96\x6c\xee\xd8\xad\xd2\x76\xe3\xd4\x63\x0e\xb9\x5c\x8c\xdc\x23\xe7\xf8\x94\x7f\x81\xdd\x9d\xe3\xec\xf7\x2e\xcc\x8b\x50\x64\x88\xcb\x40\xda\x68\xf5\x89\xfe\x92\x66\x3c\x0c\xf8\x38\x7a\xc1\x1e\x01\x01\x32\x91\xa2\x0e\x6f\xdd\x4b\x8b\x61\x7a\xb9\xf2\x71\x08\xba\xa3\x76\x97\xf2\xaa\x59\x0e\xc7\xa9\x14\xa0\x64\x27\x34\x2d\x0d\xe7\x09\x2c\x74\x13\x90\xa5\xb2\x2f\xee\x77\xfd\x4e\xf2\xa1\x54\x56\xe3\xa6\x62\x71\xdf\x77\x59\x46\x84\x70\xd5\x45\x09\x30\x60\xd1\x77\x96\x53\x37\x7d\x1f\xd2\x54\x73\x9f\xc2\xf0\x88\x14\x8a\xdd\xfe\x25\xfb\x24\x13\xbc\xa7\xe8\x17\x68\xd0\x01\x05\x59\xd5\x39\xd5\xb1\xb3\xf1\xb8\x52\x18\xa7\x36\x76\x3a\xdc\x7b\xff\x2d\xfd\x5b\xc1\xad\x44\x99\xa3\x64\xdf\x4c\x51\x5a\xf6\x23\xbc\x9c\x67\xa7\x32\x22\xc1\x26\x0c\x1f\x90\x15\x6b\xb3\xef\x69\x1e\x65\x9a\xe4\x2e\xef\x16\x0d\x5b\x68\x81\x3a\xa7\x99\x2d\xe6\xb8\x5d\x5c\x95\xad\x1e\xfc\x50\x21\x54\xee\xb9\x41\x14\xb6\x6a\x5f\xf6\xb0\x5e\xf1\x8c\x7e\x0f\x56\xf1\xd6\x97\x7c\x43\x19\x0f\xfb\xe4\x5c\x2d\xfe\x5b\x28\x67\x21\x88\x64\x39\xb9\x63\x56\x6f\x60\xcd\x66\x6f\x37\x61\x1f\x0f\x53\x3f\x2c\x58\x01\x55\xec\xba\x71\x80\x7a\x4c\x9e\x0a\xaf\x46\x63\x4a\x4c\x6b\xeb\x07\x4e\xa1\x64\x38\x51\x72\xaa\x96\x66\xa4\x6a\x7d\x49\xfe\x2a\xd4\xba\x69\x73\x22\xa2\x6c\x56\x27\x69\x35\xe6\x7b\x2d\xb1\x2e\x1a\xf1\x65\xcd\xd6\xce\x1a\x98\x79\xa0\xb6\xb4\x65\xd6\xaa\x5a\x00\x8f\xa7\x94\xed\xf4\xfa\xe2\xcd\x62\x57\xb6\xb5\x9f\x5e\x76\x38\xf7\x08\x9f\xde\xe6\x5e\xee\xec\xf9\xa5\x90\xd0\x20\xc2\xb2\xf3\xd3\x97\xde\x66\x81\x95\x17\x44\xba\xad\xdf\x45\x8a\x81\x3b\x3e\xcf\x52\xfc\x2b\xf5\x2b\x11\x31\x77\x8c\x23\x76\xca\x50\xa3\x6e\xe9\xa5\x40\x9f\xcb\xe9\xf4\x1a\x45\x38\x81\x87\xd4\xc5\xb4\xc8\xe9\xd9\xa5\x29\x74\x3b\xf9\x0c\x9b\x8e\x20\xeb\x43\x8b\x8d\x0f\x61\x8a\x08\xe4\x4b\xcf\xcf\x66\x49\xa1\x1b\x8b\x3a\x81\x37\xbb\xb2\x6a\x2e\x92\x57\x1a\xde\x02\x8e\x69\x01\x07\xe4\x7f\x9e\xd6\x8f\xe5\x90\x83\xff\x98\xb9\x2a\x87\x45\xd7\x6e\xd2\xf7\x84\xf9\xab\x5a\x75\xb8\xf4\x2d\xa9\x51\xd6\x00\x0e\x45\xfb\x68\xae\x96\xbf\x33\x2a\xc0\x51\x79\x64\x3b\x28\xc0\x4c\x9f\x8e\xa0\x26\x25\x75\x20\x12\xe1\x36\xa3\x6f\xac\x4c\x0c\xb3\xa6\xe4\x94\xef\x63\x69\xef\x97\x20\x7a\x93\x69\xbb\x4b\xb6\x64\xcc\x73\x28\x7b\xa8\xbc\x32\xbe\xe1\x67\xf9\x76\xb2\x9b\x6e\x36\xcb\xf8\x21\x3e\x92\x8b\x87\x31\x6c\xc4\x62\x55\x27\xe6\x1f\x9d\xeb\x3f\x65\x33\x08\x97\xf4\x93\x1a\x6a\x10\xea\x6b\xed\xaf\xc1\xfd\xd1\x73\x1e\x78\x5e\x8d\x37\x50\x1c\xcc\x82\x01\xa4\x73\x0e\x32\x2f\x10\xc3\xa3\xa7\xf7\x50\x0f\x0d\x64\x28\x32\x1c\x1a\x2e\x56\x9e\x6f\xdf\x84\xae\x87\x46\xf9\xbe\x53\x85\xc5\x29\x6a\x53\x93\xd3\xea\x54\x6a\x44\x68\x39\xf3\xf8\xb3\x73\x0b\xa7\xdb\xb2\x94\x49\x2f\x40\xe9\x41\x90\x05\x90\x4a\x4d\x50\xe8\xbc\xe9\x73\x1c\xfa\xf2\x7f\x37\x75\xe4\xec\xe6\x08\x2c\x6c\x68\x89\x59\xb8\x69\x00\x5d\x7b\x72\x2e\x1b\xd9\x0e\xe0\x7d\x6a\x90\x60\xd5\x24\x8d\xf4\x4b\x8a\x82\x82\x00\x6b\x73\x80\x27\x36\x48\x1e\x96\xe3\x7c\x4c\xd1\xde\xc6\x80\x3e\x29\xc4\x97\xa2\x99\x53\xd5\x07\x0a\x2a\x26\x9f\x27\xcc\x61\xa4\x1f\x72\x56\xeb\xae\xfb\x56\x5b\xec\xf0\xa4\x2f\x27\xb4\x1f\x76\x97\x4e\x90\x1f\x7b\x6e\x45\xdf\x2f\x1c\xef\x35\xf9\xd7\xa3\xe5\x3d\x3c\x75\x3b\xcf\x17\x30\xe0\xa9\x24\x19\x7d\xbf\xfe\x4a\x86\x75\x79\xdc\x53\x55\xe7\xc6\xb8\x7f\xd1\xdc\xff\xa1\x1f\xb5\x98\xcd\xea\x9b\xea\xff\xf6\x82\x18\xc1\xd1\x72\xfd\xe2\x1e\x22\x38\x4b\xb7\x6c\xd7\x91\x8c\x92\x89\xfb\x07\xbd\x42\x90\xb5\xb0\x81\x6f\xa6\xea\x54\x18\x40\x65\xb7\xa3\x15\x56\x22\x89\x80\xaf\x73\xd3\xa3\x99\x1e\x4d\x45\x05\xa3\xee\xa4\x1c\x7f\x77\x1a\x22\x80\xc2\xfc\x9e\xdc\x40\x3c\xc2\xfb\x92\xd5\x41\xa7\x11\x0e\x21\x02\xc1\x3c\xb0\x80\xaa\x56\x40\x0d\xa7\x2d\xbe\x29\x3c\xd0\xbd\x80\x78\x50\xba\x3d\x4a\x44\x2e\x74\xd9\xb9\x4c\xeb\x50\xf2\x7c\xa9\xac\x9c\x61\x46\xc6\xb7\xec\x7e\x62\xf5\x15\x7b\x8d\x5d\x28\x6b\x85\xc9\x19\xaf\x90\xf6\xdc\xaa\x22\x5a\x6f\xad\x75\xe4\x93\x91\x16\x5f\xbd\xc4\xd6\x79\x33\xb0\x45\x91\x28\xa3\xc3\xab\xe7\x61\x24\xa0\x07\x23\x43\x2d\xb9\xb0\xc7\xf7\x69\xfb\xd6\xff\x6f\x47\xf3\x8b\x4f\x8b\xb3\xa1\x17\xa8\x99\xff\x10\xc4\xc1\xca\x6e\x0c\x39\x55\x67\xc8\x90\x4b\xd5\x70\x3e\xea\x0b\x48\xad\x18\x85\x90\x56\x76\xab\xa1\x46\x2c\x90\xeb\xb2\xc4\x4f\x40\xb8\xf7\x1f\x9f\x9c\x1f\xb6\xe9\xe1\x09\xfe\x7e\xb8\x89\x58\xae\x41\x4f\xf7\x83\xbb\x2c\xf7\x10\xad\xf8\xa3\x9c\xe7\x01\x7a\x2a\x37\x0d\xe9\xf5\x33\x44\x4c\x40\x32\x2b\x18\xf6\x46\xee\x10\xf2\x73\x8a\xb7\x8c\xdb\x17\x47\x3a\xc4\x0c\x1a\xa8\x0c\x6f\x75\xfa\x3e\x51\x53\x97\xaf\x5b\xd3\x3e\xf4\x0a\xc3\x92\x15\xee\x6c\xf2\x3b\xdb\x4b\xac\xaf\x68\x58\x04\x5f\x93\x8c\x12\x1a\xec\x7c\x6a\xf9\xb3\x3f\x56\xda\x46\x97\x40\xda\xad\x63\x45\xc0\xa0\x55\xc8\x1b\xa0\x88\x75\x71\xa5\xe8\x17\x71\xeb\x95\x24\xd0\xf4\xe9\x06\x5c\x07\x26\xb8\x54\x79\xf1\xae\xe5\x65\xd9\xc6\x46\x28\xf9\xfd\x16\xd9\x3b\xaf\xa6\xde\x6c\xe8\x4e\x4a\x0b\x25\x23\xbf\xe3\xdf\x7b\x8f\xd2\x4b\xa2\xaa\xab\x50\xb3\x9c\x3e\x88\xa3\x94\xf6\xc1\x30\x08\x63\x65\xd9\x31\xcc\x93\xaf\xfe\x17\x61\x59\x4b\x70\x9a\x01\xeb\xd0\xb2\xa5\x75\x1a\x93\x7a\xe0\x61\xd8\xc2\x3d\xd7\x77\x80\x66\xc3\xa8\xd1\x42\x7d\x20\x28\x7d\x07\xfb\x73\x90\xca\x9b\xe7\x72\xc7\xfb\x22\x7f\x81\xcd\xc1\x9b\x1e\x25\xcb\x24\xbe\x73\x49\xe2\x53\x9d\xec\x1c\xd9\xd2\x56\xc7\x78\xbf\xa7\x25\x34\xdb\xfa\xba\x00\x82\xf6\x76\xa9\xb6\x38\xdf\xef\x09\x12\x94\x72\x9b\xbe\xd2\x23\xd4\x90\xca\x89\xf1\x8c\xba\x68\x7f\x4b\x3e\xa9\xd2\x96\x22\xfb\x67\x7b\x37\x60\xb5\xf8\xe3\xda\x0a\x98\xf5\x6c\x7d\x14\x97\x75\x57\xfb\x53\x4b\x25\x36\xe2\x22\xfd\x67\xc4\x3d\x66\x19\xe1\x48\x0a\x14\x6d\xa4\xf7\x4a\xd3\xd7\x6a\x48\x0b\x35\x7c\x8f\x26\xf6\xea\x2a\xba\xdb\xe1\x6e\x5f\x64\xa5\xc9\x0a\xc0\x69\xbf\xf9\x49\x4f\xeb\x5e\xee\xb1\x8b\x4a\x5a\x2a\x58\xee\x00\x60\x35\x17\xe5\x97\xa3\x29\x89\xb5\x3d\x8c\xa2\x9b\xf9\xc7\x3d\xcc\x4d\x5b\x9a\x92\x72\x4a\xec\xcf\x69\x0d\x7c\x02\x06\xf0\xf1\x89\x24\x82\x1a\x4a\xe0\xb4\x99\x69\x49\x76\x04\x72\x2d\x95\x9f\x3c\xe7\x4e\x3a\x46\x73\xd9\x29\xe1\xd9\x80\x1b\xbe\x23\xbf\x10\x53\xe9\x35\x06\xcc\x36\x3c\x77\x91\x72\xe7\x4a\xcd\xde\xbf\xb0\x65\x5b\x3f\x06\x7a\xa4\xec\x0f\xfe\x0b\x64\x35\xc5\x1c\xfd\xf4\x84\xde\x5d\x7e\xa8\x5d\x8d\xb6\xa0\x31\xd5\x1c\xb7\xc9\x48\x01\xf3\xba\x23\xa5\xa7\xc4\xad\x49\x4c\x1b\xc1\xd8\x5a\x52\x0e\xbf\xba\x6f\xa3\xce\xf0\xc6\x2c\x35\xda\x24\xc5\x8e\x12\xb2\x3f\x87\x0e\xe8\x72\x1c\xf8\x1c\x42\x88\x79\x07\x49\x09\x80\x5a\xdd\x3e\x0e\x9b\xff\xac\x63\xb2\x94\xfd\x4a\x41\xeb\x95\x03\x18\x8a\x0a\x42\xa9\x20\xd8\xde\xdd\x54\x87\xe0\x6e\x19\xe7\xf7\x1b\x97\x8c\x60\x26\x95\x8f\x9a\xb7\x46\xb7\x16\xdf\x90\x52\x1d\x53\xed\x3f\x28\x0f\x6e\xd2\xba\x6d\x23\xac\x5c\x12\xb7\xcc\xac\xcb\x85\xed\x2c\xf6\xb3\x1d\x4e\xc4\xe7\xf2\x35\x8a\xf2\x39\xcb\x91\x10\x52\x75\xd3\x28\xb2\xb7\xdf\x21\xf2\x84\xfb\x28\xf4\x4f\xc9\x9f\xcb\x11\x69\xf6\x77\xa9\xb4\x46\xaf\x34\x6d\x9a\xa1\x55\xe3\x41\xf1\xac\x6b\x28\xd2\xe6\x12\x4b\x55\xad\x80\xc2\x76\xdf\xa4\x5f\x01\x8c\xa7\x0a\xb2\xb2\x72\xa2\x45\x7d\x1c\x65\x26\x53\x39\xc9\x79\x93\xa2\x0b\x33\xd5\xca\x70\xea\x75\x05\x97\x1a\x20\xe4\x72\x2e\xca\x93\xb6\xe0\x94\x9c\x8b\x03\x71\xca\x56\x02\xbd\x93\x94\x88\x77\x1f\x6b\xc9\x12\x48\xa7\x6a\xfd\x67\x54\xfd\xfe\x13\xd3\xf0\x9f\xf4\x64\xc9\x3a\x2e\x46\x8b\xfc\xab\xde\xc7\x7b\xcb\x95\x40\x27\x3f\x07\xa8\xca\xd1\x39\x31\xe9\x50\xa3\x85\x7a\xc0\x15\x67\xcf\xab\xba\xc8\xd6\xec\x07\x16\x17\x52\x10\x18\x94\xff\x95\x0f\xb9\xda\x26\x0f\x99\xc2\x55\x43\x9e\x15\xbc\x5d\x80\x2a\x95\xae\x6c\xa3\x01\xea\xbb\x31\x99\xa6\xf9\x6c\x34\x76\xa7\xa9\xd1\xbf\x52\x3e\x98\x4e\x3f\x8f\x89\xce\x90\x6a\x6e\x3c\x87\xaf\x35\xba\xbb\x16\x42\x7b\xc0\xd8\xeb\x6d\xa9\x7d\x08\xf5\x87\xd1\xea\x03\x13\x78\x94\x43\x37\x72\xb1\x56\x8f\xb2\x2f\x86\x57\x6d\x4a\x4b\x85\x57\x21\xe9\x91\xb5\x47\x1f\x19\x20\xb1\x49\xf9\xf3\x23\x93\x6d\x12\xa2\x2f\x4c\xaf\x7b\x5b\xcb\x9e\xbf\xc0\x4f\xdc\x43\x33\xfb\x5e\x12\x25\xf6\x9d\xb9\xf0\x68\xc4\xd0\xd8\x1b\xfd\xfb\x8e\xa0\x9d\x4f\x0a\x6c\x77\x08\x4c\x19\x02\x4b\xf8\x94\xbe\xf5\x7b\x4f\xa7\x01\x63\x5c\xf7\x2f\xdd\x9f\xfe\xaf\x14\x0e\x7d\x87\xb3\x5b\x46\x80\xb2\x6e\x4f\x11\x50\x71\x8f\xa1\x84\x79\xeb\xd1\xb2\x1f\x76\xbb\x2c\xdf\x99\xdd\x42\x76\x4b\xfc\xf6\x68\x35\xe0\xd4\x89\x68\x4f\x91\xbf\xcd\xf8\x26\xb2\x0f\xac\x2c\x58\x75\x49\xcb\x53\xd1\x24\x63\xb6\x19\x62\xe3\x5f\x68\x58\x67\xb4\x50\xe2\xa9\xa3\x74\xe6\x14\xfa\xc1\xec\xdc\xf5\x95\x22\xcc\x75\xfd\xa1\xce\x13\x5c\x86\xf6\xd1\xec\xae\x10\xee\xd2\x3d\x1c\xe4\x76\x1c\x0a\xe6\x58\xda\x9e\x56\x8b\xe5\xbd\x90\xf4\xfb\x2c\xa3\x2d\x12\xda\x4f\xb2\x9d\x5a\x5b\xb1\x60\xa5\xe4\x5e\xa2\x0d\xfc\xca\xd1\x46\x1e\x97\xb3\x36\x87\xd9\x61\xfe\x27\x05\xae\x1d\xe6\x7b\xb4\x6d\x38\x17\x5f\x6a\xf8\x13\xad\xbd\x32\xd3\x78\x77\xb9\x04\x7b\x60\x2e\x7d\x98\xe6\xde\xc4\x0b\xdc\x75\x5a\x91\x15\xcb\x9f\x51\x56\x4b\xb9\xb1\x25\x0b\x9d\x16\xf7\xb5\x93\x5c\x8e\x9d\x26\xf4\x0f\x01\xd8\xd8\x91\xe8\x09\xc0\xda\x24\x29\x1e\x60\x3e\xae\x06\xf2\x59\x52\xaf\xc5\x79\x6f\xd7\x0d\x8a\xf6\xcd\x76\xf6\xa6\x37\x80\x20\x3f\x33\x71\xb8\x29\xfd\xbd\x79\x68\xee\xa6\xf3\xaf\x44\x0b\xd1\x64\x6f\x45\x89\x9f\xca\x11\x67\x0b\x83\xc9\x2c\xf6\xb2\xa8\x00\xa4\x06\x2c\x4f\x91\xe8\x2b\xe2\x01\x72\x6d\x36\x08\xee\xd3\x09\x3b\xe3\x9b\xf8\xf2\xfe\x31\x84\xfc\x7b\x3d\xc6\x11\x53\xa3\x7d\xdb\x88\xe9\xc6\xcb\x2e\xfd\x65\x73\x5b\x0e\xf9\x37\xf6\xb3\xb7\x64\x9c\x6a\x0a\xfb\xbf\xb4\x4b\x26\x5d\xa2\x07\x32\x42\x70\x3f\x84\xa5\x16\x3f\x58\x94\x50\x19\x40\x8e\x24\x53\x25\x8d\xd4\xab\x9e\x21\xdc\xed\x23\x17\xf6\x54\x1d\xb0\x4a\x35\x3a\x90\x0b\x56\xe4\x5d\x6a\x79\x48\x7c\xca\xdf\xcd\x8c\x76\xb3\x10\x35\x86\x3c\xeb\xc5\x23\x83\x77\x0a\xaf\x2a\x0c\xd3\xf3\xdb\xa4\x32\xf1\x2d\xd0\xd6\x5e\x63\xe0\xce\xd1\xbb\xc6\xed\x7d\x5f\x3b\xdc\xbd\x9e\x58\xfe\x7e\x3d\x90\x94\xf4\xbd\xca\xc1\xaf\x53\xa1\x42\x53\xf1\xab\x50\x42\x8c\xe4\xa0\x6c\xad\x20\x12\x92\xe2\x7f\x54\x8e\x99\x74\x79\x94\x30\x4f\x81\xf2\x05\xcb\x2c\xe4\xbe\xce\xc5\x41\x8b\x59\xeb\x5b\x7f\xfc\x41\xf6\xdb\x8d\x6d\xee\xfb\x3d\x6c\x13\xc7\xc7\xe3\xc2\x9f\x06\xd1\x11\x22\x6c\xfc\xd5\x72\xa9\x13\xe5\x89\x35\xa5\x4f\xf9\xcc\xb1\xe3\x77\x7a\x5c\x74\x5a\xc8\x20\x3a\x8b\x1e\xb7\x50\x40\xde\xc4\xa5\xe0\x78\xa7\xad\x52\x41\x01\x59\x5d\x2c\x8a\x58\x4e\xda\xb0\x29\x2f\xd7\x28\x74\xcb\x3d\xd5\x3b\xe8\x3a\xcf\xc5\x24\xcb\xa9\xd4\xda\x7c\x52\x20\x80\x74\x5c\xf4\xb5\x37\x8f\x14\x25\xd9\x63\x6b\xc7\x17\x18\x4b\x55\xf9\x80\xa6\xfc\x01\x41\x55\x2b\xbb\x4a\x8d\xf4\xad\xba\x54\x90\xfa\x58\x76\x93\x21\xb2\xc7\x55\x58\x40\xd0\x6c\x0b\x78\x80\xa4\x74\x58\xa2\x70\x17\x80\xb9\xc3\x0f\x83\x82\x01\x4f\xbf\x96\xf5\x02\x6a\xa7\xbc\xfc\x96\x6d\x2f\x20\xdd\x58\xd3\xf6\xf0\x9f\xc2\x09\x06\xb8\x15\xd6\x8b\xc9\x79\x0b\xcf\x91\x7d\x09\x5e\xfd\xae\xf2\x1f\x72\x8e\x55\xd8\x99\x1e\x6f\x6d\x40\xd8\x4b\xb2\x7e\xa1\x0c\xde\x2e\xce\xb0\xb4\x22\x21\x2d\xfe\x27\x67\xee\xc7\xe3\xb4\x2b\x74\x86\x34\x9a\x3e\x97\xa1\x7c\x42\x9a\xd7\x94\xe5\xdd\x7c\xbb\xb2\xf7\x6d\xc2\xa9\xbc\x7e\xb7\x6c\x41\xf9\xb7\xf8\x84\x5e\xff\x64\x5f\x9d\x2e\x40\xf0\x52\x11\xd3\x02\xfb\xa1\xc6\x3f\x8a\xfc\x47\x36\x38\xe1\x83\xca\x46\x79\xff\x61\x94\x4b\xa9\x00\x3a\x3b\x4e\x9c\xc1\xd8\x9b\x2b\x7b\xaf\xfc\x2d\x6a\x4f\x81\x9a\x76\x63\x13\x3f\x42\x1c\x7b\xe7\xf2\x7e\x90\x95\x65\x64\xfd\xff\x60\xac\x00\xb9\x3d\x03\x1c\x5b\xca\xf5\x00\x3d\x54\x99\x50\x62\x68\x29\x11\x1f\x77\x87\x64\x69\xa9\x70\x19\x0f\xe8\x2f\x88\x79\x7c\x12\xa5\x0e\xf6\x9b\x0c\xa9\xcd\xd8\x5c\x99\xee\xf1\xed\x88\x6a\xf7\xe7\x2b\xeb\x0f\xe2\x5c\x79\x57\x51\x33\xd8\xdf\xa6\x1c\x93\x7b\x2d\x11\x72\xae\x30\xc6\x15\x2a\xf1\x50\xe0\x56\x96\x4f\xc2\xa4\xd5\x2c\xca\xe1\xad\x13\x7d\x75\xdf\x86\x1a\x09\x21\xa1\x43\x22\x85\xfe\xbd\x29\x3d\x4e\x43\x6a\x03\x28\x3b\xc6\x24\x74\x1d\xdb\x45\x78\x69\x7c\xb1\x6a\xe5\xbf\xa3\x5a\xd8\x21\xea\xab\x84\x8f\xb8\x8d\xda\xe1\xbf\xa1\x82\x70\xef\x9e\xbc\x79\x66\x11\xd8\xc4\x3d\x25\xd9\xb2\xe0\x27\x20\xc0\xf1\x24\x09\x5f\x0c\x55\x10\x2d\x61\x41\x04\xcc\x8e\x28\xe0\xb9\xb0\x6e\xc2\x5f\xf5\xed\x4d\xf5\x09\x7b\x6b\x35\xe4\x4f\x01\x64\xcd\xc9\x28\xd9\xa4\xfc\x37\x4b\x6e\x23\x5b\x93\x79\xfc\x2b\xfc\x04\xe6\x0f\x51\x5b\xf4\xd0\xca\x61\x5d\xd0\x36\xda\xa8\x94\x48\xeb\x55\x1e\xa0\x92\xf3\xca\xee\x9a\x65\xdb\x79\xa8\xe5\x22\x63\x38\x5d\x56\x98\x8c\xc2\x9a\xc2\x11\x0a\x90\x8d\xaa\x93\x90\xee\x21\x7e\x7d\xbc\x84\xa5\x62\x5e\x33\x84\x99\x29\x30\x1a\x04\x2d\xdc\x84\x8d\x55\x9d\x70\x3e\x10\x65\x82\x77\xfd\xcc\x1d\x55\x47\x9f\x1a\xc0\xb1\xcd\x6e\x89\x62\xc0\x5e\xc3\x73\xb3\xbc\x3c\xfe\xf6\x51\x73\xea\x71\x19\xc6\x66\xb4\xee\x25\xe4\xd4\xaa\x48\x76\x95\x3b\x21\x7a\x75\xf9\xc7\x58\x63\xcd\x97\x0f\xd7\x3f\xf8\x40\x98\x6c\x5f\x26\x1d\x01\x0c\x61\xe3\x7e\x6e\xfa\xd6\x85\x07\xd4\x64\x88\x85\x18\xce\xd8\xb8\xbc\x66\xbf\x70\xac\x6a\xaa\x33\xe1\x2f\x85\x62\xc4\x64\x60\x60\x6f\xb5\xc4\x88\x4d\x35\x8c\x18\xe6\xf0\xe7\x25\x44\xa1\x0a\xbb\xa9\xeb\x7e\x33\x62\xc4\x48\x11\x87\x01\x08\x3c\x3b\x2d\x7a\x9c\x41\x55\xe7\x4a\x75\x42\x34\x1b\x1f\xb9\xeb\xd2\xcc\x4b\xec\x21\x7b\x02\x90\xb2\xd9\x5b\x37\x17\x2e\xa4\x30\x33\xcc\xd4\xb4\xe8\x4e\x75\xba\xd9\xc0\x73\x27\x5c\x31\x09\xfe\x14\x2c\xf9\xfe\x8f\xaa\x2b\xcb\x52\x5d\x47\xb6\x73\xe1\xe7\xfc\xbc\x49\xc9\x0d\xc6\x89\x6d\xb9\xdc\x40\x92\xa3\x7f\xda\x4d\xc8\xdc\x5b\xb5\x16\x32\x09\x1c\x1a\x5b\x52\xc4\xee\xa0\x87\x0a\x6f\x07\xfe\x60\xf7\x51\x0b\x66\x30\x43\xd4\x18\x17\x05\xe6\x8e\xf5\xef\xc5\x13\x5b\xd5\x82\x31\xad\x52\x5c\x83\x91\xe5\x1a\x21\x08\xb5\xb5\x50\xed\x7f\x99\xf7\x2f\xde\x48\xae\x86\x95\xe8\x98\xf7\xe1\xfb\x3d\xb2\x61\x07\x1f\x83\x66\xaa\xbe\x3f\xec\x57\xc5\xd2\xd3\x2f\x6c\xee\xf3\xe1\xa5\x58\xfc\xb8\xb4\xef\xe7\xce\x36\xe2\x34\xba\x8a\x46\x7a\xa9\xff\xbb\xa0\x9e\x8c\x8e\xde\x2d\x5b\x99\x6f\x5f\xab\xcf\x82\x8e\x2e\xb7\xee\xa7\x15\x8f\x65\x25\xdc\x6c\x1a\xf1\xb6\x36\x2e\xa3\x65\x26\x2a\x2e\x9e\xbc\x58\x3c\x47\x0b\x1a\x57\x16\x12\x5d\x54\x5e\x2e\x33\x4f\xe2\x40\xe9\xe3\xf5\x28\x70\x8a\x6e\x6c\x1a\x3d\x1b\x4e\x60\xf6\x2a\xaf\x7e\x48\x1d\x49\x0b\xea\xa3\xf3\x14\x0e\xf7\xad\x7b\xe0\xff\x61\xdf\x77\x85\x93\x5f\xee\x14\xe9\x78\x34\x6e\xc2\x27\x8b\x13\x25\xc7\xe3\x7d\xae\x4a\x4e\x7b\xaa\xb5\xee\x64\x81\xdf\x12\xc5\x04\xe4\x1d\xbc\x75\x93\xb0\xdd\x02\xd5\x6e\xcb\xf4\x67\x3e\xcb\x3e\xc3\xfc\xb2\x6c\xf1\xa4\x9d\xdb\x0e\xe0\x3d\x87\xe9\x29\xeb\x47\xec\xbd\x6a\xd8\xe5\x67\x2f\x90\x7c\x5c\x21\x27\x58\x80\xda\xa0\x02\xd7\x28\xe0\x36\xdb\x2b\x37\x9e\x84\x54\x51\xf3\x89\xcb\x69\x34\x2f\x5f\x35\xcf\x78\x15\x3c\x67\xf5\x3d\x07\x71\x26\x02\xd8\xd2\x21\xae\x4f\x9b\x2f\x95\x69\x9b\x1f\x14\x37\xde\x54\xee\xd8\xbd\xe2\x8a\xce\xa5\xef\xc5\x7c\x51\x26\xda\xc7\xb9\xae\x4a\x76\x75\x38\x6a\xb9\x7d\x96\xb9\xa4\x63\x63\x8f\x9d\xa7\x88\x72\x2b\xdb\x00\xb8\x37\x39\x83\xaf\xec\x15\x68\xbd\xb7\x8b\x56\x8c\x6c\xc0\xa1\x3a\x9b\x36\x6a\x24\x97\x52\x27\xc9\x7f\xb9\x81\x88\x7f\x8e\xea\x25\x47\x00\xac\x28\x99\x94\xeb\x55\x33\x0c\xcc\x4c\x15\x23\x2e\x77\x3c\x5d\xfd\x64\x01\x00\x76\x04\xdb\x80\x9c\x6b\xa4\xd7\xe8\x1f\xe9\x35\xba\x7c\x6e\xca\xee\x21\x99\x9d\xb3\xb9\xfa\x59\x9e\x30\x9e\xd2\x50\x15\x47\xd9\x0e\xb3\xdc\xb0\x4d\xaa\xfd\xd9\xb7\xdd\x0a\x24\x9a\xa6\x57\x17\x52\x34\x07\x1d\xbc\xfe\x14\x1e\x29\xab\x76\x1a\x8d\xdd\x27\x6d\x9a\x52\x57\x66\x7d\xf7\xef\x5b\xc1\x51\x2a\x68\xa8\xe5\x74\xff\x07\x56\xa7\x2e\x83\x1a\x7d\xc8\xbf\x48\x07\x2e\x53\x0e\xdf\xd2\x5f\xf0\x50\xfe\xcc\xa9\xf8\x9c\xf6\x8b\xfc\x60\xaf\x16\xce\x43\x9f\xbc\x79\x13\x07\x4d\x13\x6e\x40\x60\xd7\x40\x22\xba\xb7\x3b\x76\xef\xc7\x67\xf9\xc7\x3f\x00\x26\xe0\xbf\x51\xaa\xa0\xa5\x72\x6a\x4c\x28\xd6\xb0\x14\x58\xb0\xe9\xbf\x5d\xa6\x65\x37\x74\xff\x69\xf4\x7f\x63\x65\x03\xd7\xbd\xcb\xa7\xcc\xa6\x14\xae\x69\xc2\x04\x6a\x09\x03\xd4\x55\x94\x70\x40\x9f\x59\xcf\xb7\x8b\xdd\x52\x5f\xa2\x8d\xf8\xf6\xb2\xe9\x10\x6d\xe7\x9c\x73\xd4\x3b\x3c\x75\x3d\x5e\xf6\x0a\x15\x1f\xe8\x9b\x38\x27\x1f\x78\xbf\x12\xe4\xc6\x59\x38\xc9\x31\x72\x71\x2a\xc5\xcf\x36\x88\x0e\xc8\xee\xe1\x2e\x7e\x02\xc6\xaa\x6f\xca\x35\x7e\xaa\xa8\x71\x50\xee\x4d\x42\xbd\xa3\xee\x2e\x60\x80\x06\x8e\xd4\x8d\x88\x42\xb8\xab\x95\xf3\xdd\x7f\x96\x73\xd7\x7e\x2d\xa9\x65\x77\x77\x8f\x94\xb9\x93\x51\xa6\x2e\x56\xce\x80\xa0\x1d\x46\xbd\xd5\x83\xf1\xf8\x89\x94\x54\xc0\x66\xbe\xfd\x26\xee\x54\xe6\x3a\x31\x87\xaf\x8d\x2e\xe0\xae\xe3\xf2\xf1\xd8\x02\x8b\xa8\xb1\xb9\x6b\xdf\x5e\xa6\x80\x7b\xd9\xc9\xb6\x61\x4a\x3f\x4d\xf9\xef\x8f\xa4\xe3\x0c\x20\x4e\x95\x44\x96\xd3\xd9\x02\xd1\x26\xff\xbd\x19\x3e\x5a\xa0\xbe\xf3\x7d\xb8\x17\x55\x7e\x06\x93\x8e\xf8\x5e\xcb\x43\x93\x7d\x22\xb0\x2d\x88\xbc\x5e\xa8\x48\x6a\x82\xbe\xb9\xb8\xc4\x23\x44\x41\x77\x35\xb3\x56\x1b\xb5\x47\x5f\x9e\xa1\x37\xd7\xbf\x22\xa7\x1e\x96\x89\xe6\x29\x4d\x55\xef\x01\x8a\x52\x74\xaf\x41\x8a\x34\x3f\x19\xc1\xfc\x4d\x13\xc3\x9c\x5d\xd5\x6c\xfd\x5b\x65\x20\xf3\xfa\x54\xf4\x80\x8d\xed\xef\xa4\x4d\x76\x0e\xd9\xc1\xd8\xf2\x15\xb1\x13\x45\x53\xac\xff\xd2\xe1\x7a\x70\x05\x54\x0e\x48\x7c\xd9\xcb\x14\xb5\xcf\x0e\xf5\x0b\x4a\x3d\x09\x4e\xad\xd1\x0d\x48\xe2\xa3\xce\x79\x29\xc1\x44\x54\xa6\x5a\xfc\x84\x37\x2f\xeb\xa0\x64\x47\x92\x52\xa2\xf6\x2e\x87\x18\xac\x15\xd4\x19\x64\x8a\x6e\xd5\xca\x0a\x05\x8f\xe6\x23\x44\xef\xc8\x5c\xce\x8f\xd5\x59\x0c\x45\x11\x7f\x11\x44\x01\xaa\x28\x08\xa1\x8b\x9c\xde\x9a\x64\xe2\x2d\x73\x83\xbf\xdd\x46\xd8\xa2\xa8\xd9\xc1\x53\x1f\xad\x2f\x6c\x20\x22\x08\xde\x05\xd3\xbd\x5a\x44\x48\x44\xc8\x7f\x27\x5f\xdb\x9c\xb5\x02\xd7\xab\xfc\xf1\x95\xee\xe3\xe2\xa7\x4c\xff\xb6\x3d\x99\xbc\x7e\x21\x48\x66\x62\x7b\xca\x99\x3f\xaa\x7a\x7c\x32\xda\x84\x84\xf7\xa5\x1a\x04\xb8\x7b\x2b\xc7\x50\xc0\xca\x01\xc8\xe7\xd1\x8d\x31\xa8\xd8\xc9\x18\x0e\x6e\x5a\xbc\xb5\x08\xe6\x8d\x1b\x16\xe8\x0c\x17\x9f\x8b\xa0\x2d\x6d\xb1\x48\x2e\x68\xaf\x8a\xc2\xe5\xc0\x00\x0e\xcb\xa0\x72\x94\x61\xd3\x1d\x46\xf6\x70\x90\x5b\x24\x06\x3c\x8f\x47\x99\xb7\x55\xb5\x94\x5f\x41\xbc\xa2\x1c\x8b\x31\x60\x16\xc3\x2e\xb0\x24\x17\xc9\xbd\x7e\x27\x73\x88\xf6\x09\x16\x88\xbe\x2e\xdc\xa5\x5e\xfc\xb3\x58\x60\x33\xf3\x13\x6e\x02\x63\x54\x50\x85\x9e\x00\x29\xc6\xa4\x14\x6b\x4c\x74\xda\x4f\x4d\xfb\x74\x55\x5f\xf6\xe2\x35\xe1\x16\x0a\x2d\xbd\x1d\xc4\xa1\xbf\x22\xbf\x40\x63\xbf\xf7\xb2\xa3\x73\xf7\x02\x2c\xa8\x48\x1b\x98\x82\xef\xc1\x8e\x97\xcc\xda\xe0\x8e\x67\x0e\xd4\x3d\x1a\x98\x93\x03\xbb\xc3\x98\x6b\x42\x6a\xd8\x56\xdd\x4f\xfa\x90\xb8\x4d\xe5\x2a\xe2\x6b\xf4\x83\x27\x61\xf0\x5d\xc4\x98\xb7\x4a\xe0\x59\x7e\x8f\x56\xf8\xcf\xb3\x2c\xa4\x24\x9e\x3c\x47\xd4\x7c\x18\xa4\x95\x78\xea\x0f\xf8\x08\xf7\x58\xcc\x7e\x4a\x99\xc1\x09\xac\x7c\xb3\xa7\x8b\xaf\x32\xa5\x89\x04\x31\x06\xbb\xd9\xe3\xae\x5a\x99\x2c\x27\x1a\x44\x1a\x3a\x08\xa1\x14\x58\x63\xf8\x93\x8d\xf2\xfa\xbe\xc8\x54\x1d\x10\xf1\x10\x26\xf6\x6d\x60\x3c\xf4\x34\x71\x19\x37\xd1\x33\xe9\x06\xe6\xd3\x2c\x0f\x93\xe8\x90\x51\xf6\x28\xdc\x67\xd7\x4e\xeb\xcf\x05\x1c\x52\xfe\x1f\x7a\x92\x0c\x24\x1f\x59\x6f\xcb\xee\xc1\x5a\x28\xd0\x12\x52\x82\x52\x99\x28\x1e\x26\x71\x3e\xd2\xe7\x3d\x3a\x4b\x69\x8e\x6d\xc4\xa3\xbc\x76\x63\xf2\xd3\xb8\x31\x1e\xef\x26\x32\xbf\x63\x15\x4f\xee\xe2\x91\x77\xa0\xf9\x63\xd8\x46\x1b\x9d\x40\x54\x6d\xe9\x17\xdd\x67\xcb\x76\x9e\xdf\xd5\x30\x41\x3b\x46\xe6\xd4\x14\xb9\xed\xc3\x48\xcd\x17\x5f\x7c\x40\xb4\xa3\x5e\xa2\xff\x0a\x6e\xa2\x61\xca\x76\x33\x0c\x54\xed\x54\x84\x09\x69\x43\x30\xf4\xbd\x52\x1f\x85\x49\xdf\x4f\x43\x44\x0f\xe5\x6d\x7c\x19\xc4\xdd\x41\x6c\x1e\xe9\x83\x70\xe7\x64\x7f\x63\x8d\x88\x96\xab\x7f\x0a\xa4\x58\xee\xba\x8d\xb2\xd0\xb6\x5f\x40\x8e\xe6\x6a\xc0\x82\x0e\x81\x0b\x40\x07\x48\x33\x2f\x78\x57\x01\x18\x66\x7b\xbd\x75\x95\xdb\x95\x20\x00\x5d\x25\xe1\x9c\x90\x2e\x81\x91\xb9\x49\xfc\xc7\xa3\xf2\x29\x6a\x53\x3c\xf2\x1f\x2b\x5f\xca\x85\x5b\x3f\xf0\x9a\x86\xdf\x70\x50\xfe\x43\xb5\xe3\x96\x1a\x2f\xf0\x6b\x4b\xc0\x78\x69\x0b\x26\x3a\x2b\xcc\x15\x03\x19\xb5\xda\x0e\x3a\xb7\xc7\x53\x4d\xf8\x57\x24\xe4\x9a\x44\xf7\x60\x7c\x83\x2f\xfd\x4e\x9d\x8e\xae\x5c\x8c\xbc\xbc\x48\xfa\x0b\x06\x17\x02\x1b\x09\x89\x97\x82\x2e\xd2\x91\x3a\x7e\x2a\x05\x46\xf4\xed\x18\xe1\x55\x09\x11\x25\x1a\xf1\x77\x21\x80\x84\xdb\xed\x72\x6a\x68\x33\x68\x26\xa3\x41\xa1\xb7\xab\x9a\x57\x1f\xa2\xcb\x37\x13\x16\x75\xf0\xe4\xda\xce\x71\x7e\xba\xe3\x86\x42\xea\x4a\xa1\x91\xf5\x71\x77\x85\x3d\xd4\x28\x2b\xbd\xc4\x74\xce\x86\x8e\x22\xe9\x3c\xc9\x71\xa5\x79\x2b\x7a\xae\x9d\xb2\x03\xbc\x18\x5e\xed\xf7\x38\x55\x0b\x89\x52\x5b\xed\x34\x51\x19\xe1\x5e\xb9\x18\x59\x6c\x71\x65\x06\x07\xbd\xfc\xf6\xd2\x6b\x3e\x1c\x8e\xf9\x9f\x7c\x96\x16\x57\x82\xb9\x53\xb1\x6a\xb6\xd0\x91\xf1\x76\xd2\xb5\x83\xfd\x47\x59\x93\x09\xee\x9c\xd3\xd4\xe5\xa1\x4a\x30\x1f\x61\x8d\x92\xfe\xfa\x8a\x2b\xbd\x2f\x6b\xc0\x0d\x28\x37\x06\xd1\x0c\x84\x61\x8a\x65\x98\xe5\x1b\x73\xdb\xb9\xf1\xf7\x25\x31\xe6\x19\x9f\xae\x99\xaa\xc6\xa8\x0c\x53\xf0\x8a\x3c\xe6\x13\xfa\xc9\x02\xae\xb2\xef\x5a\x3d\x88\x56\x80\xdc\x9a\x07\x13\xb0\xb0\x9f\xd2\x45\x9c\xde\xa2\x36\x24\xa5\x01\x90\x7c\x65\xe6\xd5\x5e\xab\xc8\x04\xae\x4c\x1a\x94\x7b\x59\x76\x19\xbc\x5d\xe5\x6b\x23\x42\x56\xdf\x76\xca\x87\x82\x7f\x1e\x7f\x37\x32\xae\x2e\x07\x15\xed\x24\xd2\x44\x12\x33\x46\xc3\x80\xc8\xef\x80\x96\xee\x12\xeb\xc2\x69\x81\xb1\xfd\x41\xff\x6a\x05\x24\x56\xf1\x85\xb3\x29\xf8\x4f\x7d\xd2\xd3\xdf\x0d\xa1\x28\x41\xf1\x65\x69\xc2\x0f\x1f\xb9\x13\xe5\xdf\xeb\xe5\x1c\x5d\x2e\x48\x07\x70\x5a\x3e\xfb\x1e\x87\xf0\x36\xcc\x79\x77\x46\xf7\xfe\x34\x71\x0b\x36\x23\x50\x3f\xf2\xe0\xb8\x92\xb8\x60\x04\xa2\x91\x14\x52\xac\xd3\xf2\xe4\x80\x2e\xb9\x69\xc3\x48\xc5\xa8\xf3\x6b\x34\x0d\xbe\xd4\x72\x46\xa6\x94\xe1\xc3\x82\x6c\xd7\x6f\x78\x46\x57\xed\x24\x2d\xe5\xa6\x04\x8b\x5d\x05\x59\xad\xa3\x4a\x79\x07\xaa\xa9\x86\x22\x2d\xfa\x62\x2e\x85\xdd\xb9\x84\xec\xea\x5c\xa0\x9a\x8a\x6e\x3f\x2b\xbc\x97\x7c\x70\xf9\xb3\x1c\xa7\xe2\xe8\xbe\xbc\x9f\xc1\x00\xdb\x1d\x92\x14\x32\x0e\x95\x72\xbf\x63\x1b\x96\x7a\x47\x2e\x97\xa3\x0a\xc3\x52\x35\x64\xbd\x3b\x07\x7b\xfa\xee\x7c\x3c\x92\xe3\x2f\xa2\xc0\xae\x91\x73\xc8\x5d\x1e\x47\x71\xd0\xca\x9e\x42\xfd\x1c\x94\x84\x55\x4a\x82\x9e\x07\xfd\x75\x51\xff\x41\x4f\xa8\x8a\xaf\x1a\xb5\xfc\xfb\x3a\xae\xe6\xbf\x40\xc3\xd0\xd9\xd2\xdf\x3a\x3f\xa6\x7d\x2c\x5c\xc9\xc2\xdc\xc5\x15\x41\x19\x4d\xff\x84\x2f\x80\x87\xa6\x2a\x35\x79\x65\x25\x88\xa8\xba\xe2\x33\x37\xa3\x4e\xe6\xdd\x39\x20\xd0\xa0\x64\xe7\xac\x81\x93\xd6\xff\xef\xfc\xd2\xa3\xac\xce\xe9\xde\xa3\x42\xe6\x38\x3a\x95\x65\x69\x6f\x03\xe6\x22\x51\x0f\xf1\xcf\x81\x8e\xc1\x89\xdb\xf8\xd8\xb8\x54\xc1\xac\x48\x99\xc2\xbc\x22\x20\x95\x16\xe4\xbb\x9a\xcb\x3c\x74\x34\x2c\x9c\x2d\x2d\x68\x59\xf2\x1b\xdd\x55\xbe\xde\x04\x1c\xd5\x56\x44\x3b\xf7\xf9\x8f\xe4\xc5\x7f\x37\x78\x8c\x5d\x96\xca\xc1\x43\x39\xc8\xe6\xa2\xe5\xf7\xe0\x4f\x4d\xfc\xcb\x6f\xe4\x51\x76\xc8\xab\xaa\xc6\xb4\x3d\x11\x74\xa3\xb1\x7a\x19\x3b\x14\xb0\x29\x40\xac\x74\x19\x5f\x7e\x59\xc9\x24\x1d\xab\x84\x71\xe5\x57\x56\xd2\xf8\xd6\xdb\x70\x9b\x91\x8f\xdc\x47\x43\xc4\xcf\xf1\xf3\x26\x27\x76\xef\xe0\xcf\x87\x1d\xef\x66\x44\x67\x33\x0b\xed\x94\xe3\xd1\x96\x8f\xb0\x7f\xf9\x3c\x7f\x4a\x4d\x26\xda\x9a\xd3\x97\xe1\xf1\x8d\xb2\xce\x60\xd8\x75\x19\x61\x37\xa2\x77\xa4\x3f\x7d\x87\x6f\x5f\x16\x34\x2a\x12\xe7\x64\xb7\x9a\x49\x21\xdd\xaa\x17\x7f\xf2\x68\xc8\xec\x21\x67\xad\x8b\x45\x17\xf5\xa3\x0e\x9e\xc1\x70\x44\x0e\x8a\x19\x74\xcd\x39\x4e\x1e\x01\x2b\xe4\xa8\x72\x61\xe3\x28\x28\xb0\x1b\x8b\xee\x7d\xf1\xdb\x08\x9f\x73\xb4\xa6\x49\x02\x29\x95\x26\x2d\x69\xb6\xfc\xd6\x59\x85\xf2\xf1\x26\x19\x8d\xea\xb7\xcd\x3e\x0d\x2b\xfc\x35\xbf\xf2\x60\x53\x35\x15\x2f\xe5\x89\x46\x8a\x1e\x58\x83\x93\xba\x56\x67\xc2\x15\xa0\x84\x98\x75\xa8\xfd\x84\xb9\x31\x5c\x3e\x38\x22\x6b\xaf\x69\x67\xed\x9f\x9c\xfe\xd6\x8a\xf4\xaf\x0c\x6b\xbc\xa9\x92\x74\x58\x3d\xdc\xce\x76\x87\xac\x84\x1e\xa0\x8c\xd2\xbf\x28\x33\x05\xad\x89\xf5\x57\x36\x7e\xe1\x00\xab\x72\x53\xbf\x62\x76\xec\x2e\xe4\x93\xd4\x2f\xa0\x4c\x74\xe2\xca\xfd\x4e\x28\xae\x81\x48\x52\x5f\xfb\x92\xd5\x8c\xe2\x90\xff\x71\xb4\x44\xce\xc5\x4d\x46\x97\xfc\x2c\x0b\xca\x47\x3e\xb2\x17\x32\xd7\x0f\x53\x8d\xdf\x5f\xd2\x89\x4e\x88\x2b\xb2\xd8\x72\x97\xc1\x85\xc6\xa9\xab\x34\x9f\x4b\xf0\xd4\xe7\x6b\xab\x35\xc7\x96\x80\x85\xaa\x40\x9b\x19\x16\x31\xab\xc8\xa7\x40\xef\xca\x94\x76\xaa\x7c\x9d\xed\xc1\x39\xbb\x80\x04\x50\x70\x0a\xb5\xeb\x7b\xd7\x9f\xe9\x77\x9c\x6d\xa3\x5e\xce\x9b\xde\xf1\xf8\xf0\xaf\xae\xe6\x98\x60\x7a\xf1\xbd\xd1\x3b\x71\xbc\xa9\x94\x74\x01\xaa\x30\x9b\x29\xbf\x51\x2a\xb2\xfe\x83\x01\xc5\xac\xe0\x12\xa4\xd8\x08\xa3\x7b\x29\x39\x6f\x54\xb5\x5b\x36\x63\x60\xcd\xd5\xd2\xb1\x5a\xa1\x97\x22\x83\x95\x62\xd4\xa1\xe5\xd6\x5c\xe6\xa9\xaf\x19\xb7\xb0\x27\xc6\x87\x20\xca\x17\xce\xea\x61\x54\x26\xe7\x74\xdd\xf5\x65\x58\xf9\x04\x09\x93\x83\xa4\x45\xe5\x59\x96\x29\x2a\x72\xf2\x16\x8e\x10\x3f\xb0\x34\xa8\xa0\x60\x60\x82\xb3\xb3\xb7\xc6\x8d\x86\xfe\xb5\x8d\x0a\x8b\xf5\x26\xa0\xbe\x2f\x6f\x61\xe5\xef\x6f\x75\x24\xcc\xb0\x7a\x18\xfe\xe7\xa8\x0d\x60\x50\x56\x0e\x84\x08\x43\x89\x03\x38\x83\x65\x1f\x7e\x7d\x62\x79\x19\x1b\x7f\xfd\x7e\x90\x3d\x6a\x76\x7c\xc0\xcd\xf5\x46\xc6\xdf\x93\x37\x50\x84\x1e\xc1\x02\x2c\xbb\xfe\x80\xbc\x87\x2f\x8b\x5e\x8d\x99\xc5\x58\xef\xc8\xb3\x8b\xc2\x71\x75\x71\x68\xd9\xf1\x00\x59\x73\x8d\xe6\x4f\x72\x7d\xa0\xc1\x8d\xaa\xbb\x49\x5c\x9a\x3b\xed\x5f\x54\x74\x9d\x9e\x67\xee\xdb\x49\xf5\x57\xa9\xf1\x9a\xa8\xb7\xee\x5b\x7f\x76\xda\x7f\xde\x69\xe6\xa6\x99\x9b\x05\xdf\xfe\x70\x0f\xba\x2c\x50\xde\x75\xdd\xc7\x70\x63\xbb\xf7\xb3\xd4\x39\xc0\xe9\xf8\x4a\x97\xa4\x06\xa3\x90\xd2\x94\x0a\x31\xeb\x76\xd4\x85\x20\xf5\x8c\x4d\xaa\xee\xb4\x4a\x74\x6d\x68\x17\x4d\xdd\x3f\x5a\x50\x48\x23\xf8\x18\xb6\x95\xb0\x89\x88\x60\x41\x19\xa5\x80\xc4\x9e\x74\xd0\xef\xcd\x23\x6c\x46\x98\x04\x91\xa6\xb8\x4b\xed\x2a\x4b\x11\xb1\xd7\x72\xdb\xa0\x47\x7a\x88\xcb\x42\x83\x07\x14\xdd\x84\x02\x5d\x68\xa2\x79\x8c\x0b\x6c\xcc\x49\x9d\xfb\x2f\x66\xa8\x82\x93\xde\x9c\x7c\x52\x17\x16\x77\xa5\x72\xb8\x5f\x16\x93\x9c\xec\x54\x6f\x46\x86\x02\x81\x43\x90\x5b\x6e\x36\xe0\x74\x1d\xb9\x56\x07\x24\x98\xce\x27\xc7\x01\xa2\x7f\xa9\xd2\x12\x29\x18\x9e\x7f\x83\x9d\x18\x10\x1f\x20\xc9\xab\x25\x20\x36\xa2\xc5\x0f\x5d\x4f\xd5\x14\x47\xcd\x89\xb6\x8b\x5e\xa0\x94\x16\x61\xc8\x29\x16\x54\x87\x2f\x9d\x58\xde\x29\xfb\x40\x10\xdb\x65\xc0\x09\x0b\x7a\xc1\x99\x48\x5b\x58\x3d\x02\xd9\x45\x65\xe0\xb9\x1d\x51\xc3\x29\xaf\x27\xd4\xf0\x8e\x8e\x12\x6b\xb1\xd6\x8f\x08\x92\x6a\x2f\x42\x23\xb5\xa3\xef\x3c\xa7\xb0\xe4\x1c\xab\x0c\x94\xd9\x82\xbc\x4a\xf7\x38\xea\xfa\x2b\x9e\xb0\xcd\xdf\xde\x9d\xe5\x6b\x0d\x2b\x22\xf4\x01\x96\xce\x90\xdf\x17\xe8\x6f\xff\x7b\xb1\x2f\x31\x39\xf3\x76\x12\x89\xd4\xc5\x6d\xef\x3e\x3d\x44\x43\x21\x1f\x1a\x2f\x9f\xad\xf6\x41\x95\xb1\x6d\x83\xdc\x53\xa2\x59\x50\xd8\x7b\x66\x73\x1e\xcb\xa7\x02\xe1\xe5\xc6\x22\xd5\xd6\x9c\x2d\xce\xb1\x2b\xf4\xa1\xbc\xa8\xb3\xd6\x9b\x0d\xff\x1a\xa1\x36\x78\xe6\x6e\xc9\x65\x67\xd7\xb3\x65\xa3\x12\x93\x83\x84\x68\x6f\xb9\xfd\x4c\xe1\x1b\xdf\x8c\xd2\xc1\x37\xea\x39\x34\xb2\xed\x6b\x30\xc7\x23\xe0\xc7\x32\x1f\x86\x34\x0b\xff\x4b\x16\x1a\xf5\x76\xa9\xa3\x11\x67\x1d\x6c\x66\x81\x20\x1b\x71\xad\xfe\x14\xf0\xe3\x8c\x9f\x02\xa4\x99\x5d\x57\x04\x9c\x14\x3e\xc7\x63\x16\x3e\xe8\xb3\x95\x31\x8d\x7e\x9a\xd5\xfb\xc2\x01\xcb\x16\xec\xf6\xed\xdb\x69\x85\x0e\xa4\x65\xf0\xc9\x67\x61\x5a\x3d\xd6\xc9\x70\x79\xf4\xfa\x3e\x59\xa6\xd6\x8e\x7b\xc2\x02\xa6\x7f\x7f\xe0\x09\xa4\x97\x67\x8a\xa2\xf5\x46\x5d\x5e\x6b\x31\xca\xef\x58\x90\x62\x58\x07\xa0\xa3\xc0\x66\x5f\x4a\x49\x90\xe4\xfb\x9a\x8d\xd1\x37\x25\xfc\x81\xc1\x18\xa2\x7f\x69\x5f\x6e\x12\x12\x99\x2e\x69\xb3\x47\x82\x86\x7e\x6e\xf5\xeb\x78\x83\x23\x3e\xc7\x40\x36\x2a\xef\xf4\xeb\x32\xb3\xa9\x8b\x2e\x6d\x01\x38\x55\xf1\x1a\x30\x28\xce\xaa\xb4\xfa\x0d\x96\x0b\x9e\xbb\xc0\x52\x96\x66\x97\xa7\x63\xe7\x40\x69\xbb\x6a\x94\xa2\x54\xae\xcd\x52\x1e\x55\xb7\x10\x06\xeb\x6b\xb0\xb7\xe1\x05\x8b\x22\xf5\xae\x9a\xb4\x1a\x66\x23\x07\x09\xf3\x68\x64\x94\x92\x6c\x39\x44\x34\x34\xd6\x2e\x3b\x15\xb4\xec\x7c\x82\x76\xe9\x98\xdc\xa3\x76\x3f\xb0\x24\xdf\x2a\x13\x53\x23\x9f\xa5\x48\x44\x98\xc2\x84\xa0\x9c\x82\x29\x52\x1a\x55\xd5\xb2\x36\x45\x55\x2b\x5a\x0b\x86\xe5\x6c\x71\x2c\x01\xd0\xca\x52\x4a\x65\xb1\x14\x71\xb5\x66\xde\xce\x8a\x57\x2a\x2b\xa6\xab\x58\x85\x83\xb2\x16\x37\x5e\x49\x52\xb4\x2a\x57\x86\x0a\x70\x5f\x74\xc8\xe7\xd7\x75\xe7\xea\xc4\x6a\xa5\xac\x62\x92\xdc\x9c\x2f\x19\x76\xc5\xa8\x43\x45\xc7\x0c\x8b\xff\xf7\x55\x42\x6a\x6b\x85\x40\x48\xde\x98\xb1\x54\xea\xcf\xea\x22\xb9\x1f\x1f\xa3\xfe\xca\x72\x0a\x62\x66\x28\x98\x8e\xf1\x12\x47\xd5\x0c\x13\x56\xa1\x99\x97\xb2\x1c\x9b\xf8\x4a\xa4\xe4\xb9\xb4\x34\x31\xf3\x2a\x46\xc1\xe8\x74\xd5\xd9\x22\x6a\x49\x7f\x01\x13\x5d\x40\xa5\x89\xfb\xa8\x40\x5d\x89\xaa\xc9\x50\xea\x93\x9a\xc7\x3d\xd3\xfe\x49\xc3\x70\xb3\x66\x99\x2a\x44\xf1\xb1\xc9\x66\x01\x98\x64\x50\x26\x73\x6f\x7c\xcf\xe8\x1f\x62\xeb\x1f\x1e\xf0\x26\x85\x6a\x62\x87\xd9\xbf\x4d\x4e\xfb\xae\x1a\xd0\x33\xf9\xb2\xd2\x52\x5b\xca\x77\x84\x48\x42\x36\xc8\x51\x3a\x3e\x7c\x4f\x29\x7c\x63\xf7\xf4\x60\x54\x4d\x59\xde\x10\x7d\xfe\xb1\x82\xca\xc0\xdd\xa6\xf9\xb2\xda\x99\x62\x8c\x7e\x6e\x23\xe9\x2f\x63\x34\xf9\x80\x72\x7a\xb4\xb5\x92\x04\x97\xd1\x7c\xcc\xb2\xce\x4d\x53\xd8\x9a\x46\x97\x08\xe1\x51\xbb\x74\x4d\xb0\x31\x75\xcb\x6e\xeb\xef\xa7\x04\x9b\x2e\x1f\x3d\xac\x0b\x20\x8a\xc7\x29\xfe\x0d\x50\xe0\x93\xc1\x49\x68\x2d\x38\x71\x96\x33\xfd\x4f\x94\xf5\xff\x9d\x32\x63\x5c\x1c\x65\xf7\x3f\x40\xe0\x4a\xf4\x3e\xbd\x81\x5b\xad\xbc\x11\x40\x69\xbe\x16\x66\xd4\x73\xda\x2b\x20\x69\xcb\xd2\x8c\xfc\x5b\x8d\x1c\xd3\x0b\xfe\xc9\xcc\x7b\xbc\xf1\x42\xfc\xc1\x18\x19\x9c\x5d\x80\x06\xdf\xe1\x9d\xa6\x27\x04\xeb\x72\xe9\x2d\x1c\x1b\x07\xb9\x75\xae\x8f\xcf\x0e\x55\x43\x08\xb6\xf4\x57\xac\x3c\x6e\x95\xac\xcc\xb8\xd9\x22\x97\xf3\xc3\x05\x53\xb5\xe2\x51\x1d\x43\xe0\xbe\x60\xfe\x24\xba\x98\x5d\x94\x9f\x7c\x35\x54\x8e\x29\xa0\xec\xfc\x0a\xdc\x0b\xa1\x38\xdb\x14\xe3\x64\x32\x76\xd9\x4c\x70\xb2\xcd\xb6\x5a\x95\xde\xcb\xf5\xdf\x29\x94\x6b\xe9\xe1\x0a\xc5\x7f\x6d\xc1\x0e\xbe\xc9\x92\x77\x23\x7c\x99\xdb\xe9\x52\x28\xc6\x95\xb8\x24\x9b\x10\xcd\xce\x18\x97\xd8\x4b\x71\xf3\x3c\x6c\xc6\x88\xc2\x52\xcd\x60\x93\x05\xff\x79\x9c\x9e\xb0\x0e\xd1\x1f\xca\xef\x65\x35\x59\x7f\x6c\x5f\xa4\xa9\xb9\xf7\x42\x0d\x43\x05\x15\x7e\x9f\xe4\x0a\x51\x95\x29\xd4\x08\xc7\xea\x0c\xa5\x99\x04\x6f\xdd\x3f\x9c\xac\xd9\xce\x45\x1a\x14\x38\x94\xc9\x06\xa9\x6c\x35\x16\x74\x36\x0d\x25\x22\xd3\x2e\x9b\xc1\x79\x54\x52\xa7\x73\x14\xda\xec\x04\xd2\x52\x10\xea\x1f\x9e\x70\xb6\x4f\x61\xc9\x52\x76\x1e\x7e\x4a\x99\xa3\x9b\x93\x17\xc1\xb3\x9c\x3a\x42\x89\x9e\xe8\x0a\xf2\x6c\x79\xe6\xcc\xa9\x52\x41\xeb\x18\xa8\x5d\x82\x50\xf5\x8f\x93\xd4\xc7\xf0\x42\xd5\x0c\xf2\x53\x26\xf6\xab\xdd\xf6\x23\x5d\xbd\x1c\xef\x82\xe6\xf9\x9c\x62\xf4\x48\x5f\xa1\x59\x0c\x14\x6d\xed\xb1\x70\x9f\xaa\xb9\xa9\xa4\xfd\x26\xca\xd9\x05\xd5\xcf\x6f\x2d\x17\x1b\x97\xe6\xaa\xfa\x78\x6e\xe9\xc7\xa6\x49\x18\x1a\x23\xae\x32\x25\x6d\x83\x44\x4c\x6c\x69\x1c\xfc\xd3\xde\xf1\xf1\x59\x69\x83\x21\xfe\xe7\x69\x44\x99\xf5\xa2\x71\x47\x53\x56\xaf\xd8\x75\x2d\x67\xcc\x8c\x13\xd1\xef\x91\x9f\xbd\xee\x52\xf7\xe6\x81\xa6\xcd\x23\xb8\xf4\x17\x3c\xa9\x52\x33\x75\x0f\xfa\x6c\xe2\x20\xed\x76\xf4\x78\xd8\x28\x10\xe4\x51\x6f\x58\x6e\x02\x26\xdb\xd3\x7f\x40\x86\x0a\x76\xb5\xa5\x1e\x43\x64\x87\xd4\x67\x3d\x1a\x78\xd2\x92\xa5\x3f\x25\xb2\x71\x2c\xa8\x65\xd0\x1f\x96\x3f\x07\x37\xd8\xa5\x1c\x09\xda\xd8\x82\x3a\x86\xdd\x05\xde\x29\x9c\x9e\xe2\x0c\xe7\x32\xe4\xe3\xdd\xab\x2e\xcd\xda\x3a\x43\x98\xae\xd2\xb2\xff\xbd\x02\x87\xf0\xa3\x1d\xa6\xbc\xde\xd1\x44\xe0\x75\xc5\xc7\x45\x82\x43\xb9\x8a\x59\x0b\x62\x8f\xe5\xba\xf1\xa2\x81\x22\xbd\xfd\xac\x05\x19\x2d\x5a\x4d\x2d\x05\x9d\xf4\x46\x12\x69\x64\xe4\xf7\x8b\xc2\x60\x02\x57\xb4\xda\xb4\x94\x1b\x61\x4c\x66\x67\x05\x31\x45\x33\xbb\xc7\x37\xc2\x89\x0a\x26\xb9\xd1\xae\xd5\xfd\x88\x4e\x06\x47\xe0\xe2\xf3\x16\x7e\x2b\x1f\x0d\xc4\xd1\x56\x96\xea\x3f\x0f\xef\x7a\x54\x56\x8c\x22\x62\xc8\x04\xd3\x23\xd1\xc5\xfe\xab\x91\xc2\xd5\x8d\xbf\xf1\xbc\xd0\xad\x45\x61\xc8\x09\xcf\x7f\x01\x84\x1a\x06\x0d\x8c\x51\xe7\x70\x90\xc2\xb9\xa3\x97\x81\x5e\xa4\x3f\x52\xfb\x98\x6b\x46\x43\x1f\xe1\x09\x1d\x88\x33\xaf\x18\xcf\xb2\x03\x75\xaa\xc3\x74\xc5\xbd\x97\x1a\xb2\xa6\xb9\x76\x97\x6f\x09\x79\xa6\xa7\xc8\xaa\xf1\xc6\xd3\xa7\xfe\x7c\x65\xcc\xfe\x06\x87\xfb\x83\x84\x45\x8e\x41\x28\xe1\x60\xbe\xc8\xb7\xff\x00\xe3\x4e\xd9\x64\xd4\x2a\xec\x95\xd1\x6c\x8c\xc7\x48\x38\x28\xc5\xe7\x5f\x24\xa5\xa1\x0c\xbd\xa9\xf2\x6c\xc7\x29\xaa\xc8\x32\x5f\xbb\x32\x34\xe3\xb4\xb2\x4c\x91\x33\x2e\xbf\x09\x32\x4e\xaf\xca\x8f\xd3\x8d\x46\x94\x4b\xa4\xe3\x2b\xd3\x3e\x58\xa3\x90\xec\x57\x24\x45\x87\x55\x8c\xf7\x48\x49\xa7\x59\x3b\x9d\x55\x63\xd3\x4e\x61\x97\x50\x46\x51\x4e\xce\x86\x49\xed\xb9\x42\x96\xa0\xdd\x26\xb0\x70\x3b\x04\xab\x2c\x92\xff\x3b\x43\x64\x87\xe8\x0b\xb1\xdc\x60\xe3\xa6\x3b\xb1\x37\x8a\x2f\x2a\xb2\x03\x5b\x06\x5d\x9b\xc3\x8a\x3e\xb4\x5d\xdc\xb6\x70\xf3\x03\x4e\xba\x33\xbc\xb2\x4d\xa6\x50\x82\x96\xba\xeb\x43\xa0\x12\x9b\x90\x77\x7a\xab\xc5\x6a\xc0\xab\xb0\x6a\x52\xe5\x8d\xab\x0f\xfd\x21\x1f\x34\x59\x7b\x18\x00\xae\x56\x5f\x20\xe0\x2d\x9d\x48\xec\x10\xce\x5a\x4e\x83\x7b\xda\x9d\x4e\x51\xf3\x25\xcb\xf0\xdf\xc1\x8b\x0a\xa8\xaa\xb9\xab\x27\xce\x49\x45\xd9\x96\x4d\x67\x37\x56\x3d\x9f\xff\x9e\x4c\x56\x6b\x46\x4d\xa8\x1c\x4a\x52\x38\x1a\xe1\x05\x80\x60\x66\x66\x35\xba\x50\x14\x1c\x5b\xd9\xa1\xed\x8b\x02\xd5\x70\x43\x7a\xa9\x5f\x0d\xaf\x8b\x66\xd4\xb5\xc0\x42\xd2\x32\xb1\xb4\x79\xe3\x99\xca\x46\x41\x02\x3e\xd7\xc2\xe5\xb7\x3e\xfa\x1a\x1e\xc0\xe2\x56\x33\x17\x0a\x8b\xf2\xd3\x39\xd6\x5f\xac\x49\xb4\x70\xf7\xde\xbd\xef\x54\xb6\x3b\x9f\x58\x78\x10\x05\xa8\xfd\x54\x9a\xd6\x47\x6a\xfa\xfa\x07\x88\xc0\xc3\xe3\x62\xaa\xe6\x1a\x53\x3f\x3e\x4f\xa5\x63\x74\x2f\xcc\x0c\x9f\x6b\xb8\xc7\xf0\xf2\xc6\x38\xa7\xb0\x89\x67\xa0\xef\xe5\x94\x11\xec\xaf\x3f\xc8\x3f\xcd\xae\x2d\x5b\x17\x56\xb0\x98\xce\x35\x1d\xbe\xe1\x39\x29\x69\xe0\xf1\xb0\x2f\x36\xf5\x80\x86\x66\xcb\x57\x2b\xdb\xf2\xf7\x65\x69\xf9\x06\x9e\x25\x3c\x36\x6c\x57\xdf\xa5\x90\xd2\x45\xaa\xa9\x58\xdf\x0d\xc3\x2d\x8c\xc3\x52\xba\xfa\x4f\xd5\xef\xa0\xb5\xe7\x45\xfa\x0f\x4b\xd4\x5d\xa7\x1d\xd2\x86\x66\x17\xa9\x63\xb9\x4a\x0c\xbc\xfe\x87\x28\x04\xcd\xe0\x32\x5e\x84\xd9\x20\x39\xb8\x93\x83\x99\x25\xc4\x09\xe7\xd2\x6c\xa3\xd5\x1e\x65\xd9\xea\xff\x8c\x35\xbe\xe6\xf2\x16\xf6\x48\x05\x8e\x3c\xde\x03\xa1\x24\xeb\xc3\x49\x76\x5b\xd5\xad\x61\xa6\xee\xa3\xbc\xed\x2a\xe5\x96\x04\x5c\xdf\xef\x9a\x36\x5e\x3f\xc0\x04\x67\xe6\x1e\x65\x5b\x69\x1f\xae\xe3\xa1\x76\xf2\x21\xfe\x43\x29\x96\x89\x78\xec\x67\x18\xe4\x39\x28\x38\xf8\xb3\x6d\xcb\x8b\x45\x07\xcd\x15\x3b\x45\x35\xaa\x6a\xcb\x72\x1a\xbf\xc5\x70\x29\xe3\xe1\x2b\xd5\xe2\x0c\x95\x32\xed\xab\x5c\x88\x2a\xd2\x0e\xbe\xae\xac\xf1\xd6\xc0\xd0\x11\x8d\x59\xad\x3a\xfa\xf0\xc3\xab\x29\x4c\x70\xe8\x18\xeb\x48\xe5\x20\x74\x1a\x9b\xef\x83\x7b\xea\x26\x02\xed\xd4\xcf\x8b\xeb\xd2\x7b\xec\x00\x1c\xa5\xb1\xdb\xcf\x43\x61\x7c\xcb\xb8\xae\xae\x52\xf5\xd9\x59\xa2\xfa\xc3\xc2\xba\x9f\xb7\x65\x5e\x36\x81\x67\x87\x4d\x98\x95\x84\xf2\xff\x00\xdd\x48\x4d\xf2\x7d\xac\xd1\x29\x28\x59\x34\x00\x98\x1f\xb6\x1e\x11\x47\x0d\xf8\xb4\x7f\xc0\x4b\x27\xec\x8b\xcb\x12\x67\x15\x62\xd9\x41\xd6\xd5\x61\xef\xcb\xf6\xdb\xdf\x5a\x1b\xfe\x5b\x20\xd5\xc2\x31\xd8\x2e\x7f\x28\x0a\x67\x7d\x51\x65\x56\x34\x62\x7a\xd8\xa2\x54\xc3\x60\xca\x5e\x41\xc6\xf8\x4a\xd9\x83\xda\xea\x6a\x56\x4a\x5d\x5d\x2f\x5b\x6e\x18\xee\xff\x7b\x53\x89\xbb\x4b\x47\x5e\x76\x76\xae\x2d\x80\x9d\x2a\xd2\xe2\x26\x06\x2d\x53\x92\xa2\xca\x3d\xf2\x97\x6d\x48\x3c\xb7\xec\x0b\x52\xd4\xdd\x40\x58\xe5\xb0\x1d\x72\xc3\xde\x63\x25\x24\x19\xc4\xec\x45\xd5\xfa\x76\x85\x81\x8b\x60\x17\xab\x12\x50\xd7\xa1\x42\xb1\xb1\xb0\x56\x40\x75\x2c\x2f\x6d\xb0\x5e\x69\x1e\x7c\xb3\x65\x41\x49\x53\x18\xa2\x90\x31\x99\xaa\x07\x61\x2b\x6c\x19\x6e\x31\xe4\xbb\x82\x94\x6b\x95\xdf\x9e\xec\x45\x28\x80\x0b\x2f\xfd\x95\xb5\x65\x52\xae\x35\x8b\xb9\xf9\x67\xaa\x2e\x73\x5f\x55\xfa\x02\x43\x3a\xf5\x1a\x60\xfe\x05\x1a\xdb\x9b\xc9\x7a\xfb\x46\x60\x75\xd0\xf6\x9d\x75\x8d\xa7\x73\x9d\x8f\x10\x9d\x40\xf9\xeb\xfa\x95\xb1\xcc\x16\x07\xac\xbd\xce\xe4\x15\xbd\xbe\x87\x06\xc1\xf5\x85\x52\x4f\xb5\xaf\x76\x8f\xa8\x78\xa7\xf8\xec\x04\x4e\x73\x55\x26\x56\x6a\x5f\x39\x3f\x5d\xfc\x36\xbd\x1b\x9f\xcb\x67\x96\xa7\xfb\x12\x7d\x9c\x32\xe8\xb1\xc2\xea\x4e\x32\xbe\x96\xf1\x99\xa7\x84\xef\x70\xa9\xce\x0a\x18\x09\x53\x3c\x2b\xb6\x80\x76\x39\xd2\x46\xcc\xb3\xc5\x56\xda\xff\x4c\xc4\x39\xab\x94\x1d\x27\xfb\x3a\x8f\xbd\xca\x5c\xb8\xe6\xec\xa6\xd3\x96\x12\x26\x2a\xde\x09\xf2\x28\x8f\xbb\x6a\x7e\x34\xc3\x5f\x4e\x95\x08\xf6\xd9\x62\x3d\xcf\xb0\x8f\x77\x91\x04\xef\x93\x6a\x77\x3f\x97\x22\xc8\x90\xda\xfc\xcf\xff\xee\x74\xfe\x9e\xc1\x25\x9e\x62\x37\x55\x06\x69\xb7\x88\xf1\x10\xac\x69\x6e\xc4\x45\x4b\x9b\xca\xea\x31\x3a\xfb\xf9\x5e\xbe\x25\x9e\x45\x53\xef\xd9\x53\xf0\xa7\xee\x4a\xdb\xe2\xc8\x0f\xf0\xa5\x26\x8e\xf6\xbf\x49\x91\x83\xdb\xcb\xd1\x1f\x3c\x6b\xa0\x72\xc4\x2d\x92\x3d\x5c\x90\xbe\x32\xec\x09\x92\xeb\x51\xf4\x75\x4d\x72\x45\xeb\x77\xbe\x29\x18\xba\xf9\xcf\x66\xb5\x94\xba\x17\x60\x39\x54\x51\x23\x0a\xa6\x74\x39\x07\xae\xb2\x85\x37\x7d\xb6\xec\x35\xc2\xeb\x7a\x11\x15\x76\xac\x62\x63\x54\xab\xc3\xf4\x69\x7b\xf5\xea\x1f\x4c\x77\xe4\x00\x09\x2c\x2a\x3e\x4f\xd0\xaa\x3d\x2e\x9b\x05\x49\xb3\x91\x24\xe1\x76\x53\x19\x46\x79\x09\xd1\xb9\x9d\x00\x55\xa4\xda\x62\xa5\x9f\xec\x94\xad\x13\xcb\xc6\x28\xa0\x0d\xdd\x1c\xf3\x11\xf5\xe9\x32\x24\xdd\x37\xdd\x0d\x6c\xb1\xa2\xe1\xed\x50\xb6\xd2\x8f\x7e\x14\x89\x76\x93\xfb\xb5\x43\x4d\x01\x8c\x56\x0b\x39\x1e\xcc\x22\x6b\x0f\x99\xa5\x2d\xef\xce\x11\x30\x02\x8e\x4c\x10\x68\xf3\xa9\x6a\xb7\x5c\x90\x0f\xf5\x26\x08\x8e\xa9\xf6\x2c\x1b\x00\x27\x98\xd9\x41\x50\xb5\xea\x69\xf6\xc3\xbd\x6c\x8b\xcd\xc4\xc5\xde\x77\x15\xe7\x02\x60\x95\x8a\x5b\x1a\xcb\xeb\xe9\x7d\xfd\x8c\xf7\xe0\x4e\xdc\x23\x07\x1b\x01\x81\xf7\xd3\x05\x71\xb5\xde\xbd\xa7\xb2\xff\xe0\x3c\x56\x2a\xd8\x0b\xaf\xc2\xc1\xad\xba\x6b\xeb\xcf\xda\xac\x22\x49\xf0\xe4\xbc\x4d\xad\x64\x04\x0a\xf6\x1b\x3c\x1e\x84\x54\xc2\x03\x5d\x77\xef\xab\x6e\x20\xcb\x73\x9d\x2c\x08\x54\x70\x27\xf2\x84\xac\xaf\xb4\xdc\xab\x7c\xf5\x5f\xb6\x6a\x20\x70\xbf\x5d\x32\x13\x0d\x0d\x92\x2d\xca\xe6\x00\x42\xcb\xa4\x14\x05\x26\x7e\x04\xd7\xbc\x12\x4a\xbe\x97\xc0\x2d\xcb\x10\x53\x9a\x8b\xc9\x2c\xe1\x12\x34\x95\x6f\x9b\xa6\x64\xda\xb9\x08\xa3\x1c\x5f\xe7\x64\xc3\xc1\x9d\xfb\x82\x1a\x5c\xb2\x47\x01\x0c\x51\x95\xf3\x0f\x41\xbd\x85\xfa\xb5\x9a\xba\x6c\x87\x3c\x29\x19\x50\x38\xe6\x8a\xb6\x5c\xc7\x2a\x62\xb1\x02\x04\x03\x57\x5b\x2a\xab\x28\x97\xc8\x42\x59\x46\x15\xb9\xf7\xfe\x7a\x8d\xb2\xc0\xff\x69\x00\x87\x5c\x43\xad\x76\xe1\x10\x9c\xfa\xe9\x30\x5f\xb1\xe4\xfa\x53\xa8\xe1\xb9\x4d\xaa\x6f\xa7\x55\xda\xb3\xd6\xe5\xdd\xf6\x69\x64\x10\x5d\x5e\x15\x24\x69\xfe\x0d\x32\xa0\xff\xb1\xbb\x02\xfd\xc8\x5a\x2b\x62\xf3\x46\x4a\x71\xb5\x5c\xe9\x20\x6d\xc0\xa9\xe7\xea\x5c\xee\x0c\x7d\x19\x07\x51\xe5\xe5\xe5\x65\x91\xaa\x94\x97\x31\xc4\x67\xaa\x78\xeb\xe1\xfe\x8d\xbc\xc7\x2b\x0e\x4b\x46\x70\x8c\xe6\x5c\x31\x58\x18\xc6\x7c\x15\xca\xa5\xc6\x0b\x25\x78\x3b\x55\xaf\xc4\x71\xf3\xe7\x78\x9c\x11\x6b\xdd\x3e\xd4\x87\x2c\x17\xca\x2b\x4d\x9b\x90\xd5\x5e\x31\x13\x69\xd5\x61\xa9\xb3\xb0\xa0\xfe\x8b\x62\x17\xc5\x68\x8e\x22\x16\x65\xea\xe0\xaf\x0f\x29\x43\x0f\xbb\x60\x32\xac\xc5\x58\xeb\x96\x7d\x97\x56\x2a\x0e\x81\xad\xaa\xfe\xe3\x85\xad\x52\x32\xaa\x55\x15\x65\x4d\xd9\x78\xc9\xab\x66\xfa\x49\x8b\x00\x98\xe6\x6c\x82\x01\x24\x2b\x0d\x95\xb2\x58\x9e\x45\x20\x1e\xe7\xb0\x13\x21\x99\xb8\xaa\x36\xcb\xa2\x91\x35\x30\x7d\x38\x08\xc5\x9d\x63\x1b\x49\x73\x35\x8a\xdb\x2a\x86\xb9\xe9\xc7\x1f\x3f\x4c\xc4\xc0\x26\x75\xa4\x1b\xf9\xce\xa4\x2b\xbc\x14\xae\xac\x21\x4b\xbd\xba\x96\x35\x93\x55\xde\x11\x7e\xde\xbb\x8e\x84\x21\x94\xdd\xc2\xac\x3b\x1e\x36\x5c\x48\x7b\x2b\x52\xfd\x4d\x60\xae\xcc\x20\x05\xc6\x96\x1d\x09\xb8\x22\xa2\x19\xc3\x88\x19\xb7\x8a\x63\x81\x64\xd5\xc7\xdc\x46\xc0\x0c\x5c\x05\xab\x53\x28\x19\x6e\xd9\xe8\x2e\xf9\x7e\xa4\xa9\x7c\x1c\xfe\x93\xa3\xbe\xed\x34\xba\x20\x45\xfe\x55\x2d\x42\x63\x1a\x2e\xd7\x81\x5c\x1e\x9b\xdd\xe9\xa8\xa5\xf2\x71\x95\x96\x52\x22\xd3\x26\xf1\x3f\x8c\x90\xbd\xc8\xef\xe2\x93\x5d\x7f\x7c\x42\xfa\x86\x0c\x75\xd5\xab\x9f\xa5\x7b\x70\xe3\x40\xff\xf6\xd8\x45\x61\xa2\xdc\xcb\x4b\xe3\xd7\x79\x8f\xb1\x1d\x78\x3f\x04\xfb\x22\xf7\xc6\x8e\xb5\x6f\x4a\xc8\xb8\xe7\x29\xe5\xd3\xf1\xe7\x82\x76\xb2\xc4\x97\xee\xee\xc6\xa2\x5f\x60\x5b\x39\x96\xb1\xa9\x5b\x6c\x86\x3c\xbb\x9e\x1d\x9c\x3c\x63\xd7\x9b\x5b\x05\x72\x75\x50\xca\x5a\x50\xd7\xf6\x60\xad\x9c\x4b\xdd\x01\x62\x23\x56\xce\xa6\xfd\x76\x99\x49\x46\xed\xaa\x99\x29\x68\xc4\x30\x6a\xc2\x08\x95\x96\x57\xc3\xe3\xc3\x4d\xd9\x71\x79\xc9\x94\x2a\x72\x25\xb6\xdc\xeb\x60\xb1\xf5\xf7\x81\x98\x3c\xac\x7e\xba\xdf\x49\xd0\x44\x6e\x86\x6a\xac\x93\x6c\xb6\xd3\xd7\xec\x09\x9e\x75\xb8\xcd\xa3\xe0\xd7\xae\x11\x88\x3b\x86\xb1\x4d\xa9\x67\x75\x63\xa3\x2d\xb2\xa2\x20\x11\x27\x1a\x8b\x33\x5b\x34\x5f\x39\x54\xea\x4c\x04\x89\xd8\x24\xf5\xa3\xef\xe3\xf4\x3f\xc0\x92\xe3\x7d\xe4\x06\xb3\x6e\xfa\x48\x37\xe4\x92\xf7\x03\xbf\x7d\xe3\x8d\x6f\xb3\x51\xe9\xa7\x19\x3d\xc8\xfd\x0d\xa1\x1c\x47\x27\xc8\x28\x35\x85\x58\x51\x3b\x39\x64\x94\x32\xe1\x0f\x34\xb7\xb2\x89\x97\xfe\x3f\x77\xf8\xa0\x45\xf5\x7f\x63\xc5\x5d\x56\x66\x95\xd9\x65\xaa\x08\x84\x17\x06\x01\xc6\x4b\x0f\xe4\x08\x06\xe7\x18\xdd\x01\x39\x4d\x1e\xfd\x3d\x3c\x63\xca\x46\x71\x7f\x86\x54\x55\x85\x23\x84\xb4\x49\xfe\x96\xe8\xde\x84\x70\x96\x2e\x3d\x1e\x67\x27\x98\x97\x2b\x67\x44\x9b\xf5\x88\xe2\x5a\xb5\x3e\xb6\xfe\x82\xb5\x4b\x45\x7d\x11\x86\xdd\xcb\xd9\xe7\x51\x69\x1a\xe0\x1e\x4d\xab\xf0\xdc\x49\x7e\xc1\xbb\x9c\x64\x11\x5c\x1f\x9f\x67\x0c\xf4\x09\x9a\x55\x31\x7f\x47\xee\x85\x19\x71\xb9\xf7\x7d\x3c\x0e\x70\x81\x40\xe0\xd3\x31\x30\x0e\x34\x71\x55\x2d\xdc\x18\xb3\xb6\xe0\x65\x34\x35\x55\x64\xcf\x07\x0d\x63\x77\x46\x86\x8b\xbc\x8c\x1e\x4e\x18\x73\x52\xc2\x1a\x6a\x56\xf5\x60\x09\x23\x2f\xab\x32\x9d\xca\x7e\x40\x81\x43\xb8\x6c\x6e\xc2\x92\x3b\x15\x19\x28\xb9\xcb\x59\x9c\x5d\x74\xdf\xfb\x27\xe1\x6d\xbe\xe1\x90\xc8\x6d\x88\xcc\xbe\x85\x5d\x0f\x47\x39\x7c\x4a\xca\xc8\xa4\x39\xca\x58\xed\xd3\x1f\xd1\x1b\xe5\x07\xeb\xa2\x06\x4f\x2e\x9c\x0f\x47\x50\xa0\x14\x2f\xa5\x75\xa5\x3d\x53\xc9\xfc\xe5\xf7\x53\x33\x96\x15\xce\xaf\x90\x45\xda\xf6\xf3\x76\x3d\x8f\x2f\x6e\xf3\xd3\xb1\xf9\xa0\x33\xeb\xef\xf7\xf2\xb4\x68\xf4\xe3\xab\x28\x57\x65\x3d\x42\x27\x5a\xa5\x36\x64\x0f\xca\xcb\x8c\x28\xcd\xc5\x9f\x19\xf3\xfb\xe2\x2a\x9c\xe9\x00\x29\x44\x18\x5b\xaa\x99\x99\x9e\xcd\x24\x65\x08\x25\x2b\xba\x69\x66\x5c\xac\xa7\x95\xa7\xb0\x0d\x5d\xda\xa8\x9d\xb3\xce\x68\x85\xf0\xc7\x03\xea\xf5\x85\x70\xcd\xb1\x7f\xbb\xe6\x5e\xdd\x5b\x5d\xd1\xfa\xc0\x8f\xb3\xf3\x14\x5e\x29\x03\xd5\x1f\x10\x03\xa0\x57\x99\xe8\x1f\xc0\x20\x80\xb2\x33\xe4\xbf\xd1\x1f\xe7\x14\x1e\xff\x07\xa9\xf8\x86\xa4\x37\xaa\xa4\x83\x3a\x4d\x63\xf7\x9a\x26\xe0\xe8\x01\x61\xdd\x7a\x78\xa4\x39\xc9\xd4\x66\x85\x07\xb1\x8d\xff\x71\x41\x5b\x54\xbb\xd9\xbf\x92\x11\x01\xf6\x59\x5d\x6d\x38\xbb\xc6\x36\x1b\xf3\xeb\x5f\x9f\x6c\xa0\x8f\xa3\x32\x15\xb2\xce\x0d\xc1\x58\x46\xb6\x86\x56\xf6\xf2\x55\x71\xc7\x98\x61\xdf\xb8\x54\x21\x6e\xd9\x2c\xc9\xb4\x74\x8d\xce\x30\x62\x64\x28\xe9\x05\xc0\xbd\xbb\x11\x60\x73\x79\xf5\x0a\xc8\x41\xc1\xd5\xfe\xe1\x11\x24\x04\x5b\xed\x18\x74\x2e\x6e\x3d\x94\x70\xb7\xfc\x68\x1e\x70\xc6\x35\x1f\x74\x21\x89\x4b\xc0\xb9\x6c\xe1\x16\x6d\xb3\xe6\x37\x57\xe2\xf9\x74\x70\xe7\x69\x44\xbc\xfa\xa5\x03\x2b\x0f\x98\x9c\xbd\x5a\x33\xa2\x29\xb7\x95\xf8\x37\x37\xc1\x8e\x4e\x35\x7c\x00\xe3\x7e\x31\x6d\xba\xac\xb5\xbd\x74\xe3\x73\x99\x65\xd4\x71\x68\xcb\xd9\x23\xd6\xe1\x1c\xf6\x4c\x88\x03\x0d\xca\xc1\x0c\x23\xc1\xa4\xd7\x4f\x7f\x56\xe6\x9e\xbb\x49\xd3\xd0\x44\x37\xd5\x22\x69\x7f\x98\x69\xbd\x9c\xa8\xc9\x20\xb1\xd1\xf1\x23\x0f\x49\x06\xa8\x9f\x5d\x51\x31\xec\x22\x70\xcf\xb6\x84\xb5\xeb\x34\x3e\x83\x03\x8d\xb9\xef\xdd\xdb\xd7\xd6\xc4\x6a\xfe\xa1\x7f\xb9\x51\x3e\xf5\x87\xbb\x88\x53\x6f\x1f\xd6\x52\x3c\xb9\x89\xf0\x59\x7e\x35\xe8\x92\x14\xbf\x98\x1b\xf8\xcf\x07\x19\xb7\x4c\xc4\x7c\xab\x4f\xe6\x24\x70\x20\x32\xf5\xd8\x2d\x97\xeb\xc3\xb3\x17\x49\xe9\x09\x83\x05\xec\x11\x7f\x54\xd3\x00\x77\x17\xbb\xba\x6f\xcc\xa9\xde\x53\x63\xbe\xe6\x18\x1d\x86\x2d\xfd\x0f\xb3\xc3\x98\xf9\x61\xc7\xb2\x53\x55\x23\x61\x29\xf5\xd8\x52\xb5\xeb\x68\x62\xec\xb5\x89\x01\x57\x63\x05\x6e\x21\xc4\xb1\xad\xac\xec\xb2\x38\x74\xe9\x2b\x3a\x61\x53\x22\x92\xbb\x15\x7b\xe8\x2b\x31\x9c\xbf\x3b\x1f\x58\xe2\xf4\x12\xb5\x9d\xf1\xf3\x85\xe1\x53\x42\x1c\x50\x3f\x1d\x79\xe2\x5f\x57\x80\xae\xb5\xc5\xe1\x06\x55\xdd\xa1\xa6\xaf\x7f\x63\x5e\xcf\x48\x36\x4d\x9a\xea\xc7\x59\xc1\x44\x1c\x4f\x64\x46\xf8\x1f\xff\xc7\xd9\x70\xfc\x37\xd2\xbd\xa9\xd4\x71\x6a\x86\x9c\xfa\x87\x1e\x20\xef\x4a\x14\x43\xd5\x8c\x62\x8b\xd0\x08\x71\x7b\x64\xf2\x72\x4f\x37\xf1\x63\xcb\xee\x7f\xc0\x38\x56\x29\x2c\x0f\xa5\x82\x3e\xd8\xcb\x60\x59\x8f\xe1\x68\xf9\xf6\xf0\x99\x97\x52\xcc\x9f\x56\x14\xbf\xa7\xa0\x82\xc3\x1f\xd6\x12\x5f\x8e\x39\xd8\xa4\xf5\x55\x9f\x6f\x18\x37\x79\x4c\x0c\x68\x4a\x08\xf5\x47\x08\xf6\x43\x7b\xf2\x21\x12\xdc\xcb\xc0\x66\xd4\x64\x35\xf1\x76\x52\x8e\xdb\x1d\x9b\x52\x26\x28\x6c\x16\x6e\xdd\xc1\x47\x37\xde\x4f\xce\xb8\xe1\xfd\x9a\x0c\x0f\x8b\xa9\xe8\x80\x94\x13\x95\x75\x28\x52\xc6\xe4\x23\x7e\xef\xcb\x95\xeb\x5e\xdd\x5d\xc1\x8d\xee\x8d\x1c\x91\xd5\x80\x74\x28\xab\x86\x9f\xf5\xf6\x4b\x2b\x2c\x21\x55\x39\xd0\x59\x02\x87\xd9\x9b\xfa\x1f\xff\x4a\x65\xc5\xbf\x71\x7f\xcc\x36\xc5\xbe\x6b\x55\xd5\xc1\xd3\x0a\x88\xb2\x77\xab\x4b\x69\xef\x1b\x71\x7a\x22\xdd\x10\x12\xea\xc1\xec\x53\x74\x3e\xd0\xe3\xa4\x59\xed\x3c\x8f\xbc\x41\x2f\x53\x0e\xb7\x73\x93\xcd\xaa\xa2\xc9\x97\x5c\x81\x20\x27\xe3\xb2\xd5\x29\x32\x9d\xcd\x04\x20\xd7\xb8\x75\x52\x61\x57\x1b\x91\x5d\x6e\x4f\xca\xe5\x02\x12\xcf\xbe\xd0\x28\x43\x36\xb6\xbf\x87\x3c\x01\x22\xe4\xf1\x19\xe0\x3f\x6d\x26\x0f\x2b\x90\xa5\x90\xbe\xb9\x25\x02\xab\xdc\xe8\x88\xac\x53\xb6\x77\x95\x86\x36\xac\x7d\x8d\x29\x98\x01\x6d\xa4\x53\x4a\xa0\xec\xe1\x7a\xc5\xc2\xf2\x93\x77\x97\xbb\x60\x19\x4e\x02\x19\xe8\x46\xe5\x36\xca\x5d\x5e\x59\xfd\xbd\x0d\x0f\x2a\x37\x46\xc4\x1c\x17\x28\xd3\x6e\x17\x69\xde\xe9\xb1\x1a\x22\x71\x2f\xee\xde\x9c\x1f\x63\xaf\xa8\x4b\xfe\x46\x57\xa8\xa0\x52\xfb\x0e\x12\x81\xb5\x4c\xe0\x88\x18\x77\x45\xec\xdd\x77\xc8\x13\x7a\x16\xc9\x30\x7d\x13\x7e\xb7\x53\xd6\xcd\x68\xe8\xb1\x9d\xc2\x2d\x90\x90\xbc\xae\xbd\x72\x0a\xcc\xc6\xe3\xc9\xfe\x76\x67\x42\xbb\x96\x72\x6b\x56\x35\x8c\xd3\xd5\x1e\xe9\x81\x86\x98\xdc\x81\xee\x45\x30\x11\x5b\x85\x8d\xea\x6e\x03\xef\xaf\xc0\xd9\x6b\x32\x5b\x59\x6c\xd0\x60\x51\x0b\x03\x58\x86\x43\x25\xca\x9b\x66\x9f\xa1\x6c\xc4\x84\xa8\xa3\x9d\xe8\xd6\xc0\xa5\x42\xde\xce\x49\x19\x12\xdb\x68\xdc\x7d\xdc\x65\xa5\x0b\x78\x53\xf7\x80\x5f\xea\x10\xda\x1a\xdf\x5a\x46\x9d\xb6\x9d\x7c\xb7\x4d\xd0\x17\x1a\xf7\xb4\x9b\x9e\x20\x87\xe8\xe3\xd3\x29\x7a\x7a\x1f\xf5\x7f\xd3\x3f\xca\xab\x8a\x64\xfe\xf0\xf6\x12\xde\x6b\xd1\xb9\x00\xf5\x51\xe7\x37\x74\xce\x63\xc4\xc1\xa1\xa0\x35\xff\x7c\x12\xb7\x9d\x72\xcf\x58\x61\xa3\xff\x71\x13\x27\xdd\x01\x11\xa5\x88\x8a\x78\x8a\x43\x56\x52\xf0\xc3\x0f\xd6\x39\x4e\xf5\xda\x4c\x2a\x13\xcf\xaa\x26\xc4\x06\xeb\x75\xb6\x15\x96\x0f\xf6\x37\x1c\xe5\x1a\x1e\xab\xc4\x8a\x28\x07\xe1\x5d\xc4\xd3\xce\x5b\xa6\xb2\x7d\x5b\xfe\x6c\xb8\x7b\xc7\xf9\x8a\x8f\xc8\x83\x3b\x98\xe5\xce\xa4\xb8\xc3\x44\x2f\x78\xea\xdd\x26\x3b\x85\xff\xf8\x97\xa7\xb2\xdb\x82\x82\x96\x97\x85\x1b\x32\xc0\xe4\x4d\x0c\xfd\x94\x5f\x11\xff\x3c\x5a\x18\xa4\x9b\x63\xc5\x30\xf6\x4e\x6f\xc8\xf7\x63\x74\x5f\x99\x01\xb8\x96\x19\xbc\x41\x97\xe3\x59\xcf\x38\x8b\x8e\xa7\xf4\x1b\x65\xa3\x50\x69\x40\xef\x01\xc2\x8b\x73\xf6\xca\xb3\x97\xd1\x17\x04\x91\xb3\x2a\x41\xb0\x64\x6f\x8c\xc7\x65\xd3\x02\x0a\xaa\xaf\x70\x8b\x57\x6a\xed\x76\x70\x35\xd0\x4e\x2d\x74\x88\xb0\x53\x13\x82\x9a\xcc\xe8\x48\xc8\x5a\xdf\x63\xd8\x5e\x99\x4e\xfe\x14\xc2\x78\x2e\x3f\x92\x54\x95\x7a\xa2\xce\x2b\x84\xeb\xcb\x92\x11\x47\xa4\x2f\x54\x97\x73\x10\x1d\x35\x65\xf0\x68\x98\x84\x38\x1f\x9f\x40\x24\x8e\xf7\x88\x9d\x14\x1b\x1b\xec\xdf\x1d\x04\x51\x6f\x96\x53\xf7\x12\x56\xa7\xd9\xcd\x52\x0c\xfb\x08\xd6\x68\x05\x3d\x1e\xd2\xf3\x1d\x59\xb2\x5e\x7a\xec\xf2\xb1\x65\x97\x70\x3e\x0f\x0a\xa0\x1f\xef\x20\x10\x70\x33\xdf\xc8\x1d\xf3\x78\x28\x5e\xe3\x11\xb6\x4e\x65\x34\x47\x90\x1e\x26\x2d\x07\xf5\x21\x60\x07\x75\x0a\xc7\xc1\x6a\x2e\xa3\xe4\x87\x3e\xfb\x28\x0d\xf6\x0f\x55\x2c\xf2\xc9\xfd\xcc\x20\x8e\x8a\x8c\x6e\xfb\x5a\x58\x66\x55\x26\x80\xed\xb3\xf8\x3c\x5b\xe1\x9e\xe1\x7b\x75\x29\x1c\xe8\xa7\xe5\x80\xbe\x74\x9c\x66\x4a\xa2\xdd\x30\x79\xfb\x8a\xf1\xf0\x08\x5e\x80\x12\x01\xd0\x85\xe0\xfa\x05\x63\x46\x3e\x19\xfd\x87\xd9\x6f\x63\xcd\x4f\x61\x4e\xe0\x08\xd4\x93\x83\x17\x65\x8d\xcb\x2a\x47\x4a\xc9\x5b\x83\x42\x40\xc0\x5f\xad\x8a\x35\xc5\xbe\x80\x84\x02\xfc\x18\xa4\xd4\xcf\x95\x51\xb2\x4f\x0e\x01\x9c\x92\x0f\xeb\x5f\x9e\x61\xd3\x52\x96\x78\xa7\x7e\xf4\xb2\x07\x7b\x26\x9b\xf2\x62\xab\x57\xce\x45\xb6\x29\x1e\x5b\x9d\x96\x20\xa5\x36\xb9\x1d\x46\x5b\xa7\x9d\xb5\x44\xfb\x80\xf5\xe6\x54\x1f\x58\x4a\xd1\x60\x07\xc8\x58\x5c\x1f\xaa\x9c\x99\x77\xed\x92\xb9\xd7\x90\xec\x3d\xbc\xb8\x5a\xf7\x2e\x36\xba\x14\x55\xff\x2d\x39\x9b\x3b\xfb\xf3\x7e\x99\x93\xc1\x6d\x28\x14\xda\x8f\xde\x52\x70\xf5\x2e\x22\x34\x50\x96\x5b\xee\x5e\x38\x62\x25\x89\x54\x4f\xe9\x9c\xfb\x17\xda\xba\x6c\xb2\x1f\x2b\x53\x58\x57\x6a\xc4\xf6\xb1\xf4\x96\xc1\x6f\xf6\xf0\xdd\x1e\x9f\xb0\xe2\x7a\xf4\x91\xcf\x47\x2b\x2e\x35\x0e\xa8\x47\x31\x66\xff\x32\xe0\x6f\xe6\x9c\xc6\xc6\xca\x30\x9a\xc6\x2f\x62\x81\x48\x07\x1c\xcf\xc2\x6c\x18\xc0\x0c\x17\xcc\xe0\x0a\x84\x11\x68\x29\x66\x4a\xcd\x5a\x05\xd4\x34\x58\xb9\x38\x04\x7e\xc8\x28\x01\x29\x48\xf8\xd1\x02\x19\x2c\x75\x06\x05\xdf\x6f\x8d\x3d\x10\x07\xa8\x44\xb3\xb7\x8c\xaa\x5d\x6d\x19\xf7\x7d\xf5\x46\x46\x42\x8a\x86\x72\xd4\xf0\x98\xae\x61\xee\x89\xac\x96\xf6\xfe\xef\x9c\x53\x68\xb5\x43\x1b\x0d\xba\x41\xb5\x6c\xd0\x91\xd9\xf8\xec\xdf\xc4\xa3\xfa\x9f\x13\xf6\x2c\xee\x6e\xb4\xd5\xf6\x6a\xcd\xef\xb7\x2c\xbe\xf2\x45\xa1\x58\x61\xca\xaa\x57\xe1\x48\x4d\x0e\xb5\x25\x5e\xce\x72\x45\x8f\x4b\x1d\x33\x8c\x3c\xf1\xac\xa0\xb6\x3a\x83\x50\x8c\x7c\x4d\xe1\xeb\x63\xea\x19\xcd\xb5\xf6\xdb\x3d\x68\x20\xf0\xac\xc1\x87\xe6\xf0\x89\x72\x9b\xcb\x76\xfe\x15\x1d\x04\x14\x7b\xb6\x0c\xce\x43\x6e\x50\x65\x50\x77\x1c\x59\xdc\x23\xb5\x25\xd6\xa4\xfa\x31\xe7\x2c\x1d\x55\x06\x9c\xcc\xb2\x26\x5b\xb4\x92\xff\x1d\x59\x78\xe9\x72\x6e\x26\x30\x2d\xe8\x23\xcd\xf2\x39\x44\x00\x2f\xd9\x7e\x18\x57\xee\xeb\x52\x36\xd0\x6a\x5d\xce\x5c\x6a\xdc\x19\x20\x23\x54\x96\x5b\x75\xb7\x33\xe7\x41\x4a\xec\xb2\xa1\xdc\x47\xf5\x07\x76\x18\xea\x24\x99\xb1\xcf\xf4\x5a\xdd\x9c\x7d\x3d\xb2\xcc\x9e\xc5\x78\xe6\xae\x82\x51\xd0\x35\xb5\xa5\xb3\xb4\xba\x47\x08\x90\xd8\x0c\xe0\x5f\x79\x87\x8f\x26\xc3\xc3\x25\xa6\x1d\x99\x93\xba\x0b\xdb\x80\x94\x83\x68\x25\x40\x8d\x7d\xf1\x28\x50\x1f\x02\x3f\x3e\x74\xd0\xf5\x53\x93\x4e\xb1\x19\x96\xb2\x5d\xf7\xde\x61\x06\x9b\x92\xb7\x53\x88\x48\x4d\x90\xd0\x87\x82\xb0\xda\xeb\x00\xc6\xc8\xd2\x32\xe7\xa1\xec\xda\x62\x8b\x04\xc5\x87\x9a\x05\x7c\x0b\x9f\xc9\x32\x6f\x25\x98\xd0\xe0\xf7\x90\xa0\x7b\xa5\x1b\xb8\x16\x09\xb9\xa8\x90\xb8\x5f\xb6\x4e\xb4\x61\x7e\xe6\x9f\xd1\xdd\x06\x19\xa8\x3e\x7b\x97\x82\xcf\xb2\xb7\xd2\xfc\x23\x93\x30\x6f\x3f\x7f\xfa\x32\xeb\x94\xe5\x8b\x7c\x86\x7d\x4b\xbd\x5c\x87\xa0\x85\xb8\x49\xbf\xcd\xb9\xe4\x6a\x20\x2c\xb5\xa2\xb7\x6d\xa6\xfa\x02\x07\x64\xff\xd3\x1e\xe3\x52\x8a\x92\x9e\x7f\x53\xc4\xe2\x76\x56\x5b\x11\x26\x2e\x56\x2a\x39\x9c\xc7\xc0\x05\xd7\xab\x5f\x1c\x47\xe2\x9b\x67\x3c\x06\x30\xf1\x74\xb5\x2b\x08\xb7\xd8\x65\x0c\x1d\xcb\xdb\x77\x68\xf8\xe5\x15\x7d\x11\xa8\x6b\x70\x38\xc6\xdd\x3f\x36\x02\x10\xc1\x78\x23\x7d\x02\xd9\xe1\xe5\x45\x9f\x3a\x22\x7b\xe2\x54\x90\xa4\x5c\xa4\x55\xd1\x3f\xf2\x1c\xf0\x12\xd8\xba\x9e\xa9\x1f\xf6\x3d\x78\x84\xaa\xf0\xe1\x7e\xe6\xc3\x04\xb8\xc7\xf8\x13\xed\x69\xe8\xcf\xdd\x53\x58\x0d\x11\xc0\xbd\x4c\xbe\x08\x28\x45\xa2\xe1\xb0\x1d\x72\x26\xdb\xf7\xc8\xad\x59\xba\xf6\xe4\xa6\x08\x0a\x01\x9e\x1f\x1c\x77\x2c\x6e\xd5\x6b\xb0\xf1\xc7\x70\x7e\xec\xfe\x39\x9c\x4e\x6e\x2a\xd7\xd9\xaa\x1b\x51\x29\xce\xb0\xa1\x1d\x36\xbb\x76\x0f\x30\xed\xb0\xa5\x19\x7a\xcd\xc7\x65\xc7\x38\x6c\xf2\xb0\x82\xa0\x3d\xd9\xe1\x2c\x67\x87\xe4\x4c\xc1\x12\x1a\xa4\x2d\x18\xe4\xe3\x3c\x84\x2b\xcc\x90\x42\x56\x81\xf3\xe1\x57\x53\xc0\x90\xba\x41\x7d\xc8\x72\xbd\x74\xf6\x9b\xe1\x21\xd6\xbf\x8b\xc3\x7d\xdf\xf2\xe5\x3f\x75\xdf\x54\x86\xdd\xc1\x54\x60\xeb\x62\x83\xb6\x45\xbd\x0d\x34\x87\x75\xb5\x7d\x25\x4d\x40\xcd\x30\xe5\xec\x9c\x75\x1b\x3d\x52\x7b\x22\x4f\xb4\x71\xab\x57\xba\xac\xb4\x2d\x67\xb8\x5c\xd0\xa4\x72\xc0\x08\x53\x11\x9b\x1c\x23\x92\x0a\xf5\x4a\x50\x6c\x3b\x20\xf1\x0e\x1b\xaa\xea\xf3\x0a\xfb\xec\xa0\x92\x5c\x91\x98\xd5\x37\xf5\x5e\x36\xe3\x62\x81\x40\x06\x61\x6d\x3c\x7a\x04\xea\x95\xa0\x1d\xaa\x59\xba\x7f\x05\xeb\x02\x76\x94\x5c\x72\x7a\xd1\x6a\xfa\xe5\xef\xa3\xaa\x96\xfd\x0e\x4b\xed\xb1\x51\x7a\x48\xd1\x04\x23\xed\x8f\x5a\x26\xa4\x7a\x07\x2b\xa4\x9c\x00\x4d\xbf\x89\xfd\x51\x16\x15\x14\x5c\x65\x76\x72\xbb\xa4\xcc\x96\x6c\x95\xa4\x2d\x4c\xf4\xcb\x06\x1e\xde\xf5\xb4\x37\xab\x74\xc8\x6e\x4b\xef\xd0\x03\x76\x9b\xd7\xf2\x2e\x7f\xec\x35\xd3\xe5\x33\x50\xf7\x2e\x07\xf5\x02\x3f\x83\xff\x6a\xc9\x43\xce\x94\xe8\xc8\x91\x3b\x94\x12\xaf\x08\xc3\x51\xff\x64\x8c\xf6\x08\x1a\xbf\x6e\x9b\x48\x3c\xe6\xfb\xd1\x4e\x71\x67\x65\x38\x77\x87\xfc\xbc\xe4\x0b\xd8\x95\x6d\xd1\xef\x4d\x1d\x92\x2f\x2f\xcf\xb2\x9f\xd2\x3f\x29\x87\xb9\x5e\x04\xb9\x8b\x23\x52\x97\x1f\x10\x22\xb7\x0a\x32\x42\x37\xd1\x89\x62\x52\xd6\x00\xc8\x2e\x79\x2f\x12\x7a\x3c\x83\x77\xff\x18\x58\x5c\x7e\xa8\x31\x26\xa7\x96\x96\xa5\x6a\x19\x54\xbc\xa6\xcd\xef\x6a\x67\x6c\x01\x84\x02\x34\x35\xfe\xea\x9c\x0c\x57\x6a\xa6\x4d\xa6\xa2\x89\x42\xfb\x14\xd6\x73\x3e\xd2\x88\x32\xc4\xe8\xab\x4c\x94\xa4\x87\xec\xfe\x7e\xee\x55\x8f\x8f\x93\xb9\xde\xef\x05\x94\x3a\xfd\xbd\x3e\xa6\x3b\x47\x73\x48\xc2\x9d\x8f\x01\xf6\xe5\x72\x30\xb5\x43\xfe\x72\xa1\xa8\x68\x3c\x28\xab\x58\x35\x12\x88\xce\x11\x56\xb9\x68\xd8\x98\x91\x40\x73\xee\xea\xd5\x8b\x23\x8a\xfa\x6d\x67\x0f\x1e\xd6\xa2\xef\x17\x7e\x64\xcd\x16\x92\x30\x13\x48\xd4\x5b\x21\x14\xee\x6f\x31\x59\x81\x58\x06\xf6\xd5\x6d\x53\xcd\xf7\x93\x7f\xb7\x94\xfb\xeb\xb5\xee\x80\x60\xa2\x3b\xfd\x05\xa4\x11\xf6\xc2\x7e\x76\x17\x74\x94\x2e\xbd\x4c\x42\x09\x07\x2b\x30\x4d\x3e\xd1\xc2\xe9\xf2\x9f\x7d\xeb\x22\xb8\xa6\x39\x23\x0a\xb0\xd9\xce\x45\xd3\x3d\xb5\x14\x41\x3f\x81\x6a\xcb\x46\x72\x5b\x7c\x85\xa4\x9f\xb0\x85\x52\x1d\x76\xc9\xfd\x3c\x82\x81\x02\x2b\x81\x46\xe6\x68\xcd\x34\xd6\xee\x0e\x13\xa8\xde\xaa\x98\x9a\xf1\x72\x93\x00\x41\xc5\xad\x9d\xe3\xb8\x52\x93\x44\x0f\x69\x2a\x6e\x8a\xfc\xa4\x43\xb7\x4c\x41\x7e\x6a\x2c\xfb\xbd\x04\x40\xdc\x7a\xd6\x06\x25\x73\xa8\x01\x1a\xec\x99\xec\x7b\x0e\x1e\x85\x9a\x3d\xed\x53\xf6\x28\xee\xf2\x04\xfb\xe3\x55\x7e\x33\x77\x69\xca\x95\x42\x0d\x9a\x44\x14\xfb\x6e\x05\xc7\xe5\x4a\xce\x27\x6c\x73\x99\xf4\x26\xa2\xd2\x14\x69\xa8\x57\x83\xbd\x2b\xc9\x64\x6a\x14\xad\x97\x09\x6f\xa2\x95\xa6\xda\x40\xe2\x88\xdd\xa8\xc5\x70\xeb\x87\x51\x72\x8c\xbf\xaf\xae\x77\x68\x25\xa8\x17\x9d\x06\x26\xd9\x7a\x73\x0b\x21\x90\xed\x11\x20\x83\xe7\x6a\x53\x3e\xd6\x52\x0a\x87\xbe\x8b\xa6\x15\xb6\xb1\xaf\x2b\xdf\x49\x86\xe7\x0e\x70\xb2\x7b\x9e\xde\x01\x82\x0c\xca\xd9\xd3\xb0\x88\x4d\x44\xf4\x6e\x70\x40\x5f\x5a\xde\x4c\x3c\xd5\x3f\xca\x0a\xf9\x18\x27\xfb\x2d\xdb\x4a\x4c\x59\x6f\xf6\x9e\x4d\x6e\x81\x36\x99\x4e\x07\xf9\x9c\x3a\x76\x96\x46\x2f\xeb\x6f\x24\xd4\xa9\xc3\xa4\x44\xc2\x37\x6c\xde\x82\xde\x01\xe3\x3d\xf7\x9d\xf8\x65\xbc\xcb\xdc\x40\x9b\x7b\xf5\xa0\xfa\x66\xb7\x06\xf2\x0d\x2d\xfd\xb2\x89\x2b\xb3\xf3\x5f\x28\xcb\xb1\xd0\xb5\x17\xb3\x9d\xf8\xf5\xbe\xc6\x21\x18\xa7\xaf\x91\x67\x1c\x49\x8c\xb3\x05\xa0\xe5\x20\x4b\xf8\x73\x92\x8f\xe6\x9e\x0f\x68\x0d\x6d\xed\x2a\x95\xbd\xd2\xc5\x59\x82\x53\x41\x7b\x86\x9d\xfa\xbd\xbf\x3a\x53\xcb\xbd\x1a\x59\x55\xc3\xbd\x2a\x09\xe9\xa5\xdc\x0f\x3e\x8d\xab\x15\x1e\xe2\x1c\x67\x97\xe8\x64\xe7\xcb\x8e\x7c\x3d\x26\x1b\x57\x18\xc7\xf6\xd9\x25\x00\xc9\x3e\x56\xcf\xc9\x16\x06\x97\xe5\x3a\x9d\x84\x44\xb4\x41\xa2\x56\x28\x3e\xe0\xb4\x85\xc1\xb8\x69\x09\x87\xe1\xac\x0b\x46\xd4\x1d\xbc\xc5\x76\xa6\x06\x4c\xdd\x27\xc7\xb6\xd2\x3b\x58\x96\x06\xf8\x28\xaa\xff\xdf\x94\xa1\x68\x74\xb7\xc0\xa1\x9c\x9a\x7f\x49\xa6\x04\xd4\x02\x5c\x2d\xa2\x68\x18\x73\x3c\x46\xb7\x08\xdb\xde\xa3\xa6\xda\xf1\x98\x96\xba\x37\x31\x5c\x70\x03\x5b\xc2\xbc\x2d\x91\x94\x4a\xa8\x39\xd2\x4f\x49\xd0\x8e\x98\x57\x18\x9f\xf9\xa9\xa1\x3c\x89\xce\x93\x5c\xda\xc5\x95\x19\xef\xf7\x68\x42\x55\x67\xbb\xe3\x6a\xea\xd0\xb2\x4d\xbd\x21\x73\x40\x60\xe3\xa3\x1e\x13\x31\x9f\xb2\x4d\x2f\x55\x15\xbb\x3b\x33\x14\x5a\x37\xb2\x56\xd8\x91\xdf\xa7\x20\xb6\x72\x91\xdb\x2c\xfa\x28\xfb\x1e\x1b\xa6\x43\xff\x61\xee\xca\x63\x93\x9f\x23\x60\x2b\x35\xa6\x90\x13\xe5\x5e\xcd\x72\x31\x82\xfa\xe8\xf2\xf4\x41\xc0\xe9\x3b\xb5\x13\x61\x2a\x56\x4e\x1a\xfd\x18\xad\x3c\x5f\xcb\x2d\xfb\xd7\xb2\x4e\xb7\xf8\x59\x95\xa8\xc9\x26\x6a\x9c\xa5\xed\x19\xcd\x9c\xf2\xf6\x48\xcd\x28\x5b\x90\x10\x51\xe4\x5f\xab\xad\xcb\x0c\x23\xa8\x6d\xeb\x7f\x7d\x63\xb1\x87\x3b\x5f\xa5\xbe\x0a\xbb\x3c\x59\xe7\xa9\x0b\xa2\xdf\xde\xd6\x79\xa0\x90\x54\xf9\xc6\x39\x45\xc0\xec\x6a\xd1\x39\xb4\x1c\x97\x97\x1e\xb5\x1c\xb7\xda\x91\x89\x3e\x8c\x5b\x2e\x41\x37\x8f\x47\x0f\xb6\xf1\xbd\x85\xda\x43\x44\x04\xdf\x81\x0d\xa8\xce\x9a\x30\x5d\x17\x1b\xc5\x3d\x1f\x35\xd4\x39\x2a\xb3\xa0\x1d\x11\x39\xb6\x12\x24\xc4\x9f\x32\x44\xd0\xaf\x49\x33\x8c\x73\x35\x05\x65\x6e\x12\x59\x20\x54\xbe\x78\x7e\x81\x2d\x42\xac\xa2\xd2\x84\x8c\x32\x3f\xc8\x4d\x34\x67\x88\x4c\xe9\xb1\x4e\x82\xda\xe0\x05\xda\xd5\xe6\x0d\xaa\xfc\xba\xbf\x2f\xbb\xeb\x23\x0c\xbb\x31\x0e\xcf\xfd\x55\xd6\xa4\xce\xaa\x0a\x5a\x0c\x5c\x1d\x94\xf3\xb7\xaa\x49\x8a\xc4\xde\xe5\xa1\x3b\xb4\x83\x29\x9b\x8f\x72\x9d\xd8\x40\x69\x35\xc5\xfa\x66\x47\x3e\xbb\xce\x96\x8f\x20\x36\x2f\x28\x28\x63\xd9\x0a\xcb\xc1\x41\x5e\x6d\x30\xde\xfb\x68\x00\x73\x55\x13\x3f\xb0\x6e\x9e\x84\x0f\x3c\x0c\x16\x0a\x34\x5f\x6b\x15\x95\xb4\x52\x3c\x94\x21\x7f\xd4\x72\x91\xe1\x3a\x72\xc3\xc7\xbc\x93\x60\x89\x6c\x5d\x70\x95\xd8\xeb\xc1\xed\xd2\x5e\x3b\x85\x7c\xa9\xce\xac\xf8\x2e\x73\xb4\xd9\x5a\xb9\xd3\x15\x21\x8f\x78\xeb\x4d\x3e\x65\xff\xc2\xcb\x6f\xc9\xa0\xb9\x69\xf2\x5f\x32\x10\x5c\x55\x9d\x0b\x2d\x16\xfa\x18\x01\xb0\x53\x63\xe8\x8d\x9d\x0a\x75\x2c\xe2\x13\x60\x94\xd4\x9b\xd4\xf9\xf8\x56\x17\x6b\x09\xb5\xe8\x22\xbe\xe8\x5c\xa6\x6c\x93\xaa\x67\xc5\xe5\xcf\x26\x3e\xce\xe0\xc6\xb7\x7a\x3b\xe8\x5f\x49\x5e\x92\xb9\x06\xbb\xe1\x42\xc4\xd1\x7a\x97\x5c\x7d\xa8\xe6\xcc\xc9\x0a\xd1\xea\x3c\x6a\xc2\x22\x7c\x26\x23\xdd\xd1\xe3\x98\x2d\xc2\x41\x70\xfc\x32\x80\x78\x18\x55\x93\x4d\x3d\x7a\x76\x49\x16\x10\x00\xad\x07\x2f\x62\x94\xa7\xeb\xb6\xd3\x6d\x97\x42\xad\x4f\x94\x6b\xae\x46\x9b\xb3\x33\x7a\xe6\x4a\x8e\xc3\xa8\x7d\x44\xe3\x69\x3b\xf2\x79\xf7\xa8\x66\x7d\xd1\x7b\x48\x31\xc4\x8b\xfc\x9b\xe6\xb0\x5d\x81\x08\xc7\x2f\xfc\x63\x83\x0c\x94\x79\xb5\xe3\x33\x13\x8e\x33\xbb\x26\x98\x24\xd3\x87\x6c\x7f\xf8\xda\xb3\x0d\x75\x56\xb1\x0d\xd2\x6b\x06\x79\x4b\x20\x9b\xd8\x42\x67\xb8\x54\x94\x6d\x35\x49\x30\xe3\xfe\x27\xee\x0c\x7f\x57\x35\xae\xca\x6a\x1a\x62\x1d\x30\x6a\x64\x52\x01\x5d\xda\x2e\x6e\x4c\xf9\xab\x4c\x0d\xb9\x6d\x73\xfe\xd8\xac\x5a\x79\x42\x7a\x99\xa9\x0d\xd0\x0a\xf9\x77\x7a\x6e\xda\xae\x3e\x45\x93\x78\x0a\x23\x7d\x8e\x41\xb3\xff\xc9\x9f\x4d\xa7\x10\x8c\xa1\x37\x31\x4d\x98\xf7\x68\x2e\xcc\x92\xdb\x1e\xdc\xb6\x5b\x8d\x29\xf3\xaa\x89\xcc\x67\x34\x59\x25\x4d\x86\xd3\x60\x05\xed\xcb\x7c\x79\x5e\xf4\x99\xb6\xcc\x57\xa1\xee\xa9\xb1\x65\x7e\x18\xab\x34\x32\xb2\x74\x87\x42\xf3\xcd\x56\xd9\x10\x43\x51\x73\x90\x55\x4a\xc2\x9e\x42\x1d\x9f\x0f\x35\xc7\xda\xa2\x3c\x3e\x91\xde\xf7\xb8\xd6\x13\x0e\xcd\x5f\x29\x05\x2e\x1f\x97\xdf\xff\x24\xf4\xa1\x4f\x7e\x66\x43\x28\x67\xfb\x52\xc8\x49\xe7\x91\x91\x83\x70\x63\x6e\xb2\xb3\x94\x7f\xd4\x76\xa6\x15\x22\x27\x24\x04\xcd\xcb\x64\xbf\x1f\xe7\xb2\xfa\xaa\xf3\x84\xa4\x90\x48\x54\x4e\xf3\xb9\x94\x7a\x6a\x13\xe9\xa5\xfc\x20\xca\x43\x4b\xe3\xf3\xe4\xad\x7d\x41\x1e\x89\x33\xf9\x70\xca\xd7\x6c\xd8\xce\xe8\x14\x0e\x50\x48\xc4\x50\x1c\x16\x20\xac\x6a\x21\x61\xcd\x8b\xbd\xf9\xb0\x39\x53\x0b\xd1\xbe\xaf\x8f\x07\x6e\x62\xd5\xb0\x6d\x69\x89\x8e\x2a\x49\x1f\x72\x07\xee\xa1\x03\x98\xbd\x91\x18\x22\x98\x61\xd0\x81\x1b\x56\xd8\x70\xf1\x0b\x28\x9b\xfd\xdc\x8e\x66\xcd\xac\xd1\x63\x42\x55\x21\xfb\x8b\x52\x87\x4c\x91\xe9\x82\xa6\x12\x14\xdc\xfe\x4b\x0f\x2b\xf3\x9b\x1a\x4c\xa1\x7b\xbf\x57\xd1\xe9\x3d\x8b\xaf\x75\x77\x8e\xfd\xdd\x2d\xb6\xfb\xe8\x66\x0f\x1d\x19\x35\x48\x9b\xb9\x33\xfd\x3f\x5d\x0d\xb0\x64\xb4\xd3\x7f\x29\x55\xa9\x23\xfa\x98\x95\xdb\xff\x1a\xdd\x84\xd9\xfe\x36\x7e\xd3\x4e\x70\x4f\x27\xe4\xcb\x22\x21\x3f\xc5\x50\x0e\xea\xbd\x7e\x7d\x6c\xba\x0e\x98\xd0\x3c\xb9\x7b\x74\x8c\xf6\x4f\xc4\x3e\xc5\x7a\x21\x9f\xa8\xbd\x97\x06\x75\x91\xe0\x05\xa8\x87\x86\x57\x44\x2f\xe4\x40\x7e\xfd\xfe\x07\x3b\xff\x44\x6c\x61\x96\x85\x5e\x6c\x17\x1e\x05\x79\xa2\x2f\x75\x96\x1b\x38\xe7\x12\xd0\x48\x77\x0e\xda\x2a\xb2\xa1\x14\x4d\xa3\x13\xf2\xcf\xde\x82\xa4\xe8\x29\x8d\xf4\x69\x0e\x6a\x0d\x84\xad\xf5\xfe\x14\xd6\xb9\xf5\x60\xbb\x99\x52\x33\x7d\xa5\xab\x95\xad\x27\xe5\xfe\x49\x1a\xa4\x25\xbc\x39\x08\xef\x77\x63\x67\x65\x50\xa9\x6e\xbc\xc7\xe8\xc6\xf4\xd7\xaf\x8e\x78\x23\xdf\xc6\x50\x42\xf9\xc9\x73\x8d\xdf\x77\xce\x9b\x29\x36\x97\xa5\x46\x7f\x0f\xa5\x52\xeb\xb6\x29\x7a\x48\x7e\x65\x10\xc1\xf1\x33\x97\x57\x94\xf7\x34\x52\xdd\x1e\x9b\x16\x78\xc5\x05\x58\x6e\x74\x8a\x87\xe3\xee\x92\xee\x23\x71\xcd\x4b\x5d\x4b\xb7\x92\x6b\x57\xc2\x63\xf7\x65\x4a\xe5\xf8\x4f\xbe\x89\x44\xf7\xa2\xb5\x8b\xe2\x75\x8a\xf6\x8e\x75\x37\x35\xd2\xad\x9a\x6f\xa0\xba\x88\x2c\xb6\xda\xc3\x5a\x0c\x9d\x52\xbf\x95\x6a\xa4\x81\x8c\x1b\xfb\x5b\x90\x78\x5a\x7f\x4e\x9b\x38\x5a\x52\x84\x34\x82\xe0\xf3\x94\x95\x38\x95\x05\x6b\xd4\x1f\x52\x2c\xc4\xb6\xe0\xd0\x30\x23\x50\xc3\xdd\xa4\xea\x3e\x8f\x61\x68\x03\x4a\xb9\xb5\x45\xe2\x75\xb9\x30\xfe\x92\x86\x08\xbf\x66\xf3\x86\x61\x70\xed\x18\xb1\x75\x65\x82\x37\xbf\xa7\xac\xb1\x5c\x07\x21\x5c\x62\x3e\x74\x15\x2e\x9d\x4f\xa5\xc5\x49\x71\x93\xe4\x23\xc9\x96\x53\x04\xdd\x80\x1c\xe4\x09\x1e\x6a\x26\x30\x66\x9d\x11\x07\xd5\x93\xdb\x47\x66\x21\x35\xe7\xdf\x9f\x65\x4b\xbb\x23\x4a\x9a\x13\xc1\x24\xea\x9e\x9c\x8a\xd0\x6c\xe0\x46\x53\x05\x4b\xea\xf6\x50\xae\xa4\x76\x52\x9f\xec\xb7\xb1\xb9\x29\x45\x2f\x24\xbb\x64\x94\x59\x27\xb4\x4e\x39\x18\x52\xcd\x04\x34\x97\xff\xc2\xb8\x3d\xbd\x3d\x6f\x7a\x2c\x35\x9d\x28\x40\xce\xa5\xeb\x11\x93\xa1\x0e\xbe\x68\x41\xea\x18\x95\x79\x5b\xf2\x82\xa6\x6f\x9f\xef\x2c\x54\xa2\xe9\x9d\xe6\xd6\x98\x2e\x0d\xe5\xb7\x8b\x84\x26\x0d\xab\x13\xd9\xca\x70\xd0\x5f\x9b\xb2\x43\x8a\xa8\xf4\x74\x85\x07\xa6\xf3\x17\x95\x9c\x0c\x30\x0e\x1b\xe6\xa8\x51\x14\x1a\x27\x14\xa1\xe1\xbc\x0f\xef\x54\xde\xec\x55\x59\x04\x92\xc2\x95\x81\xb0\x2d\xd9\x4c\xec\xb2\x16\x68\x5d\x85\x57\xca\xe1\x2e\x47\x19\x27\xed\x79\xd2\x5a\xca\xa2\xe9\x13\x6e\x1e\x91\xb2\x6e\x2a\x91\x92\x79\xd9\xc2\x01\x53\x49\xba\x29\x01\xe1\x69\x6e\xce\xe9\xab\x8d\x94\x75\x03\x2e\x9e\xd2\x19\xca\x56\x47\xb9\xe2\xd3\xe0\x02\xa2\xcc\xc5\xfb\x53\x29\xe2\xe3\xe6\xa6\xd3\xfd\x8e\xcf\xed\xcf\x50\x13\xc9\xbb\xd7\x05\x9f\xc3\x1e\x1a\x96\x6f\x22\x23\xcd\x96\x21\xa4\x0e\x5b\x04\xf5\xc3\x2e\x7a\x38\x43\x1c\xd6\xb4\x78\x6f\xf7\xd7\xf3\x6b\xfa\xe4\x0f\xf3\xd5\x3f\x99\x2c\xf7\x4f\x6a\x35\x19\xd1\x2e\x53\xcd\xa3\xed\x72\xfc\xb0\x33\x77\xb9\xf5\x1d\xee\xad\xbd\x91\xff\xa3\x1f\x1b\x71\xe3\x1e\x4c\x65\x82\xe1\xa9\x02\xa7\x10\x5e\xb7\x6f\x98\x07\x6b\xe2\x7f\x33\x0b\xd5\x43\xef\x20\x21\x5d\xe8\x9d\xe1\xb0\xc8\x17\xfd\x25\x72\x52\xb4\x93\x2e\xbf\xe0\xf2\xa9\x5a\xc5\x3c\x44\x70\x4e\x99\xa6\x45\x49\x7b\xb1\x73\x27\xd2\xd2\x8a\xc0\x9b\xe8\x10\xd1\x9e\x9b\xa7\xa7\xda\x4a\xd8\x7a\x0e\x95\x75\x64\x24\x21\x6c\x30\xd1\x3e\x3a\xc2\x3a\xb3\xbb\xdc\x38\xd8\x40\xa2\xb3\xd2\xd4\xdb\x9a\x73\x51\xde\xfd\x8d\xba\xac\x71\xf2\x6e\xfd\x78\x2b\xbb\xf5\x70\xdf\x15\x8e\x59\xd5\x47\x73\xfb\xdf\x19\xe9\x0d\x78\x53\x96\x4d\x6d\x67\xf0\xdf\x68\x3c\x62\xfa\x12\xb3\xce\xa3\xe1\xa4\xcc\x11\x53\x9c\x62\x8a\x3b\xa8\x5e\x9e\x39\x72\x6f\xfe\xa0\xa2\xc0\x7f\xcd\x48\xdd\x12\x7d\x29\x93\xd3\x77\x60\x02\xfd\xc4\x80\x8f\x1f\x93\xe8\xa3\x87\xcd\x6f\x39\x14\xc3\xa9\x5c\xf0\x9c\x29\x0f\x68\x4e\xfc\x5b\x7c\x65\x40\xf0\x08\x67\xb7\x4e\x86\x32\xee\x92\x6c\x35\x95\x9e\x7f\x58\x14\xb8\xbf\xdd\x86\x79\x07\x99\x72\x3f\xf7\x2b\x0a\x74\x87\xd5\x69\x50\x68\x38\xb6\xfe\x4b\xf6\x27\x1a\x36\x6e\x7e\x95\x01\x5a\x3d\x4b\x1f\xfd\x2b\xf4\x4d\xfd\xd4\xa6\xb3\x59\x0f\x7a\x56\x0c\xf8\x2f\xf3\xc3\x4a\xda\x9c\xc6\xed\x53\xd6\x1f\x3c\x2a\xef\xe9\x9d\xc2\x21\xa5\x37\x70\x89\x4d\xe3\x10\xfd\xaa\x20\xd6\xa9\x5f\xa5\x06\x52\x59\xa0\x7a\xb9\x42\xa2\x67\x15\x00\x83\xfa\x57\xa2\x3e\x4d\x4a\x0d\x5f\xc7\xff\x50\xa1\x9c\x39\xb1\xa6\x3f\xdd\x40\x41\x87\x11\x42\x44\xe9\x0d\x1a\x32\xb7\xb2\x91\x46\xde\x39\x5f\x75\x96\xe7\xde\x6e\xfb\xc1\x9d\x35\x97\x9a\x4b\xd3\x58\x19\xd6\xfb\xd3\xa8\x04\xa9\x51\x7e\x43\x65\xe3\x0a\x66\xa0\x3b\x62\x76\x0a\x7d\x98\x35\x84\x01\x56\x4c\xdf\x39\xf6\xd1\x98\xa3\xfc\x5f\x3d\x40\xc0\xd5\x62\x77\xec\xbd\x63\x64\x77\x06\xd1\xa9\x7b\xa6\xda\x75\x97\xda\x50\xf2\xab\x9e\xc1\xeb\xa6\x4e\x0d\x35\xcb\xb0\x4d\x01\x88\xee\xe9\xdd\x89\x14\xa8\x94\x89\xf8\xc8\xe5\x2b\xd7\x64\x48\xa7\x14\xf1\xe1\x12\xf8\xfe\xf6\xca\xdf\xd3\xe3\xe7\xe1\x1c\x8a\xb6\x9e\x7a\xd0\x38\xb0\x13\xc6\xca\x87\x83\xd5\x0d\x91\x4d\xee\x31\x54\x2a\xa9\xd9\x16\xbe\xc5\x1b\x6c\xb8\xf2\x76\xbf\xd9\x76\x25\xfa\x50\xb9\xf3\xdb\x2d\x65\x98\xde\xe2\x36\x9a\x60\x55\x83\xde\x69\x88\xac\x1e\xd9\xab\x9f\xbe\x14\x5b\x4c\x9e\xd4\x88\x71\x16\x8d\xdb\x79\xeb\x77\xe7\x4c\xfc\x3d\x77\xf6\xd6\xca\x7e\x5a\xd3\x15\x01\xbf\x84\x30\x0c\x1d\x0a\xbd\x04\x9d\x44\xbf\x7a\x75\xf1\x6a\xa1\xdf\xea\x47\x05\x26\x57\x3d\x18\x01\xf3\xe8\x04\x76\x63\xa5\x6a\xd1\x6c\xec\x26\x75\xd8\xf2\x96\x63\xd4\x15\x93\xe8\x77\x50\xea\x38\x75\xe5\xe6\x3d\x1c\x67\x48\xa1\x54\x2b\x4f\xe2\x00\xec\xfd\x78\x0a\x96\x8b\xa2\x66\xe0\xad\x9f\x9f\xf2\x83\xb1\x95\x75\x12\xa6\x52\xb0\xa2\xda\x6f\x67\xf9\x12\x92\xed\x5a\x22\x5e\xd1\x4d\xbc\xb3\x8b\x16\xde\x41\xd9\xc9\x7e\x1d\xf4\x71\xc0\x32\x3c\x94\x65\x3c\xd0\xf0\xab\x2f\x09\x33\x9b\xae\x8a\xcf\xbe\x4c\xd3\xa3\x37\xe8\xbf\x8d\x33\xc0\x98\x24\x56\x97\x33\xa9\x38\xb0\x6f\x8c\x7c\x52\x3d\x86\x0f\x8c\x15\x63\xa8\xfa\xa2\x6f\x98\x86\x1a\x02\x89\xbe\xff\x95\x7c\xbf\x57\x70\x09\x63\x91\xf5\xf1\xa3\xfb\x6b\xc8\x0c\x6a\xd7\x1b\x51\x6e\x04\xad\xdf\xd4\x4f\x7c\x65\x31\x5f\x56\xc0\x5c\x6c\xfa\x29\xd0\xa3\xaf\x92\x36\x72\x68\x37\x77\x16\x0f\xfa\xea\x29\x1b\x52\x1d\xc9\xbe\x75\x1f\xf1\xd1\x5f\xf1\x67\xb0\x08\x56\x07\x71\x4b\x66\x4d\x52\xd1\x62\x0d\xdb\xd2\xe5\x2d\xb2\x3d\x66\xb0\xc9\xf4\x61\x43\xd1\x6d\x35\x5b\x30\xc5\xa3\x87\xa8\xbf\x21\xc3\x98\xbf\x29\x3f\x20\x8a\x4b\x86\x7e\x2c\x6d\xa0\x93\x79\x8c\x5e\xa1\x1b\x79\xe7\x01\xeb\x03\xad\x21\xe5\x20\xbe\xb7\x45\xfe\x1b\x3e\x7f\xcb\x66\xe2\xf8\xdb\x95\x62\xb4\x8c\x55\x9c\xbf\xf4\xef\xe9\x23\x16\x72\x19\xb6\xd9\xdf\xc4\xd2\x5b\xba\x42\x53\xd7\x49\x2f\x9d\xc0\x8e\x30\xe2\x3d\x7f\x1c\xbe\x0f\x52\xb8\x5b\x69\x78\xe4\x97\x0f\x4e\x67\x2e\xd8\x19\x54\xdd\xb9\x3a\x41\xce\x11\xb7\x30\xdb\x28\xa3\x9c\x3d\xd6\xe3\xa0\xaf\xd8\xcf\x1e\x98\x29\x37\x67\xed\x6b\xe9\xb5\x32\x45\xcf\x71\x4a\x5e\x97\xe7\xdc\x91\x0f\x1a\xff\xf4\xb8\x57\xcf\x57\x94\x9f\xac\x7e\xbe\xfe\x2a\x85\xd8\xcc\x14\x1b\x25\xfa\x8f\x1d\x98\x5f\x37\x6a\xe0\x76\xdd\x44\x12\x3a\xcd\x1b\xe2\x2a\x96\x93\x03\xb6\x23\x8a\xba\x44\x62\xba\x3e\x23\x90\xd4\x21\x3a\x7c\x7b\x90\xec\x98\x4c\x3b\xeb\x01\x35\x8f\xb3\x94\x37\x91\xac\x49\xfe\x07\xff\xc1\x64\xff\x1d\x98\xf2\x38\x93\xe4\xed\x9b\x1a\x22\x92\xdf\x21\x84\x43\x3e\x73\xdc\x59\x66\xf2\x8d\x55\x2c\x58\x6c\xfe\xd7\x4a\x75\x96\xf7\x8a\x24\x94\x09\xed\xc4\x36\xc3\xdb\xec\x69\xec\xca\x4c\xa1\x0a\x72\x42\x5c\x22\xdf\xc1\xd4\xbf\xd9\x7a\xec\x5f\xa1\xb5\x85\xb1\xbf\x37\xa0\x53\xef\x24\xa6\xa9\xaf\x3e\xca\x53\x2a\x03\x47\x6e\x26\x50\x0c\xed\xf5\x83\x1d\xbc\xbc\x15\x70\x4d\x3a\xf5\x64\xeb\x95\xaa\x39\xb8\xed\x08\x4b\x5f\x8c\x9e\x80\x20\x3e\x72\x02\x2a\x45\x41\xa9\x38\x44\x9b\xc3\x4a\xad\x5e\x59\x79\xa0\xd7\xca\xa7\xda\x0d\x8a\x9f\x41\x26\x0a\x18\xa7\x27\x1b\x63\x65\x97\x8f\x3b\x7f\x4e\x00\x4f\x66\xd9\x79\xd3\xf0\xa3\x65\xf9\x27\x7f\xb4\xef\xfc\x19\x1f\xac\xc4\x7e\xb0\x4c\xc6\x83\xcd\xee\x1f\x37\x30\xdd\x92\x3a\x88\x2f\x27\x1e\x71\x23\x02\xe7\xf6\x3e\x7a\x9a\x9b\x8d\x64\x38\x46\xb3\x74\xbf\xc9\x8d\x28\xea\x7b\x1e\xfe\x58\x2c\x57\xfe\x99\x8a\x9d\xc3\x57\xd7\x74\x09\xf4\x39\xf5\xa3\xc3\x07\xa7\xef\x4c\xb5\x3b\x25\x0f\xa4\xa6\x67\xa8\xbc\x3f\xba\x4c\xd6\x7e\xe9\x1c\x7d\x2f\xd0\xec\x2a\xbd\x88\x09\x98\x7b\xf0\xef\x70\x22\x6b\x67\x50\xf6\x62\x22\x76\xf1\xa5\x9e\xfa\x41\xc7\x41\x12\x4a\x9b\x2f\xd0\xab\x57\x89\x2d\x1f\xcc\x49\x88\x77\x98\x75\xc8\x42\x9c\x33\x8a\xba\xa5\xe1\x1f\xf1\xa0\x81\x9d\xf8\x78\x59\x7d\xcb\x5c\x2e\xac\x9a\x36\xfb\xa0\x69\xbb\x9b\x98\xe2\x8d\x3c\x20\xf3\x36\x57\xfe\x51\x6e\x77\xdf\xea\xf1\xe5\x4b\x92\x8b\x52\x99\x7d\x7f\x79\x2b\x8b\xf7\x07\xa5\x97\x18\x40\x1d\x23\x5f\x0a\x90\xf3\xac\xfc\x2f\xc3\x1e\x04\x1b\x8d\xa1\x1f\x88\xc6\xe9\x32\x44\xf2\xe8\xf3\x5c\xdc\x1c\x0d\x8b\xa3\x73\xb7\x31\x52\x15\x34\xc1\x33\x49\x2d\xd1\x7e\x88\x46\xe7\x9f\x7b\x9f\xe9\xf8\x9e\x5e\xd8\x01\xed\x4f\x71\xf1\x36\xa2\xc5\x43\xee\x10\xba\xc3\xe6\xea\x12\x3a\xa8\x61\x8a\xa0\xcf\x32\x2a\x3f\x76\xcd\x16\x5d\xae\xf4\x20\x10\xf3\x74\x3e\x0e\x49\xc6\xa3\x77\x38\xbe\x78\x47\x5c\x36\x1c\x30\xce\x12\xcb\xed\x62\xeb\x99\x81\x57\x56\xc2\x46\x97\xcb\xdd\x16\x11\xf7\xf2\x96\xed\xc5\x5b\x86\xe7\xd4\xdb\xb1\x89\x36\xe1\x31\x87\x95\xd5\xee\x38\x11\x2a\x6c\x8c\x4f\xdd\xd6\xae\x7f\x7c\x3a\x91\xf5\xc0\xd7\xa0\xa7\x07\x9a\xa9\xee\x97\xdc\xa7\x53\xfd\x86\x3b\xd9\xb0\xfe\x8e\xe9\x3e\x1c\x6c\x34\xa7\xde\x68\x08\x5b\xf7\xaa\x3b\x0a\x9a\xd3\x3d\xc8\x83\xa3\x5d\x32\xee\xfd\x61\x66\xd4\x1d\xc2\x34\x7d\x4e\x10\xfd\x6b\x2c\xce\x15\x63\xe3\x30\xd3\xdf\x03\x8c\x78\x17\x94\x0c\xad\xe9\xbc\x83\x91\xb6\x51\x77\x47\x8f\xd6\x7f\x18\xab\xd9\x31\xf7\x38\xfb\x35\xf4\x03\xfc\xb4\x72\xf5\x85\x03\xd4\xaf\xdd\x21\x65\x99\xfc\x4a\x6b\x38\xf8\xf4\xd8\x0a\xdf\xa8\x86\x1c\x91\x27\xac\x16\x53\xbf\x96\xca\xd5\x4d\x0d\x34\x7b\x93\x8c\xf3\x7a\xf4\xf3\x6c\x99\x8c\xc6\x6f\xe5\x0a\x46\xdf\x10\x08\xf0\xe0\x95\xbb\x1f\x06\xc4\x01\xe8\xd1\xe1\xb5\xda\x9d\xef\x24\xfb\x0c\x9a\x24\xeb\x56\xa1\xab\x5b\xff\xf1\x79\xdf\x6d\x69\xff\x4e\x66\x7d\xf5\xba\x3d\x1b\xdf\x91\xff\x74\xbb\x78\xda\xed\xb2\xc2\x5e\x82\x00\x78\x13\xd1\xcf\x49\x5b\xd5\x42\xb9\x36\x77\x8f\xab\x54\xef\xb0\x5d\x3b\xfa\xa1\x7a\x4e\xd1\x42\xe2\x08\x52\x60\x02\x52\x10\xf5\x49\xa7\x58\x15\x18\x2b\x8b\x7f\x58\xeb\x59\x5a\x4a\xcd\x55\xfe\xc8\xb6\x6e\x90\x00\x85\x2f\x87\x91\x32\x5d\x95\xc5\xfd\x9b\x94\xf4\x8a\x98\x8e\xeb\xef\x6a\x2c\xfa\xe5\x45\x37\x8b\x2e\xb0\x9b\x38\x5d\xef\x26\x5e\x17\x36\x9c\xa5\x94\x7e\x3a\x56\xba\xb3\x6f\x02\xa2\xe5\xdd\x29\x8e\xc4\x72\x2a\x1d\x70\x4f\x7b\x8a\x51\xa1\xb0\x6e\x75\x7f\xcf\xb5\x75\x7f\x1d\xd4\x60\xcb\x34\xf3\xb9\x4a\x57\x55\x86\x9c\x17\x68\x49\xd5\xba\x40\x45\x2e\x7c\x18\x4b\x9d\x21\x10\x81\xd5\x06\x10\xe6\xec\x86\xee\xfa\xd9\x3c\x43\xa2\x29\xdc\x57\xa7\xe5\x71\x39\xab\x07\x73\xaa\x3f\x1a\x8e\x74\xb3\xc3\x74\x23\x3a\xce\xe4\x11\x7c\x8f\x5b\x3f\xaa\xcb\x7e\x3d\x04\x01\xd5\x84\x9f\x2b\x05\xa1\xf2\x0c\xf7\x38\x60\x39\xa2\x04\xdb\x60\x3a\x4e\xc0\x56\xfc\x08\xf0\x65\xfd\x4c\xff\x7b\x68\x15\xb2\xa9\xcb\x66\xb0\x68\x92\x60\xb2\xbd\xf2\xc7\xbc\x4c\xf3\x0f\xf9\xfe\x1f\x59\x4a\x18\x73\xa3\xb4\xb6\xb3\x9e\x8a\x9e\x33\x4c\xad\x9c\x7f\x86\x68\xdb\x3e\xac\xc2\xd1\xdc\x1e\xbe\x52\xca\x5b\x6e\x08\xda\x30\xb2\x12\x38\x8a\xc4\xee\x73\xfa\x62\x22\x3a\x73\xa0\x75\x9a\x67\x73\x12\xa7\x30\xb5\x70\xeb\xa4\xb3\x04\x53\xfb\x51\xf9\x48\x8d\x3d\xd5\x9a\x30\x49\x6c\x36\x07\x9f\x96\x01\xdc\x79\xc4\x26\x8c\x1b\x84\xe4\xb8\x1f\x0b\xb1\xc8\x71\x51\x0c\x51\x84\x55\x7e\x61\x5c\x4e\xb0\xb9\x4a\x22\xfd\x37\xe5\xb7\xb2\x8e\x34\x37\x2c\x2e\x9a\x2c\xac\xab\xec\xd5\x59\x74\x97\xf3\xf2\xd4\x4d\xef\x43\xc7\x8a\x31\xd8\x28\x4b\x86\xd5\x8c\xbb\x3a\xfd\x0d\xeb\x57\xed\xe2\xc1\x49\x64\xbf\x9e\x07\x58\x0d\xdc\x46\x46\x88\x48\x7c\x01\x32\x6b\xe3\x30\x7d\xe0\x94\xa6\x16\xb2\x2f\x1a\xd0\x10\x27\x8b\x35\x9a\xb4\xf2\x8d\x40\x7c\x91\xbd\xe2\x80\x8e\x68\x9d\xea\x54\xd5\xab\xcf\x29\xd1\xe7\xb1\x21\xab\x2f\xc8\x8a\x77\x4f\xd4\x4d\x6a\x78\x99\xa4\xf7\x13\xad\x4b\xf7\xb1\x6b\x3f\xba\xd3\x81\x56\x20\x34\xa6\xa5\x28\xe0\x63\xca\xce\xbf\x26\x0c\x62\x33\x70\x4e\xbe\x7f\x7d\xa4\x49\xba\x55\x64\xb0\xba\x25\x5d\x7e\xa6\x72\x21\x6a\xcc\xd4\x08\x36\x77\x95\xb3\xa4\x1e\xf8\xca\xc2\x56\x32\xdf\xb4\x94\x2d\x27\xfb\xcb\x0b\xb8\x0f\xd1\x2d\x9e\x5a\x67\x81\x81\xab\xd8\xda\xd9\x1a\x8e\xd1\x21\x63\x45\x96\xd2\xf1\x6d\x20\x8d\x6e\xa7\xd3\x67\x53\xc3\x7a\x48\x49\x4a\x8e\x4f\x62\x8e\xd2\x0d\xde\xd1\x50\x0b\xde\x68\xce\xb5\xf3\xc6\xec\xa6\x4f\x29\x38\x6f\x72\xe8\x2a\xd5\x80\xe7\x08\x68\x5c\xc3\x9b\xf4\x53\xb6\x36\xec\x22\xbe\xcf\xae\x93\x97\xf4\x95\xb0\xfa\xce\xf6\x2c\x66\x54\x98\x9d\xac\xdf\xb5\x0b\xf5\xbe\x1e\x08\x7f\x74\x3e\xb9\x8f\x93\x1e\xd1\x9a\xf4\x12\x82\x44\xf6\xe3\x8e\x72\xdc\x02\x86\xd9\x44\xee\x84\xed\x97\x02\x9e\x94\x05\x7d\x5c\x9d\x68\xc9\x65\x39\xc9\xbe\x10\xd9\x61\xf3\xae\x8c\xaf\x91\xeb\xe4\x2b\x97\x42\xdb\xce\xd6\x57\xff\xa5\x7c\x9f\x51\x1e\xd1\x75\xc7\xd3\xce\xcb\x41\xf7\xa6\x3b\x0e\x63\xd8\x4e\xc0\x03\x27\x8c\xde\x99\x44\x5c\x59\xe3\x2f\x63\x51\xb0\x75\x8c\x66\xf6\xd8\x89\x7b\xf4\x4a\x6d\x99\x4f\xdd\x7c\x66\xb4\x11\x97\x5d\xb4\xb6\x69\x22\x7d\x2e\xaf\x7e\x54\x9b\x7a\xca\x2f\x77\xa4\x2f\x23\x46\xe4\x3e\x5d\xfb\x87\xb2\xbb\xe4\xc9\xa9\x83\xe7\xe6\xda\xea\xf8\xd0\x8b\x92\x2d\x6a\x35\x71\xdf\xf2\x16\xc3\x0e\x4f\x1e\xd5\x30\x04\x62\x29\x79\xec\xad\xb4\xb6\x50\xc0\x3a\xf0\xa9\x5c\x03\x7a\x9d\xe0\x47\x46\x17\x5b\xfe\xd8\x59\x3e\x63\xc9\x0d\xca\x23\x0c\x47\x0f\x9a\x1f\x93\xf7\x18\x0a\x80\x23\xaf\xf6\x2c\x86\xf1\x9d\x3b\xe9\x39\xd2\xda\x0e\x6b\x65\x8e\xb1\xb3\xd1\x58\x5f\xa3\x91\xcb\x24\xa0\x5d\xab\xa2\x8b\x75\x1f\x6b\x11\x42\x21\x57\x20\x71\x4c\xc3\x47\xe2\xf6\x55\xa3\xc1\xd3\x05\xf6\xac\xba\x8a\x11\x20\xe1\xb8\x89\x23\x0d\xd4\x3e\x96\xe1\xfe\xb7\x46\x10\x01\x59\x99\x6e\x84\xbe\x8d\x71\xed\x67\xd8\x48\x95\x12\x2b\x5c\xc7\x44\x61\xdb\xcb\xb6\xd4\x59\x52\x73\xb5\x2e\xde\x4f\x37\xb6\x1d\x31\x07\x26\xe6\x41\x03\xab\xaa\xea\x3d\x6b\x19\x1b\xad\x6b\x76\x46\x8f\x7e\x9d\x79\xc6\x52\xa5\x1b\x9d\x5b\x06\x45\x5d\x59\x1a\x08\xa9\x53\xf3\x97\xc6\xde\xb3\xbc\x2b\x60\x68\xa2\x9f\x79\xcf\x91\xe4\xb5\x33\xaa\xc6\x1a\x5b\x71\x71\xeb\x7b\x84\x64\xd5\xfa\xe4\xd9\x05\x14\x7a\xd2\xfe\xe8\x33\xa5\xe8\x6c\x4a\xeb\x35\x05\xc3\xfa\x0d\x3d\x3f\x55\x72\xfc\x2c\x2b\x83\x58\x9a\x47\x4c\x54\x90\x74\xd9\x28\x1b\x74\x17\xfd\x6a\x74\xf1\x76\x1b\x7d\x44\xb0\xa1\x58\x3f\x65\x6c\x75\xee\x19\x2e\x3b\x68\x5a\x2f\x8e\x1c\xdf\x1f\x59\x1a\xb8\xfd\xc1\xff\x38\xaa\x09\x07\x1c\x9a\xfb\x59\xb6\x51\xfd\x5d\x23\x74\x9c\x35\x0a\xda\x16\x32\x5a\x75\xbb\xbd\x2a\xc3\x14\x4e\xbd\xe2\xf1\xc2\x52\x2a\x3e\x5a\x5b\xbf\xbb\x16\xfb\x5c\x3e\xab\x75\xa4\x97\x75\xbe\xa6\x54\x2b\xe9\x4a\x5f\x57\x3a\xfb\x2d\x08\x4a\xb0\xbc\xd8\x8d\xfa\xef\xd8\x39\x38\x7b\xd9\x8f\xdc\x3a\xef\x3a\xcb\xb0\x6c\xb7\x1e\xce\x7e\xa7\xc1\x19\xf7\x0c\xf0\xd8\x1b\x83\x5c\x4a\x1a\x0c\xfb\x74\xdd\xcd\x0e\x67\x7a\x53\xa5\x70\x8c\xfc\xac\xb7\x3d\x90\xcb\xf6\xef\xf0\x6b\x6f\x41\x05\x64\x5e\x73\xb4\xc7\xa7\xbb\x0c\xbd\x18\x15\x13\xfe\xe3\xc1\xf4\xa2\xd2\xaf\x52\x51\xfb\x4a\x1d\x25\x15\xf5\x52\x4e\x94\x3b\xf2\x52\x55\xbf\x5f\x8b\x20\x2d\xc0\xbe\x1a\xe7\x79\xed\xc3\x25\x8d\x5c\x62\x8f\x86\x7c\x8c\x61\xa5\x26\x65\xb1\xc6\x12\x13\x1f\xee\xae\x43\xb1\x2f\x9a\x07\xca\x93\x39\x44\xc4\x15\x56\x42\x83\x80\xe7\x2e\x58\xab\x74\x3a\xdd\x7d\x30\x94\x3a\xb3\xf6\xc8\x23\x38\x6b\xeb\x6b\x10\xd5\x96\xde\x0f\x7f\x74\x80\xc2\x68\xe2\xba\x19\x8e\xa6\x47\x92\x6a\x38\x82\x3f\xd7\x33\xca\x59\x78\xa8\x9d\xaa\xdc\xca\x10\xf4\xb0\xb0\x04\x5e\x25\xc6\x5c\xcf\x46\x8d\x63\x36\xc7\x2f\x1f\x0b\x70\xde\xec\x58\xa6\x76\x2c\x16\xae\x3a\x88\xc6\x33\x93\xbe\xdc\x0c\x82\xaf\x9a\x04\x3f\x3a\xa0\x4d\x61\x65\xb6\x4e\x22\xc3\xda\x71\x38\x48\xad\x9b\x1a\xd2\xe3\xee\xee\x7b\x4e\x81\x13\x82\xcf\xea\x46\xb0\xc8\x0c\xbe\x5b\x72\xc9\xc0\xae\x7c\xe8\x4f\x5d\xf6\xb8\xd6\x14\xbb\x39\xad\xa7\x2f\x47\xae\x94\x1d\x07\x2e\x45\x12\xf5\x30\x7c\xdc\x6c\xfe\xc0\x47\xbd\xd7\x30\x8b\x29\x0e\x8c\x9d\x96\xe4\x21\x63\xf6\xee\x02\x2a\xc8\x40\x0f\x12\x35\x8a\xe5\xa6\x47\x9e\x82\x67\x7f\x74\xa9\x1f\x89\x5d\x33\x0c\xef\x53\x84\x2f\xe4\x6d\x80\x43\xac\x89\xad\x33\x43\x4f\xf3\x0f\xcd\xd1\x15\x1c\x66\x7f\xb6\xae\xd3\xac\x6f\x4f\x35\x3d\xf7\xdf\x43\x5e\x99\xf9\x5f\xd9\x0f\x8d\x62\xa0\xe6\xe0\x0e\x2d\xd9\x61\x3c\x26\xb5\xb2\x2d\x3d\xd6\x38\x22\x92\x5a\x49\x3e\xbb\x39\xb4\x5a\x3d\x6a\xf4\xdd\xad\x80\x3e\xcb\xd7\x12\x5f\x2b\xbc\x33\xca\x6e\x20\x0c\xd9\xfa\x8d\x73\x19\x5a\xdb\xd5\x88\x60\x49\xaf\x71\xb8\xf4\x96\x0b\x74\xec\x3e\x55\x17\x6d\xca\x96\x04\xce\x34\xdb\x60\x30\x0c\xd3\x93\x16\xe4\x37\xb2\xeb\xbf\x40\x64\xc9\x6e\x70\xa9\xdc\xd8\xc9\x99\xcb\x2c\x91\x1d\x1c\x3a\x9f\x53\x6c\xa4\x69\x74\x87\xad\x81\xd9\xb3\x4a\xd2\x92\xed\xdb\x3d\x96\xaa\x99\x61\x10\x1c\x2c\x4c\x3a\x8b\xc6\x73\x56\x50\x20\xf3\xb0\x63\x72\x28\x07\xdb\x57\x64\xda\x2e\x03\x19\x8e\xe1\x46\x28\xc9\x36\x5d\xe0\xf5\xd4\xa5\xd4\xd5\x76\x84\x9b\xc6\xf0\x89\x8f\xa4\xb5\x5d\x07\x7d\x6c\x33\x67\x82\x73\xd5\x9a\x6d\x06\x43\x6d\x52\xe6\xd0\x4d\xec\xdb\xf2\x5e\xcb\xc9\x66\xf1\xb8\xe2\x0b\xa9\xee\xe6\x31\x3e\xcf\x52\x09\xb5\x07\x1b\x08\xbd\x0f\xca\x4f\x9d\x44\xb9\xa5\xc3\x28\xf9\xa4\x33\x1c\x69\xc4\xa8\xdd\x3e\x7a\x5c\x99\x9e\xfd\xf4\x32\x39\xb5\xca\xf0\xfe\xf1\xe6\x01\x16\xed\xca\xe4\xc2\xa8\x0d\x12\x6d\x79\x3f\xb3\x5c\xeb\xdf\x4e\x5e\xcb\xfa\xcd\x85\x5a\xe9\xbd\xa1\x97\xb4\xc4\x40\xeb\xdc\x84\x1e\xec\x32\xf7\x1f\x27\xbb\xcd\xfd\xf4\x65\x49\x47\xe7\xfa\x3e\x60\x74\xd0\xd5\xd5\x00\xef\xd3\xaa\xee\xf6\x6f\x9c\x32\x53\x3a\xa2\x0d\xae\xa0\x07\x88\xee\xd6\x6c\x5e\x2d\xa5\xbf\xdc\xee\x4d\xa9\xf9\xa0\x87\x8b\xef\x0c\xa6\x2e\x9e\xc3\x63\xbd\x7c\xf6\x83\x6f\xd4\x27\x7b\x26\x88\x82\xb8\x76\xfc\x04\x3e\xf0\x73\x76\xf8\x21\x7e\xb2\x4e\x9c\x9f\xbe\x6c\x11\xed\xe8\x8b\xd6\xb6\x33\x39\xca\xec\xc3\xfe\xae\xa4\xe5\x37\xf7\xac\x97\xe8\x46\xef\xe7\x57\x32\x9c\xa8\x66\xe3\xd7\xb4\x34\x2e\x5c\x7d\x3c\x0e\x5d\x2a\x05\x82\xb3\x3e\x14\xda\xdc\x7a\xf6\x1d\x04\xeb\x6a\xb2\x8f\x8e\xb3\xdb\x5a\x38\x9a\x42\x4d\x39\xc2\x3f\xa9\xdf\xcd\x02\x86\xbc\x35\x34\x5b\x0c\x12\xdf\xaf\x94\x33\x1c\xcb\x70\x1b\x1e\x24\xc4\x80\xd1\xc9\xae\xad\x8f\xb1\x7c\x9b\x0b\xf7\xd3\x8f\xcf\xba\x38\x42\xb8\x0c\xcd\xd3\xe5\x0f\xcc\xb6\xb5\x5a\xd4\xe0\x24\x44\xff\xad\x1c\xa1\x17\xa0\x37\xfb\x70\xa8\x08\x8c\x4c\x6a\xeb\x7a\xae\xf9\xfb\x60\x10\x84\xcc\x5a\x63\xcd\x98\x8f\x71\x2b\xfb\x91\x72\x79\x4f\x7e\xd8\xa0\x18\x36\xfd\x73\x65\xf6\x16\xa3\x12\x96\x76\xee\x42\xc3\xc9\x8e\x33\x86\x4f\x83\xa0\x0a\x96\x43\xd6\x09\xf8\x3c\x65\x66\x4b\x73\x6d\x4c\x9b\x82\xfb\x79\x78\xae\x40\x47\x3a\x9a\xd5\x69\x91\x5e\x98\xcd\x68\x34\xaf\xf8\x60\x80\x41\xce\x44\xcf\xea\x48\x0c\x48\xf1\xe0\xbf\x3a\x31\xb9\xff\xa3\x61\x2b\xba\xfe\x30\x65\x39\x1d\x0d\x63\xde\xb8\xfb\xc1\x65\x35\xba\xb5\x3e\xf4\xf6\x4c\x02\x6d\xe4\xa0\x63\xd2\x90\x6c\x62\x31\x04\x97\x63\x08\x06\xf2\x7d\xe3\x5c\x11\x81\xe9\x6e\xda\xc3\x02\x0f\xaa\xc3\x67\x68\xc5\xab\xf8\xe9\x9e\x7f\x0d\xec\xdc\xc9\xa4\xab\xc2\xf3\xec\x70\x51\x90\x7d\x0f\xc9\x81\x80\xc3\x1b\xfa\xbf\xe7\x89\x56\x8e\x37\x3a\xe5\xe5\xad\x76\x35\xee\x91\xf8\x7c\x9f\x42\xfe\x7a\x07\x61\xd1\x3d\xe8\x89\xe4\x5e\x8d\xb4\x4f\xbf\x43\xcb\xef\x86\xf4\xd6\xdf\x0d\xfb\xdf\xd5\xf7\xe5\xb0\x0a\xcb\x3f\x3a\x6a\xb5\x9d\xb9\x63\x91\x18\x4e\x09\xcb\xa7\xc9\x5e\x22\xf7\xcb\x46\xbc\x0c\xc3\x3d\xef\xd7\xfe\xcc\xea\x1d\xff\xd6\x8e\x33\x01\x68\x11\x8a\xed\x1a\xe7\x8e\x74\x74\xaa\x5b\x53\xe7\xb0\x2d\xa4\xef\xd6\x20\x85\x07\x36\x27\xbc\xe2\xfb\x52\xce\xc6\x96\xbf\x17\x06\xab\x66\x35\xe2\x06\x82\x6a\xbc\xc9\xb8\xa2\xcc\x77\xa7\xee\xea\x67\x19\xf2\xad\xd2\x35\x4a\xaa\x8e\x01\x30\x2d\xbe\x94\x43\xfc\xf4\x5a\xda\x6d\x44\x86\xbb\xde\x90\xd5\x94\x7d\x6d\xbc\x77\x7e\xd1\xb2\xf1\x0a\xc6\xb1\xd4\xde\xe7\x1c\xea\x00\x24\xc8\xcd\x31\xcc\xd5\x76\x13\xe6\x7e\x7d\xcd\xfb\x83\x87\x56\x97\x5d\x52\x60\x60\xd1\x7a\x7b\x98\x3c\x8d\x4e\x34\x5a\x6a\x35\xc0\x60\xfd\xea\x51\xaf\xe7\x51\xe9\xc7\x92\x14\xf9\x29\x5d\x72\xbc\x5f\xf9\xfd\xd6\x29\x38\xc5\x65\x81\xed\xa2\x29\x8d\x30\x06\x0d\x19\x8a\x6f\x6f\xbf\xa3\x82\x79\x04\x47\xb6\xaf\x70\xbf\xd1\x1d\xe6\x7b\x64\xd9\x81\x5e\x3c\x57\x4b\x29\x51\x8c\xd5\x69\x7e\x2f\xb5\xe5\xec\x10\x3f\x5c\x11\x2f\x36\x17\xca\x3b\xf3\x59\xd7\x4a\x19\xd9\x02\x97\xea\x4c\xce\xdd\x2c\xaa\x77\x9c\xfc\x2f\x87\xa5\x46\x73\xe3\x78\x8b\x56\x73\xbf\x8a\xae\x5c\x7f\x10\x84\xfd\xf5\xba\x7d\x9b\x57\xfc\xea\x2b\x1b\x79\x9d\x42\x45\x6e\x49\x2b\x79\xc9\x60\xd7\x74\xb5\x25\xbd\xd5\xed\x5a\x39\x78\xce\x29\xc2\x00\x68\x43\x1d\x1e\x73\x6d\xce\x47\x64\x29\xe4\x35\x5a\xd5\xca\xda\x89\xe6\xf3\x95\xdd\x2c\x6e\xf3\xfa\xc5\x6c\x3e\xe7\x10\xbc\x73\xe5\xf9\x4f\xda\xfd\xe6\xee\xf6\xfe\xe5\x43\xc8\x83\x78\xe1\x72\x8e\x46\x6f\x7c\x60\x0c\xac\x85\xe5\xe8\x66\x83\x2c\xe2\x96\xbb\x0e\x3d\x82\x29\xe3\x1e\x63\x8b\xa8\x2f\x76\x80\x7d\x00\x70\x98\xa6\x5b\xf4\xc2\xe3\x31\x7d\xa5\xfe\x58\x68\xaf\x3f\x4c\xd3\xe8\xd4\x7c\x58\x5d\xee\x75\x74\x23\x73\x9a\x53\x44\xb9\xcd\x62\x1c\xb4\x20\x2c\x04\x69\x19\xe3\x11\x27\xd2\xae\x23\x65\x85\xb2\x55\xee\xdf\x07\x6c\x48\x7f\xaa\x11\x89\xa6\xda\x69\xa1\xb0\x50\x0e\x44\xa9\xdf\x6a\xf3\x3b\x18\xd4\x6e\x6f\x97\xeb\x5d\x1f\x27\x1d\xfb\xd3\xe1\x22\xad\xae\x78\xda\x25\xae\xd8\x3c\xf9\x01\x69\xf2\xb9\x97\x82\x81\xd6\x3a\x1d\x15\x3a\xff\xc8\xe3\xdf\xe8\xdd\xe5\x9d\x34\x0e\xaf\x70\xc4\x6e\x54\xab\x7d\xb3\xf1\xe2\x0a\x8b\x3e\xcb\xfc\x57\x5a\x74\x87\x2b\x40\x52\x83\xa9\x81\xa0\x92\x8e\x87\x27\xac\xd3\xd5\xfc\x3e\x1d\x85\x5d\x0a\xcf\x10\xc8\x9f\x6e\xaa\x93\x08\xaa\x07\xd9\x51\x91\x49\x74\xb7\x2f\x17\x00\xde\x0b\x02\x77\xaf\x41\xfb\x84\x29\xb3\x38\xdc\x8a\x5a\x84\x89\xe3\xc7\x03\x75\xc1\xc1\xc6\x05\xdb\xff\x14\x12\x0d\x62\x77\xea\xc4\x04\x4f\xd1\xf4\x6c\xa4\xa2\xbc\xd1\x12\x60\xd0\x64\xda\xe4\xa9\xbc\xd7\xd7\x48\xc1\xfe\x54\x36\x2d\x8a\x8a\x80\x4d\xc0\x5c\xf9\x09\x71\xe4\x61\xb7\x47\xea\x34\x3d\x22\xd5\xf7\x68\x62\x93\xc9\xf6\x3d\xb3\xc3\x6f\xff\x67\xbb\x48\xbf\x0a\x8a\x3c\x6d\x4a\x1b\xb8\x4b\x54\x77\x03\x24\x45\x0f\x5e\xa6\xcb\x06\x75\x3c\x44\xd3\x83\xbb\x00\xef\x4a\xe1\xb7\xd5\xf8\xb7\xb4\x89\x40\xbd\xd3\x91\x90\x69\x79\x46\x2f\x19\xcb\x98\x9b\xfb\x8d\x6f\xd4\xc8\x4b\x60\x14\x89\x40\x5e\x46\x4a\xbf\x51\xe8\x22\xd2\x98\x35\x33\x27\x9a\xf4\xe6\x39\xf2\x17\x69\x30\x60\xba\x34\xb8\x79\xe6\x59\x6f\x65\xb9\x11\xc6\x08\xab\x81\xa1\xef\x84\xb8\xa0\x10\x3d\xb2\x3e\x02\xe3\xbd\xf8\x8f\x2d\x9f\xf2\xee\xc8\xe3\x2e\x95\xc4\x27\x7a\xe7\x4b\x3f\x3b\x08\x52\x1e\x01\x4b\x1a\x44\x05\x57\xcf\x26\x4d\x83\xc5\xd9\xe2\x7c\xd7\x91\xf3\x25\x47\x43\x02\xe3\x5c\x4b\x40\x03\xb4\xe9\xc1\x05\xc8\x66\x94\x6a\xf9\x77\x61\x24\x0b\xfa\xb7\x7c\x0a\x20\xc7\x94\x0f\x6c\x4a\xb0\xfb\xd3\x80\xfb\xb3\x3f\x55\xbb\x9f\x3c\x20\xd9\xf8\xc6\x56\x3d\xef\x71\xa0\x86\x3a\xe3\xdb\x18\x28\x0b\x86\x61\x34\x90\x25\xac\x87\x3b\x89\xe7\x99\x52\x6b\x07\x45\x7c\x34\xd3\x02\x1a\x4d\x3e\xea\x91\xf3\x1a\xbd\xfb\xb1\xfa\x5a\xca\x68\x0f\xdd\xfc\x2b\x56\x92\xd4\x72\xb3\xc8\xd3\x9f\x98\xe6\x69\x57\x62\xc7\xa8\xc6\xf6\x4b\x8c\x97\xd7\xb8\x29\x15\xf4\xa5\x3e\xd8\xcb\x65\xd5\x8b\xe9\x3f\x11\x3b\x69\x8f\x13\x0a\xd4\x1a\x19\x28\xf0\x3b\xe2\x2b\xa0\x29\x11\x9e\x97\xe5\xaa\xd2\xe9\xf9\x4a\xe4\x33\x68\xd8\x56\x9f\xe2\xb3\xac\x87\x6c\xb0\xaf\x91\x1c\x75\xa2\x25\x23\x5b\x4b\x27\x88\xb8\xbb\x0e\xd2\x5a\xe7\x4d\xe1\xb9\xa0\xcd\x55\x2e\x83\x38\xec\xd0\x56\x79\x7e\xd1\xc8\x01\x0f\xdf\xc4\x10\x97\x91\x73\xd9\x70\x96\x53\x6b\x11\x47\x93\x2e\xe6\x6c\x8e\x33\x1c\x37\x48\xdf\xb0\xee\x4b\x37\x37\xd7\x3f\x13\xde\x73\x3d\x5c\x23\x29\xe5\xc8\x1f\x77\xd8\xdf\x4b\xcd\xf1\x40\xbf\x84\xb7\xee\xa5\xcb\x71\xc0\xf6\x9a\x8f\x8f\x7d\xd6\x11\x4e\x49\xcb\x84\x4c\x43\xe7\xe3\xa1\xa8\xca\x87\xaa\xaa\x5b\xf5\xbe\xdc\x39\x2c\x05\xfe\xe6\x56\x7c\x7a\x9b\xff\x5d\x79\xe3\x65\x45\xe3\x9f\x80\x8c\x23\x71\xf5\xe6\x36\x3c\x2e\xbd\xa8\x70\x8e\x74\xfe\x63\x13\xf6\x28\x53\xf8\xad\x76\xe5\xdd\x77\x37\x33\xf1\x80\x45\xfa\x16\x1d\xfa\xfb\x5d\xe2\x85\x43\xab\xd7\x11\xb6\x59\x7b\x59\x1d\xd0\xba\xe6\x90\xae\xcd\x5c\x62\x14\x08\xa2\x41\x99\x73\x0e\x77\x10\xf6\x77\xa2\xe1\x71\xb9\x95\xfb\x01\x6c\x14\xa2\x1f\x54\xb6\x64\xf7\x2f\xe3\x84\x77\x0e\xa3\x04\x78\xf2\xeb\xee\x59\x91\x9d\x80\x00\x4c\x65\x03\x53\xfd\x9c\x22\x34\x44\xd9\xab\x7a\x6c\xb3\xe6\x5e\x15\xe0\x7e\xd0\x46\x8c\x23\x89\xca\x77\x70\x28\xcb\x1a\x21\x98\xb7\x6c\x5f\xde\x6e\xf6\xf7\xeb\xea\x74\x90\x1e\x0d\xb1\xf0\xe8\x3c\x22\xd4\x11\x7c\xe3\xca\x3e\xa0\xc3\x85\x5a\xc1\xe8\x01\x71\xb0\x8e\xad\xb2\x20\x30\xe2\x4d\xa4\x01\xee\x19\xd5\xa0\x1a\xdd\x65\xa8\xe7\x41\xbf\xab\xcf\x96\x43\x8e\xbf\x2f\x24\x0a\x95\xc5\xd4\x35\xe6\xbe\x5c\x19\x6f\xbb\x1a\x42\x3e\x80\x2b\x38\x6f\xe3\xab\x9a\x52\xd8\x84\x5f\xb2\x1e\x74\xf9\x6b\xb0\xc7\xc8\x6d\x8e\xde\xfd\x48\xd9\xb1\x47\xa6\x11\xed\xe6\x5d\x95\x8f\x6b\x87\xcf\x0e\xfa\xd5\x37\x87\xa1\x51\xd8\x1f\xe7\x12\xa6\x0e\x5b\x45\x58\xca\xa3\x9a\xf1\x4f\x23\x13\x19\xca\x28\xc7\x6c\x56\xde\x18\x7e\xb6\x80\x06\x70\x42\x20\x0e\xa2\x66\x83\x46\xa3\x7b\x67\x7b\xb5\xef\xd5\xfd\x60\x07\x3b\xc2\x48\x7a\x65\xa3\xef\x7d\xe5\x77\xec\x2d\x5b\xc0\x88\x9e\xd2\xd1\xdc\x28\xeb\x9e\x5d\xd9\x26\x90\x82\xde\x6e\xa4\xb0\x71\xea\x36\x73\xe6\xcb\x8e\xa4\xec\xfd\xfd\x90\xa4\xcc\xd3\xd6\xa7\x65\x3a\xdb\x80\x0e\xbe\x4c\x03\xe9\x05\x6a\x3a\x7d\xd7\x45\xff\xbc\xec\x07\xbd\x90\x60\xb8\xb9\x18\xdf\x90\x01\xe8\x07\x88\x83\xe7\xa0\xd1\xd3\x41\x01\xdb\xfe\x12\x51\xde\xdc\xf7\xd9\xcb\xf5\x86\x22\xc4\xd8\xc1\xa3\xe7\x4c\x8d\x24\x8f\xb0\xa1\xd8\xc3\x85\x0b\xdd\xfd\xe5\xb8\xc6\x5c\x18\xc5\x61\x47\x2b\x39\x87\x81\xc5\xa3\x9e\x12\x18\xb3\x7f\x52\xc1\x83\x01\x42\xee\xda\x8e\x1f\xc6\x6a\x03\x18\xa6\x9f\x7a\x58\x6f\x72\xdf\x76\x31\xe2\x5b\x9c\xb8\x6d\xfd\xe7\x9b\x51\xfa\x33\x52\xdc\xb3\x99\xec\x6b\x50\xdb\xa7\xf5\x11\x4d\x7c\x86\x8f\x6a\x1c\x1a\xa1\xcd\x57\x61\xb9\x84\x42\x30\xb7\x7e\x26\xfa\x9a\xad\x60\x2e\xab\xbf\x0f\x9a\xe4\x4b\x4d\xff\xe0\x35\xab\x97\x4f\x5f\x35\xb6\xf6\xcb\xd7\x6f\xd7\x89\x1c\xa1\x6b\x1e\xda\xff\xc1\xbd\xfe\xca\x75\x47\x07\xe9\xcb\x6a\x74\xa8\x16\x9c\x20\xb5\xeb\xc6\x91\x16\x80\xf8\xdc\x4c\x06\x95\x3d\xee\x54\x7a\x69\xb0\xd3\x3f\xa3\x20\x01\x14\xfa\x3c\x67\x4c\x48\xdf\x2b\x39\x6a\xcd\x33\x26\x65\x97\xfb\x6b\x9e\x06\xd9\x04\xac\x13\xa6\xb4\x78\xa5\xa9\x02\x57\x18\xd6\x3b\x11\xfe\xe0\x8e\x3d\x7a\x85\xfa\xa8\xe5\x2a\xff\xe7\x01\x39\x48\xeb\x23\x1f\x4a\xda\xae\xb9\xa9\xe3\x14\xc1\x08\x38\x44\x8c\x2d\x3f\xaf\x04\x25\x91\xd4\x22\xb8\x61\xd7\x78\x25\x76\xe0\xaf\xa9\xdf\x6c\x74\x3a\xe2\x35\x93\x9f\x8b\x10\x0b\xbd\x1e\x0d\x50\xb3\x86\x91\xbc\xda\xdb\x63\xa3\xb7\x1f\x47\x37\x0e\xea\x39\xac\x65\x95\xb5\x6d\x47\xd9\x4d\x23\x7f\x92\x4c\xfa\xb2\x07\x5c\x8c\x6e\x01\x63\x90\xb9\xc0\x9a\x7e\x94\x99\xb3\x26\x77\xbf\xe1\x66\x7c\xd7\xd2\x59\x96\x5a\x4c\x35\xd5\x7e\xc3\xe0\xc1\x79\xc0\x8f\xd8\xee\x1a\x2b\x7c\x71\xf0\xe6\xf3\x53\x2f\x44\x2b\x09\x2c\xec\x36\xc9\x38\x8f\x3d\xf3\x36\x45\x52\xcb\x69\xf3\x0c\x73\xdf\x49\x7d\xe4\x66\x4e\x43\x61\x08\xf4\x5c\x00\x4e\xa6\x0b\x67\x81\xbb\x27\x6f\xa1\x88\xd6\x2b\x97\x75\xfb\xa3\x5b\xc1\x16\xa3\x94\x75\xf0\xd9\x20\x29\x92\xe3\x17\xda\xa4\xb2\x6e\x05\x01\x7b\x33\x26\x11\x19\xb3\x08\x7c\x7d\x1b\xb5\x18\x4a\x29\xd0\xeb\x91\xed\xe6\x4a\x6f\xe9\x1b\x79\x5d\x07\x46\xa1\xf7\x5c\x49\xf8\xa3\xd0\x89\x52\x45\x2b\x4d\x67\xfe\x4c\xf6\x7e\x75\xa7\x9d\xd7\x94\x3a\x52\xf0\xdc\x7d\x5d\x30\x87\xb3\x64\x38\xa2\xc1\xdf\xf8\x67\x54\x22\x62\xfc\x71\x30\xaf\x72\x7a\xdd\x15\x12\x12\x98\x03\x55\xc7\xeb\xc5\xa6\x5f\xc6\xe8\x08\xcc\xe3\xf3\xa9\xac\x99\xf2\x21\x71\x02\xe9\x1f\x83\x65\x6a\xd9\x7e\xcc\xfa\x4b\xc3\xcc\xaf\x99\x4a\x74\x0c\x40\x35\xe2\x5f\xb0\x08\xce\x35\xce\x26\xed\x42\x4d\xd2\xc6\x52\xee\x76\x39\xc4\xda\xee\x35\x3d\x93\x30\x81\x2e\x0d\x09\x93\x3d\x0e\xfe\x11\xd4\x98\xce\x3f\x19\xd5\x83\xf9\x6c\x9e\x3c\xbc\x23\x36\xfb\x2f\x94\xca\xfc\xc5\xdf\x05\xe9\xb6\x68\x42\xee\x1c\xc7\xb5\xf8\x9f\x4c\x0b\x39\x68\xf0\xca\x29\x8f\xa3\xd7\xec\xd4\xc3\x7d\xc5\x10\xc0\x5d\x7f\x49\x91\x65\x3a\xa5\x4f\xcc\xf4\xe0\xc2\x77\x86\x03\x66\xb5\x64\x9e\xa7\xc0\xa2\xe7\x52\x4d\xb6\x9e\x4a\x01\x7b\x8e\x8d\xb6\x2e\x65\x5b\xbc\xf2\xa6\x5c\xf1\xa6\xb2\x97\xf5\x5d\x96\x80\x3f\xd9\x1e\xb2\xe5\x2b\xe1\xcd\x24\x33\xb0\x9f\x6c\xa4\x00\xf1\x8b\x2f\x8f\xca\xf7\x96\xca\x42\xc7\xab\x1c\x4e\xb2\xd8\x38\x47\x83\x1e\x7e\xb1\xfd\xf2\xdd\xe4\xd7\x6c\x00\xd0\xe6\x75\x41\x02\xf4\xec\x88\xa4\x5c\x39\xe5\xe3\x5c\x60\x6a\x50\x12\x8b\x1d\x0e\x61\x63\x7b\xc5\xeb\xca\x16\xe0\xeb\xb8\xbd\xa2\x66\x08\x0f\xf3\xf7\x03\x87\xbd\x1f\xc2\x77\x2e\x7a\xff\x93\x1b\xff\x9a\x73\x38\x2e\xbb\xb8\x20\x0b\xc2\xd5\xa4\x12\xe9\xa7\x69\x89\x9d\x20\x48\x3f\xce\xe2\x5d\x5c\x3b\xc2\x48\x36\xe2\x79\x83\xf2\x23\x37\xd9\xf1\xe5\x6e\xff\x39\xdf\xe5\xe8\x40\xb4\x38\x5d\x28\x81\xff\x9e\xe3\x81\x79\x9d\x64\x46\x5b\xbe\xec\x21\x19\x57\x98\xed\x02\x22\xe9\x3c\x5c\x67\xb5\xcf\x2f\x7b\xa0\x72\x66\x7e\x84\x4b\x8c\x6c\xca\x43\xfa\x29\xe1\x53\x59\xed\x3f\xba\xdd\x43\x79\x02\xb6\x84\x91\x02\x46\xf4\xda\x83\x05\x07\xa6\xf3\x3d\xd2\xe8\x9a\x0a\xe6\xb3\xc1\x5f\x7f\xa3\x01\xc0\x0e\x3e\xf6\x47\x06\x05\xce\x91\x73\x0e\xef\x2e\x6b\xe5\x10\x46\x20\x83\xee\x01\xdd\x42\xa1\xbf\xa7\x2c\x65\xb7\xc8\xb2\x18\x2a\xb1\x49\x5e\x1d\xbc\x6f\x8a\x7d\xed\x50\xe9\x40\x43\xcf\x6b\x78\xb0\x71\xd0\x40\x32\x9d\x8c\x3f\xc8\xab\x20\x80\x90\x2a\xee\x07\x8c\x00\x9c\x03\x0e\x49\xe1\x18\x90\xda\x8b\x26\x46\xa5\xb4\x5f\xf2\xaf\xfb\x56\xce\x71\x3b\x72\xc0\x40\xa9\x73\x46\xc1\x7d\x63\x68\x60\xc4\xdb\x6c\xbd\xe5\x9d\x77\x5a\xf3\x2b\x5e\x38\x93\xe1\xa7\x66\x0a\x60\x03\xc7\xe6\x94\xcd\x29\x92\xbc\x3d\x34\xdb\x3d\x87\xbf\xac\x7a\xbe\x77\x18\xdf\x2c\x74\xb8\xbf\x8f\xbf\x7a\xcc\xb8\xa9\x56\xff\xe2\xb1\xf3\xc8\x27\xaf\xf8\xeb\xc2\x10\xfa\xbf\xbf\x51\xdd\x7f\xc0\x0b\xee\xd9\xdf\xd1\x30\xd5\xd5\x75\x4f\x1b\xd3\x8d\x7d\x50\x3e\x46\x04\xf6\xcc\x14\xe0\xab\x9a\xba\x9b\x24\x74\x47\x2f\x22\xdd\x35\x04\xb5\xd4\xa9\x43\x4a\x3b\xbe\x1c\x47\x50\xb1\x96\x59\x4f\xfc\x36\x1e\xb6\x95\x04\x5f\xc9\xbc\x0c\x41\xae\xfe\x9d\x8e\x44\xfe\x72\x2d\x99\xd2\x72\xfd\x91\x06\xcf\xce\x44\xce\x93\x60\x40\xfd\x09\x5e\xa8\x93\x3b\x77\xd8\xba\x0b\x18\x38\x97\x93\xb5\x13\x36\x5f\xfc\xcb\xae\xfe\x1e\x86\xf4\x06\xe6\x9d\x4b\x64\xbe\xf5\x94\x52\x1a\xdb\x80\x38\x6e\xaf\x24\x71\x5a\x9e\xf8\x2f\xf3\x7a\x7c\xea\xb0\xdf\xcc\xc8\x40\x89\x40\x45\x58\x19\x94\x39\x2c\x36\x5b\x65\x8f\x8a\xe2\x54\x7f\x11\x5a\xd6\x37\x54\x29\x75\xa5\x26\x25\x98\x50\x3e\x87\xb1\x02\x43\x11\x78\x39\xc6\x2d\xab\x29\x8f\x4d\xaa\xa9\xf2\x83\xc1\x86\xc9\x86\x27\x53\x54\xf8\x9d\xd5\x64\x9d\xc6\xf4\x65\x09\xcc\x81\x71\xca\xfe\x03\x1a\xf1\xb5\xbb\xd1\x01\x8d\x2f\x27\xb0\xe8\xef\x62\xc5\xd7\x67\xf1\x48\xcf\x1a\xd0\x47\xb1\x31\x4a\x67\xdc\xe1\x55\x63\x84\x5e\x63\xe5\xb2\xd7\x44\x66\x43\x10\x61\x9c\x90\xa6\x7a\x18\xd8\x03\x1c\xf5\xf5\xa4\x32\x4f\x67\xfd\x7d\x22\x89\x68\x0a\xa8\x42\x37\xe9\x13\x4f\x81\xe7\xaa\xff\x75\xf1\xa4\x3a\x2d\x57\xa5\x0e\x8b\xf0\x8d\xee\x5f\x9a\x3c\x73\xd8\xb5\xb3\xf3\x90\x1b\x0b\x63\x12\x1f\x5e\x20\x80\x2e\x7c\xc6\xc0\x45\x25\x02\x96\x65\xa8\xa2\x61\x76\x82\x34\x18\xf2\x61\x35\xb2\x79\x3b\x44\x97\x7d\x03\x18\x2f\x77\xec\xff\x3e\x15\x8f\x38\xec\x03\x0e\x03\x95\x73\xcb\x6a\xfb\xe7\xa7\x41\x0d\xe2\x0a\x15\x1a\x28\xdf\x58\x95\x86\xc2\x37\x65\x1a\x2f\x60\x63\xb9\x8f\x9d\x19\xbd\xa0\xc6\x43\x30\xe5\x87\xb5\x7d\xf5\xde\x09\x13\xde\x40\x07\x42\x77\xbc\xff\xf7\xd0\x47\xf4\x5c\x89\xd7\xc7\xe7\xfe\xbd\x60\x09\xf8\x4a\xdc\xbe\x01\x07\xff\x6b\xf0\xb4\xe6\xa0\xc2\x2f\xd7\x4b\x24\x75\x1f\xdb\x29\xbf\x6d\x8e\x8b\xee\xf1\x7b\xf4\xbd\xbd\x99\x3c\x02\x13\x04\xb3\xe0\xcb\xa9\xae\x5b\xed\x43\xf1\xa5\xb8\xd5\xae\xb4\x7d\xb0\xd7\x5a\xcb\x07\x30\xf0\x7b\x15\x14\x02\x12\xb2\x54\x57\x8e\x99\x76\x48\x76\xd9\x4d\xad\x99\xbd\x44\x84\x7a\xf5\x66\xe3\x8f\x8f\x33\x95\xff\x73\xdc\xf7\x12\x21\x02\x89\xa8\xcc\x7d\xd7\x71\x6d\xb9\x12\x1a\xf5\x4c\x5b\x3b\x23\xb4\x11\xf8\x84\xe2\xf5\x82\x12\xfc\x9d\x94\x97\xf8\xd8\x1f\x18\xb5\x8a\x5f\x45\xad\x2c\x84\x54\x1f\xa3\x1e\x56\xd6\xc0\x26\x45\x62\x75\x67\xc4\x43\x69\x56\x4e\xfd\x53\x66\x75\xd9\xb2\xca\xa7\xa0\x39\x23\x00\xca\x5f\x17\x00\x04\xe8\x32\x38\x34\xf5\xa8\x39\x6b\xfa\xd2\x86\xde\xb8\x1a\x43\x65\xdc\xed\xf4\xde\x6a\xf8\x0d\xbe\x8d\x0f\x8c\x7a\x20\xda\x28\xc8\x66\x08\xd4\x80\xbf\x87\x9e\x97\x60\x88\xb6\x3f\x62\x3c\x26\x46\x66\x67\xd0\x72\xd4\xb4\x2f\x3f\x38\xa8\xc5\x37\x11\xfd\x59\x48\x34\x75\xf5\x25\x36\x10\x0e\x2f\xe3\x9a\x85\xdb\x94\x11\xae\xf8\x5d\x56\xc6\xf6\x03\x1e\xe7\x26\x6b\x00\x0b\x78\x7b\x11\xf7\xdc\x6e\x37\xd1\x55\x10\xa2\xa0\x2f\x0d\x90\x02\x3b\x3f\x0d\x71\x05\x6c\x85\x05\x3a\xf4\xec\x1a\x35\x7d\xb7\x26\x3b\x0d\x03\x5f\x30\x5f\x01\x4e\xc8\x10\xcf\x18\x2b\xc0\x6c\x28\x80\xa4\xca\x5e\x1b\x88\x97\x78\xbb\xfd\x89\x06\x55\x46\x8b\xcd\x3c\x1b\x2c\x88\x1e\x34\xc9\x6c\x0a\xe4\x59\x8d\x7a\x91\xea\xf1\xc2\x40\x2b\xff\x23\xed\xf3\x94\xa7\xf0\x8b\xbf\x7c\x52\x32\x51\x3a\x03\xf1\xac\x92\x01\x8d\xc7\xe3\xec\xec\x66\xa3\x6e\xbf\x63\x17\x89\x63\x66\x45\x82\xca\xcb\x26\xa8\xfa\x11\x97\x6f\x3b\x9b\x1d\x3c\x3d\xe1\x1a\xe5\x0d\xb1\xa6\x40\xe3\x67\x0f\x80\x62\x04\x36\xcc\x47\xfe\x8f\xe7\x7f\x02\x1d\xd9\xc5\x05\xbd\x6e\xac\x65\x94\x80\x20\xba\xb2\xc4\x31\x34\x18\x7a\xcb\xdd\x52\x29\x19\x79\x53\xae\xbc\x57\x3c\xac\x0d\xbc\x65\x21\x38\xc7\x21\x54\x3a\xfc\xe7\xa7\xf5\x91\x9a\x2f\x25\x7a\x9a\xb2\xee\x9f\xec\xa4\x8c\x0d\xcd\xc8\x9d\x5e\x1a\x1d\x61\x50\xb6\x17\x51\xa3\xa5\x07\xa9\x6c\x69\x18\x9c\xdc\xaf\x17\x19\x90\x3c\x60\x27\x1d\x98\xc3\xcd\x42\x0b\xc3\x2f\xc7\xae\x41\xe5\x84\x79\xd8\xb0\xbe\xaa\x1d\x0c\x94\x60\xe9\x93\x1a\xa3\x13\x20\x8d\xba\xcc\x88\x89\x66\x46\xbd\x13\x76\x70\xfd\x48\x2c\x3b\xb3\x48\x59\x0e\x2a\xff\x73\x27\xee\x2f\xbb\x45\x86\x04\xd8\x9b\xac\x74\x78\xfb\xcf\x1e\xad\xef\x4f\xd5\x33\x53\xf2\xa0\x3b\xc7\xe3\x1d\x83\x47\x99\x6e\xdf\x75\x18\x9a\xcc\x38\xd2\x05\x00\x60\xc5\x5e\x85\x6f\x06\x4e\x09\x8e\x7a\x8f\x36\x76\x9e\xa6\x60\x99\xc2\xdc\xf9\x2e\xa1\x43\xd9\xe2\x87\xe9\x24\xc6\x6b\xb4\x3c\xdf\x35\xf4\x48\x56\xa8\x1c\x5c\x59\x8d\x65\x3c\xc1\xb0\x58\x80\x10\x5a\xbf\x2e\x30\xdf\xd8\x45\xeb\xde\xb4\xa8\x73\xfb\x4e\x23\x36\x0e\x65\x23\x96\xac\x6b\x78\x09\x91\x79\x09\x9f\x41\x14\x3d\xdf\x40\xa8\x22\x42\x3a\xf1\x14\xa9\x2f\xdc\xa2\x2d\x83\xd8\xbe\xd5\xab\x8a\x54\xc7\xa7\x07\xe7\x5a\xbf\x38\x90\x17\x4e\x2b\xe7\xea\x89\xe8\x5c\xde\x5c\x98\x17\x8f\x39\x43\x9e\x65\x6d\x35\xce\x72\x51\xea\x2b\x48\xb3\x96\xcf\x64\xaa\x0c\x20\x9b\xed\x2c\x27\xac\x96\x8f\x73\xc1\x3a\x5e\x3d\xa5\xff\x77\x6a\x4f\x8e\x51\x9a\x46\x93\x29\xce\xa5\x7c\xd7\xf7\xd8\x99\xa1\x70\x3e\xae\x3d\x0b\xeb\xe8\xc9\x12\x6c\x26\x9d\x7d\x91\xd5\x6e\xa1\xc0\xf8\xf2\xa9\xae\x9e\xe5\x7a\xc6\x3c\x33\x58\xe4\x9c\xdc\xf5\x45\x84\xc7\x92\x65\x28\xd4\x27\xe1\x42\x0a\x28\x83\x36\x63\xd1\x40\x6b\x2b\x89\x9e\xce\x48\x3b\xcb\xcf\x29\x58\x28\xaf\x6c\x4f\x1d\x9b\xa9\xcf\x9c\xcc\x6d\x6a\x8d\x6b\xa6\xb5\x26\x63\x93\x14\xeb\xb8\x28\x2f\x07\x3b\xe6\x1a\x74\x36\xaa\xe6\x08\x03\xfd\xce\xc7\x78\xc9\x98\x21\x62\xda\x23\xba\x0a\x45\xce\xcb\xc0\x10\x74\x83\xbe\xb3\xdf\xd7\xd1\xa3\xb2\x73\xb2\xb5\xa3\x50\x24\x5d\x5c\xe5\x5d\xe3\x6f\x87\xdd\xb0\x7f\x25\x30\xc1\x2e\xa1\xd5\xbf\xdb\x6f\x81\x2d\xf9\xfb\xe9\x13\xe5\x84\x1c\xa7\xdf\xd5\x18\xf4\xc1\x44\x05\xbf\x0c\x5c\xba\x35\x40\x6a\xa7\x5a\xfb\xdc\x8e\xdb\xc2\x23\x22\xe6\x8d\x22\x01\xa7\x75\x7b\xff\x5d\x65\x03\x65\x9f\xbe\x84\x46\xe0\xac\xae\xd8\xa0\xdb\x07\xc7\x1d\x98\x51\x6a\x7d\x3f\xdd\xb6\x53\x04\xb5\xdd\x2b\xcb\xb3\x6c\xf9\x92\x1c\x32\xf7\xd3\x74\x37\xbb\x17\xe9\x8a\xa1\x07\xb7\x16\x49\x68\x3f\x42\xe4\x04\x66\xac\x24\x0f\xf4\xe1\xd6\x9f\xf3\x3b\xc9\xea\xa0\x0c\xf5\x39\x44\x98\xf4\xa8\xcf\xc7\x67\xb5\x79\x37\xb8\xb7\x16\x94\xd8\x66\xdf\xc6\x46\x31\x46\x33\xfe\xaf\x8a\x48\x92\x07\xd9\xac\x3a\x3a\xa8\xc5\x37\x87\x94\xee\xb8\xbb\x37\xf3\xa9\x8c\xca\x8c\x34\xf7\xf5\xfe\x36\x2e\x16\x5e\x6c\x65\x93\xcc\x7f\x1c\x84\x6e\x0b\x4f\x64\x25\xb6\x97\x8d\x2f\x2e\x5f\x3d\x2d\xbb\x9c\x20\xde\xa4\xcf\x31\xcb\xe0\xc8\x60\xcf\xdc\x2b\x5f\x6e\xb6\x90\x7b\x47\x27\x4c\x6f\x60\xc2\x4a\x7b\x5c\x4e\x2c\x48\xde\x17\x30\x15\x8f\x7d\x6a\x35\xdd\x9f\xfd\x05\x61\x3d\xcb\x8f\x5e\x69\x79\xfb\x58\x1b\x14\xfb\xf8\x6b\x59\xca\xa6\x6e\xb1\xf4\x29\xee\x64\xee\x8a\x7d\xac\x7c\x91\xfd\x91\x23\x57\x2e\x4c\xe7\x60\xb4\x6a\x63\x0f\x04\xcb\x09\x46\x7b\xa4\x77\x40\x4c\xfe\x17\x1f\x74\x80\xe2\x13\x7a\xa6\x72\x84\x99\x13\xe4\x66\x34\x77\x87\x6d\xa6\xde\x4a\x7f\x15\xbe\xca\xc7\xe7\x7c\xb2\xe3\x74\x38\x1c\xbe\x51\x0e\x1a\xc5\x7e\x95\x59\xed\xa3\x9b\xd1\x81\xec\xd8\x59\xca\x5e\x09\xcc\xa7\x3d\x06\xfe\xdb\x63\xa4\x54\x26\x4e\x88\x96\x01\x9c\xfa\x55\x90\x48\x77\x99\x34\xd9\x45\x2b\x4d\x91\x9b\x89\x26\x80\xb3\x23\xf6\x7f\xa1\x30\xfa\x47\xd2\xd8\x76\x02\x99\x92\x2d\x78\x2e\x27\xe9\xeb\x66\x74\x69\x74\xbe\xfe\x5c\x97\xe2\x2d\xb3\x5f\x59\x6e\x02\xe7\x2d\x9b\xf4\x1f\x22\x4e\xe3\x5d\xe7\x42\xf9\xf7\x56\xa3\x4a\xaf\xd1\x8a\x0f\xb8\x68\x58\x45\xb2\x9e\xc8\xcc\x92\xcd\xd1\x77\x75\x83\xa3\xd4\xd6\x1a\x9e\x5e\x4b\xc2\x92\x96\xfe\x1d\x0f\xb1\x3f\x4a\x28\x4c\x9c\x92\x37\xa5\x5f\xfb\x2b\x91\xf9\x6c\x68\x2a\x9a\x7c\x17\x66\x25\x25\xca\x40\x23\xfa\x78\x45\x7b\x27\xe8\x81\x70\xde\xb0\xa4\xa9\x9c\x4e\x52\xe5\xe0\x87\xad\x12\x95\x2f\xed\x33\x16\x83\xfa\xd6\x53\x0d\xad\x5b\x81\x50\x6a\xa8\x15\x1b\x1e\xfc\x81\x5a\xe9\x32\xdf\x92\x5d\x7c\x39\xd0\x57\x95\x6c\x23\x57\x55\xbd\xb7\x0b\xfb\xd2\xb3\x61\x65\x26\x78\xe5\x5c\x7e\xcb\xd4\x06\x1a\xa0\xd5\x2a\x41\x86\x58\xf7\xdd\x3e\x4a\x67\x67\xa5\xca\x69\xbd\x04\x51\xad\xf6\xc2\xb1\xaa\x6b\x01\x94\x2a\xe3\x95\xa4\x07\xab\xec\xe0\x5a\xc1\x8e\x89\x36\x00\x4b\xaa\x88\x55\x6e\xbf\x6d\x9c\xaa\x06\x67\xdd\x64\xa9\x48\xa4\x2b\x42\xf9\x33\x11\xf3\x9b\x1c\x96\xaa\x07\xcf\x0a\x56\xa3\xf4\x27\x59\x5e\xa9\xab\x2d\xf6\xd6\x71\x0d\x85\x4b\xec\xce\x57\xe5\x45\x71\x08\x67\xee\x68\x1b\x02\xa2\x82\xe3\x18\xd8\x42\xfa\x7c\x0f\xe4\x00\x29\x01\xac\x8c\xd3\x1e\xfe\xed\xec\xfb\x8e\xe1\xe5\xb9\xd2\x87\x5a\x56\x4c\x19\xb4\xc5\x49\xe0\xd4\x22\xe2\xfa\xcd\x70\x93\x05\x35\x8a\x73\x5c\xa5\x80\x80\xeb\x7b\xb6\xa4\xb0\xea\x5f\xf4\x8f\x80\x3e\xd2\x0f\xbc\xcc\x31\x66\xe9\xab\x67\xe2\xf0\xef\x4f\x80\xd5\xf2\xcc\x7a\xf4\xb5\xc1\x5b\x43\x6a\x19\xa0\x94\x87\xf4\xaa\xe2\x38\x2e\xe8\x32\x71\x51\x38\xa1\xe1\x64\x0e\x07\x2c\x17\xfd\x02\x6b\x1f\x79\x10\x79\x5e\x4a\x51\x67\x2e\x70\x2e\x6f\x0c\x37\x4f\xae\x65\xf9\xc9\x0e\x6f\xee\xaa\xb3\xd3\x1b\x00\xea\xad\x66\x02\x12\x4e\x42\xc3\xda\x20\xd2\x7b\xb7\xa9\x81\x30\xa6\xc9\x71\xa5\x02\x9a\x34\xea\xe5\x73\x2b\x09\x4c\xc8\x66\x41\x8d\x99\xbc\xc8\x96\x45\x82\x2d\x9c\xc5\x60\x11\xee\x9b\x6b\xbe\xce\x4c\x75\x9e\xf5\x2b\xbb\x55\x2d\x9b\x8d\xcf\xf3\x2e\x5f\xa5\x1c\x36\x4e\xb3\x10\xa2\xf2\x69\x75\xbf\xbd\x9b\xf8\x42\x79\xea\x74\xa7\x6c\xe1\xa7\x38\x98\xaa\xe7\x3b\x6d\x26\xb6\xb2\x8d\x93\xfc\xa4\x7c\x61\x10\x69\x3b\xaa\x70\xa9\xe8\xd3\xd8\x08\xf9\xc1\xce\x71\xb1\xef\xfc\xd8\xf2\x3a\x51\xf6\xa0\xe3\xcd\xc0\xe0\x14\x65\x7e\x8e\xc8\x6e\xa8\x3c\xe0\x23\x63\x8b\xf8\xd0\xaa\xd8\x1d\xde\x2e\x53\x89\xf9\x57\x71\x4d\xd1\xe7\xa9\x0d\x0d\xca\xee\x54\xa0\x72\x15\x45\x8e\x2e\xe6\x61\xb9\x91\xc5\xd1\x5d\x14\xf6\x59\x12\xab\x39\x1c\xd3\x10\x1d\xdc\xe4\x5f\x3f\x8c\x39\x60\x7b\x4d\x29\xc4\xed\x3f\x68\x57\x38\x78\x98\x3f\x4a\x81\x0b\x6e\xdd\xd2\x9f\x4e\x5e\x10\xd3\x49\x96\xdc\x64\x77\xa7\x8c\xad\xb6\x50\xa7\x1c\x19\x6d\x53\xbe\xe8\x82\xf6\x3f\x87\xe5\x9d\x6a\x1b\xc5\xf6\xb7\x1a\x1a\x98\xa6\x34\x86\xaf\x01\x6f\xf6\xcd\x0e\x51\xbd\xb2\x51\x90\xc8\xe3\x87\x81\xa7\xc5\xce\xeb\x04\x2b\x80\x6d\x78\xa8\xde\x9f\x10\xfe\x23\x34\xab\x6c\xdd\x09\xba\x3e\x73\xd9\x09\xa9\x81\xf2\x5c\xc0\xcf\x24\x20\xf0\x64\x37\x95\x83\xcc\x74\x81\xe7\x03\xc5\x77\x3a\xad\x83\x01\x0d\x45\x46\x51\xf4\xfb\xe5\x23\xcb\x97\x4d\xc0\xac\x5c\xc6\x63\x97\xcb\x7a\xbb\xe2\xf3\xfc\x84\xa3\xd8\x0f\xcf\xd6\x45\x62\xd0\x9f\xf2\x15\x98\x9c\xf0\x03\x0e\x3b\x25\x34\x7d\x48\x09\x7f\xca\x87\xe3\x3d\xe9\x03\x43\x47\xfd\xc4\x3f\xf8\x61\xe4\x79\x3f\xca\x4c\x1d\xdb\x15\x2c\x50\x5b\x14\xf2\x0e\x62\x34\xaa\x75\x70\x22\xf6\x1f\x7c\xca\xf6\xb2\x71\x72\x9e\x47\xa8\x6d\x8e\x1a\xe9\x32\x2a\x2e\x8c\x23\x90\x36\x34\xa2\x3c\x22\xb0\x37\xb9\xd2\x69\x98\xb6\xeb\x7e\xf8\xa6\x5b\x4c\x23\xe7\x0e\x97\xf0\xa3\x9b\x91\x7a\x7d\xaa\x67\xea\xd8\xe1\x8c\x01\xb6\xc1\xef\x14\xa3\x32\xb3\xb4\x72\x79\x2a\x8f\x68\x24\xc6\x20\xd3\x1d\xb7\xe7\x26\xa3\xc4\x47\x39\xdb\x04\x05\x30\xac\x91\x40\xd9\x59\xfe\x87\x5b\xff\x6b\xf0\xd4\x5c\xb3\xc0\xb4\xad\x7c\xe1\x9e\x10\x61\xee\x11\x20\x5a\x37\xa9\x13\x59\xce\xe5\xa7\x50\xb1\xb2\xe7\x79\x8c\x21\xb2\x51\xb0\x23\x65\x33\xaa\x5a\x1f\x88\xf5\x90\xf0\xb4\x2c\x10\xf6\x9a\x44\x49\xf3\x50\x16\xdf\x43\xa5\xb5\x74\x39\x18\xb7\x93\xcc\x66\x1e\xac\xb3\x5b\x69\x0c\x01\xec\x0d\x3a\x91\x31\x0c\xc7\xea\x47\xe8\x68\xca\xde\xf1\x19\xa3\xad\x97\xb3\xd4\xd2\x85\xbd\xd6\x23\xcc\x6f\x19\xfb\xb8\xea\xeb\x18\x4a\xd5\x09\x1f\x18\x94\x7f\x74\xc5\xb7\x91\x7e\xb8\xe2\xdf\x98\xd0\xb8\xf7\xcd\xa9\xb0\x12\xc4\x35\x1a\x64\x8b\x09\x08\x16\x51\xba\x91\x30\x67\x0c\xf5\xe3\x60\x36\xf9\x20\x7e\xc5\x00\x93\x65\x41\x70\x69\xf7\x3d\xdb\x36\x06\xd7\x4b\x09\x8d\x1c\x00\x7d\xd1\xa0\x37\x55\xe9\x0e\xde\x30\x31\xa7\x72\x1e\x2c\x17\x34\xa6\xde\x98\xc6\x43\x1f\x78\x5b\xd9\x60\xde\xf9\x7d\xf2\xa9\x39\xf8\x49\xf7\xa8\x1d\x94\x15\xa5\xbb\x22\x5d\xf2\x3e\x55\x13\x93\xfb\x94\x62\x57\x72\x1f\x8f\xbf\x01\xdd\x09\x49\x71\xc6\x2b\x12\xeb\x3e\x06\x0f\x10\x53\xf3\x9c\xaa\x39\xd4\xbd\x5c\x55\x9c\x46\xef\x94\x1c\xca\x18\x6a\x9a\xd8\xa6\xba\x3b\x64\xe7\x9e\x42\xf7\x50\xae\x85\xff\x9d\x29\x19\x5b\x73\xad\x46\x60\xcd\x00\x18\x0d\xa2\x76\x9b\x3c\xe1\x20\x3c\xa1\xaa\x04\xb1\xff\x05\x16\xb5\x4b\x7d\xf3\x10\x43\x0c\x86\x4f\x92\xd7\x50\x55\x13\xce\xfb\x38\xdd\x38\x90\xb3\xbf\xfe\x09\x7a\x3d\xed\xa1\xb5\x11\x9f\xb9\x5f\xb6\x24\xa9\x7e\x99\xb3\xce\xf1\x16\xe1\x90\x7f\xbe\xaf\xcb\xef\x88\x81\x04\x7b\xe2\x41\xae\x26\x5f\x79\x5e\xab\x2d\x54\xd3\xd7\x5a\xa9\xec\x67\x35\x89\xd0\x11\x5c\x30\x18\x56\x38\x8f\xc6\xdf\x51\x7f\x64\x8e\xe4\xf4\xb1\x34\x67\xaa\x25\x6f\xd9\x66\xbb\xae\xc2\x64\xcd\xf7\xd0\x0a\xde\x6b\xf9\x20\xfe\x25\x0d\x11\x1b\x09\x55\x08\xf3\x1a\xb7\x8f\x0d\xf9\xb7\xfe\xd7\x2e\x53\x11\xbf\x16\xd1\x93\x37\x03\x67\xbe\xb7\x9c\x8d\x32\x7b\xca\xad\x6e\x9a\x51\x66\x16\xdd\xf8\x82\x7d\xaa\x30\xb4\xaf\x70\x00\x3c\x11\xa6\xbf\x15\x0f\x3b\xa2\xe5\xdb\x41\xd0\x7a\x49\x0e\x81\xbc\x6d\xf9\x65\x10\xae\x14\x31\x9f\xfa\x94\x72\xd0\x8d\x9e\x06\xe9\x48\x85\x8d\xa3\x36\x78\x80\xe2\xfc\x62\xd0\xbd\x6c\x01\xc8\xad\xbe\x01\x97\x52\x43\x21\xe4\xe4\x2e\x09\xe2\x02\x61\xf2\x48\xf5\x19\x04\xe7\xfc\xcf\xf7\x55\x68\x84\x60\x82\xbc\xb9\x19\xae\xc3\x80\xd1\x5e\xe1\xc1\xd1\x45\x31\xd5\x21\x5e\xc3\xdf\x31\x68\x99\xc1\xba\xb2\xba\xc8\xcf\xb3\xa5\x66\x87\x04\xec\xc3\x21\x05\xd0\x01\x4b\xc1\x04\xcb\x23\xdd\xfa\xcd\xf4\x32\xc8\xf2\x81\x0c\xb2\xf4\xa2\x77\xb7\xa5\x31\x4a\x1e\x91\xab\xe3\xc7\x9a\x1d\x18\xff\x6e\xb9\xe4\xdf\x54\xdf\x76\x6e\x94\x77\x40\x5e\x2c\xbb\x12\xaf\xbe\x4b\xf7\x7b\xd9\x81\x0a\x64\x29\xdb\xce\xdd\x46\x58\xbb\x53\x21\xcf\x95\xea\xef\xf6\x54\x94\x5a\xe0\x81\xc4\x76\xce\x1f\x22\x42\x56\xe6\x03\xf3\x7b\x3a\x9e\x80\xd9\x09\x86\xcd\x20\x87\x72\xd4\x26\x62\x3a\x03\xfa\x7a\xc1\x68\x8d\xa3\x73\xab\xda\xa5\x45\xad\x33\x8c\xf6\xba\x55\x84\x85\x16\xcc\x87\x38\x5c\xd8\x95\x0e\x84\x0f\xfb\x6a\x5f\x76\x3e\xaa\xf2\x23\xbb\x68\x5d\x72\x24\xcc\x8d\x61\xb1\xc5\xbe\x81\x89\x2f\x12\x1e\xed\x4a\xa7\xe1\x01\xec\x04\x5e\xc6\xf2\xae\x58\x6f\x0a\xc0\x9c\xc1\x28\x31\xd8\x11\xa3\xa5\x6a\x9b\x66\x99\x34\xd4\x67\x57\x4a\x8e\x34\x46\xf5\x9d\x4f\x86\xbe\xa1\x30\xea\xdb\x2b\x7d\x14\x96\x8a\x4a\x05\x68\xb3\xb7\x02\x61\x08\xd8\x4e\x67\x7f\x48\x70\x84\x1e\xb9\xef\x63\x0c\x43\x17\xc3\x29\x02\xc5\x5a\xf1\x2f\xdb\x29\x55\xb5\xd1\x31\x86\x14\x0f\xa4\x4b\x46\xc5\x95\x01\x69\xb3\x30\xde\xe8\x37\x01\x7d\x96\x4d\x3d\xc4\xce\xc6\x55\xfd\x96\x0b\x3a\x86\xbb\xb5\x5e\x65\xb1\x5d\xb5\xbd\x69\x1f\xe9\x08\x54\xef\x2c\x4b\xf4\xe4\xbd\x01\xd4\x48\x69\xb3\xa4\xc9\x56\x5e\xe1\xeb\xd5\x3e\x02\xfc\xab\x72\xa3\x6e\x1c\x22\x45\x94\x2e\x5e\xdc\x2a\xb7\x69\xc9\xab\x50\x45\x6e\x99\xdb\x34\xb7\x4c\xa8\xe5\x78\xca\x52\xd2\xb7\x57\x7f\xb2\x4d\x8d\xd9\x1f\xcd\x87\x8b\x75\xa4\x86\x42\x19\x2b\x50\xea\x2b\x37\xbd\x89\x04\xe7\x26\x34\xd7\x0d\x1c\xd4\x25\x52\x9a\xa6\xd5\xe2\xa4\x72\x7d\x08\x36\xdb\xb2\x76\xee\xcd\x96\x0c\xf6\xd9\xbc\xa5\x29\x45\xa0\x96\x91\x26\xe7\x70\x04\xcb\xd0\x6f\x09\xfc\xca\x43\xff\x99\x3d\x14\xba\x37\x9d\x71\x12\x63\xd8\xf0\xd6\xa6\x8c\x54\x13\x85\x22\x18\x71\xa4\xbb\xd6\x70\x32\x74\xc1\x96\xe3\x38\x9b\xda\xde\x8c\x03\xf7\x65\x80\xfa\x9c\x7c\x51\xd6\xa5\xbb\x61\x33\xa4\xef\xc5\x00\x04\x44\x4b\x1f\x9b\x68\x40\x36\x7d\x40\xa2\x65\x7b\xc0\x0b\xac\x29\x3b\x93\x37\x9d\x05\x9a\xbe\xda\x86\x85\xf9\x02\x0c\xc4\x96\xd1\x39\xa6\x21\x7e\x4a\x7f\x49\x9f\x29\xed\x0f\xbf\x53\x6c\x62\x9c\xc2\xdc\x54\x2a\x6c\x53\xfd\x3a\x9b\xf4\x23\xcb\xb0\x61\x10\xd3\xbe\x49\xd5\x1a\xec\x2d\xb7\xae\xb7\x92\x15\xca\x1e\x1f\xa2\xa3\x8f\x87\x73\x59\x7a\x8c\x77\x1d\xc0\xc7\x6e\x46\xfe\x46\x67\x57\x5c\xc0\xd3\xfe\xd8\x0c\xea\x69\x42\x2b\xb7\x7a\x6f\xa4\x77\xf3\x76\x5e\x55\x23\xd4\xe4\x68\x6c\xff\x1f\x73\xa0\x5f\xcb\x32\xa2\xab\x21\xc0\x6c\xd1\x64\x8f\xcc\x8a\x6c\x5f\x85\x04\x1e\xba\x11\xbe\xff\xc0\x66\x73\xe4\x78\x96\x82\x69\x1c\xce\x6b\x1c\x02\x27\xfc\x12\xb1\x4c\x60\xf2\xdd\x3a\x43\x6c\x17\xfd\x03\xb1\x14\xc7\x11\x4f\xe8\xe8\xe3\x52\x4f\xdb\xd4\x89\x0c\x9b\xca\x84\x80\x9b\xe6\x23\xd7\xbf\xd4\x94\x29\x2e\x68\x9b\x7f\x11\x26\xf3\x07\x9c\x9f\x33\x3d\x90\x36\xeb\x98\xd2\x9f\xe2\x2b\xca\xce\xdf\xbb\x10\x58\x92\x09\xd2\x2a\xb3\xf8\x50\x51\x31\x6a\x99\x38\x48\x21\xb4\x7e\xe7\xb2\x84\xbc\x25\xd8\x7f\xbb\x27\xfa\xa6\x82\x06\xa7\x90\x8e\xca\xc9\x1e\xd1\xa9\xe5\x5d\x2c\xe1\x47\x06\x5c\xd5\x49\xaa\x79\x95\x73\x19\xc9\x99\xda\xa1\x71\xcc\x78\xf6\xbe\x33\x26\x37\x5a\xf5\x51\x46\xed\x43\xdd\xa1\x37\x1a\xdb\x06\xea\xfa\x7e\x6a\xb9\x75\xbf\x49\x15\xf5\x4f\xb2\xa8\xf2\x6b\x08\x37\xec\x45\x22\xd4\x10\xce\xd7\x1c\x26\x7a\xfe\x40\x81\x54\xa3\x34\x2e\x31\xd2\x3b\x85\x4a\xe7\x8d\x32\x83\x3f\x35\x82\x3a\xb3\x14\x55\x01\x00\xa6\x2e\x24\x57\x56\xd1\xbc\x8c\x7d\xbc\xc6\x0d\xb9\x26\xc2\xee\xf8\x86\x5f\x0e\xe7\x00\x57\x58\x59\xd6\x18\xca\x7c\x8c\x31\xd4\x9b\x06\x8d\x1f\xd5\x84\x39\x1a\xc9\x55\xbb\xee\xb5\xa9\xc8\xab\x6f\xcb\x77\x98\x2d\xbb\x9a\x81\x2f\xdc\xe8\x6f\xc6\x50\x0f\x28\x2c\xf9\xd6\x31\x8b\x79\x71\x2b\x2b\x6a\x36\x02\x5a\x96\xd4\x47\x7a\x56\x04\x0d\xc9\x04\x81\xc5\x6d\xa7\x1f\xbc\x69\x0e\x39\x97\x1a\x77\x07\x57\x34\x41\x01\xe7\x72\x41\x79\x43\xee\xfc\x8c\xee\xac\xf8\xdd\x5c\xf1\x3b\xa8\xb4\xf2\xb7\x64\x8b\x6f\x6f\x09\xf1\xb0\x96\x47\xc2\x7c\xd4\x0f\x57\x54\x11\x13\x8c\xdf\xe0\xf1\xc6\x96\x92\xea\xad\x73\xa1\x06\x8a\xf5\x3f\x51\x2a\x65\x1e\xc2\x02\x33\xe2\x66\x81\x0a\x39\x3a\xef\x80\xeb\x96\x3a\x7e\x07\xa4\x18\xa3\xe3\xb8\x41\x20\x68\x7a\xc9\xc1\x22\x90\xc6\xce\x6b\x95\xf0\x83\x0c\x30\x83\x54\x65\x58\x6a\xe1\x1c\x63\xce\xf8\x65\x32\x1a\x92\x90\x8d\x03\xe2\x61\xdc\x7e\x53\x89\x2d\x02\x6b\xc4\x31\x8b\x23\xb5\x1a\x00\xe8\xa1\x2a\xe5\x93\xcb\xfa\x27\x33\xb5\x87\x35\x59\x0f\x9b\x4c\x13\xb3\xb3\xb7\x15\xa5\xea\xbc\xed\x17\x97\x1e\xff\xb1\x63\xe3\x71\x64\x9c\x21\x36\x44\xef\xa1\x54\x66\x72\x8e\x2b\xbf\x75\xd9\xc4\x72\x24\xf4\x21\xd4\x5d\xfb\x75\xc0\x65\x76\xff\xe0\x27\x90\x4b\x56\x5c\xd1\xbb\xdc\x03\x39\xea\x25\x9c\x3a\x03\x81\xa3\xe2\xcb\x88\x0f\x7d\xda\x22\x54\x02\x2e\x0f\x01\xf6\x21\xde\x45\xe2\xaf\x96\xb1\x7e\x04\x4c\xce\x86\xe1\x68\x1e\x1b\xe2\xf5\x0b\x35\x10\xc6\xa8\x0f\xc1\x34\x12\xeb\xb9\xbe\xd6\xeb\x72\xb0\x66\x89\xc0\x5c\x7b\xa3\xfd\x32\x47\xf8\xc8\x66\x7b\x3b\x79\x61\x0f\x96\xb1\x1d\x34\x11\x9f\x2e\xc5\x57\x45\x6f\x0e\xf5\xf1\xe2\x7e\x57\x0b\x65\x30\x70\x7a\x85\xa6\x2c\x19\x55\x61\x16\x6f\xc0\x58\x08\xac\x38\x57\x8f\x0c\x46\x1e\xc9\x1c\x38\xf9\xca\xed\x1a\xd5\xe6\xc3\xbe\x96\x42\x7b\x5f\xc5\x47\x66\xde\x49\x45\x05\xb9\xdd\xc0\x37\x1a\x7a\x25\xa1\x80\x57\xd2\xc3\xbe\x86\xc5\x40\x19\x89\x63\x0f\x2b\xba\xd1\xd1\xb9\x5a\x5f\xf6\x7c\x3f\xdc\xa9\xd8\x73\xb0\x9b\xf6\x9c\xd6\x86\x29\xfd\xfb\x62\x3a\xd3\x3e\x33\xc3\xc5\x7f\x07\x4c\xd8\xc0\x5a\xed\x46\x50\xd0\xe4\xe7\x5d\x0e\xd0\x1c\xc1\x1b\x94\xa3\x27\xec\x52\xa5\x55\x7b\xd2\x07\xd9\xa7\x8e\x83\x8b\x3b\x8d\x47\xf6\xd0\xa4\x48\x9b\x5e\x84\x13\x24\x52\x33\xe8\x45\x99\x5a\x60\x85\x51\x60\x52\x96\xa6\x64\x13\xc7\x0f\xf3\xb1\x0f\xb4\xa2\xfd\x08\xc2\xe2\x0a\x23\x86\x67\xcc\xc1\xd9\x18\x9b\xf6\xcb\x4e\x66\xef\x4d\xc5\xdf\x61\x7b\xe6\xf3\x48\xf5\xb2\x55\x69\x43\x80\x0d\x7b\x8d\x68\xa7\x31\x9d\xf3\x55\x60\xfe\x1b\x11\xd0\xed\x76\x2a\x2d\x1f\x26\x75\x8a\x8f\x01\x79\xf1\x34\x00\x08\xaa\xf8\xa1\x4c\x21\x1d\x8f\xd0\x74\x3b\x6f\xa5\xdc\xbb\x3c\xad\xe6\x0b\x56\xca\x8e\x06\x17\x6f\xcd\xdb\xdb\x95\x5e\x58\x6e\x46\x83\xb4\x69\x7a\x45\xbe\x40\x19\xcf\x70\x20\x98\x14\xeb\x72\xef\x69\x28\xc3\x71\xbb\x31\x40\xe9\x46\x79\x9a\x74\xa2\x5b\x18\xea\x6d\x27\x99\x60\x72\xa9\x13\x3a\x78\x0e\xa1\x1c\xcb\x47\xf8\xd5\xed\x8f\x2a\x54\x2b\xab\xb6\x76\x7d\xc0\xb5\x0c\x1f\xc6\xc9\xc3\x88\x8f\x07\xfb\x58\x10\x77\x13\x33\xd8\x10\x05\x1d\xfe\x51\xf4\xb3\x0b\x27\x6f\x5a\xaa\x9d\x86\xfd\x0e\x05\x7b\x61\x2d\x01\x5e\xa1\x3b\x77\x5f\x9d\x5b\x4f\xef\x3c\x8e\x10\x0d\x34\x7a\xbc\xba\x16\x08\x18\xd2\xf7\xf6\xc7\x77\xf4\xf2\xcb\x2f\xe1\x00\x99\x50\x44\x13\x37\x14\x0a\x38\x80\x27\xc2\xd1\x7d\xfa\x8a\x78\xee\x00\x81\xe8\xa1\x5d\x0d\xaa\xa6\x0b\xbe\x34\x7d\x3d\x93\xe6\x05\x6d\x6d\x84\x89\x8d\xff\x7d\x7c\x5b\x4e\x3f\x7e\x51\xb6\x96\xa9\xc0\x60\xc8\xe2\x96\x2b\x23\x66\x0c\x79\xdc\x9d\xb1\xd5\xb1\x43\x80\xa1\xc5\xe7\x26\x95\x5c\x75\x0a\x2f\x3f\xe1\xc3\xa2\xb3\x7c\x54\xe6\x01\x94\x6d\xa5\x22\x11\xa7\xad\x1c\x80\xf0\xeb\xfb\x21\xbc\xe9\xcf\x7a\x60\x83\xc5\x32\x26\x19\x62\xf2\x41\xf9\x3a\x0c\x19\xde\x7b\x23\x81\xf9\x4a\x6f\xce\xad\x88\x64\x80\x07\x7b\xab\x70\xf1\xf5\x87\x5f\x6a\x19\xaf\xf6\xd6\x2b\x5f\x1c\xda\x91\x7e\x04\x7a\x0d\x66\xca\xae\x71\x42\xa1\x0c\x2e\x73\xec\x79\x05\xbb\xac\x6b\x20\x8e\xf9\x2b\xe1\x25\xab\xe2\x20\xbf\x31\x4b\x12\x08\x23\x14\x6c\x71\x88\xc3\x4d\xa7\xa3\x55\x26\x07\x86\x60\x42\xf5\x05\xb1\x4e\xe9\x63\xe4\x0b\xc3\xfa\xa2\x93\x57\x1b\x68\xeb\xf4\x22\xc9\x67\xce\x8a\xcd\x43\xd9\x5a\x3f\x39\xde\x03\x7f\x1c\x17\xf7\xb7\x80\x64\x56\xb9\x5e\x55\xdc\xc5\x71\x79\x87\x5c\xef\x29\xa3\x7b\x6a\x90\xac\x9b\x53\x77\xc0\x90\xe4\x06\xe1\x93\x53\x66\x96\xc5\x6f\x06\x6d\x3c\x81\xb9\x7d\xff\x0a\x39\x5d\x08\x3b\x90\x4b\x6d\x17\xc0\xe4\x8e\x2b\xf4\x8f\x6e\xea\x62\xf8\x15\xc0\xe3\xa6\xcd\x0a\x46\xa2\xd7\xd8\xb5\xcc\x18\xbc\x81\xb7\xaa\x4c\xd3\xb2\x3c\x60\xd0\x50\x79\xf3\x92\x3f\xe2\xe8\xd1\x4f\x4c\x59\xfe\xf8\x0e\xd9\x34\x0a\xc1\x2c\x87\xdf\xec\x2c\x5a\x01\x86\xef\x1c\xe0\x4d\xcd\x38\x40\x37\x2d\x81\x2b\xc3\x20\xf7\x52\xc1\x5c\xea\x80\x49\x9b\xc0\x8c\x24\x8b\x25\x1c\x5a\xec\x1d\xc8\xcb\x1e\x26\x06\x63\x05\x26\x2a\x1f\x8a\x8b\x15\x4e\x3c\x1e\xa0\xaf\x47\x1c\x14\xce\x0b\x7a\x60\x23\x98\xbb\xd7\xb8\x87\x60\x5b\x17\x6a\xfe\x27\x69\x9d\x03\x71\x8c\x23\xd7\x43\x8e\xe7\x26\xfc\x00\xcf\x66\xb4\xc0\xef\x3f\xf9\x0e\xcc\xd6\x96\x26\x50\xff\x71\xd8\xd9\x9f\xb0\xc9\xf6\x89\x5f\xfa\x35\x62\xc5\x17\x80\xbd\x0d\x4e\xe7\x6c\xc4\x95\xbd\x85\x52\x1f\x18\x3f\x25\x61\xd0\xc3\xc7\xc9\xdb\x6d\x7d\x44\x28\xce\x84\xcf\x2a\x63\xb8\xf9\x6c\x79\xf5\x7e\xab\xc0\x31\x6e\x5c\x3b\xc1\x16\x70\xa8\xfc\x83\x72\x24\x92\xda\x8c\x32\xe9\xa8\xc8\x69\xd9\x4a\x48\x11\x88\x61\x90\xad\xa4\xdc\xab\xce\xf0\x38\xc4\x1a\xb2\xf4\xda\x22\xe0\x38\x4d\x6d\x5d\xae\x51\x54\xce\xc2\x6c\xe6\x71\x71\x98\x4e\xd9\x1c\xbc\x39\x28\x67\x11\xdf\x2e\x3b\xf6\x5a\xcd\x80\xb4\x36\x46\x24\x6a\x1a\x37\x9f\xce\x0d\xa0\x75\x81\x53\x5c\xbf\x8e\x88\xef\x3d\x34\x60\x33\xa7\x4f\x56\x34\xf6\xef\x48\x81\x8c\x30\x58\x9b\x3f\x28\x65\xc7\x43\xe8\x35\x35\xbd\xcd\xe8\x0f\xf1\xd6\xa2\xa8\x19\x38\x79\x20\xb0\x88\xe3\xd6\xa8\xcc\x07\x72\x9e\x93\xca\x50\x77\xfe\xe4\x00\x6e\x47\x49\x07\xcb\x2f\x37\x24\xcb\xfb\x18\x72\x26\x90\x54\xd2\x87\x72\x33\xee\x61\xc2\x39\x55\xc2\xc6\x84\xd0\x26\xde\x86\x05\xd4\x14\xbe\x98\x97\x0f\x0c\xf2\x79\x76\xde\x76\x35\xbc\x87\x66\x88\x37\x62\xb0\x87\x2d\x92\xa7\xf1\xda\xd2\xe2\xe2\x6a\x42\x7f\x84\x88\xa2\x69\xe4\x0f\x3b\x8d\xff\x64\x4a\x38\x5c\x9e\x0f\x13\xe2\x3d\x3f\xdf\xc2\x43\x7e\x51\x53\x5a\x3b\x9a\x09\x03\xe1\xbf\x0c\x62\x9f\x79\x85\xa5\xa0\xe1\x58\x16\x4c\xcf\x65\xf4\xa4\x8d\xdd\x5c\xf4\x19\x9f\x63\xb7\x68\x37\x52\xde\x45\xde\x25\xe7\x7a\xda\x62\xe4\x89\xd2\x18\x7f\xfb\x29\x35\xdf\x64\x5f\x42\xbe\xc3\x1f\x95\x46\x3f\x39\x92\x7e\x7e\xca\xfb\x71\x0c\xd4\x4f\x4f\x85\xd3\x4f\x39\xf7\x46\x56\xa6\x3f\xa9\xfd\x1f\x43\xaa\x6d\x5a\x58\x2e\x1c\x76\x6f\x46\x84\xe0\x54\x35\x22\x3c\xef\x08\xf1\x39\x9b\x67\xd7\x10\x5c\xd7\x2b\x5f\x47\x89\xe3\x69\xf2\xc1\x56\x49\x2f\x11\x5a\x51\xdd\x0e\xf3\x54\x3d\x09\x77\x9c\xe0\x4e\xeb\xd9\xb1\xea\xaf\x11\x53\x5e\xd6\x2d\xc7\x97\x3f\x52\x85\x6e\x99\x7d\xa1\x7f\xfd\x0e\xca\x8d\xdd\xa4\x75\x47\xbf\x1f\xd7\x3f\x72\x77\x58\x30\x68\xba\xaf\xb1\x3b\x63\x12\x64\xf8\xcf\x52\xf9\x0c\xe3\x12\x79\x18\x56\x3a\x2e\xb0\x16\x73\x16\x12\xc3\xcd\xf7\xea\x17\x87\x43\x74\x9d\x1f\xdc\xde\x5a\x65\x99\xce\xc1\xf1\x8c\x23\x96\xfc\x32\x73\xb7\x01\x09\x6b\xab\xe0\xa3\x6c\x78\x61\x84\x6b\xe6\x72\x25\x0a\x85\xb1\xa2\x3f\x21\x60\x10\x61\xc5\x43\xbc\x09\xe5\xc9\x8e\xff\xc8\x3f\x51\x48\x90\xb8\xa5\x88\x4f\x67\x71\x1f\xfe\x8b\x1b\xb1\x71\xb7\xc6\x78\x07\xfd\xd5\xf9\x8d\xf0\xb0\xfe\x24\x0f\x58\x28\x54\x04\xb9\x73\x48\x50\xa4\x08\xc5\x1f\xb4\xd5\x7a\x64\xcd\xe5\x8f\x4c\xa5\x21\xff\x34\x56\xca\xe1\x63\x5c\xc2\x79\xd1\xad\xcb\x0b\x5a\xfe\x51\x04\x3b\x66\x2c\x36\x55\x68\xd5\x68\x6a\xcc\xa3\x6c\x1a\xe1\x81\x38\x0a\x67\x26\xaf\x00\xa6\xd6\xf4\x9d\x7d\xf4\xe3\xe2\xe0\xa1\x25\x2b\x74\x9d\xef\x70\x90\x29\xc7\x70\x02\xa3\x29\x33\x28\xef\xdb\xb2\x2c\x28\xca\x80\x80\x2d\x5a\x33\xd6\x48\x20\xe2\x25\x2c\x24\xcb\xa9\xb3\xab\xbe\x24\x62\xac\xe4\xf4\x5b\xb5\x71\x14\xdb\x92\x0f\x2c\x2b\xb5\x1e\x97\xa1\x8e\xe3\x5d\x53\xcf\x7e\x53\x55\xe3\x0d\x68\x8a\x6b\x17\x08\xa7\x75\xe2\xd7\xcc\xbe\x05\xef\x97\x63\x33\xdd\x86\x52\x69\xea\x46\x47\x47\xff\xec\x4d\xfb\x1b\xd2\x36\xe4\xcf\x14\xe8\x72\x07\x2f\x35\x8f\x85\x17\x0e\x48\x1b\xe0\xed\x14\xe1\xee\xc9\x19\xc4\x65\x60\x13\x6c\x8c\x0c\xcf\x9e\xa2\x07\xa3\x45\x28\x48\x1a\xdf\x7c\xc8\x3a\x61\x39\xb1\x54\x87\xc8\x4e\x9b\xff\xbb\x8d\x71\x35\x2e\xc5\xf3\x78\x68\x49\x02\x03\xe2\xd4\xf7\xcb\x20\x46\xe9\x35\xb3\xbb\xea\x77\xd8\x0b\x4b\xd2\x99\xd8\x02\xbe\x4f\x39\x3c\x46\xee\x98\x01\x75\x6b\x9d\xe6\x68\xc6\xe2\xee\x83\xfb\x58\xbf\xea\xbb\xff\xe9\x71\x3a\xaa\xaa\x13\xb8\xa1\xa4\xa5\xb1\xb5\xbf\xd7\x24\x0a\x8e\x2a\x1a\x7d\x58\xcb\xca\xaf\x87\x03\x62\x60\xd6\x81\x4a\xb6\x59\x91\xe9\xc4\x32\xc2\x62\x4f\x43\xd2\xd3\xe7\x1a\x1b\xbb\xa5\x70\xd3\x12\xca\x97\x45\x95\x48\x2c\xa8\x49\xef\x67\x3b\x71\x8f\x5c\x76\xfb\x49\x3c\x76\x06\xb7\x0a\x5e\x7e\x19\x09\x87\x47\x9a\xef\x4a\xe1\x55\x82\x5c\x3b\xde\x05\x25\xe5\x33\xa0\x66\x21\x4c\x82\x96\x07\x4a\xbe\x75\x02\xf5\xaa\x13\xba\x53\x2c\x29\x02\x93\xe7\xf2\x76\xa6\x7e\x77\x86\xab\x7f\xb7\x89\xaf\x03\x6b\xc7\x48\x92\x0f\xd8\x19\x5a\x4f\xce\xa6\x1d\xd2\x4f\x22\xad\x5d\x46\x4f\xe5\x66\x5b\x74\x55\x76\x5e\x1c\xbb\xf8\x79\xbb\xb2\x4a\xea\xa1\x7a\xe9\xf8\x47\xcb\xcf\x52\xf6\x40\x01\x9b\x51\x77\x39\x7e\xcd\x5d\x44\x7d\x19\x97\xa3\x3f\xfb\x55\x9d\x3c\x85\x40\xa2\x50\x75\xf6\x8e\x28\x6a\x8f\x2b\x9b\x1e\x72\x1b\xce\xc8\x97\xe0\xd2\x78\xae\x9f\x2f\x5f\xe0\xe8\x7f\x7b\x96\xf6\x2c\x5a\xca\x9f\x2d\xbc\x81\xcb\x78\xaa\x51\xfa\x7d\x82\x96\x59\xdf\x54\xd9\x59\x2a\xbd\x09\x00\xc1\xc9\xe5\xac\xfd\x2c\xc7\xc3\x59\x70\xad\xe6\x16\x04\xce\x93\x1f\xd7\x6e\x70\xe3\x94\xbf\x63\x86\x44\x30\x02\xe9\x47\x51\xc0\xf0\xe1\x95\x37\xdf\x77\x52\x5e\xa2\xf5\x33\x69\x74\xe1\x5e\xf9\x93\xc3\xfa\x10\x18\x6e\x78\x16\x9e\x6b\x7d\xc0\x89\xc5\x12\xe6\xdd\xdb\x75\x78\xef\xc7\xcb\x05\x12\xb1\x57\xd7\x41\xad\x9d\xdb\xbc\x5e\xde\x90\x15\x77\x8d\xac\x10\xe2\xb1\x9f\x1c\xfe\x8f\xe7\xa5\x9c\xf4\x81\xc6\xca\x12\x8f\x87\xd1\x3c\xdb\x2f\xb4\x20\x71\x5f\x59\x6b\xe5\xe8\xa7\x8f\x85\x16\xea\x4d\xb7\x6b\x84\xb5\xc6\xdd\x33\x5b\x02\x55\xad\xd9\x87\x93\x63\x05\xfb\x80\xad\x86\x78\x55\xe0\xea\x05\xb5\x0a\xa7\x46\x0b\xcc\xd8\xad\x20\x56\x0e\xbb\xce\x38\x6d\xfb\xdc\x6b\xa2\x74\x9b\x89\x85\x41\xb2\x79\xd8\x46\xae\x9d\xbc\x62\x91\x90\x64\x79\x66\xbf\xb9\x23\xdb\x96\x89\x09\x6d\x8f\x52\x54\x36\xa3\x11\xd8\x7d\x8f\x36\x08\x6c\x20\x63\x45\x84\xfd\x23\x17\xd8\xf6\xa1\x4e\x69\xb9\x1d\x06\x61\xb0\x28\xf9\x77\xe3\x15\x12\x74\x5a\x6d\xde\xd2\x99\x29\x94\x9d\x63\x38\x29\xb6\x0f\x2b\xf2\xbe\x7d\x22\xf5\xf8\x1a\x49\x55\xf6\x37\xcf\x9a\xe8\xaf\xf2\xcb\x3f\x2c\x0d\x2d\xf8\x8a\x8c\x40\xf5\x9d\xe5\x37\x33\x22\xbb\xfb\x22\x83\x7e\xb3\xac\xfb\x3a\x2f\xd3\x36\x85\x9d\x32\xe0\x5b\x0f\x10\x08\x2b\xa4\x16\x65\x09\x7f\x3d\x88\xe2\x26\xc3\xc0\x1c\x6a\x14\xb2\xce\xb2\x89\x2e\x9b\x10\x8f\xcb\x5a\xad\x3f\x83\x59\xde\xb3\x5b\xea\x04\xa7\xfd\x1a\x1a\xb2\xdd\x1b\x69\xed\xe0\x22\x99\xce\x72\x35\x58\xf8\xb9\x94\x85\x4c\xa2\xc7\xb3\x94\x33\x82\x54\xcf\xee\xdd\x8f\xbb\x05\xa1\xa1\x1d\x68\x4e\x39\x95\xc0\x56\x72\x89\xae\x16\xd3\xff\x27\xf9\x48\x52\x65\x20\x43\xc8\x13\x17\x29\x5f\x3f\x1f\xec\xa8\x22\x16\xc9\x00\x28\x21\x5f\xbd\xc1\xdc\xb1\xe1\xde\x4c\x67\x85\x9e\xa7\xb0\x08\x91\x2f\xa4\x92\xa6\xa6\x60\xa8\x52\xfc\x59\x93\x98\xb0\xdf\x11\xd0\x0a\xac\x37\x22\x4e\x1b\x90\xf8\x0e\x8d\x42\x80\x19\x31\x8f\x52\x7b\x6a\x04\x69\x8b\xc1\xde\xc0\xa0\x7b\x4c\x46\x22\x3d\x34\x80\xd6\xaa\x46\x74\xa0\xc7\x77\xc5\x80\x05\xe0\xf6\x83\x2c\x9d\x01\xee\x5a\xc1\xa9\x9c\xfb\x26\x31\xf1\x5b\x78\x2e\x59\x9c\x65\x71\x41\x27\xfd\x3f\x68\xef\xae\x03\x9f\x14\xb4\xa0\x6c\xcf\xfe\x7b\xdc\x79\xec\x07\x40\x9b\x37\xe4\x4b\x1e\xaa\x7b\xcb\x32\x5b\x47\x72\x9a\x72\xa2\x54\xe0\xcd\x50\x0f\x13\xff\x2c\x45\x42\x4d\x5c\xa2\xf0\x82\x30\xea\xc9\x30\x1c\xa1\xc4\x74\x29\x57\x16\x14\xa8\x25\x01\x1d\xdb\xaf\x2a\x1d\x0e\x68\xa9\xea\x50\xe3\xc0\xc7\x58\xae\x33\x01\xd0\x5b\x39\x39\xec\x1e\x82\xcf\xf9\xd2\x69\x9b\xb6\x6c\xa9\xe8\x9c\x1d\x2f\x05\x4c\xc4\x7a\x48\xb4\xc4\x30\x03\xd4\x03\x63\xd6\xe8\xee\xf0\xc1\x65\x37\xd4\x4a\xe7\x0a\x96\x0b\x6f\x05\xfb\x2e\x8b\x40\xea\x00\x9f\x8d\x06\x03\x6a\x7e\x1b\x6b\xee\x48\xf5\x0c\xe0\x19\xe6\x0c\x5e\x59\x52\xd8\x02\x25\x93\x38\xd3\x5c\x6d\x5b\xe0\x80\xd1\xd5\x68\x2d\x5c\x5a\xfc\xa0\x50\x94\xfa\x33\xe3\x5b\x8f\x18\xac\x3b\xfe\xcf\x51\x9b\x1f\x01\x12\x19\x66\xad\x3c\x40\xb4\x37\x17\xdb\x84\xd2\x45\x33\x68\x55\x80\xab\xbd\xb7\x29\xcb\x22\x2d\x7c\x52\x77\x49\xb5\xca\x2e\x67\x3d\x97\x98\xe6\x53\x2b\x32\x79\x6a\xe4\xcf\xe4\x17\x64\x70\x96\xa2\xb3\x6a\x75\xfd\x37\x96\xf5\x87\x7f\xe6\x48\xf7\x95\x25\x8d\x6f\xfa\x73\x4e\xfd\xa1\x99\xfc\x53\xd6\xc2\xee\xe3\x24\xad\x05\x4c\x4b\x0d\x9d\xc9\xf5\x2b\x55\x02\x34\xa5\x4f\x63\xdc\xd1\xa1\x7d\xe7\xa8\x3c\xde\x57\x40\x3c\x5c\x3a\x77\xdd\x76\xb3\x9d\x76\xdf\x63\x67\x3c\xe5\xfd\xa8\xab\x22\xe0\x6b\xbd\x60\x6f\xd5\x0b\x24\x02\xc6\xc9\xfb\xb2\x21\xb7\x1d\x35\xe3\xb5\x60\x03\x5a\x0f\xee\xe2\x81\x73\xdc\x18\x85\x46\xfb\x92\xe7\xc2\x3b\x2d\x11\xc0\x55\x5e\xde\xaf\x30\xea\x2f\xb1\x1b\x7e\xa7\xa4\x3b\x12\xdb\x96\x2f\xc3\x18\x2f\x5b\xa2\x44\x3b\x03\xcc\xa9\xbe\x4c\x6b\x1e\x03\x8c\xf0\xfd\x4b\xa0\x9e\x02\x9d\x25\x1a\x7c\xd5\xa4\x27\x85\x69\x09\xdb\x95\x32\xfb\xfc\x72\xdb\x2f\xfb\x06\xf9\x53\x9d\x6b\x17\xd7\x10\x90\x64\xd8\x33\x06\xd8\xcc\xf4\xf2\xa7\xd1\x61\xb0\x37\xbf\x80\xe8\xa7\xb0\x5f\x7b\xc2\xf8\x20\x4f\xdd\x85\x1f\xef\xe3\xf6\xad\x13\x8d\x7f\x0e\x63\xcb\x92\xca\x19\xa5\xbd\x16\x8d\x83\x3d\x15\x50\x25\xda\xa7\xaa\x4b\x4d\x4d\x9e\x15\x7b\x7f\xde\xd9\xad\x3a\x3e\x46\x5d\x11\xaa\xc2\xd7\x81\xa9\x68\xc8\x42\x7f\x7b\xf1\x2a\x0e\xf4\xe8\x09\xc4\x82\x16\x7c\x68\x20\x51\xe8\x39\x2f\xf2\xea\x14\xe5\x16\x68\xa4\xb1\x15\x62\xd2\xa9\x93\x23\x3d\x6d\x74\x5b\x0e\x46\x4b\x18\x14\xf2\xe1\xbc\xaf\x3e\x59\x63\x9a\x64\x8d\xdd\xc5\x81\x8d\xd0\x38\xfe\x8a\x6c\x47\x14\xd8\x92\xe2\x7a\x3e\xa2\xe7\x5b\x06\xed\x03\x21\x4f\xba\x57\x02\x9f\x23\x4f\x65\xa6\x16\xd8\x8c\x7f\x48\x23\x55\x44\xb4\x27\x0d\x4f\x52\x45\x97\xa1\xe4\x6d\x4c\x1a\x85\x35\xc8\xeb\x4a\xdf\x04\xf8\xac\x5b\x75\x4f\x0f\xcc\xa4\x83\x92\xb2\x0f\xb0\x6f\x78\x6d\x1c\x69\xfb\x13\x5b\xeb\x28\x7b\x00\x3d\xb1\xb2\xfe\x40\x65\x4b\xc8\xf6\x15\x86\x8e\x1f\xb5\x45\xc0\x35\x1e\xb5\x7f\xca\x24\xf8\x99\x8d\x67\x7e\x16\xec\x82\x16\x83\xb8\x9f\x79\x85\x7a\x29\x74\xa7\xb0\xda\x8b\x0d\xd7\xfe\x61\xc8\x93\x00\x68\x64\x8b\x45\x43\x6f\x87\x38\x1b\x4e\x96\x18\x97\x5f\x2e\xa8\x7b\x10\x9c\xc6\x3e\x88\x8a\xd3\xf5\x52\x99\x2e\x46\x19\xaa\xf8\x54\x63\x2e\xdd\x1c\x96\xeb\x19\x56\x7f\x1c\x77\x36\x37\x25\x70\x6d\xe4\xf9\x5c\x1d\xb8\x4c\x64\x7a\x35\x38\x8c\xfc\x54\xf9\x97\x05\x36\xdd\x5e\x49\x65\x40\x8e\x25\x43\x44\xd6\x9b\x04\x91\x47\xb5\xff\xe5\x2a\xab\xfb\x46\x2b\x73\x20\xc1\xd5\x3d\x64\xc2\x5b\x9f\x3a\x09\x74\x46\x1a\x59\xb5\x73\xa7\xbd\xa9\x46\xbb\xc3\xbd\x90\x76\x18\x88\x28\xc7\x81\x3a\x67\x6b\x73\x57\x8b\x45\x99\x4a\x85\x6e\xb1\x03\xd9\xd6\xc8\xf2\x81\xf5\xa9\xa6\xa6\x3d\x97\xe9\x8a\x0f\xce\xe1\x25\x5b\x96\xd1\x2a\x6b\xc4\x92\x6a\x03\xcf\x05\x5b\xad\xce\x23\xde\x54\xf1\xc2\xbe\x8c\xc0\x2f\xf9\x8c\x25\x29\xcd\xa4\x0c\x9e\xbd\xa3\x8f\x77\x88\x93\xfc\xc1\x67\x60\x0b\x65\xdf\xa7\xdf\x8e\xa9\x6a\x7e\x91\xa9\x9a\x8a\x97\xa1\xfa\x9a\xfb\x94\xe5\x60\xb4\xd3\x17\xe8\xc1\x82\x14\xd8\x76\x40\xdb\xc2\x66\x10\xb0\x36\xc7\x48\x7f\x22\xd7\xca\x71\x8a\x3b\x14\x9e\x81\x4e\x77\x6c\x61\x6a\xa8\xf8\xc9\xdb\xff\x39\x4e\xcd\x0a\xd5\x71\x7d\x6f\xc2\x01\xe9\x96\xca\x0f\xf3\x60\x04\x8a\x1c\x56\xfb\xc6\xfa\xda\x07\x8c\x4f\x96\x80\xb7\xcb\x9d\x8f\x64\xe5\xef\x23\x88\xf3\x40\xb4\x23\x18\xed\xdc\x5e\x02\xa9\x21\xd2\x53\x05\x0b\x47\x3c\xa5\x8a\xa3\xaf\x6f\x41\x2a\x75\x46\x02\xb9\xd3\x6f\x8e\xa8\xa8\x3d\xbd\x4b\x71\xc1\x77\x95\x5e\xa3\xe6\xa4\x1d\x2d\x45\xbe\x8e\x94\xaa\x7a\x81\xc4\x93\xc2\x62\xd5\xa5\x6b\x92\xf1\xe8\xc8\x3d\xdb\xff\xad\xda\xf9\x6c\xf9\x93\xa2\x0b\xe2\x5c\x34\x09\x3a\x19\xf5\xd1\xa8\x49\x40\xf9\xea\xe2\x81\x70\xe2\xb2\x09\x08\x74\x7a\xac\xf7\x71\x49\xd9\xc6\x7b\x4d\x3a\x7b\x55\x8f\x2b\xa5\xa6\xd5\xdc\x32\x04\x45\x6d\x6a\x98\x10\x5e\x1e\xdb\x8a\x0e\xef\x6e\x42\x21\x40\x6d\x7a\xc5\x2b\xed\x55\xc0\xba\xb7\xe1\xb2\x8d\x40\x85\x80\x1e\xca\x18\x51\x5f\x01\x03\x0b\xbc\xfa\xd3\xeb\x2f\x56\x96\x55\xba\x50\x19\xe4\xd7\xa5\x90\x55\x17\x1a\x02\x04\x5f\xff\x5b\x4f\xa5\x95\xb1\x6b\x89\x88\x3c\x9c\x2d\x43\x85\xd9\xa0\x1e\x0a\xd3\xc4\x4d\x6f\xa7\x3d\x2d\xcc\x15\xbb\x75\xaf\xe3\x7f\x31\x5c\xda\xb1\x7e\x39\xce\x60\x0b\xd9\x2d\x0f\x77\x7f\x30\xc4\x0b\x5c\xe8\xf6\xe5\x06\x86\x83\x3e\x1c\x68\x9b\x78\x87\xe8\xca\xa7\xe8\xac\x7e\x65\xcb\xc1\x6d\x51\x9f\x3c\xad\x26\x2a\x42\xfd\x3a\x09\xbe\x2e\x4f\x80\x9a\x80\x5f\x6b\x79\xfe\x83\xfd\xd0\xf5\x33\xcc\x01\x69\x57\x8d\x83\x36\x7a\xb1\xab\x93\xdb\xab\x2c\x4f\x78\x06\xaf\x20\x3a\xdc\x88\x48\x5f\xfc\x49\xba\xba\xee\x15\xee\xf6\x2d\xa0\x91\xda\xdb\x0f\xc1\x6c\x3d\x52\xd9\x42\x55\x8f\x45\xb9\x9b\x30\x09\x2a\xb5\x7e\xa5\xb8\x05\xf7\x5e\xd6\x22\xc4\xb7\xfd\x94\x24\xc0\x1b\x2d\x6b\x03\xd5\xfb\x51\xe7\x4f\xb4\xd3\x83\x02\xb0\xa2\x97\xb0\xc4\x40\xf7\xa4\xa8\x4c\x6d\xff\xea\x51\x13\x77\x1a\xc7\xc6\x76\x9e\xcf\x1c\xc3\xfc\xac\x8c\x82\x2c\xb9\x8e\xff\x53\x61\x04\xa3\xfd\xd6\xfc\xbb\x75\x0c\xa3\x43\x06\x39\x0c\x82\xb4\x07\x14\x22\x7e\xac\x6e\x20\xc2\x95\x01\xc5\x8a\xcd\xc1\x1c\x1c\xa5\xc0\xa9\xf5\x97\xed\xc7\x78\x3f\xf0\x6a\xdf\xb2\x85\x6f\xe0\xfa\x40\xaa\x90\x95\xb7\x0a\xa1\xc2\xd4\xe4\xdf\xa0\xaf\xfa\x5b\x29\xff\xa0\x2d\xab\xa4\x81\xaa\xa6\x2d\x5f\x98\x3e\xcd\x65\x5a\xb4\x42\xc6\xc7\xa9\x06\xfe\x05\x92\xf1\x84\xb5\xbb\x1e\x0a\x8b\xf0\x88\x1f\x93\x0e\x97\x83\x69\xd7\x43\xa3\x9b\x0b\x59\x6e\xc5\xa8\x89\x69\x7b\x8c\x64\x58\x0f\xfd\x65\x96\xab\xd3\xf5\x1e\x18\xd9\x89\x1e\xec\xb0\x94\xcd\x51\xe7\x80\x81\x69\xf6\x40\x19\xea\x8b\xcd\xe7\x48\x3e\x72\x46\x5c\x30\xbf\x87\xec\x20\x50\xe4\xeb\xf1\x57\x65\xdf\x4c\x77\xb5\xa5\x7e\xf1\xaf\x08\x98\x1a\xd0\x50\x60\xd6\x97\x71\x58\x0e\x6f\x0a\x1d\xf4\xf5\x09\x2a\x46\xf2\x3f\xd0\x78\x84\x67\x2f\xf2\xbf\xc9\xff\x1e\x4c\x8a\xc4\x13\x96\xcf\x14\x38\x75\xbe\xd2\x6e\x17\x68\xce\x26\x67\x5b\xb0\x5a\xd2\xb6\x0c\xbd\xd2\xee\x76\x81\xd9\x42\xb3\xf5\x3f\x0d\xd1\xfa\xd1\x06\x69\x61\x1c\xbc\x12\xf9\xf8\x0b\x32\x7a\x4f\xe2\x63\x87\xc4\x2e\xfd\x79\xf9\xd3\x3e\x1f\x79\x73\xcc\x06\x7d\x6b\x19\x00\xa1\xf7\x96\xaa\x30\xdd\xf9\x79\x1c\xe9\x9f\x4c\x3c\x53\x96\x7f\x3a\x99\xe7\x4f\x39\x2b\x9f\x31\x30\xdf\x20\x90\x67\x13\xf9\x88\x91\x2f\x5f\xfe\xb5\xa7\xdb\x71\xc2\xc9\x2d\xc6\x99\x4d\xdd\x9b\xf3\x72\xce\x97\x30\x82\x98\x79\xf2\xce\x11\xb1\x3f\xa5\x60\xb8\x49\x82\x6c\xa4\xdb\x2a\xdc\x71\xcf\xc3\x67\x89\x8b\xe4\x5b\x81\x1c\xc8\x3a\x50\x1a\x95\xd3\x08\x5b\xf3\xb6\x6f\x1e\x67\x3f\xa1\x3b\x14\xa1\x4a\x01\x32\x57\x57\x3e\xb4\xd2\x21\xe7\x7e\x48\xb1\xe8\xce\x6e\xae\x0b\xfc\x8e\x7f\xa1\x4f\x91\xb2\xc6\xa1\xc0\xec\xe8\x80\x96\x45\xe2\xd4\x4d\xd9\x05\x4c\x46\xad\x4b\xa1\x58\x7e\xa3\xd9\xe3\x49\xee\x28\x90\xf5\x23\x82\x52\x43\x20\x55\xa3\x6c\x1a\xc3\x43\xd7\xff\x1c\x66\x77\x23\x2f\xd0\x23\xfb\x25\xd1\x24\xfc\x49\x52\x1a\x93\x22\x33\x9d\x93\x1a\xfc\xd3\xf9\x04\xeb\x91\x40\xb9\x74\xc6\x86\xbf\x5f\xbd\xf7\x72\x10\x2d\xfb\xe7\x98\x72\xf8\x2c\x4f\x65\x3d\xda\xd8\x9f\x9e\xca\x7c\x64\x28\x82\xd9\x5c\x1a\x04\x53\x20\xdc\xcf\x70\x1b\x1d\xb7\xf2\x6f\x9c\xb4\x83\xb1\x06\x79\x16\x0f\x7d\xea\xc7\x3d\xb8\x79\x53\x3a\x59\x2e\xdd\x1c\xc0\xa7\x5b\x7b\x6e\xfa\x1b\x99\x52\x14\xe2\x53\xd2\xa9\xf3\x2c\x2b\x0f\x31\xec\xb2\x87\x98\xe0\xa6\xb3\xbf\xa5\xe6\x7e\xe6\xfd\x23\x6e\xeb\xf3\x01\x87\xd1\x1b\x85\xc8\xfa\xee\x9f\x96\x55\x3d\xfd\xd0\xb2\x23\x9f\x38\xa1\xfc\xd0\x69\x58\xf0\xf6\x89\x08\x35\xae\xdd\x65\x38\x3a\x03\xf9\x87\x42\x79\x41\xe1\x79\x72\xec\xd3\x8f\x34\xab\x3f\xc0\xeb\xc7\x56\xa0\xf8\xa6\x9e\x17\xdc\xc4\xb4\xca\xfe\x54\xd5\x0a\x80\x6f\xed\xa4\x81\x7b\x7f\x87\xe5\x05\xd4\x6d\x84\x5a\xd4\x59\x3f\x72\x1f\xd7\x51\x23\x6d\x4f\x0c\x87\xd3\xf8\x54\xf7\x0b\x6b\xb6\xcd\xef\x9d\xc0\x47\xbc\x6e\xff\x0b\xff\x83\x2b\xbd\x0f\x8e\xa8\x61\x08\xdc\x7d\xd1\x50\x05\x4b\x97\xc3\x80\xa4\x9d\xed\xe7\x7f\x21\x8e\x6e\x55\xc1\xac\xa9\x14\xc0\xfb\x12\xbc\xde\x72\x90\x84\x9b\x37\x5b\x48\x95\x19\x9a\x1c\xfa\xe6\x2f\x03\x92\x4b\xd4\x1c\xe9\x81\x61\x81\x3a\xfa\x0a\x85\x9c\x80\xec\x82\x51\xfa\x86\x87\xe2\xb8\xa1\x6b\x2e\x2f\xb3\xd8\x27\x58\xdd\x1b\x38\xff\xfe\xf3\x60\xd5\x0f\x01\x25\x73\x40\xd0\xb9\x33\x06\x1d\x66\x45\x0f\x1a\xf5\xda\x35\xb8\x9c\xc7\x65\x4f\x72\x24\x3b\x0e\x33\xfd\xf0\x26\x04\x5a\x30\xf2\x21\xd3\x05\xf6\xce\x85\x30\xef\xce\x5d\x05\x88\x8f\x42\x52\x43\x8b\x5f\x01\x40\xc7\x35\xfd\xe8\xcd\x58\x63\x7c\xa0\x2f\x89\x47\x2a\x2b\xc0\x5d\x0a\x65\xed\x44\x1e\xc9\xb6\xc1\x5b\xac\x4d\x65\x88\x56\xb6\x86\x4b\x37\x38\x10\x11\x3d\xbd\x36\x68\x06\x38\x1a\xdf\x21\xf6\x79\x80\x19\x4e\x80\xbc\x36\xf1\x10\xda\x50\x87\xdd\x4f\xb9\x29\xf3\x63\xea\xdb\x8b\x83\x36\x20\x90\x81\x80\x16\x48\xd4\x44\xbe\xd1\x56\x17\xb4\x7c\x26\xea\x26\x6c\x7c\x3a\xa8\xc4\xbe\x90\x67\x1e\x1b\x15\x1f\x97\xfa\xe9\xca\xc1\x9c\x47\x3d\x62\x84\x7c\xb2\xf5\xbd\x9e\xf2\x07\x10\xf5\x47\x81\xe6\xfd\xe7\x7a\x56\xd9\x0e\x4c\x55\x7f\x1d\x26\xc6\x59\xca\xe2\x01\x5a\x65\xaa\xb7\x27\x41\xe8\xe5\xc5\x3e\xec\xfd\x53\x09\xd1\x87\x20\x65\xd0\xde\x63\x20\x83\x54\xe8\xf7\x9f\x5d\x1a\x87\xca\xd6\x1e\xd2\x19\x77\x1d\x01\x84\xbb\xa5\x74\x77\xde\xe4\xfd\x7c\xda\xad\x38\xcf\xb4\x47\xb8\x6f\x97\x9e\xfd\x5e\xbe\x15\x4e\xfd\xf7\x0c\x1d\x25\x17\xda\x7b\x39\xdb\xb4\xe4\x43\x8b\x1d\x6b\xf7\x1d\x7b\x0e\x09\xa9\xcb\x5c\xfa\x16\x5f\x11\xc3\x47\xc4\x22\x2e\x7f\xbc\x19\xf5\x18\x25\x2e\x32\xfe\x90\xc0\xf8\x34\x2e\x15\x10\x1f\xc3\x29\xe5\x3e\x56\x20\xbb\xfc\x86\xf7\x90\x86\x8f\xd8\xf8\x6b\x9b\x04\x24\xbc\xee\xa6\xef\xf2\x30\xd2\xfd\x5d\x24\x95\x72\x0d\x71\xb7\x1b\xfe\x10\x30\xba\xaa\xcf\x00\xd7\x51\x9c\xb0\x7b\x0f\xe7\x09\xa3\xf9\x1c\xeb\x6b\xe9\x0d\xc4\xa7\x17\x66\x9a\x48\x55\xb4\xdf\xdc\x3d\xc1\xf0\xa0\xd7\x28\x39\xb4\x15\x26\x60\x7a\x4d\x44\x2a\x2e\xb1\x93\xea\x7f\x1d\xee\xfc\x75\x20\x50\xfb\xb7\x54\x4d\x75\xd8\xaf\x81\xc1\x43\x97\xe6\xbd\x5a\xff\xab\x1b\x2b\xbe\x8d\xac\xb3\xd8\x44\xec\x7d\x10\xe3\xfa\xe5\xef\xc3\xdf\xa8\x2f\xb3\xaf\x45\xdf\x6f\x6f\x39\xd1\x0e\x0d\xf1\x72\x79\x53\xb4\x8e\xd5\xfd\xd0\xad\x54\xc1\xf7\x80\x13\x53\xff\xd8\x12\x24\xa8\x7e\x1e\x05\xc4\x43\xe3\xa3\x3b\x90\xc6\x15\xcf\x99\x43\xf2\x5d\xe5\xfe\xd6\x7a\xeb\x93\x96\x45\x8c\xf4\xf9\xfe\xb1\xfd\x3f\x57\xdf\xb6\xe5\xaa\xce\x33\xfb\x2e\xb9\xe9\x9b\xfd\x52\x06\x1c\xa0\x03\x98\x8f\x43\x32\xe9\xa7\xdf\x2a\x55\xc9\x64\xfd\x73\xad\x31\x90\x09\x49\x68\x02\xb6\x25\xd7\xc1\x7e\xd9\x41\x57\xc6\x13\x13\x3d\x04\xdd\x35\xe9\x2e\xea\x5c\x6f\x8d\xb4\xe3\x33\x64\xf8\xba\x28\xb9\x74\xee\xa3\xa2\x9d\x10\x3d\xc2\xb6\x50\xfd\xd7\x66\x33\x10\xb7\xa0\xe9\x54\x17\x66\xaa\x5d\x89\xed\x66\xf3\x4d\xbe\xb4\xfa\x75\xf5\x70\x76\x5d\xb9\x58\x38\x97\x88\x0d\x96\xf5\x4b\xf5\x70\x74\x0f\xa6\x4a\xf9\x3e\xc8\x7b\x08\xdf\x46\xbe\xcf\xfe\xec\x0f\xd7\xe4\x77\x37\x4e\x7e\x88\xe7\x0d\x54\x64\x65\x87\x27\x99\x12\x20\x5c\x9d\x2a\xae\x8f\xa4\x0d\x4a\x65\x7e\x43\x0e\xc4\xa3\xf0\xd5\xee\xf4\xfb\x75\x23\x68\x8f\xfa\x74\x5f\x9e\x74\xce\xf3\x98\x62\xf1\x13\x90\x00\x4a\xd1\x8b\xbe\xad\xd5\x7d\x0d\xb0\x8c\xc7\x5e\x1d\x6a\x57\x61\xea\x50\x61\x9e\x58\x1d\x47\x48\xf8\x30\x69\xe9\xd9\x2b\x14\xfc\x98\xa7\x8d\x6e\x21\xbc\xdc\x96\xd8\xdb\xa4\x5b\xab\x39\xb1\x57\xe8\x30\xe7\xf3\xed\xca\xde\xb3\x4b\xb3\x2a\xaa\x16\x05\xd0\x20\x8d\xfb\x25\xf2\x76\x47\x3a\x5c\xf7\x53\xb2\xbc\x0e\x5a\xa7\xca\x08\x65\xb0\xe9\x86\x80\xf1\x3e\x5f\xe4\xdd\xd0\xd2\x0d\x14\xaa\xcc\xb7\xb9\xe0\x66\x23\x19\x83\xbc\x0a\x7e\x60\x93\x13\x2d\x7b\x39\x56\x60\xbb\xd8\xb5\x79\x43\xab\xe9\x5b\xe0\xf0\xd9\x5a\x6e\xdb\xc8\xb5\x9a\x45\x5a\xfa\x5a\x0e\x45\x42\x11\x10\x21\x53\xa1\x06\xa5\x42\x01\x9c\x0c\xc7\x90\x62\xaf\x15\x2f\x00\xf4\x40\x1b\x4e\x94\x0e\x1f\xe8\x6e\xc9\x67\xfb\x75\x26\x31\xe9\x49\xde\xfe\x72\xa7\xb4\xce\xef\x56\x61\x83\x06\xf4\xd9\x86\x07\x65\x17\x00\x34\x97\x86\x9e\xbf\x98\xe2\x33\x7d\x35\xf4\x75\xf3\x2c\x1f\x18\xb7\x8b\xac\x3b\x6f\xa7\xca\xb0\xc4\xb3\xa8\x39\x83\x12\x1e\x4e\x91\x32\x7f\x2c\xc2\x0b\x30\x57\x6f\x03\xb7\xde\x86\x72\x14\x70\x01\x5a\xa6\x1f\x1d\xd3\xcd\x45\x7f\x9b\x43\x48\x5e\xda\xa6\x28\xbb\x82\xb9\xae\xf9\x8f\xcc\x9d\x2c\x00\xb9\x9a\xcb\xff\x23\x96\x8b\x3c\x42\xb7\xc7\x40\x3f\xd8\x90\x33\xb9\xde\x39\xf4\xbc\x3c\x8c\x17\x63\x39\x02\x58\x02\x51\xc6\x87\x2a\xd8\xec\x02\xcf\x12\x74\x46\x77\xac\x9c\x94\x0d\xb1\x6d\x5c\xf2\x79\x92\x9b\x24\xca\x0a\xda\xbb\x55\xb8\x47\x72\x7f\x8e\xda\x50\xca\x82\x3a\x66\x3f\xbe\x05\x3b\x80\xdb\xa4\x64\xc5\xe0\x38\xe9\x9b\xf5\x88\xfc\xbd\xf5\xf9\x06\x61\x09\x98\x4e\xa1\x27\x7a\xed\x6a\x06\xbf\xdc\xa2\x2e\xd4\xa8\x7d\x89\xd4\x23\xac\xb9\x27\xd9\x5f\xda\x44\xde\x7f\xa8\x84\xc5\x7b\x5f\xd6\x86\x24\xa5\xd6\xc3\xb1\x56\xc0\xed\x22\xb9\x68\xae\x51\x9f\xb1\x8a\xd1\x54\xab\x5b\xd0\xc4\xb1\x40\xc8\xa5\x71\x14\x9e\xb9\x74\xed\xac\x34\x5f\x1c\x0f\xe4\x47\x03\x8a\x4d\xe0\xe7\x9b\x2d\x5c\x7f\x6c\x1e\xfc\xd1\x56\x7c\x6e\x24\x3a\xa4\x84\x40\x64\x5a\x48\x06\xdc\xfe\x02\x1b\x9c\x01\x43\x38\xb5\x30\xdb\x94\x9d\x5e\x76\xf6\xb7\x08\xd3\xd6\x4c\x67\x96\x2f\x82\xb3\xc9\xb5\xc0\xd0\xd8\x7d\x47\x90\x83\x3d\xb7\x49\x35\x55\x98\x73\xb1\x0b\x07\x51\xd1\xf7\x10\x02\xdc\xe4\xac\x85\x6b\xeb\x39\x9a\xb3\x67\xd4\x9e\x54\x6e\x6f\xc4\xa7\x69\x00\x41\x14\xab\xfb\xaf\x94\x17\x89\xdd\xd7\x47\x45\xe4\x26\xbd\x6f\x09\xe8\x5d\x03\xbc\xac\x2a\xab\xf8\xf3\xe6\x00\x17\x72\xc8\xb7\x99\x0b\x7a\x16\xf5\x81\x1d\x08\xdc\x40\x22\x74\xbe\x49\xac\x11\x34\x20\x55\x7b\xc1\xa1\x41\x29\xda\x45\xb7\xd3\x8b\x78\x85\x97\xde\x0b\xea\xb4\x9c\x36\x53\x5b\x91\x09\xed\x6b\x95\xbc\x25\xad\x2f\x43\xc3\x13\x69\xe6\x34\x92\xb0\x7d\x48\x4c\x82\x8d\xad\xb4\x9a\xe5\x20\xbf\x22\xa2\x00\xec\x60\x5f\xc3\xde\x03\xe2\x01\x32\x3a\x79\xfb\x96\xd2\xd7\xa5\x75\x74\x5f\xa3\x64\xa7\xd7\xe1\xfa\x77\xab\x2d\xef\x43\xa0\x37\xec\x09\x22\x04\xc7\xeb\x67\x7c\x72\xd2\x26\x54\x00\x5d\x52\x7d\x00\xfc\x17\xd6\x55\xae\x7f\x3b\x54\xdc\x2d\x9a\x36\x38\xf8\x75\x81\x56\x35\x94\xb3\xf9\xed\xcb\x15\x3a\xd4\xb4\x24\x96\x62\xb5\x5e\xc4\x9a\xb9\x0f\x69\x4a\xbf\x5d\xc1\x3a\x56\xd0\x20\x49\x2d\x04\xbf\x5d\xe0\xed\x8c\xc2\x49\x02\x56\x80\x00\x01\xd7\x26\xd1\x29\x58\x2f\xbc\xdc\x0d\xc7\xa9\x2a\x4c\xfc\x88\x2a\xdc\x91\xc6\x0d\xa5\x55\x9e\xd7\x28\xfa\xbb\x4d\xfb\xe9\x3b\xc0\x3f\x02\x2a\xb7\xa8\xd5\x71\xf6\x9a\x9e\x36\xd3\x5e\x14\x8d\x5e\x9f\x48\x36\x54\x0a\xb1\xf0\x55\x64\xb6\x5f\x19\x89\x3a\x25\xa7\x15\x7b\xd8\x9e\x73\x48\x50\x42\xb0\x1a\x88\xd4\x9a\x5d\xa7\xe6\x82\x4f\xad\x47\xee\x41\x8c\xa3\xfe\x46\x97\x14\xbe\x38\xe7\xb8\x4a\x19\xbc\xb4\x76\xcd\x0e\x70\xba\xc2\xa9\xf5\xb2\x5b\x6e\x1f\x2c\xef\xb6\xf8\x73\x72\xfd\xea\xb3\x8d\xf2\x4c\x07\x59\x9e\x03\x1f\x26\xf7\xb3\x2c\x40\xad\x7b\xe3\x93\xe0\x4c\x79\x59\x33\x01\x60\xb0\x8e\x3e\x3d\x73\x3f\xd0\x7f\x0a\xb8\x06\x03\xad\x6a\xad\xfe\xfb\x7c\xfd\x21\xb3\xd0\xc0\x1e\x8c\xa1\xcd\xee\xf2\xd5\x01\x43\x60\xe6\xf6\x51\x25\x0a\x5b\xbd\x94\x34\xb7\x70\xcc\x01\xe9\xf0\x07\x1d\x77\x3f\xb7\xff\xf6\x27\x91\x3f\x00\x71\x7b\x5f\xa6\xf5\x38\x7c\x1b\x81\x36\x70\x9e\xba\xa5\xb7\xce\x65\xc7\x72\x9b\xff\x1e\xef\x32\xbd\xf6\x4f\xea\xfd\xaf\x7d\x8f\x7f\x0b\xf5\x43\xde\x23\x34\x56\x76\x46\x63\xa0\xf2\xdc\x7d\x54\x13\x59\xa2\x0f\xe0\x4f\xce\xe4\x13\x56\x74\x2a\xeb\xbd\x69\x2a\xa2\x08\x6c\x4b\xc6\xc4\xe4\xbd\xf3\x30\xfa\x5a\x25\xe2\x74\x0d\xa7\xf0\x0b\x17\x37\x1c\x18\xde\xf1\x2d\xc9\x2e\x7a\x61\xd4\x8d\x4c\xea\xcf\xd3\x97\x47\x4f\x18\x5d\xf6\xc4\x32\x08\x6c\x72\x42\xbf\x92\x43\xa9\xa5\xd8\x81\x36\x40\x65\x30\x60\x05\xa3\x63\x29\x26\x21\x17\xc6\x50\xa1\xa9\x7b\x64\x5d\xce\x37\x52\x17\xa8\x36\xdc\xcc\xf4\x94\x48\x37\x99\xf2\x4b\xc4\xad\x9e\x8c\x73\x69\xc3\x2b\xc0\x19\xf2\x9b\xe8\xf2\x96\x2f\xee\x0f\x42\x16\x1c\x14\x70\xee\xac\xae\x40\xd9\x5a\x65\x8c\x03\x00\x7c\xe1\x11\x2e\xae\xc9\x1d\xee\xd9\xc6\xd5\x78\x87\x25\xf0\x55\x16\xf7\x6d\xeb\x43\x9b\xf6\xb5\x5a\x11\xc5\x02\xb6\x3e\x25\x2b\x6f\x26\x68\x41\xb9\xb9\xf5\x62\x76\x87\xc8\x75\xd5\x0d\x55\x29\x28\x48\x0c\x83\xb4\xf9\xbd\x81\x62\x50\xc5\x34\x70\xfa\x72\x58\xa7\x26\xbf\x61\x54\x57\x77\xf8\xff\x3f\x82\x8a\xcf\x1f\xff\xc0\x53\xe4\xa0\x08\xa4\xc6\xab\x86\xfc\xc3\x26\x5c\xdc\x42\xbb\x46\xaa\x01\x70\x0c\xf5\x7e\x0e\xd6\xf8\x1a\xf7\x8e\x71\xb5\xfd\xfa\x9b\x85\x7c\x70\x05\xee\x86\xd3\x95\x83\x86\xdb\x07\xcc\xa8\xfc\x34\x98\x11\x57\x07\xd8\xb1\xbb\xe2\xcd\xc4\x74\x1e\xc3\x39\x0b\x0e\x7f\x0c\xdb\x19\xf0\x3f\x8b\xab\x55\xe3\x81\x89\x5a\x64\x76\xe0\x00\x49\xdc\x94\xa2\xdc\xba\x55\x49\x09\x89\xe9\x0e\x50\x9b\xd6\x9b\xf8\xef\x60\x37\xbe\x74\xba\x97\x14\x17\xa7\x26\x79\xc0\x65\x00\x01\xc1\xbd\xc2\x6d\x84\xe5\xeb\xb6\x09\x53\x07\x15\x1d\x3a\xe1\xee\x2e\xa5\xd0\x88\x4c\xe5\x72\x3e\x5c\xe8\x46\xde\xb8\x3f\x2a\x54\x62\xe4\xaf\xb6\x7b\x5f\x90\xef\x90\x41\x38\x82\x9e\x7f\x90\x86\x10\xcb\x7f\x0b\xca\xf2\xb9\x62\x1d\x94\x50\x01\xf4\xad\x84\x46\xcc\xeb\x0f\x83\x9e\xca\x01\x2e\x05\xf0\xa8\xa0\x09\x82\x3b\xce\x46\x29\x81\xb7\x28\xf3\xb0\x33\xa4\x5b\xa2\x5b\x4f\xf7\x2a\x89\xec\x94\x5a\xf7\x48\x42\x9c\x1e\xe7\x8f\x54\xd4\x80\x95\x0d\x03\x45\x36\xd3\x8c\x64\xdd\x63\x22\x40\x8e\x10\x24\x75\xf8\x9c\x76\xc9\x60\x6d\x77\x17\xcb\x10\x94\x06\x7e\x5a\x9c\x7d\x94\x31\x85\xed\xb0\xf1\xb5\x4a\x7c\x83\x22\x7f\xd5\x48\x57\x03\xe0\x09\x99\xf0\x52\xed\x8c\xc4\xfc\x6d\x0b\x68\xc4\x06\x3a\x12\x57\xf9\x89\x94\x47\x99\xe8\x13\x2a\x10\x7b\xe0\x94\xb0\x92\x2d\x6d\x05\x00\xa2\x42\x67\x9a\xd5\xb3\x7d\x71\x64\x04\x61\x15\xe5\x43\x71\x1c\x35\x50\xe9\xe1\xb1\x80\x57\xe8\x98\x24\xd0\xa8\x45\xfe\x84\x07\xb4\x42\xb1\xf0\xfc\xfb\x3c\x06\x71\x60\x9f\x73\xf5\xbe\x8d\x1a\xd1\x3e\x65\x62\x3e\x6c\xbb\x16\x19\xca\xa3\xe1\xf0\x82\x29\x05\x72\xda\x86\x0e\xbb\xb9\xa9\x18\x30\x86\x1a\x38\xd6\x46\xf4\x79\xa3\x2a\x6a\xa2\x66\x09\x61\xe1\x86\xb6\x71\x44\x57\xa5\xe3\xdd\xb8\x56\xf0\x08\xa7\xbb\x33\x74\x55\x00\xc5\x70\x08\x4b\x5a\xe0\xb7\xdf\xe1\x60\x37\x65\x11\x4f\x21\x90\x19\xf1\xba\x34\x06\x30\xd5\xf1\x53\xb3\xe4\x08\x93\x3c\x22\x37\xd2\x07\x90\x0c\xc5\xf3\xc9\xed\x0f\x35\xba\xb1\xec\x28\xb8\x17\x44\xc4\xf4\x41\x19\x65\x75\x55\x66\xf7\x2c\xde\x2e\xf4\xc6\x5b\x16\x5c\x76\x32\x7b\x76\x7b\xf2\x57\x76\x87\xd4\x18\xe7\xc2\xec\xde\xd2\x6b\xd5\xdf\xd4\x06\x7a\xdd\xa2\x2d\x57\xa4\x92\x35\x2a\xda\xa5\xf5\x7a\xbd\x1f\x1d\x5e\xcf\xbb\x93\x8d\xe4\x91\xec\x5a\x02\x02\x74\x4c\x55\x61\xc3\x42\xed\x4a\x73\xb0\x3d\xb6\xb3\x17\x70\x9a\x32\x02\x77\xe4\x90\x80\xb3\x2b\xd5\xfa\x15\xac\xfd\xed\x21\x55\x81\x4a\xa7\x47\x43\xbb\xc1\x74\x11\xd8\x63\x17\x2e\xc4\xce\x5a\x6f\xa6\x58\x1a\xb2\x21\xa2\x44\x22\x8b\x05\x89\x3d\x8e\x69\xb8\xb1\x41\x99\xb0\x10\x69\xec\x6c\x55\x35\x12\x33\xca\x25\x09\x14\x11\x2e\x66\x81\xd6\x20\x52\x8d\xaf\x79\x02\x2f\x14\x84\xd0\x82\x08\x82\xb0\xb1\xe5\xea\x2e\xa1\x96\xcd\xfc\x53\x05\x79\xec\x1a\xbe\xa0\x8e\x1e\x46\xbb\x2e\xa5\x7d\xe3\x47\xa6\x00\x7c\xf8\x8a\x0b\x3f\x7f\x8e\x35\xac\xcd\xe6\x4f\x21\x61\xbe\x41\x75\xab\xda\xf5\x82\xf0\xc4\x23\x74\xdf\x5a\xf0\xd4\x8e\x00\x7b\x74\x00\xd0\x84\xcd\xd8\xe6\xaa\x87\xbd\x34\x16\xda\xf0\xf6\x05\x30\x5d\xc4\x22\x6b\xe4\x6a\x28\x0c\xb3\x9e\x7e\x99\x03\x76\x92\xaa\xae\x7a\x5a\x03\x56\x92\x26\x9d\x01\xc0\x89\x7e\x58\xc5\x88\xd4\xc3\x2d\xb1\x8a\xc7\x1d\x55\x77\xb8\xcf\x51\xda\xc0\x26\xce\xbc\xc4\xff\x3b\x9d\x30\x07\x52\xe7\xe4\x5b\x5f\x09\x50\xd1\xcd\x5a\x1c\x60\xd6\x73\xdb\x4f\x51\xef\xcf\x4d\x7b\xfa\x8a\x0d\x09\xb0\x86\x3d\x13\xa4\xef\x9f\x90\x3b\x0b\x48\x05\x1a\xf7\xf2\x13\xc1\x23\x5c\x96\xa8\xed\x5a\xc1\x42\x69\x70\xd4\x23\x01\x99\xf5\x2a\xb2\x5e\x5a\xa2\xe7\x56\x01\xb6\x57\xc7\x65\x87\xd4\x3a\x16\xe9\xc9\xb0\xc7\x14\xf1\x10\xe4\xcb\x46\xb2\x77\x92\x2e\x2a\x46\x35\x2f\x54\xd0\x61\x18\x8e\x96\xf1\xd3\xb8\x79\xf0\xbe\x96\x30\x1c\xce\xff\x29\x86\xac\x31\x4a\x01\x2e\x72\x86\x5b\xf0\x44\x81\x75\xfb\x89\x5d\x55\x40\x92\xb9\xd0\x31\x38\x42\x7c\x00\x03\x5a\x42\x97\xb3\x8e\xff\xc6\xe0\x6a\xaf\xe3\x9b\x6a\xe5\x63\xcc\xdd\x50\x12\x5b\x88\xd9\x5c\xc7\xdc\xea\xa8\x4e\x04\x7b\x4c\x91\xf4\x07\xc4\x60\x4f\x95\x83\x2c\x13\x61\x2c\x83\x0d\x21\x54\xb6\x0e\x52\x9f\x5d\x9f\xcf\x27\x75\xd9\x8f\x1c\x62\x06\xba\xdc\xd9\x9d\x33\x43\xeb\x40\x58\x13\xc6\x85\x07\x6c\xe7\x9b\x09\x1f\x6e\x35\xe7\xfb\x54\x6b\x62\x99\x08\xdb\x0d\xd2\x12\xd0\x66\x53\x09\x79\x15\x63\xa5\xcb\xcb\x8c\x2b\xa9\xdf\x55\x08\x01\xde\x95\x8c\xec\xc7\x79\xd1\x45\xd8\x45\x8c\x09\x0e\x59\x38\x71\x85\x21\x5f\x72\x4f\xf9\x35\xcd\x12\x4b\x98\x32\x2c\xfb\xbf\x54\x14\x46\x97\x5d\xd4\xab\x10\xd7\xf1\xfd\xe5\xef\x8f\xf2\xeb\x81\x2a\xd9\x1f\xa1\xfc\x1e\xd5\x49\x6f\xc5\xf2\x96\x2b\xc1\x73\xfe\x8f\x70\x4a\x21\x0f\xff\x64\x91\x06\x61\xc7\x97\xcf\xc3\x09\xfa\xc2\xa1\x4c\x5c\x90\xa5\x50\xbc\x7f\x09\x12\xdb\x0e\x24\x36\x9e\x08\x6b\x77\x65\x93\x6d\x0f\xfc\xda\xb8\xed\x64\xf5\x1a\xf3\x23\xdf\xeb\xff\x06\x45\x44\x75\x5a\x1f\xea\x9e\xcb\xfe\x3a\xcc\x69\xc6\xd0\x4e\x38\x84\x75\x91\xbd\x40\x49\xaf\x0f\x6f\xf2\x45\x52\xe3\x55\x3a\xc1\xef\xf0\xc5\x86\x9e\x60\x07\x2c\x05\xc6\xec\x1e\xbc\x0b\x4a\x66\x8c\x8f\x6a\x9a\x5c\xca\x7f\xe5\x13\x1e\x04\x91\xf0\x6a\x2d\x82\x8b\x2d\x70\x0c\xf6\xad\x25\xf2\x5e\xad\xf3\x46\x0b\x61\x7e\x77\xd6\x72\xbc\x89\x66\xc0\x8b\x25\xa5\x9a\x32\x2f\x2e\x7a\xfa\xa0\x5e\x7d\xe8\x39\xa4\x2a\x8a\xef\xbc\x0c\x7e\x01\x78\xac\x61\x95\x2c\xe7\x64\x97\x6c\x00\xf9\x3a\xc7\xa7\x25\x0d\x1b\x8b\x0d\xe7\x84\xaf\xbc\x92\xe5\x0f\x8e\x9f\xb0\x74\xc9\x71\x1a\x96\xbe\x26\x3a\x41\xb8\x50\x9b\x2c\xdd\xe6\x72\xfc\x25\x05\xd6\x35\x3d\x6f\xb7\x20\x78\x28\x50\x9a\x1e\x9a\xd8\x74\x5d\xfe\x52\x6f\xb6\x06\xed\x95\xcb\x16\x0a\x6a\x20\x69\xea\x27\x75\xf0\xea\x83\xd8\x15\xad\x59\xcc\x76\x19\xb4\x4f\xb4\xcb\xb9\xa2\xe0\xe7\x32\x38\xe7\x65\x2e\x9d\x50\x2e\x9d\x65\x11\x0e\x0a\x81\xd4\xba\x66\xc1\x3e\x05\x64\xb6\x20\x51\xb3\xc8\x7d\xad\x09\xb7\xc8\xa4\xb4\xe2\x4b\x0b\xa2\xea\xec\x97\xaa\x7e\x0e\xd1\x07\x45\x59\x44\xd1\x39\x7b\x61\x8e\xfb\x30\x4c\x9c\x84\xb8\xd8\x05\xaf\x23\xd1\x4c\x39\x94\x2e\xfc\x5e\x35\x0c\x49\x07\x22\xf6\xfd\x50\xf0\xe1\x82\x7b\x31\xc1\x66\x92\x82\xa8\x5a\x10\xa8\x12\xa9\x52\xee\xba\xfb\x0a\xfc\x78\x01\x5e\xa0\xe8\x12\xf0\x98\x90\xdb\x03\x87\x2d\xcc\xb0\x51\x37\x2f\x4d\x52\x98\xda\x38\x20\x9f\xef\x1c\xda\xfe\x04\xe1\x24\x57\xa7\x6a\xd5\xb3\xcd\xa9\xab\x35\x95\xe9\x0a\x88\xb9\xf5\xdf\x3e\xc7\x70\x59\x7e\x87\x9c\x08\x1a\xe3\xa1\x80\x33\x85\x1c\x2e\x08\x44\xd4\x4f\x28\xd6\x09\x10\xe2\xf2\x0e\x9d\xfe\xd1\x0b\x45\x94\x80\x10\x38\x66\x72\x57\x0e\x79\x52\x6b\x1f\x62\x46\x2d\x6a\x7c\xfc\xb8\x0c\x89\x37\x56\x33\xfd\x71\x0f\x0d\x09\x8a\x44\x08\x28\x13\xc0\x41\xcb\x30\xdf\x89\x48\x19\x51\x47\xb1\x6e\xa8\x51\xdd\x3d\xf8\x26\x81\x4e\x26\x8d\xd6\x96\x1f\x5e\x55\x52\x29\xc0\x77\xaf\x73\xfb\xf3\x6f\xb4\xe0\xf8\xfb\x50\xb6\xf0\x45\xdb\x99\x97\x25\x1a\x6e\x15\xa0\x2e\xc1\xb2\x06\x21\x83\x60\xfc\xf2\xf3\xe6\xbe\x99\x38\x34\xeb\x0e\x7f\x5d\x8c\xc2\x3a\x18\x01\x6d\x16\xdf\xa6\xbf\x93\x6a\xff\x57\x58\x83\xff\xc2\x9f\xc6\xef\xd3\x5f\x20\xac\xb4\x93\xc3\xc4\xef\x28\x45\xd3\xdf\xb1\x42\x17\x7e\xb3\x25\xb2\x9c\x35\x58\x88\x2c\xc8\x81\x36\xf9\xf9\xdc\x34\x8c\xfd\xa6\xb9\x46\xed\xff\x96\xe2\x13\x61\xac\x45\xec\xbc\x61\x7e\x93\xcf\x3d\xa1\x67\x2d\x03\x80\x9d\x5a\x0c\xdb\x76\x63\x68\x6d\x48\xfb\x9f\xd4\x1c\x3c\x17\xf7\xaa\x23\xdb\x96\x08\xcf\x2c\x29\x0a\x1c\x73\x4b\x5e\xcb\x15\x20\xc8\x1a\x6e\xb9\x2d\x51\x50\x8b\x2b\x58\xc2\x62\x2a\x52\x3c\x27\xf7\x42\x16\xce\x07\xfa\x12\x59\xd8\x99\xee\x9c\x7a\xa1\x6d\xba\x8c\xf4\xa1\xa9\x5f\x27\xc6\xae\x60\x3b\x6d\x19\x42\xe9\x75\x5c\xbe\xf4\x31\x50\x04\x0d\x8c\x8e\x0b\x47\x48\x44\xd8\xa1\x36\x6f\xd5\xb7\xbd\x81\x99\x1c\xdf\x3f\xdf\x9e\x2d\x7c\xd5\xa6\x11\xbe\x8c\x04\x29\x7f\x75\xdb\x8e\xf6\x09\x8d\xb7\x91\x26\x46\xc3\x35\x13\x90\x22\x93\xeb\x73\xd3\xd4\x64\x38\x41\x39\x71\x30\xcb\x09\x37\x60\x0f\xe8\xd2\x30\x58\xe6\x43\x6f\x00\x40\x73\x78\x34\xba\xd6\x2d\x75\xcc\xe2\x06\x0e\x36\xe0\x87\xd3\xf5\x7c\xc0\x92\x1e\x05\x4a\xc0\xbe\x12\xff\x71\x28\xbd\x3a\xef\xa1\x04\x85\x73\xa8\xae\xbe\x00\x0d\xcd\x36\x1c\x9e\x1e\xdb\x87\x6f\x94\x99\x1c\xc6\x4e\x2a\x11\xb7\xc7\x9a\x4d\x0b\x56\x88\xce\x20\x74\xed\x06\x3f\xd0\xc9\x7e\x7a\x92\x86\x58\x3d\x09\x7b\x6f\xfe\x01\x01\xbc\xe1\x21\x2f\x96\x7b\x86\x44\x8c\x31\xb0\x3a\x3e\x1c\x32\x96\x97\x36\x13\xa8\x88\xfc\x0f\xe9\x37\x5a\x5f\xf4\x30\xfa\x11\x60\x86\xef\xda\xea\x40\xeb\x16\x05\x0e\xca\x7d\x54\x95\x89\x00\xdd\x24\x9a\x26\xf7\x50\x4a\xb6\x4e\xce\x7f\xdf\x7e\xfc\xfb\x63\x4a\xd9\x43\xad\xcf\x75\x75\xfa\xb1\x1a\x75\xf6\x10\x47\x93\x2e\xc4\x5e\x3d\x09\xc4\x03\x73\x89\x88\xea\x58\x30\x25\xc9\xcc\xf7\x69\xdc\x3e\x17\xdf\x23\x8c\xe1\xd3\xd7\xa2\x85\x11\x21\x59\xcc\xb1\x2f\xe7\x0c\xbd\x17\x42\x68\x60\x07\xae\x0a\x9d\xb8\x5f\xd1\xc8\x45\x30\x1a\x77\x66\x0b\xad\x05\x00\x31\xb8\xad\xb7\xe3\x53\xfe\x2a\xc0\xd4\xa8\x72\xca\xd0\x03\x1b\x51\x7a\x02\x66\xce\x7f\xbe\x29\x42\x26\x3e\xbd\x83\xa5\xa4\x44\x66\xf9\xe6\x69\xf3\xb9\x5f\x2d\x0a\x3d\xe1\x68\xc6\x03\x39\xdf\xe6\x4e\x64\x26\x15\xb8\xe3\x7a\x57\x02\xd9\xb4\x82\xbf\xdc\x12\xbd\x4f\xa8\x35\x00\x92\xca\x83\x73\x77\x83\xd7\x9f\xe9\xb8\x25\x7d\x9e\x69\x6b\x74\x91\x68\x17\x2e\xe7\x70\x7e\x39\xd7\x35\x1e\x5f\x32\x13\x16\xe7\xab\x1f\xaa\x49\x78\xdd\xf9\x8f\xac\xb7\xdd\xe3\xa4\x2e\x12\x29\xb2\x88\x10\x90\xe7\x13\x3f\xc2\x26\xec\x36\xe1\x27\xf7\x23\x3b\xe9\x9f\x1f\xb7\x30\x81\x7e\x10\xf4\x42\x3c\x8c\xa3\x63\x63\x3c\x07\xa4\xcf\x9f\x6d\x88\xa5\x6f\xb1\x0f\xa5\xb5\x88\x29\x3c\x9a\x6d\x66\x99\x6e\x74\x01\x6e\xa8\xc0\xbc\x34\x2e\x27\xb4\xdf\x5e\x06\x90\x23\x64\xd5\x25\xd0\x2f\xf7\xfb\xb8\x43\xbe\xe4\x4f\x21\x29\xf8\x92\x3d\xa9\x90\xea\x76\x24\x4f\x6b\xfd\xab\x2f\xf6\x0a\xb6\xc6\x31\xdb\x57\x38\x1e\xc0\xc6\xd8\x38\x48\x98\x48\xe8\x24\x76\x9b\xa5\x5d\xb1\x6e\xdc\x6d\x51\x15\x73\xe2\x9c\xfb\x04\xaa\x21\x7c\xcb\x34\x3d\x93\x6c\x08\xde\xf2\x15\x70\x44\x4b\x48\x4a\x40\x08\xeb\x88\xa8\xfd\xde\x7d\xbb\x1c\xf8\x65\x0e\x9f\x83\xb5\xdc\xfe\xe2\x6e\x50\x55\x5b\x18\x7d\x96\x2f\xb5\x8a\x3d\x34\x8d\xe2\x73\x7c\xdd\x4a\xe7\x50\x75\xab\xa9\x70\x21\x68\xc9\xbb\xdc\x66\x05\xe3\xed\x26\x7e\x10\x8e\xce\x3f\x14\xcb\x7d\x22\x32\xf9\xea\x5f\x7b\x1b\x06\xb8\xa1\x7c\x40\x53\x26\x99\x0a\xf0\xd9\xed\xc2\x9c\x2d\xbc\x06\xf8\x8b\x84\x1f\x3a\x8c\xd9\x02\xe7\x32\x47\x56\x0c\xc1\x40\x00\x7e\xf4\xbd\x4d\x33\xc6\x29\xa4\x63\x90\xc2\x46\x22\x40\xa5\x73\x86\xb6\x60\x2e\xcb\x8b\x0b\x6a\xed\x5f\xb6\x19\xf9\x6e\xf3\x2d\x9b\x1b\xf8\x8e\x0b\x0b\x51\xf4\x4b\x68\x2f\x10\x2d\x56\xfe\x38\xed\x79\x34\x7a\x7c\xed\x71\x74\x9c\xc3\x39\xad\xa1\xbd\xef\x68\x72\xc1\x5f\xd6\x70\x30\x07\x3d\x6f\x67\x28\xb2\x03\x23\x79\x95\x9f\x39\xd0\x31\x62\x54\x5a\x70\x46\x09\xae\x75\x8b\x68\x06\x94\xe7\x18\xbf\x2a\xf9\x2e\xd2\x41\xab\x01\x48\xb9\x05\xce\xe4\x13\xdd\x03\x4a\x7c\x92\xa2\xa8\xb4\xf4\x56\x00\x8f\xb2\xbd\x42\x5a\x03\xe6\x3a\x2e\x16\xe2\xd8\x98\xfd\x46\xc7\x3b\xce\xe5\x16\xc5\xb3\x26\x84\x40\xf4\x2e\x80\x5c\x42\xba\x63\x71\xf3\x43\x09\x1a\x84\x76\xc6\x97\xb9\x39\xe0\xbc\xd1\x37\xb7\x45\x32\x1c\x13\x3d\x60\x5b\xa8\x9f\x09\xa6\x52\x97\x8c\xdc\x64\x40\xe2\x19\xee\x49\xee\x03\x37\xe0\x2b\x0d\xcb\x6c\x50\xb5\x08\xa8\xa0\xbf\x57\x60\xae\x76\x54\x3d\x1e\x40\xe1\x60\x72\xb6\x03\x46\x26\x19\x99\xd7\x11\x0d\xd7\x58\x62\x29\x80\xb8\xa4\xe5\x2f\xf3\x08\xd5\x22\x1c\xb5\xe2\xd6\x66\x6a\x25\x2a\xf5\x43\x0a\x7c\xd9\x99\x62\xb7\xde\x47\x65\x45\xd5\xcd\x03\x86\x86\x47\x38\x86\xd8\x0c\x18\x6c\x68\xe9\xa6\xe4\x0c\xf8\x6b\x9b\xde\x15\xfa\x63\x1d\xf5\x7a\x4e\xc4\x89\xec\x7b\xe4\xd7\x10\xc1\xa8\x16\x0d\x09\x9e\xca\x7d\x4f\x63\xf4\xa4\x4a\x2a\xf0\x2a\x5f\x96\xf9\x29\x94\x7d\xa1\x75\x21\x8a\x3e\xc2\x2a\xc2\x6f\x1d\x16\x12\x9a\x50\xdb\x98\xc6\x86\x27\x8e\x04\xed\x08\xf0\x8a\x0d\x0f\xfe\x2b\xc1\xb3\x40\x30\x95\x63\x0a\x59\x8c\xfd\x6a\x0a\xa1\x1b\x67\xcc\x72\xa8\x8a\xa1\x23\x65\xa6\x66\x41\x27\x21\xff\x73\x12\xa7\xc1\xa2\x3e\x51\x40\x1f\xf8\x15\xbd\x79\x3b\xb5\x2d\x1f\x48\x72\x33\xb4\x2c\x41\xf2\x15\x88\x17\x29\xb5\x7b\x3b\x4b\x0a\x17\xe8\x95\x57\x30\x90\xed\xda\x9e\x42\x5c\xa0\x8a\xd8\xc4\x55\x6b\xca\xa5\x4a\x5b\x53\x8e\xb4\xa8\xc3\x6e\xca\xa2\x8b\xd3\xc4\x1a\x01\x2c\x11\xc4\x91\x03\x03\xd7\x37\x63\xd5\xda\x70\xe5\x8c\x12\x2f\xa3\x41\xa1\x6d\xd7\xce\xd8\x19\x28\x8d\x75\x93\x04\x49\x6c\x50\xe7\xac\x19\xed\xa3\x6e\x57\xfc\x06\xc2\x40\xd8\x0e\x69\xf6\x3c\xbb\xc9\xd6\x3f\xe5\x21\x53\x39\x43\x57\xbc\x8a\x76\xe4\x29\x48\x88\x0d\xca\x14\x0f\x2a\x65\x84\x4b\xfa\x87\xe0\x94\x2f\x9f\x09\x79\xe1\x37\x60\x57\x8e\x3a\xde\xd2\x45\xd9\x7e\x3a\x00\xc6\x13\xbb\x1b\x0f\xd3\x0a\x41\x08\x3d\x8d\x80\x2a\xc2\x09\xbf\xba\xb2\x8b\x83\xe6\x22\x19\xb4\x7d\x48\xe1\xf9\x60\x6f\x5d\x90\xa8\xe9\x4d\xed\x6b\x20\x60\x34\xfd\x1d\x6e\xfa\x91\xfe\x51\x13\xe2\xdc\xdb\xe1\x33\x1e\x00\x18\x27\x0a\x56\x5c\xbb\x80\x13\x58\xa7\xdd\x5b\x41\x39\xb6\x9e\x64\x9b\x10\x70\xb0\xb6\x56\xa0\x6d\xf6\xc2\xfb\x09\x12\x62\x5b\x3e\x28\xa6\x61\x5d\x5e\x22\xe8\xc2\x45\x31\xb0\xb8\xeb\x69\x93\xfb\xa6\x07\x6b\xcf\x2e\xbc\x8d\xed\xa3\xec\x15\xfe\x55\x44\x19\xb4\x31\xfa\x52\x39\x3a\x69\x29\x50\x85\xa0\xb0\x44\x2c\x3b\xda\x4c\xa7\x50\x01\x64\xc9\x6d\x27\xe1\xa3\xb4\xe8\xaf\xb4\x34\xa7\xb8\x4d\x0a\x60\x93\x25\x4c\x19\x72\x9d\x47\x02\x35\x94\xc3\x8a\xa1\x30\xed\x02\x06\xd4\xad\xdd\xa7\x6a\xa4\x4a\xf5\x74\x7f\x73\x48\x8f\xd8\xdd\xaf\x29\x6a\x7a\x3a\x44\x2c\xcc\xd3\xa5\x7b\x21\xbf\x74\x49\x5f\x14\x17\x97\x49\x1d\x88\x23\x21\xc3\x61\x43\x48\xe3\xbf\xbf\x7b\xa6\xcf\xa5\xab\x78\x99\x16\xbd\x51\x95\x39\x74\x2b\x87\x26\x62\x61\xbe\x2c\xd8\x2a\x22\xa9\xea\x65\xe8\x8f\x4a\x1f\xfb\xf7\xa0\x74\x86\xdd\x40\xf8\xd7\xf7\xbd\x34\x34\xce\x17\x27\xa2\x7f\x45\xb4\x82\x3f\xfc\x2e\xd8\xc2\xd4\xcf\x57\xfe\xaf\x33\x64\x7b\x2f\x98\x34\x62\xfb\x33\xd0\x58\xed\x73\xf9\xb5\xf9\x6c\xb1\x10\xf1\x01\xc8\x49\x68\x13\x76\xad\xb7\x35\x44\x14\xc7\x2c\x7c\xfa\xc6\xbe\xc0\xd9\x58\x1f\x17\xc0\x64\x30\xb8\x37\x8b\x3e\x61\x74\xc8\x66\x2b\x91\x0d\x94\x81\xe6\x1d\x93\x3b\x36\x03\x25\xf6\x41\xba\x7f\x45\x10\x6f\xcd\x14\xce\x18\x28\xae\xc9\x4c\xef\xc3\xf3\x79\xd0\x12\x82\x32\x96\x88\x76\xbb\x2d\xb5\x6a\x8b\xa6\x8d\x16\x33\x0a\x43\x93\x2f\x3d\x7c\x20\x4a\xe0\x7c\x01\x8b\xba\xf0\x91\xa8\x65\x18\x78\x88\xc7\x97\xa6\x7f\xc4\xcb\x84\x05\x8f\xa5\x9a\xf4\xc0\x48\xdb\x50\x08\x9b\xd9\x9e\x69\x93\x66\xc7\x8a\x7b\xd9\x23\xeb\xfc\xc3\x4c\x42\x1a\x1f\x1d\x51\x88\x1f\xbb\x61\x1f\x40\xcd\x6c\x4c\x5a\xdf\xa5\x0f\xb3\xc9\xb7\x65\x22\x44\x66\xd8\xe4\x9c\x88\x17\xeb\xdd\xce\x56\x6e\xf0\xdb\xe8\x2a\x93\x88\x33\x9d\xe3\xf3\x41\x3d\x14\xbf\x15\xdb\xea\x24\xb1\x05\x88\x40\xfa\x1e\x01\x95\x09\x21\x47\x7f\x8b\x9d\x73\xcb\x55\x92\x77\x68\x03\xbe\x41\x87\x9b\xa4\x25\x45\xc3\x89\x1c\x18\x9a\x12\xdb\x78\xcf\xa4\x57\x5a\xf2\x4f\xf8\x16\xae\xe0\x08\xbd\x22\x59\x22\xf7\xa5\x77\x40\x4d\xdc\x38\xe7\xfa\x22\x38\x95\xe2\x73\x01\x40\xf3\x3c\x39\x3c\x25\xf6\x9c\xc2\xae\xc2\x29\xb5\x8a\x87\xb1\xaa\x7d\xa8\x9f\x3b\x17\x58\xdd\x59\xbf\x11\x92\x21\x58\xa6\x7d\x57\x37\xcc\x13\xc6\x97\xc7\xa0\xf7\xf8\x88\x75\xbb\xca\x2f\xe3\x1c\x3d\x91\xb5\x3a\x98\x7c\x49\x92\x44\x58\xaa\xe3\x42\xff\xb2\xe1\x5c\x0f\xbb\x75\x89\xcc\x38\x99\x85\x1e\x27\xfc\x91\x3c\xc0\x93\xec\x01\xd7\x5b\x8e\x33\xe0\x22\x7b\xa2\x03\xfc\x76\x2a\xc7\x97\x79\x45\xb5\xcb\x73\x43\x0c\x17\xad\x80\x7b\x85\x50\x37\x40\xab\x10\x34\x33\x06\x58\x04\x72\xe8\x21\x1f\xf2\x62\x09\xc2\x11\x36\x7b\xfe\xc7\xa4\x91\xe0\x9b\x3a\x67\xf4\xe6\xb3\x0a\xb4\x61\x4d\x4f\xd4\x6e\x07\xd5\xd8\x90\x2f\xdb\xe2\x70\x4a\x3a\xa8\x80\x74\xb8\x30\x1a\x0f\x1c\x8f\x50\x37\xa1\x8f\xcb\x11\xdc\xf1\x63\xa4\x15\xac\x6b\x3a\x13\xf1\x7d\x7c\xd5\x33\xe5\x84\x51\x91\x31\x1b\x0d\x63\xdd\x12\xa3\xe5\x05\x1a\xc6\xfd\x87\x87\xe6\x10\x1e\x43\xb9\x3d\xc1\x50\x38\x30\x34\x85\x0e\x8e\x87\x3d\xa1\x1d\x51\x9a\x87\x25\xbb\x7e\x68\x5e\x54\x53\x03\xf8\x4a\x2a\x25\x4b\xf8\x52\x00\x2f\x73\x0c\xf2\xc6\x9f\x32\x68\xe5\xd2\xb4\x73\x3f\x8d\xd1\xdd\xb8\x1e\xc4\xd2\xac\x45\xc7\xd1\x1f\x9f\x61\xeb\x3d\xc3\x81\x0c\x85\x7f\x4f\x52\x5f\x76\xb8\x56\xa9\x50\x46\x36\xf0\xbd\xa4\x7b\xe2\x4c\x5a\xdb\x8e\xa5\x0d\x25\x94\x0f\x5d\xa4\x31\xe1\x71\x20\x9d\xbb\x53\x71\xcf\xa4\x9f\x04\x13\x3e\xee\xa1\xdb\x7f\x58\xb0\xdf\x5a\x28\xbe\x7e\xff\x09\x2f\x04\xeb\x0a\x7d\x93\x02\x31\xf1\x49\x2a\x26\xc1\x96\xe3\x96\x8b\xb9\x4d\x3a\xf4\xda\x6d\x69\xbc\x9f\x21\x7e\x61\x41\xda\x02\x91\x33\xbb\x14\x99\x87\xd3\x21\x4b\x8e\xe9\x49\xdd\x08\x4a\x7a\xed\x67\xe3\xf2\xff\x6f\x41\x78\xce\x8d\xd0\x28\xb7\xf5\x48\x4b\xf5\xe5\xbf\xb6\x02\xf9\x4e\xc6\x15\x43\x02\x8f\x7e\x05\x45\x10\xa4\x63\xe3\x80\xe9\x29\xb8\xb4\x4c\xa8\x95\x42\x68\xc8\x51\x6c\xd2\x2f\x80\x8b\x3b\x73\x74\xe1\xf6\xe8\x65\x97\xe8\xa4\x6a\x83\x71\x9a\x04\x15\x82\xdb\x0f\x5f\xb7\x07\x2d\x7c\xe7\x0f\x2f\x29\xd3\xa8\x43\x01\xef\x04\x44\x8d\xb4\x4b\x56\x57\x8a\x12\x1c\x08\xc8\x00\x2c\x34\x30\x9d\xf0\x55\x3e\xff\x24\x40\x7c\x0f\xca\x69\xb8\x70\x8a\x1e\x2d\x37\xf3\xa8\x3a\x19\x6e\xe4\x1f\x78\x1b\x28\xc3\x6e\xa3\x97\x9d\xf7\x12\x36\x11\x65\xbb\x57\x61\x30\x03\xb0\xe9\x89\x9f\x43\x01\xcc\xa0\xfe\x26\xc5\x39\x93\x1e\x3d\xe9\x7d\x61\x5b\xdd\x85\x34\x02\x89\x8f\xc3\x97\x4b\x46\xc5\xc1\x42\xda\xbf\xa4\xaa\xa9\x67\xf1\x76\xef\xe6\x4a\x98\x05\x6d\x45\x00\x5d\xf6\xe0\xf1\x9e\x02\x18\xc8\x83\x29\x6c\x62\x9d\xda\xb8\x4b\x57\xe5\xd6\x33\x77\x68\x50\x05\x06\xa5\xbf\x2c\x19\x91\x49\x52\x0a\x16\x50\x07\x57\x87\xbf\x2e\x4e\x9d\xf7\xd7\xd8\x09\xc0\xf3\xaa\x9e\x22\x6f\x97\x4d\x73\x8c\x75\xa2\xf3\xd6\x3e\x56\x9e\x8b\x85\x2d\xf1\xf5\x3b\x32\x28\x5e\x37\xe8\xaf\xfa\x76\xaa\x6e\x78\x3b\xd7\xae\x19\x76\x59\x5a\x3c\x63\xdb\xea\x4b\xf8\xb9\xc3\x15\x3a\x3f\x83\x16\x2a\xf7\x61\x3b\x25\x57\x0a\xb4\x51\xd6\xbe\x2c\x61\x5a\xe0\x7e\xf9\xa1\x43\x39\xa7\xee\x27\x3d\x84\x44\xca\x4b\x44\x2d\xd3\x62\xaf\x72\xc5\xb0\x06\xa4\x5d\x5c\x5f\x70\x41\x05\x72\xb2\x21\x29\x8c\x5b\x86\x14\x9f\x8b\xc5\x4f\x7e\x95\x73\x2a\x22\x5e\x85\x5f\x1b\x50\xa9\xf6\xd3\xcb\xff\x42\x46\xc8\xad\x0d\xc3\x60\x26\xaf\x9c\x95\xc3\x15\x45\xf2\x49\x79\x42\xd5\x73\x8f\x4b\x93\x89\xcd\xab\x76\xf4\x36\xce\x36\xee\x1d\xb8\x4b\x52\xcb\xad\x4f\x44\x02\x45\x1c\x48\xac\xb6\x6a\x14\xb5\x5a\xcc\x84\x3c\x4d\xfc\x09\x40\x6b\x84\x76\x10\x3a\xd9\xe3\x8f\x9d\x96\xdd\x78\xea\x71\x6c\x40\x0e\xbc\xd2\x15\x1d\x03\xb3\xf7\x1d\x53\xef\x99\x2a\x36\x0b\xef\xf0\xb4\xbc\x12\xed\x87\xa2\xfe\xb0\x27\xe7\x06\xb3\xce\x62\x93\xbb\x30\xe0\xb1\x19\x89\xcc\x57\xa6\x3f\xcd\x23\x21\x60\xf3\x11\x67\x12\x9a\x23\xfc\x9c\x09\x4e\xa4\x1b\xa9\xbb\x7b\x7a\x9d\x53\xe1\x77\x3f\xab\xa3\xed\x9e\x42\xad\x25\x8c\xd9\xad\xdf\x12\x1c\xea\x5c\x04\x96\xfa\xc2\xca\x28\xf6\x70\xfc\x7d\x67\xa2\xa1\xfe\xa9\xe8\x75\xd3\x61\x5d\xdc\x95\x1f\x0c\xea\x0e\x47\x2e\xd7\x51\xfe\xaf\xcb\x8a\xef\xce\xef\xb1\xaa\xd9\x1c\x20\xcc\x56\x0c\x53\xd9\x02\x57\xb4\xe4\x3e\xf6\x7e\x7b\xac\x83\xcd\x50\x75\x62\x26\x27\xc2\x56\xd4\x10\x5d\x45\xf9\xf6\xe9\x16\x73\x80\x56\x8d\x6b\x31\xf3\x15\x00\xf2\xf4\x51\x3d\xa0\x3b\x47\x80\x9d\xfa\xea\x23\x00\xa9\xe5\x49\x3a\x39\x4f\xac\x3b\xb5\xf1\x8e\x90\x0e\x01\xa6\xa9\x0d\x38\xd3\x96\xeb\xfb\x54\x9c\x7a\xdc\x88\xa6\x25\x3c\x60\xda\x54\x55\x69\x54\xd6\x46\xf5\x5f\x7d\xd6\x86\x59\xbb\x5e\xa5\xbc\x95\xdc\xcd\x5d\x9b\xc6\xbb\x12\x40\x90\xf8\xe5\x90\x4a\xf7\xe1\x04\x56\xda\x01\x10\xaa\xa5\x6e\xe2\x81\x76\xc9\xa9\x60\xb9\x05\x73\x26\x41\x8a\x96\x73\x69\xc7\x2f\xd1\x19\xfa\x32\xc8\x93\x05\x4c\xe0\xc0\x1e\xd9\xd5\x12\x6d\x01\x62\x34\x98\xcc\x3d\x28\x47\xd3\x8e\xab\x70\x2e\x9b\xc0\xdc\x36\x2c\x7f\xfb\xde\xac\x71\xcd\x02\x52\x64\x1f\x15\xc7\x25\xc1\xe9\x57\x71\x44\x28\x4d\x43\x4b\x13\x48\x5c\xb6\xc2\xfa\x54\x5b\x0d\x00\x8c\xae\xc4\x8c\x76\x2d\xd5\x64\xca\xc3\x4a\x39\x06\x2a\xa2\xf5\x1c\x34\xac\x58\xf6\x88\xf5\x87\x6b\x4c\x5b\x0b\x68\x8f\x04\x6f\x15\x4b\x07\x08\xf3\x81\xd2\x97\x16\x12\x56\x14\x0a\x03\xb5\x74\xf6\x35\xcc\x39\x27\xf9\xb3\x20\xf0\xeb\x35\x55\xa5\xb1\x15\xe3\x1b\x91\x49\x21\x55\x05\x6a\x60\xab\x67\x68\x1d\xa0\x58\xba\xf3\x54\x87\x52\x7c\xa2\xe8\xb0\x51\xc9\xd1\xdc\x8b\x2c\xd0\x2d\x08\x73\xf8\x15\x17\x51\xc2\xc8\x2e\x6f\xb3\x56\xe0\x18\x4a\x17\xf2\x6c\x84\xb6\x99\xef\x4b\xc7\x3d\x9f\x82\x4e\xcd\xe8\x62\x7a\x42\x6e\x61\x98\xa9\xc2\x35\x69\xba\x7c\x2e\xb1\x12\xb0\x12\x07\xb4\xc3\x29\x4b\x1e\xbb\x2d\x1d\x14\xef\xb0\xaa\xa4\x1f\x22\xc9\xbc\x69\x4d\x76\xe7\xd3\xa4\xe5\x1f\xca\x3d\xb4\x5e\xf9\xc8\xa3\x88\x88\x22\xbf\xe3\x11\x42\x62\x7e\x51\xdc\x71\x31\x0b\x21\xea\xcf\xbc\x27\xbc\x85\x22\xee\xb2\x7f\x23\x94\xda\x50\xc8\x84\xec\xa8\xcd\xa7\xf9\x67\x01\x7d\x92\xa4\x9b\x43\x47\x96\x7c\x87\x71\x53\x7f\x01\xaf\x5d\xfd\x46\x9f\x03\xb1\xbd\x1c\xce\x3c\xc5\xee\x3f\xf6\x79\x6e\xde\xc7\xc2\x41\x59\xda\x28\x76\xab\x6c\x55\x66\xaf\xd0\xc1\x93\xc8\x9b\x2f\x0d\xf6\x96\x8f\xe2\x21\x78\x48\x3a\x47\x10\xc9\xd2\xec\xb7\xd9\x4b\x71\x9c\xcf\xe9\x37\xf9\x72\xda\x3d\x21\x8f\x17\xfb\x0d\x13\x51\x49\xcb\x90\xdd\xbc\x03\x58\x19\xc9\xd5\xa0\x84\xee\xe9\x32\x88\x6e\xab\x14\x70\x8e\xdb\xe2\xc5\xfe\x32\xc7\x04\x41\xe0\xc6\x86\xdd\x36\x33\x23\x5f\xc6\xd7\x48\x24\x10\xba\xdb\x39\xdc\x71\xbd\x05\x91\x29\x8f\x31\xf5\x73\xb9\x1c\xd7\xc2\xf1\x9f\x54\x0e\x30\xe7\x26\x18\xd1\xfb\x52\xf0\x45\xf5\x58\x00\x61\x3b\x1f\xd4\xc1\xd9\xa1\xda\x45\xac\x92\xd4\x0c\x30\x95\x22\x98\xe6\xb4\xdf\x57\xc4\xcb\x19\x80\x8d\x97\x14\x5a\x20\x82\xb3\x4e\x21\x90\x03\xd7\x18\xcc\x61\x08\xd0\x39\x27\x30\xd6\x09\x54\x9a\x08\x13\x3a\x5b\x49\xde\x00\xb9\xe4\x01\xc6\x9a\x87\xf0\x4b\x02\x21\x51\x7a\x9f\x8e\x69\x73\x68\x20\x02\x93\xe4\x97\xc3\xd2\x36\x70\x47\xc9\x3d\x9b\xdd\x99\x41\x68\x10\x6f\x34\x42\xc9\x80\x22\xeb\xdb\x99\x2c\x86\xb9\xd0\x10\x6c\x1e\xff\x79\x6a\x34\xbb\xfd\xb7\xea\xd9\xf3\xb8\xf7\x3e\x64\xa9\x11\xa6\x25\x4e\xcc\x97\x55\x0b\xe4\x20\xfc\x12\xdb\x5f\x58\xf4\x2a\x64\x8a\x24\x53\x67\x59\xa4\xf5\x91\xf2\x8e\xd9\xe7\x2a\x67\x3d\xc7\x9a\x32\xee\x32\x87\xf7\xd8\x28\x26\xb8\x15\x0c\x76\x14\x25\x42\xa0\x9a\xcf\x49\x44\x11\xba\x8c\xa4\xa4\xa0\xb6\x42\x05\xc8\x39\xf5\x57\x8d\xe6\x50\x89\x63\xb3\x65\x81\x19\xb9\x51\xf9\x0f\xe2\x88\x90\xa7\xb4\x9e\x03\x3f\x75\x39\x89\xe8\xe6\x31\x61\x06\x35\xa7\xc9\x9e\x50\x9e\x85\x25\x50\x4b\x7b\x57\x43\x20\xc3\x73\xcc\x49\x11\x01\x4a\x0e\x7f\xf7\xa8\x5d\xd2\xcc\x09\xcf\x9c\x5c\x5b\x45\xbf\x7d\xf2\xd5\x91\xa3\x02\x9d\x40\x9e\x5d\x74\x18\x8c\x61\x3d\x09\x9b\xae\xbd\x10\xb8\xf4\x2f\xcf\xb8\x69\x1d\x26\x74\x52\x72\x16\xb3\x77\xef\xdd\xdc\x12\x84\x77\xd0\x44\xeb\x38\xc7\x35\x51\x90\x77\xc2\x08\xd3\x09\xed\xd4\x4a\x84\x65\x2a\x4d\xa3\x5c\xd3\xe6\xfb\xb2\xd2\x82\xe1\xb8\xd3\xcb\x30\xdb\x26\xb8\x09\x35\x14\x09\x06\xa2\x21\xe4\xd3\xac\x1d\xd5\x97\xc1\xee\xf4\x16\x35\x02\xbb\xce\x94\xfc\x19\x73\x03\xe4\x90\x87\x1d\x8f\x68\xbc\x14\x07\x1d\x52\x02\x9c\xb2\x9d\x61\x95\x41\x23\x0a\x4a\x3c\xf5\x29\x57\x0a\x2f\x2c\x65\xb9\x88\x32\xc9\x5b\x7d\x8a\x84\xc4\xa6\x3d\xba\x76\x53\x7e\x1e\xb1\xcd\x1a\xe8\x6c\xc0\xda\x42\x3d\x62\x72\xb7\xce\x9d\xe1\x95\x28\x60\xe6\x99\x0b\x05\x81\xa6\xb4\x63\xb1\x4b\x17\xd0\xc6\x0e\x1b\x0c\x59\xe8\x9e\xa0\x9a\xb7\x2a\x62\x95\x67\x4a\x85\xed\xa5\x73\x3f\x76\x04\x4f\xfa\xc3\x4e\xf4\x29\xd7\x61\x94\x62\x98\x80\x43\x93\xac\x51\x13\xfe\x4e\xaf\xab\xf8\x43\x07\x24\x96\x1f\x05\x18\x16\xe1\x58\x12\x3a\x5a\x5c\xdb\x5c\xd7\x03\xe8\xac\xac\xe0\xb6\xfd\xf1\x3f\x0d\xfd\x8d\xbf\x61\x9c\xfc\x73\x46\xac\xa4\xc8\x3f\xf4\x05\xda\xa9\x90\x79\x98\x72\x1f\xbe\x6d\xf9\x68\xff\x9e\x28\xe7\x73\x9c\xb4\x38\x11\x6a\xe9\xca\x47\xf7\x13\x05\xf5\xa3\xe4\xdb\x97\x90\x5a\x33\x27\xd9\xbf\x18\xef\x6b\xc8\x0f\xcc\x5c\x08\xfd\x85\x55\x9a\xef\x48\x81\xd3\xe2\xc9\xff\x02\x5f\xc3\x1d\xc0\xf4\x6d\x11\xb6\x59\x87\x2d\x3d\x0d\x86\xb0\xe6\x40\xa1\x26\xcb\xe1\xbd\xfe\xf2\x9b\xc6\xc9\xcb\x7b\x0f\x62\xbd\x84\x10\x83\xec\x92\x2a\x07\xbf\x3f\x9e\x29\xda\xaf\x48\xb4\xd5\x3b\x51\x59\xc0\x1b\xce\x4b\xab\xfa\x46\xb8\x65\x81\xfa\x4a\x5b\x34\xff\xd3\xf5\xfb\x1e\x9f\x75\x08\xb8\xe5\xcd\x4e\x9f\xc4\x35\xfc\x07\xc1\x60\x50\x8c\xe3\xdf\xe1\xbe\x44\xe7\x97\xc2\x92\xf3\x5f\x08\x03\x63\xa7\x06\x38\xd8\x78\xab\x3e\x49\xb7\x45\xa7\x44\x59\x16\x7e\x6c\x7e\x3e\xf3\x0d\xf4\xd2\xb2\x97\x07\x0f\x82\xb8\x8e\xf3\x0b\xde\x35\x06\x76\x05\xcb\xab\xbc\xb9\x20\x82\xba\xed\x3c\x3a\xba\x48\x6f\x34\xb9\x95\x27\xc5\x38\xfb\x24\x8a\xd6\x42\xdc\xd3\x61\xb2\xd6\x7a\x54\xa2\x02\x63\x3f\x0d\x4d\x47\xc7\x1f\x61\x00\x21\xcc\xd4\x02\xaa\x05\xcd\x32\xb6\x07\xbf\x81\x87\xab\xdb\x60\x1a\xef\x3b\xed\xae\x0e\x29\x22\x28\x38\x11\xc9\x85\xd1\x51\xfd\xcc\x40\xb0\xbc\x6d\x46\xbe\x44\x34\x3d\x4c\x13\x88\xd5\x3a\xc3\xac\x66\x70\xc7\x63\x85\xf8\xd5\x1e\x04\x92\xe9\x3a\x0e\xd0\x02\x23\x4e\x2c\xf0\x64\x73\xa0\xcd\xe6\x2c\x57\x01\x17\xf3\x06\x56\xfa\x27\x5a\xc8\x00\x39\x89\x1a\x0a\x3b\xa3\x61\xfc\x95\x38\xf8\x90\xbd\x9b\x42\x26\x71\x68\x39\x68\x80\xdd\x9e\xd4\xa0\x36\x20\x63\x3c\x97\xb6\xe4\x77\x7d\x10\x57\x56\x73\xb1\x21\xe7\x8b\x5b\x68\x9b\x11\x82\xa6\xf5\x03\x3c\xca\x0d\xab\xda\x96\xff\xbf\xb9\x01\x82\x46\x95\x4d\x14\x05\x74\xea\x90\xa2\x0f\x25\x9e\x01\xf5\xfb\x73\xd3\x11\x0d\xef\xb6\x01\x99\x01\x67\x05\x43\x9a\xa1\x9d\xca\xab\x91\x6e\x2d\xaa\x14\xff\x79\x03\x33\x7d\x89\x66\x25\xc1\xcf\xce\x85\x14\xe6\x9e\x95\x81\xfe\x2b\xe3\x85\xaa\x53\xe0\x9c\x2d\x7e\x4a\xbf\x29\x0b\xaf\x66\x7f\x84\xa4\xfc\xa2\x29\x40\xdb\x97\x2d\x52\xa0\xd6\x02\x10\x97\xd8\x41\xf7\x98\xe4\x6a\xd0\xec\x31\xaf\xcb\xea\x9e\xfa\x52\xaf\x6b\x5f\xc0\x0e\xd6\xde\xae\x96\x06\xfb\xe9\x1e\x94\x7b\xeb\x6e\x23\x09\xea\xf3\xc5\xc4\xa4\xb7\x3f\xf1\x8a\xe5\xa6\x3e\x7f\x01\x88\xa4\x1b\x95\xe3\x0d\x12\x4c\xec\x51\x04\xe6\xec\xd0\x42\x5f\x74\xef\xd3\x1e\x7e\x4c\xee\xaf\xa4\xbf\x51\x31\xdf\x8e\x7e\x7f\xf2\x13\x4d\x53\x48\x4a\xd9\x13\x4c\xd7\x24\xad\x7b\x3f\xcf\xd7\x68\xef\xf0\x5b\xec\x0b\x66\xfe\xb4\xc9\x8f\xb3\xca\xdd\x5d\x69\xa9\x18\x39\x38\x2d\x09\x6d\xb6\xe5\xc6\x37\x49\x6c\xf9\xa7\x93\x71\x62\xc1\xe3\xb9\x55\xb5\xa9\x7f\x4d\x29\x84\xb8\x61\x29\x91\xd2\x59\x70\xc9\x24\xde\xac\xb8\x21\x4c\xc4\x4d\xb5\x82\x85\x20\x95\xf6\x8e\xe2\x66\x3e\x27\xa8\x61\x28\x24\x6e\xc4\xb6\xb9\x25\xdc\x2e\x1d\x8d\x70\x76\x36\x7f\x64\xa9\x14\xa4\x0b\x41\xea\xe4\xcd\xe4\x31\xea\x20\x4e\xd0\x60\x4b\x47\xd8\xb0\x7f\x4a\x11\xe2\xe9\x05\x0c\x59\x30\x0d\x53\x08\x0a\x03\x60\xc7\x5b\xeb\x89\xe4\x59\x68\xa6\x67\x9e\x79\x2a\xee\x42\xc8\xf7\x58\xf7\xda\x9f\x01\xb6\x9b\xa3\xb2\xf3\xb4\xf9\x1a\x13\x33\x20\x6c\xd3\xfe\x75\xb5\x08\xc4\xa3\x71\x94\x8d\xab\xcf\x2c\x04\xde\x39\xc5\xca\x50\xbe\x50\x7b\x21\xee\xee\xb8\x55\xf9\xa0\x5b\x45\x8b\x37\xc1\xe8\xfe\xad\x10\x06\x26\xf4\xed\x9f\x97\x85\x17\x02\xd5\xfe\xa9\x47\xa5\x9e\x15\x41\x73\xff\xda\x29\x34\x1b\xb2\xd6\x72\x41\x69\x6b\x2b\x7b\xcc\x21\x7c\x5c\xda\x81\x57\xd4\xc3\x5d\xa2\x2c\x3d\x5d\x59\x77\xb6\x1f\x73\x09\x1e\x75\x76\x07\x58\xa9\x5b\xfd\xef\xcc\xd5\x05\x03\xc6\x71\xfa\xbe\x75\x8c\x9a\x45\x5e\x36\x4a\x7c\x02\xdf\x00\xc1\x2e\x7f\x1b\xcd\xa5\xfc\x8f\x9c\x1b\x94\x09\x84\x57\x77\x10\x5f\xd2\xe2\x55\x34\x14\x4e\x4a\x44\xf3\x2c\xaf\x9c\x3c\x91\x29\x99\xa7\x7d\xe5\xdd\x26\x54\x9f\xb4\x69\xd9\x0a\x4d\x50\x4b\xb1\x78\xcc\x90\x7d\xd3\xf7\x5e\x1e\x45\xc8\x1e\x32\xfb\xe4\xb7\xf5\x59\x66\x16\x67\x29\x7b\x17\xe8\x37\x5e\x86\xe2\xac\x4f\x64\x81\xfa\x73\x5e\x5d\x07\x7d\xd1\x23\xb4\xb1\xe6\x06\xcc\x50\x85\x31\x09\xe8\x4e\x62\x4b\xba\x73\xdc\x45\x7d\xe9\xb6\x58\x16\xe9\x7c\xe9\x8d\x6f\xc7\x82\x8a\x43\xd6\x60\xf7\x4b\x24\x4c\xb7\xb9\x44\xba\xf0\x83\xdb\x4c\x1b\xac\x29\x96\xba\xbb\x32\xca\x95\xea\xfd\xd6\xb6\x6a\x60\x74\x44\x5e\x00\x28\x78\x26\x69\x56\xed\x5b\xf6\xe5\x83\x1b\x1e\x08\x18\xfe\x5c\xf1\x85\xe1\x08\xe3\x50\x41\x0a\x55\x0b\x18\x38\x43\xce\x25\x1a\xbd\x4b\x55\xf6\xfa\xea\xea\x9f\xa5\x77\xb6\x94\x4f\xaf\x92\x5a\xf1\x65\x0b\x47\xab\x6e\x9c\x3f\xbc\x46\x94\xce\xd2\x17\xa2\xf4\x17\x16\x5b\xdd\x2f\xc5\xb6\xe8\x60\xd5\x8d\xac\xdd\x31\xac\x30\xc4\x40\x88\x5a\x1c\xd8\xb4\x2e\xcb\x89\x1e\xf2\x5a\x98\x06\xc5\x11\xa8\xc3\x26\xe7\x28\x74\x10\xef\x4e\xff\xd1\xdd\x0a\x08\xe3\x26\x63\x86\x2e\xdf\xe8\xc2\xd5\xe5\x04\x5a\x02\x09\x9d\x4f\xa5\x43\x66\x37\x42\xd5\x50\x0c\xe6\x8b\x80\xd3\x50\x70\x57\xc9\x58\x3a\x5d\x1e\xd9\x03\xf5\x62\x60\x49\x8a\xff\x71\x0e\x67\xac\xbe\x5f\xa8\x5f\x7a\xd0\xd8\xc4\xe4\xa9\x2f\xb7\xa1\x59\x62\xa1\x5d\xfa\xe3\xe6\x88\x9e\xa8\xb3\x59\x74\x17\x8e\x60\xf3\x12\x90\xca\x34\xd5\x82\xac\x4d\x26\x2c\xc5\xdd\xd0\x05\x75\x3f\xa9\x2f\x92\x29\x3a\xdf\xea\xec\xda\x0a\xe5\xaa\xa0\xfd\x76\xbb\xfc\x32\x63\x48\x13\x5e\x31\x4b\xcf\xc0\x6b\x50\xa7\x8a\x19\x60\x13\xb3\xb2\xee\xc0\x8a\xec\xaa\x4b\x0f\x21\x10\x7d\x5b\x45\xd8\x1d\x89\x18\x62\x5d\xce\xc8\x14\x71\xc8\x77\x1c\xfb\x27\x24\xac\x6c\xce\x04\x2b\x18\x07\xba\x15\xf7\x3d\x05\x2a\x31\x38\x97\x44\x28\x1e\x31\x3a\xfc\x17\xb0\x38\x4a\x14\x4b\xaa\x5e\x55\xc6\x4b\x9e\x60\xd1\xac\x8e\x00\x94\xf8\x22\x6a\x30\x80\x8e\xb7\x93\x58\xda\x14\xb9\x20\x8c\xde\xfc\x74\xeb\x39\x61\x21\x9f\x72\x1a\x57\xb8\xa0\x8a\x34\xc5\x6b\x0e\xc5\x6e\xd5\x6a\x39\x9f\x23\x30\x52\xb7\xba\xcb\x7c\x55\x6d\x2f\x5d\x8d\xb8\x42\xb3\x97\x33\xf4\x6b\xb8\x0a\x58\x1b\xe7\x3c\xcf\xb1\x13\x63\xbd\x0e\x7f\x86\x1f\xa7\xc5\xf9\x5c\xd7\x54\xbf\xa3\x49\xd5\x5f\x6d\x4e\xc1\xd9\x41\x4d\x0d\x5a\xc0\x33\xe3\xea\x92\x66\x93\xcf\xa6\x7c\xe9\x98\xd1\x24\xab\xd8\x38\xa2\x4b\x9b\xfe\x05\x3c\x73\x7c\x3e\xc3\xfd\x0d\xac\xd2\x70\xe8\x9a\xc2\x6c\xba\x0d\x1f\xba\xe1\xbc\xb8\xd1\x0f\x32\x9c\x22\xc7\x57\xe9\x31\x1d\xa7\x72\xb0\x77\xbd\x2c\xbe\x58\x38\x75\x32\xaa\xf5\x38\x6c\x91\xc1\xc8\x7d\xc5\xac\xc4\xe9\xb9\x4e\xfd\x81\x23\x7e\xf9\x70\xd9\x1b\x95\x2a\x4a\x2e\x40\x5d\xac\x9a\x75\x38\x7c\x3d\x1c\xcc\xe6\x55\xe6\xee\x3a\x0c\xec\x46\xfe\xe5\x24\x46\x5a\x56\x46\xac\x4e\x6b\x73\xe2\xb1\x7a\x93\xb9\x2a\x91\x10\x95\xeb\x5d\x67\xb1\xc6\xce\xd2\x8f\x45\x2b\xc4\x51\x89\xd6\x5c\x47\xba\x40\xb9\x2b\xd9\xa2\xf5\x2d\x34\x46\x8b\x19\x76\x13\x98\x45\x6c\xd0\xbf\x2d\xdd\x98\xcd\x2f\xf6\x1c\x16\xf9\x3e\xc9\x65\x4b\x5a\x1b\x18\xfc\x0f\x4a\xd6\x91\x48\x8c\x0f\x70\x05\x07\xfa\x9d\xff\xe4\x27\x76\x4f\x9b\x6d\x5a\xf1\xe2\x2e\xe2\x30\x89\xd3\xec\x25\x28\x86\xd4\x46\x10\x4b\xe0\x45\xa8\x28\x76\x2e\x81\x45\x85\xce\x98\x33\x3c\x6c\x80\x3e\x7c\xd6\x6e\x01\x5f\xb0\x9b\xdb\x7d\xba\xec\xb7\x24\x74\x04\xf0\x4b\xeb\xf1\xe8\x6f\x12\x2a\x63\xbd\xe0\x99\x96\x24\x93\x0c\xee\xf6\x67\x8e\xec\x64\x43\x25\xa0\xc6\x89\x5e\x0c\xb4\x95\xba\x4e\xe3\x8e\x05\xfa\x5b\x6c\x72\x59\x09\x4d\xcd\x14\x53\x38\x8b\x42\x94\x8c\x5f\x47\x80\x08\x95\xc9\x46\x09\x92\xd9\x73\x16\xa6\x8b\xcd\x94\x54\xed\x6a\x46\x96\x2b\x1b\x96\x41\x61\xab\x59\x9b\x02\x7e\xf2\x5e\x6f\x46\x00\xc3\xf5\xa2\x08\xcf\x70\x55\x1b\x77\x79\x2b\x59\x23\x7b\x4a\xd2\xdc\x20\xbb\x26\x9e\x64\x00\x3b\x2f\x6e\xf5\x20\x7a\xcd\xe5\x7d\xf2\x45\xf1\x77\x11\x64\xe9\x5d\x34\x39\x56\xbf\x9a\x3c\xbe\x0a\x45\xc7\x32\x2b\xdf\x36\xf5\xdd\xb1\x7a\xc3\x57\x3b\x41\x47\x53\x88\x9d\x7d\xf8\x55\xc0\x23\x04\x92\x17\x71\xdc\x0e\xb8\x73\xff\x88\x0a\x5d\x2e\x8a\xa9\x4d\xf6\xd3\xfe\x25\x21\x40\xe7\xc2\x49\x5b\x93\x5e\x3b\xbd\xe6\x34\xd5\x6a\x52\x57\x6f\x16\xac\x78\xb9\xe9\x8c\x1a\xb0\xed\xb4\x30\x7d\x5e\x48\x8c\x89\xb3\x7c\x6b\xe5\x27\x01\x19\xe5\x63\x6f\x12\x93\x2a\x1d\xc7\xc9\x99\xb8\x8b\xa0\xf1\x28\x4b\xdd\xc4\xbc\x4f\xee\x31\xe3\x70\x46\x88\x9c\x09\x1f\x95\x02\x36\x09\x93\x34\x74\xb2\x3e\xb9\x86\x9c\x5b\xb5\x1d\xdb\x84\xb2\x4f\x5b\x7f\x4d\x81\x24\x9d\xc3\x5b\x03\x7a\x6f\xae\x20\xf0\x20\x70\xf4\xf0\x49\x08\x21\xa4\x58\x9b\x76\xdd\x08\xfa\x39\xf1\xdc\x56\x24\x6b\x39\x60\xa2\xc7\x38\xc0\x55\x4a\x22\xa5\x68\x93\x5e\xec\xab\xc5\xc8\xcb\x6f\x42\x78\x9a\x4f\xb9\x57\xa4\xc9\x52\x48\x2c\x1a\x7a\x0c\x2c\x51\xc0\x0d\xb5\x90\x93\x26\x5a\x4b\x58\x1e\xb0\x89\xf0\x9e\x46\x25\x2f\xa9\xaf\xf2\x61\x2e\xe9\x4b\xd5\x27\x9e\x5b\x57\x89\x24\x76\x69\xed\xa3\xda\xb8\x06\xf0\x46\x0b\xf0\x6c\xf7\xe5\x11\x80\x2e\xa2\xda\xba\x61\x6f\x5c\x6c\x39\x74\x78\xa8\x1f\xac\x09\x8d\xb9\xc6\xd5\xfc\x05\x2d\x6d\x42\x8e\xd4\xa2\x8e\x7b\x9e\x7e\x69\xf8\x8f\x5e\x6a\x3e\xbb\xfd\x2b\x13\xf5\x79\xfe\x0a\x1f\xc8\xbf\xcc\x2e\xfe\x2f\x39\x5e\xcd\xe5\xcd\xd2\x4c\x41\x33\x4e\x79\x3f\x5b\x8b\x84\x04\x06\x69\xc4\x2e\x96\x12\x5b\x9b\x16\x53\x64\x6c\x84\xc2\x86\x23\x28\xed\xa9\x2d\x9f\x7d\xd4\xee\xc5\xa6\x8b\x5a\x36\x45\xe3\x29\x4d\x32\x9b\x88\x8b\x92\x89\x30\x55\xdc\x28\x94\xcc\x04\xd2\x1c\x67\xee\xb1\x07\x36\x50\x9c\x9d\x90\x99\xe8\x5a\xfc\x69\xb3\xfe\x59\xa7\x94\x47\xdd\xda\xd0\xc3\x62\x6a\xfa\xc9\x4d\xad\x09\x7f\x12\x45\x66\xc1\x0c\x64\x5f\x07\x67\xb5\xc2\x2d\x1f\xbe\xf7\x78\x04\x91\xd6\x86\x95\x7c\x25\xba\x7c\xbd\x51\x81\x9b\x35\xc5\x7d\x43\x14\x8b\x40\xc7\xbc\x75\x49\x58\x4b\xa1\x03\xde\x58\x8d\xf0\x2d\x7d\xd7\x1c\x3d\xe9\x3d\x19\x54\xae\xcb\xf9\x8e\xdd\x36\xe8\x5f\xed\x48\x84\xe5\x34\x06\x7e\xb2\xaa\x9a\xbe\x13\x52\x56\x9c\xa3\x8d\xda\xd6\x2d\x2a\xe9\x3f\x57\xb9\x18\x9d\x37\x29\xeb\x5c\x31\x8b\x55\xbc\xfc\x8d\x02\x51\xa6\x3d\x00\x8e\x30\x95\xaa\x10\xca\x73\x3c\x2a\xd6\x71\x3f\x4e\x1f\x22\x60\xce\xe6\x2b\xd5\x81\xae\xd4\x9d\x9c\x34\x99\x3b\x17\x20\x98\x43\xdd\x8c\x0f\x2b\x0d\xda\x18\xe5\x79\x9d\xca\x75\x83\x2d\x6d\xae\x9c\xaa\xc0\xd9\x19\x1a\x68\xd6\x21\xf8\x45\x3f\x17\xcc\x3e\xab\x9c\x19\x66\x74\xae\xac\x18\x7f\xe2\xbd\x47\xef\x6c\x32\x0a\xd9\x0b\xaf\xc6\x92\xbc\xce\xc9\x4f\x6f\x30\x81\x96\x93\xf4\x71\x01\x1e\x94\x65\xc6\x16\xc0\xc6\x73\x5b\xe0\xdc\xca\x50\xd8\x9e\x43\xda\xde\x87\x5d\xe1\x4e\xc5\x66\x8a\xa3\x31\x8a\x95\x33\xe0\x32\x57\xa9\x9f\xe1\xda\x1c\x04\x03\x6e\x79\x7d\x51\x76\xcd\x01\x98\x0c\x72\x1f\x32\x69\xe9\xa8\x1d\xda\xe1\x4e\xa2\x93\x5e\x41\x9c\x43\x8a\x2d\xad\xf9\x4f\x80\x4d\x9b\xe4\x28\xea\x32\xb5\x31\x50\x51\x70\x80\xa0\x74\x21\x0e\x00\xc5\x37\x97\x98\x38\xbc\x0c\xe9\x81\x34\xc1\x9c\x1f\xe3\x48\xd3\xe0\x45\xbb\x36\x99\x5b\xe1\x78\x63\x2b\x29\xf0\x93\x5a\x55\x3f\x28\xf5\xaa\x38\x2d\x91\xbc\xc1\xfa\x8d\x95\x02\xea\x94\x2d\xa1\xbe\x84\xb2\x37\xbd\xc7\x1d\x3d\x29\x13\x4b\x17\x21\x4b\xdb\x2b\x32\x09\xb4\x5f\xa8\x0b\x13\xbb\x88\x7a\x3e\xd1\x93\x59\x45\x81\xa3\xe5\xa7\x05\x12\x0f\xae\x70\xc2\x95\x26\x5f\xa4\x62\xd7\x7d\xa4\x00\xaa\x78\x83\x72\x68\xe9\x65\xbd\xed\x03\x08\xc7\x22\x0b\x10\x6a\x9a\x59\xca\x5a\xd8\xd8\x6e\xcf\xb7\x58\x63\xb6\xc1\x69\x8d\x42\x05\x94\xca\x42\x0c\xc2\x01\x90\x3c\x75\x36\x91\x2a\x12\xec\x8a\x07\x44\x28\x28\xcc\xbd\xf6\x80\x31\x9e\xee\x96\xee\x77\x12\x44\xcc\xbe\x90\x95\x8d\x04\x4b\x2c\x82\x93\xe3\xd9\x0b\x0f\xe9\x3a\x51\x92\xee\x3a\x9b\xb9\xea\xb6\xec\x00\xfb\xd6\x86\xf5\xb7\x4b\x45\x85\x41\x55\x4a\xf7\x0e\x15\xcf\x58\x46\xc7\x4f\xb2\x1e\x82\x54\x20\xa9\xb5\xfe\x03\x2c\x25\x22\xae\x70\xe3\x04\x7e\x0f\x56\x71\x23\x8f\x92\xb7\xb6\xa3\x26\x19\x8c\x36\xea\x8d\x8c\xfa\x39\x79\xb2\x49\x4b\x39\x0f\x30\xaa\xca\x31\x0e\x4a\x6a\x94\xb7\xb2\x9f\x4a\xbe\x66\xc0\xb9\xd2\x18\x0f\x3f\xcf\x1c\x9a\x6b\xa9\xce\x4f\xf7\xff\x9d\xd9\xee\xe9\x9d\x61\x55\x47\x83\x2e\x90\x90\x6a\xab\x0b\x48\x09\x45\xe9\xcb\x56\x04\x4d\xf2\x0b\xd6\x71\x09\x6d\xb5\x7c\x97\x69\xad\x21\x0f\x46\x07\x52\x3e\xaf\x88\xb0\x98\xab\x3f\x1a\xfc\x3f\x62\x20\xa9\x69\xbc\x63\x74\x9c\xb4\x67\x9a\x55\x02\x00\x33\x1b\x13\xde\x9f\x68\x80\x30\xc5\xb5\x6c\xc1\x29\x03\x32\x69\x77\x1f\xad\x20\xf7\xd2\x54\x84\xa2\xf5\x40\xcf\x49\xa2\xb2\x21\xaf\xa6\x58\x8a\x6d\x22\xcd\xed\xd3\x18\x7c\xbf\xdd\x4d\x7e\xfd\x32\xbc\x2e\x57\xf8\x0a\x61\xb4\xd3\x33\x85\xfd\x35\xbe\xdf\x82\x2c\xbe\x6c\xb0\x94\xa7\x9e\x65\x12\x71\x4d\x3d\xf4\x20\xb4\x99\xf7\xfa\x67\x23\x45\x0b\x2b\xba\xdc\x04\x9e\x91\x5d\xd3\x3e\x9c\x55\x89\x6e\xe0\xa8\xb7\x87\xb7\xf4\x1e\x96\x70\x96\xcd\xff\xbc\xb9\x67\x7c\x73\x23\xd2\xbb\x43\x0d\x03\x5e\xe8\xa0\xc3\x4e\x71\x86\x06\xdf\x0d\x41\xfc\xcf\x5b\xba\x0a\x62\x45\xec\x5f\x81\x47\x40\x08\xcb\x3c\x91\x20\xbe\x7b\xc5\x8f\x69\xa4\x0d\x6d\xf2\x1a\xcc\xd2\xf8\x85\x4a\x1a\xa1\x93\xe0\x5a\x06\xb8\xc8\xa5\x0e\x22\x5f\xda\x41\xee\x11\x60\xb2\xbd\x5d\x12\x5b\x68\xfc\x4c\x53\x4c\xed\xf7\x76\x98\xab\x41\x33\x20\x87\x0b\xaa\xaf\x32\xcb\xcb\xa1\x5e\xd8\x7e\x71\xb4\x76\x50\xf2\x46\x06\xc0\xdf\xfb\x01\xa1\xe3\x66\xd3\xce\x41\xb9\xc7\x4e\xa8\xc4\x8e\xd5\xc8\x54\xc1\x87\xa1\x3b\x97\x96\x20\x00\x03\x46\xc8\x03\x5b\xe7\xde\xb3\x57\xdd\xec\x11\x0f\x9b\x3c\x09\xa2\xed\xb9\xa1\x25\xbc\x85\x09\x17\x99\xa0\xc1\xa5\xe3\xb4\x0a\x72\x68\x51\xb4\x76\xf3\x3c\xe2\xde\x46\x39\xe7\xb5\x05\xfa\xde\x0f\x82\x06\x21\x12\xe0\x37\xc0\x96\x3f\x5b\x11\x50\xef\x4d\x78\x19\xe3\xe4\xab\x4f\x98\xa8\x81\xb6\x14\xa6\x77\xbb\x6c\x9a\xab\xca\x19\x63\x87\x17\x0a\x2d\x48\x67\x16\x59\xc1\x65\xaf\x43\x6a\xc4\x87\x64\x3c\xff\xb6\x5c\xaa\xa3\x21\x74\xd1\x3e\xd4\x56\xd3\xf2\xbf\x5c\xf2\xf8\xd1\x73\x83\x19\x13\x35\xca\xec\x77\x05\x1c\x6e\xb8\x11\x8b\x37\xc2\xf1\xb7\x8c\x15\x4c\x08\xef\x98\x6d\xa9\xd8\xc1\x71\x6e\xce\x6d\xaf\x00\xc4\x8a\xf5\x77\x3c\xdd\xa6\x13\x92\xf3\x03\x4f\x53\xba\x6a\xfc\x7b\x28\xd4\x64\x5b\x7f\xef\xa3\x22\x13\xe3\xdb\xe0\x4c\x1f\x13\x0d\x80\xf2\xf6\x6a\x47\xd8\x7c\xa1\x2b\x29\xb7\xc6\x30\xdc\xc8\xa0\xb5\xb6\xc6\x0d\x8d\x34\x90\x25\xe0\x4d\xd2\xdb\xd6\x7d\x07\x5a\x14\xd4\x51\xee\x3a\x76\xc7\x7d\xda\x30\x48\x84\x08\xf1\xa0\xa8\x5a\xe9\x9b\x52\xf7\x95\xbf\x80\xcd\xe2\x4f\x9d\x05\xac\xd9\xa2\xf3\x7d\x3e\x28\xc3\xf6\xe2\x96\x72\x56\xeb\x85\xfb\xc0\x39\x0e\xd1\x7c\xb8\x08\xdb\xc8\x0c\x60\x95\xfb\x2e\xb0\x91\xf1\xc7\x57\x15\x36\x62\xf0\x5c\x77\x6d\xaf\xe6\xab\x15\x3c\x99\x04\x77\xb4\x53\x69\x18\x1d\x61\x3b\x0e\x1c\xe5\x36\xe6\xc0\xd3\x41\x6e\x63\x0f\xcd\x13\x20\x27\x43\xd5\x7e\x75\xb1\xa4\xf8\x22\x9a\x12\x31\xf9\x85\x7f\x9f\xce\x26\x54\xd6\x6e\xbb\x3f\xfb\x71\x42\x8c\x7b\x75\x10\x69\xf7\x05\x9e\x8c\x77\x81\xa1\x51\xe3\xe5\x55\x0d\xfd\xe4\x66\xb6\x56\x46\x33\x50\x95\x70\xad\xf3\x27\x59\x86\x7f\x8a\xe2\xcc\x5c\x7d\x96\x1e\x7c\x2e\xe6\x16\x6f\x74\xe4\x81\x4d\x7e\x3f\x81\x7c\xac\x97\x10\x9a\xea\x5c\xa8\x02\x7f\x05\x98\x9d\xc2\x78\x97\x11\xe0\x82\x3b\xcc\x3f\x71\x04\x97\xb9\x65\x8d\x86\x0c\xcc\x50\xb8\xf3\x86\xe0\xa3\xae\x1a\xab\xba\x26\xa4\xd6\x76\x81\x1e\xc3\xdc\x8b\x40\xe6\x58\x48\x91\x73\x92\x10\x4f\x98\xed\xdc\xba\x71\x74\x03\xd4\x51\xa3\xd2\x04\x84\x01\x27\x95\xde\x4b\x1c\xdd\x3a\x7e\x52\x2f\xad\x97\xb6\x6b\x76\xe2\x8b\x37\xec\x69\xf6\x2b\x96\x6f\x60\xa6\x1c\xfe\x6c\xf0\xb6\x8e\x93\x36\x83\xb0\x9d\x15\x38\xf2\x18\x0a\xb5\xa1\x31\x3d\xa3\xf3\xc4\x0a\x41\x2f\x61\x33\x37\xa0\x33\x8b\x46\xcb\xaf\xa6\x5a\xe0\x91\xe3\x6f\x4b\x8f\x0a\xd0\xd4\xd7\x06\x29\x6c\x4d\x37\xdb\x68\x4d\x22\xb0\x58\x10\x72\x00\x58\x70\xc4\x88\xab\x8f\xec\xe3\x9b\xda\xe1\xb2\xf7\xcd\x8c\x2b\xe2\x12\xb9\x69\xc0\x32\xed\xb7\xbc\x14\xe2\x17\x99\xd5\x1d\xf9\x43\x40\xb8\x9a\x4d\x72\xb8\x7c\x82\x84\xe2\x25\x45\x5d\x8b\x7b\xce\xe0\x2d\x6a\xa8\x11\xb7\x8d\x72\xfb\xb3\x9c\x7a\x51\x5d\xb8\xd0\x96\xa5\x14\x8e\x3f\xa5\x50\xa3\xed\x96\x79\xf3\xa9\xbe\x2b\xc1\xfa\xd6\xcb\x35\xa5\xeb\x54\xbc\x2c\x0d\x2d\x2e\xf7\x47\x00\x2c\xf9\x9c\x95\x66\xba\x7d\x49\xd1\xa0\xb8\x96\x4c\x0a\x4b\x94\x10\xd8\xe6\x1f\xc4\xf5\xcf\xf2\xf3\xb2\x8e\xc5\x31\x91\x57\xef\x05\x81\xe5\x22\x30\x12\xb9\x2c\xa1\x8e\xf5\x41\xb2\x28\x26\x58\x4b\x51\x1d\x6d\x59\x68\x08\x68\xb7\x9f\x03\x24\x6f\xec\x97\x85\xbd\x9e\xaf\x45\x85\xd8\x25\x7f\x76\x27\x86\xee\x6c\x3c\x7d\x26\xc7\xe1\xc8\x9a\x4d\x61\xc6\x4f\x50\x26\xe6\xf3\xfe\xbb\x2e\xd9\x7d\x93\x74\x0e\xe8\x9c\x85\xe8\x24\xa6\x4c\xb8\xcd\x2d\x5e\xef\x27\xbb\xee\x52\xb0\x73\x47\x43\x04\x28\x8e\xeb\xa7\x84\x5f\x84\x4c\xef\x16\x28\x57\x14\xc1\x3c\xa1\x37\xa7\xcf\x00\x02\x83\x8b\xa8\xae\x3d\x67\x29\xd1\x4e\xf4\xe7\x4a\x0f\xc4\x89\x9b\x11\xbe\xa4\x0f\xa0\x33\xc9\xb1\xf4\x70\x6f\x27\xa1\x3b\x37\x2e\x55\xdb\xac\xdc\x67\x61\x0e\xf7\x94\xae\xac\x70\xa0\xae\x00\x3f\x9f\x31\xdc\xa0\x6a\xb5\xfb\xf6\x45\xb7\xc5\xb9\xea\xb4\xce\xa7\x27\x9a\x42\x7c\x22\x71\x14\x5c\xb2\xd8\x0c\xff\x41\xa5\xba\x5e\x0f\x31\x3c\x94\x4f\x45\x05\x72\xe2\xf4\x61\xa4\x85\xe2\xc5\xb0\x63\x4e\x33\xa3\xb7\xdb\x5f\x8f\x50\xa4\x13\x2e\x14\x61\xd5\x8d\x2b\x61\x48\x58\x3a\x4c\x73\x6e\x64\x22\x68\x08\x3a\x09\xa1\x4b\xc7\x9d\xdd\x96\x05\x91\x9f\xce\x58\xb9\x0c\x23\xbf\x19\xc4\x7d\xdf\xda\x5d\xf3\x61\xd0\x71\x56\x3c\x8f\x73\x21\xff\x15\x88\xd8\x00\x8f\xcc\xe3\x6b\xa0\x22\xcd\x9c\x31\x6d\x1b\xe5\xbb\xb8\xb9\x63\xd4\x83\x28\x51\xcb\xe8\x13\x0f\xd1\x9a\xed\xec\xe0\x00\x5d\x53\xf7\x66\x1c\x3b\x85\xfa\x59\x2d\xd4\x0a\xbb\x45\xc0\xd6\x13\xfa\x31\xb7\x7d\x0a\x05\x67\x3c\xf9\xc2\x8c\x56\x7d\x0d\xc4\xa9\xe5\x34\x71\x16\x95\xca\x66\x53\xf1\x06\xfa\x32\x7e\xc7\x82\x99\xda\xfd\x7f\xc6\xbb\x26\x68\xf6\x48\x37\xcf\x6e\xa4\x6b\x0f\x51\xbc\xdf\xb8\x85\xe7\xd4\x71\x8e\x0c\x28\x28\xa1\xa7\x2d\xbd\xa8\xf5\x3d\x30\x5c\x11\xc2\xf1\xd2\x24\x72\xba\x5a\x87\x92\x4e\xa7\x33\x09\x3d\x93\xf3\x58\x58\x4e\xeb\x76\xc4\xb2\x98\x2c\x9f\x59\xfe\x84\xd8\x8c\x5c\x1b\x3a\x76\xda\xc3\x0a\xfd\x24\xde\x19\xf1\xa0\x74\x88\xb4\xf1\xb9\x0f\x30\x24\x0a\x33\xc2\xd1\x4d\x50\x45\xe1\x8a\x16\xee\x63\x02\x46\x01\x1e\x5f\x02\x15\x5a\x45\xa0\x3c\x8e\x1b\x6b\x1a\x25\x81\xed\xfa\x78\x7c\xb9\x4f\xd2\x4b\x9e\x2c\xef\x60\xb1\x04\x90\xed\xa6\xa4\xb0\x8e\x9c\xc7\x8f\x10\x59\x53\xee\x7d\x78\x76\x44\x27\xd1\xa5\x28\xa2\xf3\xed\xe9\x73\x85\xfa\x1e\x70\x49\x49\xc0\xd8\xa4\x39\x24\xd4\x4c\x5a\x1a\xc7\x43\xe3\x8a\xfc\xe6\x17\xae\x3f\x65\xee\x96\xa2\x25\x86\xd7\xc2\x04\xc6\xfa\xf9\x57\x05\x56\xfa\x26\x23\xa5\xb2\xa1\x4d\x2e\x2c\x36\x82\x5c\xaa\x3e\x58\x58\x76\x5f\xab\x79\x65\xdc\xd4\x8e\x57\x78\x25\xf7\xd1\x75\x0d\x3c\xdf\x52\x72\x8f\x45\xd8\x5f\x15\x61\x7f\x35\x59\xfb\x2d\x57\xa0\x1f\x69\x39\xa9\x98\xee\x2d\xbf\xfc\xf1\x7e\xc7\x70\x2b\xfa\x0d\x7b\x42\x60\x2d\x5d\x8b\xf3\x37\x2b\xbf\xfe\x4d\x4b\xe0\x30\x21\xc7\x98\xf6\xe4\x7d\xd2\x6f\xa8\xdf\xfe\x12\x6e\x00\xb5\x45\xff\x09\x6c\xba\x76\x94\x55\x02\x79\x00\xa6\x3a\x56\x11\x65\xa3\x15\x3e\x4c\xb7\x5b\xe5\xa6\x42\xf8\xb8\x78\xe5\x6b\x09\xbd\x3b\x61\x2a\xa5\xa7\xc7\xe5\x66\x37\x5a\x79\x50\x45\xef\x79\xfb\x65\x05\x38\x52\x9f\xe3\x86\xcf\x01\x9b\x1c\x62\x39\xdf\xc3\x50\x85\x02\x98\x88\xa8\x46\x0b\x96\x93\x50\xc8\x50\x5c\x96\xb0\xde\x5f\x88\xec\xe5\x7f\xd5\xc8\xd2\x7d\x32\x3d\x02\xca\x38\x7d\x79\x6e\xe6\xff\x9c\x8f\x75\x10\xf1\x16\xe0\x01\xe6\xd8\xdf\x55\x9e\x8c\x3b\x66\x1e\xb7\xd4\x1f\xea\x39\x9a\x6c\xa1\xf1\x04\xb9\xe8\x96\xec\x73\x6b\x84\x2a\xa0\x24\x7f\xcd\xed\x4b\xd3\xcf\x8d\xa8\xb4\x38\xa3\x91\xd5\x75\xfb\xde\x51\xfc\xb5\x16\xc6\x48\x7e\xc1\x74\x63\xd7\xec\x84\xca\x26\xbb\x4a\x10\xe8\x75\xf9\xb1\x9c\x39\xba\x88\x3e\x80\x97\x85\xea\x3b\xad\x9a\x72\x8c\xb4\xac\x5b\x0a\xa5\x03\xbc\x23\xf4\x68\x02\x74\x39\x8d\xb5\x73\xb7\x66\x52\x95\x64\xa0\x71\xc6\x70\xea\xda\x0f\x67\x17\xeb\x18\x83\x13\x59\x36\x59\x5a\x96\xb7\x70\x98\x8b\x1c\x29\x86\x92\x7a\x2a\xe7\xcd\x9c\xe6\x0c\x63\x70\x84\x06\x54\xb7\x06\x2e\x30\x0f\x2a\x11\x0d\x7e\x39\x85\xd4\x1b\x60\xa3\x5e\x4d\xc4\xa0\xcb\x36\xea\x6b\x32\x6b\xf6\x83\xbb\x31\xca\x82\xd3\xae\x8c\x80\x9e\x79\xdc\x26\x19\x32\xc1\xd5\x43\x03\xbd\xaf\x77\xee\x64\x7c\xba\x0d\x27\xab\xec\x08\x3b\xd9\xbd\x0d\xd5\x12\x01\x4e\x9c\xa3\x44\xfe\xec\x5d\x6e\x7a\x26\x90\xe4\x97\xf8\x2b\x1b\x71\xb6\x96\x0d\x36\xb5\x0c\x0f\x45\x9b\x58\xdc\x1e\xd2\x1a\x57\xd8\x1e\x45\xca\x0c\x52\x46\x90\x7a\x81\x18\xa9\xf8\xaa\xdd\xfd\x1c\xc7\x06\xb0\x33\xb1\xaf\x3f\x0f\x61\x31\x59\xd7\xed\xcf\xd9\xc7\x6f\xf8\x73\x8a\x42\x63\x61\x97\xb1\x2a\x8b\xd8\x06\x6d\x5f\xae\xe8\x37\x69\x88\xf5\x5b\xa0\x38\xc7\x9d\xed\xb0\x88\x87\x17\x27\xf7\xa8\x73\x71\x91\xc1\xf7\x28\x57\xcc\x8d\xe5\xc3\x7e\xab\x34\x07\x70\x48\xec\x21\xf0\xef\x29\x42\xe7\x58\xf0\x54\xa0\x3a\x4a\xbf\x88\x10\xda\x87\x52\xa3\xcd\xc6\x1c\x05\x65\xdb\x79\x0d\xc8\x66\x0a\x50\x45\x3f\x62\xb9\x93\x7b\xb1\xe4\x1b\x54\x8f\xde\x06\x45\x4c\xf4\x10\x66\x4a\x6d\xf9\xee\xec\x12\xca\x81\xd7\xf4\xc5\x1c\x3f\xcf\x74\x75\x5e\x20\xeb\xb9\xac\xdd\xfb\x64\x2e\x11\xba\x09\x90\xa6\x8e\x5a\xfa\xa6\x5a\x79\xf4\x90\x40\xff\x0e\x85\xd9\x94\x7f\xe6\x49\xe8\xd3\x13\x22\x62\x0c\xca\xa7\x82\x31\x0b\x0b\xe4\x16\xfc\x1c\x7e\x49\x9e\x5b\xe0\x09\x37\xfa\xd4\x3d\xc1\x20\xbe\x84\xee\x04\x39\x4d\x30\x1a\x9f\xf1\xf2\x5b\xad\xdf\xea\xb3\x4c\x0c\x80\xbf\xdc\x69\xfd\x09\x50\x88\x12\xb5\x67\x11\xfc\x12\xa8\x9e\x8b\xd1\x5a\xf1\x8d\xd0\x3a\xfc\xd1\xeb\xb2\x6c\x79\x4e\x4a\x47\x9e\xd5\xef\xd3\xe6\xa5\x4f\xfa\x4f\x54\x58\xa6\x50\x97\x0e\xcc\xdc\xc6\x90\x64\xfb\xda\x21\x8c\x26\xda\xf5\xb5\x34\x09\xb8\x49\x79\x22\x30\x1b\x32\x3f\x55\x57\xce\x61\x9c\x0f\x47\x68\x6a\x01\xfb\xe9\x75\x14\x47\x60\x52\x1e\x91\x9f\xeb\xb1\xfe\xc0\xf4\x47\xa8\xe6\x47\x5e\xab\xe9\xa8\x18\xcd\x3d\xb2\x64\x0f\x43\x1b\xfb\x99\xb6\x80\x6b\x12\xc4\x29\xd5\x49\xfc\x82\x0c\xa6\x3d\x72\xe4\x67\xf2\x34\x2d\xa4\x15\xf5\xa7\xc4\xa2\x17\x80\x9d\x59\x2b\xbe\x37\xae\x53\xd0\x48\xfa\x93\x6a\xd6\x17\xc8\x4e\x1e\xd9\xda\xe5\xff\x63\xb4\xc5\x08\x01\x7b\x52\x08\x53\xeb\x83\xdb\xf4\xbe\x11\xa2\x69\xfe\x62\xf3\x64\x09\xa8\xdb\xe4\xd3\xf1\x8f\xc2\x76\xf9\x02\xb6\x1c\x4d\x77\xa6\x6e\xd2\x70\x64\xe1\xcd\xe5\x4d\xb0\x6a\x42\x70\xe9\xff\x54\xf1\x42\x30\xc9\x5b\x0a\x0f\xaf\x75\xc4\x5f\x9e\xe9\xae\xf1\xc8\x33\x42\xfd\x4d\x7a\x8f\x70\x73\xe0\x17\xa1\xf8\x9a\x15\x02\x5a\x4d\x80\x26\x00\xa2\x5b\x75\x30\x0d\xf3\x95\x0c\x21\xb9\x41\x4b\xf1\x20\x1c\x89\x7f\xe0\x30\x50\xbe\xb1\xef\x65\xc1\x92\x3b\x69\xbb\xa1\x00\x52\xe2\x0a\x57\x32\x61\xd8\x83\xe2\x6b\xe4\xfe\x12\xb5\xb4\xee\xda\x31\x6a\x13\xaa\x29\x8f\xcc\x93\x6e\xa6\xd0\x65\x16\x54\x0f\x66\x49\x42\x1b\x5a\x96\x03\x1e\xdc\xc3\xf1\x9c\x0b\x67\x6c\x44\x76\x0a\xcf\x09\xce\x2a\x51\x9c\xd6\xd3\x07\xfa\xa4\x83\x7c\x95\x0c\xc4\x2c\xee\x29\x4d\x80\x28\xa0\x7d\xe5\xe3\x8f\x1b\x64\xce\xa0\xdc\xaf\x50\x1f\x8a\x1a\x56\x61\xe4\x3f\xed\x36\xfe\xf3\x46\xbc\xac\x4a\x8f\x05\xac\x8b\x38\x24\x54\x32\x7a\x10\x96\x04\x9c\x78\x7f\xdc\xa2\x91\xa1\x04\x89\x25\xd6\xe9\xd0\x51\x3e\x73\x8a\x04\x02\x90\x4e\x64\x8b\x0a\x87\xb4\xdd\x82\x92\x09\x1d\x77\x80\x0f\xc7\x4d\xc3\x42\x67\x87\xa3\xa0\xc7\xef\x59\xfa\x81\x1f\x1b\x95\x38\x22\x40\xe3\xc3\xc1\x29\x5c\x3c\xc9\xb2\x78\xe6\x91\x51\xda\xeb\x46\x27\x83\x22\x71\xda\x46\x02\x6f\x69\xa7\xca\x8f\x71\xda\x6d\x84\x36\xeb\x8d\xab\x6a\x39\x0e\xe0\x5d\x1b\x21\x95\x75\x36\x43\xc5\x4a\xee\x84\x11\x55\xf8\xa6\xee\x79\xbb\x41\xa0\x2b\x37\x04\x70\xae\x3c\xe0\xdb\xc0\x0e\xad\xf4\x0e\xc5\x4a\xe1\x43\xf9\x99\x76\x77\x2f\x81\x4f\xb5\x3e\xbf\xce\xf3\xc2\xca\x55\x2f\x79\x41\x3a\xc7\xa7\x3d\x75\x07\xfb\xec\xad\xd3\x3e\xbf\x43\x74\x46\x79\x6d\x8b\xfe\x12\x87\x8c\x4a\x1c\x13\xd5\xe4\x5d\x21\x14\xb8\xf7\x1a\xa6\x1b\x56\xda\xd6\x0a\x52\xc4\x1e\x36\x02\xb1\xa6\xae\x29\x13\x21\xa4\x76\x1f\x9f\x1a\x7e\xbb\xe4\xcb\x71\xbc\x59\x6d\x40\x15\xfa\x98\x49\x76\xa0\x4a\x19\xf7\x2a\x6d\x75\x96\x2a\x7a\xb5\xa6\xfb\xf1\x9e\xa5\xbd\x00\xd6\xc6\x2b\xd6\x5f\x41\x06\x9f\xe5\x02\x4b\x43\xdf\x11\x20\x95\x23\x72\xd1\x95\x9b\xb9\x77\x1d\x25\x08\x79\x92\x47\xdd\x9e\x30\x5f\x58\x7c\x61\xa9\xdd\x4e\x55\xd4\x2c\x12\x2a\x74\x13\x08\xbf\x85\xa2\x71\x00\xe4\x10\x6b\x8a\xd9\x6e\xe1\x9d\x89\xb4\x19\xde\x60\x94\xd4\x8c\x15\x46\x88\x4d\x54\x20\xeb\xd3\x95\x57\x10\x17\xfa\x3a\x0b\xb0\x9a\xda\x43\x8d\x3d\x07\x6a\xf4\xac\x80\xca\x4d\xb2\x7c\x00\xb0\xe6\xa4\xa0\xd9\xc2\xda\x76\xeb\x12\xb1\xa0\xb0\x10\x96\x90\xaf\xa3\x57\xaf\xc0\x9f\x1e\x55\xb2\xce\x1b\x15\xed\x8f\x56\x3c\x82\x1e\xcf\x6b\x78\xe3\x63\x6a\x7f\x02\x63\x13\xf0\xd4\x6f\xb4\xb3\x37\xc7\xf5\xf6\xa8\xb5\x9b\x6d\x0b\xa7\xdb\x98\x1b\x5b\xf8\x5b\x34\x5f\xb4\x58\xb3\x99\x87\xb0\xae\x31\xe5\x77\xe7\x5a\xbf\x6c\x6c\xb4\x50\x99\xd2\x09\xb4\x45\x97\x65\x69\x25\x21\x6a\x83\x10\x15\x4b\xdd\xc3\x3a\x00\xae\xeb\xd7\xa7\xfd\x87\x59\xce\x6c\x64\xdc\xab\x58\xe8\xfc\x1f\x18\xec\x71\xe8\xf9\x14\x0c\x36\x7f\x35\x51\x9f\x51\x7e\xdd\x86\x22\x76\x7b\xff\x39\x3d\xa4\xf8\x84\x7d\xa5\xcd\x61\x5b\xaa\x3e\xab\x75\x90\xc1\x0e\x69\xa7\xb3\xaa\xe4\x43\x94\xd4\x93\xdf\xd6\xa6\x3b\xcb\x93\x48\x27\x8b\x93\x30\xab\xf0\xc8\xe6\x2f\x3e\x39\x88\x8f\x3b\x09\xf9\x73\xcd\x52\x62\x4b\x5d\xbd\x54\x97\xd8\x85\x4a\x39\xda\xb4\xe3\xd6\x9e\x73\x5b\x5b\x18\x22\x28\x37\x3b\xda\x6c\xf4\xd8\x08\x62\x3d\x8f\xbf\x95\x8f\x8f\x85\x04\x28\x3a\x6a\x36\xe0\xae\xa7\xaa\x02\x14\x6b\xd2\x2c\xad\x1d\xc6\x7a\x5b\x02\x1d\x9b\x14\xa4\xbe\x08\x5f\xfb\xb5\x08\xe9\x86\xbb\x77\x98\x60\x1c\x16\xac\xca\x36\xd4\xc3\x11\xe8\x4f\xc0\x02\xeb\x3f\x06\x59\xcf\x73\xba\x32\x35\x83\x5a\x14\x3b\x88\x44\xdd\xc8\xbf\xe7\xfa\x59\xe8\xb2\x26\x9f\xf6\x48\x23\xd5\x81\xb1\x40\xc6\xf2\xa5\x90\x09\xa5\xa9\x6e\xc7\xa8\x8d\x0b\x67\xd9\x32\x11\xb4\xa8\x0e\x4a\xce\x14\x20\x6f\xf0\x91\x5a\x36\x3b\x0a\x5b\x9e\x7f\x7f\x7b\x72\x03\xdb\x93\x2a\xdb\xf0\xd4\x0d\xd1\xd2\x45\x3f\x79\x73\x4a\xd3\xd2\xe9\x2f\x32\x6b\x05\xa3\x7d\x49\x92\x11\x0d\xae\x3c\x6c\x73\x8b\xf6\xd5\x65\x76\x38\xe7\x6a\xce\x4c\x2d\x37\xce\xec\x1d\xbb\xca\x9d\xc9\xbe\x48\xb2\xa7\xe5\x6a\x6b\xbd\xba\xf1\xe1\x80\x6f\xc4\xce\x56\x29\x45\x53\xa8\x64\xe4\x61\xd9\x8f\xff\x62\x5b\x6b\xab\xa7\xe5\x6e\x38\x79\x5a\x44\x9d\x20\xc0\x5c\x5d\x9c\x36\xb0\xae\xa5\x3b\x6c\xac\xa3\x52\x1c\x56\xb1\x0f\xc2\x24\xdc\x77\x57\x70\x57\x47\xea\x8e\xb0\xe4\x61\x7e\x60\x8f\x31\xbc\x0f\xf9\x55\x28\x78\xb2\x5f\x69\xc6\xbe\x29\xb2\xf5\xcd\xd4\x46\x14\x06\x95\x6e\x98\x9e\x13\x6f\x81\x38\xb5\x7e\x25\xf9\xec\xa7\xb1\xac\x97\xe0\xde\x3c\x94\x22\x2c\x6b\xe5\x50\x37\x90\x8e\x89\x1f\x45\xb1\x87\xd4\x64\xf7\x90\x40\xd2\xdc\xad\x74\xf1\x6a\x72\x17\xea\xa4\xba\xae\x09\xeb\xda\x15\x9e\x6b\x37\x71\xc5\xb8\x86\x4c\xe9\x26\x9d\x49\x44\x99\x93\xd8\x26\x20\xdf\x80\xb8\xca\xd9\x77\x9c\x84\x43\x4e\x82\x26\x3b\x94\x35\x35\x4d\x88\x99\xb6\xa2\x24\xa7\xc8\xb7\xec\xf7\x16\x5c\x1f\x85\x26\x56\xb6\x13\xf2\x38\x07\x75\x9e\x9c\xe1\xc1\x0e\xf7\x46\x67\xde\xcc\x0e\xd7\x3d\xd5\xd4\xd3\x71\xe9\x47\xb8\x80\xa1\x96\x8b\xd5\xba\x74\x1f\xfa\xe5\x69\xe4\x93\xe0\x31\x1c\x7b\x21\x05\xdd\xea\xb4\x36\xa4\xdf\x4e\x4c\x85\xaf\x00\xef\x45\x44\x29\x7f\x01\x50\x37\x7b\x9c\x08\x80\xb5\x59\x08\x95\x52\xb1\x94\x4f\xc4\xe7\xea\x6b\xed\x84\x7c\xae\x7c\x93\xfe\x52\x38\x8b\x2e\x84\xe8\x2e\xa8\x27\x72\x67\x40\x70\xec\x59\xdd\x24\xa8\x02\x42\x41\x91\x52\x02\x63\x1e\x31\xa3\x6c\xe6\xa9\x70\x28\x9c\x58\xfe\xd1\x09\x14\x3b\xf2\x10\xac\x04\x52\x53\x12\xe5\xd0\x40\x97\x3a\x5d\x2a\xc9\x81\xf5\x6e\xf1\x52\xcd\x96\xa8\xa9\xfb\x47\x82\xbc\x8e\x12\x57\x05\x96\xde\x0f\x18\xa1\x36\x41\x87\xe4\x11\xda\x98\x99\x91\xd4\x25\xd2\x10\xff\xbe\x1b\x5f\xf1\xc3\xc1\xb6\x87\xaa\xf3\xee\xcd\xb0\x94\x00\xcb\x3e\xfb\x81\x7f\xa7\xfb\x02\xd7\x1f\x28\x94\x59\x11\x67\x4b\x94\x7c\x67\x07\xad\x04\xb7\xf9\x6d\xc3\x7e\x16\xa8\xda\x42\xcc\x5a\xa2\x0f\x04\x3c\x80\xfc\xf7\x73\x9c\xd7\x97\x39\x74\xdb\x3a\x01\x4f\x16\xc2\xf6\xf8\xcc\x95\x34\x98\x1a\xf5\x84\x09\xa6\xdd\x55\xa3\x15\xaa\x63\x84\xe2\x76\x4e\xfa\x7e\x10\x8e\x1b\xaa\xac\x7f\x98\x92\xfd\x31\xff\xb6\x3c\x4d\x4e\xf8\x7f\x79\xe2\xb5\xb2\xc0\xab\x0c\x17\x47\x8a\x2b\xbf\x7b\xfa\xf8\x5e\xd9\xd9\x0f\x57\xde\x5f\x61\x45\xcc\x32\xd1\x95\x29\x18\x7e\xe5\xe4\x5f\x71\xa5\xf9\x74\x86\xd1\x45\x45\xbd\xcf\x95\x84\x39\xff\xec\xab\x63\x6c\xb7\xb1\x5a\x63\x7d\x90\x51\x4c\x21\xe4\x7a\x4e\x50\x27\x25\x7f\xdb\xad\x8b\xab\xe8\x1d\x30\xbf\x9a\x89\x7d\xc6\x65\x91\x15\xf1\xc2\x81\x18\xbd\x92\xa0\x9c\x40\x91\x55\x20\xfc\x67\x88\xf5\x0b\x07\xfe\xca\x9e\xe3\x03\xa5\x2b\x87\xec\xda\xd8\x41\x7f\x45\x8b\xb2\xfc\x90\x2d\x9a\xf4\x3d\x08\x1b\x2f\xdb\x78\x2b\x85\x16\xab\x2f\x4a\x85\x58\x2c\xf5\xe9\xf9\xb7\xe4\xfc\xd2\x22\x96\x85\xa1\x34\x9b\x93\x90\x25\xae\x05\x66\x13\x13\xfe\x4e\xb4\x3b\x0d\x94\xf0\x3e\x84\xa8\xf4\xc7\x9e\x72\x29\xbc\xb2\xa8\x68\x33\x58\x75\xde\x88\x74\xfc\xf4\xe2\x43\xfe\x91\xe3\xe2\xc7\xee\x4f\xc1\x89\xed\x22\x7a\x31\x00\x4e\x85\x6b\x10\xf0\xdf\xa3\x4c\x73\x09\xa3\x20\x94\x18\x7d\xbc\xa2\xde\xa7\x1c\x99\x8d\x2e\x97\x23\xad\x81\x4e\xbe\x61\xb1\xc0\x55\xf9\x11\xd9\x26\x96\x44\x1e\xdb\xdf\x43\x74\xb1\x3d\xc0\x61\xa1\xf9\xbe\xeb\xcf\xef\xe4\xc8\xe9\x77\xd2\xd4\xfd\x2d\xfa\xa4\x6d\x6d\x36\x2f\xe1\x0a\xb7\x4a\x3e\xc2\x2d\x79\x2d\x44\x2b\x0b\x2c\x0f\xd0\x31\xa7\xed\xe7\x3a\x94\x69\x8f\xa9\x99\xb7\x2a\x02\xd9\x75\x71\xa3\x71\xee\x01\x42\xa6\x77\xab\x4d\xd1\xaf\xef\x5a\xc1\xb9\x6c\x60\x3f\xd5\x46\xf6\xc9\xe1\x5f\xc5\x12\x3b\xf8\xa3\xfd\x2a\xc9\x9f\xcb\x9c\x76\x82\x96\xa1\x2d\x35\xc4\x17\x7d\x99\x2e\xb3\x8d\xca\xc4\x56\x05\x5f\x7b\x1b\x93\xf9\xfd\x55\x0a\xf6\x21\x54\xb2\xc8\x52\x1e\x6f\xe9\xcb\x98\x59\x75\x31\xf7\x53\x12\x33\xea\x5c\xa0\xbe\xee\xfd\x8b\x85\xa3\xc4\x66\x9b\x31\xc5\x9f\x49\x90\xea\x19\x9d\x16\xf0\xc7\xe1\x90\x7a\x54\x81\x2c\x09\xbe\x0a\x0a\x3c\xa6\x8e\x81\x3d\x2b\xc1\x48\x45\x65\x66\xa0\x0c\x0b\x96\x4f\x46\x96\x5b\x0f\xb2\xfa\x78\x00\x4c\x96\x27\x25\x18\x54\x76\x2d\x61\x07\x81\xe6\x12\x7a\xb0\x61\xb3\x49\x14\x78\xbc\xb9\xab\x91\xfd\x71\x45\xdc\x8a\x03\x8b\x49\x80\x06\x38\x70\xd8\xfe\xfa\x4b\xdb\x21\xc0\xb8\xf6\x5b\x6d\x01\x44\x4e\xd5\xf4\x58\xb0\x5d\x14\x9d\xf9\x55\x72\x44\xf6\xd0\xfd\xdb\x6f\x04\x3b\x14\x5f\x17\x39\xd0\x49\xde\x95\x7f\x31\x70\xc8\x52\x0d\x0a\x60\xb2\xb0\xc7\xdb\x36\x2a\xa2\xd2\x87\x6d\x9f\xbc\x9b\x80\x4b\x06\x1c\xf5\x21\x60\xf2\x40\x79\x14\xc5\x52\x9e\xad\x28\x65\xe9\xbd\x46\xdd\xf5\x08\x89\x05\x92\xbf\x15\xe4\xa8\x02\x1d\x29\xfc\xd4\x0f\x49\x98\x1d\x72\x65\x39\xbc\x28\xef\xc1\x2b\x4b\xc9\xd5\x8b\xd3\x9e\xb3\x1c\xa9\x83\xc0\x9a\x7f\x03\x60\x3f\x0d\x87\xd2\xfd\x72\xc9\x3f\xec\x76\x88\xb2\x20\xcc\x58\xb7\x25\x6c\xb9\xba\x0f\x9f\x9a\xb5\x3b\xc0\x61\x67\xf0\xfc\x82\x2d\x63\x59\xbd\xb6\x06\xfb\x56\xf6\x3e\xbb\x3d\x6c\x2b\xb7\x42\xb5\x52\xcf\x55\x1f\x31\x87\x19\xbf\xe5\xa5\x27\x37\xeb\x20\x39\xd7\x09\x9e\x64\x81\x8c\x9e\x9e\x14\x71\xa5\x29\x32\x60\xcf\xa1\x2a\xe9\x6b\x73\xc2\x52\x37\xb4\x4f\xad\x2d\xe1\x85\xcf\xc6\xbe\xa7\x8f\xbd\xdd\x49\x90\xf0\x55\xe1\xc9\x28\x01\xf2\x55\x17\x9f\x20\x2e\xd9\x86\xe4\x1e\xa9\xc3\xae\x56\xae\x08\xe8\xe4\xe5\x68\xa9\xbf\xaa\xa5\xc3\xca\x76\x1d\x81\xad\x47\x2b\x3b\x19\x94\x0d\x51\x5f\x43\x30\x36\xbe\x1c\xf8\xe7\xa4\x63\xaa\x25\xf2\x91\x89\xca\x73\x3a\x09\xb1\x9c\xe8\xd6\xec\xde\x5f\xb5\x94\x66\xed\x95\x6a\x3c\x6a\x38\xd5\x2e\x5a\x42\xe5\x5a\xb0\x06\x90\x9a\xf2\x44\xda\x9d\x5e\x55\x4a\xd2\xa6\x2f\x67\x18\x54\x83\x7b\xa7\xc8\x72\x00\xe8\xf1\x6d\xc0\xc4\xbe\x6c\x7a\x77\xcd\x82\x61\x2f\x1d\x9c\x1c\x69\x5e\x6c\xf7\xdc\x87\x6b\x17\xee\x25\xa6\xf9\x85\xfb\xde\xf0\x13\x51\xf3\x39\x2a\x10\x5b\x0a\x5e\x40\x5f\xcb\x91\x78\x3d\x79\x46\xd6\x85\xfb\x7a\x0b\x02\xa2\xa7\x37\xda\x15\xec\xab\x9d\x67\x52\xb4\x45\xa5\xc5\x12\x92\x71\x09\xf7\x6a\xaf\xa5\x85\xaa\xad\x53\x37\xfd\x84\xd6\xdb\x0a\xdb\x7b\x07\x1e\xe0\x52\xf1\x7e\x3e\x28\xc1\x06\x40\x5b\x28\xdf\xb2\x9c\xdf\x6a\xb6\x40\x66\x0b\x7c\xdd\xd6\xe1\x67\x5f\xce\xea\x5b\x5d\x3e\x22\x0d\x39\xf4\xba\xb8\xe6\x32\x61\xd9\xa3\x0c\xc2\x97\xf4\xf4\xdb\x7a\x06\x59\xd5\x25\x4a\xbd\x35\x4a\xfd\x77\x3a\x43\xfd\xd7\xa2\x95\x5e\xd4\xf2\x5e\xdd\x27\xda\x0e\xbb\x66\x2d\x46\x73\xfe\x2d\x76\xf2\xdc\x2b\x74\x3f\x14\xa0\x08\xed\x7f\x5d\x5d\xe8\x71\x82\x59\xa9\x5a\x83\x43\xb4\xbf\x4f\xed\x95\x88\x43\xd8\xc7\x7f\x3c\x80\x54\x6f\x58\x61\xb3\x59\xbb\x28\x86\x1e\x2c\x7d\xd5\xb5\x75\x99\x1e\x41\xbd\x5d\xbb\x96\x08\xef\xfe\x29\x65\x9c\x7d\xa4\xec\x17\x9e\xbd\xb4\x51\x16\xb7\x93\x65\xea\xee\xc6\xfd\x1e\x34\xf5\xc1\x07\xd1\xf7\x22\xf2\xfb\xa4\x8c\xad\xc3\x87\xaa\xbf\xb4\xf5\xda\xc8\xb2\x74\xf5\x07\x1b\xa4\xc2\x4b\xbb\x7c\xbe\x14\x8f\x07\xac\x36\xf1\x1c\x87\xff\x4c\x12\x5d\xed\x16\xa3\x3f\xe3\x75\xa2\x04\x8c\x85\xa5\xaa\xf5\x0e\x63\xa2\xef\x1a\xe0\xa5\xf1\xdb\x0d\x49\x46\xdb\x54\x7b\xd9\xb1\xa0\xdf\x8d\x2b\x07\x7c\x6f\xc9\xe1\xda\xa5\xeb\x73\x84\x82\xcc\xed\x30\x7a\x09\xd6\xd6\x0e\xfa\x7e\x40\xe5\x73\x0e\x4f\xdd\x3d\x77\x51\xc3\xdb\x73\x68\xdf\xc3\x75\x20\x47\x72\xb7\xdf\x3e\xe7\xf0\x5c\xb1\xcb\x72\xba\x85\x04\xfd\xba\x3d\x28\x9f\x1b\x81\x7e\xd6\x83\x0b\xa4\x4a\x65\xd0\x6d\x5d\xf1\xf6\x07\x29\x56\x75\xe5\xc8\x23\x42\xed\xb9\x1d\xe6\x53\x6a\xde\x50\x89\x8a\xbd\x49\xfa\xb8\x69\x5a\x63\x47\x85\xa3\x3f\x9f\xb7\x98\x6e\x3a\xab\xdd\xb7\x4b\xde\x32\x5e\xa4\x33\xec\xda\xb7\xd2\xb6\xbd\x8d\x67\x76\xff\x2c\xed\xb7\x87\x55\x9e\x2b\x16\xab\x53\xb0\x1b\x9a\x3a\xba\xf0\xbc\xc4\x9e\xed\xea\xd3\x44\x8f\xcd\xed\x8c\xc2\x07\xcc\xb2\x34\x4d\xdd\xce\x5b\xdc\x04\xf6\x48\x42\x8a\x9f\x5d\xb2\x4c\x8e\xea\xb8\x5a\x3e\xb3\x7e\xc0\x65\x59\xcb\x71\x54\x27\x92\x4d\xea\x8c\x7c\xbd\xc8\x2e\x30\x26\x80\x8c\xd1\xa5\x37\x53\xf0\xd9\xac\xdd\x11\x2c\xcf\x8a\x38\xb0\xf0\xb8\x01\x11\x12\x1c\xb0\x81\xec\x4b\xcf\x6d\xd5\x5e\xb7\x21\x3b\xc6\x83\x7e\xe0\x15\xcf\xed\x0d\x41\xb2\x81\xe9\x54\x08\xff\xb1\xb5\x0a\x67\x6d\xd9\x67\x91\x8a\x31\xf0\x26\x01\xe7\x7d\x8c\xd9\x19\xae\xa3\x00\xe5\xfb\x6d\x83\x41\x31\xde\x3b\xa6\x33\xb9\xde\xa0\x95\x4a\xb8\x89\x4f\xbb\x20\xf3\x2e\xce\xae\xc3\xd7\xd0\x6f\x77\x1d\x5f\x9d\x99\x3a\x1e\x0f\x02\xf2\x4e\x61\xde\x47\x95\xdf\xf5\xf9\xf9\xe6\x0a\xe9\xe1\xee\xfd\x94\xc0\xa3\x45\xd3\xed\xda\xe8\x18\xea\x56\x45\x77\x80\xde\xdb\x72\x7b\x92\xc3\xf4\xea\xa8\xe8\xf9\xbb\x5a\x1d\xc2\xbc\xb1\x23\x0e\x67\xf5\xb7\xb6\xdc\x08\x53\xf1\x28\x77\xf2\xf1\x06\xce\xaf\x71\x96\x08\x53\x1b\x46\xe6\x79\x7c\x57\x43\x72\xcc\x7a\x15\x2e\x63\xcd\xe0\x51\xd1\x0c\xc2\x01\x94\xf8\xbc\x27\x27\x66\xde\x3f\x1b\xc7\xed\x11\x38\xd6\xf9\xf6\x31\x3f\x62\x91\x17\x48\x05\x9b\xd7\x6a\xe5\x04\xfe\x1a\x3e\xc8\x5b\xd0\xfe\x25\x5a\x9a\x6f\x12\x10\x0e\xf7\x29\xe9\x0c\xeb\xb3\xe3\xc9\xc2\xf4\x99\xf7\xa0\x4d\xf6\x38\xe5\x82\xa7\x91\xdb\x53\x3e\xdc\x0e\xfd\x10\x4e\xc8\x86\xe2\x3f\x55\x0c\x2c\xf4\xc7\xda\x15\x78\x22\xd7\x03\x46\x3f\x52\x27\x5f\xa1\x7d\xde\x88\x28\x98\xa4\x07\x08\x7f\x9e\x83\x13\xbe\x9e\x14\x92\xa3\x23\x7a\xa8\xd6\x02\x97\x9f\xb1\x5a\x25\x54\xfe\xbf\x91\x36\xd8\xc0\xe1\x0b\x13\x8e\x90\xb0\x75\xdd\xe6\x81\xc0\xf7\x95\xb0\x40\xc7\x7b\x8b\x91\x25\xc4\x7d\xdd\x8d\xc5\x3b\x21\xf3\xcb\x0d\x83\x82\xda\xb1\x13\x25\x42\x14\x19\xde\x5f\xb7\x4b\xfb\x46\xa0\xfb\x37\xa1\xd4\xa5\x8f\xf5\x62\xfd\xd2\xbc\x37\xd7\x11\x63\x93\x35\xa9\x0d\x7b\x43\xfc\x09\xad\x97\x38\xb2\x64\x60\x95\x0d\xf2\xa3\x90\x2a\x3e\x02\xe8\x4f\x68\x7e\xac\xee\xad\xe5\x00\x82\x67\x67\x68\xfb\x37\x1f\x7a\x39\xaf\xd1\x8a\xb0\x35\x58\x84\x74\x9f\xf6\x2c\x9c\xff\xac\x8d\x83\x4a\x78\x6a\xd6\x00\x3e\x43\x00\x03\x9b\xdb\x5f\xa0\x38\xea\xb5\xe9\x92\x1c\xb4\x63\x36\x1d\x90\x1e\x94\x0d\x78\xbb\x67\x6d\x9b\x20\x12\x4c\xe7\xc8\x7d\x48\x8b\x3c\xc8\xbb\xe3\x4c\xb1\x8e\x2c\x67\x74\x8b\x82\xb4\xe6\x19\x5e\xe8\x27\x2f\x15\xea\x3f\xb9\xa1\xf9\x93\x59\x81\xf5\x46\x20\xf5\x12\xe2\x3e\xda\x98\x50\xb4\x1b\x59\x4a\x2b\x1d\x66\xf7\x85\x7f\xfc\x3f\x99\xc1\xfb\xeb\x03\x91\xfc\x83\x5b\xe4\xaf\xa2\x0d\x0c\xe3\x54\x79\x65\xeb\x33\x63\x9a\xac\x33\xcf\x55\x4a\x24\x2c\xe4\x2a\xd1\xe0\x8c\xee\x1a\xb6\x12\x39\x0a\x64\xd1\x90\x3f\xbf\xfd\xd4\x70\xac\xfe\x6a\x4e\x62\x70\x60\xc9\xc9\x7a\x11\xa2\xf9\x3f\x01\xe0\x3f\xf7\x80\xef\x9f\x81\xfc\xc7\x34\x33\x5e\xfe\x52\x71\xe6\xb4\x0c\xb9\xb3\xfa\x37\x90\x39\x2a\x59\x24\x49\x7f\x05\x22\xcf\x5e\x8b\x41\x10\x2a\xce\x40\x6b\xc6\x5f\x95\x90\x15\x33\xb2\x2f\x44\xc5\x4b\xfb\x75\xc6\xd5\x04\xaa\xbc\x6f\xdd\x8f\xa0\x07\x3c\x6e\xe3\xf8\x88\xd7\xdb\xed\xaf\x36\x2b\x57\xa0\x2a\xd3\xa8\x8d\xc5\x05\xbd\x08\xb3\x08\x4a\x3f\x9f\x7f\xe5\x41\x3e\x01\x20\xec\x3b\x63\x01\x77\x2c\x7a\x0a\x17\x67\x21\xb7\xc7\x21\xd7\xf8\xb0\x93\x07\xc1\x20\xb4\x9d\xdd\xe3\xda\x23\x9b\x99\x9f\x24\xff\x94\x15\x0c\x86\x49\x91\x8f\xc0\xf6\x30\xd8\x53\x72\x56\xfb\xad\x52\x5c\x88\x0c\x7c\x04\x27\x12\x94\xff\xb8\xcf\xab\xcc\x51\x96\xeb\x9f\x6f\xe4\xeb\xf0\x70\x8a\xc2\xee\x66\xe4\xfe\x9d\x31\xe5\x2a\x6d\x00\x4f\x6d\xce\xed\x63\x0a\x43\x30\xf2\xfc\x2a\x97\x9f\x0e\xc8\x5c\x8f\xa0\xb4\x24\x36\xc1\x79\xfc\x96\xc6\x83\xc5\x73\xd6\x05\xb0\xf6\x2b\x58\x07\xc8\x0d\xc9\x11\x28\x8b\x97\x47\x6d\xfb\x4c\x64\x29\x34\x32\x52\xb7\x71\x45\x98\xff\x91\x58\x22\x70\x0e\xa8\xf0\xfc\xd9\x3f\x45\x69\xb8\xa8\x04\xa2\x0f\xec\x12\xd4\x42\xe9\x62\x14\x5f\x00\xa1\x12\x14\xb8\x08\xed\xd5\x20\x6a\xc9\x3f\x14\xad\x06\xc8\x98\x65\x01\x90\x74\x29\x10\x40\x4e\x01\x5f\xde\xc3\x87\x7e\x73\xd3\xa7\x05\x0b\x98\x2a\x8e\xcc\xca\xa8\x67\xeb\xfb\x63\x00\x13\x15\xe0\x0a\x0a\x40\x47\xe4\xff\xf1\x16\xd6\x1f\x5e\xbe\xd2\x1a\x9f\x1d\x5b\xfb\x08\x06\x80\xa0\xe6\xc5\xad\x08\x09\x6b\x2f\xd5\x87\x17\x52\x8c\x09\x1a\x83\x3c\x1e\xd9\xa7\xe4\xa0\x49\x14\xe8\x14\x87\xcc\x71\xb1\x7e\x9e\xea\xaa\x01\xc8\x03\x79\x00\xf5\x37\x47\xa0\x97\xb0\x33\x98\xa5\x28\xe1\x6c\x00\xbe\xf3\x56\x60\xa0\x3b\xfd\xdf\x4d\x1d\x68\x1a\xe1\xfe\x0f\x40\xbb\xf5\x27\x62\x0d\x86\x2c\x80\x9d\xf3\xa4\x2c\xc8\x99\xed\x18\x5e\xe2\x0f\x3c\xfd\x2e\xe5\x89\x8c\x7b\x37\x6e\xd5\x78\x15\x54\xb3\x61\x84\xfe\x18\x5f\xb4\x94\x54\x86\xef\xe0\xa6\x23\xc9\x78\x04\x9d\xe0\x41\x36\x81\xce\xdc\x79\x05\xc4\xf4\x8f\x03\xb5\xad\x3b\x82\x03\xe6\x11\x40\x06\x39\x72\x58\x43\xc2\xdd\xf9\xb0\xc9\x7e\x93\x68\xc2\x9f\x0f\x5d\x16\x7b\xb8\x7d\xb3\x1c\x15\xb0\x8f\x51\x2b\xc0\x54\x73\x8b\x69\x18\x99\x01\x57\x58\xd8\x9f\xda\xee\xce\x20\xa7\x12\xb4\xe5\xc2\xc3\x2d\x51\x0d\xe4\x0e\x03\x74\xd0\xfc\x43\xbd\xaa\xa5\x77\x6e\xe3\x6f\xfa\x24\xe9\x40\x6f\x1a\xcf\x66\xd7\x13\x0a\xf6\xc1\x25\x37\x7c\x79\x96\x63\xd6\x0d\x9b\x1f\x86\xa1\xaf\xee\x6e\xf9\xdc\xf2\xfb\xe6\x51\xef\x9f\xf0\x75\x3c\x6f\x77\xcc\x0f\x7f\xfe\x9e\x1d\x87\x07\xf7\xb7\x01\xf5\xcb\xcf\xe9\x9c\xc3\x3e\xa7\x5b\xde\xc4\x25\xac\x79\x1b\xff\xcc\xfe\xa5\x3f\x83\x36\x84\x13\xb9\xf1\xfe\x83\xea\xd5\xbe\xa9\xf0\x37\x48\x0a\x39\xef\xe0\xc4\x9a\x68\x18\xf0\xbf\x73\xf5\x79\x99\x4a\xcc\x44\xc0\x59\x70\xca\x03\x20\x0e\xfe\x69\x25\x75\x22\x14\x1c\xbe\x68\xd0\x3f\xc4\x5a\x08\x71\x6b\x38\xd8\x3c\xc8\x5e\x00\x2e\x5a\xec\x85\x9d\x9b\xfe\x1c\x03\xbf\x34\x49\x95\x08\x8a\xd6\x9b\x6c\x84\xbd\xfe\xd7\x9c\x13\xba\x29\xa0\xac\x59\xc8\x9d\x32\x6b\x1c\xd0\x11\xf5\x73\x00\xbf\x2a\x24\xaa\xb1\x5c\xe9\x5d\x0f\x5b\xd5\xe4\x5f\x85\x79\xcc\x08\xde\xf2\xe5\xbf\xd9\x0a\xd5\xf3\xd5\xba\xda\x8d\x95\x40\x79\xfe\x4b\x2d\x9a\x0c\x22\x1b\xa1\x84\x25\x44\x21\xbc\xaa\x58\xef\xb2\x96\x9d\x92\x8d\x77\x51\xf7\x45\x1a\x37\x15\x2d\x1b\xbb\xd0\x98\xce\x84\xb7\xe7\xeb\x9c\x81\x28\xf4\x28\x51\x7f\x7a\xe3\x54\xe5\x65\x9d\x8c\xa3\x5f\x5f\x5b\x26\x43\x22\x51\x44\xe3\xc5\x1f\xff\x4b\x8e\xda\xf7\x3a\xfb\x4b\x59\xe8\x6b\x7c\x53\x80\xfa\xd8\xb9\xea\xf6\xaa\x26\x82\x2f\xb9\x9e\xbd\x46\xe8\x4e\x7e\x3c\x7a\x91\x44\x71\x51\xe7\x1f\xeb\xf0\x7b\xd2\xbe\x26\x35\xbe\x4d\x7a\xc2\x5e\xd6\x03\xbf\xdc\x60\xd0\x1b\xdb\xc4\x93\x85\x86\x89\x16\x4d\xc0\xa3\xf0\xcc\xf7\xf7\x1c\x59\x57\xf9\x3d\x55\x15\xb6\xa0\xcf\x44\x49\xa2\xb5\xfb\x5a\x34\x90\x38\xec\x82\x7e\x8b\x8f\xbe\xbf\xd9\x66\xf8\xf9\x21\x41\x6b\xbf\x58\xbf\xf9\x75\x79\x89\xea\xd7\x72\x82\xb7\x64\x76\x7f\xb3\x26\x69\xbf\x99\x7a\x1f\xb6\xe5\x74\xc4\x82\xfd\xd4\x2b\x5e\x7e\x02\x13\x83\xcf\xdc\xaf\x3d\x6a\x36\x29\xa2\xa8\x35\xa5\x9d\x5c\xc8\x9a\x70\xd5\xdf\x24\x98\xc1\xaf\x5b\x34\x29\x18\x42\x60\xc7\x65\xae\xd9\x29\x8c\xff\x16\xef\xbd\x50\xdc\x0d\xd6\x2b\xb4\x26\x79\x95\xc4\xe4\xf0\x08\x37\x00\x77\x6e\x5b\x95\x2f\x66\xfc\xc5\xe8\xb0\xbc\xb9\xb4\x41\x4e\xd8\x90\x69\x1e\xb5\x35\x27\xbd\xff\x25\xae\xc3\xbb\xa8\x7a\x3e\xba\xdd\x60\xaa\x1c\x07\xf4\x70\x92\x64\xe7\x9a\x4d\xec\x7e\x90\x00\xd2\x7c\x39\x52\x8c\xff\xc9\x44\xd1\x42\x31\xb2\xb6\xd6\x5c\x17\x71\xc7\x65\xaf\xba\x9a\x16\x43\x2f\x40\x27\x42\xa7\x95\x78\x0f\x67\x7e\xe3\x62\x77\x00\xdf\xe6\xac\x12\x1d\xfa\xf4\x12\x7d\x65\x75\x60\x41\x25\xd5\xac\xcd\xd5\xb6\x7d\x0b\x09\xc8\xca\x4a\x01\xf5\x23\xc8\x22\x80\xf0\xed\xf1\x4d\x2d\x14\x3a\xf9\xc6\x16\xe0\x3b\x8f\x6c\x76\x74\x6e\x37\xfb\x05\xbe\xa6\xb1\xc0\x0e\x5e\x47\x88\x16\x7b\xdc\xc7\x45\x50\xa3\x1e\x36\x15\x51\xd1\xa5\xd8\xed\x27\xf2\x72\x68\x9b\x44\xb8\xfd\x33\xba\x6f\x2d\x63\xd4\x08\x27\x6a\xb5\xdb\x1d\xbf\x8a\xe9\x70\xad\x40\xaa\x43\xda\x95\x2f\x61\x87\x3b\x65\xcc\x41\x0a\xe1\xbd\x02\xe0\x93\x6f\x6c\x28\x1e\x3d\x98\xa9\xed\x32\x9c\x0e\xc2\x91\xef\x2e\x28\x20\xe4\x45\xc0\x6d\x5b\xcc\x0c\x54\xbf\x29\x09\x27\xce\xc7\x12\x2f\x34\x36\x3b\x6b\xbe\x1b\x08\x00\x80\x85\x70\x9f\xf7\xb3\xdf\x82\x5e\xc3\xb8\x95\x61\xf4\xee\x07\xf6\x9e\x0e\xb7\xe0\x59\xda\x85\x57\x4a\xbd\xab\x49\xee\xc4\xe8\xfc\x39\x32\x40\xc6\x17\xfd\x0a\x07\xcd\xfe\xb0\x6e\x72\x04\x36\x79\x00\x89\xde\xfe\x6e\xcb\x7e\xf8\xb5\xa1\xc6\xed\xaa\x75\x40\xe4\x1c\xe5\x49\x88\xa7\x35\x9a\xd0\xb3\x8c\x31\x69\xc8\xcb\x76\x91\x39\x62\xf9\xe7\x53\x1d\xfa\x90\x59\xf4\xb6\x14\x7d\x1b\x25\x11\x0e\xba\x88\x2f\x7c\xa8\xd9\x61\xae\x13\xfc\x92\x0c\x19\x17\x4e\x9e\x07\x77\xac\x3f\x2a\x59\xa4\x42\x75\x06\xaa\xa1\x3d\xc8\x12\xd1\xc4\x85\x61\x93\xd4\xe8\xc7\x43\xf2\xdd\x8d\xcf\x0a\x7b\xfb\x81\xc3\x24\xa7\x3f\x2f\x9a\x2c\x5a\xa0\xad\x33\x6e\x96\x91\x2f\x83\xcd\xe0\xdb\x60\x67\x80\xdd\x3f\x55\x7d\xef\x22\xb3\x33\x8b\xfc\xb2\x3a\x29\x24\x4c\xd7\xfb\x4d\x5a\xa8\x3d\x08\x5f\xdd\xa8\x22\x68\x5f\xd5\xf6\x7a\xe8\x04\x0f\x25\x7a\x79\x58\x2f\xaf\xf5\xa3\x93\x13\x80\x7a\x37\x7b\xba\x65\xc0\xbb\x91\xd4\x3b\xca\x85\xef\x54\x14\x57\x51\xa2\xdf\x94\x0e\xbb\x4c\xb8\x4e\x37\x75\xe4\xc8\x58\xd4\xd8\x65\xd0\x27\x15\x67\xf2\xf5\x48\x5c\x3a\x05\xda\xf2\xcc\x4b\xb7\x4b\xda\xa5\x2f\xba\xd2\x3d\x98\x51\xec\xd4\xfa\x29\x81\xb2\xe0\x4c\xbc\x1e\x02\x1c\x7e\xa6\x40\x4d\xbb\xbe\x5b\x0f\x85\xf9\x2f\xde\x88\x1b\x94\xf8\x49\x83\x8d\xe2\x1c\x93\x3c\x92\xef\xd7\xa7\x3f\x4f\xe9\x6c\x8b\xb5\x2b\x3f\x3c\x6d\xe4\x14\x5a\xd0\xf0\x76\xec\xd3\xd4\xdf\x96\x18\x3d\x46\x03\xa8\xc3\x7a\xfc\x74\x2e\x76\xff\xc3\x79\xe9\xf3\xb2\xd1\x0d\x5b\xac\xdb\xfa\x42\xd1\xf3\x54\x81\xdc\x66\x91\x61\xca\xf5\x0c\xfb\x7a\x0f\x48\x7d\xd8\x80\xd9\xac\xea\xe2\xbe\xae\x36\x4a\x85\x08\xc2\xe2\x9e\x99\x58\x90\x35\xc5\x7a\xba\x23\x23\x0b\xaf\x1e\xdb\xb7\x85\xb2\xf8\xd9\x9d\xe2\xab\x8a\xc9\xe2\xa1\x3d\x2e\x9f\xa4\x6c\x1d\x8d\x76\xe2\x2f\x89\x38\x91\x90\x07\x61\x46\xf2\x12\x9f\x31\xf9\x78\xc6\x93\xef\x34\x17\x91\x5c\x7a\xad\x84\x3f\x65\x93\xf7\x9c\xc2\xa8\xd4\xa2\xe7\x33\x76\x56\x81\x03\x90\x5b\x8e\x5d\x18\x8b\x27\x38\xa1\x64\xb4\xd8\x44\x28\x54\xc2\xc1\xef\x2c\x97\x4e\xd5\x66\x3c\x2e\xa1\x89\xb5\x36\xc8\x5c\x7a\xb8\x89\x5c\x72\xaf\xc8\x80\xe4\x02\xaa\x1e\xd9\x31\x64\xcf\x40\x14\xa2\xf2\x63\x5a\x2f\x3a\xf8\xa0\xfe\x0c\x99\xc8\xa7\x94\xd1\xa5\x55\xf7\x84\x14\x16\xfb\xda\x27\x3d\xc2\x9e\xb7\xc1\xda\x33\x34\x5c\xa5\x58\xde\x31\x1c\x58\x94\x42\x94\x63\x2d\xf6\x29\x3c\xf9\xf3\x3e\x23\x54\xa8\xd4\xd9\x3f\xd3\x28\xf1\x72\x8c\x8f\x64\x53\x5c\x36\x45\x56\xd0\x4f\x01\x33\xb0\x06\x99\x18\xff\x7c\xec\x29\x0c\xed\xc2\xdd\x8a\xb9\xd6\xb6\x39\x2c\x07\x35\x12\x5d\x46\xf2\x56\x80\xf1\x1e\x53\x55\x99\xce\x6f\x09\xed\x6e\x6c\xd9\x45\x8b\xc5\x17\x18\xb6\x5c\x1c\x44\x41\xdc\x3f\x64\x72\x9c\x01\x1b\x21\xc8\x36\x9f\x7d\x48\xf2\xe4\x93\x7a\x8b\x58\xba\x29\xb2\x81\x8d\xf8\xe1\x4c\x18\xef\x22\x82\x81\x82\x75\x46\x97\x92\xca\xe0\x4a\xf0\x4f\xb5\x67\x41\x9f\xb5\x4d\x92\x35\xe7\xd5\xb2\x71\xef\x20\x91\x1b\x11\x7b\x9c\x2f\x5e\xcc\xfe\xf8\x3f\x34\x19\x65\xd0\x58\x75\x72\x59\x43\x18\xcb\x9e\xfb\xf8\xad\x15\x8f\xd4\xd4\x25\x38\xb2\x34\xd3\x8f\xba\xee\x69\x83\x81\xee\x79\x8b\x82\xd4\x32\x7f\x55\x85\xb2\x9b\x29\xef\x8c\x86\x6b\xe7\x0d\x91\x67\x39\x0e\xba\xb2\xba\x57\x41\xed\x85\x9d\x5a\xb3\x7c\x1f\x52\x68\xd8\xd3\xf3\xe2\x00\xeb\x10\x98\x45\xf7\xab\xf6\x4a\x51\xee\x2f\x98\x67\x91\x3e\xf4\xb4\xfb\xd5\xcf\x96\xab\x60\xbe\xaf\x1d\x84\x36\xb3\xc7\x11\x9c\x98\x47\xe5\xd7\xb8\xfa\xf5\xb9\xba\x26\x16\x6f\x67\xb6\x82\xa8\x60\x63\x04\x59\x13\xd0\xb0\xcd\x9d\xb8\x0f\xe7\x53\x87\x56\xac\x6d\x27\x8e\x5c\x77\x2a\x61\xee\x4e\x97\xf6\x7d\x04\x1d\x67\x51\x5a\x82\xaf\xe7\x3a\x6d\x17\x5d\x55\xb7\x91\x5c\xea\xea\xeb\x24\xe5\x8c\x5c\x1d\xec\xb6\xf4\x69\x42\x8d\xc5\xa9\x3a\x73\x65\xe5\x04\x13\xba\x2b\x95\xd8\xe3\x44\x00\xba\x8f\x76\xb0\x0e\xb8\xc2\x3a\xa2\x2b\x35\x37\xee\x28\x43\xcb\x63\x96\x9f\x83\xb3\xb5\xae\x78\x39\xdd\x59\x3c\x55\xd8\xa4\x2b\x1a\xbd\xbb\xd2\xb7\x44\x8d\x79\xa3\x75\x19\xd3\x38\xa6\xad\xa9\x3f\x63\x7f\x2a\x9d\xf9\x43\x32\xc6\xf8\x56\x41\x1c\x12\xf0\x62\xf4\xec\xb0\xfa\x4a\x9b\x1a\xff\x91\x80\x87\xf1\x5c\x66\x3c\x8d\xaf\xba\x3f\x6c\x65\xea\x8e\x01\xce\xe2\x49\x31\x58\xb6\xc1\x0e\x1a\xea\x21\x79\x89\xe2\x8e\xcb\xc2\xfb\xf2\x67\x30\x79\x76\xad\x63\x82\x35\xf4\xd6\x04\x40\x85\x95\xb7\xce\x96\xb6\xc6\x36\x2a\x6b\x38\x04\x21\x28\x58\x42\xe8\xd8\xea\x17\x85\x82\xfb\xf8\x2b\xfa\x92\xab\xc7\x93\x94\x62\x33\x83\xa2\xaf\x6c\xe3\x78\x67\x07\x55\x12\x10\x11\xc0\x08\xf8\xe7\xa0\x07\x29\x6b\xcd\xca\x3a\xe5\x50\x98\x11\x8c\xe2\x9f\x4a\x36\x3e\x38\x39\xce\x89\x48\xa2\x0f\xb9\x1e\x2d\xa3\xfc\x96\x11\x7e\x97\xa1\x59\x59\x19\x46\x2e\xc2\xc7\xfd\xf0\x10\x64\x04\xd9\xdf\x2d\xc4\xda\xb1\xce\x52\xd1\x77\xde\x8a\x9c\xa6\x23\xec\xb0\x4a\xcd\xf7\x89\x5b\x5f\x7f\x2b\x3c\xd1\xa7\xb8\x5e\xe1\xf5\xf8\x08\x3e\x91\xee\x08\xd7\x97\xe7\x39\xda\xaf\xb2\x52\x7e\x1f\x61\xec\x2c\x5d\x5c\x9d\x76\x74\x90\xb8\xef\x4f\x92\xff\x4f\x9f\x4e\xcc\xa0\x73\x1d\xaa\xfe\x7c\xde\xc9\x4d\xf3\x2e\xc9\xbf\x26\x81\xe0\xc1\x20\xe6\x53\xe4\xff\x04\xb2\x1f\x2b\x25\x51\xac\x6d\xcf\xf6\x8c\xce\x08\x3c\x9f\x4d\x69\x4c\xbb\x5d\x50\xef\xa9\x7d\x60\x8b\x95\xe0\x89\xaf\x94\x4f\x17\x7c\x1f\x02\x4e\x3d\x20\x81\x00\x48\xd3\xd0\x5b\xdf\xfc\x2f\x6c\x51\x3f\x10\xbb\x07\xc8\x7a\x9d\x11\x62\x7d\x0a\x7a\xac\x08\x25\xc0\x6d\xcf\x7f\x9d\x2f\xb8\xba\xbd\xe8\x43\x91\x0e\xfb\x2a\xe7\x21\xca\xc9\x3b\xfe\x30\x30\x85\xae\x6f\xd2\x10\x9e\x9e\xe9\xf6\x37\x68\xcb\x66\xd3\xe4\x20\xa5\x6c\x6b\x65\x1a\x6d\xdd\x2d\x1e\xbf\xee\x84\x56\x81\x1f\x74\x4e\x81\xf2\x45\x0b\xeb\xbd\xc1\xc8\x81\x26\x7e\x0c\x8b\xd2\xc1\xbf\x09\x43\x10\xf2\xaa\xab\xb2\x6d\x30\xa7\xca\xf2\xb4\xd1\x34\xb8\x47\x0e\x65\x4a\x15\xcc\x88\x3d\x5e\xe2\x00\xdb\xa7\x4c\xf5\x84\x97\x6e\xfc\x3e\x86\xad\x20\x0f\x75\x63\x0c\x69\x4e\xf1\xd9\x6f\x4a\x4f\x58\x47\x23\x1e\xa7\x4a\xfc\x19\x45\x5c\xb2\xc8\xb2\x4d\xc5\x28\x48\x4b\xbc\x7e\x2e\x9d\xce\x2f\x24\xf1\xd5\xd2\x83\xd3\x3a\x8a\x87\x41\x33\x86\xf2\xba\xcb\xd9\xeb\x7d\x20\x8b\x54\xfd\xfa\x29\x6d\x95\xee\x53\xa9\x56\x36\xb2\x6a\x86\xd6\x42\x58\x84\x5f\x3d\xc1\xca\x81\xe2\xf2\x53\xda\x83\xe3\x03\x66\xef\xb0\x55\x11\x5d\xdf\xa1\x8a\xb9\xed\xf9\x9f\x6f\xb0\x98\x4e\xb6\x0d\x96\x38\xef\x64\x98\xfa\xf6\x36\xa8\x5e\xdf\x0d\xb5\x6c\xde\x8f\x64\xcf\x05\xf8\x91\x68\xfa\x30\x42\xbd\x7b\x8e\x56\xa0\x19\xe9\xb7\x1e\x9c\x20\x2c\x41\x18\x6b\x61\x8d\x2b\xc2\x56\xba\xf7\x76\x7f\x4a\xa3\x7f\x48\x7f\xdc\x9c\x6f\xf4\x95\xda\x47\xbe\x50\x12\xea\xb1\xfd\xca\xeb\x30\x58\x96\x10\xca\xc7\x83\x38\x53\xa7\xc6\x5a\x2f\xea\x74\xb7\x44\xce\x58\x5f\xb7\xab\xb3\x27\x0b\x4b\x21\x54\x0c\x07\xe6\x22\xd6\x40\x67\xc9\x3f\xdf\xe2\x66\xfb\xe2\x01\xbd\xb3\x57\xf7\x5a\xcc\x35\x71\x77\xf8\xfc\xb4\x05\xd7\xba\xf4\xa7\x7e\x48\xe2\xd3\x04\xf8\x00\xa1\x48\xe4\x26\x9b\xe3\x8b\x62\x24\x0e\x19\xbc\x53\xb3\x98\x48\x6b\x98\x3b\xa4\xb5\xea\xe4\x73\x08\xb1\x6d\xb0\x8a\xde\xa9\xda\x5c\x48\x7a\x3f\x4e\x60\x49\x5d\xa8\xf9\x7b\x99\x5e\xf1\x34\xc9\x0f\x0c\x58\x99\x26\x60\x0c\xd6\x88\x99\x80\x85\x3a\xb4\xc1\x8f\xd0\x5c\x55\x04\x16\x7c\x24\xb2\x90\x0e\x67\x74\x3b\x1f\x91\x0d\xce\xf4\xf7\x07\xa9\x4a\x3a\x1a\xf3\x6d\x51\x55\x40\x2e\x24\x31\x89\xa4\x9c\x13\x62\x35\xce\x00\x3a\x5f\x09\x42\x90\x1e\x8e\x00\xec\x78\xd4\x89\x0c\xe4\x3a\xfc\x22\x2f\x49\x79\xbf\x34\x9c\x96\x36\x5b\xc0\x73\x1a\x49\xdf\x36\x40\x3e\x51\xb1\xa7\x01\x2e\x2f\x08\x4e\x89\xea\x59\x4e\x2d\xe0\xf6\x55\x5f\x12\x67\xad\xd9\xbe\xec\xba\xd0\xe0\xde\x72\x31\x31\x74\xc9\x70\xdd\xc1\x4d\x61\x51\xba\x81\xf1\x74\xcf\xa8\xe8\xa8\x22\x4f\xa7\xa6\x2c\x8d\x98\x56\xbc\x07\xa1\x29\xce\xad\x5d\x01\xbf\x6c\xd3\x29\xd9\x95\x06\x0f\x79\x58\xd0\x36\x53\x55\x6e\x43\x38\xdf\x61\xb7\xc7\x02\xb6\xb7\x86\xb0\x22\x85\x36\xd9\x1f\xaf\xed\x34\x8a\xa5\x6d\x13\x4b\x9e\xa2\x3d\xf2\x07\x0f\xb2\x81\x98\x77\x43\xe3\xe5\x7b\x7e\xf3\x28\x83\x81\x91\x76\xb5\x2d\x63\x24\x0c\x2d\x0f\xe5\x2f\x3c\xfe\x92\xa2\x35\xf6\xf2\xb1\x6a\x50\x05\x7b\x38\x71\xca\xd1\x9c\xbe\x2f\x6f\x3d\xdc\xc4\xc4\x9e\xda\x50\x9f\xe7\x7e\x12\xa9\xd4\x70\x6a\x4f\xf3\x25\x21\x65\x71\xe8\x28\x35\xd4\x47\xf5\xef\x12\x7d\x4a\xef\x0a\x2b\xe7\x26\x7d\xfc\x8c\x1c\xb4\xc0\x1d\x47\x5d\x27\x45\xac\x39\x69\x63\x19\x43\x58\x23\x58\xd8\x84\xed\x44\x83\x65\xc3\x2e\x58\x56\xbc\x46\x69\x6b\x94\xf1\x38\xb7\xaa\xd5\x33\x0b\xdb\x38\x79\x41\xdb\xdb\x65\x3a\x30\x56\x26\x5c\xea\x07\x2e\x4e\xe2\x69\x0a\x6f\x74\xc4\x00\x85\xbf\x14\x77\x1b\xd7\xcb\xd2\xe5\xb5\xb0\xf4\xf1\xdb\x05\x65\x4c\x4c\xbd\xe8\x19\xd0\xde\xbc\xaa\xc3\x21\xcf\x24\xcb\x78\x4c\x4a\xcc\x01\x8f\xed\x4b\x91\x1c\xaa\x2c\x19\xcf\xdc\x0e\x48\x30\x5b\x1e\x18\xcc\x9b\xfd\x9a\xf9\x83\x7a\x8f\x65\xf7\xc0\x10\xf2\x93\x58\xe6\xd7\xb6\xda\x11\x60\xb2\xa7\x6f\x0d\x32\x2c\x16\xcc\xda\xea\x50\x9e\xb6\xcd\xa9\x37\xdb\x4c\x5d\x65\x12\x7f\xb6\xd9\x99\x94\x0f\x39\x13\x90\xd6\x05\x3c\x7c\xf0\xc1\xa2\x11\xa7\x81\x19\xd0\x22\x0d\xfe\x95\xf7\x3e\x6a\x58\xd9\xd1\x79\x8f\x70\x2d\xf8\xab\x64\xad\x11\x78\x56\xbe\x15\x12\x8a\x30\x9c\x8e\xd7\xac\xbf\x66\xa6\x05\x62\x2a\x19\x5b\xa1\x5c\xe2\xe2\x66\x62\xdd\x26\x2c\x13\x0f\x22\x8d\x2d\xe1\x62\x6d\xd3\xb8\xb3\xea\x64\xa5\x19\x4b\x3f\xa2\x5e\xe5\xe9\xe4\xa7\x4e\x10\x64\xb1\xab\xe6\x1f\x32\x35\x80\xc0\x93\xc7\xf5\x9b\xc4\xc2\x92\x1a\x3a\x59\x58\x1e\xf0\xe0\x2a\x74\x6f\xf7\x4a\x75\x6e\x90\x95\x42\x5f\x3d\xb3\x53\x75\x82\x4f\x3d\x0a\x7e\x91\x86\x90\x84\xa5\x18\x20\x2a\xcf\xce\x3d\x9a\xe9\xff\x82\x18\x68\x16\x92\xa8\x2a\xb3\xea\x9c\xef\x5f\xab\xe5\x3c\x25\xd2\x09\xb4\x27\x81\x33\x2c\xf6\x42\x03\x2f\x3e\x39\x58\x7e\x6a\x8d\xd8\xea\xa9\xf1\x6e\x86\x91\xdf\x4b\xcd\x82\x42\x7e\xd0\xb4\x9c\xe4\xa1\x2b\x87\x27\x44\xd7\x39\x39\xcc\x81\x46\x09\xce\xcd\x9a\xca\xe1\x00\x99\xbf\xcc\x15\xc7\xbf\xbc\xfd\x9d\xae\xa1\xf6\x97\x56\xa8\xf8\x3a\x41\x8b\xbe\xb7\x7f\xf0\x11\x60\x81\xe2\x3a\xfb\xb2\x4f\xa0\x6c\xa0\x51\xce\xe2\x9b\x0d\x90\xd7\x8b\x45\xd6\x2b\x7b\x19\xcd\x39\x5b\xdc\xda\x38\xc3\x15\x5d\xb0\xb7\xf0\x9d\x17\xdd\x1a\xae\x1f\x08\xdf\xbb\xfb\xc1\xcf\xbc\x03\x23\x68\x3b\xbd\xfd\xa0\x31\x83\x3c\x0e\xb6\x4a\x78\x76\xd6\xd6\x8f\x1b\x24\xd8\x7c\x56\x6f\x80\xfe\x15\xf9\x54\x45\x2a\x48\x1f\xef\xe6\x49\xec\x9a\x9e\xbc\xeb\x2c\xb2\x0f\x79\x79\xc4\x8f\xf5\xeb\xcf\x20\xf7\xf4\xe6\xfe\x60\x0d\x46\x93\xcc\x8f\x32\xf3\x4f\xac\x6c\xc3\xdb\xc1\x09\xb8\x72\x7a\xe8\x7b\xbe\x1c\x7e\x88\x16\xe1\xc6\xce\x74\xb8\xfc\x0c\xae\xdd\xfc\x20\x1f\x4c\x9d\xe1\x67\x08\x32\xd8\xc1\xcd\x96\x55\x78\xff\x78\x4d\xdc\x5f\x94\x85\xfb\x87\xca\x6b\xb0\xe7\x89\x62\xdf\x27\xf3\x8f\x72\x40\x45\x48\xfb\x5b\xab\x17\x65\xeb\xad\xbc\xc9\xf9\x5e\xa3\xbc\x20\x0e\xeb\x5c\xe5\x90\x53\x4d\x43\x3f\xc9\x87\xb8\x8f\xbc\x65\x91\x57\xe7\x4a\xf7\x9a\x14\x50\x14\xf4\x93\xc4\x89\x02\x0b\xd5\x57\x70\xf8\x0d\x2d\xb4\x79\x67\x0f\xe5\xfe\xfd\xde\xae\x97\xdd\xc7\xbe\x28\x0d\x66\x18\xb7\x07\x2f\xde\x9b\x3a\x0f\xb6\xe9\xb9\x7f\x82\x75\x12\x79\x58\x60\x2b\x79\x50\x1d\xd8\xde\xa3\x43\x9e\xff\x82\x17\xb6\xb7\x41\x2d\x63\xc5\x08\x5b\xdf\x94\x38\x6f\x71\xc7\x54\x71\x79\xe7\x8f\x7f\x8c\xfb\xae\x71\xc7\x76\x04\x9f\x8c\xda\x56\x6f\xcb\x6a\x8f\x14\xc6\xe0\x6f\x8d\x0f\xef\x7b\x58\x72\xaa\x58\xf7\x10\x4f\x8c\x42\xb3\x6f\x8c\x37\x2d\x91\xd3\x6f\x5c\x34\xbd\x19\x05\x62\x79\x66\xa4\xea\x0d\xe1\x49\x98\x53\xaf\xe8\x7c\x66\x37\x34\xcb\x29\x27\x8b\xa5\xc0\x58\x47\xb7\x72\xa2\x17\x74\xda\x55\xa0\x34\x2d\xd1\xcd\xa2\x94\x7d\x6a\xe9\x17\x66\x17\xb9\x72\xb8\x58\x8b\x53\x38\x6b\xa7\x74\xbb\x49\x0b\xa3\x29\x03\x5f\x28\xa1\x73\x0e\xf0\x93\x8b\x12\x80\x55\x66\x3f\xc4\x3b\xf6\x4a\x73\xe5\x9b\x72\x36\xdd\x62\xa2\xe7\x42\x5f\xdc\xb0\xf5\x02\x34\x78\xf7\x12\x20\xdf\xee\x32\x26\xef\x78\x73\xe7\x82\x42\xb2\xd7\xb0\x46\x4f\x55\x1d\xb6\xa9\xd5\x10\x67\xd3\xc0\x9a\xc0\xff\xf6\x17\x96\x3c\x58\x13\x3d\xae\x2d\xc8\x5f\xd7\xca\xf1\xe1\xb8\xb8\x86\x71\x5c\xa0\x53\x23\xf8\x14\x09\x57\x42\x91\xd6\x5f\x3a\x49\x0f\x06\x2f\xad\xa3\x3e\xf7\x81\x6c\x5f\x9d\xe8\x71\x36\x90\xce\x84\x34\x0c\x5a\xbb\x8d\x08\x83\xbe\x0e\x4a\x61\xc9\xcb\x32\x16\xca\xd1\xe2\x64\x81\xe5\xd8\x48\x29\x3f\x20\x86\xbe\xb2\x23\x82\x63\x81\xf6\xf5\x50\xf9\xc9\x94\xe0\x85\xd3\xe3\x14\x07\x40\x64\x98\xb4\x36\x7a\x37\x29\x7c\x45\xd4\x08\x66\xe7\x27\x8e\xc5\xe7\x30\xcf\x40\x42\x78\x44\x24\x64\xaf\xff\xee\xa2\x92\x61\xe6\x1c\xa6\x1b\x80\xa4\x85\x19\x08\x5a\xad\x34\x5c\xac\x01\x3a\x13\xfb\xaa\x03\x55\x42\x59\x6d\x2c\xc2\x13\x1e\xf0\x6e\x03\x7a\x9f\x24\x38\x2e\xa5\x1c\xf8\x25\x3c\xf0\x89\x2a\xff\x12\xac\x14\x3b\xee\xf9\x40\xf5\x75\xe3\x4a\xdb\x31\xd6\x75\xf8\x63\x20\x49\x0c\x4b\xa1\xbc\x98\x43\xb1\x99\x44\x65\xdd\xd9\x24\x49\x14\x38\x4c\x24\xb6\x53\xb1\x4f\x3c\x74\x7c\x16\xf3\x6c\x48\x9f\xa0\xd8\x61\x7e\xc5\x80\xb4\xb6\x7f\x87\x2c\x45\x0f\xd7\x25\x2e\x32\xc0\x39\x5c\xb8\xdc\x03\x39\x93\xf2\xfd\x79\x76\x60\xf2\x91\xfe\x8d\x7e\x2b\xf2\x0e\x12\x10\xe6\x70\x64\xa4\x07\x50\x1e\xe1\x4b\xad\xac\xa6\x31\xad\xbb\x90\xef\xf1\x96\xf9\x49\x2f\x12\x4b\xf7\x6b\x71\x9b\x25\xef\x08\x6c\xfe\x06\x3b\xa2\x28\x11\xed\xd6\x4b\xb7\xf4\xe9\xc8\xf9\x70\xf1\x95\x9d\xad\x4e\x94\xb8\x54\x1d\x31\xd0\x25\x8f\xde\x49\x5a\xc8\xb3\xdc\x4f\x7e\x28\x90\xa0\x4b\xa1\x67\x01\x62\x77\xc8\x13\x31\xcb\x9e\x93\x54\xe9\x1e\xa4\xbe\xf1\xab\xed\xc6\x2d\x15\x5f\xbd\x9f\xf6\xbc\x93\x33\xe1\x72\x17\xad\xec\x39\x8e\x91\x18\x62\x71\xd9\x3a\x86\x5e\xe8\x90\xff\x07\xa5\x92\xf5\xf1\xb1\x6e\x6d\x51\x82\x7a\x0e\x26\xa4\xfb\x71\x62\x6d\x96\x1d\x31\x7c\x3d\x44\xc7\xb2\x87\xaa\x11\x35\xec\x14\xde\x0d\x8b\xc0\xef\xca\x89\xb3\x2b\x72\xd3\x8e\xdc\xb2\xb2\xaf\x26\x0f\xce\xda\xfc\x8a\xb1\x6a\x2d\xbe\x1f\x60\x40\xea\x8a\x2d\x96\xb3\x47\x08\x65\x40\x60\xa6\xce\xa7\x48\x7d\xd3\x79\x39\xa4\x97\x51\xfb\x22\x63\xb0\x92\xea\x72\x9a\xc9\xc0\x50\xab\x93\xf7\x9d\xc7\xcf\x24\x22\x9e\x18\x3e\xa0\xb3\xc9\x5a\x03\x33\x41\x89\xca\x02\x76\xa3\x7d\xad\x32\x0d\xeb\xd6\x09\x13\xdd\xbf\x64\xfe\x11\x47\xc1\xdc\x19\x6b\x22\x8b\xb9\x49\x88\x76\xc3\x8b\x60\x65\xe0\x9a\x8c\xb2\x92\x26\x65\x4d\x87\x97\xc3\x17\xcd\xb9\xbf\x04\xb8\xc0\x42\x71\x4e\x5c\xb3\x81\x7c\xc9\xd5\x95\x2d\x44\x87\xcb\xb9\x6b\x64\xe7\xe2\xea\x6d\x12\x6b\x01\xb1\xcd\x7e\x89\x35\x3c\x32\xd6\x24\x62\xdb\x32\x8a\x02\x0e\xbb\x11\x7d\x89\x8b\x80\x8f\xfd\x72\x88\xdc\x76\x0c\x36\xdc\x2c\x8c\x49\xf9\x43\x8a\xbb\x82\xea\xe2\x0d\x4b\x34\xf7\x44\x74\xeb\x1e\xea\x05\x3b\x16\x62\x15\x90\xae\xc4\x86\xdd\xd7\x72\x3b\x91\x12\x37\x8c\x46\x8e\xa0\xc3\x6d\xaf\xa0\x06\xec\xcb\x18\xba\x94\x58\xc5\xaf\x3b\x03\x6f\x01\x86\x9c\xd8\x79\xe0\xca\x91\x0d\xb7\x78\xc7\x17\xc7\x66\xbd\xcc\xb5\x64\x70\xe6\xfc\x01\x43\x2e\xae\x43\xa6\x4c\xcc\xfc\x3e\x55\xdf\xa0\xbd\xde\x5c\x0e\x51\x8f\xc8\x1e\x46\x3d\x00\x53\x02\x34\x04\x51\xf5\x3e\xf1\x86\x7e\xd2\xd7\x38\xb1\xe4\x60\x53\xaf\x29\xb3\xae\xbf\xbf\x12\xe9\x6e\x47\xa6\xff\x0a\x92\x94\xb1\x12\xe3\x7c\x5b\x25\xe7\xdc\x1a\x56\x77\x81\xdd\x01\xc1\x94\xeb\xf2\x4b\x80\xbc\xdd\x9d\x28\x11\x80\xd8\xb6\x47\xe0\xdb\xf2\xf9\xa2\x89\x0e\xe5\x08\x3a\x9b\xdd\xb5\xaf\x80\x4a\x81\xce\x16\x73\x1d\x87\x2d\xf0\x4c\x44\x6c\x8b\xb7\xae\xf1\xd6\x1c\x01\xff\x14\x4a\x99\x32\xda\xe2\xf3\xad\x5b\x86\x3a\x8d\xc7\xc0\x7c\x6f\xfa\x70\x51\x0d\xad\x77\x0f\xa6\xdb\x60\x19\x55\x97\x46\x86\xdb\x2a\x0e\x9d\x5e\x0a\xad\xf3\x7d\x08\xc8\x1b\x28\x74\xd9\x49\x99\x59\x5c\xbf\x40\x89\xc1\x8b\xa5\xe3\x63\x0e\xb3\xd0\x99\x81\x38\x74\xc0\x2c\x88\x56\x96\x81\x06\x24\xc5\x66\x47\xbd\x63\x69\x2b\xcf\x2e\x4c\x8c\xc0\xb3\xd3\x8f\x8b\x65\x6c\xfe\x9d\xf9\x8b\x64\xb4\x67\xfb\x02\xf6\x85\xa0\xe6\xab\xef\xc8\x29\xb2\xbd\x3d\x57\x72\x5b\x4e\x03\xd0\x8f\x0c\x1d\x30\x82\x90\xcc\xbb\x8e\xe1\xa4\xb1\x17\xc4\x3b\x6e\xf8\x94\xb7\x65\xd3\xb2\x1b\x43\x0f\xec\x37\x24\x20\xcf\xc2\xa5\xfc\x31\x98\xa5\xa6\x6f\xe1\xe4\xd5\x1e\x00\x83\x1d\x80\x81\xc0\xeb\xac\xbc\x7a\x61\xce\xe7\x34\xbc\x4a\xbf\x9b\xe4\x33\xd5\xba\x1d\x8c\xa2\xca\xc7\xbb\x58\xed\xb6\xc0\xe6\x67\xf2\x8e\x4a\x5c\x34\xc3\xf2\x59\x3c\x5d\x29\x5c\x12\xf6\xaa\xa9\x84\x08\xbd\x77\x18\xc7\xa4\xe9\x13\xc4\xbc\xb9\x24\x6d\x7d\x33\x9d\x37\x61\xce\x5a\xc1\xe5\xa5\x25\xd6\x0e\xa9\x1c\xfd\x01\xa9\x17\x5d\xf7\xc7\x6e\x30\xa7\x26\x05\x9e\x71\xdb\xdf\xab\x23\x7d\x36\xc8\x07\xe6\x87\x8c\x67\xc8\x8d\xb2\x9b\x8a\xa4\x2a\xeb\xa1\xfc\x60\x08\x80\x91\xa9\x07\x79\xdf\x37\xf7\xe1\x87\x68\x49\xf7\x67\xfb\x39\xf2\x73\x62\x3d\xb3\xca\x33\xa1\xb2\xb9\xa8\x72\xb1\x69\x69\x73\x73\xd9\xda\x00\x32\xe3\xb2\x7c\xa8\x15\xba\x0d\x17\x67\x35\xdb\x90\x6d\x2f\x19\xfd\xf0\xad\x19\x0f\x11\xed\xea\xdc\xdb\xc3\x93\x6b\x95\x63\x7d\xf1\x75\x53\xfb\x64\x93\x44\x66\x1f\x5f\x3f\xc0\x59\x22\x2d\xcd\xae\xb5\x82\x91\xe2\x39\x95\xda\xc7\x0f\xaf\xba\x3e\x7a\x4d\x7c\x40\x19\xdf\x38\x97\x2f\x33\xe4\xd5\xca\xd6\xa5\x37\x61\x2a\x03\xba\xce\x17\x8f\xaf\xd2\xe8\xc2\xd3\x7e\x73\x75\xcd\x5d\x21\xd9\x58\x5b\x5d\xf8\x03\xb7\x75\xe6\x2e\x87\x73\xf3\x84\x26\x18\xd6\xea\x33\x5f\x63\xc8\x64\x6d\xf9\xf7\xb4\x67\xe6\xb6\xa8\x51\xb3\x92\x03\x5d\x94\x5f\xaf\xb1\x75\x7b\xe2\x58\x6f\xc9\xef\xf3\x05\xc8\x8e\xd4\x67\x50\xff\xc6\x6f\xfd\x51\x67\xee\x71\xb8\xb4\xb0\xca\x5e\x90\xbb\x17\xab\x4b\x20\xbc\xae\xa1\x2a\xb2\xe5\xa6\x54\xc6\x21\xca\xec\x73\x98\x02\xa5\x60\xf7\xe9\x57\xce\x52\xaf\xc4\x58\xae\x07\xcf\xc2\xdb\xdd\x72\x03\x56\xaf\x3a\xe4\xd0\x10\x29\xf9\x5c\x6f\xf3\x85\x09\xbe\x62\xc3\x2f\x39\x86\x58\xde\xe4\xdb\xd6\xa0\x57\x2a\x21\xda\xa0\x48\xc8\xa3\xa1\x37\xec\x41\x37\xd6\x4b\x83\x98\x9f\x80\x19\x7a\x96\x8f\x4e\xa9\xf5\x34\x58\x0a\xf2\xb1\xf0\x88\xbf\x93\xcf\x56\x90\xdc\x07\x15\x0d\x3b\xc4\xbd\x87\x7c\x1f\x84\xdc\x19\xda\xd3\xf2\xaa\x91\x07\xc9\x46\xad\xd2\xd1\xa5\xc7\x61\x8a\x81\x98\x53\x93\x34\xa3\xcb\x9f\xb9\x91\x64\x30\xeb\x07\x61\x5b\xea\x64\x0e\x79\xf5\xa8\x06\xb9\x9e\xd2\x57\xb0\x80\xbc\xa6\x93\xd8\xeb\x15\x69\xeb\x10\x39\xe4\x7a\xc6\xc4\x9d\x3c\xc2\x07\x49\x84\xf4\xfe\x91\x93\x0d\x6b\x96\xb4\xf7\x91\x14\x87\x5f\x51\xee\xe1\x59\xc1\x9d\xaa\x85\x9b\x62\x10\xf0\xca\xde\x8e\x90\x40\x61\x23\x5c\x79\x2a\x65\x70\xcd\x41\xa7\x10\xad\x50\x61\x5f\xb1\xad\x20\x0c\x86\xfd\x0c\x98\x84\x98\xed\x2f\xdf\x6c\xc2\xaf\x03\x9b\x74\xe3\x13\x7c\x32\x18\xdf\x33\x56\x82\x1c\xfa\x83\x43\xe7\x9a\xa1\x76\x13\xe9\x37\x9a\x42\x4f\x03\xdc\xa4\x49\xbd\xd3\x49\xb6\x77\xde\xef\x38\x05\xbc\x01\x64\x43\x17\xd3\x5b\x9d\x20\xeb\xd2\x4f\xda\x2f\x61\xa8\xd5\xd1\x00\x1b\xa3\xec\x57\x45\x7f\x20\xb2\xa3\x36\x48\xe8\x6b\xf9\xe8\xf1\xb6\xe9\xe9\xa9\x2d\xcf\x11\x10\x94\x95\xc1\x58\xbf\xb7\xec\xe2\x10\x6e\x36\x8f\xa7\x61\xb6\xc7\xaf\x34\x15\x1e\x50\x26\x29\x6c\xac\x65\x3a\xa0\xb0\x11\x0e\x41\xae\x26\x2b\xce\x23\x4d\x23\xd7\xe9\x14\x00\x16\xc4\xc3\x39\x5e\x9d\xaa\x4c\xe1\xca\xc1\x6c\x85\xe0\xb6\x1c\x8a\x6c\x02\x86\x94\xf4\x41\xf2\x61\x9d\x85\xae\xce\x3b\xf8\x89\xb0\x29\x97\x42\xfb\xc9\xc4\x9d\x04\x13\xb1\x9d\x70\xfb\xf8\x4b\x61\xca\x34\x2e\x6b\x85\xcc\x5b\xe3\x15\x7b\x5f\xdc\x4e\x3d\x7e\x41\xde\x85\x63\xbf\xbf\x64\x89\xf4\x7c\x06\x47\xf1\xeb\x67\x1f\xdb\x96\xea\x37\xc1\x54\xbc\x18\x43\x74\xe7\x41\xfe\x21\x8d\x80\x64\x5c\x2f\x83\x1f\x94\xb1\xf4\x3a\xb4\xf0\x17\x86\xcf\x93\x93\xed\x35\x6b\x4f\xf8\x05\x65\x7a\x25\x31\xe6\xf2\x80\x8d\x02\xaf\xd8\x8a\x74\xf8\x0e\x4a\x22\x54\x7b\x38\xf5\x80\x8c\xe7\x12\x64\xc4\xa8\x4b\x63\xbd\xb1\x3a\x0d\x61\x21\x62\x0c\x47\x4a\x60\x79\xf0\xcb\xb7\x11\xa7\xd0\x27\x41\x8b\x7a\xfd\x1e\x01\x76\xaf\x2b\x00\x8d\xb8\x32\xd5\xb7\xc4\xe7\xae\xa3\x78\x8d\x2b\x7b\x14\x8f\xed\xa2\xc3\x28\x9c\x67\xa6\x5b\x35\xa5\x91\x3d\x6c\xf9\x47\x1b\xa3\x8f\x68\x75\x0e\x94\x90\xf1\x88\xc7\xf6\xc3\xbf\x1e\xb7\xcf\x51\x65\x2b\x6e\x27\x69\x7c\x16\x4e\x95\x26\xfd\x6d\x81\xf4\x08\x56\x63\xb0\x18\xcf\x03\xc9\x00\x7b\x71\xf7\x3e\xca\xf2\x3e\xea\x8a\x3d\x54\x57\xc4\xdc\x86\x9d\x71\xf1\x4c\x74\xa4\x52\x77\xb0\x17\xf5\x65\x9b\x2f\xbb\x87\x83\xd1\xa6\xba\x82\xcd\xca\x05\x9f\x06\x6f\x31\xae\x39\xe2\x25\x8c\x34\xb1\x18\x79\xa3\xf8\x9d\xbb\x48\xf2\xe2\x7c\xae\x9f\x44\x53\xa5\x60\xb3\xdb\xd9\x5f\x5d\x21\xcb\xc9\x9e\xbe\x44\xab\xa7\x21\xd1\x67\xbb\x20\x73\x0e\xfa\xe5\x93\x7e\xa8\xa5\xf3\xc9\x15\xc8\xcb\xdb\x16\x93\x66\x52\x99\x17\x71\x1b\xd1\xc5\x84\xbd\x12\x66\x9a\x41\x1f\x84\x0d\x53\x1f\x64\x9e\x92\xa8\xd7\x51\x7e\xb0\x52\xa1\xc4\xb9\xfc\xf4\x3e\x7c\x2d\x97\xe8\x24\xcb\x79\xd3\xdc\x96\x33\x9c\x96\xce\x5e\x5c\x47\xb7\x02\xd5\x4d\x84\x6c\x91\xb3\x64\x8b\x5a\x4f\xcd\x97\x52\xfc\x96\x5d\x00\x51\x09\x8f\x19\x6b\x60\x62\xaf\xd1\x65\x29\x5f\x35\x22\x6b\x00\xac\xe2\x51\x66\xd1\x7b\xe1\xec\x72\x01\x55\xa7\x7b\x90\x55\x29\xb7\xa3\xb1\x97\x62\x2a\x22\x1d\x8d\x62\x5e\xe2\xe9\xe4\x8f\x8d\x66\x64\x62\xda\x05\x09\x1c\x15\x44\xfc\x79\x68\x1e\x7c\x8d\x64\x71\xbc\x84\x8f\xde\x4b\x46\xdd\x84\xf3\x5a\x30\x29\xfb\x6a\xb9\xb4\x77\xe9\x7f\x1e\x6c\x10\x82\xf3\xc8\xfa\x39\xcf\x1d\x97\x9f\xe5\xc7\xf9\x7d\x97\x5d\xe9\x94\x3d\x4a\xcb\xec\x97\x71\x3e\xc9\xf8\x9f\xcf\xd3\xfe\xf7\x00\xce\xf5\xc1\x4d\x24\x9a\xd1\x23\x9b\x76\x0e\x34\xaf\x16\xfb\xf2\x26\xe8\x87\x33\x13\xdf\xe2\x8a\x5e\x0c\xed\xe6\xf0\x2f\x2e\x7f\x61\x84\xee\x4c\x73\x71\x2d\xcb\xd6\x90\xc2\x24\x3a\x66\xf5\x48\xf2\x96\xf8\x94\x47\x6a\x82\x8d\x19\x96\x4a\x5b\x27\xee\x22\xfd\xc0\x66\xfc\x84\x32\x61\x02\x91\x55\x91\x8b\x8e\x01\x25\x53\xb4\xd5\xd2\x07\x9c\x9a\x78\x02\xb4\x6a\x06\x9c\xc4\x1e\x78\x96\xe8\xe6\xa2\xc5\xcf\x59\x0e\xb1\xf3\xfc\x12\xdb\xd1\x0e\x12\x01\x93\xba\x88\x02\xfc\xfc\x28\xee\x32\x13\x56\xbb\x57\x4e\x24\x6a\x99\x31\x79\xa5\x12\xf9\xb5\x2d\xb0\x28\x89\x64\xcb\xe9\xa8\xef\x9e\xb4\x67\x02\xe6\x8e\x0c\xcc\x97\x78\x95\x3d\x2f\x65\x68\x33\xcd\x63\x7e\x89\xc7\x38\x76\x32\xfc\x7e\x38\xd3\x12\xfe\xa2\x72\x7a\x02\x8c\x17\x2e\x79\x7e\x98\xf3\x74\x69\xaa\x95\x43\x03\xdd\x05\xa9\x78\x35\xf3\x52\xc0\x2b\x4f\xb7\x19\xd4\x46\x52\x25\x97\x8d\x66\xd4\x0b\x94\x80\xcf\xad\xfb\x4d\xb4\x82\xb0\xce\xe9\xa2\xcb\x82\xbf\x96\xfe\x8d\xa4\x20\xcc\x18\x08\xf0\x4b\xf0\x23\xed\x67\xdd\xe9\x6f\x85\xb5\x6a\xbf\xd5\xa8\xad\x27\x86\x10\x5a\x45\xfe\x4f\x7b\x22\xf1\x72\xfb\xc3\xd8\xc0\x90\x55\xcf\x19\x8e\x20\xca\x08\xed\xee\xff\xd3\x3c\x12\xc4\x4d\x00\xba\xab\x51\x14\x34\x53\xca\x16\x44\xcf\xc5\x85\xed\x16\x35\x34\x5d\x46\xe4\x78\x22\xc6\x76\xa3\x31\xb2\x7c\xb6\xba\x58\x4d\x4f\x3a\x4e\xea\xad\xe3\x12\x26\x5a\x58\xf3\xd5\x31\xdd\xa7\xcc\x3a\x49\x57\x47\x8f\x2f\xb5\x2c\xda\x1d\xae\xc9\xd9\x5c\x78\xb3\x59\x50\x6d\xa5\xae\x58\x98\x9c\x4e\x50\xde\xfd\x66\x9a\xce\x5f\x8e\x56\xd3\xe9\xc6\x0b\x34\x5c\x2a\xd2\xa5\x9d\x4a\x65\x6f\xce\xdc\x3c\xbd\x93\x86\x30\x45\x96\xaa\xbb\xc5\x96\x9c\x91\x4e\xf3\xa0\x27\xd5\xb8\xf2\x01\x99\x8a\xcf\x99\xa7\x89\xf8\xd4\xf0\xa1\x0a\x47\x29\x9b\x53\xc7\x9f\xe2\x1c\x4e\x75\xb4\x88\x81\xfe\xf0\x2f\xc2\xc8\x3b\x68\xb7\x18\x90\xf0\x98\x22\xbb\x12\x22\xd3\x7c\xb7\x1d\x7f\xc4\xbb\x7d\x26\x32\xb9\x4b\x84\x07\x24\x47\xb9\x63\x78\x70\x3d\x77\xe2\x0b\xa6\xbc\x2e\x3a\xa8\x54\xa5\x5e\x47\xb8\xf9\x1f\x96\xb9\x66\x3a\xe5\xf4\x8c\xad\xb4\x17\x27\x64\x4d\x64\x8a\xa6\xbf\xcc\x45\x02\xf7\xb3\xf2\x6f\x22\x24\xd2\x23\xe7\xa9\xc6\xf5\xb7\xd6\xf3\x26\x76\xda\x1f\x3c\x8d\x62\x87\x92\xf1\xc9\xfd\x7d\x71\x32\xee\x94\x3a\x5d\x1a\x15\x1a\x5e\xe7\x87\x9c\xc3\x97\x4f\x29\x9d\xae\x09\xb0\x1c\x5f\xac\xca\xed\x2f\x24\x94\xac\xb6\xbe\x90\x68\x7a\xb6\xf1\x2a\x9f\x22\x25\xa1\x57\xd9\xcb\xdb\x69\xa3\xb0\xcd\xd2\xb2\xd3\x0b\x06\x68\x9d\x07\xb9\x6e\x5b\x87\xd9\xbf\xc6\x4e\x38\xcb\x57\x7e\x13\x8a\x8a\x07\xd3\x1f\xd5\x57\xd6\x7a\xdd\x2b\x41\x36\x95\xfb\xd2\xf9\x0c\xd8\xcc\x2b\x01\x4a\x34\x17\x56\x59\x5f\x18\x2a\x82\x05\xaa\xd7\x37\xf9\x6b\xd9\x24\x5d\xa7\x07\x36\x0b\x95\x13\x7e\xcf\x59\xeb\xa1\xbf\xe7\x44\xe6\xd8\xef\x89\xf5\x42\xe7\x62\x16\x08\x11\x93\x09\xf0\xeb\xba\x02\x7e\xa0\xf5\x5a\x3e\x94\xfd\x66\x58\x87\x23\x48\x34\x5c\xfe\x4d\x21\xe5\xf2\xeb\xea\xc5\x22\x27\xee\x96\x39\x4c\xe3\x4d\xb1\xec\xc5\xf2\xab\xf4\x4a\x91\x2d\x85\xff\x54\x33\x96\x73\xf4\x9c\x8e\x36\x82\x53\x94\xdc\x22\xea\x5e\x72\x37\xd6\xdb\xce\x60\x5a\x56\x6f\x01\x5f\xb9\x44\x95\x44\x4c\x46\xb4\xc2\xa8\xd7\x5b\x0e\x40\xcc\xd5\x78\xea\xb8\x0d\xb5\xa4\xaa\x59\x3f\x86\x90\xd9\x78\x75\xaf\x6b\x0c\x4e\xce\x3c\xce\x0a\x48\xf5\xf6\x54\xa3\x18\xbc\xa3\x51\xdf\xe3\x75\xb9\x71\x09\xd9\x09\x7e\xff\x72\x62\x21\x45\x7f\x86\x5b\x7d\xc5\xb9\x3e\xa7\x60\x86\x3e\x6d\x24\xf9\xa2\x52\x3e\xe5\x39\x61\x11\x4d\x0c\xdd\xa2\x2b\xde\x76\x83\xdd\xf7\xaf\x76\x3e\xd4\x28\x8f\x9b\xca\x19\x3c\x55\xc0\x74\x1f\x37\xab\x53\x5f\xd3\x86\x8e\x1c\xc2\xe6\xfe\x7a\x68\x24\x59\xaa\x72\x86\xcd\x99\xcd\x92\xdd\x02\xd7\xce\x96\x97\x6a\x46\x7e\x7e\x44\x28\xe5\x0f\x7a\x79\x05\xe5\xb3\x1c\x82\xf6\x8e\xb3\xe8\x16\x7a\x01\x73\xa8\xb1\xd2\x3f\xe5\xce\x2a\x06\x28\x24\x73\xea\xdb\xe6\x9b\x91\x3b\x4b\x6b\xc1\x1b\x40\xde\x7e\x5d\x2c\x6b\xce\x77\xce\x3d\xda\xdf\x2f\xc2\xb0\x93\x44\x99\x05\x89\x30\xea\x67\xd9\xba\xd0\x97\xcf\x04\xc7\x34\x37\xe2\x86\x62\x3c\xae\x0b\x7c\xc3\x85\x07\x67\xa5\x5a\xd6\x70\xf5\x76\x4e\x22\x49\xc2\x58\xcc\x86\x40\x12\x2b\xe9\x32\x86\xcf\x1f\xce\xbf\xbf\x44\xdf\xb0\x9d\xec\x48\x87\x9e\x47\x41\x1b\xa6\xe5\x11\x68\x08\x19\x42\x0e\x70\xc0\xb8\xc1\xd7\x9a\xc6\x0b\xfa\xee\x33\xd6\x0a\xaa\x06\x5c\x61\x4f\xd6\xa7\x5d\x51\x3e\xf6\x83\x56\xe1\x2d\xcb\x25\x17\x92\x3b\x89\x45\x1d\x50\xb5\xb0\xa7\x59\xd8\x08\xf0\xd3\xab\x9a\x31\x68\x14\x67\xe4\x5c\xce\xa9\xd0\x13\x8a\x05\xa2\x6b\x3f\xb5\x5a\x3d\x94\x39\x57\x07\x18\x34\xfa\x71\xa3\xd7\xd9\x14\x0e\x63\x98\x7a\xe9\x23\x5d\x5c\x42\x15\x16\x87\x18\xfb\x7d\x01\x88\x31\xdd\xd0\xc6\x57\x50\x59\x83\x97\xea\x2d\x1b\x5f\xfc\x07\x03\x2a\x66\x64\x60\xd7\xb5\xac\x47\xe5\xa1\xc6\xd9\x88\x88\xe9\x23\x64\x93\xe5\xbd\x65\x2d\x65\x6e\x03\x4a\x71\xc3\x18\xd6\x40\x4e\x44\x4d\xfb\xfd\x31\xa9\x73\xfe\x1b\xe2\xf4\x61\x65\x77\xb0\x09\x78\x65\x89\x0f\xd0\xf0\xf3\x2f\x02\xb9\x5e\x84\x55\xbb\x66\x9b\x38\xaa\x8b\x24\x88\x06\x22\xf6\x87\xf4\x35\x01\xb4\x09\x3b\x94\x47\x48\xe9\x4d\xae\x8a\xcf\xc9\xf4\xa0\x62\xcd\x50\x59\xb9\x29\xf5\x32\x44\xc3\xbf\x07\x98\xac\x5e\x1b\x01\x67\x55\xb4\xd1\xd3\xaf\x72\x7f\xce\x58\x80\x61\x34\xbb\x29\xd8\x39\xf1\x05\x94\x01\xc8\x82\x3d\x0e\xf7\x26\xdb\x2a\x25\xc0\xc2\x73\xad\xcc\xd6\x1b\x1d\xeb\xe4\xd6\xd8\x3f\xee\x87\x1c\xcf\x44\xa6\xec\x61\xe3\x0d\x3e\x28\xf7\x0a\x36\x6e\xc1\x70\xd3\x52\xb1\x3a\x8c\x08\x5f\xb5\x54\xd6\x4a\x5f\x84\xdb\xec\x4b\x2f\xca\x27\x68\x47\x9e\x15\xf4\x94\xa4\xd0\xb7\x4e\x4c\xd7\x7b\xac\x01\x6a\x4f\x4e\x73\x84\xf1\x95\xf2\x4a\xed\x3d\x05\x7b\x54\xaf\x34\x9e\xc4\xd8\x84\xd8\x86\xc3\x53\xc8\xcb\xcd\x34\x3f\xcb\x37\x56\xd6\x62\xa7\xde\x2a\xfd\x03\x8f\x25\x09\xfc\xd8\xd7\x4a\x5e\x7f\x5b\xcb\xf6\x2e\xcd\x5d\xa3\x87\xd3\x56\xb1\x6e\xc5\xa8\x87\xa4\x08\x99\xc1\x69\x7b\x82\xe2\x35\x31\xee\x62\xe1\xd5\xe2\x36\x68\xb5\xc9\x6d\xc3\xe1\xba\x16\x56\x6c\x96\xb8\xc8\x50\xbf\xb7\x34\xd6\x4f\x16\x25\xb0\x41\x4c\x59\xea\xd4\xc6\x6f\x8f\x3c\x59\xab\x01\xbd\x4d\x5b\x43\xb7\xb7\xe7\xe4\xb2\x07\x54\xd3\xe7\x0e\x4f\x67\x1d\x4c\x14\x62\x43\x83\xf3\xd5\x27\x1d\x6e\xc8\x62\x75\xb2\xac\x07\x3d\x12\xc3\xe7\x66\x39\xb5\xb7\x29\x54\x40\x24\x2f\x04\x30\xfd\xcc\x9f\x40\xa9\x88\xaa\x89\x52\xa1\x26\xee\x16\x7b\xf2\xca\xfd\x89\x82\xab\x4f\x74\x78\x1b\xc7\x44\xf8\xb6\x00\x9b\x38\x50\x11\xdd\x99\xe2\x1f\x82\x22\x61\xf6\x56\x1e\xd5\xf4\x4d\x1d\x0e\xb0\x6f\xbb\x38\xe1\x1e\xfb\x85\x86\x2e\x35\x5c\x45\xfd\xe3\x2d\xd9\x8b\xaf\x2c\xb1\x50\xc0\xc8\x83\xe9\xe5\x37\xcb\x93\x46\x2a\xc1\x8f\x3d\x39\x71\x72\xfa\x6c\xec\xa3\xf1\x5c\x6d\x6d\x32\x8c\x2b\xae\xbe\x26\xd6\xac\xdd\x72\xa9\x52\x5c\x41\x15\xd4\xd1\xae\xcc\x15\x24\xdb\xea\x09\xf7\xf7\xe7\x9b\x7f\xd5\x5a\x6d\x7c\x87\x15\xdc\x3e\x2c\x72\x87\x23\x51\x75\xa4\xc0\xa2\xf3\x62\x6d\x30\xa5\x7b\x9e\xcd\x64\xb6\x1c\xd7\x6a\x7c\x92\xd7\xf8\xc4\x2f\x21\xae\x33\x14\x1f\x34\xc4\x3d\x73\x98\x92\x3d\x2b\x16\x18\xfe\x72\x89\x6f\xca\x59\x34\xb1\x27\xe6\x8f\x62\xe6\x86\x69\x88\xbb\xca\x85\x4f\x9c\xbc\xe4\x3c\xb6\x1f\xab\x39\xa5\x52\xf6\x74\xe3\x38\x1e\x83\xe5\x40\x22\x73\x60\x21\x37\x54\x4e\xee\xa8\xa4\x0a\x91\x48\xb9\xf2\x69\x79\xa6\x51\x3a\x6e\x4f\x16\xfc\xb8\xb3\xf5\x89\x25\x16\xa2\xe4\x64\xd7\xe6\xb8\xbc\xf9\xca\x6b\x22\x4c\x3f\xff\xfb\x27\xaf\x38\xaf\x7f\xc1\x6c\x15\xf5\x47\xef\x8e\x7c\x5f\x47\x3d\x4a\x8f\x6f\x06\x97\x5e\x1e\x99\x10\x78\xc3\x57\x05\x3a\x86\x85\xc9\x13\x38\xbd\xa0\x0e\xd1\x06\x06\xad\xa0\xfb\xe7\x7f\x28\x5a\x54\x5f\xbb\xb1\x0f\x2f\xbb\x61\x74\x0f\x2b\x7d\x50\xb5\xe6\x62\xa8\xb7\xba\x17\x92\x76\xdb\x29\x05\x5d\xc8\x1a\x61\xd6\x0f\x4f\xbc\xfd\xcb\x43\x4f\x0e\x79\x8a\x59\x60\x60\x54\x59\xc4\x5b\x53\x3a\xb2\x8b\x81\x38\x8c\x33\x38\x31\x9c\xa4\x5d\x44\x62\xca\x36\x62\xbb\x66\xb1\x5f\xc1\x6b\xec\xcb\xa1\x90\xe2\xbf\x96\xcd\xec\xc1\x09\xf6\x44\xa2\x55\xe3\xc0\xa0\xaa\x6b\xbb\x0e\xe4\xc5\xde\xbc\xdf\xc7\x4d\xf1\xbd\x19\xc3\x80\xfb\x8a\xf1\xeb\xa1\x47\x3d\x4c\xae\xb4\xd7\xa6\x52\x6f\x9a\x6d\x50\xed\x63\xaf\x91\xbf\x4e\x4e\x70\xf5\xd4\x03\x2f\x31\xcc\xfe\xe6\x75\x48\x61\xaa\x07\x35\x7b\x5e\x15\xa8\xe2\x84\xad\xde\xec\x54\x0f\xed\xa6\xd3\xdf\x0c\x72\x42\xb8\x99\xa1\x80\xd6\x56\xb3\x29\x61\x8e\xed\x4f\x94\x0a\x99\x3d\x0d\x51\x7f\xca\x96\x96\x57\x3f\x3f\x79\x13\xe5\xa7\x33\xd6\xb5\x93\x7e\x7d\x31\xe5\xcb\xee\x86\x01\x45\x47\xcd\x99\x73\xda\xaf\xfe\x26\x15\xcb\x43\xb5\x3b\xe9\xd8\x76\xb2\xf8\xdf\x49\xb4\xab\xb3\xee\x3a\xe8\xbf\x27\x7b\x64\x6c\x49\x67\x84\xe2\xac\x2a\x28\xdd\x16\x38\x0d\x67\x00\xab\x2e\xd2\x6d\xd9\x1f\xa1\x0e\x5d\x2e\xb7\x60\xf4\x7b\xb5\x09\x46\x7d\x74\x95\x41\xaa\xb9\x07\x94\xaa\xa3\x73\x4d\x07\x4f\x52\x72\x76\x97\xf2\xa1\x16\xb6\x53\x7c\x99\x6e\xd0\xb3\x4f\x04\x4d\x61\x3a\x64\xd0\x27\xcb\xb6\x51\x22\x34\x5f\xcd\x40\x2a\x74\xee\xe6\xdb\x05\xbd\x76\x2f\xd3\xbb\x12\x6f\x77\xff\x0d\x18\x7b\x06\xc8\x90\xfa\x9f\x7a\x73\xa8\x33\x90\xca\xfb\xc5\xda\x6d\x4f\xad\x89\xb9\x88\xeb\x22\xbb\xe4\x6f\x78\xa9\x2c\x00\x03\x2b\x86\x26\x78\xf0\xd1\xb0\x74\x04\xeb\x31\xfc\x88\x25\x08\xc0\xc1\x59\xb4\xc4\xe7\xb6\x12\x6c\x2b\xc1\x38\x35\x5c\x7e\xea\xf2\xe9\x0e\x86\xd9\xe6\x70\x95\x6d\x9c\xeb\xb2\x1d\x0f\xb1\xec\xa7\xf2\x77\x01\xcd\x09\x27\x41\xf7\xee\x63\x04\x34\x4d\x4b\x62\x2b\xe5\x06\x48\x8d\x5d\x8b\x5c\xf2\x56\x2e\xd3\x77\xd5\x79\x6f\x76\xe1\xd9\xaf\x2f\xf1\xaa\xcb\x57\xfb\x29\x7b\x89\xae\x6a\xdd\x7e\x35\x82\x2e\xbb\x5d\xd5\x44\xd1\xee\xe0\x6b\x57\x70\xae\x22\x55\x43\xcf\x36\x56\x11\x90\xeb\x35\x99\x1c\x63\x70\x0b\x82\xa9\x9b\xa6\xfa\xf7\xa4\x67\x64\xce\xb0\xe7\x13\x89\xa2\xab\x66\x44\x9d\x80\xd2\x1d\x56\xf3\xf5\x73\xda\x9c\x47\x24\x65\xb1\xdf\x3a\x1a\xdc\x6a\xdf\xac\x99\x5a\x87\x07\x2b\x3e\xa5\xe7\x19\xff\xe4\x83\xdc\xbc\x3f\x10\xf6\xf7\xa9\xbc\xd3\x4b\x8b\x8e\xb0\xb8\x0f\x8b\xb1\xb3\x4a\x7c\x59\x67\x9b\xda\xe4\xdc\xc3\x73\x75\x69\x6f\xee\x75\xdc\x94\xe8\xad\x36\xa6\x1d\x87\xde\x38\x7d\x65\x82\xb5\x45\x36\xde\x4e\xc4\x36\xd4\x81\x09\x7c\x70\xe3\xbe\x41\xe2\x12\xd6\x58\x2e\xed\x75\x77\x32\x22\x09\xa6\x2a\x92\x86\x1d\x44\x23\x51\x2e\x56\x3d\xbd\x13\x79\xf5\x0d\xb7\xe6\x6e\xeb\x4e\xc2\x08\x44\x3c\x17\x4b\xd7\x3e\x61\x57\xc5\xb3\x2d\xdb\x4e\x79\xc3\x16\xb3\x13\x25\x8a\x28\x81\x06\xaf\xb7\xc8\x7d\x0d\x9c\xdb\xea\x9c\x17\x8c\xdb\xca\xc0\x1d\x97\x93\x83\x3d\x7d\xf8\xa2\x66\x31\xdd\xbb\xaa\x0c\x2d\x9a\xbc\x29\x3d\x9a\xc2\xd2\x3e\x9c\xbb\xf5\x15\x0b\xef\x3d\x9d\xc5\xf2\xbc\xd9\xaf\x14\xf9\x94\x17\xa2\xb5\xe2\xae\xf7\xb8\xab\x9c\x71\xb7\xf1\x73\xe3\xbd\xf8\x5a\x0c\x93\xf5\x43\xa0\x95\xfc\x9f\x86\x72\x50\x6f\xa5\xe9\xf6\xdd\x83\xbc\x74\xbd\xce\xa0\xd0\x24\xa9\x26\xb3\xd1\xde\x07\xc6\xaa\xa3\x5b\xfe\x91\xad\x49\xb3\xf1\xd8\x6b\x37\xa5\xbf\x23\x5a\x5d\x44\x5f\x4b\x01\x6a\x72\x99\xd2\x1b\xf5\xdd\xc0\x8a\x6d\x71\xb1\xa6\x73\x5e\xb4\x60\x0d\x42\xf0\xe2\x29\xf8\x15\xad\xfb\x95\x49\x09\x9f\x87\x4d\xb9\xdf\x0f\xbb\xbc\xf0\x35\xac\xca\x52\x76\x89\x1c\x4a\x68\x5b\xc1\x6a\xdd\x19\x30\x5e\xb4\x5e\x45\xcc\x71\x94\x8b\x19\xc0\x7e\x5e\xa7\x8e\xae\xb2\x8d\xf0\xf9\xf4\xfa\x17\xe9\xc6\x20\x96\x7d\x29\x32\xb7\x28\xa2\x62\x3b\x1e\xac\xba\xda\x2c\x85\x54\x61\x58\x06\x8e\xc4\xb5\x57\x86\xf1\xcd\x28\x2e\xab\x6b\x09\x82\xd0\xb6\x07\x9f\x37\x6e\x50\xb7\x5d\xe7\x15\x45\xfe\x9f\x3f\xf2\x04\x14\xeb\x7d\xb0\x13\xe2\x77\x0f\x22\x1f\x21\x48\x0e\x4d\x65\x63\x5b\x4a\x73\x91\xca\x1c\x1e\x93\x48\xbb\xab\xcd\x60\x9a\x57\xf8\xd6\xea\xe3\x12\xad\x98\xc1\x16\xf6\x2f\x42\x2d\x90\x09\x1f\x38\xc2\x81\x75\x45\x1c\xb0\x0a\x70\x82\x37\xb1\x83\x8f\xb0\xed\x4c\x87\x9b\x13\xb6\x8c\xab\x61\x52\x8b\xc5\xee\xc5\x46\xdd\x68\x65\x08\x2d\x3e\xc8\x12\x76\x7d\x14\xbd\xb0\x95\x90\x81\x01\x6b\x78\x7c\x17\x41\x45\xad\xf5\x1b\x84\x5e\x9b\xe2\xa9\x48\xc4\x57\x56\x12\x93\xd7\xf1\x96\x63\x11\x65\x98\x11\x88\x3f\x54\x14\x48\x4b\x15\x41\x6f\x7d\xcd\x23\x66\x10\x6c\x4d\xe4\xbc\xa7\x8a\x20\x6b\xd3\xcc\x9f\x0e\x74\x65\x9d\xd5\xf4\x17\xb7\x0a\x12\x02\xa7\xf4\xb6\x62\x4e\xb6\xa9\x91\xfe\x77\x13\xa8\x6b\xf2\x86\x1b\x1a\x53\x40\x00\x8a\x0b\xf2\xcd\x69\xbd\xd6\xce\x03\xb0\x5c\xce\x00\xf6\xc4\xa2\x65\x5a\x7f\x96\x4e\xb9\xc5\x35\x40\xa7\x8b\x67\x7b\x66\xa2\xd3\x9a\xed\x0a\x12\x28\x90\x85\xf1\x6d\x76\x87\xfd\x05\xa5\x58\xb3\x3f\x8b\xbc\x72\xdf\xc8\xbf\xdd\xb6\x58\x1f\x64\x94\x48\x2c\x06\x73\x35\xdc\x03\xb7\xcc\xa3\xa9\x2c\x0f\x36\xf1\x3e\x4a\x1b\x07\x44\xe2\x49\x47\x25\xd2\x06\xe1\x9b\xd8\x55\xe7\x45\x1b\x39\xf3\x02\xf6\x9c\xf3\x48\xdd\x11\x42\x2f\x7c\xe2\x0c\x81\xdc\xfe\xdf\x29\x96\x70\xf8\x29\xea\x20\x12\xcf\x9a\x12\x85\x6c\x30\x8d\x55\x97\x70\xd2\x71\xd0\x8f\xfb\x5c\xed\x14\x11\x7b\x30\x37\xfa\x90\x89\x9e\xb7\x0d\x45\x18\x6d\xc3\xeb\x25\xd3\x8d\x30\x5a\x69\xa6\xf3\x14\x79\xf8\x2b\xa7\x6d\x26\xb9\x49\xc3\x9e\x91\x14\x63\x0d\x35\x0d\x86\xc3\xa2\x80\xb9\xa7\x18\xcd\xf1\x32\x15\x98\x9c\xb5\x0c\x79\xe0\x88\x47\xbd\x3e\xd2\x2e\x92\xdf\x22\x90\x4b\x33\xa5\xef\xbd\x09\xce\x8e\x33\xef\x77\x6b\xc5\x24\xab\x19\x29\x80\x05\x01\xbd\x88\x98\x1c\x36\x61\x60\x85\xf8\x49\x6b\xbe\x46\x10\x7c\x68\x72\xe4\x4d\x44\x69\x0b\xdc\x49\xd9\xdf\x94\x5d\x68\xde\xa3\xe5\x17\xc3\x2c\xf7\x2e\xc0\x4f\x6a\x32\xd3\x54\xb2\x60\x03\xf0\x20\xef\x92\x3c\xd9\x4d\xf2\x27\x34\x29\xd2\x87\xab\xfa\x5c\x59\x0b\x7d\xb1\x22\x1d\x30\x84\x12\x1c\x8c\x20\xfd\x82\xd9\x2d\xfd\x5b\x6c\xbc\xe1\xce\x90\x64\x6f\xd2\xbf\x10\x38\x05\xe3\x59\x84\xe7\x3d\x07\x11\x3d\x8a\x05\x16\x3c\x6b\xd4\xd0\x25\x72\x91\xa4\x99\x45\xaf\xea\x1b\x64\x8d\x4c\x6e\xf2\x34\xed\x97\x02\x9f\xdb\x32\x7e\xc9\x31\x34\x4d\x6d\xbd\xd3\x92\xca\xa9\x0d\x6a\x74\x64\x43\x3f\x9f\x41\xad\x0f\x63\x1f\x04\x7c\x4d\x9b\xf6\x08\xf6\x75\xfb\xea\x13\xc6\x43\x6f\xa4\x97\x73\x4a\xff\x8e\x0d\x0b\x78\x33\xe3\x4c\xf6\x32\x6f\x27\xcb\xf5\x9c\x5c\x7a\x1e\xa5\x19\xff\x53\x5e\xb3\x5d\x81\x83\x85\x9d\x33\x08\xba\x89\x74\x6a\xac\x1d\x28\xf1\x27\xb7\xfa\x87\x61\x17\x2b\x1f\x08\x65\xc4\x48\xbe\x75\x25\x59\xdb\x04\x46\x2a\x8d\x22\x57\x8f\xe2\x5c\x83\x56\xad\x17\x9c\xf4\x5c\x28\x83\x46\xb3\x05\x9e\x29\x96\xa3\x1f\xff\xef\xcb\xbf\x92\xe7\xb6\xd1\x08\x72\xd3\x4a\x92\xd3\x9e\x8f\x22\xde\xb3\x38\xd0\x08\x2d\x79\x91\xc3\x24\xa1\x80\x8a\x48\xa8\x5d\xd7\x4d\xca\x04\x08\x41\xfa\x14\x95\xc6\xc6\x31\xa4\x13\x69\xb9\x64\xfa\x93\xdc\x71\x83\x13\x15\x5f\xd5\xf6\xf1\x93\x0d\x2c\xc8\xfb\x9b\x48\x98\x6e\x19\xf2\xe7\xb6\x3b\xc4\xd3\x73\xdc\x29\xc3\x58\xc9\xc3\xa0\xe1\xb1\x43\xd7\x5a\xa8\x76\xf7\x63\x71\xe8\xda\x15\xad\x87\x13\xa9\x49\x0b\x9e\xf1\x03\x4c\x14\xa1\x4a\x20\xb1\x51\x77\xd2\x3f\x65\x16\xd1\x5d\xc6\x98\xfc\xe8\xb9\x19\x7b\xcd\x23\x11\xcb\xfb\xd2\x59\x47\xf4\xfe\x9c\xae\x5d\x39\x76\x9a\xbc\x02\x28\xf7\xc7\xa9\xe5\x42\x77\x82\x8a\x05\xcb\xc8\x90\x56\x9e\x75\x68\x6a\x02\x68\xed\x9e\x99\x12\x36\x4c\xc3\x41\xfe\xf5\x66\xaf\xfb\x2d\xf3\xb4\x99\x25\x5c\xce\xfd\x5d\x1d\x56\x0e\xdd\xfb\xdf\x42\x29\x0f\x5b\x84\x6e\x82\x7f\x5e\x07\x90\x42\x5c\x09\x35\x3c\x8c\xbc\x26\x85\xfd\xb2\x5b\xc1\x74\xbc\xae\x2d\xe8\xc7\x53\xee\xaa\xdc\x1a\x68\xda\x62\x59\x8b\xa2\xcd\xd0\x9e\x7b\xbe\x01\xd2\x22\x5f\xf4\x6a\x2f\xe1\x26\x18\xfd\xca\xcd\xb4\xb1\x59\x61\xa7\xab\xd6\xec\x01\xef\x4e\x80\xac\x89\xab\x0d\x10\x31\x0f\x05\x50\x8e\x57\xaa\xa1\x11\x1f\x3d\x34\xab\xb5\x66\x57\x0d\xb5\x53\xd3\xc8\x39\x55\x38\x38\xdb\x36\x3e\xa7\x4a\xd4\x2b\xa1\xe3\xa6\xd3\xba\x55\xd8\xfc\x83\x1d\x8e\xf7\x7d\x7f\x58\x31\x84\xe8\x86\xc7\x33\xde\x99\x3d\xac\x2e\x5b\x7f\x79\x1d\x2e\xef\x41\xfe\xd0\x5f\xb6\x8c\x08\x0e\xbc\xca\xe9\x50\xa2\x0b\x58\x1f\xee\x78\x71\x3e\x7d\x51\xc0\xe2\x42\x06\xa6\x99\xc8\x15\x22\xbd\xd7\x0f\x9d\x07\x0f\x9e\xde\xe7\x5a\x00\x15\x40\xb4\x51\x5d\xe4\xe3\xc2\x1c\x4e\x49\xf6\x01\x1c\x1f\xf8\xd1\x70\x15\xce\x9c\x62\x79\xa3\x2a\xad\xfd\xc1\xbb\x47\x14\xbb\x5e\x54\x8a\xfc\x10\x1e\xf1\x29\x85\x89\xce\x87\x12\xfe\xee\xe4\x79\x45\x10\x1c\xf2\xd2\xb9\x95\xb5\xc7\xbf\xa9\x3b\xad\x07\x8d\xc5\xf2\xcf\xd7\x58\xf7\x01\xf3\x28\x42\x30\x3e\xfc\x1b\x6c\x28\x3a\x12\xbf\xec\xe6\x5b\x7d\x22\x25\xfa\xe0\xf1\x68\xc8\x0b\x87\x9e\xbc\xf6\x0e\xa7\x00\x65\x64\x85\x2b\xf0\xe9\xfd\x07\x58\x96\x3d\x4d\x72\x04\x1d\x6b\xa6\xeb\xd6\xa1\xdc\x89\xd9\xa8\x73\x10\xc9\x12\xe7\xab\xfe\x9c\x7c\xb2\x03\x11\x7d\x8f\x8d\x8c\x1f\xf9\x7a\xe6\xe5\xe4\x2e\x1b\x77\xc5\x76\xcf\x3a\xa8\xe1\x26\xbd\xab\x91\xa8\x0c\x62\x3e\xb9\x9e\x6e\x3a\x4e\xd7\x61\x71\xf6\xb8\x1f\x94\x5c\x4e\xe1\x47\xf1\x73\xcc\x53\x10\xc9\x57\xba\x1e\x03\x49\x11\x29\xbf\xc5\xfb\xd1\xe8\xb7\x4f\xfc\x99\xed\x7e\xf2\x0e\xf4\x4d\x2a\xaa\xb3\xb7\xcb\xe1\xdd\xc3\xbb\x60\x09\xe0\x87\xaf\xca\x81\xef\x3d\xbe\x99\x0b\x5b\x90\x23\xe0\x43\x86\x20\x06\x93\xf7\xc8\x7c\x53\x4e\x48\x8c\x58\xf7\x00\x45\x7c\x64\x3f\x09\x34\x20\xa7\x0a\x96\x66\x2e\xe4\x97\x2f\xad\xf8\xda\x58\x3f\x63\xd0\xeb\xa3\xba\x5c\xf4\x52\xcb\xfa\xe8\xdb\x55\x78\xf8\x6a\xd6\x28\x8f\xce\xc7\x67\x94\x3b\x1b\x4b\x18\x9d\x86\x43\xf3\xdb\x8b\x87\x53\x01\x39\x62\x66\x5b\x93\xa1\xb7\xab\xa9\x71\xb4\x7b\x5b\xa6\x40\xe4\xcc\xdb\xb9\xe8\x47\x8d\x5a\xbe\x4c\xea\x79\xc7\x78\xe4\x76\x71\x1e\x24\xc3\x4e\xd4\xf9\xca\x39\x78\x43\x41\xa2\x96\x3c\xec\xe9\x75\xa8\xdb\x59\x57\x12\xce\xbd\xde\xe0\xe7\xde\x91\x97\x1e\x76\xa4\xdb\x49\x7a\xfa\x6d\xe4\x2c\x8e\x3a\x3f\x0b\x31\x89\xe5\xab\x3d\xda\x5e\x37\x38\xc1\xfe\x0b\x3e\x7a\xf0\x4c\xd5\x5a\x63\x1a\x0f\x69\x21\xcf\x06\x3c\xb0\x8b\xa0\xfc\xde\x9b\xf4\x29\x45\x6d\x60\x0f\xc7\x8b\x13\xcf\x95\x38\xe6\xd3\xf8\xaa\x66\xa9\x53\xc8\x04\x5b\x1e\xef\x25\x4b\x01\x94\xd4\xcc\xd1\x40\x6e\x5e\x39\xed\x20\xbf\x44\xc3\x2d\x44\x65\xb3\x5a\x39\xd9\xe7\x32\x04\xac\xd7\x3a\x27\xbf\x58\xcb\xf3\xe4\x7d\x62\xd1\x96\xf3\x5f\x9c\x96\x56\x82\x6a\xd3\x86\x30\x3d\xac\xe7\x22\x8d\x51\x7d\x4e\x5d\xa4\x41\x48\x99\xb9\x78\x25\x71\xbe\x48\xfa\x7c\x79\xd7\x17\x6a\x89\xb3\xf2\xe9\xdd\x79\x65\x89\x86\x04\xdf\x19\x83\x74\x17\x8d\x58\x6f\x89\x46\x8e\x98\x98\x5d\x1e\xe7\x95\xa2\x98\x65\xc2\x1b\xe9\x3d\x06\x14\x02\x08\x84\xff\x63\xc5\x0f\x09\xcc\x8c\x65\x01\xc4\xbd\x94\x6a\x4f\xfa\x17\x1f\xb2\x63\x39\xdc\xe9\x3e\xc2\x46\x26\xa9\xf8\xed\x26\xed\xa4\xd9\xc4\xe1\x66\xa9\x99\x91\x58\xd9\x1b\x8c\x39\x6e\x32\x38\xf8\x8b\x5c\x64\x85\x75\xac\xdc\x48\x37\xa9\x31\xba\xa0\x74\x70\xe6\x63\x5e\xeb\x44\xfa\xf0\x60\xc5\xe3\xd2\x4b\xd4\xaf\xda\xcc\x8a\x12\x1f\xad\x07\x9d\x66\x33\xdd\xac\x2c\x3c\xe7\xc4\x23\xec\x27\x95\x4c\xab\x2b\xb7\x06\xc5\x7e\xd9\x9d\xd3\x51\xf9\xf9\x09\x34\xa7\xe9\x21\xcf\xd9\x7a\x1a\x90\x46\x8d\xb7\xa8\x0a\x7a\xac\x3f\x64\xb3\x97\x7f\x3e\x23\x9b\xe5\xbe\x7d\x00\xb8\xe1\xdf\x0e\x27\x35\x75\x3b\x16\xeb\x37\xb2\xc8\xc6\x88\xa2\xb7\xd2\x8e\x06\x24\x4e\xfe\xe9\x65\x5d\xa4\x6a\x75\x88\x93\x79\xa0\x48\x47\x5a\x3e\xaa\x8c\xdc\x17\xa7\x0b\xac\xcc\xc0\x60\x84\xba\x2c\xaf\xf3\x38\xe9\x27\x41\x87\x5b\x83\x70\xae\xbd\xed\x47\x8f\xb1\x6b\x24\xa8\x30\x56\x02\xc6\x01\x3e\x9b\x6f\x37\x55\x11\x2c\x82\xaa\xa1\xb3\xef\xab\x0f\x2e\xcd\x65\x21\x69\x3c\x04\x50\x18\x2d\x2e\x95\x43\xec\x77\xe6\xf1\x18\x2c\x26\xee\xfb\xd6\x20\xc2\xfa\x14\x37\xd4\x14\xc8\x54\x45\x85\x1e\x00\x5d\x18\xbf\x8d\x74\xfd\x95\x7c\x0c\xb5\x4a\xe1\xda\x00\xaf\xf2\xf6\x70\xdb\xd2\x97\x67\xb0\xcb\x03\xf0\x32\x64\x76\xa4\x58\xcb\x28\x8b\x8c\xa1\xad\xd1\x10\x92\x09\x43\xdd\x7f\xda\xaa\x64\xef\x21\xd8\xf7\xee\xa2\x8b\xc5\xd6\x26\x56\x6d\x20\x30\xd0\xba\x7a\xa1\x45\xbc\x4e\x92\x91\xe0\xa2\x71\xa7\x30\xf5\x82\x51\x1e\xe0\x33\x68\xf7\x22\x98\xc2\x81\xda\x96\xd7\xbe\xf0\xc4\x87\x70\x05\x00\x23\xab\x64\x0a\x5a\xbe\x95\xca\x86\xbe\x7c\x5e\x03\xa7\xa7\x58\x63\x07\x62\x49\xf4\xd4\x8b\x37\xf4\x7e\x85\xf1\xa6\xb4\x0b\x76\x8f\x6d\x3e\x5f\xf8\x9c\xef\x1f\x17\xa9\xa1\x2e\xc1\xf8\xf7\x47\x1e\xff\x67\xbc\xf7\xc5\x9a\xfb\xfe\x19\x63\xe1\x74\xff\x54\x9d\x0f\xb7\xfa\x05\x4b\xd8\x3f\xf8\x93\xae\xbf\x24\x7e\xfe\x27\xd5\x42\xe6\xfe\xf9\x36\x70\xd8\x6d\x08\x7d\xd1\xb1\x62\x3f\xff\x24\x09\x65\x1d\xf6\x9a\xe4\xc2\xbb\xc6\xc2\xa2\x4b\x20\x50\xc2\xcb\x43\x1d\x39\x57\xa3\xf1\x9d\x1a\x33\xc0\x25\xea\xb5\x9e\xe3\x93\x07\x75\x97\x93\x49\x4f\x79\x0e\x37\x6f\xa2\x44\x2c\x3a\x1d\x9f\xe1\x5e\xbf\x48\xcb\x44\xbb\x76\x81\x04\x1d\x0b\x71\x37\xa5\xa5\x3b\xac\xe9\xe6\x74\x2b\x24\xfc\x82\x96\x20\xd1\x85\xc3\xed\xa1\x6c\x33\x8f\xa1\x89\xb0\x1c\x62\xac\x5a\xfa\xda\x85\x28\xc2\x85\xd4\x52\x8a\x06\x9b\x2b\xdd\x52\xc2\x01\x16\xc1\xf1\x37\xb9\x5e\xc2\xcd\xf9\x47\x9f\x04\xad\xce\x68\xa0\x2b\x1c\xc8\x25\x95\x54\xb4\x1e\x5f\x27\x47\x74\xb7\x13\x71\x92\x23\x9a\xcd\x15\x3e\x90\x54\xe0\x31\xea\x43\x7c\x02\xe1\xba\x2b\xb2\xf7\xad\x1d\x2b\x10\x8b\xc2\xda\x22\xec\x82\x93\x0b\x22\xa1\xfc\x61\xf1\x00\xf8\x75\x3f\xdc\x97\x85\xd1\x71\xea\xd2\x1f\x10\xe2\xd2\xb9\xa7\xe5\x4f\x07\x2e\xc1\xf9\xb0\xb8\x5f\xc2\xa5\xd8\x3d\xa1\xeb\x55\x70\x1d\x05\x04\x96\x77\x3b\x23\x7a\x3d\xf9\x53\xf9\xb2\x3e\xaf\xf4\xea\x62\xee\x3c\x7e\x55\x9d\x8f\x7e\xbe\x98\xc7\xb2\x01\xb1\x51\xfa\xfc\x4e\xc1\x74\xf4\x70\x7f\xab\x02\x88\x29\x01\x59\xbb\x54\x36\xb0\xbb\x5d\xdb\xee\x5b\x3f\x41\xfa\x1a\x6b\x6e\xef\xb5\x25\xb4\x46\x94\x6a\xd9\x48\x62\x4b\x62\x90\xd1\x13\xb5\x26\x7e\x40\x92\x4b\xd9\x5e\xae\x46\xa4\xf5\x72\xbe\x27\x71\x9b\x91\x4e\x91\xcf\x8d\x28\x05\x53\x0d\x0e\xc2\xeb\xc9\xdf\xb3\x9c\xab\x74\x17\xc4\xc1\x77\x1e\xea\xa1\x1f\xa1\xac\x43\x3c\x3b\x25\xe8\x69\xa8\xe8\x01\x42\xe0\x94\x9d\xdd\xa5\x2e\xa5\x5c\x50\x9e\x61\x33\x5d\x6c\xea\x5c\xbb\x32\xca\xb7\x69\x1a\xa0\x06\x29\xf4\xcb\x15\x4e\xc8\x96\x22\x53\xbf\x2f\x5a\xe8\x6a\xa5\xd3\x90\xaa\x34\xc3\x7c\xf6\x71\x1f\xce\x3c\x1f\xff\xb6\x39\x06\x54\xb7\x25\xd6\xd6\x37\x45\xd9\xd8\x3e\x65\x01\x80\xf6\xd7\xe5\x94\x6b\xc6\x7a\x90\x5e\x59\x94\x73\x3b\x49\xcd\x03\xf7\x11\x90\x0e\x5a\xe3\x8e\x6b\xb1\x3c\xcb\xe9\xf0\xb8\x8d\x42\x24\x61\xfe\x52\xd6\x09\x49\x05\xc5\xc0\x76\xf0\x77\x1d\x2d\x3b\xdf\xee\x28\x34\xb6\x20\x3a\x76\xd0\x77\x38\x63\xdd\xd4\xa3\x2e\x7f\xc2\x76\x63\x1f\xae\xf8\x4b\x87\xf3\x9d\x88\xf9\x87\xe2\x82\xfa\x34\x98\x04\xdf\xae\x69\xe8\x1b\xe9\x0e\xc2\x46\xb8\xde\x43\x3f\xa1\x1a\x67\x63\x32\x17\x26\xe4\x96\xed\xda\x54\x68\xd5\xfe\x10\x36\xb6\xf0\x29\x57\x61\x36\xdd\x84\xe1\x47\xf1\x24\x4b\xe2\x3c\x35\x57\xbd\xc7\x07\x58\x08\xbd\xa4\xe9\x40\x21\x90\xc1\x17\x2c\xf8\xa6\xf4\xbf\xb3\x1e\xe9\x6c\x23\x88\x2d\xd8\x5f\xa4\x68\x0c\x47\x62\xf5\xac\xec\xf1\x15\xae\x23\xb5\x6e\x9c\x91\xc1\x3f\xd3\x79\x6d\x60\x16\x84\x7d\xb1\x5c\x5a\xf6\x2c\x50\x97\x05\x14\x69\xf0\xb5\x40\xbe\x07\xa5\xa0\xd0\x28\x0f\x45\x05\x8f\x7d\xe1\x54\xe2\x04\x36\xdb\x6a\xa6\x2a\x87\xb0\xc6\xaf\x1a\x20\x57\xe8\x21\xa4\xf3\x2f\xfc\x88\xe7\x50\x3f\xf8\xa3\xbe\xfa\xde\x42\x12\x5a\x8e\xd4\x2d\xe5\x37\xdc\x61\x95\xf7\x00\xca\x8e\xfe\x29\x76\xbb\xf0\xa7\x06\x28\x8a\x7b\x96\xfd\x45\x15\x67\xac\xfe\xc0\xb6\x50\xbb\xab\x42\x02\x72\x2f\x0f\xa6\x50\x90\xb0\x2c\xbe\xf2\x2f\x76\x47\x69\xf8\x91\x3f\x2d\x7f\xe8\xad\x02\x3b\x2d\x72\x58\x15\x29\xf8\xe7\xc2\x7b\x67\xc3\xe4\xd9\xc7\x72\x10\x12\x49\x2f\x07\x82\x8d\xbd\xbf\x4d\x92\x29\x0d\x80\x99\x16\x96\xd7\xa4\x4d\x10\x7e\x46\x8c\x3a\x8f\xa0\x47\xc4\x59\xb8\xc5\xe8\xe7\x9c\x66\x5e\xc5\x4f\xb7\x60\xba\x57\x3b\x62\xed\x1e\xae\x95\x76\x03\x5b\x51\x71\x34\x24\x0f\x74\xbc\xd4\x4a\xe1\x53\xac\x8f\x1a\xa3\x90\xb0\x01\xe2\xe9\xfa\x01\x63\xf5\x3d\xf1\x50\xc7\xa9\x38\xb0\x29\xcf\xc6\x16\x0c\x92\xe2\x31\x32\x90\x8e\xa1\x16\x3b\x6f\x4d\x84\x9d\xad\xe9\xff\x73\xf5\x6e\x59\xb2\xea\x3e\x13\xe7\x7b\x0f\xa3\x5e\x6a\x54\xfd\x60\xc0\x09\xae\x04\xcc\x9f\x4b\xe5\xce\x5a\xab\xe7\xde\x0a\x45\xc8\xe4\xf9\xea\x9c\xbd\x90\x49\xee\x17\x63\xcb\xd2\x2f\x5a\x7a\xfe\xaf\xa7\xf8\xab\x40\x30\x96\xa8\x00\x68\x84\x47\x70\x21\x44\x0a\xc3\xcb\x04\x9f\xcd\x5c\x1a\x4a\xc0\x95\x71\x94\xbe\xef\xe8\x11\x5a\xad\x59\x03\x7b\x48\x32\x9c\x92\x19\x0b\xf7\x97\x40\x0c\x3b\xe3\xf6\xf6\x2c\xfd\xa5\x38\xcc\x2d\x58\x0a\xd2\x97\x95\xed\x22\x7f\x1f\x18\x02\x7c\xb2\x74\x02\x76\x81\xe4\xae\x34\xdb\xa5\x47\xa5\x4b\x2c\x1d\xd2\x4b\x8b\xdd\x8a\xe0\x3b\x84\x57\x52\x83\x6d\xa2\xff\x20\x41\x61\xeb\x8b\x68\xab\x18\xd1\x0e\xac\x02\x18\x6e\x11\x0a\xea\x41\x2a\x5c\x44\xa9\x15\x0d\xa8\xf0\x1b\x64\x65\x8f\x4a\xe4\x35\x99\x28\x90\x15\x30\x08\x78\x05\x76\x22\x07\x02\x0a\x1f\x5a\xc6\x8f\x2b\x90\x3d\x3b\xc8\xb0\x63\xde\x83\x4b\x86\xb4\xf3\x35\x7e\xca\x8a\x13\xb4\x57\x72\x0f\x51\x64\xd7\x67\xd6\x5c\x0c\x5c\x87\x59\x90\x2e\x9f\xa8\xb8\x8c\x0a\x21\x85\x56\x72\x88\x26\xbf\x28\x9e\x1d\x1f\x99\x1d\xd0\x6c\xce\x09\x95\xdf\x3d\xfd\x64\xe9\x7d\x27\xb9\x5f\x9c\x28\xac\x0d\xd8\x71\x49\xfc\x78\xb4\x9e\x52\xa6\xa5\x6d\x0d\x6a\x42\xa2\x92\x63\xa3\xcd\x07\x9f\x3c\xc4\xee\x2b\x00\x08\x84\x2b\x38\xe6\x00\xb9\x65\x92\xd9\x7d\x7b\x5d\xb2\xbd\xc7\x25\xcd\xa1\x7b\x7c\xe8\x21\xda\x04\x49\xb3\xc6\x0d\x32\x56\x68\xfd\x57\x22\x79\x61\xab\x7f\xbb\xb4\x83\x0d\x6f\xbe\x82\x1b\x1c\x5e\x50\x90\x97\xd7\xb0\x00\x57\x88\x0f\xd7\x5f\xc4\x1b\x64\xda\xf8\xe0\x47\x52\xb6\x8b\x23\xef\xc1\x34\xd8\x4b\x66\x1a\xbf\x87\x9e\x0d\xb4\x9a\x10\x72\x23\x16\x68\x3b\x9f\x9c\x00\x2f\x44\x06\x8c\x4b\x20\xb3\x1e\xb5\xe7\xfb\x1d\xf8\x81\xdf\x26\x30\xbe\xe1\x7d\x6c\xc2\xc6\x91\xe0\x0f\x16\x1f\xe9\x1c\xe0\x11\x30\x02\x83\x04\x82\x40\x0a\xb4\xfc\x7e\x85\x70\x62\xaa\xa6\x9e\x4c\x6e\x13\xbc\x28\x5e\x93\xba\x7d\x7c\xf0\xad\x01\x28\x74\x06\xb8\x02\x4a\x3e\xaf\xf5\x41\x72\x81\xbd\x2a\xbc\xca\x08\x0c\x29\x54\x4d\x76\x91\xe3\x5b\xb6\xd3\x66\xcc\x55\xbf\x40\xf2\xf1\x4b\xf0\x81\x80\x0e\x08\xdf\x30\x7b\xe8\x4e\x30\x07\x44\x7c\x03\x47\x80\xd1\xf6\x2a\x71\xfc\x2a\x0a\xe8\x8f\x86\x9d\xd3\x25\x74\x41\xd2\x38\x16\x35\x90\xdb\x79\xcc\x29\xe8\xe4\x5b\x39\xe3\xdd\xdf\xca\x1d\x99\x00\xe0\xc0\x3b\xac\x10\x21\xdc\x90\xb9\x63\xed\x05\x9e\x4a\xd1\x00\x10\x0c\xd1\x0a\xc6\xf1\x1d\xe9\xf4\x05\x78\x24\x6d\x20\x87\x72\x35\xd2\x4d\x3f\x3a\xe4\x4c\x3f\x8d\xcf\xb4\xf5\x27\x0f\xc4\x6c\xfa\xa1\x20\x87\x98\x18\x44\xd7\x55\xde\x8e\x30\x3b\x32\x0c\x24\x0a\xb3\xc1\xbb\x54\xdd\xc7\x6f\x55\xda\x7b\xe7\x94\x12\xcb\x2c\x1c\xd3\x59\xa8\x87\x6d\xad\x05\x56\x9a\x9e\x6e\x73\x4b\x73\x6c\x2e\xe2\x85\xd6\xe1\x9b\xa5\x2d\x47\xb2\x3c\x39\x79\xf1\x0d\xd8\xa0\xc7\xee\xd3\x35\x7c\x37\x4e\x41\xe0\x94\xc8\xa6\x2d\x2f\x08\xf3\x24\x21\x21\x0b\x82\x30\x04\xbb\xc9\xea\x99\x3e\x2f\xa2\xbc\x42\xb0\x19\x6d\x38\x37\xe3\xeb\xbd\x39\xaf\x85\x57\x48\x3c\x04\x80\x9d\x2f\x1f\x2e\xda\xf4\x89\xf4\x1e\x41\x96\xc5\xf8\x32\x28\x33\xeb\x55\x42\xe3\xe1\x5b\x56\x62\x48\xc3\x96\xe6\x93\x6a\x90\x1b\x50\xef\x52\x77\x8e\x08\x3c\xb3\x44\x3c\xda\xee\x6e\x9e\x83\x0c\x66\xb6\xac\x60\x4f\xed\x53\x88\xd2\xa0\xd8\x49\x4f\x1e\xb2\x7b\xe0\x1d\x07\x2f\x10\xc9\xe3\xba\xcc\x33\x9d\x0d\xd6\x0b\x39\xbc\xe5\x6d\x06\xaa\xc0\xf8\x5c\x50\x86\x59\xf4\x00\xe8\x3c\xd0\x6b\x0e\xb2\xd7\x1e\x14\x83\xe4\x29\x29\xf8\x24\x89\x8e\x05\xd3\x27\xd1\x9d\xfa\xcc\x7e\xab\xb5\x52\x70\xf9\x3f\x4a\xcb\x21\xb4\x6c\xaf\xa2\x42\xcf\xeb\x4c\x79\x27\xb2\x0a\xdc\x0f\xef\x4b\x71\xb9\x51\x54\x87\xe1\x7d\x1c\xf9\xa2\x59\x43\x3d\xea\x96\x5a\xbf\x4b\xab\x0f\x1f\x06\xa1\x80\x36\xd2\x14\x23\xcc\x7a\x7d\x57\x42\x01\xec\x00\xa6\x9b\x54\xb3\xda\x75\xe1\xcb\xb2\x5e\x3e\xb6\x6e\xf5\xc7\x1f\xc3\x94\xd6\x8a\x51\x49\xbf\xb1\xab\x30\xf3\x2b\x3d\x31\x2b\xc9\x6f\x6b\xdd\x5f\x79\x54\xeb\xcd\x79\x05\x07\xc3\x11\x20\xe3\x4c\xbd\x65\x0c\x54\x32\xd5\x68\xad\x90\x19\xf3\x25\xd1\x79\xc0\x40\x2b\x37\xe2\xfd\x5d\x11\x03\x5c\xfd\x88\x80\x75\xb3\x19\x1d\x62\x6f\xc5\xc5\x89\xbd\x04\x5c\xaa\x7f\xae\x82\x12\x99\x9d\x9b\x9a\xf3\x4b\x9a\x1f\x6b\x76\xce\x05\x15\xa5\xf3\x78\x87\x2e\x22\x53\xd5\xb3\x60\xad\x51\xbf\x73\x46\x04\x72\xac\x11\xe1\x6d\x8d\x6d\x6b\x12\x2d\xb4\xbc\x49\x8c\x88\x23\x96\x57\x6f\x33\xad\x50\xcb\xa7\x3c\xb4\x18\x6d\x2b\x6b\xa6\x15\x03\x9d\x98\x7e\x1f\xef\xd5\x55\x7f\xdf\xf7\x7b\xe4\xc5\xe3\x0c\x75\x86\xe5\x96\x6a\x42\xd2\x9f\xe4\x9d\x01\xd2\x7d\x14\x5a\x07\x87\x21\xcd\x22\x59\x02\x46\xe0\x8e\x96\x6b\x3f\x13\x6f\x89\x18\x08\x92\x9f\x6e\x4f\xa4\x99\x52\x09\xbe\x5a\x36\xf7\x62\x9f\x25\x4f\x63\xbf\x82\x2a\x60\xa7\x1a\xfd\xa9\xa5\x4a\x28\x61\xe1\xcd\x05\xc4\xa0\x49\x74\x2f\xc8\x6a\x59\xc1\xd6\x7f\x84\x4a\x74\x95\x62\x35\x52\x4a\x69\x58\x73\x97\x7d\x92\x05\x8c\x9b\x95\x86\x67\xfd\x8b\x80\xe0\xec\x35\xae\xdd\x3b\xf2\x9e\xf6\x37\x8f\xbd\xfc\x0b\x19\xe7\x63\x67\x35\x66\x56\x04\x3d\x40\x39\x3a\x73\xec\x0f\x66\x0a\xaf\xdd\xe2\x79\xa0\x74\xb7\x2c\x1e\x5b\x2d\xd0\x15\xb7\xb4\x96\x0f\xbc\x01\xc2\x0a\x38\xe8\x03\x7a\x41\x28\x2c\x9b\xa9\x0c\xde\xa5\x8c\x7b\x58\x56\x63\x21\x6c\x30\xcf\x1c\x29\x5b\xb2\xe2\x61\x98\x78\x45\x51\x18\xb6\xe8\x40\x33\xb0\x57\x53\xa1\x83\xc0\xf5\xec\xb1\x4a\xae\xc2\x16\x1c\xd5\x7a\x6b\x12\x95\xae\x3b\xb5\xb1\x33\xb6\xce\x4d\x06\x57\x6e\xf1\x64\x00\x69\x62\xe7\x20\xd5\x21\x06\x37\xe4\xc5\xfb\x35\x6b\xc8\x6f\xe9\x47\x74\x9d\xdc\x4a\xfb\x4a\x87\x99\x3d\x97\x7f\x5e\xdf\x2c\x11\xab\x83\x27\x35\x2f\xe9\xd6\x3b\x43\x80\xe0\x7e\xfb\x44\x22\xc1\x98\xe9\x83\xf8\x48\x0a\x4e\x60\xc5\x5e\x7c\x5b\x48\xab\x24\x06\x57\x42\xd4\x5a\x9c\x81\xfd\x37\x9a\xc3\xd0\xb6\x0e\xd0\xc0\x6e\xcf\x50\xa6\x55\x95\x74\x0c\xb3\x01\x07\xac\x11\x39\x5c\x4f\x2d\x11\x88\x85\xbd\x6f\x72\xd7\xeb\xc7\xad\x05\xbb\x3b\x50\x09\x20\x1f\x84\xe9\x9c\x12\xf2\x1a\x56\x7a\xd8\x17\x97\xdc\xa7\xf1\x21\xf2\x04\x36\x82\xb5\x61\xd4\xb0\xb0\x52\x9a\xd8\x46\xc3\xc7\xef\x9c\x64\xc0\xf5\x70\xca\xae\xbf\x41\x88\x28\x4b\x9c\xdc\x98\xfe\xfe\x03\x4c\x38\xbc\x0b\xbe\x24\xb4\x89\x3d\xd9\xde\xc5\xad\x99\x77\x8f\xf4\xf3\xb8\x6c\xb3\x0f\x8a\x71\x2b\xf3\x65\x3d\x14\xdf\xc4\x7c\xf9\x57\x4a\xe8\x84\xe0\x1a\xb8\x64\xee\x48\x8b\xfc\x03\xeb\xca\xd6\x4b\x74\x84\x4a\x29\x34\x34\x7d\x09\x31\x00\x28\x84\xcd\x15\xe1\x35\xe7\x3a\x04\xc8\xc4\x3e\xa7\xd5\xa9\x24\x5c\x85\x5d\xea\xb9\x86\xfc\xc5\x5c\x02\x64\xa0\xc1\x02\xf7\xc4\x7a\xa2\xa9\x7e\xb7\xcf\x1d\x5b\x9d\x80\x26\xa0\xd3\xc0\x1d\x95\x87\xa4\xb7\x35\xf1\xce\xec\x5c\xa4\xd9\x34\xe7\x97\xf0\x08\x60\x9c\xc7\x69\x91\x4f\x59\xdd\x31\xe6\x04\x05\x3f\x26\xb4\x9f\x29\x7b\x9d\x05\xeb\x98\xf3\x72\x91\xa9\xa0\x8d\x8d\xe5\x50\x22\x8b\xd9\x37\x27\x7d\x46\xc8\x35\x52\x81\x09\x39\x78\x2d\x32\xac\x35\xba\x87\x2c\xf6\x71\x3c\xeb\xf6\x70\xd3\xb3\x16\xbf\x04\x4e\x40\xaf\xe6\x50\xe1\xc1\xc1\x14\x88\x48\x5a\x23\x95\x16\x42\x73\xdc\x0a\xaf\xc6\x0c\x46\x09\xb7\xdf\xd3\xf5\x39\x03\x76\xa7\x2d\x76\xd6\x06\x97\x5e\x37\xb2\xc8\x49\x2b\x78\x05\xc4\x80\x7e\x95\x27\x82\x7d\xac\x07\xe2\x24\x84\xed\x1f\x1e\x8a\xa7\x14\x4b\x9f\x90\xce\xf5\x19\xf8\x9a\xd9\xe7\x8c\xd1\x28\x4f\x7b\x98\x1c\xba\xf8\xb4\x1a\x7a\x25\x0f\xcc\x4c\xfb\xee\x9c\xee\xb9\xb2\x8b\x8d\x10\x7e\x5a\x12\x42\x83\x45\x5d\x21\x90\x06\xbf\xa9\xc9\x8d\x47\x4f\x6a\x9b\x00\xb5\x2e\x12\x5c\x7b\x4e\xfb\x75\x58\xdd\xf6\xcb\x5f\x26\x3a\x6b\x9f\xf9\xdd\x12\x0d\x9e\xf9\x45\x70\x03\xfd\xe8\x78\x3d\xb2\x00\x0e\x5c\x07\x94\x93\x2a\x0b\x31\x5f\xbe\x3f\x7b\x2b\x17\x8e\xa7\x41\x97\xd9\x61\x4b\x66\xf0\xf8\x7e\x1a\x97\xe7\xe7\xfa\xb1\x85\x2e\xb7\x86\x60\x74\xfc\xb0\x97\xf7\x03\xa8\x25\xa7\xd6\xf4\x62\x67\xeb\xa7\x9e\x21\xda\xbd\x22\x08\x96\x47\xf0\xc3\xbc\xc4\x9f\xdb\x1f\xfa\x53\x90\x65\x4a\x13\xe3\x9f\xde\x93\x32\x4b\x81\xc2\x3f\x1e\x0e\x49\x17\x35\xec\x98\x9b\x37\x4e\x11\x7e\xc6\x87\xfc\x27\xfd\xfa\xf9\xfc\xd8\x2b\x80\x61\x85\x35\x6c\xfd\xba\xe0\xae\xe7\x2f\xca\x79\xfb\xbc\x22\x66\xae\xdb\x48\xec\x83\xe0\x71\x68\x6a\x87\x24\x66\x09\xa8\x00\x34\x81\xcb\xf8\x29\x49\x1d\x73\xc4\x2c\xf0\x28\x07\x9a\x88\xb9\x6a\xf0\x87\xbd\x22\x58\x8a\x6d\xc5\xc6\x82\x90\x9a\x35\xc6\x01\xaf\xad\xa9\x70\xef\xdb\x9e\x1b\x6d\x01\x45\xb0\x5b\x45\x22\xf3\x19\xca\xeb\x27\x36\x62\x4f\x62\xdf\x48\x8d\xbb\x01\x16\x58\xd2\x66\x0e\xe5\x90\xf1\x68\xe8\x10\x12\x0d\x42\xcd\x2c\xa4\xef\x4a\xc8\x7a\x45\x62\x6e\x83\x3c\xcc\x9e\x7a\x44\xee\x43\x6c\x0e\x39\x15\xf3\x0d\x6a\xb8\x15\xf5\xca\xea\xd9\x8c\x4d\x82\x7b\xb8\x98\x28\x19\x47\x8c\xde\x79\x6a\xec\x0a\x7d\xe9\x65\xaf\xb1\x7b\x04\xb0\xcb\x00\xe9\xf9\x8c\x43\xe9\xa5\xe0\x7d\x2c\x0c\x2e\x36\xb3\xf7\x64\x1b\x1d\x07\xb1\x5b\x24\x3a\x28\xf0\xd1\xb5\xba\x55\x33\x7b\xff\xf2\xd3\x8c\xfc\xc1\xb2\xd8\x47\xf4\x92\x63\x46\x49\xe6\x68\x53\x85\xac\x00\x24\xbd\x7d\xde\x00\x20\x9c\x67\xbf\x51\x69\xf5\x51\xe2\x49\x19\xbe\xfd\x2c\xfa\x48\x07\x2a\x1d\xc2\x4e\x1e\x5e\xbb\x95\xef\xf2\x4d\x69\xef\x85\x70\x81\xf7\xb0\x5b\xdb\xeb\xa0\x0d\x21\x4d\xac\x31\x21\xd4\x04\x38\xd7\x6f\x95\xd8\xbb\x9b\x14\x8f\x60\x53\xde\x58\x33\xec\x78\xf4\x93\x67\x92\xc9\xee\x42\xee\xdb\x7a\x01\xc0\x46\x0f\x6e\x2b\x0f\x6f\x6a\x69\xc6\xee\xd2\x9f\x44\xa3\xf2\x82\x1d\x72\x6a\x8a\xe0\xcd\xe5\x6f\x66\x2f\x45\x66\x40\x99\x09\x5c\x00\x1f\x43\x59\x42\x28\xf4\x1c\x20\xf2\xfc\x8a\xd1\xfb\x4c\x84\x35\xc4\xc6\x18\x87\xed\x9c\x86\xa5\xd6\x9b\xcd\x50\x1d\x1e\xd8\xb3\x50\x04\x73\x58\xf2\x3d\xea\x33\xd5\x47\xe3\xc9\x4c\xab\xd7\xe1\x13\xbc\x0a\x1f\x5c\x06\x8d\xc0\x4e\xc5\xc9\xe0\xd2\x2a\x9f\xe7\x35\x44\xaf\xa7\xfc\x2f\x51\xf5\xc2\x0b\xaf\x97\x13\x1f\x72\xd3\x4e\x81\x2f\xc7\x3b\xb5\x66\x58\xeb\x8f\x90\x48\x0c\x5a\x48\x32\x1c\xf9\xaa\x5c\xd5\xea\x04\xce\xd2\x89\x03\x84\x33\xb2\xcb\x64\x76\xbb\x5e\xd9\x9a\xc7\x6f\xe9\xa1\x6b\x94\x00\x89\xac\x9b\x3b\x61\xa7\xac\xaf\xef\x94\xbb\xdd\xba\x39\xb4\x42\x7a\x3d\x64\xae\xfc\x23\xae\xf7\xd1\x6c\x6a\x98\xb7\xfe\xb5\xc7\xd8\xc9\x2f\x82\x20\xbb\x60\x17\x99\xbd\x87\x10\xd6\x94\x3c\xdc\x47\xf4\x06\x6f\x93\x68\x99\x6d\x7b\xcb\xa2\xc2\x5b\x14\xc6\x68\x31\xa1\xdd\x56\x34\x6d\x72\x2c\x2c\x8c\xfc\x1d\x7a\x5b\x39\x37\x88\x44\x6c\x62\x7e\xec\xf9\x29\xab\x1d\xde\xc8\x08\xe6\x09\x19\x4f\xb8\x3c\xe3\x9b\x4e\x4b\x97\x3f\x27\xb9\x41\x41\x3a\xe3\xf5\x21\xb6\x34\x5e\x2d\x6b\x79\xbc\x42\xe0\xc0\xda\xc9\x18\xab\x56\x2c\xcd\x28\x94\xb8\xc3\x23\xbe\xc3\xea\xa9\x5d\x5e\x91\x4e\x11\x96\x16\xaf\x74\x2b\xd9\x11\x49\xab\x9c\x6e\xd4\x11\x74\xc3\x4a\xe3\xf1\xd0\x86\xb2\x84\xbe\xbe\xa4\xa1\x7e\x30\xaf\x1b\xdd\x0a\x85\x1a\x33\x9a\x3c\xe6\xae\x94\x24\xdf\xbd\x49\x72\x4e\x4d\x56\x1d\x57\xad\xd3\xe2\x03\xbd\xbb\xe3\x1e\xd4\xfa\x51\xb0\x97\x11\x47\xbb\xd1\xaa\xec\x6e\x9b\xd1\xcd\x61\x68\x6b\xf1\xe2\x58\xef\xcc\x3e\xbe\x6f\x72\x2d\xf8\x34\x49\x36\x9d\xd6\x80\xfe\xa4\xae\xd1\x2a\x1d\xf8\x59\xee\x39\x33\x9c\xf4\x60\xcd\x49\xdd\xfa\x71\x96\x80\xf5\x58\xfe\x48\xce\x1d\x8b\x9e\x04\xab\x32\xfe\xa8\xb4\xbe\xb0\xc6\x82\xe1\x5f\x4d\xd7\x53\x0f\x78\x04\x7c\x56\xbb\xb4\xd4\xad\x9e\x9e\x42\x56\xdd\x2f\x76\x3a\x59\x94\x2a\x7c\x10\x33\x20\xb5\xae\x23\xb2\x6b\x34\x95\x1f\xbf\x32\x69\xc6\x28\x65\xac\xe9\xb9\xbc\xdc\x05\x84\x06\xe7\xc8\x0f\x18\x93\xd5\x95\x8a\xdc\x1a\x13\xf5\x99\xec\x4b\xa5\x86\x32\xac\x16\x36\xf8\x00\x7f\x86\x34\x89\xa5\xb4\x20\x88\xc7\x35\x0c\x3e\xe9\x05\x8b\xb0\x0a\x0a\xd9\x86\x54\xa3\x80\x20\x7b\x27\x7a\xc0\xde\x74\xdb\xa3\xf5\xa4\x20\x3b\x59\xe2\x67\xc3\x44\xa6\x95\x96\xb0\x6a\x77\x56\x94\xd3\x03\x12\x8c\x4a\x54\x79\x20\xaf\x87\x6c\x03\xef\x91\x17\x11\x22\x76\x56\x54\x4e\x95\x60\x0e\x5b\xa8\xb4\x93\x04\x60\xa5\x2e\x0d\xb2\x28\x36\x6f\x75\x6e\x93\xa1\x83\x34\x0a\x5e\x71\xfe\x10\x5a\xb2\x8f\x4a\xe4\x3f\xd4\xdb\x51\x29\x34\x53\xfb\x02\x51\x8f\x60\x8a\xf9\xe2\xe4\x56\xc3\x36\xbb\xb5\xfc\xcd\x8e\xc4\xd0\x07\x12\x6d\xa2\x85\x63\x05\xb9\x4c\x60\xf9\xa4\x08\xce\xfa\x98\x1b\x53\xdb\xcc\x44\x49\x33\x6b\x35\xf0\x2b\xf0\x28\xff\xd4\xbf\x01\x8f\x42\x70\x0d\x6b\x16\x30\x10\x02\xf8\x89\x10\xc0\x23\x8a\x22\xed\x77\x69\x0e\x00\x87\x7f\xee\xba\x24\x96\xc5\x7a\xf7\x2b\x1e\x91\x39\xf0\x80\x97\xd7\xa3\xab\x1e\xec\xe0\xa0\xa9\x22\x14\x04\x95\xdf\xc9\x79\x68\x8c\x05\xb3\x1c\x3c\xe7\x66\x19\x89\x94\xf8\x6d\x90\xa1\x07\x69\x02\x0f\xeb\xa1\x78\x5d\x04\xe3\x4b\xc0\x0a\xfe\x10\x6a\x44\x8f\xb4\x3f\xc5\xa9\xa0\xbb\x04\x7d\x14\xb5\x20\x1c\x52\x61\x67\xba\x06\xa7\xe2\x96\xa7\x36\x5b\xc3\x57\x5c\x87\x2b\x58\xfb\x99\x17\xc6\x89\x12\xe8\x69\x93\x60\x43\xc0\x84\xb0\x11\x01\x96\x10\x06\x22\xe4\x65\x1a\x5e\x42\x78\x05\x07\x4d\x90\x4b\x70\x2b\xcb\x7b\xc9\x9a\x0a\x5a\x18\x96\x1b\xe9\xd8\x9a\xc3\x31\xff\x7a\x0e\xbb\xd0\x03\xbf\xcc\xa3\xe5\x0f\x1e\xe0\xeb\x6c\x09\x08\x7a\x73\x7a\xc7\x1e\xe5\x63\x41\xaa\xf9\x90\x64\x7f\x89\xfb\xa0\x41\x5c\x28\xd1\x89\x4c\x41\xfa\x23\x46\x28\xa3\xd1\x6d\x6d\x7a\x8f\x71\xcb\x5b\xf5\xfe\x16\x0e\x57\x7b\x75\x06\x44\x98\xf6\xac\x91\x97\xb1\x1e\x97\xe6\x4d\x49\x79\xbe\x19\xb1\x96\x0f\xcd\xe5\x47\x81\xc7\xb5\xa2\x52\x0f\xdb\x5a\x51\x50\x6a\xe6\x0a\x89\x84\x6e\x87\x66\x90\x1f\x01\x69\x78\xb9\xfd\xf2\xb2\x78\x8f\x24\x2b\xf5\x96\xe6\x1a\x10\xb6\xbc\x04\x15\xc3\x3a\x6d\x88\x50\x13\x03\x22\xed\x2d\xdc\x96\x25\xca\xac\xc6\x3a\x48\x1b\xe6\x6f\xe2\x43\x68\xcb\x0d\xcf\x11\x14\x10\x07\x44\xc4\x8f\x2e\x68\xad\x5b\x12\x09\x37\xb9\xe8\x3a\xda\x97\x45\xc1\x82\xc0\x46\x44\xf3\x3f\x87\xa0\x58\xce\x3e\x9a\x07\x65\x5c\xbf\xc4\x43\x21\x56\xfc\x60\xc1\xc9\x00\xb9\xff\x93\x0a\xbe\x0b\xaa\xc7\x15\x00\x56\x47\x92\xfe\x88\x0e\x7e\xd3\x08\xef\x44\x96\x6f\x6a\x78\x67\x65\xcf\xbf\xd4\x04\x1a\x7e\xbd\xa1\x39\x5c\xbf\x99\x28\x0a\x6b\xc5\x13\x1d\x70\xcd\xbd\x66\x35\x64\xcf\x10\x28\x36\x47\x4e\x84\x1c\x3d\x1b\xdf\x03\x92\xcc\xd3\xd5\x7f\x09\x35\x21\xd5\xee\xfa\x3a\x82\x0b\x60\xbd\xbd\x5d\x42\x70\xb0\xf1\xe5\x65\xf2\x7f\xc4\x0f\x0e\x9e\x30\xf8\x25\xc4\x44\x89\x03\xf9\x04\xee\x5a\xc1\xb3\x56\xf9\xad\x1f\xaa\x64\x27\x90\xa1\x40\xe0\x43\xd5\xf6\x15\xf0\x31\x94\xdf\x6b\x0e\x98\xc3\x6f\x69\x23\x8f\x0d\x58\xd1\x94\xdd\x4f\x02\x07\xbe\x1a\x97\x22\x68\x12\x47\x43\x83\x40\x68\xbe\x49\x19\xa0\x80\x2e\x91\xe4\xea\xbd\xd0\xc4\xd5\x91\x53\x50\x6e\xb5\xfb\x72\x58\x0b\xdb\xbe\x36\xb3\xb6\x72\x8b\x26\xa1\x80\xfe\x56\x5b\x10\x35\x68\x04\xf2\x01\x72\x91\x43\x7d\xcd\x0a\x8e\xfb\x69\x4b\xf6\xd6\x90\x3f\xf2\x57\x23\x5e\x58\x87\x36\x16\x64\x4b\x90\x85\xb5\x21\x2e\x22\xf9\xdc\x85\xe8\xaf\x33\x0e\xe0\x83\x56\x68\x05\x90\x95\x56\x51\x38\x6e\xb1\x78\x6b\xb4\xeb\x8a\x7b\xf3\x9d\x07\x07\x16\xec\xc1\x91\x16\x6b\x07\x6e\xd3\x9e\xc6\x85\xbf\xb8\x54\x3d\xaf\x1f\x55\xf4\x24\x4f\x2f\x49\xfa\xdf\x24\x19\x06\x09\xc5\xb3\x62\x2c\x8d\x9a\x91\x1a\x96\x0f\x6c\x8c\x5e\x6f\x13\x45\xea\xb9\xd1\xed\x56\xc2\x07\xfd\x95\x46\xbd\xda\x1d\xcc\x41\x69\x0e\x0c\xc6\x5d\x4e\x5a\x1a\x8e\xd8\x2f\x21\x34\x78\x18\x0d\x45\x42\xd5\x44\x0a\xd8\x87\x62\x3d\x78\x1d\x7e\x41\xb3\x13\xcd\xe8\x6a\x1c\xfe\x1b\xc1\x30\x64\x67\x5a\xd1\x8a\x4f\x3a\x84\xed\x3b\x47\xac\xdd\x42\xf7\xd1\xc3\x76\xad\x7b\xe9\xd4\x43\xea\xbe\x8f\xac\xcf\x01\xc3\xda\x71\x34\x83\xbb\x31\x55\x70\xfc\xc2\x7e\xf5\x1f\xbc\x8e\xa5\xe1\x41\xa8\x7b\xdf\x16\x05\xa7\x83\x5b\xf3\x8e\xbc\x86\x68\x86\xfc\xe1\xc0\x07\xc3\x63\xbb\xfd\x89\x43\xee\x2e\xbf\xff\xfc\xad\xb3\xcb\x55\x78\xd0\xd6\xcb\x29\xa2\x76\xbc\x62\xec\x10\xd9\x75\xfe\xbe\x27\x60\x99\x75\xc3\xd3\x8e\x4c\x26\x1f\x81\x19\x90\xc3\x7e\xd2\x20\xd9\xc6\xda\x1a\x99\x53\x6b\x28\x22\xa3\x9d\xf1\x14\x94\xdf\xf7\xcb\xe0\xda\xaa\x4e\x00\x78\x9f\xf5\x1f\xd9\x18\xc8\x26\x1f\x42\x64\xff\xac\x1e\x1b\x6d\x86\x90\x32\xfd\x25\xaa\x87\x07\xbb\x7d\xd3\xde\x7f\xa3\x9b\xd0\x7f\x40\xcc\xcc\x7e\xb0\x73\xd7\x83\xfb\xbf\x77\x84\xaa\xf7\x56\xc3\x55\xba\xd2\xfa\xdd\x61\x8a\x32\xfb\x82\x56\x51\x15\xc2\xe3\x52\x52\xb0\x99\xae\x81\x00\x85\x7e\xc8\x99\xf3\x67\xab\x01\xb8\x56\x8b\x57\xea\x71\xd7\xc9\xf3\x28\x1d\x67\xe4\xd7\x12\xb8\x0f\x88\x7f\x29\xb9\xdf\x43\xe0\x35\x9b\x39\x56\x50\xf5\xcf\x6c\xe4\x63\xf0\xc5\x73\xf4\xa1\xe8\xf5\x0e\x43\x8b\xbb\x8a\x1f\x57\x08\x8d\x6f\x0f\x65\xd9\x69\xf5\xcf\x18\xd2\xef\x2b\x1a\xbb\x62\x7f\x38\x36\x64\x4b\xa2\x76\xe0\xad\x01\xed\x58\x05\x4e\x3c\x7d\xee\x5b\x52\xff\x82\x4f\x30\x18\xf7\x5b\x05\xc7\x04\xaa\x80\x5b\x2e\x8b\x43\xc0\x3d\x52\x12\x8e\xcd\x99\x1d\x5a\x1b\x19\x16\x83\x0e\x60\xbb\xef\x08\x41\x24\x5c\x04\x20\x12\x3d\xa9\x31\xa3\x78\x5d\x18\x8b\x9e\x5e\x3b\xca\x9d\x84\x72\xfa\x84\xb1\x54\xb0\x56\x65\x78\x38\xf6\x5a\x37\x29\xf6\x5b\x25\xb8\xdd\xe4\x90\x70\x46\x9a\xf9\xe4\xc4\x23\xb1\xb5\x28\xfd\x4e\xb4\x95\xfe\xd2\x50\x22\xf5\x83\x92\xd2\x0b\x64\x45\x25\xca\x33\xb6\xa8\xe9\xc2\x84\xde\x46\x28\x41\xbe\x47\x6a\x6c\x11\x07\x8d\xf4\xc1\x20\xb9\x2b\x5a\x67\x8d\x30\x7e\x2b\x60\x35\x4e\x0a\x19\x50\x79\x70\x67\xd6\x26\x89\xf3\x87\x29\xd0\x0d\xc2\x76\xe5\xe1\x36\xbb\x2b\x71\x49\x97\x6f\x6d\x77\x6e\xb2\xc4\xb2\xef\x5d\xba\x40\xa0\x7e\x99\x3f\x74\x7d\x9c\x31\xb2\x77\x42\x5f\x34\xe0\x48\x9c\x51\x03\x90\x68\x55\x35\x6c\xfa\x40\x10\xf4\xd5\xba\xed\x97\x8e\x3a\x46\x35\xfb\xaa\x07\xbc\x0e\x08\x47\x1b\xe2\x4a\xdb\xa1\x37\xf5\x0d\x94\x98\x64\x02\x4b\xef\xd2\x7c\x9d\xf1\xfa\x59\xc7\xe8\x6c\xdc\x12\x8c\x43\xe7\xf4\x60\xe1\x50\x9e\x89\x99\xa5\x8d\x8a\x22\x1c\xac\xad\x1a\x72\x96\x3d\x08\xd4\x9c\xee\xa3\x70\x0a\xf0\xb3\xf1\x61\x05\xa1\x2f\x06\x66\xfb\x39\x02\x49\xfb\x72\x47\xd6\x58\xe5\xbc\x5a\x9d\xb7\xd3\xf4\x58\xd6\x7e\xf2\xc4\x25\x5a\x74\x0a\x7a\x8e\x28\x0d\xcf\x1f\xf7\xc3\x04\xf0\x74\xf5\x71\x1b\xba\x18\x6d\x46\xb1\xab\x4c\x86\x49\xf5\x38\x14\x9e\xfc\x34\xa7\xe5\x4d\x0f\x4b\x8f\xe0\x18\x9e\xf2\x54\x90\x06\xe2\xcf\xed\x94\x33\xbd\x29\x6e\xf1\x3a\x4d\xb9\x9f\xd6\x37\xd7\x49\xd7\xaf\x77\xa8\xc8\x23\x99\x92\x57\xca\x08\xe3\x38\xf7\x7c\x69\xdf\xa8\xa2\x45\x5c\xb1\x0f\x81\x78\x29\x5b\xe0\x3e\x26\x88\x2e\x0e\xb4\x06\x22\x28\x81\x46\xc9\x7f\x82\xa4\x5c\xb3\xf0\x45\x79\x97\xb7\x95\x8b\xcc\x47\x61\xd5\x66\xad\xcc\x6b\xa6\x37\x06\x36\xb7\x95\x1d\xad\xc3\x3d\xc0\x07\x28\x6f\x82\xdb\x3d\x7b\xd4\xbd\xe4\xfc\xf1\x01\x16\xb0\xe4\x04\x76\x53\xf7\x24\x11\x2f\x93\x28\x77\x31\xd0\xa6\x88\xa7\x19\x53\xb8\x26\x61\xab\xbe\xb7\xcf\x52\xf2\x51\x77\xb3\x5c\xcb\x94\x7b\x21\x64\x45\xb6\xdd\xc9\x3a\x66\x31\x5d\x76\xa4\xfe\x7f\x87\xbd\x86\xb9\x5d\x22\xc5\xa4\xbb\x9e\x72\xb3\x1d\xc7\x76\xba\xaf\xb9\x87\x40\x95\xde\xb8\x90\x29\xee\x7d\x9c\x99\xc6\xe0\xa4\x24\x6d\x15\x5f\xfe\x3b\xfc\xac\x4f\xcb\x31\x91\xd4\x8b\xd8\x63\xd6\xf5\x69\xd6\x78\x9d\x5b\x3b\x0d\xd4\x0c\xc1\x8e\x99\x3d\xc7\xa0\xea\x6a\x15\x2e\x61\xef\x5d\xeb\x72\xda\xa5\x4d\xbf\x71\x35\x7b\xf8\x78\x89\x93\x4a\x62\xe2\x76\xef\x8d\xa3\x20\xb0\x5f\x89\xaa\xf8\xd7\x1f\xa3\xb0\xbb\xeb\xcd\x0f\x2f\xa9\x17\x45\x9c\x96\x43\x20\x1b\xe0\x5b\xe6\xe0\xc6\x20\x2d\x46\x53\x6e\xa3\x6a\x5b\x6b\x09\x8e\x0b\xdc\x3f\xf5\x25\x7b\x98\xb5\x5a\x7c\x7a\xbb\x6b\x9e\xa7\xc8\xd4\xec\x02\x4a\x72\xf5\xef\x27\xa7\xd1\x1f\xe9\x38\xd6\x46\x99\xd7\x6e\xaf\xaf\xae\x45\x2f\x81\x0b\x43\x42\xde\xa1\x12\x21\x1c\x7b\x5d\x66\x19\xfc\x88\x76\x08\x3f\x1a\xc4\xa5\xb1\x13\x78\xc8\x0b\x02\xbf\xff\x18\xd9\x5b\xee\x13\x56\xe4\xb3\x78\x31\xf3\xfb\x2f\x07\x3e\xe6\x79\x6d\xf1\xcb\x40\x92\x87\x3d\x96\xaf\x8b\x80\xe0\xce\x47\x80\x64\x44\xa0\x08\x58\x32\x43\x33\xb5\xc3\x80\xf2\x81\x2a\xf3\x16\xc6\xaf\xab\x7f\x7c\xf4\x80\x8b\x09\xdc\x8a\x9b\x6d\x6e\x5c\x8c\x7a\x52\x6a\xbd\xab\xcd\x89\x6e\xe6\xe1\xbb\x46\x20\x15\xa9\x0b\x5d\xc3\xcc\x3c\x11\x2d\xff\xa0\x3d\x16\x32\x3d\xec\xf3\x77\x04\x5c\x66\x46\xef\xa3\xf0\xfa\x59\xa5\xce\xb3\x75\x30\x2f\x67\xa5\x3d\xe6\xe9\x19\xec\x66\xe8\x66\x29\x28\x01\x61\x61\xa7\xc4\x07\x1d\x1f\x23\xa2\x0c\x1d\xaa\xdd\x2c\x91\x61\xe8\x97\x08\x62\x32\x23\x82\xb3\x04\x0d\xc6\xea\xc8\x53\x49\xc4\x5c\x2e\x0d\xed\x37\xb0\xe2\x5d\x3a\xe4\xcb\xf9\x30\x88\x6f\x78\xd2\x54\x1e\x99\x59\x7d\x7a\x13\x4e\x02\x6e\x0c\xf9\xf9\x30\x7b\x26\xbf\x74\xe0\x83\xf4\x34\xe8\x31\xe6\x49\xfd\x97\x46\xd2\x15\x09\x83\x59\x87\xa4\xfe\x73\xe6\x4a\xb0\xec\xbb\xc2\x9b\xe9\x99\xeb\x1d\x52\xba\x79\x09\xac\x5d\x27\x35\x43\x38\xad\x34\xcf\xda\x10\x47\x90\x62\xc8\xb7\xb1\x2e\x86\x7e\x9b\x35\x88\x0c\xab\xfe\x4f\x46\x40\x64\xe6\x86\xb3\x01\x5d\xba\xc1\x67\x46\x51\x81\xf2\xa3\xc9\x7a\x77\x19\x51\x32\xbf\xf2\xfe\x77\x9e\x2f\x22\x6b\xfe\xcb\x64\x80\x9b\x4d\xa7\x4b\x97\xd1\x6d\xd7\x13\x04\x9b\x97\xcf\xac\x02\xb6\x05\x6d\x8f\x91\x77\xb3\x7f\xea\xb5\xc5\xf8\xd7\x19\x07\x9e\xae\x33\x8e\x3c\xde\xd4\x74\x09\xdd\x49\xeb\x8b\x48\x9b\x39\x2b\x68\x8d\x05\xc6\xb6\xb6\x22\x37\x91\x90\x12\xda\x69\x5d\x8c\x6d\x38\xbd\x86\xa5\xc6\x11\x85\x8b\x86\x09\x96\x66\xad\xa9\xd7\x1e\x24\xc4\xdc\x85\x38\x60\x17\x84\x64\x33\xa2\x6e\x48\x91\x06\x43\x8b\x47\xb3\x46\xfa\x56\x97\x16\x39\x2d\x21\x0b\xae\x63\x9d\x67\x8a\x7b\x71\x2d\xff\xb6\x74\x69\xda\x93\x76\x26\x39\x49\x07\xe5\x68\xcb\x2e\x7e\x40\x9d\x4b\x14\xda\xb1\x22\xd4\x29\xee\x5d\xea\xde\x07\xb1\x56\x66\xa1\x21\xa6\xad\x74\x42\x5c\xd9\x6d\xfe\xf5\x49\xfe\xe3\x84\x7d\xfc\x04\xa1\x36\x06\xd2\x3b\x19\xe4\x1a\x97\xc8\x06\xf8\x12\x05\x87\x63\xd7\x32\x65\xd5\x93\x91\xe6\x22\xe2\x30\xb4\x2d\x29\xc9\x02\x29\xa5\x4a\xbe\x81\x19\x52\x95\x18\xc5\x72\x30\x08\x6a\x11\xe9\xe5\x79\xf1\x00\x66\xc2\xcf\x22\x44\x0c\x7d\x6b\xfb\x35\x32\x89\x32\x61\x90\x28\x62\xca\x71\xab\xfc\x0c\x5c\xbe\xa1\xd2\x7a\xf8\x44\x8d\x3e\x24\x45\x24\xe2\x6a\xa0\x04\xf0\xcf\xdd\x93\x3c\x9d\xcd\x47\x88\x09\x2e\x21\x96\x33\x0a\xf0\x6d\x51\xf9\x16\x0d\xfc\x09\x6e\x9b\x06\xa1\x59\x41\x1e\x39\xc9\x7c\x00\x60\xfd\x1d\xee\x46\x28\xee\xcf\x61\xe0\xf5\xd2\x59\xac\xa3\xfc\x6e\x8c\x43\xbb\x9a\xa5\x9f\xed\xb9\x45\xc6\x6b\x44\x9e\x81\xe0\x56\xb5\x6f\x4a\x5a\xcb\xab\x06\x62\x1a\xc2\x96\x08\x58\x59\xc1\xb5\xc9\xb4\x1c\x7a\xc7\xce\xb0\x1d\xa7\x3c\xa8\x69\x21\xdd\xc7\x9a\xe9\x6d\x00\x34\x21\x04\x8c\xb7\x62\xf1\xa7\x96\x80\x9c\x6b\x61\x08\x51\xf0\x71\x74\x19\x54\xca\xed\xa7\x76\xe5\xe6\xea\xcd\x06\x3b\xb0\x80\x23\x62\xb8\x46\x40\x1e\xb0\x9e\xfd\x24\xc3\x5f\xef\x43\x83\x83\x7e\xa4\x64\xa9\x90\x3a\x6e\x71\xa4\xc2\x1e\xbc\x78\x04\xda\xab\x9b\x46\x0a\x9d\x5b\x65\xaa\xbd\x40\xee\x77\x9c\x7d\x8c\x39\x3d\xf6\xf0\xdd\xd9\xcb\xb1\x57\xba\x93\xd2\x43\x9a\x0c\xa1\xf7\x90\xf2\xae\x41\x66\x12\x79\x76\x59\x33\xa7\xf0\x9e\x11\x73\x33\xfc\x26\x17\x4a\x5a\x45\xf2\x81\x20\x28\x6f\xe7\xb0\x40\xb9\xfa\x3b\xec\xd5\x53\x4b\xd4\x04\x4a\xc3\xcf\x25\x32\x73\x1a\xa6\x16\x00\x61\x55\xd5\xff\xae\x76\x08\xc3\xd0\x24\x06\x69\xeb\x25\x1c\xd0\xa4\xe3\x89\xc1\x8c\x1b\xd7\x7b\xc6\x67\xeb\x3a\x21\x6a\xe9\xb7\xdd\x14\xa0\x3f\x49\x00\x12\x44\x08\xb1\x0f\x47\x98\x08\x8a\xbe\xcf\xa1\x3b\x5a\x0e\x9b\xbd\xf9\xbf\xd9\x3f\xa6\x2c\xf8\x0d\xea\x82\x11\xe2\xdc\x1e\x9e\xa0\x7d\xf4\x58\xdf\xa6\x44\x19\x9e\xe4\xcc\x1e\x33\xfe\xae\xbf\xcb\x7f\xf9\xbb\x5e\x85\x42\x55\x7f\x95\xde\xfd\x3f\xc6\x0c\xfd\x95\x6d\x76\x04\xe9\x5f\x7a\x22\xb6\xd6\xfb\x0f\xef\xcb\xd1\xbe\xef\x6b\xc1\xf3\x69\xcd\x3b\xef\x11\xbd\xab\xa3\x0c\xdf\x20\x02\x78\x19\xa0\x96\xc3\x8d\x41\x54\xf1\xb7\xf7\x5e\x06\xe6\x53\xbc\x33\xd5\x03\xde\x39\x11\x87\xe8\x86\x1a\x51\x6e\xfb\x89\xbc\x1b\xfe\xf5\x8d\x2a\xd6\xa7\xd3\xf9\xe7\xa3\x96\x6f\xc0\xb3\xfc\x04\xde\xdf\xe2\xa1\xbe\xbf\x29\xdb\xf3\x4f\x08\x98\xeb\x83\xa9\x83\x06\x17\x16\x06\xe5\xe7\x8b\x80\x1f\xb1\x4c\xcd\xb4\x7e\x56\xf5\x01\x0d\xf8\x3b\x8e\x56\x43\xa2\x54\x8a\x36\x50\xa1\xe8\x7c\x12\x81\xc1\x45\xdd\x89\xfc\x52\x38\x39\xcd\x41\x5b\x5c\x9f\x84\xff\x2c\x77\xb6\xd4\xcb\x6a\x04\x6b\x77\x1f\xfc\x65\x7d\xbe\x7c\xe2\xb5\xfa\xab\x88\x56\x8f\xc9\xb0\x27\x6f\xe2\xbe\xec\xb2\xbd\x35\xe5\x42\xfa\x38\xbb\xe1\xd3\xb5\xb2\xac\x98\x78\xa4\x8a\x3a\x00\x21\xab\x00\x31\x5e\xed\xdc\x7d\x61\x0b\xbf\xcd\xaf\x12\xcd\x31\x5a\x83\x2c\xaf\xdf\x5f\x93\xdf\xa0\xd7\xf4\x62\xf2\xe6\x6b\x72\x9e\xc3\x6b\xe2\xbe\xa6\x50\x42\x30\x6b\xb8\xe8\xa8\x33\x93\x3a\x12\xa0\x08\x45\xc3\xd2\x89\x42\xc7\xca\x71\x6c\x2b\xec\x6d\xbe\x1d\x84\xf7\x69\xcd\x0a\xc2\x89\x9b\x5c\x30\x9d\x91\xb1\x0d\x7b\xf8\x0e\xfc\xd0\x99\xc2\x22\xc8\xc1\x0c\xc5\x38\xbe\xd8\xae\x01\x86\x28\x04\x0f\x31\x4e\xe1\x7e\x3c\x18\xf9\x60\x58\xb5\xd9\x3d\x63\xdb\x88\x27\x0a\x13\x71\xee\x22\x1f\xe5\xcc\x9a\xe4\x95\x87\xb1\x08\x5f\x14\xf1\x1c\xaf\x9c\xe8\x52\x32\x63\x53\x4b\xf9\xc5\xe7\x0e\x59\xee\x8c\x60\x7d\xa5\x7f\xe2\x16\xc1\x03\xbf\x8e\x22\x4c\x79\x20\x92\x1b\xba\xa7\x36\xdd\x45\x3f\x7c\xa1\x6b\xa9\xcd\x39\x2f\xcb\x0f\xc0\xae\x9b\x8b\x8b\x03\x6f\x94\xdc\xf3\xce\xcd\x0f\x03\x2f\x03\x5c\xa7\x7e\x5f\x92\xc6\xcc\xad\x43\xba\x7a\xe6\xc0\x6f\xf5\x5e\x1c\x88\x46\x3c\x70\x64\x0b\x34\x1f\x36\x0a\x8a\xdb\xfa\x2d\xff\xb2\xe0\x44\xc7\xb4\xd6\xe0\x19\xb9\xa7\xcf\x4d\x74\xd4\xc3\x3c\xaf\xea\x20\xb1\x5f\x0a\xf8\xdc\xae\x26\x10\x8d\x84\xba\x74\xf3\x9b\xd6\x2c\xc7\xef\x6f\xf1\x5c\xa7\xdf\x32\xe6\x20\x27\x21\xc2\xc0\x3f\x75\xbf\xc5\xd6\x74\x17\x06\xc3\xed\x38\x80\x09\xa6\x91\x03\xd3\x89\x3d\x0a\xe7\xa1\x57\xed\xea\xcc\xb6\x84\x41\x27\x1a\x65\xad\x36\x73\x32\xe6\x26\x55\xfb\x9b\xe3\xf5\x87\xa5\x35\xc8\x55\xfc\x4d\xce\x7c\x76\x6b\xae\x7c\x29\x5d\xd6\x16\x7d\x52\xb7\x47\x69\x5a\x9b\xa5\x69\x7f\x47\x08\x5e\xd7\xe2\xfc\x20\xe4\x7a\x7a\x77\xd5\xc9\x44\x1c\x32\xba\x36\x74\x6f\xb9\xdf\x6b\xf3\x01\x2b\x5f\x65\x7d\xdd\x58\x66\x2b\xa0\x86\x24\xea\xe7\x24\xb3\x9e\x76\xf8\x8d\x02\x4d\x54\xfe\x53\x6a\x99\x29\xd7\xea\x5a\xf2\x53\x5b\xd1\xc9\x45\x5c\x74\xa1\xb4\xd4\x8d\x2f\xaa\xbf\xcd\x06\x79\x6e\xe5\xe1\x90\x5d\x24\x7b\x7d\x04\xdb\xcc\x0a\xcb\x27\x51\x08\x41\x46\x45\xd8\x24\x8f\xde\xd1\xfc\xfc\x6f\x83\x88\x05\x0b\x43\x0e\x8e\x86\xdb\x63\x0a\xec\xbe\x17\x63\x20\x27\x96\x5d\x4b\x03\x31\xb9\xcf\xd3\x5a\x45\x47\x5c\x97\x1e\x3c\xcd\x49\xa6\xb5\x26\xb4\xd2\x7f\x49\x41\x6a\x42\x5d\x2b\xfd\x0a\x5a\x46\xbd\x42\x95\xfc\xa6\x5d\xcb\xe6\x77\x67\xbe\x7c\x14\xed\x9a\xa6\xc9\x51\x2b\x2f\xd5\x37\x27\xd2\x6c\x3c\x8d\xe8\xbc\x8e\x27\x27\xfe\x86\xda\x14\x60\x5d\xbf\xb7\xf6\xf2\xd2\xd7\x61\xc6\x38\xf9\x1b\x0f\xf0\x50\xbc\x1d\x84\x10\xb1\xf3\x70\x5e\x8f\x07\x57\x57\x9c\xcf\x79\xb8\x73\x1c\x83\x2f\xa4\xe8\x5b\x5b\xff\x1f\x99\x3f\xfe\xd1\xb6\xc9\x86\x76\x0f\x67\x81\xf2\x7a\xee\xb2\x37\xd6\xcc\x50\x42\x5c\x82\x2a\x64\x6f\x8c\x40\x46\xa5\x23\x9e\xac\x91\x86\xb8\x2c\x6b\x49\x27\x0e\x85\xcc\x0c\x99\x43\x67\x7c\x87\x1c\x31\xe4\x2f\xdc\x79\x23\x87\x12\x02\xd4\xe8\xf2\x43\xf9\x5b\x3f\xd8\x17\x26\x36\x31\x10\x08\xb3\xb7\x16\x3f\xe2\x70\x59\x47\x9e\xf5\xda\xb3\x88\x64\x27\x32\x92\x02\xec\x03\x8f\x99\x1f\x4e\x95\xf6\xb9\x1b\x3a\xad\xaa\xe4\x34\x87\x12\x89\x13\x64\xfd\x70\xe6\xbc\x9d\xca\xb2\x47\x67\xa2\x97\x31\x72\xba\xf0\x3e\xd5\xa5\x22\x40\x8e\xf3\x82\xba\x7d\x56\xc1\x47\xce\xea\xbe\x24\x3b\xe9\x3f\xe2\x86\xa0\xfc\xeb\x21\xce\x80\x16\xe9\x04\x0a\x35\x8d\x6c\xda\x11\x30\x35\xbd\x9c\x2a\x8c\x80\x04\xd1\x84\xce\x89\x3f\xec\x17\xfd\x98\xb0\x0e\x81\x81\xf6\xd0\xad\xa4\x39\xc8\xb2\xf3\x6f\xcb\x96\x9e\xab\x5b\x3b\x80\xb1\xca\x88\x84\x7c\x06\xe7\xde\x0a\x7e\x75\x10\x9f\x58\xd7\x0b\x9e\xe4\x5d\xe5\xa4\xb8\x3e\x50\x89\x5e\x42\x0c\xe1\x1b\x18\x5b\xe6\x8f\x08\x16\xe1\xe9\xe6\x7f\x6c\x3a\x23\xe8\x58\x6b\x22\xce\xfa\xd1\x5e\x15\xd0\xfd\x78\xdc\x0e\x1f\xba\xad\x2f\x52\x86\xc0\x35\x10\x65\x88\xf4\xa1\x68\x03\xdd\x08\xa2\xb6\xa5\x19\xda\xf9\xf9\x0c\x28\x51\x03\x93\x9d\xf6\x85\xdc\x6a\x6c\x3c\x2d\x81\x8d\x06\xae\x85\xfb\xb6\x66\xb6\x43\x98\xe0\x1b\x3d\xaf\x39\xb8\x44\x9a\x5a\x55\x4f\x9f\x97\x63\x89\x06\x1a\xc4\xfa\xb8\x34\x88\xf6\xe2\x44\x71\x51\xbf\xac\x59\xaa\xe7\x0e\x61\x39\x5a\xa7\x28\xd9\xd1\x2c\xad\x6c\x6d\x11\x76\x99\xad\x8e\xd6\xac\x5e\x31\x4a\x67\x8a\xd1\x82\x53\x62\xe4\xde\x70\xf7\x13\x89\x82\xe7\x22\x1c\x6f\x66\x08\x1d\xf4\x10\x21\x95\xcc\xfb\x69\x8a\x2a\xf0\x32\xa7\xe8\x06\xf4\x61\xb2\x86\x05\xef\x48\x77\xfd\x70\xbc\xa3\x58\x0d\xaf\xb2\x80\x22\x74\xc8\x5e\x02\x03\x63\x6d\x95\x76\x59\x9d\xa9\x10\xae\x6f\x2b\x64\x61\x68\x5e\x0d\xef\x71\xfd\x22\xb3\xcb\x2d\xb1\x8c\xf0\x71\x73\x63\x5f\x99\x73\x89\xa6\x20\x61\x14\x17\x32\xa1\x09\x35\x35\x3b\x84\xe6\x55\x82\x47\x5e\xcb\x6f\x88\x66\x9f\xe1\x52\x3b\xa2\xdc\xd0\x1f\x28\x3c\xe6\x46\x43\x02\xe8\xc2\xd3\x68\x0f\xa7\xef\xf1\x74\x40\xb2\x1b\xd2\x1c\x9c\xa5\x55\x42\x41\xb0\x74\x5e\x00\xeb\xe9\x78\xd7\x48\xca\x3f\xc8\x9e\x3f\x2e\xe2\x6a\x40\xf1\xf6\x9e\xc5\x71\xc5\x86\xfa\x27\x6f\xc3\x65\xdd\xa3\x93\x8d\x20\xa2\x94\xda\x69\x58\x3f\x69\x2f\x6d\xb0\x1a\x38\x25\xe0\x90\xb3\x0a\x18\xc3\x99\x69\x86\x9b\x08\x25\xc8\xa5\xf9\xf5\x39\xe1\x01\x11\x12\x09\x26\x77\x8b\xfa\xb8\x04\xe2\x28\x94\xf4\x1b\x3f\xa9\xd1\x94\xd2\x12\x1c\xbd\xc3\xab\xcf\x23\xac\x86\x55\xa2\xfb\xdc\xa1\x2f\xaf\x06\xb4\x41\x69\xca\xab\x30\x47\x18\xce\xf3\xfb\x6a\x75\xd5\x8d\x90\x41\x8f\x31\x8e\x40\x68\x19\xae\x5b\x9a\xe0\x0b\x6c\x78\x01\x68\xe7\x97\x72\x47\xcc\xfc\x65\xb4\x33\x64\x54\xaa\xa6\x9c\x2c\x8b\xb6\x92\xf3\xfa\x7a\xbb\x47\xef\x70\xb0\xc7\xa2\x25\xcc\x9e\xe8\x54\x86\x3f\x6e\x6c\x47\x83\xdc\x1d\x09\x51\xc2\x9d\xb2\xb4\xa7\xf5\x4c\xc8\x06\xf2\x6b\xfa\xbf\x2b\x1c\x9f\x32\x33\xcd\x26\xc1\x02\x3b\xd6\xdb\x42\x01\x12\xac\x25\xd6\x17\x07\xf2\xf3\x81\x4f\x25\x9b\x67\x03\x00\xcf\x0d\x77\x0c\x73\x09\xe8\xf9\xd3\xa8\xcf\xd8\x92\xab\x4b\x80\x68\xe3\x25\x38\x8d\x19\x35\x78\x6c\x37\x97\x09\xad\x5b\x66\xc9\x98\xed\xcd\xbf\x06\x5c\xd2\x73\x83\x4c\x8b\x3d\x89\xb2\xc4\xd7\x0b\x9e\x24\x6b\x9b\xf2\x67\xb1\xb1\x5c\x0e\xfe\x22\x44\xe9\x25\x96\xd2\x39\x45\x4f\xc4\x0e\x64\xe7\xa4\x17\xf4\x07\x21\xf3\x42\x22\xf1\x5e\x58\x9f\x7e\xca\x9e\xc9\x8a\x4e\xe8\x07\xa0\x8e\x45\x19\x9b\xa0\x4e\x0b\x5c\xe5\xf1\xbb\x93\x96\x2a\x77\xf0\x20\x3e\xa6\x0e\x4c\x73\x3b\xf8\x05\x3c\xaa\x67\x1c\x85\xc5\x0b\x5c\x53\x33\x88\x7a\x02\x6b\x89\xf7\xdb\x39\x4b\x3e\xc0\x1d\xc8\x25\x5d\xd4\x35\x50\x7a\x07\x1a\x8e\xf7\xec\xd2\x90\xdf\xde\xd9\x0b\xf2\xcf\x7a\x53\x68\x16\xca\xe6\x3b\x9f\x89\xcf\xf5\x82\x41\x12\x5f\x6c\x69\xcd\x09\x37\x45\xa0\x3b\x66\x6b\x5e\x8b\x05\x36\x5f\x6d\x43\x60\xc7\x7b\x2b\xeb\x98\x4b\x40\xdd\xe6\x9b\x78\x84\x7c\x74\x49\x2a\x98\x9d\xfe\x22\x96\xe3\x78\x56\x66\xea\xda\xb1\xed\xde\x40\x3c\x58\xd8\x1a\xdb\xed\x99\xa3\xca\x2e\xe7\x93\x0c\xa6\x13\xb4\x6e\xc1\x9b\x0e\xe2\xc4\x8f\x50\x67\x3f\x4a\xf4\xd3\x0e\xa4\xa2\x40\xbf\xe7\x50\x81\x13\xbd\xe4\xa0\x1e\x73\x07\x65\x7e\x6a\x68\x06\x66\xcc\xe2\x35\x28\x10\x9b\x14\x02\xea\xee\x8b\xa2\x43\x19\x0e\x9e\x63\xba\xdc\x21\xee\xe6\x7e\x5f\x10\xb4\x36\xf8\x86\x4f\xd5\x23\xa6\x0e\x38\xf3\x55\xa7\x4c\x1f\x38\x63\xb4\xaa\x9c\x79\xcd\x4b\x6d\x9f\xc3\x50\x85\xc3\x5b\xf2\x8e\xbd\xa0\x4b\xa2\x95\xcd\xaa\x8d\xf3\x94\x79\x3a\x93\x35\x2a\x57\x1a\xe0\x29\x88\x15\x65\x4f\x0b\x01\x68\x53\xc8\xcf\x1c\x4c\x2a\x38\x64\x6a\xb1\xa1\xfd\xa8\x91\x43\xb3\xac\x6f\x3d\xbf\xc3\xe4\xf3\x8b\x01\x04\xbe\x60\x9e\xdb\x1b\xce\xaf\x23\x6f\xdb\xf5\xf4\xef\xb0\x35\x9f\x02\xa0\x66\xed\x7d\xbe\x98\x66\x80\x0b\xbf\x88\xb4\x8e\x6a\xbd\xe9\x6e\x1e\x79\xfe\x5b\x99\xd3\x8a\xb8\x30\x24\x5d\x09\x9e\x86\xe8\x87\x42\xa2\x14\x4f\x01\xf5\xb7\x2e\x7f\x7f\xb1\xe9\x78\x20\xe8\x47\x86\x5f\x9a\x7e\xbf\xac\x0e\x09\x76\x19\x43\x7f\xf8\x78\xf9\x57\x47\xa2\x3a\x28\x74\xca\xaf\x43\x97\xfa\x0c\xab\x91\xcb\x10\xf2\xa0\x99\x45\xea\x35\x07\x44\x4d\xd6\x86\x94\x2a\x83\x20\x58\xfd\xc4\x40\xff\x03\xf2\x21\xed\x2b\xd0\x27\x81\xde\xfa\x06\xf9\x87\x69\xa7\x58\x5f\x5a\x4f\xbc\x3b\x34\xdd\x1a\xbf\x8a\x41\xee\x36\x65\xa2\xe3\x21\x49\xfb\x23\x12\xed\x61\xa8\x7a\x48\x7b\x5f\xad\xe6\x14\xbe\xd1\xd3\x1f\xb8\x44\x08\x5c\x1d\xf0\x23\xcb\xa0\x97\xef\x48\xf4\x64\x81\x51\x0c\xdd\x30\xae\x39\x82\x23\xb2\x73\x74\xdf\x4a\xe2\x54\x3d\xb2\xf7\x27\x39\xb3\x17\x06\xab\x47\x4f\x4f\xac\x42\xeb\x71\x5b\x93\xc3\x6f\x50\xea\x30\xc7\x9e\x8c\x89\xc1\x9e\x20\xba\x0a\x33\x74\x2d\xae\xee\x0f\x6f\x05\xc6\x27\xdd\xec\xba\xa0\x54\x59\x73\x9c\x83\x77\xbb\x7f\x34\x06\x92\x91\x2a\xf1\x4f\xd5\x85\xe5\x19\x66\xbb\x57\x7b\x1e\xf8\x3a\xed\xa1\x80\x6d\x46\x34\x62\x61\xa2\xe5\x20\x7a\x12\xee\xd3\x3b\x4c\xef\xf2\x61\xaa\x95\xa8\x21\xcf\x60\x44\x94\xb4\xdc\x5c\x07\xf7\xe1\x9b\xf5\x88\x59\x21\xfd\xba\xd7\xe1\xde\x60\x27\x4a\xa6\x33\xb0\x38\xaf\x28\xd1\xdd\x23\x42\x76\x05\x5b\xee\x45\xf1\xb4\x3b\xb8\x9a\xfe\x04\x20\x1d\xa6\x59\xa3\x7e\xf4\x04\x3d\xb7\x02\x64\xb2\xe7\xd7\x8d\xcd\x42\x44\xb8\xd6\xc9\xbf\x37\x4c\x49\x0b\x3a\xe7\xea\xa0\xc9\x0f\x57\x40\xad\x62\xc1\x43\x01\xe7\x9e\xf1\x70\x41\x49\xbf\xfd\x82\x1e\xab\x20\x57\x1e\xe0\x1c\x88\xa9\x23\xc0\x51\x60\x39\x22\x1a\xe3\x22\x7a\xe9\xb8\x65\x9d\x44\xc8\x92\x99\xcf\x7b\x77\x56\x25\x44\xb5\x20\x32\x16\xcd\x3d\x5e\xb3\x06\xc1\x5a\x62\x1d\x68\x26\xb0\x0b\x1a\x36\xcd\xea\xa2\x0d\xb4\x91\x9b\xc0\xa3\x5b\xff\x2a\xa7\xce\x1b\xff\x22\xd6\x6a\xe7\x6f\x4b\xb9\x8f\x64\xc9\x9d\x90\x51\x76\x39\xda\x30\x9b\x95\xd2\xbf\x14\xc7\xf7\x73\xfd\xe6\x35\x30\x56\x3f\x77\x2a\xe7\x9e\x7d\x54\xc5\x1a\xce\x70\x75\xc5\x9a\xe2\x5c\xf1\x9e\x5b\xa9\xae\x71\xd4\xa3\xb5\xcb\x65\x31\x7a\x54\x67\x3a\x2a\x24\x6c\xcf\x8f\xda\x0b\xd9\x85\xf8\xd0\x58\x8f\x0d\x3e\xa4\xb4\xd8\xbe\xb5\x8e\xfc\x31\x6a\xfa\x5a\x8d\xf1\x56\x82\x23\x2a\x8f\xf2\x21\x5c\xb6\x67\xc6\x85\xa5\x58\x70\xbe\x81\x5a\x7d\xba\x19\x5e\x7d\x6b\x27\xe0\x61\x39\x99\x20\x8d\xb4\x2b\x28\xd6\xb5\x1f\x66\x29\x28\x00\xba\xd4\x10\x5d\x89\xc3\x3b\xde\x36\xda\x3b\xaf\x69\xf6\xa6\x98\x62\xd6\xe8\xbd\xb4\x5d\xb9\x74\x3b\x47\x86\x57\xe5\x30\xaa\xf8\x45\x16\x17\x39\x63\x09\x3e\x14\x7d\xfa\x1d\xe7\x27\xe4\xd6\xc6\x36\xa0\x7b\x3b\xfc\x63\xb0\x7b\x42\xe5\xc8\x5f\x7f\xfc\x0b\x0f\x44\x57\x71\xcd\x00\xce\xb5\x4f\x9f\x57\x17\xc9\xa3\xbb\xd7\x30\x83\xfa\x35\xb4\x4e\x31\xec\x80\xa4\xe1\xab\xa6\xa3\xef\xbc\xa6\xfb\xdf\x45\x3c\xcb\xff\x2e\x74\x44\xbe\x48\xf6\xf2\xc7\x03\x2c\xc4\xdb\xe0\x85\x32\x33\x73\xad\xec\xb9\x3c\x68\x22\xef\xfa\xa8\x4b\xd5\x90\x0b\x02\xf3\x85\x7d\x83\x56\xaa\x29\x54\x45\x0f\x9a\x48\x1c\x1d\xdc\x8c\x1c\xc1\xcd\xbe\x54\xe7\x75\xd3\xbe\xec\xbb\x05\x8d\x21\xb7\x47\x6f\x61\x6f\x60\xcd\xc6\x29\x39\xf0\x2b\x04\x3c\x59\xd8\xa4\x98\xc0\x92\x8f\x59\x7a\x1d\xb7\xed\x21\x70\x86\x21\xd8\x74\x94\x27\x4d\xab\x0d\x86\x36\xdf\x53\x5c\xfc\x2c\x50\x10\x21\x09\xb8\xb0\xf6\x4a\x44\x69\xfd\x0a\x74\x58\xcf\xc6\x2d\x0a\x19\x41\xbc\xc2\x4f\xed\x2d\x8b\xc9\xf5\x51\xf6\x26\xa4\x8f\xe2\xf4\x6e\x60\x00\x14\x23\x7e\x0c\xbc\xf8\x47\x58\x4b\x0c\xd4\xd1\xce\xda\xc9\x23\xbc\x9e\x8e\x23\xcb\x37\x8a\x6c\x2e\xbf\x91\x17\x6d\xb5\x07\xf4\x65\xc2\x9b\x86\xbe\x8a\xae\x01\xab\x59\x1d\x61\xa4\x4f\xb9\x27\x95\xcd\x75\x87\xf1\x89\x8b\x96\xbd\x7d\xa0\x0d\x66\x7b\x71\x49\xb3\x42\x75\x31\x00\x7a\xa5\xe5\x1f\xfe\xbd\xd8\xf0\x1a\xba\x3e\x5d\x6c\xb2\xb7\xce\x68\x03\x98\x2d\xf4\xed\x6e\xe2\x57\xed\x69\x56\x67\x77\x43\x6c\x7d\xd2\x80\xe8\x76\x67\x84\xb9\xc9\x4f\x39\x7a\x52\xfe\xd1\x52\x97\x2a\xa8\x33\xe8\xc4\xc7\x7c\xd7\x89\xa0\xa9\xba\x86\xd5\x26\x8d\x40\xb1\xc3\x91\xa0\x79\xfb\xf9\xcc\x6f\x59\xe0\x42\x30\x6a\xd0\x4a\x2b\xe3\x64\x82\xb7\xd6\x0e\xc7\x9e\xd0\x5e\xb4\x29\x90\xe1\xce\x30\xb4\x5c\xdd\xe2\x58\x16\x89\x3e\x6c\x95\xdd\x8c\xad\x16\x31\x1e\xb6\xaa\x9d\x0f\x60\xd4\xf9\xde\x67\xf6\x3b\xac\x99\x40\x5f\xaf\xb3\xd2\xf4\xc2\x23\x48\x43\x8d\x05\xc7\xa0\x89\x1c\xec\x49\xf9\xdf\x11\x09\xe2\x01\xb7\x5d\x3d\xc2\xd4\x6d\xfc\xe1\xf9\x96\x7f\x8c\x93\xdf\x02\x53\xb5\xa1\x9f\x60\x6d\x41\xae\x50\x3c\x84\xca\xba\x99\x29\x7e\xdd\x1b\x6e\xad\xac\xd5\x9a\x74\x99\x26\x08\x83\xba\xc0\x56\xd1\x3e\xf8\x9d\x71\x7e\x9a\x66\xaa\x0b\x0d\x43\x57\xb8\xc4\x76\x1a\x90\x0b\x64\xd4\x95\xd3\xe7\xe6\x30\x5b\x2e\x60\xad\x29\x7c\x65\xfe\xc3\x56\xe3\xd6\x9c\xae\xe6\x86\xbd\x8c\xdc\x5c\xa4\x6f\x83\xa4\x56\x09\xfa\x3d\x3e\x8b\xba\x1f\x48\xc8\x56\x8d\x32\x15\x62\x16\x74\x10\x13\x32\x26\xf2\xda\x76\xe1\x90\x17\x1e\xc9\x94\x8e\x58\x08\xe2\x72\x84\xd1\xe5\x97\x5e\x3d\x7c\xdd\xe5\x1f\x07\x5f\xad\x12\x6e\x1b\xb0\x36\xad\x98\x77\x78\xda\x79\x31\x33\xb5\x0c\xf0\x88\x28\x82\xc2\x4d\xd5\x7e\x4e\x69\xbb\x6e\x32\xdb\xee\x28\x27\x9a\xa0\x14\xe9\x85\xb1\x02\x4e\xea\x2d\xdb\x61\x1c\x5a\xff\xa1\x26\x8d\x33\xde\x98\xd1\xe4\x9d\xc5\x8b\xbf\xe3\xd9\x94\xb4\x9e\x78\x6f\xb1\xa6\x67\x2f\x72\xeb\x73\xdb\xff\x3c\x6b\x0b\xf6\x35\xe4\xe8\x1c\x40\x05\xbd\xba\x0a\x66\x53\x78\x5a\x07\x1f\x3d\xe2\x2d\x2b\x1e\x62\x4b\x0e\xce\xfb\x96\xad\x69\x8c\x8c\x6f\xc0\x61\x1d\xa2\xb6\x9d\xe7\xbb\xe7\x90\xeb\x06\xd5\xaa\x99\xbd\x7a\xda\xaa\x07\xd3\x59\x79\x75\x01\x93\xa3\x21\xc5\xcd\x26\x58\x80\xa6\xd0\xea\x23\xdd\x1b\x17\xd8\xc9\xa1\xc3\xc5\xbb\xcf\xf5\x2e\xb2\xc4\xc8\x62\xda\xf6\x1e\x5c\x0d\x5a\xb7\xf9\x18\xcc\x06\xfe\xbc\xd5\xa4\xdc\x94\x9d\x47\xe2\x56\xaa\x22\x67\xb6\x04\x54\xbc\xce\x03\xd2\xfe\xf2\x24\x6f\x01\x1f\x72\x7b\x89\x5a\x21\xcd\xdb\x47\x64\xf5\x26\x1d\x1b\x10\xec\x42\x56\x7d\x83\x36\xf8\xed\xc1\xd8\x92\xbb\x28\xeb\x8b\x18\x38\x80\xa2\x24\xd0\xe1\xb9\xf2\xa7\x1c\x90\x5e\xc0\x3d\x55\x5b\x15\xe5\x35\xdc\x77\xae\x9a\xf1\x2f\xe8\xd6\x28\xa5\xf5\x9f\xbc\x85\x5e\x42\x57\x90\xc9\x6a\xd6\x16\x7d\x35\x80\xdd\x75\xfe\xd6\x66\xae\x97\x04\xa5\xcd\x9e\x55\xa7\xbb\xb9\x36\x93\xf1\x7b\x6e\x29\xfd\xc1\x79\x78\x6c\x8c\x9a\xc9\x1c\x0b\xb8\xbe\x6c\x81\x20\xe3\xd9\xb3\xfc\x76\x43\xcd\xcd\xea\xbe\xdf\x95\x29\xa6\xcc\x2c\x6b\xe3\xa1\x08\xb1\xcc\xd4\x00\x56\x59\x89\x46\x75\xf3\x2f\x96\xce\x7d\x23\x4c\x95\x3b\x00\xc6\x70\x97\xe5\xb4\xbd\xea\x6e\xb3\x3a\x37\x12\x2f\x7a\xb4\x98\x28\xe6\xb5\x3e\xbd\x3d\x2d\x7a\x9e\x00\x7a\x9f\x76\xb8\xf4\xab\xfb\x90\x32\xad\x8e\x08\x58\x7b\xeb\xd2\x1a\x71\x95\x5f\x4e\xd0\xfb\x90\x35\xaf\x9d\x58\x34\x55\x4d\x92\xfa\x8d\xd1\x13\xbe\x1b\xf5\x7b\xe2\x80\x5a\xfd\x86\xda\x9d\x3f\x52\x34\xd9\xf4\xb1\x1b\xb0\xf9\xd7\x73\x55\xd7\x7e\xbd\xf8\xb1\x5e\x49\xee\x5a\xaf\x88\x01\x73\xec\x45\x38\x2b\x57\x34\x86\xb2\x46\x2e\xad\xd0\x2c\x6b\x33\xf0\x7a\x39\x6b\x2f\x3b\xd2\x60\x65\xb1\x73\x44\x5e\x5d\x04\xb7\xf1\x84\x32\x2e\xb9\x88\x4d\x57\xbd\x73\xba\x16\x6a\x38\xac\xc5\x73\xef\x5d\x77\x8d\xdf\x6d\x3e\x7b\x62\x61\xad\xf9\xb5\xf0\xf2\xac\xe8\xb4\xf9\x74\xe1\xeb\xb3\x22\x90\xa1\xab\x3b\x9c\xb5\x9a\x31\xa2\xc9\xcf\x51\x8e\xd5\xe5\xde\xf9\x84\xd3\x76\xa3\xf7\xbe\x6a\xef\x4f\x18\x98\x7b\x5c\xb1\xf7\x0b\x4e\xb4\x4f\xa4\xe6\xaf\xd6\xbe\xbe\x48\xd9\xdb\xc0\x02\x9c\x09\x80\xb0\x9e\x01\xda\x6c\x53\xd3\x68\xc5\x8c\xfe\xcd\xf6\xb3\xd9\x74\xcf\xac\xc9\xae\x8f\x2c\x12\x05\xd6\xef\x37\x49\x18\xce\xde\x6b\x38\xbb\xf7\x64\x47\xed\xf7\xc8\x6b\x6c\xcd\xbd\x8e\x27\x45\x3d\xcd\x6a\xb3\xf2\xc5\x48\xd4\x05\xa3\x16\x27\xad\x45\x81\xa4\x4b\x08\x9e\x2f\xd7\x48\xfc\x9b\xf5\x11\xbd\xc7\xbf\x5c\xbd\x6d\xeb\x29\x58\x5f\x3f\xe1\x70\x7c\x8d\xdd\xaf\xe6\x12\xd9\x49\x8b\xe3\x8e\x84\xd4\xc3\xa8\x3c\xba\xd5\x64\x94\x01\xb7\xb9\xca\xf0\x7d\x80\x3a\x1f\x04\x48\x16\x1e\x14\xf9\x72\x74\x5f\xa1\x3b\x7e\xf1\xf7\x93\xcb\xcb\x8b\xb8\xd8\x9d\xf2\xe1\x30\xc0\xfa\xe8\xa3\x00\x0d\x06\xdf\x88\x9d\x36\xaf\xd5\x52\x3d\x52\x90\x5b\xb1\x13\x73\x4c\x21\x52\x55\xf0\x6c\xf2\x4c\x6a\x21\xeb\x6f\x8a\x10\x3a\x50\x98\xe3\x95\x5e\x2a\xc3\xd9\x17\x7a\x84\x17\x72\x9a\x16\x0d\xff\x2e\xe5\x63\x40\x03\x29\xa6\x5b\x0e\x6a\x5f\xc3\x16\x45\x9f\x01\xce\x53\x77\x8f\x02\xe9\x97\xa8\x58\xea\xe2\x26\x5a\x19\x2f\xc5\xb5\xcb\x4c\x5c\xc3\xea\x2f\x3f\x33\xeb\x56\x46\xaa\x8e\x63\xfe\x08\x64\x67\x89\x6f\xdf\xe2\x19\xf3\x6c\x2f\x90\xf9\x17\x7b\x85\x56\xcc\xf7\x19\x66\x11\x79\x30\xef\x7f\x2f\xe6\xb4\x2c\x65\x78\x29\x20\xcf\xf6\xe2\x2a\x31\x24\x38\xa2\xd0\xeb\x2b\xe6\x85\x2e\x16\x9a\xb2\x46\xa6\x96\xc9\x03\xd9\x96\xfc\x87\xd1\x47\x7f\xa8\x17\xab\x5b\x22\x5c\x69\xc1\x38\xe7\x35\x37\x74\x9d\xd3\x03\xf9\x54\x2f\xd0\x63\x83\xd8\x24\xc3\xbe\x17\xcf\x8f\x8f\x7e\x01\x46\xec\xa9\x2c\xb4\xe4\x42\x1e\x21\x07\xf0\x96\x8c\xb7\xae\x73\xcb\x73\x34\xb9\xa9\xc1\x15\x64\x6d\x1a\x94\x3d\x5c\xac\x55\x50\xbf\x7e\xcc\x2f\x5e\xce\x7e\xb8\xd6\x80\x7e\x2e\x3d\xfd\x32\xae\x92\x88\x69\x7a\x9f\x4e\x67\x30\x43\x84\xc3\x74\xfe\x25\x71\x07\xa1\x5b\xdb\xcb\x26\xf3\xb0\x21\x08\xd5\xf2\x00\x8b\xc5\x1a\x58\x37\x79\xf0\xc8\x7a\xd2\xd3\xfe\x4f\x80\x46\x6b\x18\xbc\xb5\xe9\xfd\x0c\x28\xab\xdb\x29\xe8\x80\xc0\xef\xc5\xec\xd9\x2a\xa4\x2a\xfb\xe9\x6a\x22\x1c\x94\x21\x65\x94\x8f\x52\xda\x23\xa8\xc6\x87\xe9\x74\x41\x40\x8d\x8d\x99\x88\x98\x77\x6b\x2d\x8f\x7c\xdc\x1f\x7d\xcc\xe8\xa5\xb8\xb5\x78\xe8\x14\x37\xb8\x2c\x81\x3d\x5c\xb8\xad\x59\xf5\xb8\x96\x9c\x89\x37\x9c\xc9\x85\x58\xd2\x4f\x25\xea\x66\x49\xf0\x3e\x71\xcd\xa9\xf9\xf7\x16\xe4\x25\xaf\x32\x30\xa2\x1e\xa9\x7d\x4b\xc2\x17\x54\x20\xca\xa6\x3c\xeb\x2c\x42\x8f\xbe\xe0\x88\xb3\x95\x07\xbb\x61\x7c\x44\xe0\xdd\x2c\x0c\x6c\x36\x9b\x71\x7e\x30\x56\x3e\x29\xdf\x07\x53\x2b\xe6\xf7\xfa\x8f\x13\xd1\x04\xdf\x31\xf2\x3a\xbf\x07\xa5\xe0\xcf\x8a\x43\x98\xd5\x8a\x9c\xaf\x80\xf6\x5d\xf6\x32\x8c\x32\x7b\x3e\xaa\xc2\x1a\xae\x02\x17\x5e\x45\x9a\x65\x73\xa8\x09\xcd\x51\x29\x01\x66\x88\x8f\xd5\x79\xdb\xfc\x7d\xf1\xd0\xf2\xb9\xaa\xd9\x3b\x7b\x1c\xd9\x9f\xd6\xe9\xe9\xe5\x77\x9c\x21\xa6\x73\x7d\xf3\x23\x14\xa4\x5b\x37\xad\x32\x0c\x76\x1a\x0a\xd9\xdd\xa6\xb3\xd4\xb6\xf0\xbe\x5d\x91\x76\x36\x17\xa6\xc2\xcd\xc5\x2f\xa3\x36\x25\xa4\xe1\x87\x74\x14\x8e\x74\xe6\xb4\xb3\x57\x9a\x3f\x87\x46\xdf\x8c\x0c\x6a\x19\x0d\x7d\x38\x25\x8f\x1e\x9c\xf3\xab\xb0\xab\x8e\xe1\xe0\x5d\x91\x5b\x73\xf6\xb7\x41\xf3\xad\x32\xa3\x73\x7a\x06\xc3\xaa\x99\xd4\x68\x85\x91\x22\x88\x70\xce\xee\x69\xa4\xd9\x5c\xba\x40\x8d\x01\x9f\xe1\x5d\x66\xd2\xb8\x60\xa4\x7f\x29\xa2\x87\xe7\xf4\x1b\x4f\xa5\x75\x42\x9f\xe4\x1c\xc6\xb0\xc5\x0c\x18\x14\x71\x88\xab\x46\x68\x66\xbe\xa8\x80\xaf\xbc\xbf\x6e\x7e\x22\x1f\x3c\x94\x22\xaa\x7d\x46\xc3\x4f\x97\xc8\x51\x9a\xec\x55\x02\xba\x53\xb4\x40\xff\xc4\x13\x24\x6a\x62\xdf\x1c\x8a\x24\x28\x36\x0b\x9f\x10\xad\xf1\x9d\x16\x0e\x10\x3c\xdf\xfb\xf8\xfe\x93\x2a\xdc\x73\x8f\x21\x3f\xfb\xae\x12\x91\x58\x7f\x8b\x20\x85\xf8\x88\x42\x15\xcb\x59\x84\x35\x34\xa0\x9f\x10\xaa\xc7\x26\x11\x8b\xf6\x4d\x03\xe6\x97\xa8\x8b\x74\x3c\x3b\x7b\x51\xe6\xc2\xac\xe3\xe7\xac\xc4\xac\x67\x79\x49\xff\xe4\x69\x4d\xec\xc0\x29\x9e\xf2\xd0\x3c\xf5\x65\x7b\x42\x42\x9f\x5d\xbd\x67\xd9\xbb\x58\x6c\x1d\x07\x76\x3f\x9f\x45\xa1\x6a\xa7\xbe\xf4\xcf\x62\x9f\xef\xe0\x34\xea\xf3\xf0\x2c\xb3\x10\x8d\x65\x58\xbd\x17\x67\x06\x83\x37\xcc\xa0\x47\xe0\xa9\xf0\x69\x4c\x23\x9f\x36\x6c\x99\x8c\x8d\x73\xcc\xe3\x04\xce\xa3\x17\xac\xcd\x44\xc9\xb0\x67\x7e\x31\x6c\xfa\x69\x75\x0b\x77\x4b\xb7\xed\x13\x21\x3a\x3e\x9d\x43\x50\xf6\xd9\x0f\xf8\x5e\x3d\x51\xa3\xeb\x8d\x87\x4d\xdc\xe3\x9e\x99\x48\xf2\x4c\x85\x33\x1e\x79\x5e\xa5\x4b\xf6\xb4\xfb\xd9\xf9\xd4\x57\xfa\xb9\xd6\x1f\x1f\xb5\xfe\xd1\xf8\xc9\xcf\x35\x3b\xcf\xfb\x07\xd0\xd3\xec\xc6\xea\x01\x8a\x3f\x75\x66\xf7\xf2\x07\xe9\xab\xb8\xb1\x3f\xf9\x95\xe3\x78\x7e\xb2\x32\x69\x7e\xb2\xd4\x44\x7e\xb2\xe7\xed\xaa\x52\xff\x49\xef\x80\x38\xbe\x94\x15\xfc\x83\x76\x61\xd5\x20\x1c\x0a\xde\xe6\x85\x21\x2e\x63\xc8\x84\x14\x74\x81\x51\x1f\x94\xd5\x55\x32\x1b\xea\xd0\x29\xbf\x34\xe1\x63\x6c\xa6\x7f\x6b\x60\x60\x9c\x2c\xbe\xd9\x0d\xc5\x28\xda\x23\x4a\x75\x4c\x37\x53\xd1\x15\xdb\xfa\xe0\x2d\x06\xaa\x51\xac\x43\xb4\xe5\xe5\x28\xf7\x82\xa7\x4f\x9f\xf9\x3f\xc5\x1b\xe2\x08\x07\x7f\xd8\x0d\xc6\xe0\x25\x04\xdc\xad\x5e\x68\xf0\x7e\x33\x11\x41\xa1\xa3\xf7\xec\xf3\xb4\xe6\x80\x52\xc2\xb1\xd1\xf8\x8b\xd1\x23\x15\xcd\x70\xf5\x51\xc8\xc0\x14\xae\x50\x45\xe1\x4a\xab\xea\x29\x00\x20\x0b\xb7\xfb\x13\x5e\xd4\x02\xc9\xb9\x56\xf7\x00\xdc\xef\x13\x6f\x68\x41\x2b\xe0\xeb\x03\x12\xc9\x25\x1e\x3b\xd9\x8c\x88\x0d\xbd\x43\x88\x01\x8d\x2c\x7d\x43\x3c\x3e\xbc\x4d\xa6\x13\x1a\xae\xfb\x87\x81\xed\xb0\x28\xe0\x2b\xce\xcd\x81\x9b\xc2\xda\x7e\x6a\xa7\xe0\x4d\xa1\x2a\xc6\xe6\x10\x75\xbe\x8f\xb3\x47\x23\x09\xfa\x02\xdd\xbd\xd0\x7f\x47\x2a\x50\x6e\x83\xc5\xc8\xad\x06\x21\xa0\xe4\xb5\xdd\x02\xe4\xf7\x5b\x6f\x39\xf6\xa7\x0f\xa3\xfb\x6c\x43\xd6\xcd\x19\x95\x9a\xee\x9f\x5b\x4e\x7b\x03\x26\x95\xb5\xdb\x73\x03\x4e\x02\x55\x89\x5e\xa9\xb6\xba\x6c\xd7\x10\xb7\x8c\x31\xb4\xa5\x06\x9b\xca\x1d\x7a\x4b\x04\x2e\x03\x55\x19\x29\x1f\x66\x7b\x1a\xf2\xda\x4a\xbd\xd6\x28\xe8\x72\xe3\x6d\x2f\xe1\xe7\x2b\x43\xa9\x88\x34\x83\x86\x33\x6f\x52\x2f\xf2\x97\xb5\x4b\x3c\xa9\x94\xf4\xd1\x1e\x23\x53\xfe\x41\xb2\x26\x1a\x7e\x9e\xde\x00\x97\x3a\x09\xf0\xed\x8e\x5c\x75\xf1\x1d\x5b\xd9\x4f\x73\xdd\xd9\xbd\x99\x28\xdb\x3a\x5d\xfa\x2e\x4d\x17\xf9\x9b\x48\x4e\xe7\x0f\x8b\xb7\x97\xa7\x6b\x56\x83\x67\xba\xba\x3e\x89\x66\xd9\x71\x70\x79\x3a\x4f\xd4\x24\x08\x4a\x48\x9c\x76\x4c\x03\x36\x8b\x55\xa6\x3b\x85\x47\x97\x35\x89\x92\xab\xc2\xad\x5e\x3a\x5f\x4c\xb1\x30\x2b\xc2\xc9\xc0\xb0\x8c\x8c\x41\x28\x5d\xa1\x51\x7e\x5e\x5a\x0a\xaf\xaf\xac\x41\xd3\xa4\x48\x74\xa4\x76\x86\xe3\x64\x82\x08\x07\xa7\xac\xb2\x1a\xc3\x92\x4b\x8a\x60\xc9\x43\x5e\xf2\x6b\xcf\xca\xfb\xb7\x52\xb7\x0b\x9a\x89\xc8\x86\xef\x30\x83\x7d\x09\x4b\x5b\x7c\x02\xfa\xcb\xbd\xb8\x93\x63\xaa\x23\x22\xfc\xb9\x5c\x48\x2c\xda\x6e\xaa\xb6\xd7\x35\xc2\x27\x4c\x1e\x7d\x62\xfa\xde\x54\xf8\x9d\x9f\xca\x22\xbc\x09\x5c\xaf\xbd\x44\x46\xa6\xf2\xd3\x1a\x9d\x93\xbd\x83\x8c\x84\x11\x47\x13\xd2\x03\x6e\x74\xf9\x7e\x92\xa7\xcc\xe4\x04\xeb\xa1\x5e\xdf\x17\xb9\x95\xf6\x81\x4e\x9a\xa7\x87\x7a\xca\xf0\x47\xf3\x13\x37\x65\x51\x1c\x79\xc6\xd0\x76\xe2\x25\xcf\x81\xde\x9e\x32\xd5\x3b\xdd\x6c\xff\xdd\x25\xb7\x86\x31\x36\xdd\x92\xb0\xdd\xe4\xdd\xcc\xe9\xf7\x4d\x00\xc8\xe4\xa2\x8e\x71\xb7\x90\x30\x9d\x05\xe4\xb4\x2b\xe8\xb9\x9e\x2c\x0c\x9b\x38\x3c\xce\xd1\x94\x6e\xcf\x94\xbf\xfd\x94\xd3\x9f\x7d\xf3\xf8\xb4\xa5\x3f\x55\x87\x53\x7a\x2b\x9b\x17\x31\x2c\x7e\x77\x24\x22\x30\x41\x5c\x43\xa7\x02\x87\xa8\x40\xad\x49\x11\x72\xa0\x70\x96\x20\x69\x9a\x39\x24\xcd\x8d\x38\x57\x33\x83\x0e\x38\x79\x92\xa2\xac\x5e\xa2\x97\x13\x58\x18\x8d\x9d\x0a\x30\x27\xe9\xe1\x30\x75\x8d\x81\x4c\xd4\x29\x03\x9c\xc0\xe7\xc8\x1a\xd4\x13\xa7\x9d\x2b\xf0\xfa\x3b\x97\xca\xbe\xe9\x67\x08\x00\x9f\xb2\x3c\x76\x32\x0e\x92\x4d\x91\x89\x49\x21\x53\x62\x62\xce\xf4\xfd\xf6\xf2\xf8\xf6\x96\xcf\x78\x51\x69\x6e\x54\xb0\xfb\x78\x89\xfe\x32\x5e\x37\xc9\xd1\x53\x0a\xf8\x6b\x51\x94\x87\x5b\x7e\xae\xe3\x7e\x65\xe2\x34\xaf\xb8\xb9\xe3\xee\x7f\x5f\x24\x77\xfa\x03\xfc\x01\x69\x23\xba\x93\xab\x22\xf1\x85\x8e\xe9\xb1\x45\x55\x8e\x3b\xc8\xd6\xea\x39\x8e\x08\x27\xdd\xf9\xe9\xb0\xcf\x93\xb0\x91\x4e\xee\x3c\x69\x35\xe0\xe2\x18\x8d\x02\xf7\x14\x6a\xb9\x95\xe2\x9d\x76\xad\x67\x06\x88\x8e\xb5\x7a\x27\x83\x44\xce\x43\x56\xe2\x74\x88\xce\x15\xec\x99\x8b\xcd\x43\x70\x0b\xc7\xea\x4f\xd8\xc1\x05\x86\xf4\xa2\x43\x0d\xe6\xe2\xc7\x47\xaf\x8a\x4d\xb8\x8d\xf9\xdd\xab\x2e\x18\x11\x25\xc3\x79\x8c\xce\x1a\x89\x1d\x03\xae\x13\x83\x1c\x11\xc3\x38\x7a\x6f\x87\x27\x31\xe7\x35\x86\xe0\xc6\x39\x5d\x7d\x25\x89\xb4\xec\xb3\x07\x11\xd1\x46\x52\xa4\xaf\xc8\x78\xb3\xb1\xd8\x33\xf2\xa6\xc1\x63\xf0\x50\x4b\xc9\x39\x8e\x13\x93\x18\xc6\x7c\x34\x8f\xda\x98\x3f\x72\xe4\xad\xd0\xb2\xd7\x79\xf6\x20\xd0\x39\xe7\x33\x3f\xc5\x32\x1f\x33\xbe\xd5\xb4\xf2\x53\xb3\xd2\x1e\x6e\x49\xd8\x9c\x99\x42\xa3\x70\x04\x72\x70\xa0\x31\xdf\x2d\x84\x11\x63\xd9\x27\xf7\x6b\x6f\x86\x1f\x58\xe2\x33\x49\x9e\xc1\x08\xaf\x6a\xff\xc7\x48\xd4\xf1\x7b\xa2\xda\x19\xc8\x9f\xe5\xeb\x06\x7f\xfa\xb6\x1e\x37\x1d\xd9\xee\x49\xe4\x50\x3d\x40\x13\xe0\x3a\xfd\xf3\x95\xc2\x62\xbd\x65\xd6\x44\xd7\xd0\x03\xd2\x5f\x82\x62\xee\xf9\x62\x8f\xed\xb1\xb7\x30\x13\x32\x42\x09\xdf\x44\x16\xa8\xc6\xc2\x1c\x18\x2a\x1a\x26\x94\xc4\x98\x37\x6c\xed\xa4\xbf\x12\x73\xdd\x77\xdc\x27\x6d\x30\x15\xa1\x3c\xff\xc5\x30\xea\xa3\x6a\xbc\xfe\x81\x97\x23\xfa\xd0\xd6\xc4\x12\xf3\x15\x8d\xad\x4b\x89\x4e\x66\x3f\x32\xc3\xc3\x31\x30\xf8\x62\x4c\x64\x00\x45\x63\x45\x26\x40\x01\x27\xaa\x57\x11\x44\x51\xb5\x0f\x3c\x28\x24\x96\xa4\xa3\xea\x81\x8f\xbd\x80\x99\xad\xdf\x0f\x1c\xe8\x8e\x30\xc2\xb0\x23\xf6\xf0\xe1\x20\x1c\x6d\x77\xce\xec\xdd\x3c\x66\x8f\x16\x93\x89\x5c\x97\x93\xe6\xf9\x62\x06\x26\x4c\xe4\xc7\xf4\x51\x88\xd1\x8d\x07\xde\xc8\x21\xb5\x1f\x0a\x8f\xa8\x45\x8b\x3e\x42\x0c\xf8\x21\xe8\xdf\xa3\x90\xbc\xff\xb0\x27\xb0\x91\x39\x1e\x68\x2e\xeb\x67\x84\x6b\x14\x59\xf3\x2c\x2b\x8d\xda\xc8\xfc\x24\x2e\x74\x46\x45\x43\xd3\x71\x78\xbc\x38\xb0\x23\x28\xe9\x51\x1e\x5c\x19\x99\xab\xd2\xe4\x7c\x40\x14\x90\xbb\x49\x91\xdb\xf6\xc8\x0c\x12\x7b\x64\xaf\x43\x11\x6b\x53\x7c\x50\xfa\x91\x97\x08\x77\x7f\x84\x8b\xfd\x61\x5f\xfc\x9d\x8b\x79\xc7\x00\xba\x17\x8d\x2c\x2a\x86\x0c\x11\xc3\x31\xd3\xfa\x26\xd7\xf4\xa4\x29\xe8\xab\x5e\xae\x47\x8a\x18\xfa\x47\xfa\xa1\xb2\x22\x84\xe0\xdf\x8d\x59\x5a\x76\x57\x12\xec\xa3\x74\xeb\x81\x3d\x92\x26\xd6\x15\xf0\x6e\x01\xf4\xcf\x4e\x4d\xd5\x26\x71\x48\x29\x7e\xcb\xef\xcc\x51\xb3\x2f\xe7\x8f\x32\xbc\x82\xfe\xbf\xfc\x8f\x90\x79\x0e\xc2\x90\x41\xca\x03\x47\x36\x18\x82\x91\xe3\x07\xc4\x5c\x47\x2c\x24\x8a\x43\x69\x04\xd3\xc4\x63\xca\xff\xea\xde\x53\xcf\x36\xff\xf3\xbe\xce\xd9\x90\xf2\xf9\x9f\x7d\x9f\x8f\x60\x76\xfe\xcb\x3d\x57\xb0\x36\x1f\x86\x2f\x77\xee\x03\x90\x2b\xc8\xe9\x37\x36\x2a\xdc\x18\x5d\x70\x4d\x31\x42\xac\x43\x43\xba\x60\x13\xdd\x05\xe5\x94\x43\x6a\x19\x5f\x41\xbf\x58\xf9\xa2\x1f\x57\x26\xb2\xc8\xbc\x4e\xca\x37\x0d\xf5\xeb\x86\xa1\xc6\xbc\x44\xc0\xb2\xa3\x07\xe7\x08\x0a\x0a\x32\x1f\xea\x71\xeb\xc6\x72\xfc\x4d\x27\x65\xfd\x52\x28\x32\xae\xf9\x52\xdf\x17\xa7\xcc\xb0\xbe\x0c\x7a\xbf\x3c\x2d\xd0\xa2\x59\x74\xb0\xeb\x28\x59\xc0\xbc\x3e\xe4\xbe\xb3\xf5\xfd\x00\x56\x0d\x3a\x85\x22\x25\x62\x33\x7a\xcf\xb2\x63\x8b\x2e\x53\x8c\x96\x97\x60\xe1\xaa\xe0\xe6\xbf\x25\xd5\x68\x05\x0c\xca\xb3\xfa\x01\xec\xf4\x86\x9a\x96\xa6\x20\x0e\xa0\xe9\xa1\xaa\xc4\x7a\x62\x2e\x58\x99\xfd\x46\x7f\x09\x5b\xba\x83\x8f\xee\xc7\xa1\xe0\xb6\x2f\xc7\x94\xd6\xa6\x2c\x2b\x66\x69\x4b\x18\xcd\xc3\x2f\x6b\x96\x6c\x9d\xc5\xe8\xce\xe5\x01\x83\x20\xaa\xc2\x73\x7f\x25\xc2\xf0\xd1\x75\x65\x5a\x52\xee\xcb\xee\xd3\x74\xe8\xe1\xb3\x36\xd8\x24\x3d\xf8\x0c\xfd\x1a\xc2\x02\x65\xf2\xe0\xad\x6d\xe6\x1b\x1c\xde\x87\xcb\x3f\x62\xbd\xc1\xa5\xc5\x79\x59\xe0\x28\x55\x0e\xb9\xa3\x4d\x89\x2a\xbc\x98\x0d\x3a\x58\xfd\xc6\x24\xd4\xe1\x52\x3a\xfa\x70\xad\x1c\x3b\x37\x43\x2d\x6f\x58\xfa\x6d\x19\x3c\x6a\x64\xb8\x40\x5a\xe2\xac\x61\xa6\xe8\x85\x9d\x29\x2e\xd1\xb0\x5f\x41\x13\x1f\x3c\x8c\xdb\x9f\x0b\x98\x3c\x06\xb4\x91\x6a\x58\xd5\xa3\x2b\xbe\x04\x4b\xe5\x3e\xc0\xb2\x94\xa4\xf6\xb0\xcb\x71\xea\xdc\xd4\x20\x40\x22\x77\xfc\x0c\x96\xe3\x9e\x62\x5a\xd6\x8d\x7a\x79\x66\x8f\x6a\xb9\x0e\x55\x43\x15\x78\xff\xb9\x7f\xfa\xf7\xe0\xae\x56\x93\x78\xa8\x82\x3a\xe2\xeb\x34\xd3\x78\x4a\x3b\x71\xb0\x8f\x04\xe4\x52\xf8\x7b\xf5\xc4\x36\x3f\x9e\x0a\xa0\x99\x2e\xbc\xd9\x88\xae\xe1\x79\x60\x40\x4b\x86\x7e\x25\xd9\x38\xec\x9e\xc9\x6c\x43\xa5\x90\xc9\x80\x84\x05\x29\x90\x0f\x3f\xee\x7e\x1e\x90\xcf\xa7\xa3\x2e\xbf\x94\xba\x02\xa1\x75\x10\x17\x68\x00\x4a\xfd\x4b\x64\xd6\x43\x40\xd2\xe3\xae\x15\x07\x68\x58\x8d\x91\xc3\x1a\x30\x56\xd9\x4b\xd2\xaa\x50\xed\x89\x99\x6e\x7f\x09\xb2\x8a\x6a\xfa\x8c\x42\x73\x8a\x70\x06\x02\xcb\xb5\xa0\x67\x50\xc7\x51\x1e\x7d\xd9\x22\x20\x0b\x90\x55\xa7\x94\x68\xeb\x7b\xc4\x29\x0e\xd0\x8a\xf1\xe9\x12\x48\xd5\x2b\x70\xaa\x57\xaf\xc6\xc4\x50\xc6\x7c\xb4\xed\x0a\xcc\x34\xdc\x31\x40\xc8\xcb\xf6\xf7\x49\x03\x5e\xad\xfc\x45\xba\x6a\x83\xd8\x3a\x68\x95\xe3\x3e\x5f\x4e\x56\xd5\xa7\x7c\x40\xf6\x7b\x51\x1c\xe5\x40\x4d\x5b\x5a\xf5\x9f\x76\x91\xcf\xb6\x2c\x2a\x6c\x3f\x44\x45\xfd\x72\xae\xc8\xab\x03\x0b\x7d\xdc\x17\x7c\x24\x69\x78\xd2\xb0\x2c\x5d\xb1\x6c\xaf\xb8\x56\xdf\xca\xcd\x28\x85\xad\x0d\xad\x11\x61\x20\x60\x2b\x57\x5b\x2e\x6d\x69\x71\x8e\x60\xb0\x49\x05\x83\x18\xb2\x34\x9d\x86\xf6\x34\x66\x05\xa9\xc3\xe8\x3e\x09\xac\x73\xb7\x73\xc8\x16\x63\x48\x52\xa1\x1f\x72\x84\xfc\x0d\xf6\xc8\x5c\x6c\x94\x0f\xf9\xd1\x20\xac\xbc\x36\x8f\x56\x59\x03\xdf\x1a\xd0\x59\x34\x41\x6e\x5a\xeb\xaa\xe1\x16\xd8\x7d\x00\x5d\xe1\x2a\xd3\xe9\xf5\xfb\x7b\x6b\xf6\x0d\xa8\x0c\x56\xeb\xb3\x9d\xbc\xb0\xab\x59\x05\x49\xda\x0e\xea\x05\x73\x21\xe8\x2b\xd0\x40\x9e\xa4\xe6\x2d\x1e\xbc\x41\xd3\x07\xc5\x06\x97\x75\xe4\xc3\x97\x9a\x0f\xc2\x4d\x1e\xc8\x37\x02\xbf\xdd\xc0\x50\x1c\x31\xc9\xdf\x31\xec\x6f\xd6\xb8\xa2\x25\x63\x76\xff\x97\x39\x38\xed\x46\xf5\xb4\xfa\x67\x11\x83\x15\x30\x53\x82\x04\xdf\x40\x63\xbb\x61\x57\x7e\x60\x0e\x25\x42\x3a\x89\x69\x33\x4b\x7e\xac\x5e\x02\x12\xa0\xb1\xde\xb0\x53\xe2\x58\x79\x9d\xc9\x63\xd5\x42\x70\x02\xa9\xdf\xd2\x93\x64\xdc\x5f\x4c\x6c\x80\xb8\x2f\xdf\x6d\x67\xb2\xd2\xb7\xd2\x37\x4d\x8d\x3e\x72\x76\xc1\x68\x55\x38\x6a\xdf\x84\x69\xcd\x92\x2b\xad\xf7\x88\xfb\x2e\xd8\x86\xee\x74\xe4\xe6\xf3\x11\xf0\x54\x8a\xe4\x12\x64\xb9\xc7\xbc\xb4\x68\x8d\x14\x0a\xbc\x50\x17\x67\x9d\x05\x7d\x9f\x17\x33\x88\x7a\xc4\x0d\x11\xd6\x07\xa9\x25\xe6\x9a\x82\xd2\x7c\x06\x20\x42\xe8\x55\xd2\x96\x5a\x79\x55\x1b\x1a\xa5\xa3\x91\xa2\x7a\xeb\x55\xaa\xc5\xd0\xd7\xe3\x86\x0d\x59\x81\xa3\x9d\x66\xf8\x01\x20\x79\x9a\x60\x4e\xf1\x3c\x03\xbd\x7a\xfc\xa7\xc4\x42\x84\x7c\xc1\xe4\x04\xba\x41\x4f\xed\x66\xef\x1a\x59\xb3\x2a\xd4\xb8\xf7\x71\xc5\xad\x9e\xcd\x56\x47\xce\x0a\x68\x79\xf2\x91\xb0\x0f\xc8\x70\x30\x5a\x0e\xfe\xda\x6b\x96\xaf\x80\x4c\xd7\x21\x5e\x7f\x21\x5e\x1b\x2b\x15\x78\xd7\xfb\xb8\x81\x6f\x15\x2c\xd6\xcd\x9b\x87\xe8\xcc\xe3\x54\x02\x25\xbb\xfe\xa8\x39\x6a\xe6\x98\x25\xaf\x64\x36\x24\x13\xe2\x52\xae\x6c\xcd\x8f\x51\x18\xf2\xc7\x15\x5a\x09\x18\xf7\x8f\xbc\x63\x5d\x45\xd2\xf6\xd8\x5c\xc5\x9f\x01\x67\x60\xe7\xc1\x26\xaa\x33\x5b\xad\x6d\x7b\x36\xf4\x2a\x22\xe3\x3e\x48\xa9\xee\xea\x15\x43\x77\x59\xea\xf0\xb1\xe4\x92\xf7\xde\x9b\xc3\xdc\x9b\xd5\x3e\x69\xbc\x02\x40\x3b\xb7\xb1\x39\x2f\x3e\x85\x3d\x2d\x22\x65\xd6\x11\xa4\x56\x31\x52\x1f\x51\xfb\xf5\xb5\x7b\xe5\xce\x0d\x96\xd7\xce\xef\x02\x86\x94\x39\x63\x76\x79\x22\x99\xcb\xc1\xd4\x2c\x33\x1b\x62\x75\x16\xc8\xdd\x8d\x95\x06\xc3\xaf\xdc\xc8\x34\x36\x4e\x06\xcd\xbf\xd7\xd6\x10\xa9\x19\x4b\x17\xfb\xc9\x84\xb0\xe6\xb4\x47\xcc\x15\x08\xb9\x51\x17\xcc\xc0\x91\x09\x1e\x0c\x09\x39\x35\x73\x60\x4f\xb1\xd5\xb4\x3e\x6f\x73\x6c\xe6\x22\xc7\x52\x5f\x7e\x7f\x75\x55\xad\xfa\x78\xd1\xcb\x6d\x66\xfc\xba\x0b\x80\xf9\x8e\x92\x3a\x2a\x6a\x6f\x82\xcf\x2a\xe8\x28\xa9\x5c\x41\x16\x9d\x40\xad\xe0\x12\x95\x0d\x31\x24\x6f\xf1\x27\x68\x6e\xba\x61\xaf\x65\x6d\x60\x0d\xe0\x58\xa3\x89\x0b\x7b\x26\x36\x79\x12\x3f\x55\x83\x88\x88\xa2\x3c\xb5\x1d\xf0\x59\xb9\x26\xe8\x6b\xd6\x25\xff\xc7\xc2\xae\x70\x32\x87\xae\xee\x1a\x38\xe8\xa1\x01\x74\x31\x39\xda\x6c\x57\x9a\x4b\x25\x76\x67\xdd\xc1\xc6\x37\xb5\x82\x3f\x55\x50\xed\x8a\xa7\xdb\xda\xfb\x60\x9c\xf1\xe1\xf6\x9e\xca\x20\xeb\x43\x7e\x92\xc5\x07\x45\x2d\x1d\x3e\xca\x6b\x91\xed\x77\xbf\xac\xd6\x99\xe4\xd9\xa0\x6f\x1b\x97\x38\xfd\x66\x7a\xfb\x1c\xd5\x5a\x82\x25\x7a\x21\xc1\x3d\x50\xa7\x57\xf0\x66\xed\x43\x3b\x44\xcd\xd8\x74\x8f\xcd\x9a\x82\xf6\x7a\x46\xee\x3f\x38\xae\x51\xeb\xf9\xf8\xc9\x96\x49\xbd\x4d\x07\x70\xb0\xfa\x61\x0f\xda\xea\x7e\x02\x32\x34\xcb\x76\x4c\xa7\x7e\xd8\x82\xff\x9b\xe8\x60\xb6\xe9\x7c\x74\x49\xb3\x72\x78\x30\x61\xe3\xf9\xe3\x5b\x91\x90\x59\xd3\x7e\x00\x03\x76\xe1\xce\x11\xfa\xaf\x00\x04\x7e\xad\xe7\xc6\xd2\x05\x2a\xb7\xe1\x4e\x43\xf7\xb0\xf7\xd8\xd6\xef\x30\x8b\x30\xc8\x69\x4d\xfc\x84\x82\xec\x06\x2d\x1a\x22\x7b\x01\x77\x13\x49\x76\x6e\x41\x49\xb0\x8b\xfb\xf0\x54\x7a\x68\x48\x1e\xa1\xc0\xda\x72\x0c\xfc\xf7\x09\x98\x67\xd1\x18\x81\x69\x25\xa9\xf0\x3a\x5b\x98\x7f\xe7\x8c\x74\x2d\x70\xbc\x25\x77\xd3\x5d\x72\xdf\x76\xd7\xbe\x69\x3a\xd6\x25\x17\xf9\x61\xba\xcb\x41\x3e\x5d\xcb\xf3\x37\xeb\x19\xa1\xff\x20\xb7\xf6\xf4\x2d\x75\xd7\xfc\xd4\xb7\xa0\xbb\xca\x3c\xc4\xfe\x03\xaf\x78\x59\x6f\x91\xd8\x46\x58\x5c\xac\x7f\x42\xb5\x94\x5b\x45\xf2\x25\xc1\x9f\xfb\x25\x61\x5c\x20\x5c\x0f\x51\x55\xd1\xc5\x10\x52\x1a\xd0\x56\x61\x29\x11\xfc\xfc\xa6\x21\x49\x57\xb3\x62\xf8\x4d\x94\xd6\xe3\x36\x65\x89\xaa\x9a\x45\xf9\xc0\xe8\x9a\xe6\x24\x74\x22\x57\xed\x52\xc8\x5b\x07\xa3\xf0\xc8\xab\x07\xd8\x75\xde\x0b\xa0\xb7\xb8\x6b\xda\xf2\x1d\xf5\x06\xdc\x3a\xf8\x7d\xb7\xaa\x7c\x54\xe4\x59\xd7\x12\x5b\xba\x5a\x41\xbd\xe4\xef\x35\xe6\x11\xa8\x89\x51\x2b\xf6\x30\xbb\x8a\x7e\xbb\x70\x94\x35\x02\xce\x3b\x84\xe4\x12\x1e\x8b\x6f\xc2\xbe\xa9\x59\xda\x55\x77\xb8\x76\xf6\xc1\xf3\x15\x66\x24\x78\x13\xe2\x89\x67\x89\xb7\x17\xb2\x40\x80\x2c\xe8\xa4\xbd\xd8\x88\x8f\x1d\x24\x4e\x05\xdf\x9c\x19\xaf\x6f\xed\x2a\x26\xa9\x77\xb3\x54\xa2\x88\x61\xd5\x42\xa0\xc9\x53\x38\xda\x6d\xf5\x1d\xdd\xa6\x77\x95\x66\x6c\xde\xed\xb0\xba\xe0\x23\x00\xde\xaa\xcd\x75\x4d\xbb\x15\x5c\xd6\x2e\xc0\x9a\x05\x21\xeb\xd6\xbb\x8a\x00\xb3\xae\x54\xd7\x5c\x18\x34\xe0\x0b\x86\x97\xd5\x89\xf4\xe7\x74\x56\x0f\x2b\x9f\xaf\xf3\x00\x23\x0e\x12\x75\x11\x88\xd8\x95\xf1\xfb\xe2\xa5\x2e\x5e\x19\x7d\xcb\xce\xa4\xaa\xc2\x21\xc2\x59\xf9\x08\x29\xcc\x2e\x1f\xfa\x95\x99\x09\x18\x77\x53\x56\x7f\xe7\x1c\x57\xad\x20\xf2\x2b\xe4\xaf\x35\xc3\xba\x75\x7e\x57\x00\x79\x9d\xf8\xeb\x7c\x92\xf3\x82\x1a\xb9\xab\x6f\x2e\x38\xdf\x6c\x35\x14\x42\xc7\xbd\xcb\x53\x11\x14\x37\x43\xad\x4e\x7b\x1f\xab\x70\xb2\x79\x0e\xb0\xac\x2d\xf8\x4b\x8b\x48\x05\xae\x03\x4c\x6b\x6c\x35\xb1\xd3\x09\xa3\xe1\x68\xad\x96\xe5\xbb\x83\xf1\x6a\xe7\x32\x7a\x81\xfb\x4e\x97\xdf\x59\x38\x30\x59\x26\x23\xb0\x43\xd7\x80\x97\x3a\xe9\xcd\x94\x02\x1b\x97\xda\xa3\x47\x63\x66\xf7\x69\xd2\x51\xd0\xb1\xcf\x0f\x0e\x01\xde\x5c\x1d\x1d\x08\x30\x40\x69\x4d\x2c\x0c\x8a\xd9\x72\x0a\xeb\x17\xd1\xab\x7a\xb7\xd3\x28\x6f\x47\x97\x24\x1b\xd8\x25\x41\x10\xf0\xbc\x53\xe1\xaa\x0b\x7c\x1c\x90\xaa\xdc\x45\xfa\x7b\x2a\x63\x2f\xbd\xad\x49\x00\xf0\x25\x6c\x0e\x9a\xa6\x17\xfe\xdc\x48\xcf\x1c\xd4\x55\x86\x7e\x00\xb8\x2a\xca\x22\xba\x12\x6a\x18\x98\x0d\xaf\x22\x49\xd8\xc9\x83\xad\x9c\xcf\x69\xd5\x82\xaf\x74\x61\x18\x2e\xde\x14\x7c\xeb\x7a\x1a\x3b\x75\xe5\x81\x29\xaf\xae\xb3\xad\x92\xd7\x21\xc3\xd7\xcd\x58\xfd\x22\x53\x75\x0f\xb0\x24\x6d\x9e\xca\x81\x04\x6c\x79\x0c\xad\xb1\xc4\x67\x05\xb1\x99\x1c\xce\x4f\x22\x7f\x25\x0c\xd5\x25\x87\x67\xca\xdb\x8c\x18\xcc\x38\x52\xab\xe1\x05\x01\xdd\x07\xc5\x48\x78\x9a\xc7\x1e\xd6\x50\x6a\x4f\x96\x9b\x73\x59\x73\x83\x9e\xee\x5d\x41\x1e\xab\x40\xa9\x7b\x62\xfc\xb6\x3b\x3f\x36\x0f\x30\x19\x54\x4c\xc1\xf0\xdc\xe0\x3f\x0e\x64\x26\x72\x53\xd4\x4b\x48\xeb\x1b\x3a\x4c\xdf\xbe\xc2\xfa\xaf\x84\xac\xbc\x75\xa0\xe4\x17\xf7\x64\xeb\x19\x81\x76\xb1\x06\x61\xbc\x10\x6e\x0b\x66\x6b\x59\xc8\x77\x1d\xe7\x7a\xc8\xd0\x10\xb7\x80\xad\x81\x0d\x05\xad\xf5\xb0\x16\x34\x53\xa7\xbd\x68\xad\x37\xae\x3c\x54\x0e\x49\xc0\x9a\xe9\xf3\xc7\x73\xc8\x43\x5e\xb9\xb5\x85\x6f\x6e\x5a\xe8\x4f\xb0\x66\xe8\x54\xba\xa2\xdf\x56\x5c\x2e\xe8\xa4\xf8\xd7\xc6\xca\x88\x8f\xf1\x43\xb6\xd6\xbf\x7a\x16\xd0\x40\x42\xa8\xa6\xdf\x00\x7c\xfb\x31\x9d\xb5\xd5\xf9\x97\x8f\x24\xdb\x69\x69\x3e\xd1\xc7\x95\x89\x81\xfe\x0d\x59\x33\x7f\x5c\x65\x9b\x00\x04\x65\xf7\xca\x4a\x89\x84\xdb\x19\x4a\xdd\xbe\xcb\x78\x5d\x40\x7d\x8d\xa9\x9e\xaf\x79\xae\xfd\x0d\x87\x9d\x4b\x43\xe2\xc2\x45\x2a\xaf\x25\xec\x51\x73\x41\x9f\x1a\x18\x7c\x65\x85\x5e\x9b\x4d\xe5\xa9\xc3\xb4\xb7\xca\x0d\xc4\xd5\xf9\x79\x15\xbe\x36\x76\x84\x5c\x16\xb1\x5d\x2d\xf6\x22\x8d\x02\x6f\xd8\xdb\xbb\x7b\x0c\x45\x1a\x91\x8b\xc0\x45\x01\xb1\x08\xdf\x5e\x7a\x60\x60\xa7\xf5\xf8\x12\xd2\xa7\x31\x1d\xea\x76\x43\x59\x7f\x22\xcc\x11\x6d\xa0\xfe\x03\xd6\xea\x59\xfa\x3c\x42\x17\xc5\xfa\x6a\x6c\x56\x92\x90\x69\xf3\x48\xfa\xfd\x4d\x3f\x06\xa0\xac\x50\xe5\x90\xbb\xdf\x8a\x0d\x52\x67\xdf\xa8\x4a\x84\xbd\x5d\xf8\x7d\x17\x45\xb6\xf3\x14\x90\xc4\x14\x2a\x0c\xc7\x7f\x70\x58\xdb\x1f\xca\xdf\xc2\xeb\xfe\x5d\x08\x12\xf6\xa7\xeb\x8f\x1d\x0a\x9b\x3c\x83\xf5\xf4\x67\xdd\x92\x4a\x4a\xd6\x5f\x23\x99\xfd\x41\x6a\xcd\xdb\xb6\x7f\xd9\x1a\x81\x7c\x2d\xfe\xbc\x7d\xfe\x76\xab\x9c\x18\xc1\xf5\xad\xa7\x95\x4f\xe6\x1f\x48\xc2\xbe\x19\x5c\x5d\x9b\xbe\x67\xba\x8b\xdf\x8d\x02\xf2\xce\x87\x4b\xdc\xbe\x31\x88\xe1\xd3\xd1\x17\xc8\x76\x80\x53\x18\x98\xa6\x77\xf5\xc9\x6b\xe3\x84\x44\xd7\xa4\x28\x9b\x77\x9a\x86\xc4\xe5\x18\x95\xf0\xfe\x1e\xdd\x33\xf0\xcf\xaa\x19\xa6\xbd\xbc\x5e\xb5\x7a\xe5\xfa\x82\xb7\xe5\x95\x18\x3f\xfa\xda\x9b\xc2\x0f\xa8\xad\x83\x9f\xc0\xab\xfa\xc0\x8e\x80\x9d\x04\xed\xbf\xe8\xf4\x64\xd5\x47\xb2\x2b\x0d\xcf\xee\xc1\xf4\xe4\x40\x23\xcc\x68\xe7\xda\x2e\x49\xd0\xb4\x16\x8e\x83\x5e\xb5\x36\x3d\xb1\x2f\x24\x32\x72\xb1\xd9\x1d\x34\x5a\xc7\x3e\x61\xa7\xb6\x3e\x07\x5b\xb5\x42\xd5\x8f\x68\xd0\x3b\x9c\xc7\x93\xbf\x78\x27\x5e\xe5\x70\x94\x67\x11\xa5\x35\x08\xaa\x08\x54\xe4\x9c\x75\x1c\x62\x2d\x60\x95\x88\x66\x81\x5d\x5f\x80\xbc\x79\x01\x01\xde\x34\xce\x58\x56\x61\x19\x2f\x77\xb2\x3d\x65\x41\xbc\x56\x47\x63\xed\x6b\x2a\x4a\x1d\x2a\x59\x1f\x8f\xad\x2e\x2b\xb8\xfc\x08\xb0\xaf\x17\x77\x26\x60\x2f\x7a\xc8\xe2\xe2\x4e\xef\xb7\x6f\x66\x6a\xb9\xb8\x4e\x7a\xf5\x69\xf9\x6b\xe8\x56\xe6\x93\x90\xf7\x7a\x86\xf5\xe0\xf7\xe9\x05\xc0\xb5\x6e\xe1\x54\xe2\x67\x4a\xee\x3a\x09\xf6\xda\x48\xda\x85\xdd\x69\x6e\x56\xf7\xf6\x85\x10\xa0\x30\xd3\xdf\x1f\x81\xa8\xd6\x17\xd6\xbf\x24\x40\x2d\xa3\x15\x1c\x17\xdb\x68\xb1\xdf\xcd\xdc\xbf\x04\x8b\xf5\xed\xe4\x7f\xd1\xb9\x79\x65\xf5\x33\x61\x7c\x11\x23\x7b\x91\x67\x9b\x43\xae\x17\x4c\x59\x89\x39\x60\x61\x92\x70\x73\x1b\x34\x7a\x49\xab\xfc\x95\xbb\x8d\x09\x3c\x56\x4f\xb7\x94\xbd\x17\x44\x09\x7d\xea\x6a\xfb\x82\xd2\xbd\xf8\x69\xa6\xe5\x55\xc4\x2b\x35\x97\xfd\x4b\x34\x64\x4c\xb3\xfc\xd0\x66\x77\x12\x84\x79\xa5\x59\x9e\x4a\xa0\xc3\xba\x24\x99\xe8\x57\x2a\xe2\x9e\x83\x16\x8b\x7f\x5f\x00\xbd\xca\xd1\xf9\xeb\xba\x25\x44\xc2\xee\x0a\xd1\xfd\x65\xa7\xce\x26\xf0\x31\xb8\x35\xc3\x8d\xbe\x93\xf6\xfa\xeb\x6d\xe3\xdf\x12\x70\x05\x07\xc4\x5e\x6e\x6c\x2c\xe3\xb3\x57\xc9\x83\x1d\x72\x1d\xd3\xa2\xe5\x82\xeb\xf0\x0b\x6f\xc6\xb7\xac\xe9\x7d\x1c\xb5\x04\xf2\x35\xed\xea\x1e\xff\xaa\x1b\x6a\x3d\xf4\xeb\xb7\x68\xd6\x2e\x70\xeb\x3e\x5e\x92\xb2\xf2\xd1\xdb\x86\x71\x85\xdd\x80\xb0\xf9\xef\x42\xb8\x3d\x0b\x9e\x20\xf4\x9b\x67\x64\x9a\x65\xce\x9b\x39\xa0\x05\xa3\x2f\xf6\x85\x61\xc5\x1e\x88\x58\x7f\xf0\x7e\xad\xa9\x9b\x23\xe4\x06\x12\x73\x81\xb5\xb5\x06\x6b\x0f\x5c\x3b\x4f\x2c\x6d\x3a\x2f\xbf\xb9\x93\xf3\x8b\x7f\xed\x63\xca\xe6\x30\xdc\x1a\x83\x3e\x15\xb0\x43\xa9\x0d\xa0\x76\x85\x31\xfd\xda\x37\xe6\x5a\xb8\x40\xdf\xab\x3a\xb9\xfe\xba\xfc\x2c\x8a\xa4\xbf\x8e\xcb\xbf\x11\xd6\x11\xdb\x57\x7f\x27\x2f\x81\x03\x70\xf6\xc4\x79\x5c\xab\xd7\xce\xbc\x18\x60\xc8\x7a\xeb\x58\x87\x7c\xad\xbf\x60\x68\x37\x00\xea\x19\xc3\x96\x66\x3a\x89\x53\xd9\x71\x48\x67\x8b\x7a\xd5\xe5\xc9\xaf\xa0\xb8\x1e\xfd\x1e\x34\x81\x6b\xdd\xf3\xc7\x06\x80\x0c\xdc\x9f\xe9\xfe\x6d\xbc\xa5\x92\xae\xd5\xb9\x11\x6d\xbf\x88\x9e\x76\x02\xed\xc5\xbd\x55\x40\x06\xf5\xdb\xea\xc1\x6c\x2b\x0b\x0b\x55\x7b\xae\x75\x2e\x4d\x27\x1e\x48\xe9\x60\xd2\x06\x6b\xd7\xfa\x27\x76\xf0\xf2\xcb\x39\x9e\x16\x7d\x91\x76\x30\x4e\x05\xde\xd3\xcc\x42\xef\x1e\xc5\x6b\x7d\x04\x5e\xc9\xcc\xe4\x79\xca\x6d\x85\xc1\x73\xe7\x3a\xfd\x6a\xf7\x13\x2c\x9c\xb8\xa6\x2a\xe6\x28\x34\xe2\x49\x94\x9a\xad\x78\x00\x1d\x2d\x5c\xc5\x9b\xa3\x19\x52\x1c\x28\x9a\x18\x42\x02\xc3\x5b\x7c\x8a\x6a\xcb\x77\x0f\x06\x9a\x82\x67\x5b\x00\x6d\xc0\xa0\xe2\xb2\x8f\x02\x57\xc1\x6e\x6d\x93\xbe\xc4\xc5\x81\xb6\x12\xb8\xd2\x51\x24\xe4\x76\xfd\x94\xd7\xb1\xcf\xc4\x3d\xc6\x78\xad\xd1\x9e\x64\xc1\x03\x92\xbe\x9c\x8b\xab\xb7\xe4\x52\x02\xdc\x35\xbd\xdc\x7d\x74\xa9\x38\x92\xfb\x6d\x53\x9f\x3c\xe8\x7f\x01\xf5\xcb\x2f\x0f\x01\x9b\x8e\xb2\xcc\x1f\xe6\x40\x93\x9d\x2d\x33\xd6\x88\xf7\x74\x5b\xd3\x31\xd6\x68\x43\x97\xb4\x71\xcd\x4f\x50\x3e\xb8\x19\xeb\x8c\xce\xac\x55\xcf\x96\x8c\x09\x2b\x29\x98\x58\xe1\xbf\xa7\xdd\x74\x85\x99\x9f\xd7\x82\x01\x21\xc1\x64\x2f\xe5\xab\x9c\x8c\x13\x83\xb5\x33\x69\x18\xe3\x95\x4f\xcd\xb9\x3a\xe4\xe9\xf1\xe4\x30\x24\x34\xd3\x80\xbb\x2b\x11\xd0\x0b\x5f\x8a\x92\xfa\xad\x20\xdd\x0e\x00\x78\x4b\xa2\x90\x0b\x6c\x4e\x12\x24\x6a\x1b\x39\xd5\xe3\xc6\x1a\xf6\xd7\xb5\x2f\xb8\x77\xf1\x78\xb9\x45\xeb\xec\x02\x3b\x71\xc6\x6f\xeb\x71\x33\x08\xbd\x18\x22\x1d\x2c\x28\xc4\xdd\x0b\x0f\xba\xd7\x68\x5b\xa3\xa1\xfd\x00\xb8\x88\xae\xac\x17\xf3\x1a\x1b\xff\x1f\xa7\xcb\xa6\x2d\x96\xad\x91\x83\xcb\x1a\x88\x5f\xc5\x11\x9a\xf5\x48\xf3\x48\x28\x2d\x72\xdb\xb3\xd8\xc2\x9e\x05\xed\x7b\xf6\xbc\x3a\xef\xce\x3a\xf8\xb7\x70\xe6\x19\xc1\x36\x34\x79\x20\x15\x38\x32\xb6\x6b\x4f\x66\xae\xcb\x2a\x73\x98\x81\x13\x86\x87\xcd\xab\xea\x93\x60\xfd\x53\x8d\xb2\x13\xef\x08\xa8\xbf\x6e\xc3\x37\x42\x77\x87\xf7\xd5\x79\xc1\x2a\xe3\xed\xce\x3a\xb2\x48\x37\xcb\x59\x1f\xd7\xce\x61\x12\x47\x04\xc7\x21\x85\x57\xf4\xac\xdd\x7e\x11\x2b\x0c\xd7\x85\xe6\x25\x34\xc5\xaa\x3f\x10\x95\x19\xf7\x8a\x48\x72\x15\x52\x2e\x24\xb9\x0b\x50\x53\xdf\x9a\x9e\x51\xd1\x9e\x1e\x1a\xed\x8d\x9e\xb3\xc8\x6d\x76\x16\x88\xfd\xf0\x58\x27\x6a\xe4\x9f\x71\xe7\xa6\x6b\x1c\xdd\x8f\x4e\xca\xb0\x0e\x12\x03\x0d\x1d\x9f\x68\x33\x73\x18\xaa\x65\x00\x19\x7e\xf0\x5a\x4f\xd5\x69\x67\x9d\x5e\x1f\x08\x01\x4c\x8a\x3c\x47\x8b\x59\xd4\x49\x12\x88\x69\xd9\x91\xf0\x57\xfb\x02\xcf\x89\x38\x5f\x04\xa8\x70\x03\x5e\xbf\x55\x0d\x94\x9d\x1e\xe6\x74\x49\xdd\xfc\x74\x46\x42\x68\x16\x11\x35\x4c\x23\x1f\xfc\x3a\x03\xb5\x86\xcb\x7c\x0a\x22\xbc\x5d\x7e\xe3\xf3\x7a\xc5\xd6\xed\x2b\xd4\x0b\x5e\x1c\x63\x35\xb0\xf2\xae\x81\x4d\x14\xb4\xa9\x96\xfc\x04\x50\x0b\xf5\x78\xa3\xf4\x20\x44\x13\xa6\x4f\xda\x1d\x8d\x81\xf6\x33\xfd\x83\x56\xb8\xf7\x04\x60\x73\x3b\x9e\x84\x27\xc0\xaf\x55\xc1\xe2\xbe\x9d\x10\x11\xd2\x9e\x12\x02\x98\xce\x30\x13\xc4\xc5\x68\x0f\x9c\x7c\x73\x8a\xc1\x7a\x01\xf3\xe3\xb6\x5a\x25\xf0\xd6\x34\xc0\xc2\x84\x55\xda\xbb\xb0\x5c\x5c\x0d\x09\x6c\xda\x4f\x47\x1d\x1c\x7f\x6a\x4e\x0a\x51\x41\xcb\x36\xe0\xd0\xc9\x23\xf8\x79\xa5\x0e\x8c\xb0\x33\x13\xf8\x78\xab\x61\x71\xbc\x81\xcd\x18\x1a\x94\x18\xb0\x9c\x43\xe6\xca\x70\xef\xe3\xc5\xfc\x0c\x9b\x02\x2b\x00\xcb\xda\x4b\x3f\xea\x25\xc0\x1e\x13\x67\x5f\xbf\xbe\x9c\x80\x9d\xd7\xfe\x0b\xad\x19\xc5\x8a\x5a\x71\x61\x23\x0e\x2c\x61\x0f\x0f\xd5\xec\xfc\x60\xba\x06\xd0\xc2\xb1\x04\x21\xc3\x6d\x55\x72\x86\xe3\x0d\x17\x5c\xf8\x60\x9b\xca\x4b\x87\xa4\x2a\xc9\x19\x26\x66\xf2\x72\xfa\xca\xd6\x4c\x3b\xf6\x20\x0e\xe3\xe1\xa1\xd1\x45\x23\xe5\x70\x71\xd6\x7e\x2e\xde\xc2\xb5\x07\x5a\x3c\x68\x34\xea\x83\x1d\x3c\x06\xf8\xf4\x7a\x3c\x4a\x5f\x84\x33\x3a\x40\x07\xe0\xce\x03\x4d\x79\xb5\xa0\x0b\x07\x0e\x73\x6a\x5f\x62\xd5\xaa\xc7\xd5\xe1\xe9\x88\xb3\xe9\xa8\x1c\x1a\x44\x5e\x2b\x17\x64\x85\xdd\x3f\x07\x49\x14\xed\x24\xc4\x76\x88\x3f\x3c\x5d\xc2\x40\x9f\x04\xc2\xe2\x03\x14\x73\x90\x0d\x33\xc8\x1a\x93\xda\xed\x88\xed\x0a\x5e\x2a\x3e\x2f\x23\x32\x24\x74\x48\x56\xb6\x7e\x8b\x9c\x08\x18\xf9\x7e\xb7\x1f\x92\x52\x24\x82\x44\xfc\xdf\x42\xfc\x66\x5f\x99\xf3\x06\xbb\x9e\x20\x86\xc6\xc6\xaa\x5d\x03\x6f\xab\x59\x95\x80\x54\x3a\x1e\x40\x11\x9c\xdb\xab\xaa\xb0\x96\x4f\x62\xf1\x23\x5e\x5c\xd0\x88\x63\xc3\xf6\x56\x05\x5a\x14\x15\x46\xb5\x36\x45\xfb\x89\x47\x92\xb7\xa5\x0a\xba\x69\xf6\x94\x82\x59\x9c\x85\x5f\x25\xa0\x58\x17\xea\x86\x09\x9f\xde\x91\xe2\x8b\x70\x46\x16\x2e\xe2\x34\xdb\xf6\xd3\xa2\x4e\x15\x86\x34\xf6\x50\x33\x0f\xed\xe8\x46\x90\x86\xd6\x0f\x91\x53\x30\x6f\xc0\xd1\xe1\xfc\xb5\x41\x56\xeb\xea\x7b\x01\x53\x30\xc0\xa2\xc1\xe3\x05\x5d\x15\xc7\x18\xf3\xdc\xac\xbb\xeb\xb5\x83\x1b\x99\x19\x99\x66\x3f\xf3\xe1\x62\x31\xad\xa4\x57\x00\xa1\x63\xd1\xce\x76\x7a\x31\x1f\x4f\x67\x4e\x71\x7b\x92\xd1\x3f\x36\x4a\x56\x1e\x1e\x79\xcb\x75\x19\x72\x8c\xa9\x52\x6d\xcc\x84\x9f\xf6\x52\x5a\x13\xb0\xc6\x82\xb0\x83\x6c\xcc\x37\x77\x4b\x7b\xe3\x28\x27\xb1\x4c\x37\xe7\x60\xf9\x61\xd7\x77\x97\x05\x3e\x46\x8b\xf6\xfc\x40\x1e\x0b\x90\xe1\xb6\x3a\xcd\x6e\xab\x2f\x7d\x54\xc9\xfc\x1f\x08\x15\x50\x3a\xee\x51\x39\xe6\x71\x38\x2a\x8c\x86\xbd\x04\x1c\x35\x23\x34\x59\x3c\x56\x7d\xea\xed\xd1\x19\xef\x06\x28\x70\xc8\xdf\x02\x23\xcf\x18\x66\xe5\x01\xcc\x65\xae\xff\xbb\x78\xbc\xac\xa4\x40\x45\x0e\x64\x6b\xd5\x61\xf6\x45\x59\x10\x5e\xea\xec\xcd\xe2\x91\x44\x42\x35\x00\xc8\x87\xa6\x01\xe8\x85\xe9\xed\xb9\x63\x45\x7b\x37\x16\x6c\x6d\xdf\x63\x6d\x88\x9d\x63\x4d\xd7\xa1\x58\x1c\x00\x0b\x35\x17\x14\x64\x2d\x6b\x66\xe4\x15\x98\x6d\xcd\x7a\x57\x36\x38\x88\x50\xa0\x35\x07\x56\x75\x56\xaa\x8e\x19\x11\xa1\x02\x4a\x32\x9f\x98\xb9\x2a\x4c\xfd\xb0\x76\x97\xdc\xf3\xc7\x1c\x70\xd0\x63\xce\x57\xc4\x42\x03\x92\xfc\x1b\x7a\xe1\xc7\x1c\xe3\xe4\x18\x2f\x5e\x1b\x0c\xb9\x34\x2e\xfb\xd3\xda\x66\xe1\xdb\x82\xbe\x1e\x88\x81\x0e\x4d\x3b\x9e\x69\x8c\xc0\x7b\xe7\x23\xfb\xb4\x5e\xff\x7c\xda\x08\xef\x65\xfd\xe1\x21\x14\x6f\x18\x0b\x44\x6d\xaf\xe8\x4b\x06\xbc\xa7\xda\x2d\x6a\x8e\x3b\xff\xf5\x28\x70\xbb\xcd\x4c\x89\x40\x21\x40\xca\xe3\x45\xde\xb7\x63\x52\x04\xf0\x36\x1b\x0a\x3b\x39\x16\x59\x6f\x6c\x75\xa1\x62\xaf\x3d\x9b\xfc\x6d\x40\x80\xb0\x9b\xd3\x3b\xea\x9b\x29\x6a\xca\xe9\x66\xd3\x4f\x27\x69\xbf\x4d\xa6\xc7\xac\x92\x49\x6e\x9e\x5a\x6c\x83\x9b\x3e\x20\xcc\xc2\xf6\x6c\x12\x8a\xc7\xa4\x21\x00\x17\x96\xe5\x77\xc6\xbd\x66\x27\xad\x33\x44\xb6\x61\x7b\x18\xbe\xec\x2e\x71\xcb\x65\x8b\xce\xa5\xa7\xd9\xc4\x2d\x99\xa0\xb4\x42\x23\xa4\xe7\x61\x86\x68\x92\xd9\x85\x7b\xcd\x03\x85\xd5\x0e\xa4\xda\x71\xf7\x99\x78\x06\x80\x9c\x15\x8b\x73\x30\xb2\x44\xa6\xb5\xe2\xb8\x69\xab\x32\xe9\x7a\x26\xca\xf9\x94\xf9\x88\x0b\x96\xbe\xed\xe1\x26\x68\xf9\x9f\xe4\xd2\x88\x6b\xe6\x96\x72\xd4\x4e\x99\x0f\x08\xe3\x6f\xd5\x67\x38\xe0\x1b\xd7\x97\x32\xef\x1a\x1b\x39\x32\xe4\x6c\x90\x00\xc0\x47\x24\x47\x2b\x06\xc1\xf0\x59\x96\xea\x35\x84\xe7\x73\x6a\x15\x11\xdf\xd9\xbb\x85\x08\x82\x46\x8b\xd2\x38\x3c\x42\xfd\x68\x56\x44\x5e\x1d\xb9\xac\x0f\xf9\x3b\x8f\x1c\x07\xdd\xb6\x40\xa7\xde\xa1\x38\xf9\xc3\x23\x35\xa3\x1a\xca\x14\xfa\xa6\x63\x3d\x4a\x6e\x22\x40\x4c\x2b\xf4\x76\x71\xc4\xb0\x4e\x71\x25\x52\x40\x18\xcc\x9c\xe3\x92\x21\x8c\x4b\x9f\xc2\xfe\x6a\xc3\xbb\x66\x7b\x90\xde\x81\x7c\x87\x78\xd2\xa4\x31\x3f\xd0\x2e\xcb\xc2\xae\x31\xe2\x8e\xf3\xca\x1a\xd1\x8b\x76\xb3\x54\x2b\xf4\xb6\x3f\xce\xb3\x8b\x13\x10\x67\xb2\xa6\x27\xe5\x60\x1c\xfd\xb4\x8b\x61\x0b\xf6\x34\xb8\x63\xe4\x67\xf7\xf7\x43\x8b\x28\x26\x1d\x42\x6a\xd5\x88\x87\xaa\xac\x89\x51\x06\x07\xf4\x86\xb9\x39\x3c\x2d\xfa\x48\x27\x09\x51\x99\x61\x87\xca\xeb\xd5\x46\x22\x8f\xb4\x6b\xa3\x70\x59\xf9\x46\x3c\xfb\x7d\x24\x62\xde\xda\xd4\x55\x46\xc7\x1f\x67\xe1\xab\x9d\x2c\x4e\xa3\x88\x0c\xfd\xc8\x3d\x55\x69\xbc\x34\x70\x40\xcc\x0c\x09\x04\x03\x2d\x5d\xc0\xe2\x50\xc5\x92\x3a\xe5\xeb\x98\xa5\xf7\x01\xc4\x47\x36\x75\x76\x04\xc2\xe4\xc2\xf6\xba\x75\xc2\x0e\x45\x9f\x01\x32\x40\xf6\xb1\xa3\xa5\x71\x32\xf0\x11\x04\x00\xb7\x3a\x53\x7c\x75\xf3\xa0\xaf\x01\xc8\x52\x2e\x76\x04\xff\x59\x42\xbc\x60\x6e\x39\x06\xb6\x81\xa2\x8f\x25\x4a\xcc\x27\xc3\xa8\xf7\xe9\x0d\x5f\xa0\xa2\xf9\x8c\xef\x35\x40\xd1\xf6\x35\xe7\x17\x75\x77\xd0\xa3\x58\xb5\xc1\xf4\x47\x8a\xc0\x1e\xe3\xf4\x76\xa6\x5b\xa5\x6a\xf5\xee\x7d\x56\x35\x43\xec\xf9\xf1\x95\x4a\xb4\x72\xed\xcd\xd7\x68\x46\x53\x61\xdc\x4b\x27\xd9\x5b\x9c\x9a\xce\x61\x7a\x9f\x13\x47\xb7\xed\x19\x22\xe4\xf7\x25\x8a\x1e\x48\xd1\xd5\x07\xcd\xb2\x4a\xec\x39\x82\xa5\xc0\x2d\x13\xa5\xe4\xae\x4d\x40\xa3\x0f\x97\x46\xd7\xba\xd6\x7a\x8f\xa5\x08\x8d\xbe\x4b\x8a\x52\x3d\xa2\x48\x78\x6f\x46\xee\x9c\x02\x37\x01\x56\xdd\xf1\xb8\x69\x99\xe6\x6a\x41\x77\x94\xd8\xec\xcc\xc4\xa5\xc8\xb2\xbf\x09\xd1\x77\xd1\x5e\xf3\xd8\xe9\x07\x03\xcf\x0a\x73\xe9\x03\x80\x0c\x38\xd6\x6d\xcf\x73\xb3\x99\x94\x01\xa3\xdc\x58\xe4\xba\x8f\xe9\x43\x34\x7f\x57\xf0\x3a\xf7\x08\xd2\xd9\xf9\x41\xd1\xb6\x66\xe6\x1f\x8d\x14\x07\xe5\xe2\x94\x7d\x50\x9a\x17\xb2\x88\xb3\xdc\xa6\x80\x4e\x0b\x8a\x8c\x18\x0f\x9c\x9f\xb8\xc4\xd9\x3d\xd0\xb4\x20\xa5\xf8\x75\x33\xa9\xdd\x7c\xde\x19\x30\x7b\x06\x00\x20\xf0\xd4\xe3\x1d\x0a\x49\xe0\x74\x40\xac\x47\xf5\x56\xad\xab\x77\xe5\xb8\xb4\x0f\x7b\x69\xee\xf8\x58\x94\xb3\x37\xc5\x09\x44\xce\x48\x16\x64\x17\x1c\x1d\xc4\x35\xcb\xb8\x41\xd1\xf9\x5f\x5a\x62\x7e\x3e\x34\x1c\x6f\xcf\xd2\x1a\x44\xee\xc1\x9e\xac\x0f\x66\xb5\x2d\xd1\xe9\x66\x0e\x7a\x8c\xf3\xd0\xd7\x80\x93\xf7\x77\x87\x1b\xbc\x5c\x1f\x2c\x72\x70\x2e\x94\xae\x1a\x18\xbc\x2f\xe0\xf9\xa6\x8f\x62\x69\x67\xd9\x07\xfe\x97\x40\x6b\xce\xec\x5a\xd8\x85\xf3\xac\x5b\x38\x20\xb2\x2e\xdf\x9a\x16\x31\x68\xc8\xb8\xbe\xaf\x88\x82\x82\x77\x4a\x54\xbb\xf5\xfd\x64\x57\x7b\x4f\xaf\x39\x20\xe8\x5e\x41\xfa\xfa\xa9\x7d\x43\xf7\xe4\x9f\x80\x9d\x3d\x77\xb8\x96\x31\x04\xc1\x03\xb5\xda\x71\xf7\x78\x80\x0f\xc2\x79\xb2\xa7\x82\x17\xd0\x1e\xc0\x61\xaf\x5a\x6d\x62\xbc\x0c\xa2\xa9\xf9\x6e\x0a\x34\x0e\x5c\x35\x4f\xb0\x75\xd2\x61\x71\x03\x9d\x35\x40\xe1\xfa\x04\xb7\xda\x7b\x07\xce\xab\xbe\x64\xc9\xe1\x6b\xdf\x6b\x4d\xd4\xcf\xa5\x1e\x1d\x8d\xf9\xab\x71\xab\x8f\xdb\xe4\xa1\x5a\xa1\x68\x7c\xc4\xcc\x71\xa1\xef\xc0\x4c\xe4\x2b\x11\xe5\x0a\x89\x63\x4c\xaf\xf3\x5a\x38\xb6\x6c\xe6\xb7\x3f\xfe\x80\x5c\x3f\x84\xfc\xa5\x39\xd0\xcc\x32\x56\x85\xff\x6d\x17\x02\x24\x49\xb5\x16\x2c\xf8\x1a\xbc\xeb\x65\xd3\x86\x01\xf6\xae\x10\x8f\xcb\xec\x9e\x1f\x06\x00\xa1\xeb\x60\x97\xeb\xed\xbc\x5f\x87\x5d\x0f\xb8\xc2\x5e\xca\xd7\x00\xc7\x8a\xdb\x49\x38\x67\xd7\x21\x26\xb3\xb9\x62\x44\x6c\xd7\xec\xf3\x13\x57\x26\xbc\xb5\x7b\xf8\x88\xb7\x66\xc5\x09\x3b\x35\x5e\x75\xfd\xa8\xa5\x36\xc8\xcd\x3f\xe2\xa7\x71\xff\x00\x60\x82\x56\x7d\x7b\x30\xc4\xae\xbe\x77\x34\x94\xf8\xde\x35\x7c\xb5\x96\xeb\x62\xcb\x1d\x89\xf5\x41\xb5\x16\x84\x15\x4a\xa8\x6b\x98\x18\x37\x3a\xc3\xb6\x57\x25\xc0\xbe\xf6\xe2\xfb\x44\xbe\x38\xd9\x29\x54\xd8\x36\xaf\xce\x37\x7d\x09\xb6\x9b\x4e\x40\x02\x76\x18\xeb\xe7\xa5\xc9\x1f\x42\x54\x9b\xc3\xf8\xa3\x26\xda\xf0\xe4\xc0\x69\xb2\xc7\xa1\x5a\x4d\xb0\x9d\x61\x15\xed\x03\x09\x49\x08\x61\xd2\xe9\x91\x98\xbd\x7d\xec\x00\xaf\xfa\x19\x48\x6f\x6b\xdc\xf8\xdb\xe2\x28\xec\x8d\xd8\x4f\xb7\xa3\xb7\x43\x30\xf6\x21\x2b\x48\xd4\xe7\x26\x10\xf5\x41\xc1\x02\xbc\x92\xcd\xd1\xe2\xc9\xb0\x3e\xaa\x0e\x0b\x61\x06\x32\x1f\x76\x17\x49\xda\xad\x7c\x2f\x31\x8d\x75\x88\xaa\xad\x9e\xc9\xbf\x55\xd5\xed\x5b\x9d\xdf\x5a\x72\x7e\x2f\x2d\x4e\x7a\xf3\x3c\xa7\x3e\xac\xc8\xa8\x44\x41\x00\x07\xe4\x97\x08\xa4\x1d\x14\x61\x6f\x24\x3c\x81\xce\xf3\x92\x5d\x73\x7f\x8e\x67\x6b\xf7\xb1\xc9\x02\x16\x36\x52\x85\x37\xda\x2e\xb9\x17\x77\x1a\x45\x3e\x0d\xf3\x4d\x09\x0a\x62\x36\xcd\xa3\x09\x95\xa1\xb0\x38\xdf\x5b\x11\x4e\x36\x43\xd5\xc4\x06\x1c\x91\x8c\x1e\xd4\xc1\x66\x73\xeb\xd6\x31\x4a\x1e\x46\x00\x4c\x36\x1f\xe9\xb2\xe5\x06\x32\x2f\x9b\x16\x5b\x01\x98\xac\x34\x5d\x93\x2b\xc0\xd9\xae\xf7\x2d\xfb\x29\x24\x71\x11\xd9\x74\xf3\x2f\x19\xd7\x9a\x67\x0d\xc9\x99\x49\x85\xd5\xad\x84\xc3\x6a\x2b\xa3\x5a\xf3\xb4\xdc\xc8\x42\x54\x97\x9c\xf9\xe6\x96\xde\xf3\x9a\x19\x7b\xbc\xd9\x25\x0c\x7a\xf6\x7e\x23\xae\xcd\xe4\x4e\x00\xd7\xfe\x01\x06\x2d\x92\x80\x7d\x0e\xb4\xf6\x84\xd6\xb6\x6a\xc0\xfa\x05\x97\x0a\x02\xde\xb2\x90\xbb\x58\xc6\xf7\x44\x22\x6c\x5c\x11\x94\xd0\xbf\x8f\x9f\xdc\x4b\xc5\x23\xb5\xeb\x5f\x17\x3d\x57\x53\x8a\x57\x0f\xfa\x99\x95\xba\x81\xdb\x83\xcf\xfb\xc3\x41\x5d\xeb\x85\xf7\x13\x65\x34\xe0\x7e\x69\xb4\x74\xba\xcd\x5f\x2b\x7d\xfe\xed\x6a\xfb\x55\xb4\xc6\x16\x8b\x3b\x74\xb4\xb2\x4c\x7b\x6e\x9c\xe8\x07\x1b\xe3\xf8\xf1\x03\x72\x60\x78\x35\x9c\xcb\xbd\x7f\x70\xb9\x75\x5b\x1d\x21\xa6\x67\x39\xef\xc8\xd3\x21\x23\x7b\x2f\x75\xa8\xa1\xe8\xed\x54\xee\x35\xf4\x4f\x51\x42\x02\x26\x4d\xe9\x7b\xb9\xbf\x98\x9f\xc1\x0d\xd1\x03\x6c\x1d\x7a\x9b\x6d\x89\xfb\x88\x42\x84\x35\x6e\xf7\x20\xc4\xd6\x88\x48\x01\xf4\xa6\xb9\xbe\x3b\x25\x82\xa1\xd0\xed\x95\x80\x35\x2b\x4c\x4c\xdd\xdc\xb2\x64\x56\x90\x61\x47\x87\x88\x5b\x7b\x3c\x54\x0c\xe2\xb6\x49\x43\x7f\x67\xed\x27\x6f\x51\x49\x78\x4b\x89\x1f\x64\x78\xeb\xb4\xbd\xf4\x7c\x6b\x7a\x73\xf9\xed\x73\xc8\x8f\x5a\xfa\xd7\x7b\x47\x68\x4b\x72\xab\x81\x03\x1e\xd1\xa4\x00\x81\x6b\xe6\x21\x6d\x15\x87\x7b\xfb\xd4\x91\xa8\x69\xa6\x1d\x7d\x09\x77\xfb\x59\x17\x95\x4f\x86\x47\xe8\x72\x43\xfb\xd0\x00\xec\xf6\x04\x6d\xe8\x48\xf5\x51\xf8\x78\xe4\x51\x64\x8d\x80\x94\x94\x58\xb9\x7d\xe2\xec\x2d\x81\x02\x27\xd7\xd4\xb7\x37\xad\xb9\xa1\xb9\x15\x32\xe3\x46\x0b\x85\xdc\xec\xae\xcd\x49\x27\x14\x81\x8d\x66\x09\xcd\x6e\x86\x82\x2f\x37\x6f\x76\xd1\xc7\x0e\x12\x38\x5e\x13\xd5\x6d\x56\x42\x55\x39\x69\xd7\xf6\xaa\x07\xfd\x3d\x31\xf2\x42\x2c\xf4\x31\x47\xe3\xc3\xea\xcf\xa8\x22\xac\x45\xc4\x27\x1a\x06\x5b\x1a\xf5\x4d\xb4\x75\x44\x03\x3b\x47\x1c\xfa\x9f\x6b\x14\xbe\x82\x21\xce\x87\x1e\xf6\x5e\x14\xb2\xa1\x02\x37\xf1\x0b\x4f\xce\xfb\xfe\x01\xc9\xdb\xb1\x15\x04\x19\x66\xc8\xb2\xe6\x7b\x46\x5b\x0b\x19\x40\x3c\x42\x7b\x16\x4e\xe5\xe1\x99\x69\xaf\x69\xbe\x1a\x7d\x7c\x8e\x4d\x3b\x5a\xbc\xd9\x0f\x85\xdc\x79\xb2\x61\x18\x9c\xf8\xbe\x2e\x31\xc6\x1b\x73\x57\xb4\x59\xe5\x77\x55\x07\x35\xa4\x88\xee\xa8\xf0\x99\xf9\xb4\x47\xd5\xaa\x0f\xb8\x7f\xfe\x00\x22\xe0\x96\x3f\x7a\x41\x69\xfe\x3f\x33\xfc\xee\xd6\xdd\xbb\xbd\x15\x51\xc3\x2c\x7f\x0f\x59\x99\x3b\x35\x3c\x20\x95\xdc\xe9\xe5\x76\xda\x12\x4f\x4e\x3a\x38\x4c\x60\x72\x60\x57\x86\x5c\x4b\x98\xdd\x0f\x7e\x55\xb0\xab\x23\xe9\xfc\x3c\x16\xde\x79\xbb\xac\x1a\xe6\xab\x4f\xa4\x79\xee\x0f\xf6\xf3\x91\x54\x37\xf0\x5d\xaf\x0f\x9d\xfa\x83\xdf\xd8\xda\x61\x0c\x63\x67\xb8\x76\x2b\xf0\xcc\x3a\xe6\xfb\xdb\xd4\x7b\xc7\xf5\xdb\xbe\xab\x3b\xb7\xf2\xbd\xe7\x32\x37\x40\x79\x5e\xbd\x1a\x5b\xdf\x50\x7e\x71\x23\xb5\xff\xb1\xe6\x7a\x49\xa9\xd0\x0c\x4f\x69\xb7\xe9\x1e\x5d\x15\xb3\x95\x38\xbe\x5e\x3b\x18\xd6\xc5\xcd\xa5\x3b\x9e\x97\x66\xcf\x68\x38\xe6\xe3\xb6\x5b\x40\xef\xda\xf2\xf9\xd6\x0b\xda\xe6\x30\x4e\xff\xea\x7d\x52\x72\xd7\xea\xa3\x75\xde\x6a\x74\xac\xb9\xea\x09\x20\x89\xad\x8a\x52\xab\xd4\x4a\x8f\x96\xb1\xbd\x2a\x4d\x05\x53\xef\x08\xac\x75\xaa\xa4\x7d\xd7\x8e\x3d\x21\x6b\x9c\xbf\x78\x8b\xcd\x22\x70\x63\x65\x48\xd9\x5a\x3a\x4d\x34\x78\xbe\xe6\x57\x24\xcb\x99\x49\x4d\xc8\xb0\x13\xb5\x48\x3f\x8b\x6d\xc1\x3e\xc9\xad\xbb\xe6\xdf\x36\xfb\x8a\x59\xd6\x78\x40\x6c\xb9\x9f\x95\x0f\x75\xbf\xea\xee\x0f\xfc\x2a\x14\x9d\x35\x1d\x1c\x01\xcf\x8f\xbd\xa3\xd2\xf9\x40\xac\x72\x9e\xae\xd6\x5b\x23\x20\xc2\x7d\xce\xe9\x63\xdc\xc8\x66\x70\x7f\x48\x08\x3b\x42\x98\x62\x0d\x45\xef\x35\x11\xe6\xb9\x92\x74\xb4\xa6\x87\xbb\xcd\x97\xb7\xf5\x47\xf7\x81\x35\xf2\xf2\x9e\x95\x5b\xb2\xbc\x9d\x93\xfa\xe5\x28\xf4\x32\xdf\x30\xf4\x00\x8c\x8b\x61\x7e\x3a\x52\x81\xb8\x74\x61\x91\xaf\x53\xdf\x1e\x5a\x6e\x1c\x02\x68\x5f\xc7\x33\x68\xe9\x7b\x90\xb5\xcc\x24\x99\x75\xb9\xe6\xd7\x3d\x73\xb6\x56\x40\x3a\x02\x6b\x6c\xf5\x42\x0d\x4e\xf3\xf5\x93\x3d\x93\x74\x89\x81\xd3\xe5\x1a\xe0\xf6\x1a\x63\x59\x87\xac\xab\xb0\x7b\x47\x76\x61\x0d\xb9\x20\x8b\x3b\xcb\xc0\x47\x72\xa3\xbd\x8b\x5a\x6e\x06\xc7\x7e\x96\xea\xd1\xd7\xda\x06\x11\xeb\x7c\x02\x85\x58\x77\x0b\x83\xa3\x34\xd8\x81\x72\xca\x7a\xac\x63\xa6\xce\xbe\x42\x5f\x99\x3b\xd8\xef\x7c\xbc\xa5\x2a\xd2\xc8\xc7\x61\xde\x61\xc4\xea\x78\x03\x56\xd6\x72\x28\xec\x49\x8c\xf5\xb5\xa2\xbd\xfd\x97\x55\x18\x29\xbb\x03\x93\x2d\x09\x8c\xe4\x4c\x14\x46\x35\x33\xed\x9a\xea\xd8\x1f\xfe\x91\x04\x9e\x5d\x79\x35\xa0\xb3\x5f\xbc\x0a\x3d\x2f\x94\x8f\x45\xea\x28\xca\xf9\xf7\x9b\x88\x7e\x2f\xcc\xc7\x27\xaf\xbd\x5d\x19\x7b\xce\x4e\xc7\xb6\x2e\x40\x5b\x7c\xf6\xab\x38\xef\xe7\x22\xbf\x62\xf9\xbf\xc8\x0a\x8c\xe5\xef\x11\xa9\x62\x85\x0f\x67\x8b\xe8\xee\x45\x5e\x09\x10\xde\x35\x82\xee\x0e\xa9\x67\xd9\x4f\xd9\xcb\x7d\xa0\xeb\xf0\x42\x2a\x25\xd7\x97\x93\x6b\x29\x33\xc4\xb8\x2a\xe5\x2c\x1c\xfb\xde\x44\x56\x96\x32\x5e\xc8\x69\xaa\xb4\xf7\xfb\x8c\x00\x0b\xe3\xa5\xb1\x2e\xc3\x25\xa1\x4f\xd8\xae\xaf\x4b\x7b\xe7\x28\xff\x82\xf1\x1c\x6d\x7c\x48\xdc\xac\x53\xde\x61\xa1\x39\xeb\x5d\x23\x16\x26\x7b\xe0\x98\xd1\x63\x5f\xd2\x41\x11\xab\x0b\x50\x5d\xa4\xb7\xef\xfd\xa5\x24\x1e\x6b\xfa\x5f\xfe\xa6\xc2\x88\x39\x0a\x6c\x35\x8b\x41\x99\x0b\xc2\x65\xed\xa5\xd5\xef\xcb\x42\x7e\x3b\xc6\x64\x38\x67\x6e\x3c\xdb\x25\x8f\x89\xae\x1e\x58\x7b\x92\x31\xbb\xc3\xd7\xe3\x18\x16\x75\x2e\xac\x65\x73\x31\x1a\x0a\x5c\xd9\x5f\xfd\x16\xc0\xd9\xc5\x19\xd2\xf0\x71\x1d\x6a\x2d\x2f\xfd\x8a\x98\x21\xbe\xd0\x3d\x12\x5b\xa7\x37\xbd\xc9\x4b\x7a\x6f\x6c\x5c\x9a\xc5\xe0\xa5\x25\x5d\x9a\xb6\x78\xda\x25\xb5\x20\x75\x0c\x36\xbd\xc3\xd0\x9c\xbb\x6b\xb7\x24\x75\x30\xc9\x82\xe7\x1e\xa0\x15\xbd\x04\x24\x7d\x77\x61\x4f\x99\x59\xcd\x55\x04\x8d\xea\x09\x43\x93\x32\xc8\xf2\x30\xd5\x0c\x5b\x3c\xa6\x6d\x0f\xd3\xbe\xfa\xf4\x52\x7a\x81\x53\x57\x7f\x89\xc3\x58\xfb\x00\xae\xaf\x4c\xbc\x5c\xd2\x22\xce\xfa\xec\x9f\xc8\x78\xbc\x31\x50\xb0\x24\xb1\xea\x67\x40\xa9\xfb\x49\x6b\xce\x1e\x79\xa9\xdd\xcc\xa9\x68\x47\x4f\xeb\x0f\x6a\x89\x9f\x1c\x51\x60\x0b\x94\x1f\xf4\xea\xdb\x64\x11\x69\x1f\xc7\xc4\x1b\x09\x98\xca\x4c\xe2\x92\x00\xf1\x3a\xc9\xd1\x29\xcf\x4b\xca\x33\x6a\x29\x5e\xb1\xa1\x67\x85\x17\x6a\x3e\x80\xc5\x5f\x9c\x3e\xd2\xee\xe2\x53\x9a\x9d\xf8\x00\x26\x4f\xc0\x58\xbe\x39\xfa\xbe\x7c\xe3\x5b\xc2\x4b\xeb\xcd\x3b\x5f\x1a\x1c\xef\x5d\xc8\x73\xf8\xc1\x56\x37\x14\x65\x39\x5f\x8b\xc0\xee\xae\x3a\x13\x20\xf1\x10\xc8\x98\x2f\x0a\x77\xcf\x8a\x30\x17\x28\x5e\x2c\x70\xa4\xfb\x53\x6e\x64\x8e\xc1\x7b\x33\x14\x75\x3e\x57\x0e\x4c\xcc\x80\x45\xf8\x94\xa4\x33\x9b\x72\x68\x67\x6e\xb0\xc5\x19\x48\xa0\xf0\x21\xcf\x55\x6d\xfa\xb9\x16\xad\x88\x71\x60\x0e\xef\xb3\x6d\xa7\xd6\xd4\x6c\x2d\x2f\x2e\xa8\x64\x6d\x37\x76\x5a\x9d\x42\x71\xe6\x9a\xd8\xdd\x77\x19\x1a\x1e\xa3\xb5\xf7\x2f\x49\xc9\x3b\x68\xfe\xe2\xef\xeb\x93\xe3\x19\x4d\x4c\xdd\xf1\xf2\x52\x79\xd4\x8c\xd1\x61\x9d\x5f\xc2\xcc\x07\x8a\x1d\xba\x03\x49\xa3\xad\x28\x34\xdd\x52\x14\x3c\x47\xf6\x8b\xbc\xf9\x90\xa0\x71\xbe\x8c\xb0\xf7\x09\x2e\x35\xce\xfc\x74\xb9\x59\xb3\x93\x2e\x4d\x7b\x41\x30\x0a\xca\xb7\x6a\xce\x91\x40\x0d\x8b\xdc\xf3\xe0\xe8\xcd\xd9\x23\x84\xf9\xbc\x5b\x47\xec\xef\xab\x41\xe6\xf9\x3d\x9a\x51\xab\x04\x94\x9f\x76\x03\xdf\xbb\xf6\x19\x0c\x40\x51\x8f\x30\xfc\xf3\x39\x5b\xa7\x92\x18\x96\x39\xbd\xde\xf1\xca\x9b\x1d\xae\x40\x33\x3d\xcf\x4d\x05\xeb\x10\x88\x1b\x7f\x59\x67\xdb\xbb\x6a\x33\x2a\x12\xfd\x7c\xee\x8d\x42\x1f\x4d\x12\x8f\xd0\xa6\xa1\xcf\xde\x6c\x8d\x36\xea\x18\x24\x17\x2c\xd5\xba\xb1\xbf\x67\x8e\x21\xac\x99\xe9\x0c\x33\x34\xfc\x7d\x0a\xb4\xd8\x65\x4d\x2d\xd2\xf2\xfb\x69\x7f\xdb\xe7\xdf\xcf\xde\xd1\xf5\x7e\x60\xdf\x9e\x77\xcf\x37\xe1\xdb\x5f\xde\xe7\x2b\xd1\xb9\xfb\xbc\xfe\x20\xff\xe1\x56\x38\xb7\x9e\xfb\xd5\xff\xbd\x35\x98\x6c\x4d\x17\x86\x4c\xd3\x7e\xda\x42\xe4\xd7\x5b\x7b\xd4\x19\xf5\x15\x55\x3c\x81\xef\xf5\x7a\xa4\x7f\x6e\x58\x9d\x27\xcc\xba\x75\x45\x9c\xfa\xbe\xd6\x7f\xd1\x6b\x07\xdd\x3e\xd9\x06\xb4\x83\xb5\x48\x82\xde\x19\xf7\x7e\x00\xb3\x47\x4e\x58\x5d\x29\x60\x83\x7d\x63\xc5\x98\xb7\x35\x39\x63\x05\x81\x93\x74\xfa\x96\xd8\xf8\x04\x9c\xba\x0c\xb2\xe7\x3b\xe0\x12\xb4\xfa\xd4\xf4\xad\x41\xa0\x67\xcf\x9e\x58\x7a\x52\xeb\x27\x5d\x6d\xeb\xe9\x78\x52\x15\xcd\x25\xda\xcf\xcf\xfc\x2b\x26\xfd\xaf\xa2\xeb\x9f\x79\x7d\xf3\x7e\x3e\xf3\xa8\x17\x11\x01\x0f\x87\xba\xa0\x4f\x08\x01\x69\xdd\x44\x72\x3f\x38\x10\x4f\xa2\xe8\xd1\x3d\x1d\x2e\x9a\xb1\xe7\x04\xe1\x4d\x3f\x5e\x5c\x73\x62\xf1\xad\x3e\x9f\xf5\xeb\xe8\x0d\xe5\x9f\xeb\xb7\xf8\x64\x47\x2b\xa5\x6f\xdd\xc8\x9f\xeb\xe7\xed\x18\x4f\xb7\x07\xc7\xfa\xfe\xd4\x48\x37\xfa\xa9\x52\x27\xf9\x71\xbd\x75\x36\x3f\x7f\xc4\x4a\xf9\xa9\x6a\x9c\xff\xc0\x6d\xa8\xc5\xa6\x35\x3e\xd8\x3f\xd6\x26\xf3\xad\xd9\xf7\x8d\xd5\xf9\x8f\x23\x55\x65\x71\x19\x75\x18\x6c\xea\xfd\xb3\x9f\xbc\xfe\xf9\x03\xf7\x83\x54\x06\xb1\xef\xf3\xca\xed\x58\x9d\xad\xd7\xf6\x87\x5a\xf6\x3f\x79\xc0\x67\x9d\x30\x7d\x0c\x20\x69\x7c\xfe\x27\xbd\x85\xe7\x8f\x34\xe1\x9f\xb4\x2f\x59\xa0\x7c\x06\x27\xfe\xa4\x51\xa0\x7d\xeb\xf1\xda\x4b\xe4\x0f\xd5\x8f\xc0\xbf\x98\xba\x02\x29\x0f\x2e\x45\x35\xf9\xe3\x99\xf3\x3f\xae\x33\x02\x67\xab\x53\xea\xaf\xc5\x79\xee\xe0\xa2\x07\xc1\x7d\x87\x04\xf0\x2e\xde\xbd\x28\x40\xe0\x9b\xbf\x55\xe6\xc8\xa8\x78\xe7\xfb\x7f\xd4\x6b\x51\xfc\x18\xa5\x03\xa5\xdf\xaa\xf2\xb1\x09\x88\x59\x33\xf2\xd7\x63\x53\x30\x98\x54\x3e\xf0\xfb\x57\x97\x6e\x9a\x3f\x65\x3f\x1b\x7d\xdf\xf5\x8c\xc3\x1d\xed\x64\x7f\x4e\x5b\xe6\x85\xc7\xc7\x51\x28\xc3\xcd\xe3\xd6\x13\x25\xd9\x3f\xb6\x9c\x15\x27\x4a\x6c\x7f\x59\xdb\x61\x5a\x11\x41\x0b\x7b\x14\x7a\x7b\x86\xee\xed\x01\xab\x32\xc6\x82\x63\x2c\x05\xd2\x4c\xac\x7f\x9c\xef\x66\xed\xd7\xf2\xd1\xfe\x76\xc0\xff\x18\xe0\xf8\x0f\xc0\xbf\xce\xc6\xea\x4e\xb6\xc1\x59\xe2\x31\xff\x38\x0b\x45\xe7\xa6\xbb\xc2\xfc\x17\xce\x1a\x35\x91\xcf\xc9\x1b\x84\xd2\x96\xf7\xd4\x8a\xb6\xef\x9b\x16\x07\xac\xff\xd1\x78\xfd\x21\xa2\x05\xbe\x7f\xeb\xb3\xa9\xc0\x23\xf1\xa1\xdb\x9b\xef\x6f\x7d\x75\xaf\xe4\xcd\x4e\x92\x37\x20\xee\x53\x0a\x68\x56\x84\xce\x95\x80\xf4\xf0\xea\xdd\x17\x67\x40\xe3\xe4\xad\xfb\x0f\x0c\x62\x58\x76\x3e\x6d\x75\x80\xf8\x3e\xe4\x0c\xd8\x15\xa1\x49\xa1\xd4\x7b\x49\x8c\xc0\x0f\x0d\xf3\x3f\xfc\xe7\x62\x13\xbb\xd6\x08\xff\xd7\xde\xce\xd9\x11\x52\x94\xfc\x6b\x3f\xdb\x33\xd2\x82\x8e\x34\xc7\xb5\xfc\x75\x84\x7d\x9d\xfc\x3d\xd0\x8e\x7b\xc2\xfb\xbf\xa4\x1d\x10\x17\xad\x2f\x7e\x08\x33\xd7\x49\xe4\xd2\xc7\x0d\x4f\x83\xed\x20\xf5\xba\x2e\xcb\x86\x20\x12\x6e\x62\xf1\x71\xc2\x36\x52\xec\xe5\x6d\x6f\xb9\xed\x28\x97\xa3\xfd\x54\x6e\xd1\x80\xcf\x21\x40\x2b\xd6\x23\xe4\x10\x16\x0c\x34\x49\x16\x1c\x52\x03\x42\x74\x22\x57\x2a\xf2\xed\xa0\x2c\x20\x9d\x02\x64\xfa\xb5\x96\x02\x8a\x8a\x6e\x81\xd9\x15\x2d\xd4\x5d\xfa\xb9\xc3\x78\x7b\x98\x88\xc2\x76\x49\x8e\xd9\xdb\x9d\xf1\x16\xce\xde\xde\xa0\x59\x3c\x1c\xce\xbe\x40\xee\x72\x80\x64\x81\x3f\x3d\xbd\x88\xe9\x1e\x77\xe7\xdb\x90\x14\xc1\x25\x85\x02\xab\xcd\x56\xcd\xa7\xfb\x0c\x2a\x04\xd0\x2f\xe6\x55\x99\xae\x95\x44\x7d\x6b\x81\xa6\x90\xcb\x84\x2e\x81\x20\x26\x66\xaa\x43\x0f\x91\x82\x30\x3c\x41\x5c\xeb\x5b\x27\x31\x06\x8f\x27\x29\xc3\x79\xce\x05\xd1\xe9\x68\x02\xf3\xd3\x37\x9d\x0b\x45\x0a\x3c\xfe\xd3\x26\xb3\xe0\xfe\x27\x89\xfe\x27\x07\x51\xa7\xaa\x37\xc9\x8c\x50\x02\xb0\xfa\x07\xac\xa5\x2f\x4a\x08\xc4\x4b\x0a\x1b\x14\x83\x30\x19\xd6\x08\x01\x98\x5b\xe0\x70\xaa\x4d\x08\x40\xf9\xaf\x53\x2d\xf1\x06\xbb\x8a\xc0\x4c\xb6\xd6\x54\xa3\x29\x3d\x49\xd9\x0d\xd2\x01\x45\x12\x03\xc2\x55\x4c\xcb\x22\xa1\x86\x22\x70\xcf\x54\x10\x84\x2f\x23\x24\x04\xd0\x8b\x61\xe3\x12\xb6\xcb\x43\x14\x72\xeb\xe0\xc2\x70\x3a\x8a\x56\x6e\xd5\x3c\xb4\x06\xd4\x84\x00\xda\xe0\x60\xa4\xdb\x94\xdf\x83\xc7\x24\x4c\xd6\xda\x26\xf5\xdf\x7a\x84\x0a\x4a\xa4\xcc\x00\x1f\xe2\x09\xae\xbb\x6d\xc2\x10\xb5\x3f\xac\x56\x76\x42\xbd\xb5\x76\xad\x2d\x4d\x90\xff\x12\x03\x7f\x32\x69\x31\xec\x6a\xca\xf3\xf6\xd1\x03\xb6\xe2\x72\xcc\x59\xbf\xcc\x13\xa2\x35\xbe\x3e\xb4\x08\xdc\xd6\xcf\x31\x1d\x06\xee\x51\x9d\x30\x57\x17\xe8\x24\x72\x6f\x85\x4d\xc7\x99\x42\xde\x01\x81\x9a\x27\x9b\xe2\x6e\xe7\x58\x72\x50\x64\x9c\x64\x08\x74\xab\xd2\x2b\x06\x55\xa6\xf4\xeb\xcd\x54\x9b\x46\x04\xd5\x94\x24\x1f\x48\x89\x01\xee\x2a\x1d\x9c\xb3\xff\x66\x31\x19\x5d\x61\x80\xd3\x81\xda\x41\x93\x34\x36\xd2\xaa\x4d\xae\x47\xa5\x28\xc0\x3a\xae\xec\xa0\x7a\x54\xdf\x19\xbb\xc6\xad\x6d\xb3\xd9\x60\x98\x62\x9c\x25\x9a\x7e\x13\xc8\xb1\xa7\xcc\x19\x72\x61\xd0\xa3\x5c\x55\xac\x5c\xf4\x6e\x9d\xb8\xec\xa3\x4f\x27\xc9\x0b\x50\xe9\x02\x39\x2a\x83\x7b\x08\x70\x81\xc7\xb7\x1c\x9e\xe3\xa5\xb3\x19\x2f\x6f\x7a\x8f\xe8\x82\xb2\x3c\x7b\x0b\x7c\xe4\xe0\xf0\x88\x18\x92\x99\x81\xe8\xd6\xb3\xfa\xa5\x34\x81\x3d\x2f\xe8\x9d\xaf\x2c\xec\x71\x36\x66\x5b\x57\xc4\x9a\x8d\xa4\xda\xef\x17\xd2\x5f\x76\x99\xcc\x82\x87\x85\x70\xa2\x10\x13\x88\x0c\xf8\xd1\x75\xc3\xbf\x24\x41\xa0\x95\x2a\xbb\x45\x23\xf9\xa4\x63\x0c\x29\x9b\xc1\x10\x49\x33\xec\x30\x86\xa2\x6d\x95\x47\x50\xfb\x19\x32\x27\x73\x98\xab\x76\x9d\xc9\x2e\x30\xc3\x1a\x52\x6f\x5a\xa9\x89\x20\xa4\x5f\x47\x37\x71\x2d\xbb\x1b\x4f\xcf\x26\x18\x11\xb4\xc3\x65\x15\x08\x3c\xba\xec\xac\xcc\x2b\x14\x16\x5c\x99\x89\x07\x52\x01\x81\xa2\x31\x86\x66\xc1\x43\x47\x56\xe7\x61\x61\x48\x03\xcc\xbc\xee\x95\xdb\x29\xc4\xd2\x8d\x4d\xe5\xc0\x61\x9f\xef\x91\x21\xdd\x2a\xe6\x56\x4c\xdf\x97\xba\xc5\xe3\xac\x1b\x05\x72\x7c\x34\x5f\xa0\x55\x30\x4a\x04\x72\x04\x9c\x4f\xe8\x77\xb3\x17\x7f\x72\xcc\xe8\x45\x7b\x1b\x5d\xc1\xc8\xcf\x01\x4d\x6a\xd6\x5a\x66\x32\x88\x60\x2c\x4a\xd5\x1d\x43\xeb\x7a\x54\x23\x7b\x2c\xe0\xd8\x71\x54\x75\x9c\xa0\xbc\x49\x39\x87\xc9\xe6\x79\x5d\x36\xe2\x91\xe6\xaf\x8c\xab\x1a\x73\x3c\x0e\x7a\xae\xc7\x08\xc1\x71\x1b\xec\x19\x8d\xdc\x8c\x08\x3e\x9e\x65\x45\x20\xc2\x98\x5d\x5e\x07\xa8\x3f\x7e\x34\x47\x04\xf1\x15\xaa\x21\x54\xc5\x5f\x24\x7f\x0e\xf1\xdd\xe2\xd4\xeb\x31\x20\x25\xcf\xf8\xc5\x75\xe4\xa8\x55\x81\xf4\x9a\x7b\xa4\x4b\xc5\x2c\x7b\x40\xe3\xde\xcd\xb9\x63\xff\x60\x4c\x7f\xa8\x74\xad\xbd\xe2\x27\x9a\xde\x92\xbc\x48\xed\x21\x48\x72\x7a\x87\xb0\x02\x4d\x46\x8d\x43\xcc\x4c\x57\xdc\x15\x16\x69\x24\xcd\x90\x3f\xd7\xbe\x1e\x1e\xde\x35\x2a\x51\x0d\xd3\xb9\x19\xac\x3e\x46\xa5\xac\x8d\x2d\x92\x1e\xde\x84\xd9\x9d\x94\x66\x39\x6a\x87\x15\xda\x98\x34\x4a\x34\x26\xd6\xab\x23\xe3\x37\x1e\x97\xeb\x93\xd2\xd5\xfe\x60\x18\xd1\xe3\xda\x83\xba\xfa\x68\xa0\x38\x58\xd2\x2a\xb8\xd6\xe7\x5b\x3d\x35\xb3\x07\xc2\x81\xf4\xcb\x90\x3e\x59\xea\x0f\xab\x41\x76\x6f\x94\x3e\xec\xc2\x2c\xf5\x74\x3f\xf2\xe3\xd2\xcd\x40\x94\x22\x0f\xfb\xd1\xf4\x49\x30\x66\xe2\x8e\x76\x1f\x3c\xf1\x7a\xec\x81\x70\x5f\x1e\xc4\xfe\xd1\x98\x79\xec\xd6\xaf\xb7\x7f\x34\x2b\x35\x20\x10\x87\x10\x12\x0f\x15\xae\x34\x6f\x2b\x9b\x3d\x6a\x03\x88\xed\xd7\xea\x25\x22\x86\xd8\xa6\x96\x65\xf7\x2a\xa2\x8b\x50\x92\xc2\x03\x06\xf5\x86\x50\x5c\x84\xbc\xc4\x5c\x93\x46\x8b\xbd\x94\x42\xc2\x0a\x7a\x13\x22\xbf\x3c\x20\xf4\x94\xfe\x84\xf2\xc7\x61\xef\x1f\x61\xa6\x90\xa0\x78\xda\xa5\x96\x40\xc2\xee\x5b\x90\x2e\x01\x0a\xd6\x22\xd0\x21\x25\xc1\xa5\x1e\xb5\x25\xf3\xd3\xbb\xa2\xa5\xeb\xbe\xde\xe3\x86\xad\xc4\xa3\x91\x4a\xc5\x5d\x6a\xce\x1e\x2f\xac\xb1\x85\x31\xe2\x03\x21\x54\x71\x4e\x3e\xb0\xfc\x25\xb5\x0a\xbf\x00\xd0\xaa\x50\x9a\xed\xe3\x6e\xf0\x50\xb7\xa2\xd9\xcf\xb0\x12\xf5\x22\xa4\xac\xf2\xf0\x6c\x98\x30\x05\x0c\x7c\xcc\x1f\xe3\x98\x2e\x76\x21\x54\x9a\xd9\xbe\x47\xe4\x54\xb9\xc2\x03\x67\xe6\xc2\x70\x77\x2d\x93\x87\x90\xc0\x81\x8d\xd6\xca\xc5\x1f\xd2\x5b\x5b\xf4\x76\x8e\x4d\x5e\x2d\xd1\xe0\x31\xb7\x34\x0a\x17\xb8\xe8\x92\x36\x90\x9a\xbc\x46\xc3\x94\x3e\x66\xbd\x5b\x8f\x72\xa8\x83\x02\x58\x8a\xce\xa2\xec\xf1\xa3\xc7\x24\x3b\x68\x02\x76\x3b\x3e\xb3\xbb\x6b\x0c\xab\x50\xa3\x03\x4f\xd9\xfe\x11\x7a\xfc\xf0\x70\x9a\xac\xdf\x24\x45\x51\x80\x0c\x56\xd8\x27\x0a\xca\xd1\x46\x48\x2e\x5b\x34\x8f\x0f\x97\x27\x9a\xc9\xbd\x1e\xca\x92\x1f\x83\xb7\x35\x1e\xa5\x8b\x44\x82\x07\x1c\x9c\x5e\xed\xb3\x20\x37\x03\xc4\x31\x78\x8b\x20\xab\xe6\xbf\x21\x32\x7b\x97\xc1\xee\xcf\xc3\x83\xa8\xdf\x5c\xcc\xba\x8b\xbc\x06\x94\x9a\xfa\x92\x66\x46\x3f\x79\x3e\xf6\xc3\x73\xd7\xb8\x93\xfc\xa9\x93\x01\xf5\x99\xea\x75\xe7\x23\x11\x8c\x63\xd3\x5e\xe7\x61\xb5\xaa\xea\x31\x33\x73\xa4\xf9\x41\x40\x21\x1d\xef\xf6\xcb\x9a\x5a\xec\xfd\xc3\xf9\x59\xbc\x5e\x56\xe3\xa9\x06\x43\x8a\x20\xef\x75\x62\x67\xe1\x91\xe2\xbd\xcf\xff\x90\xd0\xcf\x95\xa5\x91\xe1\xc7\x45\xdb\x37\x64\x26\xfd\x0c\xed\xa7\xe9\xba\xe5\x23\xfe\x79\x8b\xfa\xa3\x98\xa4\xe7\x9a\xff\x21\x5c\x50\x2a\x16\xff\x10\xe9\xa8\xd7\x2a\xff\xeb\x43\xa6\x19\xe6\x4c\x03\x32\x3b\xfb\xbd\x8b\x14\x81\xf3\xf9\x57\xf9\xa3\x66\xf4\x21\x71\x02\xd7\x8e\xfc\x50\x6e\x36\xb0\x5a\xfe\x4d\x11\x3c\x0a\x7d\x8c\xd1\x45\xf7\x5c\xa1\x22\xc4\x2d\x22\x16\x3c\x1f\xde\x07\x95\xf2\x45\x8d\x9e\x1c\xd2\x31\xbd\x79\x96\xa5\x01\xe5\x49\x3e\xcd\x71\x93\xbd\x99\x35\xca\xf2\x43\xd9\xd7\xe3\x55\x18\x15\x90\x37\x30\xf3\xb7\x24\xc5\xdc\xbc\x79\x63\x9f\xfb\xdf\xfa\xda\xb4\x33\x22\xff\x05\x83\x71\x4b\xa0\xe6\x5a\xa1\x89\x6c\x4c\x7b\x70\x23\xf3\x7a\x5c\xda\xed\xea\xf9\xea\xc9\x4d\x3b\xe4\x90\x06\x59\x55\x0b\xe5\x75\x6e\x55\x0f\x42\xbb\x14\x39\x28\xb3\x9d\xfc\x0a\x21\x84\x58\x0a\xa9\x64\x6e\xf4\x7b\xc4\xd2\xb8\xde\xa0\x6b\x85\xac\x49\x83\xa9\xd4\xdc\xd0\x3a\xe8\x8d\x4b\xf0\x62\x41\x1c\x02\xaf\xdd\x62\xf7\xa1\x68\xe1\x2e\x4b\xff\x06\xca\x1b\xa1\x63\x81\xc1\x2e\x56\x78\xb9\x11\x84\x33\x52\x1c\x35\x30\x60\x76\xf1\xc9\x22\x47\x10\xd2\x78\xb7\x68\xa9\x60\xc0\x68\x95\x0f\x2e\xd3\x8d\xa1\xf9\x90\xef\x68\xf2\xcf\xcc\x90\xe2\x71\x5a\xbd\x25\x31\x10\x55\x5a\xd6\x2a\xe4\x60\x25\xd7\x1c\xbd\x21\x99\x43\xb4\x87\x12\x1f\x5c\xe1\xd1\x64\x2f\x73\xf6\x08\x29\x48\xbf\x1c\x9a\xc6\x51\xc4\x37\xd9\xf5\x3d\x10\x35\xea\x36\xc9\x89\xdc\x03\xc9\x62\x19\x92\x5f\x43\xa3\xb2\x63\xac\xb7\x53\x0f\xcf\x2e\xfe\xcb\xc3\x90\xf3\xb7\x64\x3b\xc2\x93\x36\x5c\x6b\x27\x34\xe0\x70\x2d\xcb\xb3\x6e\x0f\x37\x47\x06\xcd\x0f\x40\xe1\x94\x83\x1c\xfb\x26\x0b\x33\xd8\x3d\x44\x1f\x84\xab\x59\x07\xe2\x29\x0d\x8f\x5d\x03\xe8\x03\x20\xf2\xf7\x02\xd5\xbb\xe2\x36\x65\x58\x2b\xd4\x38\x62\xca\x63\x35\x2b\x42\x59\x86\x5d\xb8\xfa\x41\x34\x61\xda\xe9\x2f\x4b\x88\xe3\xe5\x8d\x7f\x4c\x85\x43\x87\xb9\x85\x1a\xc7\x2b\xd1\xed\x08\x31\x0e\x9f\x44\x56\xa9\x3d\x8c\x35\xc0\xc8\x43\x85\x6a\xdf\x2e\x2b\xcf\x63\xc0\xa1\xac\xa8\x85\xef\xcf\xb2\xe4\x3a\xb8\x53\xff\xc4\x20\xcc\xb2\x89\x73\xd4\xdf\x26\xd0\xb1\xe6\x71\xe2\x62\x4b\xe1\x44\x1b\xfb\x71\xf1\x89\xda\xd3\xdf\xa9\x6f\x30\xa4\x38\x56\x5d\x4f\x37\xfd\x26\x43\xa7\x86\x42\x27\xe5\xf2\x1c\xa0\xe3\xc3\xfe\xa2\x58\x07\xde\x20\x06\x7e\xa0\x44\xc9\x21\x2e\x76\x1c\x45\x5e\x33\x88\x77\x5c\xdb\x79\xdc\xe6\xbd\x90\x47\xce\xfb\x5a\x29\x54\x38\x3c\x7e\x8e\x92\x2f\x05\xa9\xcc\x71\x5c\xc7\x82\xb7\x6c\x5f\xda\x46\x59\xfe\x0a\x59\x0f\xba\x1e\x61\xc3\xc3\x55\xea\x7a\x2f\xe9\x9e\x82\xdc\x4e\xeb\x08\x09\x52\xde\x70\x17\xfe\xb0\xdf\xd9\x71\xf0\xa2\x7d\xb0\x18\x27\xec\xa5\x59\xee\x29\xc8\x80\x1c\x77\x92\x12\x8a\x4d\x80\xa1\xec\x67\x89\xab\x85\x80\x37\xf4\x58\xbe\x28\x10\xc2\xad\xc2\x47\xc9\xb5\x46\xae\xf0\x68\xbe\x5d\xd8\x52\x97\x29\xc4\x9f\x0d\x76\x97\x5f\x59\xcb\x87\x1c\x1a\xac\x18\xd9\x1b\xbc\x3f\xd4\xe5\xb0\x27\x45\x6e\x9b\xdd\xb5\x5b\x95\x5f\xa9\xe9\x83\x28\x4a\x12\xea\x20\xa5\xd5\x24\x90\x05\x69\x42\x2e\xf0\xa0\x9e\xb7\x15\x2f\x65\x3e\x53\x7b\x20\xa8\x2d\xa0\xcb\x2a\xc9\x90\x50\xbb\xc0\x45\x8d\xd4\x01\x24\xde\xc7\xb9\xe5\xbd\xe5\x17\x0c\x79\xbb\x4e\x39\x2f\x07\x8e\x48\x48\xe5\x24\xbb\xd3\x44\x32\x22\xb1\x6c\x91\x8a\x09\x3c\xc7\x49\xfb\x5c\x43\x9b\x0a\x82\x22\x7e\x0f\x63\x0b\x0b\xdf\x3a\x0c\xb5\x7a\x8f\xa0\xcd\xb7\xf7\x42\x9f\x9c\x21\xcf\x3a\x41\x10\x16\xa5\xc6\xe1\x29\x58\x4a\xc7\x80\x8a\x48\xaf\xd7\x97\xa2\x20\x3c\x54\x77\xa5\x87\xfb\x16\xc5\xee\x2b\x44\x41\x62\x09\xf5\xff\x87\x9c\xa5\x51\x63\xd5\xe2\xc7\x51\x74\xd4\x9f\xc9\xe9\x7f\xbc\x2a\x29\x44\x70\x12\xa3\x05\x87\x74\xe7\x4a\x0f\xa8\x21\x15\x07\x3b\xb8\x4c\xe5\x18\xf3\x9f\x1f\x62\xa1\x83\x2b\xe7\xc7\xab\x14\x05\xda\xfd\x7f\x05\x44\x06\x9a\x21\x34\xb2\x78\x74\x58\x8d\x82\x4f\xe6\xdd\x9f\x50\xb7\xc7\xda\xb9\x9b\x68\xa0\x7f\x76\xf8\xb6\x9a\xc8\xc3\x1d\x86\x6f\x04\x1a\xef\x6f\xdf\xcb\xb7\x13\x77\x5c\xc9\xe0\x1d\xa4\xf4\xf7\xca\x47\xcf\xc5\x42\xd6\xd0\x8b\x70\xb5\x10\x1a\xd9\xc7\xdc\xcc\x48\x6c\xa1\x59\x67\xe1\xf4\xb4\x4a\x29\x81\xec\x67\x43\xdf\x63\x18\xc0\x9f\x26\xb3\x16\x54\xe6\x04\xde\x5f\xfb\x20\xbd\x91\x35\x97\x07\x89\x8b\x90\x13\x71\xe6\xe7\xc0\xc2\xc6\xf1\x7a\x6e\xd2\xe5\x76\x7a\x64\x11\x6a\x58\xbe\xbf\x22\x67\xd2\xf5\x5b\x8e\x30\xbc\x57\x66\x16\x3c\x69\x3c\xf0\xdd\x47\x77\x3f\x32\x78\xd1\x77\xed\xe6\x50\x05\xb9\x06\x09\x42\x40\xff\xa9\x87\x5f\x92\x05\x1e\xe8\x0e\x19\x73\xf7\x17\xa3\xba\x11\xcf\x1d\x1f\x17\xb6\x5c\x7a\x64\xde\x30\xb4\x1b\x42\x24\x6a\x00\x20\x2b\xd8\xdf\x05\x08\x91\xb0\xd1\x48\x4b\x3f\x32\xb4\x1c\x32\x24\xcf\x43\x06\x27\x8f\x53\xe8\x09\xb7\xe3\xf4\x52\x67\x1f\x4f\x4a\x2f\x40\xcb\x37\x44\x3e\x7c\x60\x78\xa6\x7d\xd9\x5d\xff\xa6\xb4\x08\xb0\x65\xa2\x1d\xf6\xe8\xef\xd1\x38\x9b\xf6\x41\x3d\x5a\xeb\xcd\xec\xd9\xc7\x24\x6f\xc9\x11\x1e\x62\xdd\xb7\x10\x36\x84\xea\x48\xa0\x4c\x21\x3d\x72\x21\x7d\x42\x22\x26\x6b\x6e\x72\x1d\xd4\xff\xb2\xe9\x10\x82\x08\xb5\x86\xf8\x49\x9d\xa5\xb0\x52\x23\x4f\x1e\x66\x48\x64\xd4\x27\xa8\x06\x9c\x0b\xa5\xa1\x10\x91\xc0\xa0\x91\x52\x2c\x69\xfb\xab\x4e\xb3\xbb\xce\x38\xc3\x10\x2b\x09\xd1\x0f\x0d\x52\xc2\x90\x58\x92\xe2\x8d\xda\x96\x5a\x57\xc7\x0b\xcb\x16\x35\x84\x6b\xff\xdc\x42\x27\x4c\x84\x95\xc8\xc7\xea\xe9\x5f\x4d\xc3\xa1\x7e\x0c\xf5\x41\xaa\x04\xfe\x89\x4f\xe9\x93\x87\x9a\x49\x6e\xee\x92\x2c\x79\x94\x33\x8c\xa3\xf5\xe4\xa5\x7a\x12\x07\x70\x5f\x3d\x28\xf8\x95\x5b\xfa\x65\xf5\x0e\x79\xdb\x81\x8b\x44\x48\xc7\x05\xe1\x7e\xb1\x31\x49\xd6\xf8\x08\x96\x36\xb4\x04\x16\xc8\x4d\x49\xda\xc3\x8e\x61\x13\x57\xf2\x8b\x4b\x10\xd2\x27\xa1\x91\xc2\x01\xd5\xa6\x92\xf2\xd1\xdc\xf0\xe2\x52\xf7\xfb\x4c\x96\xc5\x3d\xdc\xba\x44\x4b\xdb\xba\x1d\x1e\x8f\x14\x24\xad\x18\x03\x54\x49\xbb\x45\x7c\x54\x6d\x56\x88\x8e\x54\xf8\x12\xd8\x30\x81\xbd\xaa\xfb\xdc\x13\x4b\xde\xde\x36\x44\x19\x66\x09\xc3\xcc\x91\xc0\xda\xd7\x1f\xf9\x18\xfa\x5a\xd8\x19\xc6\xa0\x62\xd4\x46\x6e\xea\xfe\x85\xf0\x6d\x6f\x15\x5c\x7b\x40\x07\x08\xa2\xb9\xd5\x5b\x97\x26\x16\x68\xfa\x91\x2e\xdc\x72\x28\x03\xa2\x9f\xaf\xb3\x05\xeb\x49\xc8\x25\x2c\x4e\x97\x23\x52\x6c\x50\xd8\x68\x04\xbd\x9e\xf2\x2d\x87\xc6\x5a\x7a\x97\xfc\xe4\x91\xd3\xe4\xb6\xb2\xfb\xa4\xb5\x0d\x25\x7b\xf6\x33\x05\x8b\x21\xe1\xc2\xf3\x9a\xc1\x87\xd1\xca\xe9\xbd\x08\xdf\xd0\x63\xfc\x48\xd5\x14\xcd\x26\xeb\xa2\xb1\xba\xbe\xb8\xfa\x58\x53\x24\x29\x17\x55\x7c\x89\x40\x94\xeb\x20\xf4\x5a\x72\xfb\xa5\xe8\x75\x81\xf6\xfd\x12\x35\x4c\xe1\xb3\x3f\x21\xb0\x99\x73\x30\xce\xa7\xab\xe3\x3a\x2e\xd1\x33\xb5\x12\x42\x41\x42\xcc\x08\x25\xad\x50\xd9\x72\x33\x63\xd9\x42\xf3\xa5\xf6\xd4\x75\xb1\xbb\x3d\xc7\xd6\xca\x2e\xf5\x97\xe2\xf8\x4e\x74\x2d\x59\x97\xa0\x8f\x99\xfa\x49\xfe\x74\x2b\x0a\x46\xef\x52\x2f\xf4\x7c\xbb\x99\xad\xa9\xff\x2f\x0a\x69\xa0\x92\xca\x24\xfd\x09\xdc\x87\x23\xb4\x58\x71\x27\xae\x8e\xc6\x22\x15\x9f\x29\xc1\xef\x75\xed\xad\xd4\x6b\x27\xe0\xac\x9e\x9a\xb9\x8f\xda\x58\x82\x90\x12\xf2\x09\xe3\xe8\x31\x64\xcc\xf1\xd7\x7e\xe2\xb7\x3f\xce\x35\x2d\x7c\x4f\xa7\x34\x5f\x4e\x1c\x31\x0b\xa3\x22\xbc\xf4\x53\xe2\xa7\x38\x33\x27\x19\x53\xe6\xca\xd0\xba\xdd\x86\x28\xbb\x63\x2a\x6b\x39\x64\xc1\xd3\xca\xdd\x2e\xbd\x19\x98\x9c\x89\x86\x99\x5e\x00\xd4\x98\x6b\xe8\x34\xa1\x2b\x1f\x9a\x34\x40\xec\xb1\xae\x45\x3f\xd7\x1b\xcb\x7d\x6e\xb9\x4f\x56\x17\xa5\x90\x85\xf1\xdc\x61\xd7\x8c\x79\xf9\xb8\xdb\x18\x45\x2a\xb1\x1c\x2a\x8e\xf5\x56\xa2\x39\x83\x6f\x6f\x66\xb2\x77\xec\x90\xca\x0f\x24\x66\x86\x10\xa1\x39\x0a\x13\xa3\x61\x29\xff\xaf\x8f\x8f\x2b\x46\xf1\x42\x66\x86\xc3\xbb\xb1\xbd\x5b\x11\xc7\x1a\x8d\xb3\xe6\xb5\x30\x6b\xd8\xf4\x28\xc0\xd2\x36\x6f\xfd\x03\xb7\xad\xe9\xd1\xe6\xb7\xad\xae\x92\x86\xd9\x25\x8b\xb3\x0f\xa5\x5a\x93\x00\xef\xc9\xde\x66\x28\x4c\xbd\x07\x4c\x78\x95\xba\x52\xda\x85\xd7\xe8\xd3\x76\xc9\x07\x68\x66\x08\x27\xa5\x88\xf6\x72\x6e\xa3\x8e\xd1\x9a\xd0\xd7\x1c\x76\xda\xb2\x8c\xa1\x64\x2d\xba\x6c\xa9\x8c\x7a\x48\x92\x7b\x36\x42\xc7\xc6\x9a\x72\x4d\xd9\x67\x46\xbb\xf6\x3c\x69\xa7\xa5\x9c\xa1\x98\xc3\xa7\xca\xb6\x07\x2f\x1c\x67\xd9\x0d\xe1\x82\x5d\xfe\xe3\xd1\x76\x2e\x84\xe9\xc2\x0e\xef\xbf\x46\x71\x87\x9c\xcd\x93\x81\xf7\x30\x43\xd5\xc3\xcc\x6f\x1a\xef\x26\x6b\x63\x4f\xa4\x4f\x8f\xa6\xa8\x71\xb1\x7a\x74\xec\xb7\x97\x91\x8a\x43\x43\x81\x5f\x9d\xd5\x9a\x4f\x0e\xf8\x75\x1e\x95\x4e\x0b\xce\xd3\x98\x3b\xcf\x4d\x59\x67\x9e\x87\xea\x5d\x79\x33\x3b\x9e\x5c\x27\x99\x4f\x28\xdb\xbc\x3b\x77\x6b\x75\x68\x8f\x4a\x40\xe4\xe2\xf0\x49\x77\x75\x17\x7f\xea\x3a\xbe\x33\x1d\x86\x33\x29\x4a\x23\xe7\x1a\x14\x6f\x56\xe6\x01\x76\x90\x0b\x4e\x13\x25\x68\xea\xaa\xf7\x5a\x42\x38\xfe\xea\x98\x2d\x3f\x1b\x44\x6f\x86\xe8\xbe\x76\x56\xd3\x3d\xa5\x8a\x53\xf2\xa3\x57\x2b\x11\xe1\xbf\x52\x41\x81\xd4\x75\x2c\x9b\xf3\xa4\x4d\x78\x7a\xa2\xcb\x27\xb1\x98\x9e\xa1\x94\xee\x85\xd0\x5b\xd9\x7d\xd0\x9c\xe3\xb1\x1d\x86\x3d\x29\x57\xef\x26\xb7\x6e\x2f\x14\x2f\x07\xc6\x41\xe3\x4c\x51\x05\x95\x30\x9b\x40\x8f\xd5\x1f\xaf\xf4\x1b\x8b\x94\x55\x3d\x64\xb3\xc7\x91\x6d\x71\x33\x07\x8e\x4e\x41\x2f\x85\x62\xdf\x6e\xf1\x71\x80\x35\xd0\xe0\x88\x66\xe7\x9a\x7f\xab\x22\xcf\xed\x66\x9c\x8a\xa8\x6c\x32\xb8\x2e\xcf\xf3\xa6\xa1\x4e\x14\x34\xd7\xa4\xc0\x53\x0f\x49\xfd\x40\x80\xe7\x1f\xad\xa7\x23\x99\xb2\xe6\x3f\x11\xe6\x2e\x93\x95\x3d\x2c\xe9\x61\x76\x68\xf7\x59\xdb\x58\xbb\x5c\xc7\x2a\x23\xd0\x5c\x30\xe3\xc7\x38\x62\x38\x04\xd5\xcc\x52\x41\x07\x4a\x25\xd0\xae\x16\x49\xd1\xba\xc5\xa9\x6a\x89\xae\xe2\x3a\x69\x3b\x5d\x57\x35\xa5\xfe\x09\x06\x77\x4f\x19\x9d\x7c\xe5\xd0\x06\xfa\xa9\x12\xdd\x81\x04\xd0\xc4\xe7\x15\xfa\x3f\xa5\x09\x00\xf5\x4d\xca\x09\xb6\x37\xa6\xa4\x1a\x04\xbc\x15\x1f\xae\x99\x1a\x38\x73\x96\x46\x90\x86\x67\x3b\x26\x8e\x73\x69\x44\x36\x72\xe1\x34\x0c\x6d\x26\x95\x83\x5a\xa1\xcb\xd2\x3c\xfa\xa9\x8e\x34\x71\x95\x62\x9f\x52\x7e\xad\x63\x8e\xbd\x4d\x26\x44\x36\x0f\xb4\x35\x18\xab\x5f\x7a\xd7\x76\x26\x75\xff\x2e\x7a\x01\x15\xc1\xc5\x17\xa6\xcc\x7c\xb8\xcb\xb8\x88\xda\x6c\xe6\x14\x7b\x45\x20\xe8\x11\x01\xb3\x5d\xb1\x56\xf1\x56\xa4\xbf\x73\x1d\xd2\xbb\x02\x58\x15\xc2\x6c\x6e\xdb\x17\x64\xef\xa9\xca\x73\x94\x2c\xd5\x1a\xb4\xa4\x28\x85\x64\xfd\x8d\x68\xd5\x9b\x9d\xa9\x96\xe6\xc7\x04\xd7\xf6\x1a\x31\xc4\x28\xd1\x5f\x6c\xd6\x4f\xc9\x61\x68\xc5\x35\xbb\xb8\xf7\xae\x52\x3f\x31\x26\xc6\x4d\x3d\x33\x70\x73\xf9\xd4\x5a\x3e\xe9\x9e\x8b\xa0\x19\x2a\x7a\xe1\xe3\xcf\xa9\x8b\x0d\xee\x3a\xd2\xf0\x1b\x74\x79\xda\x75\x28\xa3\x23\xde\xc2\x8c\x2d\xe5\x55\xeb\xe7\x07\x97\x07\xad\x94\x2d\xe4\x2e\x87\x62\xd2\xc0\xd1\xab\x0e\x90\x2c\x9f\x42\x3c\x07\xa3\x1f\xac\x77\x73\x0a\xe5\xa9\x9c\xfa\x50\x4d\x8a\x31\x71\xb7\xaf\xa1\x5e\x12\xee\xd1\x13\x4d\x54\x6b\x2b\xec\x31\x86\x0c\x9b\x11\xd1\xfa\x45\x4d\x3a\x58\xaa\x8e\xf0\xd1\x7c\xeb\xd7\x2e\xa6\x3a\x80\x04\x31\x71\xd6\xdc\x69\x3b\x15\x30\xec\xa2\x44\x97\xd4\x5a\x51\x68\xf2\x45\x0b\x77\x69\x7d\x07\xcd\xb0\xd7\x32\x8e\xdf\xe3\x99\xb8\xeb\x67\x8c\x87\x76\xf0\x67\x31\xec\x1e\x01\x6c\xd6\xf8\x1e\xb8\x44\xc7\x31\x99\x2e\x25\xbe\x5b\xdf\x0f\x82\xc3\xa0\x40\xe4\x9a\x32\x52\x80\x76\x21\x22\x37\xd0\x0f\x1f\xc3\x5c\x15\xcf\x96\x7e\xd3\xc9\x26\x8e\x44\x89\x24\xe0\x73\x61\xbc\x44\x0e\x36\x2f\x28\x37\x49\xb6\x54\x88\x20\xb3\xb6\x7c\x35\x11\xa3\x33\xdd\x6b\x4c\x88\x99\x8c\x1c\x91\xcf\xb2\x17\x39\xbc\x0b\x01\xa9\x16\xf4\x90\xae\xce\x5d\x3d\xd0\x38\xe2\x43\x05\x2d\x53\x65\xeb\x26\x64\x69\x4d\x45\xb3\xed\xbe\xe8\xe9\xf7\x8a\x22\x5c\x06\xe9\x78\x1f\x27\xd3\x99\x3c\xfc\xc1\x1a\x89\x0f\xb7\x8f\xb2\x94\xe8\x0e\xdc\xa5\xaf\x26\x86\xd4\x54\xc7\xe5\x70\x95\x76\xd0\x01\x07\x6c\x09\x6d\x23\xdc\xdb\x2c\xab\x0f\xc9\x20\xd8\x53\xd5\x05\x46\x54\x9f\x76\xef\x8d\x34\xce\x44\xea\xee\xac\xd1\x13\x6f\x86\x69\x4d\x45\x65\xb8\x54\x92\x9d\xcf\x3b\xec\x81\x46\x40\x17\x13\x30\xa3\x14\x95\xd9\xfc\x05\x0c\x3d\x24\x9a\xc8\xae\xe0\x2a\x9b\x7b\x2e\x75\x83\xad\xa0\x96\x66\xda\x3c\xd8\x9d\x96\x3d\x6c\xdc\xe8\x7a\x82\x68\x42\x6b\x96\x5c\xd1\x59\x10\x9f\xfb\x96\xbd\x6a\x2a\xd7\xa9\x74\x6a\x6c\x86\x22\x14\x13\x86\xd0\x10\xeb\xe2\x63\x6a\xda\xe8\xd4\xa4\x9d\x10\x6f\x45\x3d\x24\x07\x29\xe8\x31\x51\x14\x3d\x60\xe6\x89\x09\xe3\x50\xa3\x54\x27\x2b\x11\xdf\x9d\xec\x3b\x37\xd3\x90\xe6\x12\x9f\xb5\x55\xfa\x4a\x7d\xe4\x37\xe3\xd3\x5f\xd5\x99\x45\x2b\x73\x7a\xcf\xb7\xb8\x53\x92\xac\x5a\x44\xd4\xa5\xe5\xdc\x13\xb5\x96\xa0\x5f\xe0\xfb\x5b\xb6\x2b\xd0\x62\xc4\x33\xcb\xf4\xbc\x0e\xae\x94\x43\x4c\xcb\x5e\x58\xe8\x34\x70\x24\x0d\xc9\x07\x45\xd2\x4b\x54\x5a\x3a\x19\x65\x01\xc7\x66\x89\x1b\x7b\x6b\x2b\xf1\x27\xbb\x3f\x14\x57\xaa\x57\xe6\x47\xc9\x31\x75\xa1\x66\x85\x48\x3a\xfe\x0e\x68\xcb\xfe\xa1\xac\x94\x57\xd5\x8f\xae\xa6\xa4\x13\x76\xf3\x96\x5c\x2a\xe3\x1a\x3f\x78\xfc\x12\x1f\xb7\x59\x1d\xaf\x34\xdf\x1f\x31\xb3\x33\x33\x7a\xd2\xec\xe2\x98\x5f\x2e\xb5\xf4\x52\x46\x2f\x24\x40\xa9\x72\xa4\x06\x63\x9a\x3c\xbb\xcc\xde\xc4\xa6\x13\x4e\x5b\xc7\xf7\xdf\x88\x8d\xf4\xa0\xb8\xd2\x7f\x6e\x1d\xc0\x82\x1b\x35\xfd\x60\x0f\xef\x15\x94\x07\xff\x69\xf0\x70\x6b\xc9\x8c\x0d\x22\x23\x98\xe1\xcf\x8d\x06\x49\x12\x64\xff\x23\x65\xcf\x0a\x48\x2f\x3d\x3f\xc2\xa5\xac\x1f\x60\x55\xf5\xa0\x2c\x19\x34\x5e\x35\xde\x96\xe0\x0a\x3f\x58\xd3\xa6\xfe\xda\x00\x06\xf1\x70\x23\x96\xf9\x94\xd9\xac\x24\x08\x5d\x13\x76\x3a\x54\x68\x72\x10\xa9\x97\x4f\xd5\x76\xb2\xd6\x17\xc2\x3f\x78\xc8\xfd\x24\x59\xa7\xbe\x41\xcd\x20\x5d\xac\xea\xa5\xef\x2f\x39\xaf\x60\x2e\x37\xf5\x1f\x02\x51\x6a\x99\x41\x1c\xca\xf3\x14\xfe\x53\x80\xdd\x1d\x70\x3f\xbf\x69\x42\x40\x59\x5a\x51\x47\x9d\x7f\x6b\x58\x8a\x71\x31\x3b\xc7\xc3\x60\xcd\xdc\x49\xba\xd2\x48\x76\x2a\xa3\x58\xd2\xc9\xc5\x17\xdd\xc0\x10\xdd\x6a\x4f\xa6\xdf\xfc\xf8\xfb\xaf\xe0\x14\x0a\xdf\xac\xa5\xfe\xdf\xff\xef\xff\xf9\xff\x03\x00\x00\xff\xff\x71\x1d\x08\x34\x38\x36\x05\x00") + +func dataEnglishJsonBytes() ([]byte, error) { + return bindataRead( + _dataEnglishJson, + "data/English.json", + ) +} + +func dataEnglishJson() (*asset, error) { + bytes, err := dataEnglishJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/English.json", size: 341560, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dataFemalenamesJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x6c\xbd\x4b\xb2\xab\xbc\xd3\xe5\xdd\x7f\x47\xf1\xc6\xbf\xfd\x8d\xe0\x1b\x43\xcd\xa0\xa2\x1a\x32\xc8\x20\x5b\x80\x0f\x17\xef\x83\x2b\x6a\xee\xa5\x14\xde\xe4\x6f\x71\x2a\xe2\x69\x1c\x1e\x6f\x63\x90\x52\x79\x5d\xb9\xf2\x7f\xff\xd7\x7f\xff\xf7\x7f\xfe\x47\x5a\xd6\xff\xfc\xff\xff\xfd\x3f\xcb\xbf\xcb\xd5\x10\xe6\xfd\x3f\xff\xdf\xf1\xef\x57\x58\xe7\xd4\xa4\xf0\x7b\x9d\xd3\xd8\x9e\x17\xb7\x30\x97\xff\xce\xcb\x98\xd3\x27\xdc\xe2\xda\xff\xfe\x8f\x47\x1c\xc7\x74\x8f\xf3\xef\x75\xb9\xb1\xdf\x69\xd9\x96\x30\xe2\x93\x2e\xcc\x71\xfd\xbd\x6e\xa7\x79\x5a\xfb\xdd\x7f\x75\x39\xbf\x37\x86\xb1\x39\x3f\x78\x96\x2f\x9d\x37\x29\x3f\xbd\x9e\x9f\xf4\x31\xfb\x27\xe5\x97\x5a\x7f\xce\x76\x1a\xc7\xf3\xa2\x09\xf3\x94\x7f\x2f\xe6\xcd\x1f\x7e\xe9\xcb\x27\xfe\x80\xa9\x29\x77\xcc\xf1\x7c\xa2\xb0\xf9\x0d\x97\xb2\x08\xe7\xf7\x9e\x69\xb8\xc5\x39\x9f\x0f\xd2\xc6\xdb\x84\x8f\x1f\x71\x59\x52\xe3\x5f\xed\xd3\x9c\xe3\xf9\xc7\xcd\x3e\xae\xbd\xaf\x51\x18\xbb\x98\xcf\xab\xa1\x2c\xf0\xe2\x0b\x71\x2b\xaf\xee\x7b\x11\x86\xdd\xbf\xe5\xaf\x37\xc7\x5b\x6c\xfc\xe7\xde\x69\xee\xd2\xe8\x3f\xf0\x0c\x6b\x9f\xa3\x2f\xd4\x2b\x0c\xfc\xc1\x30\xaf\x7d\xc0\x8b\xcc\xf8\xb9\x80\x1f\x5f\xd6\xf8\xea\xc3\x98\xa2\xac\xea\x7e\xde\xb6\xe9\xe7\x22\x61\x69\x8c\x94\x84\xf3\xe2\x11\x46\xdf\xf9\xa6\x3c\x51\x9c\xf1\xa7\xf7\xb9\x6c\x78\x5c\xf0\x72\xe7\xf7\xa6\xbd\x39\xff\xac\x4d\xc1\xbf\x13\x72\xf2\x4f\x1e\x5b\xf6\xdf\xea\x63\xbd\xff\xef\xe5\x1a\xe7\xb8\x40\x30\xca\x63\xfe\x5e\x74\x79\x82\xb4\xc6\x77\xc4\xfb\x3c\x62\xc0\xbb\xc5\x79\xcf\x2e\x27\xb9\x9d\x63\xcb\xf5\x95\xb7\x79\x4c\xfe\xcd\xb0\xf4\xd8\xfa\xc7\xd6\x26\x97\xbe\x79\x5a\xb8\x3e\x78\x9d\x67\x11\xc3\xf3\x4b\xe5\x83\x29\xe3\x4d\xdb\xfd\xba\xe4\xb2\xd5\xe7\xa7\xf6\x54\x78\xf1\x5b\x79\x3d\x11\xd9\x31\xf9\xcf\xaf\x61\x70\xd9\x4a\x45\xe8\x64\xe3\xce\x03\x51\x56\xeb\x7c\xf8\x60\x87\x85\x7b\x8d\xb5\xb3\xa3\x18\xe5\xa9\x66\xff\x30\x4f\x1b\x7e\x79\x81\x72\x29\xfb\x8e\xdf\x6d\xfe\x6c\xe5\x30\xf8\xff\xf9\xa1\x34\xde\xca\xf9\x4e\xb2\xfd\x7e\x1c\xb6\x9b\x2b\x95\xc9\x37\x9b\x0b\xf5\xea\xf7\x9c\xfd\xa3\x71\x9a\x07\xff\x2c\x6c\x7e\x3c\x4c\xe4\xf8\x7c\xfe\x9b\x39\x95\x3b\xf8\x46\xc7\x22\x15\xbb\xef\xec\x2d\xf9\x79\x8b\x5d\xe7\x5b\x36\xef\xcb\x1a\xb2\x0b\x60\x68\xf7\xf3\x31\xe6\xb4\xfa\x0f\x87\x1f\x17\x3f\x79\xd9\x7b\xd9\x86\x38\xba\xb0\xac\x65\x2b\xce\xfb\xc7\xd6\x1f\x77\x4d\xf7\x7b\x18\x77\x9c\xd7\xc1\xb5\x40\x11\x3e\xd7\x8f\x45\xe1\x9f\x7f\xd6\x95\xdb\xf9\x9a\x47\x7c\xf2\x4e\xcd\x2a\xe7\x85\xc2\x5c\x54\xa2\xeb\xbb\x38\xbb\x75\x59\xf6\xfc\xf6\xef\x3c\x8a\xcc\xbf\x7a\xec\x6a\x91\xd2\x3c\x40\x55\x96\x35\x76\x8d\x5c\xee\x94\x7c\x2f\xe2\x0a\x89\x33\x45\xed\x8b\x9f\x83\x2a\x9e\xc7\x34\x8b\xa2\xe2\x55\xd1\xf9\x79\x5a\x57\xff\xf3\x69\x84\xb2\x8e\x0b\x75\x87\xc9\x02\xee\x1c\x07\x7f\xd4\xc7\x56\x8e\xec\x0a\xd9\xc0\xc5\xdc\x4f\x90\xd5\x3e\x7c\xfc\xb9\x83\x59\x0e\xd7\x38\xd4\xbc\x37\x7f\xc8\xf0\x2a\xe7\xe9\x94\xb4\xb8\x40\xbb\x35\x19\x27\x26\x6f\x4d\x82\xc5\x7a\x84\x21\x89\x1a\xc2\xa3\xe7\xa2\xcf\xa6\xf3\x97\xdf\x21\x47\x2c\x4a\x6b\x8a\x1d\x37\x1a\x62\x07\x1d\x96\xe9\x1d\x2c\xdb\x87\xf7\x3d\x8c\xe6\x79\xd9\x05\x7f\xee\xf2\xa2\x34\x2d\x65\xd9\xa1\x57\x8a\x32\x92\x75\x7f\x94\xf7\x38\x9f\x75\xf6\xd3\xd3\xc5\x39\xe4\x16\x7b\x60\x56\xd9\x77\xbe\xa1\xc6\xab\x6f\x0c\x65\x35\x53\x2a\x8a\x7a\x82\xaf\x00\xfd\x3a\xc7\x0e\x9a\xa1\xfc\x76\x03\x9d\x59\x5d\x23\x5f\xa6\xc9\xce\xde\x82\x17\xa4\xd6\x0e\x5b\xd1\x7a\xe7\x6d\xf7\xf7\x84\x65\xb2\x25\x83\xcc\x3d\x36\xb5\x93\x2e\xf2\x2d\xf4\x4d\xd1\x14\x0d\x2c\x3e\x0c\xfe\x18\xcf\xaf\xa7\x16\x96\xff\x0d\x8d\x54\x94\x50\xd9\x00\x97\xc2\x09\xef\x7c\x2b\xaa\x66\x85\x6e\x30\x8f\x80\xba\xad\xbc\xe5\xea\x5f\xdd\xa7\x4c\xdd\x6b\x96\x91\x2f\x63\x3b\xe2\xdf\x2d\xda\x1e\x17\x66\xa0\x7c\xb7\xde\xe5\x8b\xf0\x6e\x02\x4f\xfe\x06\x51\x5d\xfc\x0e\xea\x6b\x52\xf2\x8a\x3a\x7a\x26\x9c\x71\x57\x14\x2b\x4e\x88\x19\x59\x3a\xbb\x45\xa1\xc0\x17\x2a\xbe\x81\x9b\xb4\x22\x6a\xeb\xbc\xb5\x11\x87\xcb\x8d\xe9\x34\xee\x70\x82\xb3\xec\x91\x6f\xfa\x4f\xc2\x2b\x51\xac\x9e\x87\xa5\xf6\x37\x59\xf0\x8e\x63\x28\x26\x01\x87\xbf\x1b\x5d\xc6\xca\x39\x09\xa2\xba\x70\x86\x6e\x72\x97\x36\x8a\x70\x9a\x27\x89\x4d\x7b\xc5\xf2\xdd\xf3\x17\xe4\x36\x83\x9d\x28\x1c\xa9\x22\x28\xb8\x0c\x66\x28\x5d\x3e\x8b\xa7\x80\xd5\x2d\xee\x99\xaf\xde\x54\xfc\xce\x00\x9b\x55\x96\x06\x66\xaa\xda\x4b\x6a\xb1\xe2\x0b\xf9\x7d\x42\xd9\x4b\x9e\x08\x28\x1c\x93\x53\x8f\x0c\x22\xef\x32\x24\x1a\xc6\x41\x5f\xab\xd8\x8e\xd6\xf7\x36\xd3\x91\xce\x3b\x7e\xfb\x9d\xa6\x8c\xc7\xde\xe6\x75\xf4\x0d\xad\xe1\x8c\xeb\x8d\x95\x5b\x5f\x1d\x60\x68\x98\xe2\x5a\x62\x61\x44\x4c\xf1\x8c\xeb\xca\xab\xbf\xf8\x7e\x82\x13\x32\x94\x20\x8b\xde\xd5\xe2\x8a\x74\xd8\xe7\x15\x41\x4a\x44\x9c\x53\xfd\x41\xb8\x78\x8c\x12\x4a\x94\xb7\x78\xe4\x54\x5c\x58\x97\x53\xb3\xf2\x93\xb8\xbe\x5c\xd6\x11\xaf\x65\x31\x1c\x3e\x49\x8c\xb1\x16\x8d\xc0\x8a\xbd\xe9\x5d\xf8\xc6\x11\xf1\x9c\x47\x9e\xe5\x79\xcd\x80\x21\xf0\x9b\x86\x24\xeb\x7b\xfe\xd8\x94\x3b\xd7\xcb\x22\x4b\xe6\xa3\x8d\xe2\x0e\xf9\xfe\xe5\x38\x8d\x81\xef\x75\x7e\x72\x8f\x6a\xd6\x26\x84\x4c\x43\x2a\xbb\x3e\xf8\x11\xc4\xa1\x2e\xa1\xd6\xd3\xd5\xe8\x44\xa3\x6d\x82\xe4\x41\xce\xf3\xe2\x9b\x17\x0d\x92\xfc\xfe\xd8\xa6\x21\xb8\x33\xdc\xd3\xf1\x6f\x43\xf2\x1d\x9b\xc3\x80\x37\xa9\x2e\x56\x82\xcd\x7a\xd2\xdb\x9e\xb9\x2f\xc5\x35\x9a\x71\x08\xc7\x76\xc1\xea\xd8\x65\xc0\x11\x1e\xe1\x91\x74\x5b\x68\x43\xde\x5e\x50\x37\xa2\x51\x8e\x78\x1e\x5e\xcf\x22\x51\x52\x03\xb1\xb9\x87\xdd\xb5\x5b\x1b\xa8\xf7\x20\xd8\x4b\xb8\xf1\xc9\xd3\x72\x39\x03\xdd\x56\x5e\xd4\xcd\x4e\x2f\x47\xa9\xaf\x4e\xde\xb9\xfa\x03\xad\x5d\x13\x8b\x90\xa5\x8b\x2e\x3e\xdf\xaa\xc4\x9e\xae\x27\x6e\xc5\xd2\x15\x87\xc6\x1f\x09\xfe\x6f\x31\x25\x17\xef\xca\x9f\x15\x41\x65\xdc\xc4\x29\x18\x71\x60\xca\x61\xff\xb8\x0e\x92\xb5\x6c\x25\xd6\xb1\x10\x1d\x29\x82\x2c\x96\xbc\x6e\x53\x2a\xe1\x9c\xbf\xec\x98\xfe\x6c\x78\x34\x7f\x9f\x07\xcd\x7a\x39\x79\x99\x02\xbf\x43\xff\x8e\x17\xb9\x85\xf7\x5c\x9e\xd3\xdf\xe7\x1e\x2e\x2a\x77\x87\xcf\x35\xbd\x3c\xb4\x09\x62\x36\xf6\x37\x3d\x86\xf2\x76\x93\xaf\x6b\xde\xce\x45\x59\x36\x2c\x71\x51\xae\x88\x1c\x2c\xec\x09\x72\x50\x5c\x8e\x9f\xb3\x1e\x28\x78\xc1\x19\xc1\x5c\x86\xa2\x2f\x76\x75\xc4\xa1\x2e\x7f\xd5\xfb\x96\xad\x53\x12\x0f\xc7\xd6\x40\xb2\x0d\x61\x14\x6f\x48\xfe\xf8\xe5\x9a\xc3\xe2\xf8\x73\x2b\x7e\xfa\x44\xcb\x52\x64\xbd\xed\xa0\x2e\xe8\xc0\x34\xdc\xfd\x1c\xd6\x69\xa7\x1a\xf7\x37\xb5\x65\xf0\x3f\xec\xca\xf6\xd2\x1b\xc0\xcb\x26\x28\x2d\x73\x84\xa9\x71\x5c\x8f\x1c\xc6\x6e\x84\xbc\xcc\xb4\xd0\x16\x8f\xbb\x91\x88\xb0\x56\xf5\xd4\xd0\x40\xc1\x0a\xac\xd4\xb2\xe5\xe9\x65\xcf\xe0\xa6\xfd\x0d\xe2\x2e\x77\xa6\x9e\xf1\xf1\x0d\xd9\x85\xb6\x9c\x74\xfc\xb1\x85\xb2\x74\x9f\x72\xfc\x2b\x96\xe8\x36\x4f\xd3\x53\x1c\x4a\x78\xbe\x4b\x68\xe9\x6c\x16\xa1\x68\xb9\x99\x66\x4d\x12\x0e\x96\x8b\x5c\xe4\x4f\x94\x13\xdf\xc3\x56\x59\x72\x24\x50\x77\xdd\xfc\xb3\xf2\x13\x51\xf3\x64\xe6\x3d\x53\xcf\x35\xdc\xba\x48\x03\xff\xd4\xec\xc1\xb1\x4a\x23\xf4\x29\x03\xa5\xb2\x7b\x6e\x21\xaa\xe7\xa2\x16\x53\x12\x1e\xe2\xcf\xd3\xe0\xc3\xe8\x14\xff\x26\x4a\x02\x21\x4a\x8a\xaf\x8d\x4b\xb1\x34\x91\xa7\x68\xa4\x87\x37\x26\x04\x4e\xf0\x45\xbe\x59\x2c\x24\x03\x23\x14\x63\x9c\x25\xcd\x50\x04\x50\xb6\x07\xd2\xdb\x5c\x0c\x6e\xe4\xc9\x8f\xa9\xeb\xfd\x9e\x5d\x0f\x9f\x6e\x7a\x21\x1b\x1b\x2d\x63\x04\xc9\xd2\x8c\x70\x57\xc2\xa2\xf2\x7f\x46\x18\x16\x1e\xc0\x39\xd8\x11\x39\x2d\x52\x1c\xcd\x22\x21\x45\x90\x77\x04\x3f\x0f\xe8\x10\xf3\xc0\x5c\x9f\x60\x6b\x2e\x89\xf9\x60\x5a\x4b\xf4\x23\x32\x78\xb4\xa4\x89\x39\x97\x58\x2e\x90\x19\xe7\x13\x17\x67\x21\x52\xb3\x24\xc8\x00\xe5\x4e\xbc\xee\xa2\xd6\x1f\xfe\x4c\x48\xd0\x64\xbc\x52\x4b\x7d\x36\x30\xc1\x24\x41\xcb\x40\x03\x5b\x7f\x94\x61\xa0\xa4\x8d\xee\xe9\xa2\x74\x19\x07\xcc\x0c\x50\xdb\xf4\x97\x06\x00\x2b\x68\xd9\x6e\x78\x25\x14\x2c\xe4\xc4\x1f\x53\xcf\xf3\x61\x55\x02\x38\xa5\x03\x33\x2e\x25\x1c\x4a\xf8\xbb\x1f\x88\x1f\x0b\x1a\xf1\x36\x49\xb0\x7d\x3b\x3f\xc1\x59\x33\xc9\x4e\xb8\xf3\x2d\x21\x7d\x32\x71\x07\x7e\xd2\x98\xee\x4c\x41\xeb\x09\xb2\x63\x89\xac\x65\x79\x10\xbf\x4f\x48\x83\x9f\x51\xee\x71\xd1\xda\x23\xd7\x89\xe1\xf4\x40\x83\xaa\x4e\x5b\x79\x31\xb8\x80\x2f\xcd\x97\xcc\x4c\x83\x1d\x3e\x2b\xfc\xc0\x96\x67\xbe\x18\x10\x86\x52\x16\xcb\xba\xbe\xb0\x20\x9b\xdf\x9c\x99\x95\x6d\x68\xc2\xca\xa2\x31\x05\x55\x8e\xa7\xa9\x3e\x17\x9b\x1f\x3f\x9f\x0d\x33\xcf\x2d\x72\x58\x56\x4f\x79\xba\x3b\x60\x02\x44\xe1\x9a\x66\xa4\x9c\xe2\xfd\x8e\x2d\xe3\xb2\x97\xbb\xc0\xb3\xe5\xee\x95\x70\x7b\xa2\x85\x64\x80\x45\x7d\x61\x59\x4a\x38\x6f\xf4\xf8\xcb\x2f\x61\x0f\xc6\xf4\x7c\x5e\x54\x7d\xd0\x95\x5d\x1a\x1e\xa5\xa4\xe6\x4d\xe4\x06\x1a\xca\x0c\x88\x17\xde\x2c\x63\x04\xf7\xc5\xea\x02\xac\x95\x95\xb8\xb9\xf5\xe4\x43\x4d\xd2\x41\x13\x32\x2e\xbf\x17\x1d\x06\xd5\x84\xd0\xbb\xfc\x1c\xcc\x57\x39\xff\xfe\x73\x89\xce\x1a\x97\xa5\x1e\x33\x26\x89\x02\x12\x62\x4d\x39\xe1\xd9\xdf\x21\x8d\x5d\x71\xba\xce\xab\x37\x4c\x45\xf1\xa9\xd3\x25\x8e\x76\xed\x3c\xe5\x96\x8b\x84\x14\x51\x51\xd6\x2c\x7e\x1e\x25\x17\x48\xf1\x88\xcd\xc4\xf1\x7a\x5c\x13\x68\x92\x5e\x6a\xa8\x13\x2d\x8f\x52\x8c\xca\x44\x85\xf3\x84\x5f\xb4\x50\x62\x8e\x3a\xa4\x1c\x0c\x57\xef\x8c\x88\x5a\xd1\xa5\xe5\x50\x64\x57\x8a\xbe\xc5\x5a\xe1\x38\xea\xb5\x11\xea\xca\xbf\x65\x79\x33\x28\xf8\x57\x2c\x52\xf7\xb9\x68\x05\x97\xab\xa3\x7a\x1a\xe1\xc6\x52\xdd\xf6\xe2\xf2\x34\x25\x82\x77\x35\x10\xef\x8c\x67\xcc\xf1\x9b\xd3\xe4\x2a\x52\xbc\x0d\x78\x58\xa2\x3c\x19\xd2\x06\x2a\xe9\x22\xc3\x3c\x09\x08\x3e\x6b\x1d\x9b\x79\x37\x6c\x5e\xfd\x4c\xb4\xbe\x87\x0d\x16\x77\x7a\xf0\x57\xe3\x59\x66\x6e\x16\x96\x06\xa7\x86\xde\xf5\x2b\xa4\x0e\x01\xdd\x78\xa9\xbb\xf1\x2e\x78\xed\x36\xbc\x7a\x56\x48\x5d\x32\x4c\x2b\x78\x55\x23\xae\x2e\x25\x5d\x55\x01\x7e\x8f\x34\x4c\x1d\xeb\x7f\x13\xcf\xee\x33\x52\xef\x64\x66\x5a\x2c\xc3\x06\x8f\xc6\x62\x79\xdc\xf5\x09\x1d\xbd\xcd\x0b\x5d\xb3\xf4\xf9\x40\xcb\xa5\x99\x09\x63\x93\x0c\x51\xd2\x52\xe6\xd9\x19\x9e\xec\x52\x3b\xc4\x52\x76\xa2\xe3\x8a\xf3\x02\xbf\xbd\xd6\xc4\xa4\x18\x0e\x79\x38\xe2\x8a\xb1\xf5\xf3\x64\xe9\x0e\xa6\x84\x13\x94\x92\xc9\xf8\x47\x6e\xe4\x98\x03\xab\xd9\x30\x7e\x8c\x22\x9e\xc5\x30\x46\x16\x19\x3b\x79\xcd\x7b\x59\xc7\x96\xee\x16\x8f\xcd\x06\x93\xfd\x6f\x7e\x55\x43\x58\x45\x01\x1c\x3f\x73\xdd\xaf\x0c\x23\xb5\x6e\x83\x27\x05\xca\xb7\x83\xd6\xb8\xa1\x12\xab\x79\x76\x81\xbc\xe8\x51\x0f\x9f\x36\x89\x7b\x98\x55\xcb\x1b\x6d\x96\xe5\x7a\x04\x28\x52\xfc\x47\x26\x38\x96\xa9\xd8\x8a\x79\xc2\x9f\xd3\xef\xb7\x6f\xe3\xb3\xb7\xbb\x11\x8d\x98\xe1\x9a\xbc\xe3\x86\xad\x1f\x3c\x0f\x4f\x6e\x96\xba\xc3\xe1\x7b\xd2\x57\xa1\x8c\x4a\x79\x21\xb3\x0c\x99\x83\x80\x52\x7e\x92\xbc\xf1\xb8\x41\x0e\xbb\xe0\x3f\xbe\x70\x9d\x5a\x2a\xf1\x65\xbf\xb9\xa7\x13\x6e\x5e\xf5\x4e\x6f\xe4\x80\xe9\x34\x6a\xe6\xa6\x41\x06\x06\x62\xff\x90\x8c\x40\xd7\x06\xaa\xe3\xe9\x4e\xa9\x19\x62\x60\x9d\x70\x6b\x99\x29\x5e\x99\x63\xce\x2c\xe4\x96\xdd\x1b\x79\x9b\x5b\x62\xfa\x60\x29\x1a\x48\x75\xed\x8e\xc0\x1a\xb9\xba\x0a\x74\xa1\x11\xa5\x6e\x32\xdc\x12\x94\x5c\x2d\x4e\x88\x9a\xc6\x66\x47\xa4\xb0\xbe\x69\x19\x3f\x38\x73\x3f\xb1\x94\x0b\x95\x6d\xfa\xc8\xad\x21\xd4\xf0\x91\x46\xe0\x19\xce\x13\x83\x1e\x2c\x85\xc9\xb9\x2b\x9c\x6d\xed\x91\x5d\x8f\x58\xbf\x72\x02\xe2\xfc\xa6\x1a\x70\x39\x58\xc5\xaf\xce\x11\x51\x43\x5f\x7e\x0a\xb5\x2f\x73\x0d\xcf\xcf\xde\x21\x33\x7c\xbf\xcd\x92\x14\xa8\xca\x0f\xd9\x9e\x12\x10\x48\x52\xd0\x2a\x56\x10\xfb\x37\x9e\x34\x88\xda\x83\x43\x99\x53\xcb\x02\xd1\x4c\x85\xf2\x9b\xb5\x91\x0a\x52\x13\x5f\x0d\x6a\xa3\x6b\x92\x98\x0c\xd0\xad\xd9\x73\xe8\xed\xa4\xc5\xdc\x27\x6c\x84\xc7\x6a\x31\x8f\xe2\x29\x5d\x4a\x17\xe5\x43\xec\xc3\x9b\xba\x65\xa7\x9b\x20\x41\x5e\x89\xd8\x02\xd6\x7e\x89\x0c\xaf\xa8\x87\x82\x46\xd3\xf7\x24\x71\x2d\x12\xa0\x2d\xab\xa5\xa3\x84\xbc\xdf\x7c\xf7\x0a\x55\xc3\x6a\xf7\xab\x18\xed\x3c\xbd\x10\x21\xe7\xd0\x95\x3d\x3d\xdf\x7f\x60\x46\xfc\x16\x05\xca\x50\x64\x0b\xa9\xdb\x0a\x61\x42\x58\x0a\xab\x17\x97\xa1\x96\xe7\x35\x64\xf0\x8f\xdf\x78\x1e\x13\xa0\xf3\xf2\x43\xa5\x36\x04\xa9\x2b\x8c\x92\x66\x2a\xfe\x6e\x7c\x22\x90\xda\xb8\x51\xbd\xe9\x50\x97\x6f\xe6\x7d\x8b\xf3\x03\x5f\xf5\xd7\x94\xf3\x00\x31\xbf\x1e\xa4\x60\x32\x53\x2a\x1f\x22\x1a\x66\x9a\x1d\x45\x61\x18\x03\x94\x04\x18\xa1\xb5\xd4\xaf\xe5\xe5\x2f\x49\xbf\xc3\xf1\xa0\xfa\x88\x03\x8d\x51\x43\xa0\xd1\x07\xce\xc1\x78\x71\x22\x27\xaa\xee\x78\x2d\xec\xe6\xf2\x84\x04\x00\xf1\x53\x6e\xf9\x22\x3e\xb7\xed\x31\x54\x69\x31\xfe\x40\xb0\x65\x49\x11\xe7\xf0\xe4\x9f\xc6\xf6\x47\x2d\x71\xf1\x7a\xd4\xae\xc7\x99\x29\xd4\x5d\x2c\x1b\x3d\xfb\xbf\xe2\xe6\x43\x13\x55\x34\x19\x56\x72\xd4\x58\xca\x9c\xb4\x41\x70\x1f\x41\x80\x18\x89\x4b\x50\x33\x1b\xe7\x1a\x6c\x1f\xb9\xd1\x34\x4b\x32\x75\xc7\x4f\x68\x1a\x96\x8a\xb0\x15\x57\xa1\x4a\xd9\xa8\x6b\x07\xa9\xe3\x53\x6e\xb0\x41\xcf\xb0\x48\x05\x7a\x17\x20\xcf\xfb\xea\x21\x1a\x3c\x50\x8b\x2b\x30\x14\x41\x60\x73\x7b\x89\x4e\x71\x7e\xcd\x4a\x61\x77\xda\x2e\x72\x95\xa1\x88\x5e\x52\x68\x38\xc0\x43\x90\x5d\x7a\xa1\xeb\x47\x9c\xaa\xd3\xd0\x99\x05\x96\xf5\xad\x08\x00\xc5\x80\x62\x69\x16\xf1\xc3\x69\xa1\x8b\xc8\x49\x14\x72\x04\x67\xfe\xd7\x02\xaa\x4a\xed\x4c\xd1\x58\x92\x14\x4f\x90\xae\x8e\xcc\x98\x16\xcb\x07\xd0\x4f\x4c\x33\xee\xd2\xe1\xa0\xdc\x24\x11\x15\xac\xf2\xec\xf5\x1e\xcb\xad\x42\x6e\x4d\x05\x61\x1b\xad\xe6\xee\xe9\x1c\xea\x79\xa9\xf5\x95\x25\x7c\x23\x34\x13\x97\x20\x68\x7a\xb9\x6a\x0d\x37\x61\x13\xf4\x94\x1a\xef\x85\xf9\xbb\x5a\x79\x44\xe9\x9f\x4b\x59\x51\xb5\xd8\xb2\x56\xe2\x14\xcb\xf0\x28\xb0\xef\x8e\x0f\xbb\x0d\x19\x94\xe3\x1c\xc0\xbe\xd2\x1b\x0a\xa6\xff\xa1\xe1\xdf\xf6\x08\x28\xc6\x85\x72\xa3\x85\x70\x0d\x98\x8e\x03\x39\x23\x92\x02\xa5\x5a\x2b\x5d\xd7\x23\x8d\x4d\x96\x4a\x43\x16\xb4\x44\x18\x5e\xc1\x23\x0c\x3b\x61\x62\x92\x90\x39\xa4\x28\xfe\x24\xb5\x85\xbe\xae\x25\x7a\x89\x40\xc2\x6f\x74\x94\xd3\x3f\x47\x3b\xa8\xd0\xd0\xfd\x84\x92\x64\x05\xb3\x9c\xea\x96\x82\xc1\xd5\x06\x88\xec\xd8\x51\xdf\xec\xe6\x89\xbd\x2f\xcb\x91\x2e\x25\xe9\xa8\xb0\x4a\xc4\xcd\x0a\xe9\xa5\x24\x34\x61\xb9\x94\xdf\x0e\x8f\xda\x77\xd4\xde\x71\x0d\x14\x39\x82\x39\x2e\xb0\x39\xa9\x31\x19\xb8\x8c\x99\x40\x45\x65\x1b\x22\x7c\x5c\xa9\xc2\x22\x1e\xb2\x16\xbd\x60\x0b\xa9\x62\x4c\xc9\x0a\xa2\x34\x7b\x2c\x5f\xe1\x6d\xe7\x0e\x44\xc0\x50\x3a\x6e\xf7\x0c\x77\xa3\xdc\xee\xcf\x96\x14\x7b\x87\xa4\x2b\x45\xc6\xfc\x1b\x22\xa0\x6d\x6d\x10\xea\x7e\x91\xf1\x48\x9e\x69\x4a\x33\x4f\x5c\x4a\xab\x91\x27\x16\x46\x7f\x22\x15\xe3\x0e\x13\xff\x83\x20\xc4\x6a\xfa\x97\xc4\xee\xa9\x72\x00\x45\xab\x0e\x39\x14\x8e\x29\x2a\x3a\x5c\x37\x6e\x79\x97\x70\xf0\x82\x38\x94\x6f\x56\x05\x5e\x61\xf4\x52\x20\x0b\x23\xc5\x23\x92\x34\xd7\x9a\xe0\xfe\xb7\x1a\xb2\x59\x54\x48\x97\x48\x94\x00\x02\xac\x12\xbc\xc6\x46\x83\x08\xba\x03\xf9\x1f\xb8\x3c\x12\xd0\x47\xf6\xce\xb7\x34\xce\x03\xbb\x2c\x2c\x08\xf3\x23\x20\x87\x78\x05\x6c\x7e\x6a\xd6\x40\x38\x74\x68\x99\x2d\x46\x8e\xa8\x8b\xea\xc6\x7c\x9b\x53\xa0\xca\x98\x8d\x1f\x05\x37\x64\xe8\xcd\x5e\x8d\xa0\x8b\xe6\x34\x22\x7f\x9c\x8b\x29\xe0\x6e\x58\x83\xc2\xf9\x13\xbd\x64\xe0\xc3\xb8\x96\xa3\x29\x8e\x86\x25\x5a\xfc\x58\x5b\x34\x9c\x5a\xfa\x65\xbe\xae\xdc\xae\x28\xf5\xa8\x56\x6c\x41\x4e\x48\x63\x54\x1f\xe4\x5c\x0f\x62\x57\xac\x06\x05\xdf\x71\xa0\xcf\x69\xa5\x4a\xd4\x30\xbe\xb9\x66\xe4\x06\x97\xc1\x8f\x8f\x45\x68\x0c\x4a\x5a\x38\xfa\x5c\x15\x29\x2c\x17\xd3\x86\x47\xae\x91\x14\xfc\xfa\x81\x79\x9d\x40\x7c\xd8\x3c\x35\x9e\xac\xae\xe7\x18\xf1\x75\xbb\xaf\x0e\x3b\xaa\x21\x17\x2a\xd6\x8b\xc8\x93\x39\x40\x58\xc1\x8e\xe5\xaf\x4c\x79\x7e\x99\x69\x0d\x94\xa0\x10\x99\x2c\xde\xa5\x45\x4a\x5d\x15\x9a\xe4\x0d\xee\x41\xf3\x47\x10\xf1\xb5\xf7\x48\xd4\x28\x6b\x31\x15\xaf\x80\x0c\x38\x53\xd5\x52\xdc\xba\x69\x95\x3d\x2d\xb2\x15\xdf\xe0\x89\x41\x18\x9a\xa2\x5a\x05\xad\xb4\x71\x88\xeb\x4c\x55\x01\x7f\xe1\x11\x2e\x4d\x25\xa6\x00\x80\x4f\x4e\x92\x25\x92\x63\x74\x2f\xa6\xc7\x6f\xb4\x4a\xb6\xf5\x0b\xae\x67\x74\x87\x52\x1d\x1c\xd2\xa2\x75\xad\xdf\xe1\x62\xe1\x21\x9e\xe6\x1a\x48\xf0\xb2\x6a\xe2\x98\x41\x1a\x76\x8c\xf6\xd7\x3a\x09\x10\x3d\x6c\x6d\xd2\xd4\x25\x57\x26\x01\xf6\xd4\x28\x70\x50\x15\x43\x5f\xf4\x4d\x1c\x89\xca\xed\xe3\x44\xc0\x6b\xed\xb2\x62\x0b\x84\x65\x57\x89\x6a\x57\x47\x32\x4b\x13\xc8\x4d\xb7\x70\xa4\x5d\x6d\xf9\xc8\x56\x89\x75\xac\x5e\x51\x1d\x2e\x5a\xcc\xac\x32\x22\x79\x43\x56\x0c\xc1\x27\x0e\xb3\xa6\xbc\xac\xb4\x82\xde\x9c\xcd\x0a\xfd\xf3\x20\x82\x37\x41\xb7\x1c\xc5\x65\x0d\xea\xe9\xe4\x49\x10\x93\x27\x56\xac\x8b\x32\x45\x75\xa9\x57\x50\x73\xa8\xf2\x0f\x03\x86\x65\x0e\x9d\xa4\x98\x8a\x5f\xda\x06\x77\xfc\x92\x65\x6b\x7d\x8f\xd2\x5b\x23\x63\x05\xe3\x57\x43\x7f\xae\x52\xa4\x49\x16\x1c\x82\x28\xe8\x35\x0a\x18\x38\xb1\xab\x22\x6f\x4d\x39\x31\x04\x97\x30\x3b\x62\x25\xc7\x1e\x9b\xca\xea\x50\x10\xb3\x7c\xd4\x79\x7c\x03\xb5\xcb\x62\xe9\xf9\xcd\x57\x91\x4b\xe6\xa3\xd1\x78\x64\xb6\x0d\x4d\x54\x2d\xdc\xd7\xd5\xa2\xe2\xf3\x6a\x1a\xf8\x5b\x2d\x9f\x6a\xa4\x71\x00\x76\x92\x69\xe8\x39\xdc\x83\x24\x39\x76\x58\x1f\xba\xcc\xe5\x3b\xbc\xf9\x9b\x87\xcd\x9a\x6a\xfc\x0d\xc5\xd6\xd1\xcd\xe6\xc6\x2c\x45\xbb\x13\x20\x32\x73\xeb\x8f\xf4\x3b\xf4\x88\xb8\xbb\xef\x48\xe8\x9d\x24\xff\xec\x80\x51\x43\xa0\x81\xce\x8a\x71\x90\x12\x4b\xbe\xf9\x87\x35\x15\xe6\x1a\x5b\x92\x6d\xcd\x25\x65\x63\xb9\xf9\x73\x5d\x27\x37\x0f\x87\x8b\x85\x23\xed\x26\x41\x4e\xc4\x01\x16\xe4\x8a\x0f\x1e\x21\x48\x3a\x4a\xce\x55\xf5\x0c\xa4\x13\x14\x10\x13\x39\x38\xe2\xe9\x1d\xf0\xce\xe0\x0f\x0c\xcf\x59\xb2\xf7\x51\x6c\xf4\x26\x2d\x34\xcf\x9d\x4e\xc2\x81\x2f\x38\xdf\xf4\x65\x59\x7a\x28\x87\x99\xf0\x3f\x3e\xf2\xd1\xd1\xe7\xa6\x25\x28\x88\x8f\xbf\x1f\x27\x38\xea\xb3\xe8\xfd\x07\xd7\xeb\x48\x44\xf2\xac\xb1\xac\x5f\x8e\x06\x83\x24\x48\x7d\x2d\xca\x75\x3c\x11\x2b\x7d\x30\x96\x07\x33\xa2\xdd\x9a\xe6\xf7\xe7\x97\xe2\x6b\x9a\x89\x38\xa3\xee\x78\xc7\x71\x3b\x77\xea\x00\xee\xfb\xaf\x35\x02\xfe\x3d\xde\x27\x49\x94\x52\x74\x0d\x01\xd9\xa3\xe2\x16\x8b\xfe\xd0\x76\x21\x6d\x6f\x5b\x80\x54\x64\xff\xab\xc9\xa0\xaf\xbe\xe1\xf4\x20\x33\x4f\xdd\xe0\xc7\x36\x76\xbe\xa3\xfb\x82\x2c\xfe\x8e\x0a\x5d\x90\xda\x4d\xc5\xb9\x68\x59\x13\xe7\x41\xa0\x19\xf7\x94\xa7\x01\xbe\xc1\xa7\xfc\x3b\xb1\x6a\x75\xd4\x0a\xc4\x3f\x81\xdd\x78\x03\x93\xbf\x31\x9f\xc5\xc7\x79\x5d\x4a\x40\x47\x97\x25\xd3\x94\x4c\xf5\x5a\x24\x7a\xbe\xb1\x98\xa1\xa8\xfd\xbf\x52\x46\x6a\x43\x35\x7e\xd4\x1b\x52\x75\xbe\x31\xb5\x39\x86\xa7\x00\xfb\x98\xc1\xae\xe9\x54\x44\x84\x9a\xca\x45\xe1\xa8\x15\xc8\x61\x2b\x5d\x9c\xd6\x7c\x4f\x7f\x6b\x95\xac\xca\xc4\x8c\xed\x37\x2d\x0e\x9d\xc1\x4a\x96\xa9\x4a\xd9\x9f\x5a\x5e\xe6\x59\x65\x31\xaa\x9d\xde\x8c\x19\x06\xc9\xae\x0e\x40\xf6\x7f\x1b\xa4\x4f\x99\x40\x8a\x7a\x25\x44\x73\x60\x11\xde\x92\xa0\x2b\xb3\xa0\x56\xbb\xbf\x68\x56\xff\x62\x43\xcb\x56\x02\x47\x7a\x4f\xd1\x0b\xb1\x97\xb4\x64\xf6\x96\xe6\xc7\xd4\x8f\x92\x33\x84\x73\xc2\x44\x8f\x99\xbc\xc8\x96\xf7\x27\xb2\xc8\xd2\xcd\xdb\x5f\x8c\xcb\x1e\x5a\x58\xd9\x57\x9c\xa5\xb8\xda\xb1\x61\xb9\x42\x92\x05\xbb\xd3\x13\xa0\x3f\x4c\x1f\xe9\x81\x35\xf7\xd0\x7b\x0f\x25\x1d\x51\x34\x41\x7b\xcd\x7e\x8a\xab\x95\x24\xff\xb3\x0a\x9e\x2c\x07\xf9\xf0\xdb\x38\x37\xaa\xa7\xe0\x8f\x18\xd0\x10\x6d\x7d\x5b\xb1\x0b\x33\x8e\x6e\x11\x7b\xaa\x89\x2f\x4d\x03\xce\x65\x27\x29\x49\x07\xa5\xfc\x42\x3e\x60\x5d\xd8\x63\x0a\xaf\x68\xbe\x10\x63\x4c\xcc\xa9\x1c\x72\x78\xee\xaa\xf4\x1d\x04\xeb\xcb\x56\x27\x07\x66\xa8\xc8\x39\x96\x68\x22\xa0\x31\x5e\x52\x91\x33\x0b\x40\x70\x8e\xca\xaf\x11\x16\xbc\xc6\xcb\x42\xc4\x91\xfe\xd2\x4d\xb0\xf2\x45\xb7\xa8\xd7\xdd\x48\x10\x2a\xc9\xad\x56\xe3\x44\x96\x16\x0f\x0e\x11\xc2\x5c\xc5\xb9\xbf\x91\xa3\xa4\xd8\xb1\xb8\xfc\x03\x30\x72\x17\x0e\x39\x86\x38\x4e\x6f\x04\x8e\x4d\x2e\x61\xed\xb8\xa6\x4b\xd7\xc3\x8d\x5e\x1c\xb0\xdc\xf5\xea\x1f\x09\x1b\xa9\x9e\x99\x2e\x6a\x82\xd7\xa6\x25\x77\xbc\x02\x62\x55\x5e\x5a\x8b\x0f\xde\xe7\x62\xea\xef\xfc\x77\x24\xf7\xc9\x9b\xd0\xd4\x37\x0f\x67\xcd\xd5\xfb\xae\x5a\xd5\x2a\x09\x42\x52\x4e\x6a\x09\xcb\x47\xd2\xad\x80\x6d\xa5\x91\x22\xac\x96\x0a\x44\x52\xad\x71\x12\x0e\xeb\x85\xf5\xa6\xb6\xbd\x5e\x0a\x89\x0a\x98\x12\x0f\xba\xb6\x5a\xfb\xda\xfc\x40\x28\xc7\x48\x2c\x41\x10\x9c\x58\x76\xa3\xdd\x4b\xc2\xf9\x5e\xa4\x73\x12\xa7\x33\x88\x97\x62\x41\x51\xa6\xcc\x91\x79\xc5\x9c\xaf\x4c\x35\xed\xdb\xb4\x9d\xaa\x22\x27\xa9\x6f\x66\x62\xf2\x61\x49\x25\xb7\xf4\x88\x02\xe9\x17\xc8\x6f\x5d\x20\x46\xbf\xbd\x04\x94\x41\xc1\x4f\x89\x7e\x37\xdc\x8a\x46\x3d\x25\xb3\x85\xc8\xc7\xa6\x0c\x77\xb7\x93\xfa\x7a\x74\xf0\x96\x94\x1b\xec\xf9\x11\x02\xbb\x16\xb3\x7e\x10\x3c\x46\x0c\x84\x44\xb6\x5b\x6e\x90\xba\x5c\xd3\x9b\x0e\x52\x16\xe8\xd4\x13\x38\x92\xe3\x68\xc1\xb1\x92\xfa\x84\x35\x1e\xb9\x2e\xf4\xd3\x53\xa1\x58\x04\xf0\x2f\xe2\xf4\x1b\x0e\x88\x66\x38\x06\x36\xac\xfc\x62\xb2\xb0\xb6\x8b\x58\x9f\x6f\x26\x16\xd1\xde\x28\xb6\x88\x4a\xb2\x52\x13\x11\x8a\x28\x70\x0b\x83\x49\x45\x26\xf4\xda\x24\x61\xea\xb8\x8a\x9c\x43\x70\x9a\x83\x64\x83\x6f\xac\x8d\x94\x8a\x12\x60\x79\x37\x12\x8b\x26\xcc\x27\x2d\xfb\x2b\x1a\xa9\x50\x97\xcd\x04\xb4\x3b\x6b\x47\xbb\x65\x3a\xfc\xaa\x16\x63\xfc\xd8\xfd\x20\xfb\xd7\x3c\x23\x51\x55\xd4\xd5\x87\x5a\xf7\x1d\xba\xed\x17\xd3\x91\x34\xbf\xd3\x06\xb9\x91\xaf\x70\x45\x61\x78\x35\xac\x7c\x79\x94\x6e\xc5\x0d\xdb\x2a\x94\x11\x06\x35\x07\xd6\x3c\x56\x94\x12\x0e\x95\x36\x29\x70\xcb\x2d\x26\x0a\xa0\xd0\x9a\x15\xed\xb3\x86\x0a\x91\x65\x8c\x86\x8f\x5b\x4d\x92\x7d\x0c\x67\x04\xb0\x8e\x91\x13\xb9\x10\xec\xd2\x5e\x5c\x51\xd8\x7e\x27\x40\x2d\x56\x8a\xbb\x91\xf1\xb8\x5e\x7e\xf5\xdb\xe4\xd1\xd2\x73\x57\xfa\x03\x13\xf5\xf3\x45\x6a\xaf\xee\x79\xcf\x30\x5e\x28\x59\xe6\x89\xe6\x7e\x6c\x04\x97\x20\x39\x57\xe9\x1e\xb2\xe2\x95\x38\x89\xc7\x8d\x45\x5e\x11\xd8\x5f\xfb\xde\x2b\x63\x15\xab\xaa\x45\x34\x5e\x78\x07\x65\xb7\x98\x60\xd6\x4a\x00\x1c\x77\x04\x18\xe5\xa0\x3a\xf2\xe7\xb9\x63\x55\x52\x8e\x17\x7f\x31\x66\xe1\x5d\x13\xe4\xbf\x45\x1b\xd0\xa9\x9a\x52\x3e\x8a\x09\x00\x02\x33\x03\x16\xd9\x1b\x19\x06\x81\xcb\xee\xac\x42\x1a\xc6\xc6\xcf\x97\xa5\x8a\x7d\x9b\x3a\x03\x3f\x9d\xf2\x1e\xdf\xec\x3e\xb9\x9c\xb0\x9d\x09\x14\xba\x03\xcf\x1d\x11\xf4\x97\x7f\x44\xde\x76\x4e\x6a\x1d\x2f\xc2\xe5\xac\x18\x89\x29\xb4\x30\xb2\xc5\xbc\xc8\xfd\xc2\x04\xf7\xe6\xba\x40\x51\x34\xd6\xfb\xcd\xfc\xc1\x5d\xba\x12\x6a\xde\x71\x54\x4c\x1c\x5e\xd3\xba\x02\x8b\xc3\x4c\xa6\x27\x56\x2b\x0e\x22\x1e\x78\x25\xd6\x14\x43\x87\x9a\x57\xb7\x5b\x84\x52\xfd\x1b\xc4\x3b\x8c\x9a\x23\xeb\xc6\x89\x4d\xc5\x89\xaf\xa3\x64\x4a\x33\x7f\x3d\xb0\x5f\x4a\x7c\x60\x92\x8b\x19\xc7\x15\x19\x23\xde\x82\x6d\x4b\x92\x1d\x95\x5a\xcf\x23\xaa\x4f\x21\xf8\xc1\x72\x1f\x84\x9b\x59\x6d\xc6\x1f\x65\x03\xf8\x65\x17\x84\xc2\xfc\x52\x4d\xf9\xca\x4b\xc4\xd9\x24\xa5\xe1\xcb\x37\x29\xd9\xfa\x41\x2c\x9b\x8f\x5a\x63\x3d\x5a\xe2\x53\xc2\x0f\xbe\x92\x23\xb2\x19\xe4\x19\xa3\x97\x68\x2b\xc3\xc6\x79\x40\x2c\xb9\x49\xbf\xca\x60\x0d\xa8\x50\xb1\xff\xd5\xae\x16\x0a\x6c\x7f\xd1\xd4\x34\xe5\xcc\x07\x5a\x6b\x95\xc6\x81\xaa\xa2\x58\x92\x9d\x14\xc6\xe8\x7e\x96\xd4\xfb\xe7\x01\x32\xf4\x81\x15\xf8\x9b\x26\x62\x45\x8a\xd7\x0f\xd9\x30\x0f\x03\x05\xe8\x31\x8a\x8e\xbe\xd4\x97\xd9\xc6\xc9\xac\x48\xd5\x00\x6e\x65\xd2\x40\x8a\x05\xcf\x92\xdd\xc3\x8c\x38\x21\x4a\x30\xda\x68\xfd\xf5\x37\xa9\xb8\x70\x17\x32\xb3\x8a\x8e\x34\xd9\xa7\x3c\x49\x02\x82\x15\xe5\x95\x18\xa9\x97\xd1\x09\x81\x03\xe7\xa5\xc4\x2a\xbb\xa0\xef\x8a\xf3\x31\xa2\x13\x66\x9a\x5f\x44\x69\xcd\xef\x08\xc0\xe1\x47\xa4\xec\xc8\x35\x63\x75\x66\xcd\x97\x5c\xa8\x80\x0e\x5e\x15\xe8\x2f\x42\x17\x2a\xf5\x09\x5c\x4f\xcd\xea\x82\xc5\x05\x42\x62\xd2\x2c\x0f\x60\x45\x70\x28\x3c\x44\x35\xbd\x2f\x62\xb1\x3a\x4f\x6f\xed\x3a\x40\x7c\xb0\xe6\x02\x83\xea\x93\xf0\xc2\x3d\x04\x8f\xd5\x5c\x18\x2b\x8a\xfe\x5d\x01\x5f\xae\xa8\x3c\x74\xed\x08\x9e\xb8\x0f\xb2\x97\xb5\x95\xc4\xd7\xb5\xa1\xd3\xcf\xee\x32\xff\x46\xca\xcc\xe6\xa6\x1c\xaf\x1c\x5b\xc9\x8f\x08\xfc\xee\x1d\x8c\x00\x07\x5f\x1e\xe2\xb7\x56\xf3\x9a\xc0\x0c\x08\x0d\xc5\x53\xf2\xf1\xf1\xe6\x6a\x61\x97\x94\xde\x48\x8d\xca\x74\xe7\x10\x81\x51\xb6\x83\x73\x2b\xc1\x8c\x6b\xa5\xe9\x4d\x0b\xd2\x91\xfc\xee\x5b\x4b\x74\xd3\xb9\xb5\x9e\x0a\xfe\x20\x99\xf9\xbe\x64\xc1\x7c\x83\x6b\x9e\x4a\xba\xa0\x12\x71\x1a\x66\x43\xa1\x27\xaa\xf0\x31\x5b\x83\x93\xf2\x08\x9f\x41\x9a\x3c\xcf\x6f\xf5\x93\xff\x53\x6a\x67\x95\x55\x0e\xa7\x9f\x32\x10\x4b\x28\x21\x49\xac\x56\x4b\x7f\x54\xff\xb4\x56\x86\x03\x51\x48\x59\xe2\x29\xb5\x2e\x52\x31\x45\xe7\xbf\x8d\xd6\x10\xa5\xfc\x31\xb6\xe9\xd2\xdd\xbc\x48\x90\x0d\xcd\x8a\x74\x78\xf5\x51\x20\x61\x40\x16\x95\x33\xbd\x8a\x3b\x82\xa5\x33\x33\x88\x78\x8f\xd1\x3e\x1d\xb0\x46\x94\x84\xe1\x53\x04\xf9\x25\x4c\x7f\xab\xb1\xbc\x31\x99\xc7\xa4\x2a\x0b\xf8\x59\x83\x96\xe2\xc2\x02\xf8\xa6\x64\x00\x07\xaa\xc3\x1f\x8e\x29\x96\x86\x05\x9c\x6f\x6d\x3d\x53\x1b\xa0\x65\x6a\xfb\x30\x0a\x0d\x2c\x27\x4c\x42\xba\xb2\x0b\x32\x14\x6f\x57\x31\x2d\x70\x54\x8f\x52\x0f\xb0\xdb\xda\x04\x20\x04\x61\x82\xeb\x97\xae\xf2\xe6\xd2\x1c\x2f\x48\xd2\x90\x87\x48\x10\x83\xb0\xf1\x65\x85\x56\x58\xf7\x16\x9b\x1f\xcd\xb7\xf0\xda\xcb\x9b\x52\xdf\xec\xd8\x8b\x86\x41\x5f\xc3\xce\xef\x4f\xd2\xc2\x12\xa4\x4f\x48\xda\x70\x5a\xbf\x91\x1a\x3e\x95\xd2\xf4\xe1\xa9\xc1\x61\x16\x44\xa0\xb1\x14\x45\x28\x39\xeb\x5b\x64\xe3\xa1\xd0\x2e\xe1\x79\x12\x21\x16\x49\xea\xb9\x35\xa3\xbe\xf0\x8a\xcc\x74\x15\x3f\x48\xe2\x92\xb4\xb2\x60\x09\x2f\x67\x49\x6c\x20\x3f\x88\x79\x15\x10\xb7\x3b\xf1\x5b\x56\x0e\xa1\xde\x7a\x23\x3a\x55\xa0\xda\x0e\x10\xff\x62\x3d\x67\xa5\xc9\xb0\x56\x20\x24\x5b\xb6\x57\x22\xba\x1a\xa9\xde\x1c\xf0\xa6\x51\xf6\xc8\x4e\xf4\x55\xe2\xce\x2b\x6b\x55\xde\x71\x66\x60\x32\xbf\x4d\x27\xe7\x65\xa7\x70\xb8\x1f\x09\xba\xab\x1a\x97\x33\x86\x9a\x4f\xbf\x51\x07\x3a\xac\x6c\x67\x38\x57\x99\x41\x11\x86\x59\x0d\x9a\x55\x84\x74\xdb\x19\xea\x8d\x23\xdd\x95\x4b\x73\xf4\xc6\xb8\x57\x5a\xbc\x60\x98\x9f\x2a\x6f\x48\x54\x3d\x26\xe2\x5b\xee\x24\x5f\x31\x46\x0f\x5f\x3d\xd1\x55\x86\x76\xf5\x55\xff\x6c\xa4\xb7\x83\xab\x31\xa1\x6c\x55\x13\x27\x81\x44\x28\x82\x1e\x78\x08\x03\xc7\x37\xc0\x16\xe2\x27\x56\xed\x03\x6b\x8f\x54\xe2\xef\x8a\x8f\xe6\x99\x25\xf5\x78\xb5\xc8\x6c\xac\x91\xaa\xe9\x28\x98\xda\x0b\x9a\x9f\xeb\x57\x01\x97\x90\x1e\x85\xfe\x77\x6c\x48\xba\x0b\xc7\x53\xd4\xc6\xf3\x98\x6b\xe7\xb3\x5f\xb7\x91\xdd\x88\xab\xe4\x1a\xc9\xcf\x77\xfe\x73\x92\xb4\x87\x64\x70\x93\x32\x5b\x89\x56\xac\x99\x4b\x3f\x96\xda\x16\x3d\xad\xc2\x24\x67\xdd\xea\x09\xba\xbf\x61\x43\x7f\x2f\x59\x8a\x12\x65\xf3\xea\x4a\x6b\xfb\x08\x1b\x8f\x51\x14\x2e\x1d\xcb\x98\xa3\xad\x1a\x99\xb4\x30\x84\x56\x3c\x95\xc4\x73\x24\x79\x5f\xab\x27\xf8\x21\x9a\x6e\x48\x29\x9b\xf4\xba\x7d\x29\xa7\x1f\x7a\x62\xda\x24\xdd\x07\x52\x9e\x81\xf0\xfb\x83\x82\x4d\x0a\xe2\x92\xe3\x20\xd7\xef\x81\x47\xf1\xf3\xb2\x81\x2c\xbc\xc8\x64\x66\x71\x2d\xb2\xcd\x73\x6a\x55\xdd\xd2\x60\x97\x23\x98\x23\xfa\x5f\x90\x9d\x78\xb2\x8e\x5f\x0d\x0a\x5c\xbf\xa4\xc0\xbc\x39\x2b\xb9\xc3\x47\x42\xd7\xea\x5a\x9c\xd7\x01\x1d\xc6\xf3\x51\x8e\x3f\x9f\x8d\xe9\xba\x21\xcd\x1a\x61\x8c\x9a\x9b\x93\x7e\x3a\x82\x31\xbe\xb0\x02\x17\x0a\xb2\xc1\x1e\x20\xca\xf0\x8f\x45\x91\x02\x8d\x1a\xa8\x86\xce\x09\xbb\x80\xaa\x26\x40\x46\x36\x4c\x4c\xdf\x8c\x77\x1c\x76\x7a\x1e\x0e\xf8\x92\x39\x01\xc4\x28\x2d\xbd\xf4\x13\xbc\x82\x34\x7e\x5e\xd4\xb5\xb0\xcf\x10\x12\xf8\xa5\x90\x87\x96\x96\xb2\x85\xad\x13\xa9\xb5\xc4\xd7\x3f\x26\x54\x20\x73\xde\x6f\x54\xdc\x42\x96\x19\xaa\x73\x85\x3e\xb4\xa8\x48\x5d\x28\xd6\x5a\x4d\x6c\xc4\xf6\x43\x0d\x66\x6e\x44\x6d\x74\xe4\xe1\x17\x4c\x6e\x00\x8e\xdf\xb0\xc1\x6c\x36\x25\xc2\xb6\xa5\x14\x37\xc2\xac\xd0\x10\x29\xff\x91\xda\x8f\x14\x50\xde\xe0\xbc\xa9\xea\x81\xf9\xc2\x90\xaf\xc3\x1b\xa0\xf0\x8d\x44\x4b\x55\x3e\xfa\xdc\xd0\xb9\x57\x55\x3a\xbc\x76\x16\x5e\x02\xe3\x9a\x9f\x9d\x20\xdd\x55\x18\x6e\xed\xd4\x4f\x52\x67\x12\x07\xe3\x22\x5d\x2d\x0f\x21\x01\x8a\x69\x7c\x4a\x37\xbd\x22\x0a\x12\xfa\xb8\xb3\xf4\x16\x6c\x34\xe6\x59\xf8\xff\xc8\xab\x19\x85\xf9\x77\x12\xaa\x73\x4b\xe2\x46\x5e\x8a\x84\xed\xd2\x87\x04\x65\x64\x96\x53\xc8\x43\x77\x49\xf0\x8d\xf6\x12\x91\xd8\xa9\x48\xbb\x60\xed\x4e\xf4\xb9\x07\xe4\x57\xe6\x8d\x38\x09\x63\x8e\x83\x23\xf2\xc1\x01\xad\x72\xbc\x5f\xd8\x40\x83\x74\xdf\xee\x33\x3b\x55\xb5\xf8\xaa\x64\xa1\xc6\x71\x87\x45\x1a\x22\xad\x80\xe1\xd4\x67\xae\x99\x52\xd0\x1f\x45\x35\x7f\xf9\x07\x83\x90\xe9\xa6\x5d\x3c\xc2\x18\x83\xae\xce\x5a\x45\x80\x1a\xd9\x9c\x9a\x93\xc9\x1d\x6b\x84\x93\xb6\x00\xa9\x41\xdd\x95\xca\x4d\xa8\x59\xbf\xc8\x7f\x3f\x97\x3b\x93\xca\x8d\xb2\x7e\x57\x3e\x04\x7a\xd2\xb5\xb7\xb1\x11\x5f\xd1\xb5\xe3\x47\x56\x76\x9f\x7c\x33\xd7\x38\xfe\xdb\x00\xcb\xc3\xc3\x08\xd0\xca\x2a\xf8\xb7\x14\x32\x0c\xe4\xc3\xa4\xfa\x2a\xbc\xd0\x65\x41\x50\xcc\x7b\x46\x88\x93\x55\x40\x3c\xd6\x22\x36\xb7\x13\xc7\xf5\xb7\xeb\x17\x4e\x7f\x47\x4c\x4e\xe5\x8c\x84\x88\x44\x72\x4f\x5a\xf5\xe1\x83\x44\x5e\x25\x94\x64\x32\x11\x11\xa7\xb1\xa9\xc4\x0b\x09\x74\xc4\x51\x60\x04\x3f\x5e\xe0\x4c\xc3\x85\xa1\x9b\xb3\x0f\xf2\x26\x9d\x94\x54\x44\x4f\xa9\xe4\xc5\x56\x75\xf7\x8d\x54\x98\x77\xe4\x23\xd7\x4b\xdf\x04\x49\x0b\xca\xde\xb1\x93\xa9\xc3\x4e\xf4\xf8\xd9\x44\x21\xc6\x01\xda\xf5\xfc\x88\xe9\x3f\x92\x34\xcc\x92\xb6\xfc\x6b\x2b\x62\x25\xb0\xa2\x26\xc2\x0e\x8f\x22\xef\x22\x0b\x38\x21\x5f\x89\xf8\x46\xe0\xd7\x03\x6b\xac\x8c\x76\x84\xe1\xe1\x99\x3e\x9e\x94\xb9\x1b\x65\x01\x90\x2d\x47\xcb\x82\x87\xea\xd3\x0d\x85\xf7\x72\xb6\x1b\xd6\x48\x4b\x40\xe3\x5a\x62\xde\xa4\xf5\xca\x55\x70\x6d\xc5\x4d\xff\x16\x8e\xfc\x79\x6a\xcb\xd8\xf9\xf7\x69\x1e\x88\xb8\x4b\x04\xe2\xf4\x6c\x46\xae\xd1\x36\xca\x4d\x08\xd8\xad\x49\x2c\xd2\x2c\x72\xf8\x4e\x4b\x4a\x8d\x86\xe9\xb9\x1f\xf7\xb0\x84\x98\x8a\xa0\xaa\x97\x39\x94\xa4\xb8\xdc\x50\xa5\x5d\x82\x9f\xd9\xbc\xbd\xd9\xfb\x5f\x37\xc1\x2f\x7c\x7d\x8a\x89\x41\xfa\xa8\x73\xa8\xc4\x31\x77\x86\xdd\x01\x82\x96\x35\x4a\x1a\x97\xa7\x89\x55\x9e\xca\xa0\xb9\xd2\x4c\x43\x96\x9e\x20\xce\x1d\xe3\x44\xf7\xf0\x20\x18\xc7\x56\xb5\x8c\xd4\x2a\x31\x23\xbd\x51\xe0\xaf\x03\x01\x69\x8a\x24\x3b\x60\x8f\x91\xbb\xb6\xcb\x9c\x14\xd1\xe7\xbf\xb8\x3b\x57\x3b\x5f\x4a\x10\x66\xc5\xb6\xf2\x57\xee\x58\x25\x75\xba\x2d\x8b\xce\x3a\x77\xf1\x64\x11\x9b\x88\xba\x7c\x09\x53\x72\x62\xe9\xa8\xb6\xc3\xf2\x04\x42\x65\x3d\x26\xba\xd8\xc5\xed\x27\x97\xa0\x98\xab\x9b\xcc\xd0\x61\x0f\xe5\x01\xce\xf4\x0d\x73\x8e\x1b\x22\x95\x89\x71\x3f\xd8\x68\xa1\x0e\xa3\x72\x86\x48\xba\xdd\xcc\xc0\x18\xf5\xa4\x44\x9c\x14\x3c\x7f\xbc\x94\xb7\x0c\x6a\xc7\x10\xe9\x2d\x4d\xf0\xc6\x3c\x48\x26\xb2\x8a\x7e\x85\xc4\x74\x21\x03\x0b\xdb\x26\x71\xca\xa5\x43\xa3\xc4\x46\x0a\x19\xc2\x87\x47\xb7\xaf\x9f\xd8\x79\x13\xb8\x7f\x1d\xde\x73\x2e\xf9\xb7\x2d\x0c\x7b\xc0\xf6\x64\x2b\x0b\x8d\xe8\x61\xe3\x46\x06\x36\x9b\x7d\x70\x62\x76\xe4\xca\x6a\xfa\x37\xea\xea\x9c\x57\x96\xa2\x5a\x59\x72\x41\x43\xef\x32\x0d\x03\x49\x00\xcd\x42\x40\xdc\x28\xd1\x42\x57\x55\xd5\x3f\x29\x67\x40\x8e\x91\x39\x8f\x2f\x0b\x7d\xde\x2f\x67\x9c\x87\x3d\x8a\xf8\x3c\xa4\x96\x61\x1a\x9b\x7f\x28\x4c\x36\xc9\x43\x0a\x03\xcc\x9c\x1f\x6a\x89\xeb\x7d\xf7\x8a\x59\x6d\x44\xf1\x6d\x92\x8c\xd6\x6d\xde\xa4\xd1\xb0\x36\xad\x9f\x6a\xbe\x96\x38\xce\x8b\x59\x6a\x40\x2b\xbb\xc7\x56\x3f\x2a\x2b\x67\x04\x96\xe7\x47\x91\x67\x89\xc2\x0d\x4b\xa4\x4b\x9d\xec\x80\xbd\x46\xfd\xaa\x0e\x3d\xa0\x06\xac\x2d\x76\x8c\x8b\x2f\xe3\x4a\x8c\x1f\xc1\x17\x54\xb8\x5e\x1a\xc1\xa0\x17\x15\x41\x95\x06\xb7\x9c\x49\x95\xb7\xe0\x1e\x8d\x87\x34\x93\x00\x7c\x50\xf2\x6b\x69\x50\x2f\x51\xce\xf0\xe2\x44\x8d\x86\xe5\xde\x2a\x1b\xac\xe1\x3e\xa6\xcc\x88\xbd\x88\x1f\x4f\x22\xb4\x67\x2f\x64\x9b\x31\x2c\x4c\x6e\x64\xa1\x27\x30\x93\x03\x97\xa6\x67\xfd\x35\x58\x43\x86\xbf\xc9\x62\x7b\xd0\xba\x4e\x26\xc9\xcb\x4c\xd8\xc0\xd8\x4d\x8d\x1b\x2b\xc9\x3f\x5d\xcc\x2b\xb1\x44\x59\x4f\x97\x51\xd5\x09\xad\xb7\xce\x0b\x7b\x08\x0e\x1a\x9d\x10\x11\x43\xfa\x5a\xe9\xa9\x6f\x74\x60\x53\xb8\x68\x81\x5e\xda\xb9\x7b\x99\x35\x38\xb2\xc4\x4f\xc7\x62\x60\x13\x46\x66\xd9\x45\xd0\x67\x06\x77\xda\x58\xbe\x49\xc2\x6a\xba\x33\xc8\xfa\xb3\xe1\xfc\xa7\x6e\x64\xec\xd3\x43\xc7\xf5\x69\x46\xb8\xf3\x4b\xa4\x0e\x1b\x4d\xb6\xcf\x56\xd1\x0d\x6d\xe8\xb3\xb0\xcc\xc9\x68\xa3\x4a\xa6\x8b\x4f\xc7\x22\x96\xa8\x7b\x89\x59\xba\x05\x21\x7a\xb5\x23\xc3\xe8\xe3\xff\xe5\x5d\x73\x91\x7f\x46\xad\x66\x03\x76\xf0\x67\x4b\xd2\xba\x27\x07\x09\xb5\xec\x81\x25\x9a\x21\x5e\xc8\xbd\xe6\x2e\xc1\x69\x15\xeb\x9b\x22\x63\xf2\x5d\x0b\x68\xa8\x75\x3d\x64\x0a\xa4\xfe\x40\x64\xcd\xc1\xca\x69\xa4\x0e\x48\x88\x0c\x9b\x20\xf3\xba\xe8\x6e\x84\x9b\x02\x81\xf0\x87\x75\x16\x18\xd6\x8b\xdc\x1f\x75\xf5\x98\x75\x7e\x32\xc6\x50\x17\xf1\xd2\x21\x07\xde\xd0\xea\x2e\x4a\x33\x3d\xf5\xf6\x33\x09\x6a\x73\x93\x72\xcb\x67\x90\xd4\xfc\x88\xf0\xa0\xaf\x69\x18\x34\xfb\xd7\xd1\x52\x13\xb9\x26\xeb\x18\xb1\xf3\xf2\x38\x8c\xa7\x71\x2a\xf2\x08\xe3\x35\x97\xb8\x91\xdc\xc8\x75\xca\x09\xdc\xbe\x7b\x26\x5d\x48\xa3\xf5\xe4\x2f\x47\x89\x4b\xe1\x78\x21\x96\x7e\x13\x74\xbe\x0a\x1b\x84\xa9\x43\x11\x57\x57\x8d\xe2\x08\x8c\xd2\x88\xa3\xa9\x85\x41\x11\x81\x79\x93\xa7\xcb\xd7\xac\x3b\xc7\xfa\x3d\x38\x0b\xcd\xdd\xa1\xde\x73\x01\x8a\x49\xae\x83\x32\xcf\x45\xa1\x9d\x8d\x64\xde\x8c\xa4\x4a\x2d\x7b\x88\xce\xa4\xd6\x30\x17\xf0\xd8\x84\xf3\x2f\xb2\x1f\xaf\xb1\xe9\x8b\x8d\x94\xf3\x7a\xba\xff\xcc\xf0\xbc\xc9\xc8\x50\xd9\xbf\x59\x13\xff\xa1\xf9\x09\xec\x06\x5f\x64\x8c\xda\x12\xc4\x3a\x1e\xa6\x34\x8a\x7e\x10\x16\xbd\x51\xa0\xcc\x32\x3c\xe4\x42\x40\x00\xd7\xbd\xa3\x71\xd2\x06\x95\x59\x8c\x51\xb8\x14\xf3\x74\x0f\x89\x74\x88\x02\x68\x8c\xc8\xb1\x57\x41\xec\x7d\x5b\x19\x18\x9b\xd0\x4b\x8f\x39\x1e\xd3\x5a\x7b\x26\xf4\xf6\xa4\x7f\xc8\x91\x9e\xb8\x6e\x99\x64\xc9\x48\xf1\xec\xe4\xf4\x78\x07\x24\x5f\x66\x06\x5f\xab\x20\x66\xb6\xa7\xff\x93\x31\xc5\xe4\x28\xb5\x62\xb3\xfc\xff\x5f\xaa\x03\x40\x74\xce\x25\x1e\xe0\x48\xe6\x5a\x2b\x90\xba\x15\x90\x4d\x4c\xd7\xe7\x89\xac\x39\x45\x5e\xe7\x0b\x2e\x02\xa4\x30\x65\x7d\x77\x8e\x43\x05\xd3\x15\x07\x01\x35\x52\x3b\x3e\x68\xfc\x3d\xfc\x48\x34\x22\x41\x13\x18\x61\xd9\x46\xd2\xaf\x5e\xe8\x32\x8a\x3c\xbb\xc8\xbe\x25\x6f\xbd\x4a\xde\x7a\x9d\x04\x2d\x2d\x1f\x69\xc2\xc8\x6a\x47\x82\xa5\x5e\xd8\x36\x72\xcc\x6d\x81\x7c\x0b\x70\x8f\x58\xbd\xc8\x54\x84\x5d\xc1\xe2\x09\x99\xa4\x81\xde\x66\xbf\x60\x27\x69\x27\x5e\x45\x65\x37\x4f\xe8\x41\x2f\x76\x87\x41\x48\x50\x4c\x44\x14\xb5\xa9\x93\xe6\x5a\xe7\x4c\x6a\xcd\x07\xc2\x41\x90\x01\x8d\xd2\x3d\x93\x05\x6b\x33\x0c\x42\x66\x71\x63\x9f\x76\x2d\x99\x4a\x95\x72\xbe\xc8\x25\x1c\x8f\x4d\x7e\x66\xd4\x1e\x1e\xcb\xe6\x91\x2d\x85\x72\xf4\x8c\x17\x8a\xd0\xcf\x46\xef\x5e\x08\x92\xec\x65\x30\x46\x20\x08\xca\xa0\x38\x68\xc4\xe7\x37\x79\x12\xe2\x8a\x6f\xbd\x04\x26\x4f\x5d\xdb\x83\x68\x90\x42\xbb\xb5\x52\x4d\xc6\xa6\xfd\x92\xa7\x9e\x4a\x82\x7a\xa1\xfc\xe1\x65\xac\x0b\x18\xa9\x65\x7e\x45\xe5\xe4\xf3\x73\x1f\x65\x74\xc4\x9f\xa4\x9d\x22\xba\x82\x60\xdc\x8e\x4a\x14\xaa\xb4\x3f\xcf\xdd\x5b\x2b\x4b\xf0\x13\x2f\x73\x94\xae\x9d\x9d\xe0\xc9\x60\x66\x33\xb2\x00\x64\xed\x95\xb0\x85\x3a\x2c\x3f\x74\xc0\x06\x34\x32\x3b\x79\x62\xc8\x77\x80\x11\x31\xc0\x5c\x28\xca\x5e\x13\x8b\x78\xaf\x2b\x19\x6d\xcd\xba\x27\x41\x9f\xaa\xef\xc6\xdf\x3d\xb3\xb2\x50\x8d\xb3\xb8\xad\x28\xd6\x28\x49\xcf\xaf\x4f\xc5\x36\xb6\x27\x53\x37\x8b\xa4\x6e\x8a\xbf\x85\x79\x2e\x2d\x59\x47\x1a\x61\xc5\x3d\xf2\x03\x6a\x8d\x22\x39\x9d\x63\x27\x69\xfd\x08\xa7\x75\xd1\x99\xff\x0b\xfa\x02\x8b\x3a\x7a\x0b\x83\x25\x54\xdc\x2c\xc8\xc3\x39\x48\xcf\x99\x35\x91\x08\x99\x51\x59\x30\xa7\x83\x26\x85\x4c\x11\xa7\x1b\xd1\xec\x4f\x0a\xe9\x01\xb7\x63\x81\x4f\xc8\x76\x39\x33\xfc\x21\x39\xc8\x24\x54\xcf\x83\x92\xa7\xc1\xa7\x6b\x09\xdc\xb4\x7c\xea\x40\x26\x14\xc3\x90\x30\x75\x29\x08\x0b\xab\x6b\x83\x81\x4e\xfb\xd6\x66\x76\xcb\x76\x28\x7c\x1c\xb3\xe3\x7c\x63\xc0\xb7\xf1\x21\xd9\xf6\x2f\xb4\x2c\x8a\x16\x60\x31\x66\xce\xc2\x16\xab\x23\x4b\x00\x7e\x99\xcb\xeb\x17\xc9\xf1\x1e\xb6\x28\xf1\xbe\x65\x6b\x91\xe4\x1e\xd8\xcc\x54\x5c\x03\x7c\x32\x09\xcd\xd0\xc1\x31\xe1\x4a\x42\x67\x6f\x90\x69\xa9\x12\x12\x9f\xdb\x64\xd8\x9b\xcb\xc0\x02\x99\xe8\x5f\xe2\x70\x09\x8c\x92\x80\xf4\xea\x38\xd8\x20\xda\x1b\x1a\xa0\x78\x25\x96\x2b\xd4\x90\x24\x42\xfb\xb2\xbb\xaa\x5a\x7e\x99\x80\x86\x68\xd3\xb8\x96\x94\x6b\x86\x25\xce\x3e\x60\xe4\x8d\xbc\x79\xd9\x09\xa9\x2d\x84\xb7\xe2\x9e\x25\x17\x68\xad\xa6\x38\x40\xcc\x99\x4c\x2d\xa1\x5c\x23\xf5\x76\xd2\xce\x29\xf8\x64\xbb\xe4\x2c\x9f\x44\x9e\x95\xd3\x81\xbb\x9b\xd7\xe9\x47\x45\x52\x9b\x8c\x3c\xfa\x1d\x6a\xcc\xd5\x78\x31\x62\x9e\x0d\x31\x83\x06\xe8\xfd\x2c\x94\x34\xd2\x96\xfa\x25\xbf\x81\x35\x9c\xdf\x29\x5f\xbb\xca\xe1\x32\x13\x4f\x54\xdc\xd9\xc4\xae\x96\x11\xce\xd0\x5b\x1a\x5a\xc5\x0d\x5c\xbd\xfd\xe9\x0b\xfd\xc1\x4e\x25\x19\x91\x88\x9a\xa1\xb5\x63\x42\xec\xc7\xc5\xe0\xe5\xc2\x61\x2d\xe3\x51\x2d\x5a\x03\x3a\x52\xda\xcb\x2a\x60\xc3\x77\x04\x64\xb7\xbf\x23\x2b\x3d\xaf\xb4\xbb\x37\xdb\x09\x66\x3d\x66\x1d\x29\x76\xd4\x1d\xaf\xff\x83\x96\x30\x08\x2c\x3f\xac\xf1\x02\x24\xca\x4c\x90\x14\x2f\x16\x01\xa5\x50\xd5\x88\x5b\x55\xcb\xd8\x5a\x3b\x22\x84\x6f\xdb\x3d\xbb\xb1\xec\x25\xf8\x41\xe9\xc8\x4e\xbc\x13\xa8\xec\x12\x2f\xee\xbe\x47\xf5\x0a\xb2\xcd\xf0\x5d\x48\x54\x31\x9c\x85\x63\x58\xb3\xc0\xb9\x7e\x6b\xa5\x11\xba\x07\x75\xce\x49\x7c\xb5\x72\xfb\x56\xe0\x4c\xca\x03\x1a\x08\x94\xff\x81\x15\xce\xc2\x01\xd4\x68\xb7\x4c\x09\x17\xc7\x1f\xcc\x06\xcd\x32\xe0\x02\x6c\xf3\xab\x90\x74\x6c\x3c\xab\x4b\xf1\x01\xd8\xe1\x37\xc9\xd8\x21\x4b\x4d\x05\xea\x7d\xea\xc3\x2f\xbc\x0d\xd9\x54\xe5\x15\x2e\x97\x6c\xdf\x1b\x2e\x4c\x7f\x34\xe8\xaf\x2c\x65\x2b\x24\xb2\x8c\x3e\xfb\xfc\x77\x89\x0a\x2f\xdc\x41\x44\xb9\x4a\xd3\x67\x05\xd6\x5f\xc6\x47\xc2\x66\x48\x07\xcf\x53\x4c\x6d\xbd\xf2\x73\x04\xb5\x06\x2b\x6f\x60\x11\x70\x18\x9c\xdc\x34\xe2\x8d\xba\x5b\xb6\x89\x3b\xfa\x26\x75\xd1\x3f\x2d\x6a\x42\x67\x0b\x6b\xd9\x4e\x32\x17\xb0\x92\x45\xc3\x8d\x05\xda\xa8\x06\x0a\x32\x87\x59\x80\x55\x39\xfd\x85\x1d\x92\xae\x86\xb9\x15\xc8\xe7\x8f\xa6\xc9\x7e\x44\x32\xc2\x26\x23\x53\xc4\x7a\x6b\x57\xc1\xcc\x87\xfb\x4e\xe3\x50\xab\xe2\xe7\x10\x8a\x25\x4f\xcc\x0e\xa4\x45\xd8\x55\x55\x14\x1f\x02\x20\x7e\xb0\x19\x62\xf1\x25\xeb\xf7\xda\xf2\xe3\xa9\x99\xe8\x01\xb6\x59\x7e\x6d\x4b\x62\x3a\x58\x5b\x59\x26\x99\xdd\x70\x99\x40\xdd\x5e\x22\xde\x4b\x63\x67\x93\xd8\x91\x77\xd3\xee\xfb\x4c\x22\xdc\x63\x58\xaf\x9f\xee\x85\xd0\x5d\x13\x75\x66\x3f\x33\x1f\x70\xdf\x98\x9c\x60\xf1\xae\xfc\x5c\xe7\x4a\xe1\x47\xa9\x1a\x2e\x28\x44\xfc\xda\x68\xcd\x3b\x38\xd9\xa9\xdb\xb4\x25\x59\xc6\x26\xed\x37\xc5\xd4\x65\x0d\x0b\x8f\x51\xe6\xf8\x3f\x2d\x71\x0d\x80\xc8\x9b\xb8\x0b\x39\xc6\x44\x9e\xd9\x9a\x0f\x92\xd1\x08\x9b\xf6\xf6\xcb\x0b\x65\x25\x2a\x7a\x2a\x11\xc0\x93\x59\xfc\x27\xe7\x1c\x3d\x82\x75\xae\xb8\x7f\xa8\x58\xfa\xce\x3c\xc4\xeb\x20\x07\x02\x33\xe2\x2b\x89\x57\xd0\xee\x32\x53\x90\x0c\xa1\x11\x73\x16\x0c\x3b\xca\x51\x8a\x95\xd5\x97\xd0\x52\x99\x12\xa8\x03\x50\x1b\xe1\x4c\xb5\x61\x45\x17\xe3\x8c\x8d\x34\x32\x4a\xf1\x82\xd8\xf3\xba\xce\xe8\xde\x30\x22\x0f\xa0\xa0\x16\x2b\xc4\x77\x0c\x17\xc8\xa6\x7b\x94\x7f\x99\x2d\x24\xac\xe4\x3b\x58\xd8\xf7\xbf\x22\xef\xfe\x89\x7e\x21\x20\x6c\x4d\x23\x2c\x2f\x6b\xdb\x5f\xe6\x48\xb8\xa7\x8c\xf0\x8d\x92\x8d\x67\x6a\x9d\xae\x56\xa7\xd5\x22\x65\x65\x32\x37\x0c\x9c\x23\x61\xdc\x14\xe2\xff\xd4\x0d\x61\xe1\x8d\x5a\xf5\x68\x9b\x42\x4c\x28\xe8\x20\x73\x62\xdd\x4d\xbb\xcd\xf0\xdf\xc2\x67\x6b\x64\x04\xc5\xa8\xc9\x9e\x0e\x59\xf3\xb7\xf8\x25\x6f\xad\x6d\x59\x78\x7e\x99\x97\x4c\xbd\x1e\x6f\xc2\x84\x1c\x08\xec\xe3\xcc\x88\x59\x17\xeb\xc5\xae\x7e\xdb\xee\xde\x2f\x50\xb3\x4a\x73\x64\xae\xa9\x0e\x91\x5a\x92\xfa\x6b\x59\x8e\xb1\x8c\x76\x3a\x7c\x2e\x98\x6a\x76\x61\x04\x65\x3a\xf4\x34\x92\x36\x0d\xd6\x09\xc7\x7e\x15\x0d\x42\xea\xc7\x5d\x9a\x27\x4e\x2f\xda\xc3\xc5\xbc\x59\xbe\x45\x1c\x01\x22\xe3\x7b\xb4\x79\x77\xa2\x2b\x0e\xd5\x80\xe2\x96\x96\xad\xe3\x5f\xe2\x29\x51\xd2\x9d\x59\xd7\xb1\xb6\x07\x3f\xbd\xf1\xcd\x83\xec\x59\xac\xb0\x2c\xdb\xc8\x6c\x81\xa4\x57\xcd\x72\x40\x07\xd8\x85\x3f\x7f\x31\x1d\xf0\x54\x0e\xbc\xcd\x79\xf9\x43\x15\xfa\xe3\x0d\x27\x3f\x21\x17\xcb\xe2\x65\xbf\x37\xb5\x48\x64\xcf\xb9\xc9\x9e\x60\xe3\xd2\xc5\xa3\x14\x58\xdd\x2b\x91\xe1\x59\x3d\x0c\xeb\xeb\x15\x8e\x80\xe4\xec\x41\x45\x4a\x88\xd7\xdd\xa4\x21\xe1\x21\xd9\x7a\x43\x69\x6b\xd0\x94\x04\x0b\x4d\xcd\x74\x0f\x50\x0d\xe0\x06\x8e\x4d\x3f\xf9\x0e\xbd\x29\xfb\x25\x54\xda\xfc\x34\xd3\xcb\xb3\x31\xf0\x4c\xef\x0c\xfc\xf0\x3b\x4d\xc7\x13\x6c\x2f\xc8\xf9\xe1\x50\x70\xfb\xa4\x26\x87\x8a\xe0\x26\x85\x08\xe1\x1c\x30\x0a\x73\x4e\xb9\xe6\x3d\x2c\xe7\x70\x49\xaa\x7b\x53\x63\x94\xb0\x66\x8e\x52\xba\xb3\x69\x9e\xe8\x9e\xba\xb5\x9b\xd4\xf6\xa5\xa5\x5d\x06\x3c\xc4\xae\x0b\x5a\x5a\xe5\x55\xc7\xba\xf6\xdc\x5c\x26\xa1\x4a\xba\xa2\x0d\x32\xc8\xa4\xf8\x57\xec\x65\xfe\x70\x14\x6e\xd0\xb7\xce\x57\x38\x3f\x43\x9b\x72\x44\xf0\x11\x4e\x4f\x1a\xa7\x46\x80\xa1\xdd\x0f\x87\xca\x94\x23\x3f\x09\xc8\x40\xe6\x66\x58\xd8\xec\xee\x40\x1a\x10\x05\x1d\x72\x44\x8b\xc2\x1c\x63\xe5\xb4\xe2\x25\xa9\x49\x28\xec\x87\x59\x10\xb4\x13\x06\xaa\xb5\xe5\x7b\x04\x45\x4b\x62\xec\xef\x64\xf0\x10\x4f\x51\x89\xa9\xad\x10\x57\x99\xcb\x2c\x85\xad\x0b\x42\x1f\xd0\xea\xf3\x34\x54\x9e\xb7\xf3\x82\xf8\x24\xeb\xbd\xf4\x7b\x8f\x97\x6d\x1a\xa4\x57\xbc\x4e\x7b\xd7\xd6\x96\xe7\x24\x92\x33\x73\x4a\x20\x18\x10\xd3\x47\x19\x01\xa3\x96\x74\x12\x27\xe2\xcb\x90\x9e\xca\x30\x82\x91\xe2\x92\x5d\x1c\x47\x4e\x18\x1a\x39\x7a\x43\x5a\xde\x7b\xce\xb9\x8a\x3a\x73\xb1\x55\xc3\xd0\xea\x51\xf9\x92\x24\x9d\x92\x91\x25\xed\x78\xf0\x6e\xb8\xda\x30\xb6\x16\xf4\x91\x68\x2a\x3c\x08\x84\x6c\xc7\xa4\x9f\xdd\xcb\xc1\x3f\x7e\x9c\x7e\x02\xf1\x52\x9b\x2f\x9e\x49\x83\x6b\x0b\xf6\xd9\x2d\x02\xff\x3c\x46\x54\xf9\xa5\x0d\xe5\xe1\x14\xa1\xd0\xa1\x8b\xb0\x92\x57\x35\x02\x0a\x86\x9d\x9d\x72\x22\xc4\x6e\x6a\x15\x45\xb4\xa2\x75\x51\x34\x6b\x09\x5d\xc0\xa5\xc2\x42\xd7\x10\x59\x6e\x2d\x82\xf4\x26\xb6\x80\x13\x71\x77\x51\x81\x96\x59\x90\x79\xe6\x1b\x87\x43\x05\x9d\x56\x6f\x23\x03\xaf\x60\x25\xfa\x8a\x4f\x4c\x74\x7c\x4c\x8b\x54\x0b\x1f\xa4\x2d\x7a\x68\x8b\x34\x91\x4c\x87\x15\x73\xd5\xf5\xae\x3e\x96\xc7\x2c\xe5\x2e\x7e\x0e\x94\x1a\xf5\xdb\x4c\x4d\x61\xdb\x21\x6c\x26\x7b\xf2\xa9\x50\x88\xce\x0c\x48\x2d\x53\x75\xfe\x9b\xa6\x26\xe8\xb8\x8b\x4a\xe3\x44\xf7\xc3\xe3\xd3\x5a\xf8\x8d\x48\xd9\x5a\x5d\xa1\x77\x03\x26\x8d\x24\x2e\x71\x65\x37\xb2\x66\xb0\x66\xf1\x38\xe2\x85\x03\x67\x93\x9e\xa0\x45\x8c\xcb\x2c\x5c\xcc\xca\xf4\x2c\x63\xd5\x6b\xbc\x83\x5d\x5e\x05\xf1\xf8\x67\x53\xd2\x0a\xe6\x6f\xb5\x1d\xe7\x99\x83\x36\x94\x25\x61\x93\x86\xd6\x09\x3a\x1c\xec\x81\x74\x5a\x57\x5c\x73\x19\xa6\xb4\x62\x6a\x7f\x1c\x24\xfa\xae\xad\xfc\x88\x1d\x15\x5f\x5c\x2c\xc0\xd8\x71\x4b\x49\x0a\xc5\xa1\xbf\xb3\xcc\xa4\xb2\x89\xbf\xd3\xe9\x7e\xd7\x89\xc0\x73\x2b\xd8\x2d\x2c\x6b\x2d\xf7\x03\x63\x34\xcb\x6c\xee\x20\x6c\x14\x04\x85\x8b\x4f\x8f\xdc\xf6\x7e\x29\x1a\xaf\xd3\x0d\x43\x03\x16\xd6\x25\x59\x16\xae\xae\x28\x2f\xa2\xd4\xbf\xb2\xa4\x41\x95\x65\xc5\x10\x4c\xf0\x88\xec\xed\x5c\x6b\xcd\xd3\x3b\xb5\xe2\x21\x54\xe4\x81\xb0\xec\xf7\xf4\x91\x08\x6f\xba\x76\xa5\xba\xb6\xb2\x8d\x52\x02\xd2\x5d\x5c\x19\xa6\xa8\x9e\x51\x3b\xf5\x59\xe2\x7a\x46\xba\x7a\xdf\xf9\xa2\x10\x2a\xe4\xe7\xbb\x3a\xd0\x14\xd1\xb2\x72\x7c\x44\x1d\xc9\xc3\xc0\x59\xc7\xb8\x1f\x4a\x85\x52\x45\xb5\xa1\x29\xe5\x9b\x8c\x51\x29\xaa\x15\x76\xf2\x97\x26\x18\x02\x22\x9c\xc5\x32\xed\x94\xd3\xb9\x0e\xd2\x32\xd4\x19\x96\x7e\xe5\xc8\xa2\x70\x1d\x3a\x11\xa5\x12\xba\x2b\xdb\xa2\xf6\xc8\x07\x48\x85\xfb\x3a\x01\x1e\xe3\x48\x26\xe9\xb4\x2e\xc8\xd5\x59\x74\x2c\x21\x8e\x52\xcb\xef\x4a\x6a\x58\xcc\xa5\x00\x3e\x6f\x17\xf6\x0f\xc5\x0f\xc8\x7c\x8c\xf5\x52\x4d\x95\x0e\xe4\xac\x5b\x90\x83\x30\x80\x3e\xa5\x04\x67\x69\x58\x5e\x44\x09\xac\x17\x28\xde\x47\x54\xaf\x49\x7f\xe4\x21\x21\xe9\x23\x08\x8b\x68\x22\xc1\x5e\x44\x8e\x47\x26\xbd\x15\x1f\x64\x25\x4c\xb7\x0e\xce\x47\xc7\xad\x10\xe0\xcd\x34\x49\xb5\x8c\xeb\x17\xff\x20\xc6\x48\x0d\x63\x15\x56\x17\xc0\xa4\xe0\x48\xb6\x7b\x7b\x0c\x58\xc4\x8d\xf9\xd8\x90\x39\x7f\x83\x7d\xe0\x49\xee\x87\xae\x76\xab\xaf\x09\x70\x8f\x16\xcc\xba\x15\x85\xf9\x50\x14\xe3\x22\xda\x5e\x89\x75\xe6\x78\xdf\x3a\xba\x54\x17\x84\xf5\x85\xed\x51\x5c\x39\xeb\x69\xa4\x47\x04\x50\xa3\xb5\xa6\x41\xf0\x24\x1e\xa9\x49\x0f\x08\xe2\xa5\x44\x33\x29\xb4\x5e\x80\xd0\x99\x23\x2f\x9e\x6c\x09\xae\x08\x00\x12\xa6\xda\x75\xa4\xbe\x23\xc3\x77\x46\x7b\x45\x94\x6e\x80\xb4\x4c\x68\x50\x3e\x89\xe3\xfd\x7f\x80\xaf\xf6\xe0\x4c\x44\x76\x22\x8a\xba\x39\x86\x07\x21\xe9\x67\xe3\xdc\x57\xe0\x09\x1b\x69\xf6\xbd\xb4\x2d\x37\x75\x0f\xe7\x4b\xb8\xa7\xed\xbf\x2e\x0f\xcc\xd2\x12\x32\x7a\x40\x72\x91\xb3\x3d\xfa\xc3\x12\x45\x07\x46\x6d\x57\x7c\xb4\x52\xcc\xd2\xf8\xc9\x00\x87\x2a\x6f\xa7\x40\x4d\x0b\xe1\x61\xe3\xd4\x63\xb0\xf7\x08\xef\x61\x98\x38\x5e\x42\x67\xd6\x0c\x4a\x56\x10\xc9\x56\xf4\x6d\xd0\x67\x6e\x40\xac\x67\xd0\x5e\x89\x41\x79\xd8\x8f\xa9\xae\xe4\x1f\x69\x13\x33\xbc\x59\xb0\xc0\x93\xf0\x4a\x66\x75\x6f\xaf\x83\xc0\xb5\xfd\xa5\x02\xda\x5a\x11\xe5\x09\x2d\xbf\xec\xb6\xf5\x76\xe6\x28\x2d\x9c\xab\xd4\xee\x9f\x01\x3c\x0c\x8c\x08\x84\x0a\x74\x67\xeb\x8c\x70\x16\xf5\x5e\x9e\xea\xa5\xf4\x7f\x8c\x58\x65\xca\x3b\x49\x28\x1a\x97\x97\x0c\xf8\x66\xd7\x77\x1b\x85\x88\xae\x36\x8b\x36\x82\xd7\x9f\x50\xe6\xbc\x6d\x28\x10\xfc\xd2\x43\xba\xa2\x75\x4c\xd8\xcd\x48\x29\x11\x74\xdc\xd2\x0d\x1d\x83\x41\x6e\x13\x31\xe8\xc1\x82\x74\x5c\x15\x6f\xe5\x25\xf4\x4f\x33\xca\xfd\x6f\xe1\x90\x5f\xb5\x0e\x36\x0d\x03\x7b\x79\xe1\x3c\xce\x8c\x38\x30\xe5\x30\x0c\x83\x1e\x11\xa2\xdf\x42\xeb\x77\xfb\x92\xdb\x23\x20\x6e\xd0\x92\x5a\x42\x4e\x38\x8e\x40\x25\x8d\x92\x15\x35\x86\x7e\x69\x34\x9f\x95\xd1\xdb\xfa\xfe\x84\xe0\xfb\x8d\xb4\x87\xf6\x6e\x66\x16\x46\x6a\x20\x8b\x2b\x75\x30\xc9\x20\x15\x81\xb4\x4f\x34\x7b\x47\xaf\xeb\x45\x67\x42\xd8\x88\x0b\xfe\x81\x49\xbf\x17\x3d\xe1\x97\x03\x5c\x6f\xc0\x0f\xea\x98\x50\x17\x3e\xa9\x7e\xc7\x20\x90\x4e\x01\x99\x34\xca\xc2\xd3\x28\x92\xbf\x09\x25\x56\xa1\xb2\xb5\xff\x51\x8b\x2b\x1e\xdd\x1c\x01\x8c\x5e\xbb\x6e\x96\xe2\x7d\xb8\xf8\xa4\x6f\x19\xa5\x72\x0c\x8f\x77\xd9\x9a\x29\x44\x2b\xdb\x12\x75\xee\xf7\xa2\x44\x98\x07\xcd\x05\x50\xce\x0c\x61\x37\x94\x90\x8b\x42\x06\x1d\x1d\xfa\x74\x67\xe6\xa6\xfe\x6c\x68\x19\xa8\xd0\xd5\xf3\x4b\x46\x59\x84\xfa\x8f\xf6\x6a\x52\x0a\x47\x49\x6b\x8c\xa4\xcd\x02\xfe\x46\x8a\xca\x43\xd8\x27\x45\xea\xe8\x74\x2c\x63\x8b\xea\x71\xd1\x89\x7b\x72\x49\x8b\x09\x93\xad\xf9\x15\x42\x34\xc5\xce\xfa\x1c\x55\x53\x8b\x5a\x97\x42\x65\x16\x0c\xf8\x33\x89\xcf\x11\xd7\x0d\x79\xfe\xaa\xb0\x93\xb4\x87\x10\x3a\xca\xf4\xe1\x41\x8d\xc6\x72\x04\x5b\xd2\xa4\xdd\xaa\x0e\x2d\x71\x25\x5e\x82\x28\xcc\xe2\x4e\x8e\xeb\xed\x05\x73\xde\xa5\x6d\x89\x2f\x2a\xbf\x7a\x2c\x71\x2a\xef\xc6\xe3\xe0\xc7\xf2\xc0\xf3\xc3\x06\x88\x3e\x34\x3b\x32\xb0\xf2\xe1\xd3\xc1\xdb\x0d\x3c\x4c\x36\xd4\xd6\xd3\x03\x3b\x92\x69\x35\x35\x84\x24\x43\xed\x11\xc7\x01\xea\xae\x24\x03\x6f\x66\x47\xff\xd2\xb4\xfe\x04\x90\x38\x69\x9b\xfa\x2a\xa3\x70\x6a\xd2\x98\x40\x3d\x3c\x4f\xd1\xd7\x37\x41\x2b\x8b\x8b\x24\x2d\x18\x7d\x92\xb8\x7f\x13\xb7\x88\xdc\x4f\xb5\xb1\xf4\xcf\xc6\x4f\xfd\x2e\x51\xa2\xbc\xe2\x92\x87\xbb\x94\x58\x05\x2b\x33\x2d\xaa\x41\x5e\xe5\xe4\xb3\x43\x6b\x12\x7d\x33\x86\x96\xc7\x62\x9b\xd8\xc2\xda\x5f\x41\x1a\x4d\x6c\xe3\x87\x27\xce\x12\x5e\xb8\x6e\xe4\x88\x21\x91\xde\x81\x53\x62\x08\x77\x66\x6d\x73\xd0\xf9\x30\x3b\x61\x15\xd5\x05\xc0\xf5\x40\x98\xc0\x53\x9a\xf2\x6c\xd0\xb4\x5f\xc8\xf7\x2a\x8b\xd9\x05\xc4\xcb\xad\x4f\x32\x96\xe3\x34\x42\xea\xe5\xf4\x9c\x24\x5f\x89\x8c\xe8\xf6\xc0\x91\x8a\x3d\xa0\x61\x51\x20\xbe\x36\x29\x47\xfa\x42\xa3\x40\xf5\x78\x0a\x6b\x5e\x03\x26\x48\x46\xfb\xcd\xd3\x9e\x49\x83\x35\x5c\x10\x1a\x9c\xe0\x68\x1e\x03\x52\x20\x3b\x58\x4d\x24\x23\x64\x58\x6f\x06\xa3\x97\xd1\x1c\x45\x97\x61\xe9\x8f\xd2\xcf\xef\x95\xa8\x99\x7d\xba\xa4\xd6\xa4\x80\xb4\x87\x9e\x6c\x36\x06\x97\x66\x5a\x7a\x4d\x92\x2c\x50\x60\xe8\xaa\x2d\x82\xc6\x2f\x48\x8b\xa6\x33\x9e\xde\x97\xb9\x62\xdb\xc8\xd1\x75\x34\xc7\xd5\xdf\xc2\xb9\x64\x63\xda\xce\x86\x82\x0d\xf6\x0f\x1c\x60\x73\xec\x58\x94\xb3\x06\x44\x8c\x27\x35\x23\x44\x0d\xf4\x0a\x03\x02\xae\x41\x28\xe6\x86\x09\xe5\x9f\xef\xc8\x71\xfa\x65\xc4\x39\x64\xe9\x82\x63\xfa\x25\xe9\xc6\xe5\x28\x6d\x62\x6c\x27\xb2\xf9\x25\x52\xb2\x3c\x02\xe1\xf3\x52\xe7\xe4\x1b\xd7\x10\x69\x40\x49\x52\xf2\x24\x38\xd2\xf2\x83\x8e\xaa\x88\x97\xfe\x09\xcd\x7a\x3c\xb6\x0b\x17\x21\x0d\x1d\x5d\xdd\x47\x00\x23\x52\x6f\xa9\x3a\x87\xde\xa5\x16\x15\xde\xee\x9f\x7e\x49\xe9\x67\xb9\x93\xab\xf9\x98\x4b\xee\x5d\x81\xc5\xf0\xdd\xc8\x4f\xf6\xc1\xbf\x15\x3d\x76\xd0\x8a\x72\x0e\x1c\x9b\xd4\x24\x78\x6a\x93\xc0\x59\x2a\x4f\xd7\xc2\x63\x2f\xa3\x42\xbf\x54\x94\x24\x9f\xe8\x95\xe7\x0e\xec\x6a\xb7\x98\x9f\xa8\xf2\x73\x7f\xcc\x28\xe0\xf4\xa2\xac\x69\x1a\x1f\xa7\x73\xf6\xa3\xf9\x90\xa3\x19\x10\xee\xe0\x71\xb6\x3c\xc3\x75\xa8\xb0\x00\x3f\xa1\x86\x56\xc3\x78\xcc\x28\x97\x7d\xfa\x6c\xf4\x41\x47\x65\x39\x52\x0a\xf6\x5e\xc7\x6c\xd4\x4c\xa9\x5e\xff\xd9\x14\x4e\x5a\x6c\x2b\x9c\xd5\x8f\xc6\x49\xd6\x86\x86\xc4\x15\x19\xba\x74\xc0\xef\x1c\x24\xc6\x7f\xf5\xa8\x28\x59\x6b\x8a\x20\x88\xad\xb8\xdc\xb0\xe9\x6f\x04\x89\xad\x75\xa7\xf8\x61\xa6\xf3\x37\x88\xb3\x5b\x71\xce\x51\x5c\xd5\xf7\xa5\x67\xd9\x52\x26\xd2\xae\xd4\xcb\xd5\x95\x09\xf4\x23\x63\x54\x6e\x37\x16\x9a\x7a\xba\xb2\xa1\xc5\x08\xaf\x67\xba\xb4\x9c\x5f\x5a\x9b\x64\x6e\xde\xf3\x42\x57\x23\xdd\xb5\x86\xa6\xe5\x99\x4e\x0c\xe9\xcc\x81\x5d\x94\xc2\x33\xa0\x62\x90\x06\x29\x7a\x3f\x8f\x39\xad\x7e\xf2\x13\x69\xb9\xac\x7b\xcd\xfd\x5b\xf5\xe8\x0d\x48\xc1\x11\x02\x2c\x5a\x15\x57\x81\x03\x7d\xe2\x70\x29\x38\x00\x5d\xdd\x12\x32\x3d\x29\x16\xf7\x7b\x8d\x93\x1e\x67\x45\x61\x82\x9e\xaf\x02\x4f\x78\xea\x39\x0d\x3f\xd9\x69\x95\xd9\x45\xfd\x45\x01\xc4\x45\x60\x7f\x4a\x0a\x56\xee\xbc\x48\x00\x4a\x7e\x89\x85\x04\x9a\x38\x05\xc6\xe1\xe3\x7e\xc2\x91\x51\x89\x8a\x2c\xf6\xbf\x4d\x98\xfb\x76\x73\xcf\xee\x77\x2a\x2c\xe2\xd7\x4e\x5a\xcb\xa2\x60\x8e\x2f\xc0\x31\x38\x4d\xc5\x11\xc0\x91\x34\xb7\x40\xf0\x87\x0a\x91\x3e\x58\xc1\xe0\xb9\x43\xc2\xd7\x38\xbc\x48\xbb\x33\xc8\xa0\x14\x72\x8d\x2d\xc5\x36\x3f\x51\x85\x9b\x40\xf0\x54\xb4\x93\x30\x6a\xcc\x32\x44\x9f\xb3\x1a\x8f\x29\x28\x50\x34\x69\x12\xad\x03\xc7\x20\x02\x2a\x46\x54\xde\xcc\x2c\xca\x24\x63\x6c\xe2\x65\x48\xbd\xef\xde\x04\x1f\x1e\xd8\xa7\x31\xc8\x0c\xca\x21\x65\x52\x78\xcd\x3a\x40\xca\x82\xe2\x59\xe7\xe9\x69\xf3\xc4\x20\xb3\xb9\xb6\x59\x27\x27\x66\x99\x89\x55\x04\xd4\xa6\x16\x4a\x52\x53\xca\x40\x97\x5a\xb9\x39\x1f\xca\x7a\xb6\x37\xa4\x92\x17\xb6\xab\x1d\x9e\xfd\x25\xfa\x0d\x54\x25\x1c\x56\xce\x44\x55\x57\x01\x50\xe7\x55\x0e\x7b\xeb\x10\x86\xf2\x52\x28\xe4\x76\x88\x29\xcc\x7b\x68\xaf\x3e\x80\x1f\xef\x9b\x30\x4a\x07\x01\xd4\x1e\xec\xc8\xd2\xab\xdd\x12\xed\x50\xdc\x51\xe4\xd6\x9b\x49\x43\x81\x78\xe9\xe4\x56\xeb\x56\x29\x37\x50\xe4\xac\x63\xe9\xe0\x06\x08\xb2\x5f\x1a\xc8\xcd\xef\xc5\x40\xac\xf1\x21\x2c\xf2\xa4\x80\x0c\x59\xa9\x26\x82\x22\x9c\x3e\xc0\xc5\xed\x1b\x2b\x48\x06\xbb\x98\x5a\xfc\xe6\x5b\x60\xac\xd2\x70\xb8\xee\x52\xb1\xc2\xc8\xb2\x75\xd2\x2a\x97\xfc\x1d\xeb\x9a\x2b\xe2\x90\x25\xe9\x7c\xce\x9a\xd9\xe4\xb1\xf5\x6c\xc3\xa2\x53\xde\x17\xa5\x09\xb1\x5c\xd7\x8e\x4e\x62\xe6\xc7\x22\x01\xa6\x45\x4d\xb8\xab\x10\x36\xd6\x21\xc6\xe9\x86\xa0\x7d\xec\xd8\x7f\x66\x54\x8d\x08\xb4\x9f\x9c\x14\x7e\x54\x2c\x60\xde\xff\xa6\xe1\x32\xca\xde\xff\x9d\x60\x49\x2d\xe1\x1f\xe4\x74\x5e\xce\x1e\x4f\x1e\xca\xfb\x39\xa0\x93\xa9\x92\xf2\xe3\x14\xae\xbd\x06\xe0\x72\x60\x67\xed\x76\x4e\xec\xe7\x04\x71\x88\x71\xd7\xdd\x2f\xe1\x38\x82\xb5\x03\x6f\x84\xab\x27\x8d\x46\xbf\xbb\xb5\x27\xb9\xe6\x1c\x3e\xa8\x57\xdc\xb3\x64\x6f\xee\x52\x8a\x89\xd7\x21\xf1\x3f\x3a\x1f\x40\x46\x62\x93\x25\xec\x81\x0f\x5a\x58\x72\x70\x87\x49\xf3\x70\x39\xb7\xa4\xcf\xca\x12\xb4\x97\xa7\x77\x71\x68\xb4\x3f\xa6\x39\xc2\x57\x89\xf7\x8d\x1e\x80\xd7\xb0\xef\xa0\x32\xbb\xf1\xa4\x2b\xad\xd6\x2c\x24\xb5\x96\x65\x01\xfd\x4b\x71\x41\xfd\xa3\x41\x1a\x81\x18\x1d\xbc\x27\xe9\x0a\x72\x80\x9f\xb9\xfd\xfe\x49\x14\x08\xdb\x0e\x81\xfa\x36\x65\x9e\x77\x2c\x37\x6c\x12\x1b\x0d\x34\x07\xc7\x5a\xa4\x8e\x9b\x5f\x13\xf1\xbf\x6b\xd4\x2b\x30\xc9\xae\x51\xb1\xa4\xe4\xb7\x5e\xc9\x6c\x5c\xeb\xc3\x88\xfb\xc3\xba\xcd\xe4\x48\xb6\xe4\x08\xd2\x04\x2f\x2f\x31\xbd\xc2\xe2\xa9\x4a\x26\x67\xc7\xed\x26\xbd\x08\xe9\x3a\x13\xff\xe2\xd7\x5b\x69\x5b\xfe\x47\x2b\xbd\x6c\xd2\x9c\xc2\x7a\xb0\xb9\x51\x3a\x2b\x71\x6c\xdd\xe7\x3b\x2c\xf3\x45\x17\x60\xd0\x62\x44\x22\xe7\xe8\x82\xf2\x2b\x49\x60\x3f\x2f\x8d\xbb\xcf\xbe\x32\x99\x81\x4e\x39\x66\xf6\x3d\x2a\x29\xd8\x28\x94\xd7\xe5\x88\x13\xdb\xa1\x23\x08\x50\xa2\x7d\xc8\x88\xc3\x1e\x88\xdf\x4a\x55\x01\x93\x5e\xcd\xf6\xdb\xd3\x6e\x68\xb4\xad\x4c\xd9\x70\xef\x87\xa0\xd9\xba\x3b\x1b\x51\x24\xde\x6b\x55\xea\xca\x7e\x34\x52\xb1\x0c\xd2\x33\x39\x23\xdc\x6b\xb6\x46\x4e\x3e\x61\x70\x49\x66\x6c\x31\x93\xad\xb3\x05\xad\xb2\xc4\x32\xfe\x92\x58\x3d\xf9\x76\xa8\x53\x11\x44\xfa\x60\x15\x45\xe7\x57\x93\x30\xf0\x9d\x28\x3a\xff\x03\xd8\xae\x5b\xf9\x29\x41\xcd\xb1\x67\xc5\xd2\xac\xae\x1f\x58\x26\xfe\x10\x7f\xf1\x61\x9a\xcb\xd0\xc0\xe8\x03\x09\xd0\x7d\x3f\xd2\xb1\x79\x90\x8f\xbb\x7e\xb0\xc9\x0a\xf4\x02\x70\xae\x67\xc9\x00\xac\x02\x08\x32\xa2\x6b\x39\xf6\x3f\x4c\xde\x6b\x52\x91\x48\x9e\x0a\x6a\x60\xc6\x9e\x44\x97\xc2\x49\x28\x45\xbe\x9a\xcb\x40\x60\xd1\xc7\xcb\x28\xf0\x78\x89\x18\x88\x21\x9d\x85\x21\xd6\xa2\x04\x2a\x1d\xc4\x05\x88\x1d\x18\x8f\xcc\x2c\x8a\x5a\x0a\x22\xef\xb8\x1c\x9b\x4b\x2d\x17\x00\x54\xc2\xc1\xb4\xfb\xe5\x79\xe1\x43\x49\xcd\xbc\x31\xd3\xdf\x44\x45\xf7\x48\x6b\x5b\xde\x6e\xd0\x53\x8a\x1c\x23\x2f\x42\x8e\xcd\xa5\x76\x06\x9f\xa4\xaa\x63\x7c\x4a\xb7\xa3\x0f\x6d\x7a\x68\xb5\x4c\x7b\xb5\x16\xd0\xba\xe7\x7c\x49\x3e\xc8\xe8\xa0\x65\x5b\x92\x5c\xaf\xe2\x99\xb0\x99\xec\x11\xef\x77\x49\x54\xec\xc4\xfa\x04\xe5\x2d\xfc\x82\x7d\xdc\x05\x49\x02\x29\x8f\x6f\xc9\x3f\x60\x4e\x09\x01\x09\xf1\x48\x99\x41\x35\x2d\xac\x64\x0b\x1d\x6f\xcb\xe6\x4f\x38\x2a\x23\xc1\xda\xc7\x50\x80\x05\x97\xc2\x44\xb9\x23\x37\x60\x9e\x0c\x3c\x10\x63\xf7\x14\x57\xe6\x9a\x7e\xc8\x52\xac\xb8\x94\xcc\x6b\x31\xd6\x53\x96\x46\x74\x2c\xad\xc8\x30\x1b\xd6\x97\x1c\xe9\x98\x20\x6b\xd9\x6d\x10\xd9\xd0\x8d\xdb\xe2\xfa\x45\xa8\x1e\x12\x0b\xcb\xef\xd4\xac\x02\x58\x5c\x77\x8d\x1f\x24\xe0\x5e\xa7\xa6\x21\x23\x18\x38\x9a\x0e\x92\x1b\xfe\x2d\xc7\x1b\x2c\x93\x14\xf7\xe2\x25\x7b\x39\xe8\x80\x4e\x0b\xe0\xe4\x12\xdc\xd2\xf1\xb5\x46\x92\x05\x2e\x52\x19\xb4\x0e\x46\xbf\x10\x7a\x16\xae\xc1\xac\xdc\xd6\xb5\x2a\xe1\xd9\x82\x95\xc2\x58\x82\x4d\x18\xcb\x63\x22\x01\x69\x18\x1a\xb2\xca\x33\x4c\x32\x2e\x3e\x5c\x68\xa6\x61\x5d\x3c\x43\x33\x70\x32\xe6\x10\x95\xc1\x6f\xee\x90\x92\xe8\x75\xbc\xa1\xd6\xc4\x8a\x32\xd1\xc9\x07\x64\xf8\x93\xa2\xc6\x34\x8a\x9e\x19\x05\x7b\x42\x2f\x36\xd7\xf9\x7c\x59\xf4\x8e\x0e\xb7\xb3\x7e\x7c\x37\x2c\xd6\x31\x4a\x48\xfd\x41\xc5\xc9\x20\x88\xed\xa4\x62\x84\x1e\x13\xe7\xae\x17\x6f\xc5\x3f\x09\x47\x5b\xe8\xef\x75\xef\x60\x96\x8e\x53\x11\xba\x3e\x2d\x9a\xd4\x3c\xf8\x51\x41\xa6\x57\x24\x65\x49\xa8\x4c\xde\x95\xd0\x4b\xa6\x39\x69\x1d\xd9\x7c\x51\x22\xae\xa1\x45\x84\x6b\xa4\x66\xa1\xa2\x5c\xd3\x78\x14\x8d\xb3\x53\xe1\x48\x42\x94\xcf\xde\xec\x25\xb6\xc4\x48\xf4\x9a\x20\x71\x8d\xb1\x5f\x00\xb5\x6c\x6a\xa6\xdf\x77\xdb\x38\xb1\x6e\xe3\x07\x24\x1c\x2b\xa7\x86\xfc\xb9\xe1\x8d\x54\x40\x90\x35\xfd\xe0\x4c\x15\x6f\xc4\x30\x87\xf8\x1f\x0a\x12\x38\x52\x91\x4f\x5e\x67\x85\x82\x17\x37\xea\x09\x84\x8e\x50\xd0\x10\x84\x1b\xa7\x7b\x62\x03\xe5\x4e\x07\x65\x1b\x39\x42\x9d\xe2\xb9\x86\x67\x60\x42\x13\x4d\xd3\x8b\x10\x5e\x2d\xe9\xaf\x62\x0d\x58\x1e\x8d\xcc\x3e\x9a\xff\xc1\x16\x96\x9b\xf0\x77\xef\x46\xee\xed\x39\x8e\x88\xd9\x19\xdc\x15\x99\x83\xa4\xbc\xb7\xc2\x2e\x50\xab\x9a\x50\x0c\x3a\xf5\x77\x53\xc0\xf0\x8c\x2a\xb7\x5d\x5d\x7c\x94\x46\x58\x00\x68\x7f\x86\xf0\xe4\xac\xb5\xe9\xad\x60\xf6\x6d\x26\x59\xcf\x3c\x0b\x0e\x48\xc0\x70\xc7\x40\xab\x20\xda\x82\x94\xfd\xd2\x5c\x9e\x75\x7a\x52\x33\x4b\x7a\xd3\x62\x29\x34\xea\x18\xf0\x94\x0c\x03\x6f\xfc\x3b\x51\xe1\xcc\x13\x6b\xa2\xf0\x47\x12\xe0\xc4\x8f\x18\xb4\x14\xf1\x08\x2c\x8c\x24\xf0\x94\xa4\x4a\xb7\x0d\x8d\xe2\x7f\x78\x0f\x36\x7f\x03\x3e\x8b\x80\x48\xa3\x82\x7a\x12\xfe\x8d\x25\x52\x48\x6c\x5b\x8c\x36\x70\x3c\x32\x67\xa8\x81\x6b\x6a\x05\x10\x71\x27\x8a\x1f\xd6\x92\xa8\x4b\x2e\x95\x7c\xa3\xb9\xea\x64\xab\x79\x44\xed\x34\xca\x54\x2d\xe2\xa8\x28\x74\x2f\x93\xe7\xff\xa6\x1d\x13\xb5\x44\x12\x47\xa4\x5e\xa8\x7c\x80\xe7\x34\x1a\x4d\xa1\x75\x63\x8f\xc9\x2c\x6e\x61\xe5\xc3\x16\xfa\x3d\x9c\xa9\xc0\xa1\xbc\xa1\x92\xd4\x96\x7f\xff\xaf\xff\xfa\x3f\xff\xf5\x7f\x03\x00\x00\xff\xff\x1c\xf7\x13\x7e\x95\xd2\x00\x00") + +func dataFemalenamesJsonBytes() ([]byte, error) { + return bindataRead( + _dataFemalenamesJson, + "data/FemaleNames.json", + ) +} + +func dataFemalenamesJson() (*asset, error) { + bytes, err := dataFemalenamesJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/FemaleNames.json", size: 53909, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dataKeypadJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x9c\x94\xcd\x6a\x85\x30\x14\x84\xf7\x3e\x45\xc8\x52\xeb\xff\x5f\xec\x0b\xf4\x21\x4a\x17\xdd\x75\x21\xa5\x14\xba\x2a\xbe\xfb\xcd\xd5\x8b\x99\x91\xe3\x3d\xea\x46\x26\x42\xe6\x3b\x33\x1c\xf2\x1f\x19\x63\xdf\x7e\x3f\x7f\xbe\xec\xab\xb9\x1f\xfc\xb1\xf0\xf2\x7d\x96\xc6\x7c\xff\x8d\xe3\xcb\x43\xdb\xd2\xae\xb2\x0a\xb2\x0e\x32\x5b\x25\xde\xdb\xea\x59\x7e\x2c\x7f\xbc\xa7\x0c\x23\x70\x13\x10\xad\x38\x43\xb1\x0b\x26\x58\x05\x30\x4c\x23\xfb\x77\x4a\xc6\x0d\x95\x48\x35\x92\x2a\xc5\xfe\x59\x59\x32\x97\x58\xcd\x91\x0a\xfb\x70\xdd\x69\x6d\x96\xfb\xb9\x5a\xcc\x05\xb5\xc9\xf6\x83\x56\x26\x41\x09\xd4\x21\xa8\xd5\xdc\x13\xb5\x4b\xa6\x12\xaa\x3f\xd0\x1f\x59\xe5\x5a\x97\xcd\x7e\x81\x0e\x73\xf5\xe2\xd8\xe8\x1f\x6b\x65\x12\x95\x48\x03\x92\x60\x4e\xd9\x3d\xd5\xca\x64\x28\x91\x62\x24\xe5\xe7\xd6\x5a\xe4\x62\x56\xc7\xac\x04\x59\x83\x12\xe5\xc8\x04\x9b\x8c\x04\x4b\x11\x16\x5f\xb6\x25\x04\xa5\x24\x5a\x86\xb4\x42\x79\x6b\xaf\xcc\x40\xb4\xfc\xe4\xd6\x53\x08\x79\x2d\x1d\xbe\x07\x0b\xcc\x7f\xa7\x68\x8a\x6e\x01\x00\x00\xff\xff\x2d\x9a\xa0\x40\x67\x06\x00\x00") + +func dataKeypadJsonBytes() ([]byte, error) { + return bindataRead( + _dataKeypadJson, + "data/Keypad.json", + ) +} + +func dataKeypadJson() (*asset, error) { + bytes, err := dataKeypadJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/Keypad.json", size: 1639, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dataL33tJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xaa\xe6\x52\x50\x50\x4a\x2f\x4a\x2c\xc8\x50\xb2\x52\x00\x71\x80\xdc\x44\x20\x33\x1a\xcc\x04\x72\x4c\x94\x74\x60\x4c\x07\x25\x30\x2b\x16\x22\xa0\x94\x84\xac\xcc\x02\x55\x2e\x19\x59\x4e\x03\x61\x44\x35\x82\x19\x8d\x60\xda\xa0\x6a\x4e\x45\xd6\x6c\x8c\x2a\x97\x8e\x2c\x67\x86\x30\xc2\x12\x55\x59\x26\xb2\x32\x43\x84\x32\x45\x04\xb3\x06\x55\x47\x0e\x0e\x1d\x35\x08\xa6\x39\xaa\x8e\x7c\x64\x1d\x06\xa8\x72\xc5\xc8\x72\x2a\x08\x23\x4c\x51\x95\x95\x20\x2b\xd3\xc6\x69\x53\x05\xb2\x32\x55\x54\xb9\x2a\x64\x39\x23\xa8\x1c\x90\xac\xe5\xaa\xe5\x02\x04\x00\x00\xff\xff\xd5\xd6\x71\x46\xdd\x01\x00\x00") + +func dataL33tJsonBytes() ([]byte, error) { + return bindataRead( + _dataL33tJson, + "data/L33t.json", + ) +} + +func dataL33tJson() (*asset, error) { + bytes, err := dataL33tJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/L33t.json", size: 477, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dataMackeypadJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x9c\xd4\xcb\x4a\xc6\x30\x10\x05\xe0\x7d\x9f\x22\x64\xd9\xda\xfb\x35\x42\xd7\x3e\x84\xb8\x70\xe7\xa2\x88\x08\xae\xa4\xef\x6e\x6c\xa5\x39\xa7\x4c\x99\xd4\xcd\xcf\xf4\x87\xcc\x97\x39\x24\xf9\x4e\x8c\xb1\x4f\x9f\xaf\x1f\x6f\xf6\xd1\xfc\x7e\xf8\xcf\xca\x97\xcf\x5b\x69\xcc\xfb\xd7\xb2\x3c\xfc\xd5\xb6\xb6\x47\xd9\x84\xb2\x0d\x65\x71\x94\xb8\xee\x5c\x6f\xe5\xcb\xfe\x8f\xef\x29\x63\x04\x77\x81\xe8\xc5\x3d\x54\x97\x30\x61\x0d\x60\x38\x8d\xdc\x7f\x50\x66\x3c\xa9\x24\xb5\x28\x35\x5a\xfb\x4c\xcd\x8d\x59\xa2\xba\x98\x04\xc7\xb0\x7c\xd2\xc2\xac\xaf\xc7\xea\x71\x2c\x48\x4d\x6e\xef\xb4\x2c\x09\x25\x68\x40\xa8\xd7\xba\xe7\x5a\x94\x8c\x92\x34\x46\xc4\x47\xad\x66\x2d\xca\xee\x3a\xbf\x09\xc7\x1a\xe5\xad\x42\xff\x52\xcb\x92\x54\x92\x1c\x4a\xb0\x4f\xb9\x7b\xaa\x64\xc9\x26\x41\x29\x42\x65\xd4\x03\xa0\x46\x9c\xe3\xdc\xa4\x65\xa8\x0d\xca\x61\xb8\xed\xb6\x8c\xe5\x88\x39\x25\xb8\x28\x80\x12\x25\xab\x40\xab\x52\x1e\xda\xff\x84\x4b\x5a\x89\xda\x7c\x6f\x06\xf9\xac\x38\xbc\x15\x64\xcd\x37\x2f\x18\x61\xf2\x0d\x98\xf0\xe5\xd9\x31\xff\xbb\x26\x6b\xf2\x13\x00\x00\xff\xff\xa3\x67\xe0\x02\xd0\x06\x00\x00") + +func dataMackeypadJsonBytes() ([]byte, error) { + return bindataRead( + _dataMackeypadJson, + "data/MacKeypad.json", + ) +} + +func dataMackeypadJson() (*asset, error) { + bytes, err := dataMackeypadJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/MacKeypad.json", size: 1744, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dataMalenamesJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x5c\x5a\x4b\xb6\xeb\x38\x6c\x9c\xf7\x2a\xfa\xbc\x71\x56\x90\x35\x64\x07\x39\x19\x50\x22\x2d\xd1\xa6\x48\x3f\x52\xb2\x5b\x37\x27\x7b\x0f\x28\xb1\x0a\x78\x3d\xd3\xf5\x95\xf8\x01\x0a\x85\x02\xc8\xff\xfd\xf5\x5f\xb1\xed\xbf\xfe\xf3\xbf\xff\xfa\xfb\xef\x5f\x4f\xb7\x85\xf6\xeb\x3f\xae\xc7\xb2\xe6\xfb\xa9\x96\x29\xd4\xfd\x7e\xde\xe2\xbc\xba\x90\xee\x3f\xbe\x31\xa5\xe8\xb6\xfb\x0f\xef\x3e\xd1\x8f\x0f\xfa\x4b\x75\xfc\xd1\x1f\x93\x0e\xda\xc2\x7b\xbd\x9f\xf7\xb5\x6c\xae\xe1\xa5\x2a\x8b\x28\xef\x35\x54\x8c\x96\x23\xa6\x79\xbb\x63\x3c\x6d\xae\xbe\xc6\xff\x4b\x76\x69\xcc\xb0\x84\x52\x97\x70\x3f\xbf\x42\xce\x61\x1f\x33\xb4\x3d\x7c\xc2\xd8\x44\xf0\x5f\x2e\x69\xaa\xd1\x71\x6f\x3a\x8e\xcb\xb2\xa4\x7c\x62\xa0\x4f\x1c\xef\x3c\x5d\x2b\x19\x0b\xd8\xf7\x35\x7c\xc7\xbc\xae\x8e\x97\xf7\xb8\x95\x7d\x3d\x75\x8f\xf7\x53\x72\x15\x6f\x3c\xc3\xe3\x51\xc3\xf8\xe3\x51\x5d\x1e\xfb\x68\x73\xd9\x87\x69\x83\x98\x8d\xeb\x16\x4b\x64\xac\xca\x57\xcc\x58\xdd\xb9\x95\x8c\x6d\xd7\xb0\x94\xaa\x93\xae\x87\xc3\x5c\x9c\xd6\x8b\x39\xe2\xb0\xf1\xd7\xa5\x1d\xe6\x7d\xbb\x5d\x66\x1b\x6b\x78\x07\xfe\x2e\xbe\x2a\x30\x87\x2f\xc7\x92\xe0\x20\x59\x0e\xc6\x9c\xc5\x9f\x63\x69\x75\x5f\x8f\xf1\x65\x3d\xd5\xa4\x0b\x86\x7b\x96\x61\x89\xe7\xe1\x68\x4c\x4c\xeb\x92\xc2\xea\x29\x6e\xd8\x57\xbe\x73\xb4\x1d\xc6\xdf\x75\x33\x32\x2c\x7d\xf5\x0a\x91\x5e\x76\xdb\xf1\x07\x22\x03\x8c\x95\x00\xb5\xe4\xbe\x35\xe4\x79\xfc\x23\x0b\x3c\x0b\x77\x56\xcb\x18\x7e\x0a\x59\xe0\x8f\x79\xa7\x7a\xe0\xfd\x49\xdc\xe5\x81\x00\xe7\x01\xf8\x55\xbd\x2b\xae\xf5\x30\xf2\x99\xf1\x99\xac\xe5\x34\x40\x1c\x4b\x29\x07\x1c\x22\x7e\x0a\xdb\x78\xc3\x89\xe1\x61\x3f\x99\x6d\xfc\x1a\x8e\x25\x60\xb8\x6e\xf6\x82\x35\x1f\xad\x85\x34\xf6\x3c\x95\x69\x1a\xef\x7f\xe2\xbc\x97\x0a\x38\xe5\xd0\x86\x79\xdf\x6b\xb7\xcb\x7b\x58\xb4\x78\x8f\x05\x34\x40\x75\xae\x2e\x2e\xf0\x0b\xfc\xd0\x56\xf7\x1d\x8f\xb3\x60\x59\x2d\xd8\x02\x5e\xe9\x23\x63\xe0\x2b\x88\x95\x3c\x10\x49\x81\x78\x79\xc6\x8d\xfb\xcd\x7b\xc9\xb1\x30\xd8\xf1\xf2\xa4\x38\xda\x19\x8b\x89\x26\xdb\xe2\x0b\x4b\xd8\x5d\x4e\x08\xa8\x14\x04\x3f\x88\x6e\x8b\x24\xef\x52\x40\xe4\x66\xa2\xa4\x16\x9f\xf1\xe9\x7c\xd4\x1d\xa3\xe7\x52\x37\xc7\x48\xaf\x24\x00\x79\x98\x43\x1e\xb6\x5c\x92\xc4\x94\x06\x75\x20\x07\x54\x21\xc0\xa6\xff\x20\xfb\x79\x02\xbf\x4c\x63\xec\x90\x38\xb6\x4b\x0a\x9e\xd7\x89\xd5\x76\x86\x98\x31\x9a\xe0\xcf\x73\xab\xe2\xb3\x83\x31\x59\x35\x82\xfa\x28\x41\x63\x5a\x98\x82\x21\x98\xc8\x80\x98\x94\x68\x0e\xde\x33\x5c\xe4\x5b\x6e\x05\x31\xd1\xb1\xe8\x08\x34\x05\xbc\xcc\xab\x06\x17\x53\xc1\x93\x29\xf0\xd3\xb1\x85\xb9\xf0\xa5\xf9\xa0\x17\xe7\x35\xb8\x31\xaa\xf0\x69\xf1\xa5\x02\x87\x29\x3e\x1e\x85\x23\xc7\x85\x4e\x2b\x4d\x22\x00\xa6\x3c\x09\x28\x60\x65\x43\x94\x58\xd3\x86\x7f\x48\x2f\xf0\xbc\xf0\xa1\x89\xcf\xb1\xea\x54\x4e\xcf\x81\x36\x03\x2a\xb0\x68\x0d\xc8\x3b\x62\x03\x46\x9e\x04\x70\xd9\xe0\x31\x1d\x43\x3e\xc4\x02\xb8\x96\x1d\x2b\xfd\x86\x46\x5f\x7a\x86\x51\xe7\x72\x2c\x95\xb9\xcc\x1b\x1a\x7c\x07\x5f\x0b\x57\xa3\x7e\xf6\x18\xe1\xc7\xf5\x44\x0b\x50\x17\xe6\x1a\x01\x89\xc1\xf4\x21\x5f\x8e\xd1\x3f\xe2\xc2\xf2\x47\x86\x2f\x70\xc1\xe9\x83\x62\x1d\xc3\x28\xb3\x08\x2d\x64\x05\x8d\xc0\xa0\x90\x88\x15\x4a\x30\x45\x63\x6e\x99\x2a\x63\xa8\xba\x0d\x53\xef\x82\xf9\xf1\xc2\x12\x4d\x46\x50\xe2\xeb\xc8\x19\x9f\x85\x25\x6a\xba\xae\xc7\x14\x48\xd6\x01\x59\xd4\xe5\x05\x88\xb9\x89\x80\x32\xa2\xba\x87\xd3\x58\x58\x00\xa6\x2d\xa6\x5d\xa9\x17\x4a\x83\x43\xcf\x61\x8e\x09\xfe\xe0\xbe\xaf\xa4\x3c\x86\x4a\x9b\xee\x10\xc1\xbe\x38\xd1\x18\x4a\x37\x34\xb3\x50\x2b\xe9\x80\x61\xef\xbc\xea\x91\x17\xc9\x72\x66\x6e\x17\xee\x3d\xe0\x11\x09\x71\x83\xc4\x13\x3b\x0d\x58\xe3\x2d\xa4\xa2\x66\xdb\x4f\xc4\xea\x1e\x3d\x66\xb3\xa7\x97\x63\xe6\xbe\xf7\xc0\x50\x56\x79\xb3\x9f\xb2\xf0\x60\x60\x3f\x5e\x4e\x26\x86\x64\x3f\xc0\xd3\x5c\x90\xb5\x9e\x47\x02\x1f\xbc\x0e\xf8\x53\x58\xc4\x69\x2e\x39\x39\xf5\x7a\x2c\x2b\xe6\x1e\xd1\xea\x4d\x12\x15\xce\x5a\x56\x0c\xd1\x91\x8c\xf5\x3f\x42\x8a\xff\x90\x05\x36\x2c\x48\xf2\xac\x62\x41\xad\x4a\xa0\x80\x82\x9f\x2e\x6e\x4c\xac\x0d\xc1\x72\x93\x31\xa3\xd7\x04\x85\xa8\xdb\xf1\x7a\xfc\xd0\xb8\x3d\xc9\x61\xe2\x16\x35\xa7\x4c\x27\x5d\xde\x6d\x81\xf7\x63\x73\x6e\x56\x9a\xa3\x09\xba\x68\x21\x99\x8a\xa5\xe1\xd5\x4f\xac\x0b\xfc\xaa\x9a\xa0\x09\xab\x38\x8f\x58\x7c\x45\x28\xe2\x16\xe4\x6d\x44\x22\x25\xf0\x8b\x31\xd7\x85\x94\x7a\xab\x32\xbc\x82\xc0\x9a\x21\xdc\x5f\xd2\x34\x2f\x9a\x2f\xfe\x3e\x98\x92\x4c\xb2\x68\xbb\x7c\x64\x32\x8f\x46\xbc\xfc\x7c\x54\x5a\x30\x3c\x7b\xa4\x14\xd8\x0b\x06\xca\x4a\x10\xc7\x4e\xcd\xff\x0d\xd9\x5b\x6e\x0d\x5b\x74\x2b\xdc\xea\x8c\x41\x91\x47\xbc\x41\x62\x61\x16\xdf\x6b\xf8\xc0\x3c\xe9\x80\x5e\x90\x62\x83\x3c\x23\x3a\xb2\x1a\x91\x4b\x4b\x41\x6f\xac\x87\xf2\xd0\xc5\x27\x85\xc4\x77\x20\x08\x4e\x15\x16\xa4\x9e\xf4\x28\xb9\x8d\x77\x4b\x4d\x0a\xd6\x8a\x44\xd4\x45\x1c\xfd\x7e\x2b\xb4\xf1\xca\xdb\x4d\x98\x26\x09\x7b\xe7\x1f\x8c\xb3\x81\xa8\x04\x26\x13\xd4\xf6\x94\x9c\x6e\xac\x3a\x7a\xb5\x58\x0d\xf0\x52\xe9\x2c\x74\xe4\x56\x4b\xcf\xf0\x44\xac\xce\x30\x1a\xaa\xb1\xd0\x98\x6a\x05\xe3\x46\x4f\x6d\x2e\xcd\x25\x61\x9c\xc3\x17\x4a\x6c\xaf\x94\xfe\x32\xf2\x46\xde\x19\x33\xbd\x6b\xdf\x2c\x53\xb3\x3e\xd6\x79\x8d\x86\xea\xc7\xbe\xbf\x63\x92\x5e\x9c\x80\x9c\xb3\x99\x6f\x71\xa6\x2e\x28\xa6\xb8\xba\x4b\x09\x8c\xde\x69\xe2\x8d\x84\x1f\x14\x2e\x37\x06\x0a\x42\x00\x60\x10\xf9\x8f\x22\xec\xf2\xc2\xf8\x3d\x98\xc4\x24\xfb\xc7\xe6\x96\x43\x22\x57\xf2\x2b\x86\x71\x46\x72\x4f\x0a\xa7\x5c\x8c\xf0\x2c\x02\x92\xb1\x59\x65\x89\xe0\xb7\x03\x89\xe1\x8a\xef\x5d\x05\xd1\x15\x5c\x58\xd2\x97\xf1\xd1\x15\xc3\x02\x58\x9a\x1c\xef\xb5\x6e\x6d\x67\xfa\x98\xfc\x5b\x8b\x14\xa6\x9f\x90\x40\x8e\xad\x32\x1d\x3e\xfb\x00\x11\x8c\x20\xfa\xab\x72\x1f\x5f\x9b\x94\x53\xd0\x04\xd6\x22\x1d\x1e\xbb\x54\x1e\x8b\x91\x25\xd2\xf5\x0f\x04\xea\xb7\x14\x61\x81\x91\x57\x5e\xff\x2a\xf5\x93\xac\xd8\xb8\xbf\xc1\xb6\xa2\xf0\x3f\x88\x88\x28\x99\x48\x7b\x00\x3b\x1c\x1f\xd3\x1f\xba\x25\x82\xeb\xc4\x89\x5a\xe0\x49\xf6\x34\x9c\x16\xdb\xc6\x6d\x17\x59\x77\x42\x1c\x6b\x95\x1d\x54\xf9\xfb\xf0\xd5\xdc\x40\x83\xa8\x62\xef\x65\x37\x38\x63\x19\xeb\x88\x4b\x76\x33\x98\x58\xf4\x68\x18\x29\x67\xd7\x76\x87\x78\x2c\xa9\x06\xd7\x88\xbd\x1a\x03\xd1\xe6\x5c\x02\x47\x58\x28\x2a\x49\xeb\x7e\x9c\xa4\x63\x70\x85\xbc\x82\x19\xd4\x67\x16\xbb\xa2\xbb\x22\xd8\x78\x2e\x99\x72\x25\x17\x10\xed\x22\xbf\x21\x60\xd7\xa8\x52\x44\xcc\x4f\xda\x4d\x8e\x9c\x74\x2b\x1a\x3a\x00\xba\xfc\x1d\xea\x4c\x8d\xfb\xcf\x6e\xf5\x91\x11\xf7\xa1\x26\xdd\x2a\x45\xfb\x06\x04\x5c\xb9\x08\x70\x97\x5f\xc1\x4e\x51\xdd\xd3\xa8\xd7\x44\x88\x6b\xcd\xd7\x57\x9b\x94\x34\x58\x69\x14\xd5\x09\xbb\x96\xa2\xdd\xce\x5a\xf5\x4b\x0e\xd2\x02\x94\x75\x35\x7e\x72\x13\x3c\x32\xb8\x62\x38\x4e\x52\x15\xdd\x23\x96\x7a\xc2\x9c\x33\x25\xf9\xf5\x3e\x20\xe2\x8e\x89\x7c\x15\xb6\x8d\x82\x65\xeb\x35\x3e\x60\x61\x2b\xd6\xa7\x69\x7d\x08\x59\xb0\x07\xd4\xe7\x25\x52\x55\x35\x95\x7d\x27\x56\x3c\xfc\x29\x33\x76\xf1\x5c\xb8\x53\xf4\x5e\x42\xd3\xcc\x89\x08\x5a\x8f\xcd\x84\x96\xac\xd1\x2c\xe6\x6a\x4f\x39\xaa\xc1\x03\x36\xfd\xc4\x5e\x25\x53\x19\xca\x2a\x77\x72\xb5\xf2\x86\x14\x7f\xcc\xea\x82\xf7\xc8\x02\xc3\x41\xb3\x08\x4b\xb2\x83\xe4\x83\x58\xa7\x12\x7a\x41\x53\x91\x89\xa0\x5a\x58\xba\xbe\x63\x47\x0d\x1d\x81\xbd\x9e\x0c\x17\x11\xbd\x24\x3a\x29\x7b\xa6\xa8\x8d\x43\xad\x74\xa5\x88\x65\xab\x43\x60\x98\xc8\x6e\x4b\x2d\x1f\x2c\x2d\x68\x0e\x9b\x53\x27\x56\x6e\xd1\x9f\xaa\x75\xd7\x43\x4b\xb5\x4d\xdb\x8e\x41\x8b\x97\xde\xc9\x00\x13\x5e\x6d\x0c\x88\x86\xab\xc9\x03\x8e\x60\xed\x2e\xdf\x45\xf8\x45\x8c\x81\x92\xba\xd0\xf2\xa2\x0d\xb8\x43\x91\x18\xd8\xe0\x4c\x29\x2e\x92\x2e\xb3\xb0\x74\x8b\xa9\x32\x9f\x12\xd9\xc4\xd3\x47\x5b\x5e\x9a\xb4\xf6\xb3\x19\xd9\x6a\xd4\xf2\x44\x3d\x28\x95\x8d\x78\x90\x81\x03\x43\xfa\xc0\x4e\x64\xb7\x44\xa0\x88\x76\xbf\x0f\x82\xe0\x02\x0a\xde\x6f\x06\xe7\x49\xc2\x6b\x67\xbc\xd2\x18\x77\x0f\x94\xd5\x86\xa4\xb1\x08\xaa\x2b\x6d\x46\xf7\xb1\x27\xc1\x89\x21\xac\x65\x4f\x2b\xa9\x30\x89\xe5\x52\x2d\x69\x92\x63\x72\x51\x67\x3a\x46\x2d\x77\xd8\x17\xaf\xc5\x0c\xac\x37\x29\xb0\x2b\x4a\x8e\x90\x7a\x1a\x54\xb4\xd9\x22\x5e\x11\xbe\x95\x48\xa6\xeb\x74\x80\x61\x1e\xd1\x07\x76\x4c\x9c\xf7\x01\x1f\x5c\x1d\x13\xbe\x3f\xe3\x25\x07\xf0\x57\xf7\xd6\x8e\xbd\x44\x82\xea\xae\x8d\x80\xed\x92\x83\x2a\xbd\x77\xaa\x49\x8d\x00\x92\x68\xf7\xa6\x8d\xfb\x43\xf5\x46\x0e\xd4\x2d\xca\xae\x02\x5d\xe4\xe8\xab\xd7\x93\x14\xa4\xb4\x1f\x7b\xa7\x6e\x32\x61\xb1\x2c\x0c\x48\x36\x13\xa5\x6e\x62\x21\xb0\x60\xdb\x52\x8f\x61\x04\xed\xbc\x48\x7d\x42\x8a\x35\x5a\x71\xb3\x05\x96\x90\x05\x34\xe6\x22\xa9\xd3\x25\x6d\xab\x68\xf7\x4c\xe4\x4a\xc4\x48\x8b\xca\xe8\xfe\xa3\xa1\xc5\xde\x60\x56\xc5\xcf\xad\xc9\x30\xd8\x44\x2e\xa6\xdb\xa2\xd0\xd2\x24\x6d\xe2\xfd\xee\xce\x00\xcb\xab\x28\x73\x9c\xac\x94\x5c\x98\x81\x26\xd7\x40\xf9\x3d\xfd\xa8\xcc\xe9\x27\x09\xe0\x61\x06\x5d\x47\x27\x32\xb1\x66\x82\x26\xd1\x60\x9a\x04\x8f\xbb\x73\x38\x26\x3e\xd2\xd9\x88\x40\x11\x69\xd1\x56\xc1\x52\x70\x31\xb5\x7a\x55\xb8\x8b\x63\xb8\x08\x5f\xd3\x5a\x52\x72\x01\x54\x4e\x79\xc3\x47\x3e\x39\x92\x96\x30\xe8\xc6\xe4\x33\xa3\x87\x58\x4c\x3d\xd8\xfb\xb1\x6c\x88\x1e\x19\x62\xab\x35\xd4\xd4\xfe\xd0\x2e\x69\x73\x59\x85\x86\x68\xc1\x49\xcf\x2e\x36\x96\x73\x57\xf5\x85\x83\x8f\x22\x0c\x03\x4b\xee\xe1\xe1\xb4\x53\x8a\x4d\x92\xe0\x24\x26\x35\x92\xa7\xe0\x8e\xc1\x87\x26\x23\x2d\x8e\x9d\xb3\xd8\x22\x2b\xe0\xbd\x1e\x46\xa8\xa7\xed\x5f\x55\x16\x79\x29\xd2\xab\x68\xeb\x8e\xb1\x94\xf9\xb6\xde\x05\x4c\xec\xfa\xf4\x33\xb6\xd3\xb2\x40\xcc\x54\xa0\x35\x71\xfa\xa0\x5c\xf5\x32\x8d\xef\xae\x90\xa9\x5f\x64\x0a\x15\xb8\x1f\xe6\x9a\xb9\x5b\x88\x6b\xcf\x1f\x95\xef\xaa\xcd\xc3\xc6\xb0\x7e\xbb\xf6\xfb\xd0\xee\x7b\x91\xea\x73\x73\xa6\x61\xec\xb2\x36\xff\x23\x68\x33\x99\x83\x16\xcf\xce\xc6\x75\xfe\x12\xf4\xfc\x05\xcc\x73\x49\x14\xb2\xa0\x8b\x50\x99\x87\xba\x7e\x31\x95\xd1\x64\x92\xa1\xe4\x2e\xb6\x03\x3a\x62\x09\xce\xde\x46\x25\x80\x9f\x6e\x96\x5c\x09\xe9\x21\x59\x0d\x58\x2c\xed\x60\xf7\xe4\xab\x11\xdc\x33\x22\xa7\xee\x7d\x0d\xed\x2b\x9e\xbd\xc0\xe3\x8e\x59\x59\xee\xbd\x16\xd2\x83\x33\x1e\xe4\x88\xa5\xc5\xde\x9a\x95\x59\xb5\x66\xf2\x74\x99\xa5\x3e\x62\x99\x51\x8c\xe6\x5d\x0f\xc8\x95\x9e\x89\x6d\xda\xd3\x9e\x70\x53\x56\xee\xe4\x3f\x86\x8f\x9d\x67\x72\x04\x86\x2b\x14\xd9\x7c\x56\xa6\x9b\xb3\x46\xed\x6b\x66\x73\xc0\xc5\x9e\xa0\xf6\x01\x64\xac\x5d\x95\xf0\x46\x59\xe2\x8e\x5b\x75\x68\x53\x73\x5e\x89\x64\xff\x25\x0f\xdf\x2d\x0f\xd6\x93\xd0\xa9\xdb\x69\x0e\x94\xb3\xe3\xa9\xc2\x6e\x52\x8d\x29\xe2\x7e\x34\x8b\x89\x25\x09\xb5\x1f\x57\xff\xe4\x71\xd3\x67\xd0\xba\xc3\x3d\x8b\x09\xd2\xc8\x81\xaa\x69\x39\x6b\xab\xd7\x4d\xfe\x60\xb7\x98\x39\x30\x1d\xb3\xe2\xbd\x85\x73\x2b\xe8\xe3\x5c\xc7\xbf\xec\x5d\xf6\xd3\x3e\x78\xf4\x8e\x18\x86\x61\xe7\x13\xd5\x6c\x35\x1f\x54\x64\x7d\xf0\x40\x26\xaf\x3e\x66\xa6\xf5\x9d\x87\x4f\xe1\x87\x7d\x9e\xa4\xfa\x72\x52\x8d\x72\x22\x04\x2f\x2b\x8e\x8f\x1c\x0b\x34\xa9\x7b\x18\xba\xbf\x79\x1a\x97\xf4\xdc\xee\x25\x98\x0e\x1b\xad\x0c\x62\x9b\x8a\xc9\xe2\xda\xcd\x93\x84\xac\xdd\x73\x38\x81\x50\x15\x46\x79\x17\x2e\x73\x74\x74\xa9\x43\x5a\x78\xe0\xd3\xc2\xda\xca\x1e\xe8\x1b\x61\x55\x43\x34\x25\x4f\xb7\x14\x45\x8e\x6a\xd4\xaf\xe9\x4b\xf5\xc8\x20\x86\x24\x25\x1d\x0a\x17\xcd\xe0\x13\x95\xf4\xf3\x20\x10\xd9\xa9\x15\x22\x6d\x3c\x00\x5a\xc9\x79\x39\xf2\x5c\x42\xca\x1e\x3d\xdc\xdf\xbf\x14\xa6\x89\x24\x27\xf6\x93\xe8\x23\xf5\xd6\xf0\x38\xd8\xdb\xf5\x64\xf6\xd2\x3e\x66\x73\x58\x48\x3f\x54\xe2\xe1\xc4\x7d\xa2\x09\xd1\x19\xd9\x16\x8e\x9f\xa2\xe7\x96\xec\xca\xde\x0a\x18\xd9\xd1\x89\x13\x78\x04\xd6\x8f\xba\x50\x80\x3e\x64\x65\x3f\xb0\x76\x0b\xe4\xb5\xcd\xd2\x9f\x64\xe0\x05\x0b\x62\x99\x34\x6e\x79\x80\x79\xaf\x86\x29\x9a\x17\xe9\xdc\xb4\xb1\xae\x58\xe9\xe4\xaf\xad\x28\x3d\xa9\xa1\x5e\xe9\x68\xd3\xa2\xe5\x1b\x11\x95\x93\x4d\x76\xa2\x7a\xd1\x9f\x52\x45\xed\x2e\x0e\xd2\xe6\xc5\xe1\x09\x8f\xc3\x33\x23\x2c\x7c\xe5\x3a\x34\xd2\xd3\x81\x30\x1b\x2e\x60\x07\x31\x2b\xb3\xe7\xe8\xe1\xfd\x1d\x0f\xef\x52\x1f\x91\x05\x4b\xf1\x0c\xa5\x90\xed\x8d\x99\x43\x14\x1c\xfc\x53\xd8\x2f\xd1\x0e\xd8\x4c\x11\xf3\xa2\x23\x6f\x52\x05\x4f\xbf\xf4\xea\xcb\x2a\x72\x82\x53\x4e\x87\xf6\x19\xc7\x22\xea\x87\xc1\xef\xd8\xbb\xef\x67\xf2\x20\xa6\xfb\x6c\x91\x2e\x29\x49\xe1\x1b\x27\x25\x8e\xc4\xe0\x52\xfe\xc9\xe3\x1b\x71\x92\x22\x95\xac\xb1\x17\x55\xd6\xda\x05\xbe\x3a\xda\x5c\xaf\x9e\x58\x5e\x94\x48\x4b\x9b\x73\x37\xaf\xdb\xdb\xa0\x06\x7b\x62\x58\x4d\xb0\xf3\xd4\xb0\x4c\x68\x71\xe8\x25\x1c\x26\xcc\x7a\xbc\xb5\x59\x56\x92\x96\xf4\x2f\x03\xa6\x5e\xbe\x2a\xa4\x23\x23\x99\xa7\x65\x5f\x0d\xcb\x71\x38\x42\x2c\x7b\x5c\x09\x79\xe1\xd6\x84\xb0\x09\xea\xba\x53\x38\x14\x4b\xee\x37\x0b\xd8\x7a\x5c\xb9\xed\xaf\xbd\x54\x62\x45\xae\x76\xab\xb7\x22\x14\x06\x9f\xbc\x48\x3a\xb9\xcc\xab\x46\x06\x65\xd6\x55\xbf\x9a\xfa\x3f\x12\xf8\x8f\xab\x03\x3e\xeb\x25\x0d\x73\xec\xbc\x97\x29\x6a\xde\x85\x93\x57\x27\x6a\x9c\x61\x73\xb4\xf0\x7e\xb3\xf8\xb7\xe7\xff\x22\xf6\x89\xd3\xbe\x69\x9e\xc3\x9f\xba\xae\x57\x90\x88\x40\xa7\xa1\x9f\x94\x54\x60\x2a\x68\x5d\xa6\x76\x16\xb5\x24\x72\x90\x13\xac\x81\x6d\xf8\xba\xb3\x90\xea\xd7\xc7\x78\x79\xe2\xe0\x09\xb9\xa1\x15\x51\x73\xe6\x8e\x04\x92\xce\xae\x9d\x7a\x3d\x45\xba\xaa\x52\x0c\x16\x85\x2b\x49\xd7\x8f\xde\x86\xd0\xfe\x0f\xc5\x98\xff\xe3\x44\xb1\x6b\x11\x84\xc1\x75\x03\x02\x08\x96\xea\x31\x1b\x31\xff\x4f\x44\x86\x6c\x85\x4d\xcd\x14\xe2\xa2\x77\x9b\xfe\xe8\x07\x4f\xdc\x6e\x75\x4d\x05\x80\x14\xe7\xbb\x36\x50\x14\xbe\x24\xc6\x7e\x8d\x8a\x94\x20\x91\x0b\xe7\xfe\x66\x0e\x0c\xe2\xd1\x29\x6a\x29\x08\x7e\x17\x9b\xf0\xd4\xc4\x1b\xc9\x79\x1f\x1d\x8c\xb5\x88\x37\xd9\xb5\x2a\x27\x43\xf0\xd4\x4a\x2a\xfc\x84\x17\x85\x94\x10\x4e\xb3\x30\x54\xa2\x0e\x89\x57\x4c\x46\xd1\x88\x9d\x57\xe6\xcf\x1c\x4c\x63\x3f\x78\xc5\xb4\x0f\xf6\x4e\x93\x53\x49\x2f\x3f\xb3\x7b\x3a\xee\x0d\x38\xaa\xfd\xea\x4d\xc5\x4a\x9a\xbb\x32\xc6\xfd\x48\x02\xed\x47\x31\xba\xa3\xfb\xba\x1e\x9f\x4d\x45\x7a\xe5\x41\x52\xa7\xdb\xa6\xca\x4b\x83\x7b\x64\x6c\xac\x9a\x12\x1f\xa6\xdb\x28\x86\x92\xa8\xd5\xd6\xa0\x6b\x1b\x4f\x0e\x49\xad\x5a\x7f\xbe\x48\x06\x6c\x64\x69\x75\x28\xc9\x0b\xab\xed\xd7\x89\xc0\x65\x22\x20\x78\x3f\x6e\xa5\xd0\x7d\xf2\x1a\xc2\xb8\x1b\x88\x70\x93\x8d\x31\x88\x4b\x33\xf4\x27\xbf\xb6\x6f\x61\x1d\x71\x9f\x68\xf3\x1c\xa3\xf0\xc4\xfc\x36\x39\xdb\x54\x6c\x75\x4d\x21\x8b\xfb\xe6\x9d\xcc\xc6\x14\x01\xf4\xc5\x56\x79\x95\x68\xb9\x54\xf9\x30\x58\xcf\xee\xc8\xd5\x0d\xe2\xb7\xd2\x2c\x3f\xbc\x87\xb8\x15\xaf\xc7\xb0\xd7\xad\xa5\x60\x6e\x2d\x65\x06\xc5\xd3\xa1\x0a\x73\x67\xd2\x0a\xd3\xa9\x7a\x7c\xc8\xde\x6c\xb7\x24\xd8\xc3\xe3\xeb\xe6\x2c\x30\xb9\xc8\x34\x06\xa2\x5f\xed\xf8\x25\xdc\xef\xe8\x0b\xd4\x0b\xa6\xbc\x3f\x99\xf5\x9a\xd6\xfc\xaf\x83\x34\x49\x41\xb1\xe8\xad\x99\x34\xe3\x52\xd4\xab\x98\xd3\xd1\xf6\x0e\x2b\x39\x53\xef\x20\xf4\x3d\x8d\x67\x36\x7e\x57\xb1\xb7\x63\x7c\xa8\xb0\xa3\x2e\xed\x07\xc0\x43\x8d\x57\x7d\x62\x8f\x34\x18\xf1\x7d\x8b\x96\xc4\x33\x24\xd1\xe2\x94\x2a\xd7\x3e\x1e\xe6\x0e\xaa\xe6\x5d\x29\x75\x8a\xa9\x58\x02\xbb\xe6\x29\x98\x9b\x05\x2f\xbd\xbd\xf8\x0c\xff\xbe\xa0\x05\x9a\x37\xb7\x98\xe7\x3f\x6f\x2c\x24\x6d\x0b\x98\x8c\x2a\x30\x4e\x7a\x01\x71\x19\x79\x5e\x84\x00\x55\xf4\x53\x64\x0a\x8d\xb1\xe8\x1a\xae\x63\x3c\x49\x66\xe0\x1f\x53\xfb\xb7\xc8\x4b\x62\xf1\xc1\x45\x3a\x2c\xf2\xbe\x51\x0d\x3f\x5c\xd7\x0e\x7f\x78\xf9\x80\x97\x90\x2f\x24\x8d\x61\x4e\xd3\x8b\xea\x77\x26\x60\xc3\x88\x00\x24\x29\xf6\xb6\x03\xaf\xf2\xfd\x79\x53\xa0\x1f\x22\xb6\xf2\xeb\xaf\xff\xf9\xbf\xbf\xfe\x3f\x00\x00\xff\xff\x45\xf8\xc0\x95\x0f\x2e\x00\x00") + +func dataMalenamesJsonBytes() ([]byte, error) { + return bindataRead( + _dataMalenamesJson, + "data/MaleNames.json", + ) +} + +func dataMalenamesJson() (*asset, error) { + bytes, err := dataMalenamesJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/MaleNames.json", size: 11791, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dataPasswordsJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x4c\xfd\xeb\x72\xf3\x3a\xd0\x2c\x8c\xdd\x0b\x7f\x24\x55\x7b\xbf\x3b\x65\xc9\xe7\xe4\x16\x72\x07\xf9\x91\x02\x49\x88\x84\x44\x12\x7c\x78\xd0\xe9\xbb\xf9\x6f\xa6\xbb\x21\x2f\xfb\x59\x65\x2d\xd9\x92\x48\x60\x30\xc7\x9e\x9e\xff\xab\xfa\xff\xa6\x75\xab\xfe\xdf\xff\xbf\x6a\x0e\xeb\x7a\xcb\x4b\x5b\xfd\x4f\x75\x38\xbe\x7f\x7c\x7e\xbd\x1e\x7c\xff\xe8\xa1\xfd\xf8\x77\x8b\xcb\xf6\x28\xbf\xb2\x9f\xed\x12\xba\x3c\xd9\x83\x79\x5f\x57\xff\x45\x1d\xd6\x58\x87\x61\xb0\x87\xa7\x9c\x37\x3d\x1c\xe2\x36\xc6\xe4\x7f\x37\xe6\xe9\x12\xfd\x0f\xbf\x7e\xfd\xdb\x1e\x84\xba\xb1\x77\xf3\x5f\xed\xeb\x16\xa6\xce\x1e\xad\x7d\x68\xf3\xcd\x9f\x0a\xeb\x16\x17\xff\x3c\x7c\xd9\x83\xe3\xdb\xdb\x9b\xfd\x38\xdb\xa5\x06\x7f\xbf\x75\x9f\xe3\x32\xe2\x61\x1f\x96\x21\x3e\xfe\xae\xdb\x2f\x61\x6f\x2e\x63\xf4\xdf\xed\x13\xdf\xc8\x9f\x79\xe4\xdd\x1e\x6d\x8b\x7d\xde\x94\xfd\x4d\x17\xfb\x58\xfc\xb6\xde\xf5\x79\x5b\xea\xf8\xcc\x9a\x9b\xe6\xf5\x42\xdc\xdf\xc6\x4f\xdb\xa2\x2d\xdc\xff\x60\xdd\xec\xc7\x25\x0d\x03\xfe\xac\xcf\x0d\xef\xaf\xf1\xcb\x49\xfe\xd9\x43\xbe\x46\x5c\xe9\xb4\xf6\x69\xf2\x87\xf6\x9a\x3e\x0f\x51\xab\xe0\xef\x12\xe7\x19\x2f\x0f\xf6\x69\x78\xc3\xb2\xf6\xfe\xdb\xaf\xcf\x8f\xf7\xe3\x01\xcb\xd1\x75\x78\x4b\x5b\xa8\xe5\x16\x16\xff\xc3\x35\x0d\x57\xbc\xb4\xb5\xa5\x0e\xfe\xcc\x23\xd8\x12\x47\xbd\x09\x97\xf6\x0b\x5f\x7e\x79\x71\x18\xb2\xfd\xcc\xb8\x65\xbf\x9f\xb4\x45\xac\xd0\x69\x89\xb1\xcd\xa3\x5f\x79\x1e\xe7\x9d\xcb\xb0\xc6\xbb\xdf\xcb\x66\xcb\xd7\xe2\x89\x2e\x69\xa5\xfa\x30\x8e\xfc\x93\x5d\x0f\x9a\xbc\x5c\xe3\xb6\x45\xad\x15\x6f\xc7\xd6\x13\xdb\xae\xdd\xb3\xbf\x1c\xf8\xff\x47\xff\xf6\x37\xcc\xc3\x89\x2f\xef\xed\x9a\xfd\xc5\xf3\x92\x26\x2d\x82\x3d\x37\xac\x31\xf8\xcd\xa5\x60\x92\xe3\xd2\xf9\xf0\x3b\xb8\xe1\xca\xbb\x36\x43\x5a\x62\xb3\xc4\x0d\xcb\xda\x9e\xba\xde\x9f\x99\xc3\x72\xc1\x26\xe4\x5b\x9d\xf1\x20\x8c\x61\xc9\x58\xc2\x6d\x49\x77\xbf\xc6\x30\x34\x90\xdc\xe4\xfb\x43\x91\xe8\xf6\x64\x0b\x0b\x69\x5e\x66\xec\xcf\xda\x98\x10\xe3\xfa\xe6\x3e\xc7\x09\xaf\x0c\xf8\xa2\x90\x44\xec\xc1\x9c\x97\xd5\xae\xd5\xdf\x3e\x69\xfb\xc7\x60\xbb\x92\x20\x32\xf6\x16\x17\xec\xda\x14\xd6\x86\x6f\x1f\xc3\xb4\xfb\x15\x1f\xde\xfd\x9b\xc7\x02\x2f\xeb\xf3\x32\xf9\xcf\xd5\xae\x77\xda\xfa\x00\x09\x9b\xb6\x84\xed\x34\xd9\x8c\x03\x3f\x71\x9d\x72\x9e\x71\xde\x72\xe6\xf2\xdf\xfa\xb0\x45\x4a\x42\x6a\x22\x65\x74\x1d\x33\xaf\xa6\xb3\xdf\xdd\xc2\x03\x52\x72\xc9\x5b\x78\x2d\x8d\xbf\x57\x0c\xdd\x10\xb9\xdc\x7e\xf5\x13\x96\x9b\xc2\x3e\x04\xfc\x7c\xde\x9b\x6b\xed\xcf\xdb\x56\x2d\x61\x49\x2e\xf0\x53\xea\xfa\x8d\xa7\xae\xb5\xad\x8f\x12\x9c\xf0\x0f\x0f\x4e\xa7\x18\x79\x75\xf6\x8f\x62\xd6\xf4\x38\x60\xc3\xc0\x5d\xbb\xe3\xcb\x2f\x3c\xda\x46\x40\x04\xe7\x21\x3c\x70\x03\x53\xd3\x1c\xbe\xdf\x5c\x60\x6e\xe9\x19\xa0\x94\x7c\x23\x6a\xbf\x81\xf3\x3e\xa5\x8c\xbb\xf4\x13\x3d\x61\xe3\x5d\x14\x74\xc5\x26\xd7\x2d\x44\x36\x4e\x53\x5a\x71\x0f\xf9\x76\xce\x35\x8e\xee\x64\xdf\x5c\x6c\x1d\xf3\x75\x4e\x94\xeb\x21\x5c\xb8\xb0\x4b\xa8\xed\x5a\x7d\x55\xa4\x30\x6c\x75\x9b\xd8\x62\x7d\x4e\x51\xa7\xe0\x61\xbb\xd3\x4b\x2c\x6b\x9c\xa7\x3a\xaf\x1b\xa4\x09\x32\x81\xfd\x5f\x78\xd6\x7d\x51\x4d\x47\xbe\xb4\xcc\x8a\xed\x98\xec\xb4\x9e\x70\x7f\xfa\x18\xbb\x85\x2d\x6d\xb8\xe0\xb0\x50\x16\x96\xe0\x17\x27\xf9\x9a\xf0\x9b\x96\xd2\xec\xf7\x84\x15\x33\x41\x9f\x20\xe8\xbe\x02\xa1\x6d\xa9\x78\xa2\xee\x6e\xb0\x13\x83\x8b\x1a\x53\x5b\xb6\xab\x1e\x76\x9c\xd0\xe4\xba\xc8\xf7\xe1\x0d\x5f\xd8\xc8\x69\x0a\x38\x3d\x65\x1b\x0e\x87\x97\xda\x35\x45\x60\xff\xfc\xa2\x62\xbb\xe6\x3b\x74\xc2\xfd\x70\x78\xff\xd1\xb1\xe3\x1d\x0f\x75\xc6\x21\x73\x91\xed\xf1\x16\x94\x1c\xd7\x2a\xa6\xad\xe2\x14\xdc\x18\xfc\x0b\xcf\xdb\x7a\xc7\x3e\xe8\xaf\xbe\xf9\xe5\xbb\x1b\x56\x2a\x42\x5b\x98\x89\x1a\x27\x0f\x2d\x64\xb2\xde\x37\xfb\xf3\xe0\xc2\x70\x4d\x17\x5e\x7c\xba\xd9\x27\xf9\xc9\xf5\xa5\x1d\xd6\x97\xf6\xe0\x89\x8f\x0b\xee\xbe\x4b\x0b\x7e\x35\x86\x36\xad\x78\xa6\xc7\xa1\xe6\x91\x0a\xcb\xb6\x44\x1c\xd3\x30\x6f\x81\x36\xca\x56\x12\x32\x6a\x57\x33\x72\x17\xfd\xc3\xb9\x4f\x39\x77\xe5\xba\xfc\xae\x17\xd7\xf7\x1b\xd6\x43\x87\x6e\x48\x76\x0a\x67\x48\xfd\xc9\xf6\x89\xc6\xc3\x0e\x08\xcf\xe6\xb8\x9f\x4e\xf8\x90\x6d\x5f\x36\xaa\x98\x3c\xf7\x50\x0f\xbe\xb4\x76\x5f\x7e\x59\x5b\x7e\xf0\x94\xae\xc9\x4f\x1c\xd7\x43\x12\xd6\x25\xbb\x67\xdc\x6a\x68\x24\xb4\x53\xbc\x3d\xf2\xc2\x9b\xd0\xfa\xd5\x7b\x5d\x07\xec\xe1\xf1\xf8\xfe\x5e\xd1\x0a\xe1\x8f\xc7\x6c\xb6\x90\x37\x6a\x47\x69\x8b\xbe\xa0\xed\x92\x78\x79\xa6\x70\xe7\xb1\xa8\x70\xae\xf1\x5c\xd4\xd7\xe0\xa6\x13\xcb\x73\xb7\x33\xeb\x3b\xf9\xf3\xf5\xfd\xf9\xfe\xe6\x26\xaa\x8e\x81\xc6\xc0\x5e\xb5\x51\xe1\x64\x7c\xda\xe7\xe1\xd3\x85\xeb\x88\x2f\xff\x8b\x3e\x95\x5d\xf4\x8f\x30\x45\x81\x75\xee\xf6\x40\xeb\xb9\x71\xe5\x75\x16\xba\x68\xeb\x9f\xca\xd5\xbf\xb4\x06\xf4\xc6\x4b\x66\x1a\x3b\xd5\x6d\xe0\x72\x2f\x09\x8f\x7e\xf4\x85\x0d\x32\x87\x64\x6f\x71\x92\x37\x33\x91\xa9\xf1\xfb\xcd\xcd\x06\x25\xb2\x2d\x79\xaf\xb9\x0d\x7b\x31\xbd\xeb\xb6\x9b\x5a\xc0\x2e\x8c\x4d\xf0\xbb\x31\x53\xbb\x50\xe9\x98\xe6\xf6\xf3\xe5\x12\x37\xcf\xd4\x9a\x7e\x94\xaa\xe2\x1a\xed\x09\x0b\xd4\xe1\x53\xec\x63\x71\x22\xdb\x3c\xd8\x16\x4f\x54\x2f\x69\xaa\x61\xbe\xba\x5d\x02\xfe\xfb\xf3\x6d\x06\xbe\x82\x05\xe6\xdf\x87\x21\xde\xa9\xbb\x16\xb3\x22\xd0\xcc\x19\xda\xed\x78\x80\xcd\x94\xe9\xb4\x27\x43\x93\x07\xbf\xdf\x7b\xb8\x26\x3a\x01\xfc\xa8\x8a\xfe\x09\x37\xb0\x36\x35\xf0\xf6\xf6\x8d\x15\x18\x6b\xfc\xd9\x35\xe7\x16\x12\xaa\x25\x34\x73\xc3\x93\x11\xe6\x4c\x07\xe1\x94\xa0\xd2\xb7\xa2\x4b\x6c\x83\xaf\xb8\xa6\x6b\x7e\x04\x9e\x00\xd7\x4a\xd0\x6b\xfb\xda\xeb\xca\xea\x48\xb3\x3f\xbf\xac\xe7\x32\x27\xff\x1b\x13\xec\x19\xf6\x6a\x7d\xb4\xd2\x6e\xb1\xa5\x6f\x32\xeb\x8c\xf8\x27\x50\x29\xd3\x06\x9f\x4d\xbc\xe9\x5c\x9d\x86\x07\x45\xd7\xcd\x89\xff\x3c\xbe\xfb\xb7\xab\x17\x7c\xfd\x7d\x12\x6c\x57\x96\x93\x34\xc4\x2e\xc2\x65\xc8\xfb\x0f\xae\x8e\x8e\x51\x05\xbb\xf6\xc4\x47\x2d\x65\x13\xea\xb4\xb4\x49\xfe\x90\x36\xf8\x13\x5f\x10\x83\xd9\x36\xab\xa2\xa2\x93\xb2\xeb\xfd\x62\x27\xa8\x22\x39\x6e\x53\x1a\xc3\x20\x49\xc7\xfb\x74\xd4\xd5\x1f\xf6\x55\x41\x2f\x5d\x03\x9c\xa3\x2e\xb7\x4f\xf3\x16\x03\x54\xc5\x29\xf6\x34\xb1\xb3\xa9\xdf\x0d\xee\xd7\xc2\xbd\x0e\x7b\xb7\xc3\xc3\xb4\xbd\x19\xe9\xcb\x64\x7f\x7f\x33\x92\xb6\xaf\xfb\x88\x15\xba\xe0\x92\x4d\xcd\x35\x19\x17\x75\x09\x5f\x37\x8a\x86\xfc\xc9\x66\x1f\xcd\xd5\xe4\x89\x5c\x4e\x29\x0e\x2d\x74\x89\x5c\xa8\xc6\x34\x81\x7f\xc2\x00\x67\x84\x1e\x39\xfc\x51\x3b\xc4\x5b\x7c\xb9\xd7\x55\xf1\xb7\xb1\xe6\x70\x17\x60\x13\x4c\x59\xc0\x24\xbb\xa6\x35\x23\x57\xc9\x62\x50\x94\x23\x04\xf5\x9d\x8e\xab\x2d\xe9\x15\x66\xca\xcc\xbf\x6b\x80\xd7\x55\xaf\x15\x7d\x1e\x88\xc4\xba\x2f\xf4\x05\xcd\x72\xaf\xd0\xa5\xbf\xf8\xc2\x22\x98\xbe\xc4\x1e\xa4\xa5\xf6\xbf\xf7\x0b\x19\x22\x56\x4d\x5a\xc5\x7f\xd9\x6c\x94\x01\xd3\xf4\x2d\x7c\x61\x9c\xca\x8a\x8e\x96\xbf\xe4\x3e\x9b\x8e\x90\xf4\x9a\x2a\xa0\x81\x5e\x92\xbc\xd4\x36\x36\xe5\x84\xdc\xa8\xde\xd7\x5b\x2c\xda\x5d\xfb\x92\xa7\x81\x26\xc1\x3d\x0e\x69\x32\xbb\x97\x7c\x19\x1e\xfe\x16\x8d\x3b\x7d\x78\xc9\x12\x1a\x29\xd0\x48\x4f\x44\x76\xd6\x9c\x38\xaa\x82\xd8\x9a\x52\xef\xfc\x61\xbb\x44\x3b\x80\x15\xdc\xc7\x3e\x75\x8c\x66\xa2\x6b\x69\x6a\x13\x6e\x37\xf4\x04\xd7\xb3\x2d\x51\x94\x39\xb3\xa6\xc3\xa1\x64\x52\x67\xce\xab\x4b\xc8\x3b\xbe\xfc\x5a\xcc\xb6\xd1\x26\x99\x63\x6b\x82\x5e\x02\x0b\x8b\xb8\xfc\xd6\x66\x73\xf8\xb9\x29\x27\x73\x86\xb3\xb6\xdd\x9f\x99\xd3\x38\x63\x41\xb0\xd7\xfe\xd3\xad\x0f\x03\xb8\x29\x2d\x57\xba\x51\xd7\x60\x7f\x05\x2d\x21\x8d\xec\xfe\x1b\x85\x7e\xde\xc7\xf9\x82\x3f\x37\x47\xf5\xa6\x20\xd0\x75\x09\x8f\xfc\x5a\xe2\x83\xd1\x14\x1d\x44\xd7\x0e\xff\x26\x75\x6a\x3b\x1a\x10\x4a\x36\x71\xd8\xa0\x47\x4d\x7a\x96\x85\x5e\xfc\xba\xe2\x94\xbe\xb4\xfb\x3a\xe9\xfc\xd9\x51\x8f\x6b\xa2\x38\x99\x52\x6f\xb9\xc0\x34\x26\xae\x4f\xcd\xe3\xa2\x8b\x3a\xb8\x5a\x70\x89\x2e\x9a\x0d\x91\xef\x1b\x9c\x4c\x3b\xb4\xd2\xb4\x16\x49\x5d\x63\x07\x11\x5a\x87\x34\x5f\x26\x9c\x21\xad\x6b\x6b\x17\xeb\x2a\xff\xf0\xef\x78\x7b\xc7\xf2\x34\xf6\x37\x08\x5e\xf8\xd4\x07\x54\xf1\x52\x22\x23\xf3\x37\x37\x79\x9e\xfb\x8a\x3b\x52\x00\x61\x1b\x64\x52\x38\xd1\x1d\x37\xc1\xb4\xa8\x17\x22\x64\xef\x9f\x10\x33\x22\x5c\x3b\x40\x69\x64\xca\xe5\xc9\x2d\x1c\x1d\x7f\xfb\x55\x73\xc1\x15\x36\x99\xfb\x66\x1b\xdb\xc6\x53\x45\xeb\xcf\xe5\xec\xc3\x2d\x24\x17\xa3\xd3\x60\xdb\xac\x10\x63\xc5\xaf\x2c\xaa\x1b\xb9\x78\x52\x74\x1e\xc3\x33\xd2\x68\x2d\x7e\x92\xbc\x30\xa8\x3a\xc3\xb9\xb6\x8b\xe0\xef\xdd\xb2\xc1\x01\xb6\x63\xda\x52\xc4\x26\x53\x58\xfd\xc6\x0f\x98\x60\x84\x5d\xc7\xe2\x09\xc5\x9e\xa6\x88\xf8\xff\x08\x76\x0e\xdc\x75\x44\x05\x6e\xdd\xe1\x75\x48\xbc\x57\x93\x3f\xc8\x9d\xf9\x1e\xbd\x5c\x8b\x8f\x0f\x69\x52\xf3\x82\x69\x16\x5a\x58\x38\x7f\x43\xfa\x83\xfe\xdc\x50\xe2\x05\xfb\x13\x5d\x97\x7b\xd8\x13\x16\xd6\x84\xcf\xf4\x81\x3f\xe7\x9f\x57\xff\x39\x14\x7e\xac\xcd\x21\xe0\x33\x83\xef\x2e\x8d\x42\x70\x53\x84\x94\xc8\x9b\x7f\x43\x81\x98\xb7\xc8\x60\x45\x09\x93\x83\x16\x0e\x37\x64\xf1\x92\xf9\x1b\x90\x04\x13\xc3\x31\xa4\x01\x07\xcd\xb4\x03\xf5\xa4\x59\x80\x1d\xd6\xc2\xe4\xeb\x12\x78\x33\x32\xa6\x61\x71\xf7\x14\x31\x64\x58\x1e\xe7\x30\xe9\xfe\x67\x2c\x98\xdd\xd5\x86\x1b\x6d\x63\xc6\xd1\xeb\x28\x36\x16\xc0\x6c\x32\xd5\x7e\x4a\x32\xed\x5b\x93\xf7\x8e\x8b\x76\x7c\xb3\x7f\x65\xd3\xfd\xfa\x2d\x0e\x18\x43\x55\x82\x8b\x0a\x3e\xc6\x13\x97\x59\x7b\xb8\x10\x25\x0d\xc8\xed\xec\xf8\xdf\x76\xc9\x37\x53\xc7\xb3\xf6\x69\x40\x86\xc5\x7c\xf8\x23\x9d\x78\x13\x0a\x6c\xaa\x9d\xc4\x97\x3b\x9a\x8a\x6f\x64\x36\x75\x8d\xfe\xe6\x8b\x44\xd5\xfd\xb9\xe8\xca\xec\x66\x9b\xb7\xa6\x96\x9e\xd7\x73\xbf\x24\x2d\x29\xf5\x77\x5f\x8e\xce\x10\x5a\x4a\x5c\x30\xbf\x26\x48\x75\x60\xfd\x0f\x1f\xdf\xf6\x0f\xca\x6a\xa1\x61\x5d\xa3\x8b\xf3\xc9\xdf\xe9\x6c\x1e\x1c\x4f\xb7\x29\x81\x05\xda\xd3\x4d\xd2\xbe\x52\xb7\xbb\x1f\x40\x4f\x23\x31\x7c\x6a\x77\x73\xf4\x78\x09\x0b\x3d\xaf\x50\x3f\x3c\x6e\xa8\xe0\x79\xb7\xb6\x02\x5c\xec\x25\x31\xe9\xe3\x51\x9b\x42\x49\x1e\xc7\x39\x14\xbf\xa1\x5e\xf6\x6d\xc7\x9f\x8f\xb6\x34\x2e\xde\x66\x00\x5c\x01\x73\x6b\x99\xa2\xf2\x80\x00\xd6\xdd\x0f\xbb\x5f\x1e\xf2\x21\x30\x9d\x26\x1a\x3d\xfe\xf4\x9e\xc6\xfd\x6f\x39\xb1\xfb\x5a\x9e\xd9\xf6\x79\xc4\xa3\xa6\x77\x25\x8c\x87\x2e\x06\x14\x79\xbb\xe0\xc4\xf8\x3f\x9f\x4a\x06\x6e\x36\x03\xcd\x40\xfa\x61\x7a\x8f\x69\x9e\x1a\xb7\x10\xa7\x33\x74\x36\xdc\xfb\x03\x77\x94\x0e\x14\x63\x58\xdc\x4a\x6c\xf6\xa5\xd8\x19\x1e\xe2\xd0\x8e\xb8\x25\x73\x26\x5a\x5b\x3c\x04\x24\x76\x6c\xa1\x3c\xa6\x46\x39\xa2\x85\xf1\x27\xf2\x41\xad\x14\x94\x52\x89\xd4\x55\x08\xe2\xcc\x13\xe0\x85\x9b\xd1\xf5\xac\xc9\xa4\xed\x52\x6e\xcd\xb4\xf2\x82\x57\xaf\xff\xf6\x84\x63\x70\xf6\xb4\x52\xc3\x53\x56\xd7\xb8\x42\x73\xcc\x97\xe1\x8c\xa5\xf4\x88\x7d\x5f\xe8\x78\xdb\x35\xfa\x79\x91\x17\xb1\x78\x02\xc6\x57\xc3\xdc\x05\x7e\xe2\x68\xa6\x7f\xa1\xa2\xab\xf1\x85\xb7\x32\x3f\x8a\x69\x8b\x29\xf0\xba\x4d\xdf\x0d\x0a\xa0\xcd\xeb\x68\xcc\xea\xc2\x82\x9a\xdf\x54\x82\xc8\x4e\x32\x68\xfe\x3d\xa3\x78\x17\x0c\x65\xd8\x3a\x7e\xd6\x33\x8f\x35\xb3\x77\xb7\x34\x8e\xf4\x0d\xda\x1d\x2e\x1c\x83\x87\x03\x05\x2f\x16\x9d\x3e\x04\xb8\xaf\xa6\x16\xe4\x32\xe7\x2c\x9b\x35\x96\x98\x0c\x2a\xe8\x44\xbb\x67\xce\x9c\x1c\x7e\xb3\x29\x97\xc3\x8f\x3b\x82\xc5\x4c\x9a\x7b\xb1\xf3\x77\x1e\x17\x22\xb3\xd2\x33\x69\xe3\x86\x73\xc1\xa2\xf8\x72\x9b\x4f\x0f\x47\x2a\xbc\x92\x5c\xa6\x54\x68\x85\x87\x54\x4b\x9f\x9b\x58\x3c\x33\xd4\x8f\x6f\x62\x85\xf8\x53\x2f\x84\x9f\xcf\x83\x67\xf6\x69\xe3\x01\x77\x11\xa4\x2d\xb2\x18\x00\xd6\x2c\x0c\xca\x18\xc1\xf7\x82\x3a\x08\x54\x14\xc7\x0f\xff\x86\x2c\x8c\x35\x82\xaf\xb6\xa4\x62\x9b\xc1\xf5\x03\x03\x2b\x64\x91\x98\x1a\xc9\x8c\xb5\x43\xd3\x30\x7d\x3d\xe7\xb9\x61\xbe\xc4\x5c\x46\x7a\x49\xb5\xb9\xf9\x34\x3c\x3b\xb4\xa0\x45\x43\x0c\x88\x2c\xcc\x34\xc7\x9d\x77\xc7\xa8\xdd\xaf\x01\xee\x18\x3e\xd2\x83\xf6\x4d\x07\xcd\x1e\x0f\x34\x4a\xeb\xa3\xe9\x21\x1d\x66\x09\xe8\x73\xcc\x66\xe1\x53\x80\xaf\x92\xa7\x09\x91\xa2\x59\x11\xe8\x29\xf3\x32\xa9\xb0\xcc\x15\xd7\xa6\xdb\x41\xd5\xd6\x32\xff\x34\x32\xcd\x67\x52\x95\x19\xf5\x66\x65\x69\xda\x78\x4d\x03\xd5\xa6\x3c\x2d\x58\xe3\x0a\x9e\x43\x9b\x98\x4e\x59\xfb\xd0\x75\xd0\x29\x4b\xe6\x83\x7f\x0c\xa8\x2e\x66\xfa\xd7\x00\xcd\x7a\xc9\xa6\x11\x18\x66\xcc\x90\xf1\xe2\x48\xda\x8d\x68\xbf\x7a\x13\x29\x25\x12\x1f\xf4\x76\x4c\x85\xd7\xd2\x23\x13\x23\x0d\x77\x5d\xab\x57\x7a\xce\x6f\xe0\x1f\xbe\x2a\xf8\xe5\xe6\xfe\x31\x57\x62\x9a\x82\x02\x1b\xae\xb6\xd1\x0c\x23\x3a\xe5\x07\x4c\x36\xb1\x1a\x52\x1b\x38\x94\x8c\xa4\x3c\x37\x7a\x0a\x0d\x3d\x7b\x33\xe3\x35\xbc\x68\xd3\x16\x8c\x8e\xb7\x65\xa7\x09\x71\xcf\x7c\x56\xd0\x14\x97\x2b\xfd\x7b\x53\x10\xf2\xc5\x15\x8c\x30\x5f\x66\x22\x04\x63\x63\xe1\xee\x83\x4b\x75\xa5\x26\x31\xaf\x54\x69\x7c\xcf\xd7\x71\x25\x12\xdf\x7f\x09\x33\x73\x03\x07\xc6\x42\x08\xa3\x97\xc0\xd7\x97\x6c\xf0\x69\x09\x4c\x33\xf9\xd9\x57\x72\xc9\x34\x36\xb6\xd4\x4e\x82\x3f\xf3\xfd\xf3\xcb\x32\x8a\x7b\x33\x16\x5d\xd3\x3d\x31\x25\xc2\x54\xab\x29\x3d\x08\x5e\x1f\xfa\xa0\x3c\xaf\xc5\xbb\x90\x60\x73\xfd\x5b\x26\xa9\xcd\x5e\x5d\xa9\xe8\x56\x4f\x6c\x21\xdb\xed\x1e\xff\x35\xc8\x1e\x61\x5b\x8e\x9f\xfe\x5d\x54\x0d\x34\x13\x8b\x15\xab\xbd\x44\x7e\xd4\x1c\x1f\xd8\xc1\xb0\x6d\x38\x2e\x9b\xb9\xc4\xab\x8e\x12\x23\x9c\xb0\x2f\x34\x5b\xe6\xb5\x64\x85\x40\xcc\x3e\x28\x9d\xe7\x0f\xcf\x61\xa6\x44\x98\xb0\xe2\xb3\xe1\xfa\x70\x23\x71\x98\xe1\x05\x79\xb2\x46\x99\xca\x92\xf0\x77\x85\x0d\x53\x6b\xeb\xd5\x47\xe6\xea\x16\xf7\x37\x83\xb6\xb4\x63\xe9\xc7\x83\x04\x95\x56\x46\x8f\xf9\x98\xca\x33\xdb\x8a\xa8\xfa\xbc\x73\x35\x3c\x4e\x0a\x71\xf0\x0f\x9b\x8a\x7a\x38\x7c\xfe\x7e\x7f\xba\x7b\x0e\x57\xe1\x00\x91\x31\xe5\x20\x4b\x74\xbb\x70\x01\xcc\xae\x04\x9a\xfc\xdc\x96\xec\xbd\x9d\x11\xaf\x3c\xe1\x23\x1b\x95\x68\xe6\xc7\x12\x46\x64\x81\x2c\x0e\x88\xc8\xc5\x5d\x42\xf1\xe2\x4d\x0f\x63\x31\x93\xfc\x88\xc6\xd3\x75\xfe\x4c\x9a\x4e\x25\x1e\x9b\xe3\xbc\x22\x73\xc5\xd2\x17\x75\x3b\x6e\xb1\x77\xfb\x44\xff\xc8\x0c\x56\xc4\x92\xf9\xea\x60\xa7\xf2\x6e\x6a\x1f\xe5\x0d\x73\xbb\x26\x9a\xbf\x61\xb0\xb0\x0a\x96\xa9\xfc\x15\x42\x29\xed\x33\x6f\xc1\x14\x45\x2a\x1e\xc1\xd4\xd1\x45\x6d\x42\x5c\x59\x6f\x30\x85\x23\x67\xce\x1c\x7b\xb9\x5d\x75\xbe\x0d\x14\xa9\xdb\x5e\xea\x6e\xfb\xb4\xb2\x92\x32\x04\x3b\x39\xc8\x70\x97\xd2\xd8\xd3\x4b\x54\xdc\xcb\x19\x5f\x15\x8a\x71\x70\x7f\x65\xcb\xfc\xbd\x99\xbb\xb1\xd3\x60\x7a\x30\x50\x17\x31\xe6\x33\xd9\xcc\x4c\x88\x87\x95\x46\x59\x15\x32\xd4\x85\xf0\x55\x31\xa9\xdf\x31\xe1\xe9\xe9\xf2\x41\xe9\xa4\xc0\xea\xca\xe6\xd1\x78\xd1\x70\x66\x2f\x91\x68\xc9\x75\x38\xc5\x0d\x22\x6c\x2f\x59\xe9\x4d\x31\x3d\xb4\x9a\x12\x56\x92\x15\x5f\xbe\xbe\xe6\x8c\xed\x33\x85\xba\xcd\xf8\x24\x88\xf0\x5a\x54\x0c\x2b\x28\xe6\x41\x21\x67\xbf\x9a\x2a\x80\x4f\x11\xcc\xfc\x79\xa2\xd9\xae\x80\xb1\xe5\x35\x45\x6c\x93\x39\x8a\x6d\x86\x8b\xd5\x4a\xfd\xb6\x69\xa8\xa9\x95\x66\x0f\x21\x71\xa8\xce\x52\xae\x26\xca\xca\x17\x9e\x86\x62\x29\x4f\x25\x69\xda\x46\x93\xd8\xc4\xa3\x64\xd2\x3a\x49\x9b\xee\x4c\x1d\xa2\x98\x53\xc9\x2b\x43\x8a\x2e\x6e\x7c\xab\xfb\x29\x0d\x2a\x10\x95\xf2\xdc\x9c\x9e\x4f\xc6\x17\x35\xb5\x54\x0c\xc3\x46\xb7\x72\xda\x37\xbf\x83\x6e\x37\x07\x05\x7e\xa0\xb9\x3f\xd8\x2a\x53\xd5\x5d\x4f\xcb\x69\x02\x63\x92\x83\xcc\xdd\x38\xd5\xd7\xe6\xee\x39\xb6\x5b\x92\x17\xa7\x42\xad\x6f\x9c\x69\x27\x5b\x21\xbf\x6b\xcf\x00\x2a\x0b\x18\xcc\xb9\x67\x45\xc7\x23\x29\x8a\xc1\xe1\x76\x8c\xef\x8b\x2b\xf2\xde\x42\x5e\xfa\xcc\x97\xa9\xa8\xdc\xd8\x4e\x11\x1a\xcb\x9d\x43\x39\x88\x5d\x7a\x8e\xd8\x02\x3b\x2c\x08\x3a\x58\x6b\x46\xfa\xc3\xed\xa2\x12\xc5\x4b\xb2\x28\x16\xa5\x25\xb3\x99\x9e\xc6\xab\xa0\xa7\x37\xa6\xec\xcc\x97\xbb\x21\x24\x42\x81\x80\x25\x48\x66\x81\x43\x25\xa5\x0d\x8f\x79\x9c\x03\x33\x72\xb6\xea\x38\x46\x76\xfd\x1d\x3c\x1c\x64\x85\x0f\x7e\x41\xa8\x08\xcd\xa8\x7e\x99\x60\x2d\x88\x5c\xd7\x51\x29\x13\xb3\x6b\x4f\x85\x9e\xbb\xdd\x96\x1c\x10\xf9\x8c\x6e\xb5\x75\x57\x76\xbd\xd2\x57\x90\xb6\x0a\x41\xf0\xbe\xb1\xca\x6a\x9a\x97\x7e\xc1\xab\xfa\xfb\x06\x99\x69\x3d\x5f\xd8\xf0\xec\x50\x9e\x4d\xea\xa9\x74\x91\x63\xa6\x2a\xa0\x8f\xe3\x55\x02\x46\x4c\x2b\x8d\xb7\x97\x2e\x2a\x2a\x65\x56\x39\x3d\xa9\xa0\x98\xd1\xd6\x89\x65\x1d\x86\x0c\x2a\x37\x3e\x4b\xf5\x28\x2a\x0b\x66\x97\x6a\xa1\x15\x04\xd3\xd3\x14\x2c\xab\xbd\x4a\xf3\xc7\x57\x31\xd7\xdf\xb5\xc4\x1b\x4b\x6c\x52\xa6\xec\xef\xb2\x42\xc1\x3d\x5a\xa8\x52\x2f\xea\xe0\xdd\x16\xfa\x91\x73\x1e\x14\x78\x6d\x49\x81\xb9\x49\x0e\xf5\x85\xbf\xa1\x2a\xc4\xe5\xc4\xac\x97\x47\x49\xc2\x41\x26\x56\x9e\x3e\x5a\x58\x1d\x61\x8b\xb9\xec\x4f\xe8\x08\xe5\x92\x87\x6b\x18\xe9\x5a\xf0\x1d\x37\x94\x47\x90\x7b\xc4\x3a\x86\x85\xce\xf9\x2d\x6e\x05\xcb\xc0\x45\x91\x80\x52\x50\x4e\xd9\xd4\x0d\x77\xcf\x5c\x09\x7f\xb3\x31\x2f\x73\x1f\x71\xa3\x1e\x06\xd0\x69\xf9\xf0\x6f\xad\xef\xb6\xa3\xc6\x31\xdb\x63\xa4\x3b\x3d\x14\xc6\x8e\xf9\xb9\xff\xff\xdb\xd9\xa6\x3a\x76\x25\xc2\x77\xde\xcd\x76\x42\xc8\xd7\xd4\xb1\x5a\xb5\x6d\xb8\xb4\xe3\x9b\x7f\x57\x25\x54\xf7\x37\xb3\xc3\xf2\x03\xb1\xb5\x13\x09\x49\xbb\x06\x6a\xe0\x2e\x5b\x88\x99\xe8\x5f\x4d\xac\xeb\x87\xba\xf3\x0a\x85\xef\x08\xbe\x20\x4f\x0a\xd5\x78\x3e\x29\xd0\x8c\x50\xe3\x7d\x56\x60\x74\x4d\x4b\x07\xbd\xff\x2c\xeb\x7f\x33\x0d\x74\x61\x12\xd8\xf5\x1f\x7d\x3c\xf3\x7c\xd7\xfd\x95\xf0\xba\x30\xc3\x63\x0e\x4c\x94\x41\x34\xcd\xbc\x2f\xc8\x68\xfe\xfe\xbe\xf2\xba\x48\x93\x33\xa9\x6f\x7b\x12\x37\x25\x9b\xa3\xfd\xab\x0a\xfc\xc3\xdf\xa7\x44\x23\xe6\xaf\x7a\xc9\xe3\xe5\x6e\x6c\xf0\x1f\xec\xaf\x3c\x13\x9c\xb0\x07\xd8\x6b\x3f\x40\x72\x83\x7f\x95\x37\xc5\xd5\xdc\xf7\x80\x4d\xf3\xe0\xda\x5f\xf9\xfd\x57\x7a\xac\x5d\xf9\xc3\x47\xe8\xed\xd8\x16\x07\xdd\x13\x16\x84\x6a\x98\xe3\x30\x97\xb4\x50\xc9\x2d\xed\x1d\x37\xdc\x62\xe7\xc4\xd4\xb5\xf9\xc1\xb6\xf0\x8d\xca\xfd\xb8\xf1\x9b\x99\xb9\x52\xbf\x51\xf6\xb6\xed\x5e\xd1\x0f\x51\x33\xfb\x22\xb8\xc9\x14\x58\x28\x37\x9b\xea\xaf\x90\x57\xe4\x15\xc9\x44\x1c\xcb\xaa\x24\xcb\x9c\x3a\x3a\x6e\x10\xac\xf2\xae\x4c\x25\x79\xd6\x84\xbe\x80\x45\x7b\x8f\xbf\x7b\x63\x10\x36\xf2\x75\x0a\xc0\x7b\xee\x82\x83\x75\xa8\x45\xa8\x9b\xed\x06\x59\x11\xf2\xa3\x2a\x93\x65\x3e\x3c\x4b\xb1\xf6\xba\xa2\x65\xcc\x1f\x2b\x29\x0c\x48\x65\x52\x59\x7a\xa1\x43\xe5\x36\x5e\x77\xe6\x96\x94\x05\x7c\xf3\xf7\x99\x21\xb1\x38\x30\x00\x60\x12\xbd\x7e\xe3\x9f\x8f\x7a\x71\x85\x54\xb2\xce\xa5\x69\x75\x66\x24\xaf\x09\xb9\x36\x05\x1f\x48\x01\xfd\x22\xaf\xe8\x25\x46\x95\x19\x1b\x8f\x38\x58\x09\xeb\xcc\xf9\xa7\xfc\x17\xa9\xcd\xa9\x51\x21\x68\x72\x91\x85\x8e\xb4\x3b\xba\x06\x54\x4e\x6f\x7d\x5a\x15\x2d\x2a\x6d\xef\x1a\x8e\xd9\x5a\x06\x5a\x12\x75\x77\xb4\x87\xcc\x4c\xd2\x62\xf1\x0a\x21\x1d\x76\x8e\x19\xfd\x08\x7d\x43\x53\x33\xd2\x11\xeb\x7d\x31\x07\xfa\x3c\x29\x9e\x90\xe6\x36\x95\x72\x62\x5a\x03\x2e\x69\xc5\xf8\x0d\xe7\x64\x18\xcb\x81\x72\x60\x4b\xd4\xb2\x54\x88\x5f\xc6\x52\x1e\x82\x2e\x4d\x0c\x88\x96\x56\xa9\x92\x25\x8f\x23\xb4\x92\xd2\x95\x76\x84\xdb\xc0\x68\x66\xf4\xe0\xf9\x2a\x77\x9a\x7e\xfe\x38\xe2\x8c\x7a\x0e\x44\x5b\xc4\x3a\x69\x58\xcc\x6e\xe3\x12\x16\x93\x1f\xd6\x15\xb9\x26\x66\x08\xa6\x8b\x72\xaf\xb4\x20\x9e\xdb\xb6\xeb\x1f\x2a\x66\x65\x58\x3b\x2e\xa6\x21\x2d\x14\x9c\x03\x0f\xfb\x39\x7a\xfc\x0e\xd7\xdc\x7c\xf4\x52\x45\x01\xb0\xa7\xd4\x47\xfc\xa2\xd7\x5b\xf1\x62\xec\x7e\x19\x3b\xb8\xc5\x66\xe6\x2b\x6d\x1e\xb1\x54\x2f\xbf\xfa\x88\x1b\xf8\x0f\x6a\x0c\xb1\xdc\x90\xec\xa6\xb1\x38\x84\x22\xd1\xd7\x2e\xe5\x66\xc8\xd4\xe5\x51\xc4\x9d\x81\x9c\xe9\x29\xb3\xf8\x2d\xad\xa2\x39\x1c\x37\x84\x49\x87\x4f\xff\xae\x18\xa2\x08\x54\x63\x07\x82\x22\x26\xf7\xb9\xcb\x6d\x4b\x4d\x69\x7f\xa0\xda\xe8\x5a\x3c\x55\x64\x18\x54\xd7\xf0\x3f\x3e\x15\x88\xcd\x64\xf7\x4f\x4b\x8a\x5c\x7d\x55\x92\xfd\x70\x5c\x93\x85\x0a\xf1\x59\xde\x67\x8e\x54\x72\xb9\x94\xe4\x51\xfe\xf4\x3b\xb7\xbb\x9c\x54\x34\xc8\x9e\xe6\xc6\xb9\x76\x93\x48\xf7\x63\xc9\x67\x9d\x42\x57\x95\x48\x25\x23\x11\x2b\x13\xe1\xf8\x88\x34\x12\xb0\xa1\xc4\x58\xb3\xa4\xb1\x9c\xfb\x4c\xab\x7d\x32\x8d\x14\x8a\x07\x21\x2c\x9b\x17\x0e\xe5\x70\x8e\x28\xeb\x9e\xca\x96\xdd\x4a\x70\x87\xc2\x28\x73\xe2\x2c\xae\x75\x4b\x8c\x52\x2e\xbf\xff\x29\x65\x41\x7b\xcc\x54\x6e\xc9\x74\x99\x5f\xa4\x69\xc1\x97\x6f\x6c\x42\x0e\xa1\x6a\xe9\x2d\xd9\x3d\x8d\x35\x1d\x83\xd0\xee\x03\x7d\x12\x4f\x86\x61\xfd\xf7\x81\x49\x6d\xcf\x2e\xf7\x50\x4a\xf8\xf4\x0c\xe1\x8b\xb8\x7f\xcf\x36\xb0\xe6\x66\x0e\x1b\xc3\xcc\x56\xa5\x0e\xcf\x84\xc1\x83\xbf\x28\x2d\xfc\x6e\x66\xfc\x13\x39\x80\x81\xf0\x22\xa0\x3d\x4a\xc5\x44\x69\x72\x13\xdf\x4e\x01\x21\x4a\x6a\xfe\xde\xf8\xe2\x51\xa3\x9b\x6a\x0e\x3d\x65\xa5\xcf\x88\x6d\xbb\xec\xdf\xd8\x41\xaf\xb4\x22\x01\xe0\x29\x56\x7a\x4c\x44\x9b\x9c\x06\x1e\x4e\x25\x7d\x6d\x2b\xf7\xb0\x28\x8d\x01\x95\xb5\xc5\xa6\xc7\xbd\x0d\xc5\x8c\x0f\x61\xa0\x1f\xeb\xd9\x8c\xde\xed\xa1\x1d\x03\xe2\x92\x96\x74\x4f\xcc\x29\x0d\x70\xc1\xcc\x83\x64\x50\x59\x67\x79\x5c\x17\x99\xce\xdf\x2f\xa4\x0c\xe7\x9d\x8b\x30\xa4\x7f\x3b\x02\xe1\xba\x54\x03\x2d\x40\xa3\xaf\x69\x2a\xfa\x46\xdc\xc9\x05\x5f\x78\xf5\xb7\xa2\x3d\xe6\x90\x6b\x93\x5f\x85\xac\x1e\xc4\x2d\x14\x5a\x13\x56\xe4\xec\xa6\xc0\x2a\x61\x67\x4e\xc2\x5e\x80\x0e\x54\xf7\xb8\x96\x4b\x28\xb9\x7d\xcf\x40\x31\x31\x3f\x75\x97\x7c\xa9\x5e\x48\xce\x23\xc4\xd7\xcc\x2f\x81\x1d\xe1\xb1\xd1\xa5\xb4\x50\xdc\x14\x24\xd7\xeb\xf2\xb8\x85\xe1\xa2\xfc\xac\x4e\xad\xb9\x22\xe6\x4b\xe3\xd3\xaf\xc1\x36\x60\x88\x2c\x3c\x04\xa5\x50\x4d\x5b\x24\x66\x4c\x96\xe7\x2b\xe5\xd1\x4a\x2d\xc5\x62\xd1\x3b\xba\x96\xa6\x10\xb6\x86\xe1\x99\xc9\x64\x1a\x75\xd1\x3d\xdc\x1d\x4f\xdd\x6c\xca\x17\xa0\x1c\xb9\x6c\x4c\x7a\x36\xfc\xbd\xfd\xa0\xbf\x77\x85\x77\x3a\x3f\xa4\x7c\x4d\x43\x9c\xfd\x4e\x1e\xa6\x60\x6f\x9e\x63\x43\x31\xfe\x84\x58\xe8\x85\x0d\xdd\xe8\xe4\x9f\xf9\xd6\xa6\x61\xf7\xb5\x14\xe0\xcd\xeb\x83\xb7\xb1\xbc\xd0\xa5\xe6\x3d\x21\x00\xc8\xc2\xb8\xd9\x8d\xe0\x83\x2c\x22\x1b\xf1\xc4\xf8\xd0\x01\xaf\x93\x85\x5d\x78\xea\x11\x7a\x68\x42\xbb\x99\x95\x90\xa4\x78\xff\x20\xf8\x6c\x54\x50\x3b\xc7\x52\x6d\x9c\x53\x83\x1f\x7d\x62\xc8\xb6\x71\x79\xec\xc6\xa9\x03\x94\x52\xc4\x4e\x87\x86\x4e\x80\xa7\xd2\x2e\xc8\x81\xe0\x0b\x97\x89\xd8\xcd\x64\x00\x2e\x9d\xd9\xd0\x25\x0c\x8a\xeb\x88\x7b\x63\xcd\x87\xfe\x7e\x28\xa0\x0f\xfb\x71\x4f\x58\xca\x3b\x9f\xdc\xc2\x53\x49\xbe\x52\xf0\x31\x0f\xbc\x4f\x35\x23\x10\xf3\xb3\x58\x08\xa3\xa4\xf1\x7c\x9e\x03\xe0\x24\x2e\xbe\xbb\xdf\xc0\x63\xe7\x1b\xe4\x91\xe0\x0c\xdf\x2b\x5c\x74\xb6\x63\x89\xc2\x96\x79\x00\x8b\x47\x50\xd0\x63\x2c\xcc\xc2\x7d\x47\xa9\x57\x65\x0d\x0b\x16\x97\x70\xa2\x3b\x43\x13\xb3\x16\x41\x5b\x79\xaf\xd2\x2f\xe7\xa4\xaa\x84\x97\x11\x33\x5e\xb1\x70\x09\x4f\xd2\x1f\x71\x53\x68\xfd\xcf\x3c\x59\x3a\xd6\x76\xe4\xe0\xbf\xf2\x2f\x6e\xf8\xf2\x4b\xcf\xfe\x6d\x0f\x9e\xbd\x3e\x8a\x7f\xe0\x55\x19\xfa\xfc\xe1\x79\x5f\xfd\x2f\xff\xf1\x53\x1b\x7e\x52\xd3\xf3\x9e\x5b\xfe\xf9\xa4\x03\x91\x63\xd2\x42\xc5\xf9\xa5\x63\x23\xec\x8c\x69\x0c\x56\xf5\x2d\x34\xda\x25\x56\xd8\xf6\x7e\xef\x1c\xe2\x82\xd3\xcf\xe5\x4d\xfc\x8c\x91\xfb\x34\x16\xef\x76\x62\xf2\x9c\x05\x68\x3f\x22\x87\xfa\xd8\x00\xe0\x43\x89\x7d\x96\xe5\xba\xcb\xd4\xbb\xfb\xd9\x64\x56\x57\x1f\x82\x70\xa6\xa0\xcf\xd0\xbb\xc6\xd1\xe4\x10\xa2\x16\xf5\x31\x5d\x6a\x98\x9f\xec\x92\xeb\xce\x72\xb3\x5c\x1c\xf3\x87\x74\x68\x61\x11\xb3\xb0\x82\x9b\x02\xfc\x0b\x57\xc5\x7e\x24\xde\x00\x71\x15\x42\x9e\x8f\xf2\x78\x3a\xfe\xda\x71\xb2\x70\x5f\xbb\xa8\x32\x0f\xfe\x6e\x2e\xf7\x9b\xe8\x47\xff\xe3\xd3\x66\x56\xaf\xf8\xeb\x89\xab\x33\x69\xe5\x4b\x91\xc7\xcd\x41\x56\x2e\x90\x21\xbd\xad\x02\x51\xb5\x81\x1b\xcc\xd7\x3d\xf9\xba\x27\x45\xea\xc1\xa5\x7a\xf2\x77\x77\x7e\xd4\x93\x57\xf0\xf6\xff\xb2\x6f\x3a\x5b\x7c\xde\xb6\x2c\x51\x1a\xf9\xc3\x53\x79\x7c\x50\xa4\x14\x61\x3a\x3f\x60\xe6\x55\xcc\xfc\xf4\x41\x7b\x19\xcb\xce\x8e\xfe\x16\x8b\xe4\x55\xcb\xdb\xf0\xc7\x22\xd1\xd2\x2b\xf9\x7f\xff\x52\x91\x3b\x6a\xc3\x1d\xfe\xcc\xae\x08\xab\x14\xf1\x99\x39\xe5\x0f\x6d\x85\x67\xfb\x68\xf6\xd7\x66\x60\xec\x4e\x0b\xa6\xda\x7c\x45\x57\x6f\xcc\xd8\xc8\x27\xdf\xff\xc9\x5b\xb9\x4b\x4a\x9e\x7d\x7c\xfd\xe4\x0f\xfe\x51\x28\x27\x07\x27\x69\x64\x32\xf4\x49\x85\xfd\xe4\x25\x3e\xa5\x1b\x98\xd0\xc6\x2a\x65\x8a\x3f\x7e\xbd\xe9\x26\xf9\xfe\x97\xfd\x25\x9d\xf0\x2b\xdf\x3f\xbf\x11\xff\x22\x15\xc1\x33\x98\xf1\x83\xdb\xf5\x4f\x97\xe7\xf2\x99\xb0\x00\x5a\x07\xfc\xd5\xa4\xdf\xea\x97\xc7\xe3\x0b\x5e\xf9\xd4\xda\x3c\xf5\xab\xb5\x2f\xfb\xab\xff\x77\x40\x03\x71\x65\xe7\x82\xfe\xf8\xfa\x7a\xb5\x07\x20\x25\x9b\xa1\x84\x91\x62\x85\x2e\x54\xa4\x77\x33\x8d\x6b\xbf\xf4\xcf\x3f\xbe\xbd\x01\x87\x08\x6c\x29\x40\x19\xe6\x13\x4b\xd5\x3a\xc2\x11\xfe\x9f\xbd\x9c\x39\xd4\xe3\xc7\xd7\xcf\x81\x69\x0b\x33\xaa\xc8\x0a\x98\x39\x26\x02\x0d\xe9\x06\xd5\x50\xcd\x39\x24\x74\x83\x70\x1d\xa1\x22\x16\xc4\xa5\xaa\xdc\x9b\xaa\x43\x45\x65\x5f\x4e\x0a\xd2\x6c\xbd\xfe\x83\x39\x44\x68\xb1\xb6\xf6\xcf\x1f\xec\x35\x31\x63\x8e\x6c\x36\xad\x8f\x9e\x14\x77\x3d\x92\xc2\xe4\x89\xbb\x2a\x00\x3a\xd2\x99\x6a\x60\x70\xb1\x11\x5c\x35\x8e\x01\xb2\x75\xf0\xbb\x45\xc2\xd9\x9b\x30\x70\x8b\xdd\x92\x33\x60\x6d\xdd\x90\xf9\xf6\x87\x1f\xff\xe6\x85\xfe\x56\x52\xf7\x2c\xd5\x98\x09\x52\x75\xf6\xa1\x8e\x0b\x7b\x91\xb4\x46\x1b\x6e\x34\x3e\xf6\x57\x6c\x82\xb0\xd7\xbf\xe1\xc7\xd7\x47\xc5\xa2\x68\x85\x2c\x19\x5d\xfd\x86\xfe\x42\x6c\x23\x8b\x21\x8c\x5b\xed\x35\xd8\x95\x6f\xff\xc6\x03\x64\xe7\xdd\x6f\x71\xcf\xf7\x6c\xe1\x06\x9b\x01\xdc\x11\x87\xeb\x1d\x66\x41\xc6\xe6\x02\x6f\xbe\x06\xb9\x38\xd1\xdc\x64\x58\x15\x3b\x64\x7d\xa4\xd7\xe7\xf0\x77\x24\xba\x95\xb6\xed\x53\x4b\x3d\x86\x16\x8a\x1d\x97\xf0\xf3\x06\x99\x6f\x9f\xf0\xb6\x0f\x1f\xdf\xc7\x4f\x5f\x8f\x53\x59\xc6\x7a\xef\x4a\xab\xcd\x49\x69\xfb\x31\x0f\x54\xb5\xca\x6e\xdd\x5e\xc5\x6d\xaf\x79\x6d\xbc\xf4\xc4\x92\xeb\xc1\xfe\xe4\xdd\xff\x88\x60\x7a\x56\x79\x62\x8d\xb3\x6e\xab\x31\x6f\xfd\x92\x99\x17\x35\xb9\x50\x45\x70\xf4\x70\x8e\x81\xee\xc2\x92\xfc\x98\x5b\x06\x29\x76\xbd\x1f\x92\x50\x9e\xdf\x9b\xa2\x0d\x40\x0d\x16\xdc\xad\x29\xbd\x2d\x01\x42\xe2\x18\x4f\xac\x84\x42\xea\x39\xdf\xb8\x5a\xdb\xad\x84\xd0\x5e\xfe\x8d\x0d\x74\xb9\x5d\xcc\x4e\x9c\x22\x32\x91\x15\x4a\xc2\x02\x2a\x2a\x83\xce\xe8\x3d\x2b\x81\xdb\x67\xe6\xac\x57\x7b\xa5\xc3\x93\x2a\xe2\x9f\xa0\x34\xc6\x5a\x48\x5b\x25\x75\xd7\x50\xf3\x3d\xaf\xf9\x41\x48\x91\x4a\x80\xef\x5f\xfe\x5d\x11\xff\xee\x97\xdf\xa1\x3d\x0a\xfb\x9e\x08\x96\x54\xc5\x76\xda\x5b\xba\xa1\x0a\xa7\xd6\xc1\xd6\x8f\xad\x13\x76\xf3\x88\x22\x4e\x9e\xbf\x66\xee\xa4\x76\xa8\xbd\x5f\x79\xb8\x78\xe2\x33\x41\x56\x1c\x34\x93\xe9\xe1\x0c\x6a\x68\xf9\xfd\xf6\x05\x35\xb1\x7f\xd8\x4e\xe3\x32\x26\x39\xe4\x4d\xe3\x95\x2c\x5c\x3b\x73\x43\xde\x7f\x85\x3b\x97\xba\x86\x48\xe6\x61\x1f\x6b\x24\xf5\x2e\x16\xf9\x8c\xdc\x2d\x8f\x18\x06\xa2\xe0\x07\x33\x37\x70\x6b\xed\x68\xb8\x7c\x16\xfc\xef\x25\x28\x87\x31\xee\xaa\x1d\x6e\x7d\x44\x32\xe0\xea\xf9\xe3\x02\xa0\x45\x49\xa3\x0d\x45\x06\xb3\xd0\xbf\x4c\x29\x78\x32\xf8\x05\xfc\x67\xa5\x41\xd0\x1d\xe6\x80\xcd\x25\xe6\x41\x48\x26\xba\xfe\x8e\x3f\xe7\x8f\x47\x7c\xdf\x9f\xb8\x4f\xf3\x74\x18\x76\x03\x93\xe3\xaf\x28\x90\x70\xc4\xb4\x5e\x16\x56\x52\xd1\x6e\x72\x43\xf7\xdc\x1f\x98\xfd\xee\x18\x76\x74\xa5\x05\xd3\x45\xc2\x06\x32\xe5\xde\xe1\x0b\xeb\x76\x62\x4e\xc1\x13\x7c\xc8\x59\xf8\xe9\xc5\x5a\x99\xdf\xbd\xed\x4a\x0b\x3a\x48\x12\xf6\xc7\xbd\x02\xa4\xa5\x1d\x17\xb5\xaa\x0e\xc1\xfc\x82\xd9\xb1\x85\x30\xa4\xfb\x46\x05\x6b\xa2\x4d\xd4\x64\x9f\x37\x96\x6e\xdf\x3f\xfc\xbb\x7a\xb5\x81\x54\x7f\x58\x40\xc8\x95\x62\x5e\xaf\xf5\x0e\x44\x5e\xac\xdb\xab\x91\xee\xe3\xd3\xbf\x2b\xba\x53\xaa\x00\xe7\xac\x8c\xc7\x9a\x9b\xe2\xbe\x17\x00\x04\x6b\x35\x5e\x9b\xc2\xb1\x7c\x7f\x35\x46\xb9\x21\xe0\x3e\x9e\xd2\xb0\xf5\x7e\x61\xb9\x7f\x44\x34\xaa\x84\x93\x60\xc7\xc9\x73\x50\xc4\xec\xb3\x44\xca\xfa\xc7\x2a\xf8\xf8\xa2\x32\xcc\x9c\xb7\x80\xb8\xb3\xc7\x17\x64\x6c\xea\x98\x1c\xbf\xc5\xc8\xb2\x07\xf0\x27\x08\x2a\xbd\x80\x0b\x05\x53\x74\xca\x50\x20\x12\xf3\x4e\x30\xbb\x39\x66\xac\x02\x79\x96\x06\x9e\x08\x52\x48\x28\xb4\x79\xd2\x90\xb5\x95\xe9\x31\xf2\xb7\xed\x2b\x2f\xe0\x69\x6f\x81\x62\x72\xb8\x48\x2c\x32\xbe\x28\x37\xb4\x60\x66\xfd\x59\x34\x6f\x8a\x1d\x54\x3e\x95\xd8\xba\xb5\x51\x57\x44\x5b\x34\x66\xe3\x1d\x3f\x8b\x44\xb9\x94\x85\x16\xc2\x0a\xd7\xd2\x51\x73\xce\xe7\xac\x6b\x55\xda\x70\xf4\x90\x14\xb1\x96\xfd\xbf\x1a\x1d\x4f\xf8\xa2\xae\xb2\x05\xc8\x04\x9c\x9b\xeb\x8a\x15\xff\xcb\xdf\xbc\xba\x30\xf0\x55\xa9\x6e\x87\x9c\x94\x89\x83\xda\x2c\xc6\x87\x3e\xc9\x65\x52\xe5\x18\x53\x15\xc0\x2c\x98\xa9\x55\x23\x80\xa7\x3a\x14\x38\xd8\x19\x40\x1c\xeb\xf0\x3d\x22\xb0\x54\xb3\xf9\xd3\x20\xf4\x58\x5a\x47\x94\xc0\x27\x76\x3c\xec\x5d\x7b\xfa\xf7\x11\xe8\x19\x95\x73\x74\xfc\xf6\xef\x0a\x21\x2c\xa0\x8b\xc4\x7b\x75\x9e\x09\x1a\x1e\x52\x44\xc4\x1c\xc5\x93\x94\xa5\x57\xc9\x99\x1d\xf9\xc3\x37\x8e\x79\x4a\xbc\x2f\xd3\xfb\x14\x9f\x75\x08\x14\x09\xbb\x74\x82\x48\xb7\x95\x4d\x5f\x8e\x2a\x45\xad\x1e\x05\x7d\xec\xd2\x1b\xf2\x5f\x15\x01\xd3\x32\x38\x40\x86\x4c\xb8\x13\x93\xd1\x11\xc9\x8c\x2e\x5f\x5c\x25\x0c\xf8\x82\x5c\x84\xf5\x89\x58\x33\x5b\xec\x4d\x94\xd9\x0a\x5f\x80\xdd\x78\x78\xc6\x44\x67\xd3\x05\x09\xf9\xff\xd7\xd9\x6b\xde\x0f\x4b\x12\xad\x29\xd9\xb2\xf5\x5e\x76\x2a\x49\xab\x0a\x30\x0a\xf3\x4d\x2b\x04\x3e\x43\xa4\x85\x08\x25\x2e\xf3\xa6\x27\x15\xfb\x81\x05\xae\x98\x15\x4c\x84\x70\x2d\xa5\x5e\x88\xdc\x1f\xed\xeb\x17\xf7\x38\xd4\x03\xd1\x9b\x0b\x50\xf5\xaf\xe6\x22\x77\x47\x59\xf7\xeb\x4d\x1c\xb9\x12\xb1\xa3\x51\x31\xbb\x4e\x2b\xbd\x86\x25\xf4\xbe\x84\xa6\x40\x94\x9f\x18\xf2\x3e\xb0\x8b\x97\xc5\x0f\xb8\x96\x4c\x53\xbe\x09\xda\x65\x8a\xb4\x66\x9b\x12\x7b\x78\xfd\x0d\xce\xb1\x45\xf4\x66\x47\x34\x13\x2b\x96\x99\x7a\xf4\x22\x14\xf6\x48\xcb\x07\x24\xbc\x2a\xac\x91\xb9\x8c\x39\x5d\x82\x1d\xc8\xea\xd5\x0e\x4b\xdd\xe0\x0d\x78\xb8\x12\xc2\xd5\xa9\x70\x72\xe9\x1e\x46\xd7\x22\x0e\x83\x59\xec\x9a\xb0\x71\x57\xff\x8b\xa0\x52\xbb\xdc\x66\x34\xbb\xf8\xb5\x96\x86\x16\x4f\x08\x94\xf4\xf2\xdc\x0b\xe2\x6e\xc1\x09\x72\x9a\xee\x91\xab\x51\x75\x11\x48\x74\x2e\x50\x17\xc7\xe2\x09\x37\xb9\x04\xe6\x28\x7a\x22\x9a\xfd\x7a\x59\x3f\xaa\x00\x63\x1c\x99\x2f\xb6\xf0\x68\x64\x8f\x66\x8c\xa7\x86\x40\xaf\xe7\xf3\xaf\xb3\xa6\x57\x00\xec\xe9\x1e\xc8\xa7\x6a\x87\x0e\x0a\xca\x54\x32\xa6\xb7\x6b\xc1\x66\x9b\x0b\xd0\x15\x5d\x5e\xd4\xe3\xe2\xea\x44\xb0\x2e\x73\xf9\x4b\x0a\xcd\x93\x8b\xaa\x64\xd8\x5a\x9c\x94\xbc\xf3\xd4\x24\xde\x6f\x0c\x4f\x02\x47\xed\xa0\x13\xeb\x8d\xe2\x16\x32\xba\x2d\x74\x36\xa3\xa4\x7f\x2f\xfc\x19\x77\x8e\x67\x82\x28\x3a\xc0\xd0\xa1\x02\xdd\xc6\x60\x07\xa5\xbe\xdd\x20\xfa\x7d\xe4\x7e\xf2\xff\x2a\xf8\xa9\x3f\x9f\xc7\xea\xd5\x99\xcd\x2a\x5d\xf7\x82\x18\x48\x0b\x9b\xc7\x52\xfc\xe3\x87\xe9\xb6\x5d\x49\x5f\x13\x01\x75\x63\xc6\x50\xfa\x1a\xec\x46\xe9\xa9\xd9\xbd\xb4\x2c\x0f\xb3\x3f\x1d\xa6\x0c\xbd\xc7\x10\x7b\x40\x14\x51\xbb\xba\xc4\xc9\x7d\x41\x3c\x7a\xd4\x99\x87\x12\x9e\x35\xcd\x88\x29\x33\x3a\xa9\xe1\x89\x75\xb0\x07\x03\x74\x0f\x44\x05\x6e\xb2\xbb\x89\x75\x45\xec\x25\xd3\xe7\xa5\x5b\xdd\x71\xfa\x29\x76\x4c\xba\x74\x93\x72\xad\x16\xb5\x11\x16\xd4\x94\xfe\xba\xd1\x4e\x35\x11\x63\xee\x87\x69\xb5\xee\xd4\xc5\x1b\xd1\x91\x5b\x41\x0c\x12\x1e\xcc\xae\x59\x3f\xaa\x15\xbd\x20\x87\x49\xf0\x38\xd0\x54\xe4\xfb\x89\xda\x27\xaf\x89\x35\x99\xbc\x74\x61\x1d\x25\x05\x44\x14\xb1\x81\x1a\x09\xcd\x3d\xae\xea\x70\x58\xdc\x26\x63\x47\x4b\xc1\xd5\x53\xd4\x61\xc9\xcc\x79\x9b\xc9\x0a\x34\xf4\xe6\xc3\x40\x4f\xd8\x06\xb1\xc7\x41\x9e\x17\x65\x9f\x70\xbc\x73\x69\x58\x3f\x87\x6b\x69\x8c\x84\xa0\xe6\x56\x2a\x58\xdd\xe6\x4a\x9f\x16\x37\xe2\x34\xa8\xa7\xc5\x34\x5e\x8b\xa5\x99\xa2\x9f\x2c\xc2\xf7\x4d\xd6\xa0\x3f\x2e\x05\x76\x70\x8b\xf5\x8b\xb4\xe0\xba\x0f\x04\x22\x1e\x7e\xfd\xbb\xa2\xb1\x53\x1d\xd6\xac\x27\x0d\xe8\x29\x2c\x82\x00\x2c\x7b\x57\x0b\x62\x1d\x65\x38\x01\x45\x20\x45\x80\xb7\xc9\xe1\x08\xdb\x92\xf7\x6c\x16\x37\xcf\x29\xca\x20\x65\x0b\x0e\x59\xbc\x5c\xa4\x52\x3c\x25\xbb\xd2\x76\xba\x72\x3c\x13\x18\x98\x77\x57\x05\x74\xb7\x1c\xce\xc2\xa0\xbd\xb7\xcd\x2e\xd5\x32\xd3\x66\xb0\xbc\xf8\xaa\x4a\x2e\xae\xfd\x80\xc4\xb0\xe1\x2c\xf7\xdc\xda\x38\x5c\x89\xf8\xc3\x27\x40\x49\x78\xb0\x34\x31\x1b\xe2\x29\x7b\xbc\x93\x83\xf5\xd8\x28\xe1\x65\x79\x61\x86\xbd\xe3\x53\x47\xa4\xf1\x9e\x6d\xe1\x2b\x52\xe9\x5a\x74\x38\x28\x0b\xd5\xad\x63\x7d\x2a\x04\xec\x0c\x02\x47\x17\x66\x66\xc0\x00\x5a\x87\xfb\x91\x85\x72\x18\x77\xfb\x2b\x4a\x95\x90\x73\x2c\xf4\xf9\xee\x33\xf7\x20\x67\xf5\x92\xf4\x41\x4c\xce\x9b\xc3\x2f\xfb\xcd\x4c\x95\x93\x57\x28\xb3\x00\x47\x92\xa8\x74\xf9\x44\x27\x47\xb8\x52\x31\xed\xee\xf3\x32\x63\xb8\x32\x98\x76\x0c\xe1\x40\xe1\xf1\x18\x46\xc9\x13\x74\x90\x42\x53\x0f\x8f\xd1\x77\x81\x47\x49\x1d\x4a\x2e\x31\x40\x7c\xf6\x81\xfd\x97\x08\xdf\x36\xa0\x20\xa0\x41\xe9\x94\x45\x7c\xf1\xa2\x7b\x79\xdd\xb6\x9f\xb2\x14\x5e\xda\x52\x60\x63\xdb\x61\xf2\xca\x9c\x7f\xbc\x2e\x44\x30\x6c\x05\xb4\x6a\xfe\x83\xad\x02\x2e\xa1\x77\x48\x34\xd5\xe5\xc8\xb3\xec\x62\x21\xc8\x86\xbf\x2f\x1b\xc1\x1c\xd0\x69\x07\x8e\x10\xbd\x66\xaf\x77\x59\x77\x6e\x3e\x99\x19\x9e\x61\xa6\x55\x35\x93\x31\x64\xf2\x30\x30\x28\x19\x93\x5a\x83\xa0\x1e\xa0\x7b\x5c\x19\xf2\x54\x09\x1d\x0f\xc0\x15\x42\xae\xa5\xf4\xc4\x83\xed\x82\xd5\xe6\x50\xe0\xbd\xe8\xcf\x64\x5a\xc3\xac\x20\xdb\x96\x4c\xe0\x3c\xfb\x53\xd6\x02\xf8\x3c\xb4\x65\xaf\x65\x21\x99\xb2\x5f\xc6\x1d\x26\x29\x9b\xee\x1e\x0a\x78\x55\x96\x61\xb9\x34\xac\x3d\x02\x16\x51\x01\x6d\x3e\x35\x40\x42\x3c\x04\x03\x48\xd3\x29\xb2\xe3\x15\xe2\x2e\xf2\x09\x27\x5d\x60\x45\xfb\x84\xba\x82\x43\xa5\x10\x5a\x0d\x81\x87\x73\x96\x4e\x9a\x97\x0c\xac\x83\xc5\xa3\xbe\xc9\xfe\xc7\xe6\x9b\xb3\x74\x6e\x47\x92\xde\x94\x6d\x20\x53\x14\x0f\x7c\xd9\x03\x74\x1e\x11\x65\x69\xb7\x0c\x25\x6b\xb6\x1b\x7e\x2b\xc3\x42\x0f\x2c\xf7\x8e\x92\x57\x68\x59\xcc\x09\xe0\xfb\x09\x56\x79\x60\xae\x1f\x19\xc2\xbc\xa0\x47\xff\xb6\xa4\x52\xf5\x7f\x21\x24\x9c\xba\xa5\x40\x6a\xe6\x85\x0b\xee\xbd\x04\x0c\x6d\x28\xdd\x8e\xf2\xb3\x1f\x9f\x5f\xfe\x0d\xe9\x9c\x4e\xfb\x5f\xb5\x19\x4b\xfe\xa0\xe5\xe8\xf7\xa5\x40\xb1\xd1\xf2\x05\x99\xb9\x1f\x9f\x97\xee\xc7\x73\x7f\x4f\xa1\xa6\xcc\xd7\xdf\x98\x48\x66\xef\x26\x91\x0d\xbe\xe2\x66\x6e\x19\x1a\x00\xd9\x59\xbd\xfa\x12\x8a\xb8\xe2\x73\xfb\x87\x5d\x3c\x5f\x7a\x89\x57\x21\x6d\x7d\x83\x80\x8f\xfa\x78\xf5\x8d\xad\xee\xd3\x95\x1e\xc3\x85\x2d\xb1\x53\x27\x4c\xee\x69\x27\xac\xcb\xeb\x83\x35\xa3\xbd\x9c\x86\x52\xa0\x2f\x28\x24\xf4\xae\x03\xf6\x90\xc6\xd1\x96\x1d\x0b\x02\x64\x33\x43\xef\x41\xb8\xf9\xfb\xc8\x02\xed\x39\x2e\x82\x1c\x78\x4f\x57\x89\xfe\xfb\x58\x58\x1d\xd6\x15\x79\xa5\xa6\x64\xdf\x46\x8b\x2b\xa1\xf2\x4a\x5b\x07\x0f\x91\x5a\x2b\x04\x18\x87\xde\xa6\x33\xeb\x91\xa9\x84\x9d\x4b\xc7\xf8\xbc\x62\x24\x53\xda\xab\x4d\x66\xfd\xe3\x04\x9c\x29\x66\xeb\x51\x0a\xcd\xb2\x16\xd9\x7c\xa1\x9d\x39\xd6\x2f\x24\x6b\x23\x81\xed\xef\x5f\xc7\x0f\x24\x94\x04\xea\xc1\x96\x25\x35\xec\xd8\x05\x44\xc7\x7a\xe2\x0e\xef\x04\xc0\x0b\xfa\x56\xba\x69\x70\xfe\x14\xbb\xc6\x9b\xa2\x08\x28\xcc\xd3\xae\xca\x36\x9a\x66\x2a\x28\x7a\x0b\x83\x82\xaf\x97\xd9\x33\x05\x8c\xbb\x23\x1e\x29\x4d\x93\x6e\xfc\x66\xfb\x40\xa4\x8e\xfb\x7c\xfe\x8c\x99\xd4\xc7\x5f\x9e\xb5\x42\x1a\x88\x18\x2b\xc7\x51\x9d\x86\xac\x16\x2d\xef\xb0\xc0\x0e\xd9\xdf\xed\x38\x78\xf0\x0a\xfe\xa3\x1e\xa0\x5a\x2c\xde\xe1\x29\x14\xfd\x0b\x62\x0f\x7b\x2d\xa5\x27\xbb\x69\x52\xb2\x2a\x2b\x59\xd5\x2c\xca\xf9\xc4\xbb\xda\x65\x92\x97\x3e\x4a\xc7\x9a\xf2\x1e\x43\x40\xf0\x62\x6a\x5f\x88\x0a\xd7\xc7\x5c\x1c\xf3\xca\xbc\x29\xa4\x52\x45\x11\x6f\xe9\x96\xac\x62\x3f\x85\x44\xc1\x71\x6e\x15\xaa\xbf\x6a\xa4\x35\x0d\x4d\xd4\x67\x2c\x46\xc0\x85\xa1\xa7\xf3\xe8\x19\x13\x75\x2b\x98\x63\xca\x48\xea\xb2\x2f\x6a\x36\x50\xd2\x25\xa3\x39\x95\x65\xa7\x9b\xaa\x75\x38\x5c\x7e\x87\x17\x2f\x96\x2b\xc3\xb7\xa9\x7c\x7f\x43\x3e\x8d\xa5\x71\x46\x93\x66\x1b\x6d\x69\x89\x51\x31\xa1\xe9\x91\x6e\x06\x59\x8d\x9e\xaa\x69\xbd\xe6\x2c\x03\x1e\xdc\xb5\x64\x5b\xeb\xf4\xa4\xb5\xf3\x83\x95\x8a\x33\x40\xdc\x89\x79\x41\x2c\x76\x7b\x3f\x0c\x53\x48\x4d\x66\xc2\xa5\x15\x5d\xc5\xbe\x8e\x0d\x85\x44\x08\x90\x8b\x43\xcb\xe8\x8a\xd8\x71\xbf\x28\x80\xf3\x15\x01\x42\x2d\x35\x0f\x6a\x7e\x73\x72\x96\x91\x91\xfb\xb6\xb7\xc8\x0a\xbe\xbf\xbf\x1a\xa7\xd7\x59\x4d\x78\xe6\x51\x13\x23\xe5\x8a\xb5\x34\xa7\x9a\xad\xe9\x05\x7e\x32\x6d\x31\x6a\xd3\xc0\xd5\x82\xb8\x41\x81\x74\xbc\x37\x05\x34\xee\x72\x8d\xf4\x4a\xf2\x92\x4b\x82\xda\xb0\xcd\x56\xb6\xc3\x8e\xcd\x1d\x77\xb9\xf5\x0a\xfb\x87\x53\xa1\xd0\x0a\x0d\xff\x1a\x75\x0b\xe6\xa5\xc6\xd0\x14\xaa\x17\x77\x73\x85\x2b\xbe\x7a\x57\xda\x7f\x78\x7d\x08\xad\x09\x4f\x5c\xbd\x57\xd2\xe5\x08\x85\x7f\xe6\x77\xa5\xbf\xc2\x3b\x4c\x15\x9d\x1a\xf7\x72\x70\x4e\x08\xee\x9f\xe7\x17\xce\xdf\x4c\x57\x9b\x80\x8c\x99\x8a\x13\x6c\x21\x65\x81\xc9\x5e\x4d\x3f\x21\x42\xb9\xfd\xd5\x38\x92\x52\xee\x6b\xf2\x30\xf3\x85\x09\xe0\x26\x75\x4b\xde\x67\x7a\x01\xf1\x8a\x3f\x2b\xa9\xa3\xee\x95\xec\x6c\xf3\xde\xf5\x72\xbc\x3d\xd4\x82\xbd\x9c\x76\xb5\x2e\x0f\x2c\x81\x0c\x16\xe7\xa4\x19\x66\x7b\xb7\x43\xc5\x93\xe8\x9d\x35\x2c\x93\xe4\x41\x11\xf1\x95\xfc\x20\xb7\x54\x17\xae\x8f\x91\x78\x07\x33\x66\x9f\x90\xb9\x99\x39\xf0\x93\x19\xd2\x27\xfb\x40\xd9\xc3\x4c\xae\x1a\x78\xd1\x9e\xf4\xe3\xf5\x9b\x1a\x61\x53\x98\xe7\x71\xfc\x03\xf0\xe5\x5b\x93\x0b\x8f\x93\xe7\x82\x3b\x1c\x6c\x4f\x89\x88\xb3\x6b\x6f\x21\xce\x26\x8b\x8e\xf7\xb4\x47\x3f\x87\xd3\x7e\xb9\xf8\x9d\x7f\x7f\x1c\x18\x80\x36\x25\x62\xf3\x46\x14\x38\x14\x28\x37\x75\x92\xfe\x8d\xaa\x28\xf2\x50\xda\xfe\xb3\xa1\x19\x3b\x5d\x87\x9a\x7b\x9d\x88\x74\x6f\xbc\x95\x44\x59\xb7\x41\x71\x42\xe9\xe3\x01\x3a\xe1\xc0\xd3\xbc\xc8\x99\x43\xd6\x07\x3c\x44\x08\x87\x5e\x9d\xce\xab\x85\x95\x38\xdc\xab\x30\x86\xa5\x2c\x6d\x87\xb6\xe8\x1c\xd1\x45\x8c\x21\x7a\x30\x56\x09\xc5\xec\x1f\xf0\x42\xfa\x3a\x7d\x0f\xfd\x50\x25\x5f\x1f\x19\x4b\xec\x35\x66\x26\xb1\x7b\x6a\x39\xbb\x46\x75\x86\x21\x27\x46\xb2\xaf\x42\xc9\xd3\x79\x73\x3c\x37\x4b\xa4\x56\x70\xbe\x6a\xfb\x58\xdf\x89\x30\x17\xbe\x12\x3b\x66\x74\x05\x72\x47\x6b\xdf\x27\x19\x12\x6f\x3d\x13\xfe\xdd\xd3\x2e\xca\xf4\x1f\x7e\x7f\xd4\x92\xce\x2c\xa9\xc0\x13\xa8\x94\xbf\x6a\xe5\x82\xb4\xad\x68\x02\xf5\x07\x8e\x00\x56\x01\x73\xd8\x45\x9e\x40\xa2\x30\x44\xcc\x0e\xd0\x62\x4e\x68\x63\x11\x1a\xf0\x33\x04\x45\xe1\xc1\x9e\x32\x3b\xbf\x44\xf2\x1c\xde\x90\xd0\x0c\x43\x4d\xab\x88\x32\x1d\x8e\x4b\x74\x4e\x9f\x85\xa4\x19\xbb\x7b\x7f\x44\x0b\xfa\x77\xe5\x2a\xaf\x94\xb7\x98\xd7\x3d\xfc\xfe\xfe\x60\x23\x2f\xd4\x39\xb7\x9c\x4f\xfe\x5f\x45\xa7\xb2\x62\x9e\x1e\x2a\x3a\x31\x09\xdf\x98\xd2\x5c\xa8\x66\xfe\xd7\xff\x72\x45\x3d\x3d\xce\x74\x9e\x2d\x40\x4f\x6b\x2f\x55\x6b\xce\x2f\x33\x74\x57\xdb\x30\x3a\xb0\x2c\x7c\xb1\x43\xd6\x9b\x47\xd4\xa6\x1c\xd8\xc2\xe3\xbd\xbc\x5b\xa0\xab\x33\x09\x0c\x89\xb7\x1d\x42\x6d\x4b\xe3\xeb\x1f\x27\x66\x90\x18\x33\xd7\xc4\x4d\x8d\xe1\xd1\xa3\x45\x79\x89\xad\x4a\x33\x5d\xbe\xe6\x81\xba\x23\x8e\x34\x06\x9f\x6f\xfe\xed\x4f\x95\x43\xb7\x14\x8a\x23\x81\x4a\x59\x1d\x74\xac\x05\xf1\xce\x93\x99\x78\xdc\x66\x1b\xd7\xcb\x99\xfd\x0c\x7b\xdb\x0e\x6a\xdb\x2e\xfe\xf5\xe8\x5d\x18\xe8\xb2\xef\x05\x2b\x3e\x7b\x89\x1f\xde\xb0\x49\xc9\x91\xa7\x44\xad\x26\x75\x7a\x32\xf9\xb2\xa6\x7b\xb1\xf2\x05\x26\x66\x96\x4f\x1d\x84\xce\xbd\xb2\xaa\x15\x3c\xda\x5a\xab\x6c\x66\xae\x2f\xcd\x8b\xa7\xa1\xde\x0f\x2c\xdb\x99\x0b\x44\x6d\x77\x1a\xe4\x58\x9a\x1d\x07\x3b\x88\x19\x99\x61\xc9\x81\x25\xa4\x15\xc0\xcd\xc6\x42\xf7\x01\x49\xc9\x7a\x79\x6b\xdf\x17\x4a\xf0\x52\xe8\x98\x6e\xb1\x2d\x4e\x64\xb8\x11\x81\x82\x6c\x96\x52\xeb\x70\xa9\x27\x6f\x65\x61\x5d\x38\x33\xb9\xea\xc1\x26\x37\x5d\x05\x09\x27\x5d\x51\xca\xa8\x5e\x82\x10\xb6\x33\x23\xb3\x81\x08\xe5\xb6\x30\x27\x22\x73\x4a\x71\x34\x91\xe1\x03\xef\x06\x60\x0e\xe6\x29\x44\x96\xf2\x21\xc7\x2f\xff\xc6\x95\xa6\xa9\xa8\xb9\x6d\x61\x9a\x01\x80\x57\x62\x03\x4a\xb1\xdf\xdc\xe3\x89\xf2\xe3\x5c\x19\x2c\x66\x38\x31\x0d\xd6\xd0\xae\xa0\x65\xfb\xd4\x68\x3a\xa2\x58\x50\x14\x9e\x09\x48\x50\x4e\xe5\x45\xe9\xd7\xc6\x17\xa3\xdb\xc4\x6e\x46\x74\x47\x33\x89\x38\xc9\x69\xbb\x04\x73\x3c\x55\x7b\x54\x66\xe5\xe3\x20\x96\x0a\x19\x52\xef\xbd\xa0\x6b\x9e\xe2\x22\xd2\x17\xfb\x84\x85\x0c\x53\x76\x8a\xe9\x4c\x0e\x51\x47\xb7\xc0\xbb\x70\xa5\xde\xaf\x87\x17\x2f\xb9\xce\x42\x25\x79\x75\x8c\xa1\x42\x20\xee\x61\xf5\x5a\x92\xf8\x0b\xc1\x30\x51\x11\x3c\xb4\x21\x7e\xd8\x56\xbb\x42\xa0\x6e\xe0\x18\xd0\xf4\xef\xac\xfa\x28\x1d\x0c\x33\xb5\x13\x8b\xe0\x38\x63\x55\xd0\x4c\xe9\xfb\x36\x3c\xc3\xbf\x83\xe8\x1c\xd8\xd8\x89\xcf\x9c\x4b\xe7\xa9\xbb\x16\xf8\xa0\xd5\x62\x74\x14\x27\x91\x30\xaa\x4a\x23\x09\xd2\xc1\x63\xe1\x65\xf4\x9e\x92\x9d\x9e\xdc\x22\xad\xb7\xda\x7e\x51\x49\x06\xc7\x07\x55\x85\x7f\x12\xde\xf4\x65\x08\x3d\x4b\x9e\x03\x81\x29\xad\xf3\xc4\x25\x5d\x70\x55\x7c\x0e\x9e\x51\xd6\x31\x5f\x6d\xb8\xe3\xf8\xea\x1c\xbc\xd9\xa7\xf5\x99\xd8\xcd\x3d\xaa\x81\xfa\x69\xbe\x9a\x1a\x4c\x41\x2c\x40\x28\x69\x3a\xa9\x88\xf1\xd7\x06\x33\x90\x86\xc6\x61\x93\xb1\x68\x92\x0a\xde\xb1\xea\xfa\x8e\xf8\x47\x66\xdb\x24\x63\x0d\x84\x25\x26\xea\x5d\x17\x6e\x99\xa4\x94\xc0\xb5\x62\xcb\xea\x6e\xc5\xe3\x59\x4a\x9b\x66\xd2\x6a\xee\x9a\xa9\x18\xb3\x9e\xb0\x95\x5e\xf0\x90\xf3\x48\x64\x65\x5d\xbf\x38\x08\xfa\x30\xfc\xd2\xe8\x74\xa6\xba\x79\x3a\x95\xf2\xea\x72\x69\xc7\xf0\x42\x1b\x3d\xd2\x91\x6d\x8f\x6b\xb3\xc3\x52\xe7\x69\x78\x40\x53\x6f\xdb\x1f\xa8\xd2\xe2\x7e\x41\xc5\x6d\x9f\xb0\x3f\x83\x77\x3a\x23\xf8\xdb\x59\x8b\x3c\x9b\xe2\x0d\x37\x74\x43\x10\x43\x08\x20\x58\x89\x2f\x28\x15\xeb\xab\x95\x72\x2e\x34\x52\x76\x77\xe6\x23\x40\xb1\xbf\x00\x03\xc3\xe5\xdc\x77\x94\xf0\xc1\xd9\x9c\xa8\xe4\xed\x74\xec\x2b\xd2\xae\x7b\x52\x02\xad\x7b\x8c\x13\x6b\x2e\x8d\x09\x3b\xe9\x01\x72\x18\x14\x28\xb6\xeb\xc8\x56\xef\x81\xd8\x17\x71\x28\x22\x1f\x92\x59\x71\x33\x87\x5e\x90\xf5\xe6\xd5\x52\xd9\xc6\xf8\x54\x2d\xb9\x2f\xe8\x0f\x65\xce\xc0\x14\xc3\xdb\x7e\x64\x6f\xef\x61\xf6\xaf\x30\x54\xac\xf1\xae\xd0\x2a\xde\x95\x78\x4d\xcd\xff\x53\x79\x8a\x51\x4e\xf4\xcb\x5a\xa9\x42\xb3\xc4\xed\x79\xa1\x6b\x67\xd7\xc4\xec\xf5\x69\x49\xac\xcd\x65\x53\xaf\xc8\x49\x51\xe6\xb9\x10\x13\x58\x1a\x2b\xb7\x4a\x71\x69\xd5\x56\x1f\x0f\x1f\xf8\xc4\x3a\x0b\xe6\x78\x21\xa0\x00\xf9\xb0\x26\xef\xa4\x70\x39\x7c\xf9\x37\xa4\xec\xc7\xa5\xec\x99\xd8\x76\x0a\xef\x44\x10\xdd\x4d\x16\x31\xbc\x7a\xa8\xbd\x79\x45\x2d\xd9\x0d\x78\xc0\xb0\xf6\x79\x48\xac\x49\x89\x85\xcc\x03\x47\x95\x65\x2c\xe2\x60\xdd\xca\x3e\x18\xf6\xcd\x7c\x4c\x2e\xb8\xf9\xc4\xf6\xaf\x62\x7d\x57\x3c\xaf\x8d\x08\x8b\xec\x8f\xae\x82\xf3\xd9\x72\x85\x49\xbd\x09\x02\xdd\x7a\xf4\xa5\xa6\x3e\x57\xb4\xa4\x1a\xb3\x55\xe4\xa2\xcc\x11\x70\x85\xeb\x1a\x3b\x38\x86\xe8\x1e\x39\x68\x2b\x0e\x54\x3f\x2c\xc5\xad\xff\x76\x47\x97\xe1\x73\x3c\x6b\x04\xd9\xcd\xa5\xcf\x23\xbf\x0a\xdc\xa1\x50\x0d\x5a\x34\xa7\xd2\x8b\xc7\x1e\x0c\x42\x3d\x0f\xb3\x05\x82\x40\x03\x0a\x42\x88\x38\x51\x43\x16\x41\x27\xc1\x29\xba\x47\x2f\x91\xe0\x8a\xb7\xc7\xa0\xe2\xdf\xc3\x7c\x3d\x1a\xf2\x7d\x6a\x97\x82\xaa\x97\x52\x98\x4a\x8a\xf5\xea\xce\x52\x47\xb0\x8e\xa0\x28\x1e\x14\xbc\x43\xf5\x8a\x9f\x07\xbd\x2f\x28\x4d\x3b\x37\x48\x69\x72\x6c\xb9\xa8\x00\x5a\xe3\xc4\xc5\xbd\x8b\x99\x50\x06\x5b\x2e\xa0\xf3\x2d\x14\x20\xed\xaf\x53\x20\x64\x22\x86\x65\xa7\xbc\xf9\x67\x60\x27\xb2\x39\x64\x33\x1b\x06\x5f\x94\x77\x8e\x29\x20\x89\xcd\x69\xd0\x51\x02\x51\x9e\x1f\x4f\xb3\x2d\x1b\xfd\x78\xdb\xb0\xbd\xf5\x0b\x45\x03\x16\xf2\x48\xf9\x44\xef\xc2\xf3\x62\x10\xfa\x3c\xc6\x91\xb0\xe6\x97\x32\x36\x57\x9e\x27\xd1\xf4\xa8\xb7\x08\x55\x7f\x95\x11\x7f\x98\x48\x2c\x90\xa6\xd5\xf7\x51\xed\x0d\x8f\x33\x99\x74\x2c\x50\xa4\x73\xb1\x95\xca\xa7\x17\xec\x0a\x4d\xcb\x98\x5a\xf6\xdc\x2d\x69\x66\x27\x8d\x93\x3a\x9c\x64\x71\xd8\xbc\x8b\x0c\xa9\xf8\x6a\xba\x3e\x6e\x1b\x55\x47\x67\xae\x0e\x5a\x07\xf6\x75\x0a\x57\x42\x82\x26\x69\x7a\x1a\x4c\x82\xf1\x86\x15\x8e\xb5\xb7\xf1\xaa\xc9\x71\x2f\xbd\xbd\xde\x8b\x19\x55\x21\x9e\x3a\x29\xe2\x31\xad\x27\xfa\x1d\x69\x38\x4d\x68\x0b\x47\xcf\x1f\x5e\x71\x33\xeb\x4b\xc3\x91\x3a\xd1\x29\x23\x3b\xd9\xa3\xcb\xff\x29\x5a\xc4\xad\xd4\xef\x2f\xe6\x47\x9f\x50\xf5\x0f\xcc\x2c\xb9\x14\x0f\x19\x49\xb1\x60\xb1\xcf\x27\x9b\x2e\x3d\x48\xe4\x23\xe7\xb4\xf5\x17\x02\xf7\xe5\x8a\xab\x44\xd0\x60\x94\x82\x34\xdb\x69\x61\x24\x81\x8e\x19\x3c\xb0\xe0\x80\x47\x33\x75\x4c\xf3\x99\x20\xaf\xc4\x45\xc6\xf8\xc8\x6a\xed\xca\x74\xe0\xec\x66\xd0\x8c\x04\x3d\x54\x32\x12\xce\x9b\x13\xd4\x79\x45\xb8\x0e\x04\xd4\x8f\x25\x91\x13\x4e\xa6\xa2\x34\x95\x39\xf4\x54\x8a\x60\x49\x54\xc0\x50\x30\xf9\x1e\xda\x45\x35\xc5\x38\x5f\x10\xa0\x8e\x05\x4c\x42\x36\x38\x51\x40\xa5\x55\xc0\xf4\xd2\xb6\xed\x92\x37\xf3\x68\xc5\x33\x92\x04\x05\x8f\xd6\x67\x13\x6f\xca\xd8\x2a\xe2\x44\x70\x2d\xd4\x99\xde\x27\xf9\xcd\x4b\x06\xe3\xe6\x00\xdf\x8a\xfe\x32\xb9\x48\x7c\x79\xa0\xfd\x66\x6a\xc3\x97\xcd\x43\x2b\x05\xd3\xf1\x53\xc1\x17\xba\x3b\x87\xf4\xab\x59\x51\xd6\x10\x00\x07\x87\x12\x73\x9a\xcf\x20\x94\x2d\x03\xe1\x93\x89\xa6\x1a\x79\x4e\xe6\x3c\xc3\xe1\xb3\x53\xbd\xd0\x34\xac\xa5\xf3\x69\x35\x9d\x05\xab\x89\x12\x17\x83\x5f\x54\x69\x69\x40\xba\xa4\x94\x9a\x7f\x57\xa5\xed\xc4\x57\xee\x51\xfa\x76\xed\x7c\xc2\xc8\x8a\x03\x00\xd4\xc8\x8c\x75\xaf\xfb\x80\x1a\xe8\xd5\xbe\xb0\x32\x4e\xc6\x98\x28\xa3\x0a\x1d\x1e\x3b\x59\x27\xdf\x80\xb8\xf4\xeb\xb1\xe7\x49\x82\x02\xba\x6d\x3a\xc0\x53\x1d\x64\x34\x09\x63\x5b\xed\xc0\x90\xf3\x2c\x9f\x36\x17\x1b\x2c\x54\xd3\xd0\x78\x6f\x7d\x5a\x44\x21\x33\xc4\x3c\xf3\x44\x99\x02\x0b\xac\xb3\xc4\xd1\xe4\x4e\x1c\xc3\xb7\xd2\xa4\xb3\xce\xbb\x18\xc4\xdf\x3f\xbe\x80\xa9\x0d\x53\xe1\xb1\x44\x84\x5c\x07\x02\xa4\xd4\xa4\x76\x7a\xb1\xb7\xad\xa6\x0d\x26\x21\x7d\x3f\x3f\x55\xf5\xf3\x36\xb9\x0c\x95\x43\x64\x8b\xc5\x0e\x66\x3f\xf1\x20\x91\xc2\xcd\x69\x91\x94\xc8\x6d\xe1\xdd\xa7\x54\xbc\x3a\xb2\x5d\xac\x7b\x4d\x2a\x6d\x74\xa9\x31\x9f\x34\xc5\xc2\x1f\xed\x65\x44\x15\xeb\xe6\x52\x17\x28\x39\x33\x11\x20\x02\x20\x49\x44\xcf\x79\x9f\x22\x71\x92\x5e\x31\x10\x74\x60\x60\x3f\xb5\xb7\xc6\xb3\xf0\xe9\x31\xdf\x85\xd8\x49\xf7\x18\x89\x6a\xf0\x5c\x3f\x91\x78\xf5\x8b\x93\x16\xc9\x11\xb8\xff\x5e\x63\x18\x62\x50\x38\x6c\x51\x11\xd3\x28\xf9\xf9\x64\x8b\xca\xfd\x2f\x4d\x62\x8a\x47\xa4\xc8\x16\xaf\xdd\xd2\x89\x79\x54\x76\x73\x91\xfc\x81\xba\xa0\xc1\x3b\x38\x03\x1d\xd2\x45\xc4\x18\x3b\xe3\x8c\x7c\x0d\x94\x01\x57\xae\x13\xb2\x25\x4e\x0c\xc1\xf0\x28\x2e\x60\xad\x13\x24\xd0\x2c\xde\xf1\x83\x30\xac\x76\x2f\x8e\x83\xab\x46\x11\xae\x79\x93\x50\x24\x2a\x06\xf4\xf1\xcc\xbf\x7e\x7c\x02\xfe\xd0\x38\x8c\x86\xdd\xd3\x0e\x99\x54\x1b\x86\x0a\x39\x6c\xbe\x73\xa8\x08\xb2\x9e\x76\x20\x60\x31\xc2\x10\x2e\x85\xe8\xa3\x42\x36\xb3\x16\xab\x6e\x1e\x0a\x79\xa1\xdc\x3f\xd3\xef\x45\x29\x90\xf8\x0a\x48\x54\x2a\x10\x27\x25\x14\xf5\xb2\x03\x0e\x77\xf1\xe7\x99\x06\xc5\xdb\x3e\xbd\xd1\xbd\x87\x36\xc9\x6c\x99\x72\xb5\xc2\x7a\x49\x29\x11\x9b\x32\x62\xfe\x32\x74\x0c\x2a\xc7\x70\x27\x46\xc9\x4b\xe0\xb9\x15\xc0\x7c\xf1\xaa\x80\xa0\xa4\xde\x58\x8c\xb0\x8a\xe4\xec\xc8\x07\x78\x76\x9a\x89\x40\x07\x52\xac\x45\x21\x28\xa3\xbf\x64\x5a\x23\xbb\x91\x07\x8b\x9b\xc5\x0d\x72\xe4\x38\x71\xba\x40\x16\x12\x32\x38\x38\xb1\x95\x98\x22\x92\xfa\x27\xeb\xbd\xbd\xc5\x54\x78\x0c\x85\x23\xb3\x93\x91\x08\xcb\x89\x77\x4f\x63\xc7\xa9\x21\x1d\x88\x93\x11\xe0\x7e\x25\x3c\x87\xdf\x2f\x60\xe7\x37\x95\x42\x9d\x24\xa3\x57\x01\x44\xce\xd4\x0c\x9a\x5d\xd1\xef\x10\x9f\xc6\x75\x99\xd9\xa6\x6a\xaa\x54\xcc\xdb\xde\xfa\xab\xb2\xf5\x5f\x78\x64\x2f\x11\x51\xa7\x05\x4a\x27\x55\x2d\x0a\x27\xa8\x2d\x5a\x23\x72\x4a\x0b\xa4\x73\x57\x78\x2a\x99\x0a\x2f\xe4\x76\x80\x88\x7c\x80\x90\xd5\x8b\x8b\x85\x19\x00\x81\xde\xff\x81\xc1\x4e\xf5\xd7\x5e\xbb\xc6\x31\xb7\xed\x8a\x16\x52\x87\x94\x1d\x8a\x4a\xa8\x54\x7f\x62\x72\xd7\xd9\x37\x68\xe3\xe0\x7c\xb7\x95\x0a\x76\xca\x0f\x2c\x4a\x38\xba\xce\x50\x23\x73\xb3\xed\x5a\x80\x38\x17\xed\x90\xc8\xaa\xb2\x39\xd5\x1a\x73\x0b\x16\x3c\x05\xff\x4f\xe7\x82\xbc\xdd\x43\xda\x44\x49\x20\x7e\xca\xa5\x50\x04\x86\xd7\x89\x71\x66\x49\x9e\x27\xaf\x27\x88\xad\xdc\x3c\xbd\x32\xc9\x61\xc9\x8f\x80\xa0\x0f\x14\x1a\x64\x4e\x4e\x92\x89\xbf\xfe\x99\x31\x38\x4f\x2a\x93\x1b\xe6\x24\x62\x6f\xbc\xc5\x43\xa5\xd1\x29\x5f\x92\xdc\x5e\x76\xbd\xd5\xcb\xe7\x87\x2f\x99\xd3\x76\x8f\xa5\x39\x61\x64\x72\x05\x65\x3b\x92\xc7\x9b\x01\x76\x2d\xa8\x2e\xe6\xf7\x4f\xff\x86\x12\x08\x44\xb3\xa9\x5b\x1e\x39\x55\x16\xe8\x6d\xb9\x58\x79\xdd\x0a\x35\xf1\x50\x33\x66\x31\x03\x05\xba\x18\xd7\xb2\x82\xae\xa2\x19\x19\x6a\xbd\x03\xbc\x51\x65\x07\xd6\x75\xfd\xe6\x70\x69\x39\x90\xbc\x6d\x40\x53\xaf\x20\xae\x83\xc9\x8b\x12\xb4\xaf\x22\xa7\x43\xcb\xc4\x44\x65\xcb\xcb\x3e\x40\x8f\x64\xe0\xa4\x4e\x25\xe6\x04\xc7\x02\xcf\x09\xbd\x92\xff\x53\x09\x69\x8c\x33\x32\x8a\x93\x2b\x99\xfe\xc6\x26\xaa\x54\xef\x20\x13\x01\x4d\xea\x97\xeb\xbf\x15\x27\xfd\xe3\xf3\x8b\x24\x62\x9b\xa3\xda\x52\x91\x93\x48\x0e\x63\xb3\x7f\x64\x9d\x38\xbc\x81\xd7\xc0\xc2\x37\x8d\x62\xb0\xfd\x1e\x90\xb2\x01\x0e\xfb\x43\xfa\x83\xa5\xb6\x6b\x2c\x5c\x26\x4b\x7b\x62\x82\xd3\x1d\x59\xae\x51\x78\x8c\xf4\x80\x2c\x72\x20\xd7\x43\xa1\x0a\x87\x15\x25\x4f\xae\x7b\x18\xf0\xa9\x0b\xfa\x0e\x6e\x24\xe4\xa0\x13\x32\x69\x60\xa7\x50\x2b\x84\xf4\xc5\x5c\xc5\x4b\x00\x9a\xcb\x1d\x62\x86\x06\x29\x6e\x13\xfc\xae\x2b\x05\x9c\xfd\x2f\xb8\x8e\x37\x05\xe1\x45\x31\x00\x5f\xab\x66\x53\x72\xc6\x96\x18\x3c\x29\x0e\x74\xa7\x81\xf0\x39\xb3\x3f\xbe\xb0\xe6\xee\xf9\x09\xe3\xad\x33\x8f\xba\x2b\x39\xb7\x3a\xab\x28\x83\xbb\xc9\x91\xfe\xa4\x59\xa6\xb5\x58\x02\x7b\x2d\xf6\xe9\x32\x31\x4f\x12\x6a\x13\xc7\x9d\xde\x82\x8f\x58\xa1\x97\x20\x63\x59\x21\xff\x73\x2b\x31\x81\x2e\xf2\xf0\xf3\xf1\xfe\xf5\xc9\x76\x1c\xf2\x07\x3c\xef\x8d\xfd\x73\x61\x7f\x7b\x67\x07\x8b\x93\x39\x68\x92\xcc\x62\xd1\x99\xf8\x41\x57\x2f\x9c\x14\x37\x76\x54\xd7\x79\x2c\x58\x80\xc3\xc7\x2f\x50\x8a\x53\x47\xfe\x8c\x5c\x18\x16\x38\x85\x83\xd2\x9f\x17\x46\x43\xce\xae\x41\x37\xd3\xb9\x34\x99\x4a\x30\x83\xdb\xd3\x3b\xb4\xd0\x5f\x9c\xf1\x43\xde\x04\x21\x5d\xa6\xec\x81\x22\xcb\x90\xb6\x10\xab\x00\x2c\x4b\xbb\x0b\x3f\x74\x8d\xe2\xe2\x59\x58\xca\xa6\x53\x59\x89\x1c\x09\x81\xaf\x39\x2a\x6a\xdb\x30\xbf\x40\x0d\xb0\xb1\xf4\xe5\x9b\xf4\xaf\x42\x4e\xb3\x85\x22\x69\x44\x45\x81\xbb\x6c\xe1\x31\xb0\x15\xe4\xe3\xe3\x40\x7a\x57\xd5\x9d\xdd\x9d\x82\x5e\x46\xf2\x71\x22\x31\xa2\x27\xce\x99\xd6\x50\xc5\xc2\x77\x5d\x1c\xbb\x64\xdb\xc5\x93\x60\xb5\x47\x3f\x81\x17\xdf\x54\x3e\xca\x43\x71\x33\x55\x48\x30\x99\x1f\x64\x24\xba\x5e\x54\x91\x73\x68\xe9\x0f\xce\xae\x39\xf9\xe7\x16\x4f\x61\xbb\xcd\x07\x28\x78\x64\x68\xd5\x02\x17\x15\x46\xb4\x19\x0a\x97\x51\x6d\x8b\xcd\x42\x48\x9f\xfd\xbb\x62\x9d\x49\x0d\xf2\xa6\xc5\x37\x32\x9e\xc5\xd2\x91\xce\x1c\x38\x21\x39\x77\x2d\xe2\x39\xde\x62\xb9\x67\xf7\x6c\x61\xf6\x79\xd3\x4b\x4f\x8e\x83\xba\x05\xac\xd2\x53\xdf\x39\xab\x45\x2d\xfd\x87\x7a\x13\x67\xca\x81\x49\x4a\x25\x2e\x79\xdf\x22\x61\xf4\x11\x16\xce\xfe\xff\x12\x34\xd7\xc8\x7c\x1c\x36\xb5\x99\x6f\x41\x90\xf4\x30\xbc\xa0\xe8\xdb\x2d\x15\x42\xd4\x66\x49\x82\xaf\x34\xfb\x2c\xfc\x30\xb0\xf2\xf0\x4d\x3d\xb3\x48\xb4\x80\x00\xf4\x43\x21\x15\x32\x9f\x81\x49\xdd\x34\x79\x97\x9c\xdf\xe2\x3d\x2e\x77\x15\xd3\x12\x51\xf5\x22\x62\x98\xf5\xd3\xe1\xd6\x81\x34\x4a\x63\x2c\x3d\x57\xa6\xb0\x82\x28\x3c\xb6\xc4\x6e\x81\x60\xc6\x41\xa0\x50\x2d\x06\x36\x9c\x86\xe3\xf3\xf3\xb3\x0c\x1f\xb2\xe5\x6b\x79\xc8\xdb\xac\x7c\xe1\x74\xcb\x1f\xa5\x69\xb9\x64\x4e\x47\xe2\x10\xa9\xa5\xdb\xbf\x36\x0e\xa5\x19\x3d\x36\x06\xd9\x8f\xcb\xce\x94\x27\xd6\x9f\x0b\x5d\x18\x79\x97\x95\x7d\x64\xaa\xe0\x97\x26\x72\xb8\x70\x67\xaf\x57\x05\x62\x6a\x1e\x44\x02\x9b\xb9\x3a\x8b\xc7\x48\xdf\xa5\xca\xc0\xf6\x72\x59\xcf\x7b\xd7\x91\xb5\xdd\x25\x1f\x2c\x9f\xe6\x38\x46\xf1\xf8\x7c\xbe\x01\x09\x43\x25\x51\xa0\x3c\x1e\x11\x39\x6b\xe8\x55\xb0\xcb\xbd\x16\x9d\xb7\x39\xae\xc4\x56\x17\x1a\xed\xda\x51\x50\x15\xa2\xc0\x07\xcc\xc8\x7f\xf0\xe0\xdb\x63\x80\xba\x78\x3f\x1e\xc8\xcc\xe9\x05\xdc\x89\x81\xe5\x0a\x42\xce\x0a\x19\xba\x20\xc8\x4a\x50\x0e\x5c\xd3\x8b\x7c\x37\x7b\x8b\xeb\x58\x49\x47\x81\xf4\xdf\x2e\xa7\x58\x4d\x9e\xde\x1b\xeb\xe7\x11\xec\x71\x70\xd4\xeb\xe5\x0b\x31\x85\xa9\x02\xd3\x89\x81\x85\x9d\xd2\x72\xed\x8d\x74\x5b\x81\x9a\x83\x0f\xa2\x5d\x34\x1d\x29\xd7\xe7\xd8\x6c\x2f\x2f\xb3\x2d\x42\x5c\xfd\xe5\x60\x95\xa5\x6a\x5f\x67\xb6\x30\x10\x90\x25\xd2\xc2\x32\x01\xa4\x9c\x6a\x91\x8e\xb0\x73\xae\x21\x71\xe8\x5d\x03\x51\x8c\x9d\xa0\x8f\xe6\x38\x9f\x03\x77\x4e\x6e\x4f\x4d\xf6\xc8\x67\x6a\x89\xf9\xdf\x0a\x27\xaa\xa3\x81\x04\xec\x5b\x89\x12\xf3\x26\x08\x0f\xe1\x2a\x80\xc8\x76\x3a\xf6\x9b\x2a\x5d\x8e\xc7\xa3\xd7\x85\x15\x4d\x15\x55\x98\x1a\x01\x0a\x1a\x4f\x6d\x96\xa7\x5d\x48\x0c\xac\x49\xf5\x82\x56\x54\x40\x37\x2d\x72\xf7\x3a\x11\x2c\xce\x0e\x39\xa2\x2b\x24\x62\x23\x68\xbb\x28\x5b\x3f\xd2\x4e\x6c\x5e\x52\x27\x03\x88\x97\x1f\x05\xd9\x9f\x23\xb9\x19\xa7\xbc\x30\x2c\x36\xdb\xcf\xf3\x82\x26\xc7\x85\x19\x12\x1d\x8e\x73\xe9\xbc\x7b\xbf\x7f\xcf\x77\x08\x0a\xc6\x97\x41\x76\x7c\x52\x40\xd6\x7c\x2c\x55\x49\x59\xf6\x73\x82\x2b\x4a\x88\x47\x86\x22\x52\x9d\xda\x45\x74\x6a\x1e\x1c\xbf\xa0\x4f\xc2\x9a\x1f\xd8\xc3\x72\xf8\x78\xb7\x7f\xbe\x64\x6b\x60\xaf\xb8\xbb\x89\x3c\x5b\x3f\xbf\xfe\x5d\xfd\x4f\x99\xd0\x04\x2c\x36\xe7\x5b\x21\x51\xec\xa9\xd3\xe2\x38\xb6\x27\x97\x45\x3c\x7b\xbb\x48\xea\x96\x2e\x3f\x48\x87\x02\x01\xa4\x43\x56\xb8\x7c\x84\x9d\x36\x4b\x23\x34\x05\xa2\xca\x17\xe4\x6a\x16\xb1\xbb\x17\xe2\x45\xcd\x91\x4a\x25\x32\xde\xc0\xf2\x07\xf1\x5a\x52\x83\x6e\x75\x10\x18\x13\xcd\x70\x27\x18\x2e\x6f\x8b\x02\xd6\x46\x54\x6b\xe6\xff\x08\x65\x3d\x7a\x57\x10\xc6\xe7\xe5\x65\xeb\x5e\x2c\xd4\x1b\xeb\xd4\x3e\x39\x4c\x5d\x8e\xd9\xdb\xc2\x59\x3b\x1d\x84\x45\xc0\xb9\x63\x13\x04\x5c\x26\xd3\x5f\x2c\x00\x85\xd7\x9c\x89\xab\x98\x9b\xfa\xb0\xa8\x6c\xe7\x84\x76\x58\xe5\x4b\x62\x16\x5c\xfc\x35\xcc\x0e\x6f\x35\x7c\xfe\xbe\x60\xe5\xfb\x7c\x03\x7a\xc9\x91\xf9\xfd\x40\x9e\xb3\x8b\x85\x06\xdc\x16\x77\xa5\x8a\x23\xf7\xfb\x43\x75\x68\x8e\x7e\x9d\x14\x6c\x0b\x6e\x61\xc6\x92\xe8\x38\x5a\x4d\xc4\x56\x2c\xff\x30\x87\x1c\x33\x87\xb5\xcd\x05\x61\xe0\xa4\x05\xf9\x55\x8d\x53\xdf\x83\xe3\x0f\xb0\x10\xd3\x39\xeb\x01\xa9\xbb\x5c\xaa\x3c\x53\x8e\xd3\xb6\x60\x31\xc3\xf3\x29\x8b\x1c\xbc\x48\x86\xd0\x29\x45\x41\xed\xda\xbc\x35\x08\x0c\xcc\x73\x0f\x72\xd6\x4c\xae\xc8\xd3\x6b\x7b\x3b\x05\x71\x7a\x79\x3a\x5d\x85\xf3\xfd\xae\x73\x53\x10\xf9\x75\xe9\xa9\x72\x1c\x11\xca\xfb\x63\xa9\x7c\x5e\xbd\x2f\xd6\x7f\xc5\xd1\x37\x64\x54\x35\x33\xc1\x8d\xbc\xbd\x48\x3f\x9e\x3e\xa6\x84\xe9\x8a\x87\x79\x30\x4a\x44\x99\xf7\x4a\x80\xed\x68\x3e\x2b\x81\x2f\x99\x74\xe0\xe1\x36\x3d\x1a\x7a\x43\x4a\x89\x8b\x8d\x18\x98\x83\xff\x6d\x3e\xd7\xff\xfe\xef\x41\x48\xcb\x3a\x48\xa9\x6c\xe4\xd6\xb0\xa7\x4e\x9e\x0a\x20\xf1\x65\x63\x9b\x92\x65\x82\x5f\x63\x24\xc1\x3e\x55\x0f\xb8\xfd\x42\xea\xdd\x3c\x4a\x13\xca\x3e\x67\xd4\x7a\xcd\x88\x35\x61\x2e\xf0\x20\x85\x4d\x1c\x4d\x07\xe9\x1e\x58\xa8\x33\xa7\xbc\xc0\x29\x2d\x88\x74\xf1\x20\xcb\x0b\x41\xcb\xbd\x59\x71\x92\x2d\xba\x6c\x36\x0f\x6d\x76\x26\x33\x45\x4b\x05\xa5\x49\x64\x6c\x5c\x0a\x4d\x99\x56\xb1\x3b\x2c\x06\x75\xe7\x6e\xc9\x84\x87\x99\xc7\x90\x7b\xe6\x67\xbe\x7f\xfc\xbb\x12\x5b\x42\x85\xf2\xc9\x18\xef\x84\x6c\xc9\xcd\x43\x5f\x38\x74\x47\x2a\xcd\xe9\xa7\x9d\x19\x37\x13\x1a\x46\x51\x7f\xfd\x3c\x0e\xc6\x47\x5d\x70\xc7\x97\x3d\xf8\x3d\x1c\x7e\x0f\xac\x37\x80\xdf\x9c\xdd\x1e\xa1\x50\xbe\x4f\x25\x11\xf0\x9f\xa2\xb7\x87\xd4\xac\xcf\x5d\xd3\xb2\x31\x85\x71\x36\xff\x2e\x52\xdb\x82\x4f\xa0\x52\xee\x9b\x05\x26\xb5\x40\x1e\x55\x6a\x1c\x04\x8c\x74\x36\x1c\xa5\xb1\xe6\xfe\xc1\x20\x34\x11\xb8\x8e\xee\x56\x68\x68\x6f\x5b\x98\x89\x2c\x01\x28\x80\xf1\x78\x57\x1a\xf1\xe3\xe5\x22\x78\x86\x66\x0c\x7a\x6d\xee\xf2\x9f\x52\xbb\x80\x02\x9d\xfb\x66\xcc\xe9\xe2\x22\x38\xa3\x84\x99\x3c\x56\x83\x5f\x38\x48\xc1\x44\x11\x0e\xfb\xd5\x7d\x7f\x7f\xff\xbe\x63\x8d\x40\xcc\xc6\x8c\xf9\xe4\x48\xc6\xca\xb9\x7d\xb7\xd2\x0d\x47\xc6\xea\x83\x16\x5c\x29\xf3\x4e\x41\x9f\x99\x6f\x35\x4c\x84\xa5\x10\xca\xfa\xd8\xac\x0a\x8e\x6b\x54\xf7\x5c\xde\x27\x8d\x18\x10\x8e\x85\x33\x3e\x0f\x3a\x9f\x15\x0c\x9c\x39\x39\x89\xeb\xcb\x69\x08\xc7\x37\x24\xcb\x5f\x03\x48\x6f\xb3\x3f\x73\x03\xda\x6a\xaf\x29\x55\x7f\x15\x74\x10\x78\xd3\xdf\x2d\xac\x3a\x4a\xbd\x20\x9a\xe4\x89\x17\x87\xe0\x68\x3a\x8b\xbb\x5f\x78\xff\x2c\xaa\xab\x33\x33\x20\x88\x94\x4c\x9d\x9a\xa9\xa6\xb7\xbf\x2c\x84\x81\x84\x53\xf3\x4b\xc3\xb6\x09\x43\x9c\xed\x06\x61\x42\x73\x7e\x35\x1c\x8f\x25\x3f\x29\xbc\x27\x48\x3c\x88\xfa\x92\x64\xbe\xf9\x77\xa5\xd1\x37\x45\x44\x45\x58\xd8\x17\xfa\x35\x33\x1a\x0f\x11\x1c\xc4\x57\xa7\x8a\x66\xe8\xf9\x6b\xfe\x1f\x2c\xb3\xfa\x8f\xff\x0f\xef\xfe\xd5\x91\xac\xa9\x99\xa8\x52\x13\xba\xd1\x65\x35\xe7\x7f\x7c\xfb\x77\xc5\xa4\xf6\xa5\xf8\x72\xca\xa3\xcf\x41\xcc\x00\xf9\x92\x49\x0b\x36\x9b\x07\x93\x5a\xc1\x33\xfd\xbb\x62\xe3\x5e\xaf\x10\xa5\x76\xa8\x51\x45\xd0\xa6\x2f\xb2\x49\x2a\x1c\xa4\x11\x79\x25\x98\x96\x3e\x6c\x2c\xd9\x15\xbf\x3c\x15\x36\xe0\x57\xc1\x12\x12\xe2\xcd\x1a\x03\xdd\x65\x52\x65\x01\x02\xe3\x77\xfa\x56\x1a\x31\xb0\xc3\x3c\x3b\xfe\xb6\x15\x32\x9f\xbb\x22\xca\xa8\x64\xa8\x89\x2a\x15\x68\x1f\x1e\xa1\xe6\x2e\x8b\xb1\x9c\xe9\xde\xbc\xf0\x74\xfc\x0b\x4f\xc6\x70\xf6\x37\x24\xd3\xb4\x38\x6c\x22\x25\x38\x32\xba\x9a\xf9\xe3\xce\x5b\xab\xbd\xb9\x16\x7f\x81\xbe\xab\x45\xc4\x19\x90\x18\xcf\x25\x73\x52\xdc\x25\x9f\xc1\x3f\x09\x1e\x11\xd6\xfb\xe4\xc4\x1e\xca\x3c\xb0\x9b\x09\x04\x72\xdb\xcf\xc8\xa1\x21\xc5\xde\xbc\x10\xd3\x69\x54\x04\x80\x86\x7e\xfa\x73\xa5\xf1\x05\x05\x5d\xe6\x38\xd9\x39\x5b\x43\x5b\x08\xaa\x44\x3e\x6b\x4e\x41\xb5\x87\x41\xd8\x34\x11\xfc\x9a\x99\x0f\xa4\xf9\x33\xb7\xb9\xe7\xca\xbc\xba\xc5\x1a\x4f\x9d\x2d\xa2\x12\x1d\x63\x53\x38\xd9\x6a\xd1\xa2\x7b\xe2\x83\xca\xb6\xb5\x6b\x51\x9f\x91\x64\x9e\xdc\xad\xaf\xdc\x39\x17\xd8\x29\xb0\x39\x9e\xcf\xdb\x5f\x4a\xe2\xc1\xf3\x22\xac\xaa\x2c\x8f\x75\x28\x3c\x1f\x9b\x88\x6e\xbc\xc6\x7e\x26\xf8\x54\x33\xce\xec\xb6\xa9\xba\xdb\x2e\xf6\xda\x06\x54\x57\xb9\x39\x1a\x7e\xd4\x93\x67\xa7\x8f\x0f\x76\xf3\x21\x55\x26\x22\x42\xdb\x34\xa6\x18\xbc\x86\x26\xd6\xbd\xe4\x03\x5e\xd9\x6a\xbc\xee\x13\x46\x4b\x56\x64\x69\xf0\x67\xe2\x54\x26\x2e\xfa\x3c\x08\x6c\x84\xb0\x57\x79\x22\xba\xca\xbb\xd3\x2e\x05\xd5\xd4\xf4\xca\x25\x2e\xa3\xc6\x48\x78\x4e\xf1\xc4\xac\x13\x0a\xc7\x28\x4f\x1c\x68\x33\x0e\x1f\xc7\xcf\x77\x82\x53\x93\x1d\x51\x98\x4b\x8e\x59\x60\xa6\xb9\x8c\x19\x0b\x02\xff\x76\x9c\x7b\xa3\x92\x85\x0a\x52\xb2\x63\x60\x40\x3c\xe8\x14\xab\xc9\x23\x2f\xb8\x84\xe5\xd8\x1e\x9b\xf7\x99\x75\xe9\x2b\x47\x7f\x99\x3e\x26\xee\xed\x71\x37\xb5\x88\xb2\x5f\xa1\x1a\x74\x6a\xc4\xbc\x2f\x8c\xbb\xd6\x5e\x69\x1d\x51\xf0\xa3\x60\x17\x8e\xf5\xbb\xbf\xcb\xe1\x35\xb7\xfa\x96\x21\x7f\xec\x09\xec\xf3\x99\xcb\x89\x71\xc1\x42\x98\x74\xaa\x95\x98\x5b\xb2\x0b\xb3\x6a\xde\xc5\x4e\x2e\xc9\x49\x8c\x67\x67\x01\x51\x0e\x47\xc8\x6d\xed\x03\x53\xe1\xc1\x79\x6e\x13\x9e\xc3\x7a\x5f\xbe\x45\x49\x2b\x0a\x7a\x8d\x5c\xa5\x57\x30\x0c\x62\xa5\xea\x4a\xab\x60\xcb\xf2\xad\xf7\xac\xd3\x71\x65\x5d\x77\x2e\x14\xc1\x4b\x10\x41\x47\x5d\x66\x23\x79\x58\x44\x4f\xfc\x51\xa8\x86\xa3\x18\x0f\x2f\x79\x7a\x30\x7f\x9f\x34\x99\xea\xf8\xe3\xdf\xf6\xe0\xfe\x90\x0e\xf9\x38\x7e\x79\x34\xed\x8f\xde\xfc\x1b\x52\xe4\x3d\x6e\x03\x79\x34\xa6\x6e\x66\x2b\xe4\x10\x9e\x61\x51\x30\xba\x48\x95\x43\xbf\xc1\xd5\x2f\xa3\x52\x5c\x75\xab\xcf\xdb\xeb\xb2\x7c\xe0\x11\xa0\x2b\x50\x8d\x5b\x69\x9a\xbf\xba\x7e\x47\x78\xfc\x89\x4d\x71\x9d\x53\x16\xb3\x0d\xac\x2d\x95\x29\xd3\x60\x27\x06\x02\x9a\x74\x7a\xd0\x09\x55\xd3\xb6\x0f\xcc\x62\x2e\x60\x63\x31\xad\x19\x70\x7d\xaa\xeb\x4e\x4a\xc7\x5c\xe9\xc0\x99\x78\xb0\xf8\x7f\x31\x9b\x3d\x26\x42\x55\x91\x36\xf1\x28\x29\x15\xe2\x6a\x27\x06\x9a\x84\x7e\x10\x19\xcc\xd5\xaf\x8d\xaf\xa0\xfe\xaf\xe0\x7b\xfa\x1a\x3e\xef\x4d\x99\x68\x37\x0b\x2d\x2f\x24\x04\x4a\xe2\x15\x0b\xe1\x1c\x03\x66\x02\x45\x57\x57\xcb\x3a\x96\xc1\x21\x8b\x2a\x36\x66\x4d\x61\xf9\x9c\xc3\x38\x30\xb8\x09\xbb\xad\x8a\x9f\xef\xcf\xcf\xba\x13\x65\x4a\xf3\xb7\x8a\xde\x5b\xc5\x79\x8b\x9e\x7f\x27\x09\xb4\xc6\x4e\xb6\xd3\x1a\x5a\xb6\xcb\xcf\xb2\xc9\x1c\x31\xd6\x01\x7e\xb9\xbd\x06\x81\x9b\xdb\x11\xca\x2c\x54\xbb\x40\xc2\x4e\x33\xd3\xd1\x4d\xde\x1b\x72\x1b\x38\x12\x57\x74\xf5\xf9\x35\xb6\xa3\x07\xbe\x1b\xe1\x65\x9f\x9e\x29\x30\x1e\xb5\x95\x84\x9b\x57\x06\x8b\x80\x58\xf9\x51\x91\x59\x05\xa7\xcd\xa9\x29\xa9\x90\xc0\x8b\x58\x01\xeb\x34\xc8\xaf\x0c\x65\x78\xf5\x2c\x5c\x1b\x26\xb4\xf8\x0b\x1d\xea\x04\x67\x36\x3e\xd5\x6e\x0e\xcc\x17\x6d\xc8\x13\x4e\x3c\x08\x3e\x8e\xd4\x37\xa5\x69\x6f\x59\x5e\xad\xcc\xad\x5b\x1f\x64\x32\x4b\x73\xfb\x5f\x8f\xcb\x56\x48\x4d\x83\x29\xb9\x07\xf9\x65\x5a\x67\x8c\x42\x55\xd0\x19\x39\x14\xb6\x95\x41\xca\x16\xe3\xaa\xd0\xef\xf7\xcc\x55\x47\xef\x2c\x5e\x71\x71\xa8\x36\xba\x63\x92\xf8\x6f\x3c\xd7\x5c\xf8\x20\x87\x91\x3d\x09\x9e\xdf\xa3\xbb\x83\x91\xa4\x38\x4f\x51\xe7\x29\xe6\xdb\x8e\xa2\x9d\xb3\x73\xd3\x77\x7b\xbc\xba\x42\x3d\x42\xc6\x21\x71\x20\xaf\x1f\xbd\xaa\x38\x1d\x28\x16\x15\x4a\xa7\xc7\xf3\x41\x6c\xa0\x8f\x39\x66\xb2\x3f\x09\x3f\xe0\xa3\xd8\xd9\x79\xe6\x33\x18\x09\xca\xb6\x37\xf8\xfc\x91\x46\x2b\x83\x51\xff\x7a\x24\xeb\x02\xbb\x31\x85\xaf\xc6\x2c\xaf\x8c\xd1\xf9\xf0\x66\x6d\x32\x8f\x9e\x5e\xcc\x31\xad\x73\x9f\x8c\x85\x9f\x53\x52\xe8\x0e\x89\xc0\x0c\x1e\xa8\x92\x66\xd3\x4e\xee\x63\x64\xe5\xaa\x8d\xf0\xad\xcd\x68\xf1\xff\xff\x82\x41\x10\x3a\xa0\xfa\x1e\xc6\x0e\x82\x8a\x14\x2b\x4e\x1d\xa7\x72\xb1\x38\x1d\x5e\x93\xe5\x50\x85\x54\x79\xe7\xa1\x55\x72\x18\xb7\x88\xa8\x38\x83\x88\x3c\x0b\xb3\xb9\x85\x38\x72\xc7\x42\x43\xed\x59\x53\x62\x4a\x9e\xa9\x7b\xc2\xa6\x3e\xfe\x36\x00\x41\x11\x83\x2b\x0b\x62\x18\xc7\xb8\x14\x17\xe8\xde\xed\x65\x6c\x4d\x7c\x45\x24\x59\x66\xfc\x73\x1a\x44\xa5\x49\x35\x75\x99\x5d\xcf\xfa\x10\x5c\x60\x5e\x2a\xc0\x5d\xd4\xa3\x0f\xba\x71\xaa\xce\x40\x0d\x78\xce\x9f\x44\xb8\x1c\x7b\x8c\xc5\xf7\xc9\xc1\xf5\x50\x40\xfc\xaf\xe1\x02\xfb\x82\x5e\x8f\x1d\x83\xbb\xb3\x38\x53\x42\x1b\x46\x0e\x12\x06\x3d\xf4\x58\xba\xa7\x46\x02\x34\xc5\x38\x4f\x7a\x60\x78\x2e\x69\x66\x1d\x80\x49\x6c\x7f\xea\xf8\xeb\xdf\x94\x47\x56\x22\x6f\x7f\xb9\x88\x75\x13\xfb\xbc\x13\xc8\xcd\x3c\xdc\x8b\xf0\xa9\xa2\x95\x9c\x77\x4e\xc1\xd2\x60\xc8\xd9\x01\x45\x43\xe1\x12\xff\x60\x19\xcb\xdb\xe3\xee\x84\x05\xd5\xb1\xa1\xcb\xf1\x27\x63\xee\xe2\x31\xac\xef\x82\xba\x80\xcb\x69\x5f\x0b\x5f\x80\x85\xad\xaa\x15\x8f\xc5\xec\x30\x06\xac\xd0\xc2\xc5\x33\x63\x2e\x1a\xea\xb9\xe3\x43\xa3\xe4\xdd\xf9\xd5\x08\x28\x9f\x0b\x0a\x49\x70\x0b\x1e\xff\xd2\x96\xd0\x78\x0e\x4e\xa4\xf2\x1a\x64\x0a\x7d\x4a\x11\x10\x4d\xf2\xfd\x39\xca\x0f\x7d\xd8\x47\xec\x3b\xc7\x49\x82\x13\x11\xd9\x25\x24\x75\x87\x5d\xb2\xe8\xf3\xbc\xc8\x5b\x6a\xeb\x46\x7e\xa9\x70\xe2\xd4\x7d\x4f\x0a\xe0\x1d\x40\xeb\x4c\x2f\x6a\xa0\x7b\xe7\x2e\x8e\x86\x13\x7b\x79\x56\x0c\xa3\xd7\xd8\x25\xc2\x1f\x39\xdc\x17\xdb\x9e\x39\x8f\x96\xbc\xd9\x30\x92\x9c\x1f\x7e\xd0\xbe\x0b\x28\x0c\x13\x81\x8d\x37\xb7\x20\x32\xb4\xf7\xcf\x90\xa5\x34\xdd\xff\xc4\x4d\x0e\xc3\x8d\x9b\x76\x4d\x6b\xc9\x40\x3c\xd4\x1e\x73\xf8\xfd\x79\xe7\x59\xda\xb7\x04\x5c\xe3\xd3\x47\x91\x81\x8a\xc2\x3b\xe7\x27\xe1\xc8\x5e\x14\xf4\x43\xa1\xe9\x58\xc7\x50\x46\xd4\x83\x7d\x9b\xc1\x85\x99\x4e\xfa\xad\x7e\x95\xa0\x45\xc7\xe4\x24\xaa\xc7\x73\xa6\x06\x37\xaf\x0c\xc9\x9d\x79\x4b\x80\xb9\x01\xa6\x25\x9e\x1f\x87\x2e\x10\x08\xbc\x9b\xed\x62\x1b\x6f\x30\x67\x89\x05\xd3\x8e\x10\xa2\x13\x86\x4c\x12\x43\x84\xa9\xba\x7c\x38\x65\xcf\x9d\x57\xe2\x2f\xf7\x9f\x6f\x47\x6c\x22\x10\xf5\xcc\x66\xd5\xb4\x12\x91\x58\x56\x1f\x4e\x85\xc6\x45\x73\xa0\xc8\x53\x94\xef\x9a\x17\xd0\xc4\x52\x62\xe4\x7c\x8f\xf5\xa5\xc5\xd8\x6c\x22\x94\xab\x2d\xe0\x17\xb5\x12\x9a\xaa\xcd\x58\xc8\x16\x80\x03\xd6\xaf\xeb\x7f\xf9\x17\xd6\xd3\x0c\x39\xd1\x13\x16\x30\xa9\xe4\x92\x97\x91\xb5\x54\xf6\xc0\x7f\x1c\x09\xcd\x32\xc5\x39\xd1\x45\xf3\xfa\xa2\xdc\x61\x4d\x06\x05\xcf\x4f\xe4\x71\x05\x49\x8b\x1d\xfb\x2c\x39\x7f\xf1\x85\x09\x1a\x71\x78\x13\x62\xa9\xb1\xf0\x13\x52\xfc\xdc\x38\xed\xff\x8e\x9e\x5a\x9f\xc0\x86\x68\xab\x0f\x17\xea\x2f\xb3\xe1\xf0\x5d\xc3\x6b\xee\x99\x33\x59\x57\xff\xa3\x79\xfd\xac\xbe\x62\x86\x39\xa5\xbb\x25\x74\xce\x49\x6b\xc8\x93\x7a\x13\x9d\xd6\xfc\xd0\x28\x4c\x30\xc7\x20\xff\xf4\xe2\x31\x98\x32\x55\x42\xed\x04\x04\x5a\x77\xf4\x19\xfb\x64\x0f\x91\xb5\x62\xde\x9d\x5f\x6a\x6c\x05\x06\x70\xe7\x99\x65\xa3\xcb\xe5\xc5\x67\xfe\xf7\x08\x4d\xbc\x39\x31\xf3\x88\xe0\xde\x9c\x40\xb8\xd6\x1f\x5f\x60\xbd\xd4\x1c\x1c\xb8\xc7\xaf\x59\x06\x22\x2a\x86\xa2\x08\x00\x60\xac\x7b\xfd\x64\x4c\x03\x1f\x11\x4b\x7f\xc9\xc3\x05\xcf\x5c\x4a\x03\x06\xa8\x33\x28\xf3\xfb\x36\x25\xd2\xbd\xaf\x9b\x36\xe0\xec\x72\xa5\x2d\x38\x02\xfe\xe2\x35\x38\x92\x64\x61\x18\x9c\xef\xca\x47\xbc\x16\xa0\x37\x3d\x5f\x0d\x49\x87\x53\xb4\x7d\x3d\x04\xa8\x19\x7d\xee\x2c\x95\xc9\x90\xe1\x10\xbb\x5d\x56\x77\x86\x5f\xba\xd0\x29\x8d\x1d\x84\x56\x23\x6f\x26\x8d\x3f\x1a\x1d\x81\x36\x31\x67\x80\xd3\x4a\x91\xfd\x25\x1f\xf5\xc0\x76\xfa\x47\x78\xb0\x0f\x7e\x56\xe4\xef\x4c\x01\x14\xcf\x42\x7f\x25\xce\x4a\x4c\xad\x42\x5d\x30\x9d\x4e\x61\xd2\x48\x5d\x71\x8f\x0d\x25\xa9\x75\xce\x6b\x9c\x7b\xfa\x30\xde\x33\x4a\x74\x77\xb4\xd3\xce\xd2\x4b\x78\x66\x61\x62\x54\xf0\x57\x33\x7b\xf7\x98\x57\x7a\x2d\x65\x18\x74\x18\x0b\x2f\xba\x60\xd8\xa6\xe5\xa9\x5f\xed\x99\x51\xe0\xf8\x14\x59\x5d\xec\x44\xf9\xde\x9a\xbe\xe5\xb4\xf0\xa4\x79\x35\x1c\x42\xa4\xce\x1b\xa7\xc4\x77\x11\x7c\x80\x6e\xf3\x55\x7a\xcc\x4b\xeb\x7b\xe2\xdd\xd7\x50\x9b\xf3\x52\x88\xe5\xec\xd1\xdc\x73\x04\x9f\x53\xfc\xf8\x2b\xf6\xa1\xf4\x72\x37\x65\xc0\x9c\xb9\x57\x0a\xf6\x90\x5c\x85\xde\xda\x91\x03\x9e\x5e\xed\xc7\x28\x0e\x51\x61\x3f\x88\xf7\x34\x2d\x63\xc6\x1b\xad\x24\xde\x96\xc7\x7e\x78\x9f\x0a\x59\x83\xc0\x93\x63\x93\xa1\xf6\x63\xf1\xd4\xd6\x79\x28\xfc\x2b\x28\x15\xa9\x78\x82\xd9\x6f\x34\xfe\xa5\xe0\x34\xfa\x4b\xd2\x0b\x01\x8d\x67\x9c\x9f\x1d\x9f\xec\xad\x9b\xea\x90\x0c\xa4\x1c\x40\xb3\xf7\x4a\x79\xb4\x10\x07\x08\xa4\xa5\xb0\xbf\xa0\xaa\xc4\xbe\x6f\x55\x08\xdb\x32\x17\xb2\x5d\xd2\x49\x24\xa4\x3e\x52\x33\x70\x54\xe9\x6b\xd4\xe0\x1f\x19\x98\xf7\xc3\x7d\xbc\xbf\x7d\x13\xc5\xe3\x6c\x4e\xc0\x3a\xc3\x02\x72\x35\x9d\xb7\x89\xab\xb9\x06\xc4\x73\x6d\x68\xd9\x1a\x3e\x3e\x54\xf3\xaf\xf3\xed\x86\x1b\xf0\x0a\x1b\x07\xa5\xb8\x43\xa9\x8a\x94\x07\x85\x1e\x00\x54\x0c\x15\x39\x68\x60\x18\x0a\x91\x45\x7a\x61\x85\xd5\x49\x05\x6d\xcc\x71\x26\x4c\xcd\x94\x0d\x5d\xcd\xe5\x42\x32\xd4\x74\x00\x7d\x59\xaf\x98\x0f\x8a\x13\x41\x32\x97\x4a\xa3\xd3\x96\x23\x07\xdb\x72\x48\x20\x3d\x0c\x0d\xce\x03\xe5\x17\x1e\xc4\x93\x39\x60\x20\xfe\xd4\x70\x44\x17\xb7\x25\x13\x99\x89\xde\x42\x9c\x09\xfa\x9d\xd3\xc4\x97\xd7\x72\xb7\x00\x0f\xa1\x2b\x58\x02\x05\x80\x4c\xf9\x08\x6c\x65\x0c\x33\xcb\x80\x7d\x1f\xf1\xa2\xd7\x76\x41\xa6\xca\x3b\x84\x54\xfe\x34\x13\xaf\x46\xac\xb4\x6c\x35\xeb\xe0\x19\x23\x56\xa9\xd5\x1b\xb5\x32\xfe\x15\x44\x09\x54\x2d\x18\xaf\xbc\x2a\xa3\xf4\xd7\xbf\x16\x9a\xfd\x3f\xfc\x06\x90\x7f\x53\x43\x10\x90\x10\x39\xac\x65\x8a\xa3\xed\x3b\x8a\x42\xe5\x48\x4c\xf1\xbe\x11\x88\x92\xeb\xf6\x41\x98\x6b\xdc\x97\x78\x21\xc3\xec\x38\x92\xbd\xab\x39\xff\xde\xee\x9f\xc8\x0e\xd8\x76\x2a\x3c\x40\x8f\x3c\x60\xf2\xa6\x9d\xd7\x1b\x22\x80\x1b\xc3\x5d\xc7\x31\x8d\x0a\x22\xa2\x26\x73\x4f\x0a\x85\x93\x26\xad\x01\x28\xba\x11\x6a\xf8\x94\x0d\x7d\x3f\x1c\x58\xbd\xf0\x80\x4c\x82\x84\xee\x1e\x66\x9f\x26\x75\x58\xad\x79\x1f\x34\x43\xc2\x99\x28\x60\x96\x2f\x8b\xda\x6d\xe0\x1a\xb3\x24\x50\x98\x1c\x40\xbf\x06\xbb\xa3\xb8\x62\x07\xcd\xe1\x29\x29\x1f\x1a\x68\x0e\xf1\x0e\xc7\x4a\x59\x02\x6a\x13\xf3\xdb\xf7\xff\x54\x03\xfc\x51\xed\xc8\x30\x65\x02\xbd\x7c\xc3\x99\x40\x3d\x25\xef\x0f\x02\x34\x17\xfe\xf0\x59\x55\xc6\x7d\xe0\xb4\xc9\xab\x85\x3e\x8f\x85\xf9\xc5\x7d\xd6\x54\xdc\x51\x96\xcb\x87\x1a\x99\x2e\x24\x88\x60\x57\xf3\x89\x99\x95\xa0\x6e\x01\x2f\xc0\x30\x26\x9c\xb2\x73\xda\xb2\x5b\x2c\xd7\x1a\x22\x99\x0b\x28\xc0\x3b\x16\x10\x30\x3b\x21\xcf\x8d\xcc\x76\x7d\x34\x95\xca\xa4\x6a\xde\xc9\xc5\x6e\x31\xdc\xa4\x12\x6d\xfc\xab\x49\x38\xfe\x89\x09\x2d\x67\x67\xe4\x2a\x61\x28\x15\x2e\xc1\x3b\x45\x89\x73\xf6\x66\x95\x54\x3a\x46\xc8\xc7\xfd\x41\x76\x6f\x80\x5c\x5f\xec\xe7\x68\x07\x87\x78\x14\xed\xb1\x2a\x6b\x87\xfc\x7f\xd1\xa5\x7a\x34\xec\x1d\xab\x2d\x83\xa7\x0d\x71\x78\xd7\x9a\xa0\xc6\xf3\x4e\xf0\xe1\x18\x5b\x62\xf0\x1c\x97\xc2\xb1\x20\x62\xa4\x83\xfb\x81\x38\x5f\x24\x76\x70\x44\xde\x90\x73\xf2\xf4\x2b\x7b\x4e\x46\xc4\x5d\xdf\x9f\xfe\x6d\x0f\x3e\x7f\xfc\x1b\xc7\x1b\x5e\x4c\x45\x17\x97\x30\xd7\x36\xe5\x1e\x9e\xf4\x3e\x3b\x2b\x0a\xcc\xaf\x1d\x90\x8a\x7e\x80\x8a\xc9\x9a\xbd\xcc\xa8\xc4\xd3\xc7\x3c\x70\xe9\x72\x01\x58\xc2\x01\x44\x74\xb3\x1e\x1b\x13\x21\xf7\x46\xf5\xda\xb4\x68\x0a\x9a\xad\x39\xb1\xe7\x5e\x82\xd6\x9d\xbc\x26\x72\x1d\x5e\xa4\x79\xb5\xf7\x3b\x09\xb1\x50\xcb\xe4\x7a\xbb\x1c\x51\xa9\xc8\x7d\x02\x3e\x85\x91\xc2\x50\x8f\x1e\x54\x16\xa8\x9c\x3a\xac\xcc\xc1\x9d\x34\xab\xa4\x0c\x6d\x9a\x17\x36\xf5\xdb\xaa\x6f\x8f\x99\x55\x42\x1f\x89\x43\x18\x92\xc5\x07\x1c\xba\x32\xb8\xb5\x3a\xe8\x01\x89\x03\x96\x02\xcb\x3d\x90\x9f\xfc\x70\x7c\x11\xb1\x9a\x73\x51\xf0\x97\x66\x3f\x40\x7f\xe4\xee\xb9\x52\xc8\xa7\xcc\xb6\xe9\x36\xb7\xec\xa5\x54\x7b\xba\x27\xe2\x46\x32\x91\x82\xca\x33\xeb\x34\x0b\xa2\x5e\xca\xc1\xce\x2c\x47\x86\x2c\xa9\x40\xb0\x3f\xb0\xb2\x30\x94\xa1\xcd\x73\x3c\x81\xc8\x28\xb6\xbb\x90\x08\x85\x55\xdb\x8c\x7d\xaf\x46\x7c\x73\x4e\x38\xa2\x8d\x93\x12\x28\xf9\x53\x49\x90\xb1\x3f\xbf\x26\x82\x7f\x6a\xc5\xd1\x7a\x7d\xa1\xd2\xae\xa6\x0e\x90\x23\x99\x30\x88\x8b\xf2\x8f\xb2\xc0\xcf\xb7\xfd\xe3\xff\xb3\x5c\x04\xbf\x73\xdd\x57\xfa\x84\x1c\x9f\xc4\xfe\x7e\x2f\xf5\x95\x56\x21\xf6\x04\xf8\x70\x7c\xc6\x19\xe6\xab\x98\xb5\xb9\xe8\x48\x68\x92\xa1\x3f\x0c\xfa\x29\x85\xbf\xe5\x22\x24\xe7\x28\x5f\xd0\x55\xa0\x62\x6c\xf9\xb0\x23\x26\x0e\x2b\x9f\xaa\x0c\x60\x0e\x6d\x19\x56\x89\x14\x17\x1f\x10\x00\xe0\xc3\xbe\x59\xc5\xc0\x4c\xed\x8a\x58\x5a\x69\xa3\xef\x9f\x5f\x92\x73\xfc\x8d\x7b\x6a\x2c\xac\x0c\xfc\x00\x33\xb8\x9d\x46\x26\xaf\x1a\x26\xf3\x97\x6a\xe4\xa6\x5a\xa8\x4d\xb1\xca\x6a\x60\xfe\x63\x2c\x45\x25\x6c\xc3\x6d\xef\xfb\x0b\x03\xf0\xf7\xc8\xdc\x15\xfa\x99\x0e\x0d\x92\xc1\xcb\x52\x97\x6b\x43\xd1\x9c\xcc\xfc\xe3\x0a\xbc\xc6\x83\x49\xec\x41\x49\x21\x87\x63\x31\xa1\xe5\x09\x1c\xf1\x69\x4a\x03\x79\xe8\x83\xfa\xe6\x25\xdd\x84\x5a\x9b\xfe\x66\xa4\xcd\xf4\x14\x50\x3b\xf9\x40\x0c\xff\x0d\x96\x1b\xcf\x87\x31\x21\x6e\x27\xf3\xc5\xc6\xb7\xb4\xa8\xff\x39\xa5\x71\xc5\xa2\x13\x69\xb7\xc0\xfe\x09\xe3\xee\x95\x6d\x01\xf7\x5f\xe8\x1b\xdd\x88\x6d\x63\x24\x01\x46\x28\xed\x6b\x2a\x2f\xf9\x1e\xd0\x42\x15\xf8\x7a\xd8\x6e\xb9\x70\x44\x4e\x6a\x08\x39\x85\x65\x64\xf0\xea\x24\x9a\x82\x8f\xf8\x40\xfb\x95\xde\xe1\xea\xc9\x11\xad\xff\x2a\x59\x38\xc2\x0f\x77\xe3\x75\x49\xa2\x22\xf4\x12\x4b\x05\x7f\xba\xc1\x79\xc5\xe0\xa5\xb5\x3c\xf8\x2b\xfd\xe3\xdc\xbc\x40\x00\x69\x75\x42\x37\x8a\xa3\x5a\x0b\x79\x4a\xe8\x70\xf8\x68\x81\x32\x5e\x80\x1c\x17\x35\x26\xc4\x32\xd9\xeb\x9c\xd7\x78\xea\xf2\x22\x9b\x61\xf0\xbd\x13\x50\xe0\xc9\x52\x55\x53\x00\xe4\x54\x5b\x80\x39\x79\x9c\x28\x65\xb1\x16\x8a\x44\x83\x27\x60\xe9\x53\xed\xec\x99\x07\x4d\xa0\x58\xda\x6a\x21\xfd\xc6\x70\xbf\x59\x34\x86\xe3\xa1\x49\x49\x8e\x95\x53\x5b\xe5\x32\xae\x5b\x69\x60\x34\x4f\x93\x93\x37\x2c\xc0\x23\x0a\xa3\x2e\x94\xee\x41\x3c\x59\xc1\x6b\xbd\x28\xea\x7c\xbe\x33\x00\xfe\x10\x01\x72\x99\xfa\xe4\xad\x97\x87\x9f\x77\x34\x3b\x0e\x8f\x32\xef\x98\x9d\x9c\x08\xa9\xbc\x6f\xa1\x30\x79\xfb\xa8\x73\x6c\x74\x66\x93\x58\xee\xcb\x8c\x84\xd0\xd4\x51\x33\x8b\xdb\xbf\x09\x74\x8f\x92\xec\xd2\x78\x4f\x8b\x50\xa7\xd0\xb1\xa1\x3b\xf3\x14\xfa\xc9\xe1\x64\xb8\xc5\xb5\x09\xb3\x37\xa1\xa0\x60\x27\x0b\x8b\x37\xed\x6e\x4c\x85\x62\xcd\xdd\x12\x02\x8d\xe6\x35\x0d\x62\x13\xf4\x1e\x57\x26\x8a\x27\x5f\x54\xc6\xb9\x20\xf2\x84\x00\xfc\xb9\xfb\xc5\xe7\x83\x29\x63\x77\xbe\xb9\xa4\xf4\x4a\xd7\xd2\x5d\xed\x98\x99\x64\xbe\x11\xb6\xc6\xb7\xb4\x26\x04\xcd\x49\x4a\x61\x80\x89\xf0\xac\x48\xcd\x92\xef\xac\xb3\xa1\x7b\xe0\xa0\xc1\xca\x8b\xcf\x02\xe6\x31\xe9\x3a\xec\x86\x29\xa5\x82\x47\x2a\x45\xf1\x7a\xf9\x7d\x7b\x5b\x08\x48\xaa\x4d\x3d\xd2\x4b\xf7\xc9\xc6\x37\x0e\xf9\x21\xbd\x1d\x8b\x8e\xe4\x28\x00\xa2\x42\x0b\x5c\xfa\x11\x9b\x51\x33\x99\x9c\x2d\xa3\x02\xeb\x4f\x27\x1b\xb3\xf9\x0c\x7a\x5a\x7c\x8b\xa3\x44\xfa\x1d\x42\xe0\x94\x00\x8b\x5a\x03\xb7\xb4\xd1\xdb\xb7\x0e\xa8\x40\x84\xba\xa8\x27\xb2\x2e\xce\x63\x1c\x7c\x0a\x37\xac\xe3\x25\x15\xee\x81\x5b\x7a\x0a\xca\xc8\xa9\x9c\xd8\x37\xcf\xd6\x2b\x0c\x33\x11\xef\x55\x25\x3a\x7e\xfe\xbc\xf9\x7f\x54\x4b\x65\x54\x8d\xf7\x02\x91\x6d\xd1\x2f\x6e\x56\xbe\x71\x09\x37\x56\x7d\x5e\x1d\x18\xb1\x26\xe1\x5f\xba\xcf\x4c\x10\x7b\x77\x09\xcf\x53\xff\x90\xbf\x43\x80\x93\x2f\xff\x46\xee\x1d\xc7\x82\xc8\xd4\x30\xd4\x15\x9a\xbe\x74\xfd\xba\x0a\xc1\x0c\x16\xff\x9b\xaf\x1f\xff\x86\x1e\x63\x63\xb3\xd9\x74\xb5\x69\x64\x44\x50\x07\x3d\x3e\x83\xb9\xd9\x8c\x39\xa9\xea\xd6\x18\x3a\x52\x1f\x65\xce\x24\x1c\x34\x56\xcc\x51\x63\x70\xa8\x6c\x3f\xcc\x83\x46\xf7\xc1\x35\xec\xf7\x9e\x07\x2a\x34\xa9\xd5\xd8\x1b\x93\x25\x10\x70\x3c\x50\x54\x83\x8d\xcb\xf9\xa9\x5e\x25\x07\x68\x36\x1c\x06\x07\xfc\x8c\x63\x74\xd4\x71\x37\x8a\x77\xf0\xc0\xbc\x06\x56\xd6\x8c\x17\xae\xa2\xb6\x33\x51\xef\x82\xa6\x7b\xbc\x06\x61\x74\x80\x26\x51\x68\xe6\xb1\xdd\x4a\x82\x72\xbc\xbd\xc3\x3b\xc5\x8c\xdf\x9a\x3b\x40\x37\xc4\xc7\x56\xac\x65\x34\x1b\x51\xe5\x6e\x0d\xe9\xe8\xfe\x87\x86\xef\x52\xe6\xe8\xed\x1b\xec\x15\xc6\x51\x95\xa1\x7a\xde\x7e\x48\xa0\xc9\xe0\xd8\x9a\x49\x55\xeb\x8b\x5c\x05\x81\x4d\x9d\x4c\x8c\xf8\xcd\xf3\xee\xd4\xd6\x38\x72\x49\x30\xe6\xd1\xd9\x90\xee\x74\x1f\x3c\x67\x88\xc4\xb6\x0f\x29\x45\xf9\x4f\x59\xf4\x8d\x07\xb2\x0e\x8b\xda\x72\xd5\xd4\xe9\x9a\xcb\x8c\x3c\xb0\x8e\x4e\xc6\x8b\x85\x72\xd0\x08\xbd\x89\x56\x31\x3f\xf3\xcc\x42\x65\x71\x8c\x9d\x1b\xb7\xb6\xc4\x66\x76\x05\xd0\x03\x5f\xbf\xc8\xce\x7f\x3b\x41\x05\x10\xfc\xb7\xe5\x98\xbe\x7b\x40\x0e\xdf\x3f\x8f\x1f\x44\x51\x48\xdb\xbb\xf6\xe4\x9f\x9d\x92\x32\xa4\xe6\x20\x6b\xe2\x29\x58\x7e\x57\x54\xd9\x9d\x1a\x16\x8e\xf0\xc9\xce\xe9\xc0\x62\xd2\xc9\x01\x06\xc8\x87\x05\xed\xc1\x49\x70\x99\x35\xf8\x25\xe2\x81\x50\x03\x66\x2c\x80\x04\xe7\x43\x4d\xb5\x6f\xd3\xb5\xac\x19\xc7\xc4\x38\x40\x46\xfd\x45\x0e\xfb\x67\x10\x18\x27\xe0\x61\xcd\x2f\xa0\x6b\xa0\x41\xea\xd5\xff\x14\x9a\x16\x62\x67\xa4\xb3\x4a\x70\x3b\x05\x6f\xf1\x40\x48\xf1\x9f\xbc\xd6\xb2\x13\x80\x53\xef\x6d\x98\xe3\x8b\xa0\x9f\x70\x2d\x53\x0f\x79\xc7\x09\x27\xbd\x1d\xb5\xb4\xa9\x95\xa2\x3f\x0a\xed\x5b\x6f\x2e\x44\xaf\x0c\x98\x1b\x6e\x3c\xeb\x50\xb1\xed\x32\x91\x38\x0d\xf5\x69\xfb\x41\x6b\xdd\x69\x2c\x93\x4b\x3a\x93\x35\xcf\xf0\x8f\x2c\x49\x98\xef\x0d\x17\xf7\xed\xed\x0d\x49\x4f\x0c\x4b\x81\xd0\xc6\x65\xa6\xd0\xac\x23\x3d\x69\x53\xae\xb7\x42\xd5\x9c\xcc\x33\x21\x57\x7b\xee\xe5\xa4\xd6\x59\x63\x03\x4c\xc8\xd8\x29\x83\x70\xde\x4f\xc5\xe1\x8d\x85\x0c\x0b\x59\x70\x6e\x30\xd2\x1d\xea\x33\xc8\x59\x9a\x9e\x41\x2e\xeb\x95\xeb\x82\x90\xcf\xd7\xfb\xf3\x1d\x85\xb9\x53\x20\x2b\x1d\x99\xae\x58\x23\xf4\x34\xe3\x11\xfb\x3e\x09\xdb\xcd\xa8\xb3\x5d\x5e\x2c\xd9\xb6\xdb\x34\xb9\xd9\xe2\x14\x46\x4b\x79\xe5\x87\xce\x4b\x7e\xd2\x32\x2c\xe9\x6a\x07\x94\x51\xe4\x28\x1e\x06\xc5\xf7\x15\xdc\xd6\xc8\x9a\xa2\x89\x86\x2a\x44\x16\x7c\x88\x5e\xaf\x49\x4d\x93\x48\x30\xa2\x16\x41\xfb\x33\x33\xcc\xc0\x89\xb4\x21\xd2\x6d\xab\x5f\xac\x1c\x35\xe8\x78\xfd\x56\xd9\xf4\x1e\xbb\xee\x35\xde\x69\x11\x15\x98\x7b\x61\x88\x2a\x9d\x06\x2e\x4f\x48\x18\xf8\xa8\x5f\xca\xd8\x33\xef\x4f\xf8\x29\xc0\x32\xfe\x62\x79\x31\xc6\x0c\x39\x7a\xf8\x31\x05\x05\x73\x87\xdd\xf6\xae\x65\x66\xe0\x23\x81\xee\x68\xf3\x67\xa2\x6a\x20\xff\xbb\xcf\x18\xea\x59\x1c\x01\x90\x0a\x92\xb9\x3c\x44\xab\x34\x38\x20\x76\xd1\x66\x2b\x3c\x61\xf3\x56\x55\x1c\x30\x6c\xea\x9c\xd4\xb3\xa9\x9a\xbe\xd7\xfd\x74\xce\xe3\xc4\xd4\x8d\xeb\x54\x26\xde\x92\x50\x7b\x7e\x68\xf3\x09\x14\x35\xde\xe7\x4b\xea\xd1\x9c\x47\x91\xe7\xfb\x79\x2c\x6d\x11\x8e\x3d\x8f\xcc\x8a\xfa\xe0\x4f\x46\xf8\x4e\x3f\x8a\xbc\x9a\x7f\xd1\x38\x3c\x38\xee\x2d\x5f\x4c\x5c\x81\x0a\xce\x1a\x33\xb8\x7b\xbe\x90\x66\xbb\x61\x37\x8b\x17\x52\xcc\xcc\xb0\x4c\x38\x31\x16\x8b\xa1\x0c\x84\xb4\xa0\x18\x83\xae\xb1\x3b\x04\x0c\x8f\xa8\xf1\x2d\x44\x44\x28\x3a\x77\x8b\x2e\x3a\x20\x8c\x81\xdf\x68\x61\x82\x48\xe5\x39\x1c\x09\x15\x84\xdc\x25\xf1\x52\xa0\xb0\xe2\xcf\xbd\xfd\xb0\xaf\x72\x1f\x7c\x4f\x3f\x8e\xa5\xe0\xe2\x55\x2c\x22\x49\xa4\x48\xdd\x03\x64\xd7\x34\x28\xa9\xd4\x67\xde\x4d\x00\x9e\x38\x33\xba\x28\x27\xc8\xfc\xb3\x78\x47\x2d\xac\x84\x45\x8a\xfc\xa7\xc7\x95\xfa\x2e\xa9\xde\x95\x46\xb1\xd3\x45\x1d\xe8\x98\xa7\x96\xd5\x85\x1d\xa7\x1f\xa8\x55\x5a\x7c\x53\x08\xda\x58\x04\xfe\x40\xd0\xe7\xfb\xc3\x87\x64\x55\x42\x8d\x93\x3e\xe7\xb4\x6f\x75\x16\xdd\xeb\xaa\xca\x6f\x7a\x30\xc9\x69\x67\x13\x1a\x33\x0b\x98\xe1\x7e\x3c\x75\x74\x49\x32\xec\x2d\xc4\x7b\xda\x37\xf3\x50\x2a\xb4\x29\xd6\x60\x59\xbc\x9a\x36\x8c\x64\xce\xdb\xb2\x9a\x6f\x37\xcf\x04\x54\x6c\x6e\x13\xd6\x07\xf7\xe1\xe4\x2a\x33\x73\x3e\xb5\x23\x9a\xfc\x57\x7d\xde\x0a\x8f\xe8\xe6\x94\xb7\xd8\xec\xf5\xc2\xd1\xd1\x76\x10\x35\x9b\x21\x5f\xe8\xc5\xc5\x45\xb3\x1a\xb6\x45\xf8\xd2\xa5\x55\xf4\x71\xc9\x1a\x0d\x34\xe6\xe2\x6a\x30\x48\xbd\xfe\xa5\x1b\xc4\xc9\xe9\x9b\xfb\x37\xd7\xd0\xab\x18\x17\xc2\x87\xc1\x51\x82\x03\xed\xdc\x1d\xa4\xed\x76\x39\x11\x0e\x4b\xb8\xaf\xf7\x6f\xff\xae\x50\x51\x7e\xbc\x1a\x8c\x38\x89\xcb\x8d\xb4\x5a\x03\x1a\xa6\xfc\x06\x50\x83\x33\x8f\x6e\xb2\x79\xae\x44\xca\x86\xea\xbf\x79\xb5\xbe\x8f\xa5\x8d\xbc\xf7\xe2\x05\xb7\x3c\x10\x88\xdd\x84\xa1\x63\xa7\xad\x9d\xdc\xd2\x9d\x70\x1a\x5e\x61\x9b\x45\xa1\x33\xb3\xe2\xcb\xa6\x2d\x63\x06\xdc\x11\x6e\x1a\x8d\xb2\x5f\x8f\x91\x7a\xd6\xb1\xd7\x75\xbe\xb9\x0d\x22\x6c\x51\x90\xdf\x51\x6a\xc2\x93\xa2\x60\x58\xbe\xd6\x13\x3b\x4e\x1a\x4d\x2a\xf5\xb1\x1f\xd8\x49\x37\x6e\xe4\x7b\x00\x07\x17\xf2\xaa\x51\x33\x85\x1b\x26\xee\xba\x7e\xbb\x69\x6e\x52\x21\x7b\xae\x3d\xf6\xc4\xee\x68\x9f\xfd\x3c\x01\x62\xc3\x62\x92\x4f\x7e\xe5\x91\xba\x58\x80\x47\x0f\x78\xaa\x99\x21\x8a\x37\xb5\x51\x5f\x3d\x65\x88\xd6\x04\xf8\xf0\xac\x96\xfe\xb2\xd1\x7d\xb9\xc4\x42\x7f\x95\x5b\x67\x77\xac\x90\xbd\x23\x21\x82\xab\xb5\x5c\x97\x19\x95\x65\xbc\x0d\xed\xb5\x77\x3d\xb2\x89\x08\x85\x0f\x76\xea\xf4\xda\xe9\x73\x8e\x9a\x7a\x92\xda\x32\x8d\xe4\xc4\x53\x7d\x38\xbe\x7d\x21\x77\xe1\x59\x1f\x9e\xdf\xc8\xe6\x45\xef\x0f\x58\x90\xaf\x73\xba\xf9\xb5\x52\x55\x10\x56\x16\x58\x26\x3e\xf0\xbe\x04\x24\x7e\xbf\x3e\x3f\x35\xae\x1c\x5c\x39\xd8\x6a\xe7\xc1\xd6\x70\x53\xd3\x06\x2c\x43\x3a\xcd\x83\x6c\x1d\xd8\xc4\xb8\x65\x16\x05\xab\xa6\x52\x86\x78\x74\x66\x72\x35\xa2\xc5\x79\xd6\x98\xac\x18\x25\xc3\x8d\xda\x59\xca\x90\x8b\xd9\xe7\x34\x96\x30\x6d\x64\x7f\x2e\xa8\xba\xde\x21\x2e\xca\x0e\xd9\x7e\x0a\x30\xb7\x14\x0d\x6a\xfe\x76\x14\x9f\x86\x3b\x9c\x50\xf7\xed\xc8\xe4\xd5\xef\xd7\xbb\x46\xde\x34\x91\x32\xd8\xa4\x85\x30\x4f\xaf\x95\x90\xca\x15\xac\xf0\xd7\x44\x31\xd9\x56\x72\xc7\x08\xc8\x1b\x07\x33\x4d\xdf\x90\x8b\x42\xe2\xea\x4d\xc7\xb4\x4e\xce\xf9\xa5\x82\xc9\x83\xc6\x15\xad\x2a\xd8\xaf\xc0\x96\x98\x73\xb8\xc4\x33\xdb\x85\x4d\x42\x3e\xf8\x03\xf5\x74\x02\x55\xdd\x74\x9f\x03\x69\xea\xe3\x20\x12\xb1\xd5\x7c\x3e\x06\xb1\xea\x45\x61\xd0\x56\x9a\x27\xdc\x7f\x25\xd1\x4a\x57\xf4\xdd\x18\x54\x51\x77\xe6\x21\x82\xc1\x2d\x0a\x68\xd7\x7d\x6b\x2b\x4e\x85\x2f\x39\xc5\x34\x9e\xd1\x75\xcc\xfa\x32\x6f\xc3\x79\x58\x88\x78\xd8\xcc\x79\x23\x41\x80\x79\x6c\x0d\x16\xf5\xc0\x66\x8f\xc3\x1b\x3a\x6a\x1c\x1c\xac\x83\x1e\x9e\xeb\xbd\x65\x0b\xcb\xc2\x03\x15\xc4\x1f\xe6\x52\xc6\x8a\xa3\x9a\x0f\xbf\x7f\x70\xeb\xde\x75\x12\x58\xac\xb7\x73\x42\xa8\x83\x63\x18\x45\x34\xee\xc5\x4c\xa2\xfc\xcb\x6e\x7b\xee\x31\x11\x56\xec\x98\x44\xa0\xae\x93\x85\x8a\x78\x44\x02\xd7\x40\xb7\xdd\x2d\x2f\xd9\xa2\xc3\x8d\xf3\x60\xb6\xe5\x35\x7f\xab\xb1\xc0\x85\x40\x17\x67\x0e\x25\xf0\xce\xb3\x41\xa3\xb2\xf9\x6a\x43\xce\xb9\x64\xe7\x45\xae\x6e\xce\x48\x1e\x68\x7a\x23\x66\x65\x16\x1c\xb2\xf8\x14\x31\x73\x53\xcd\x69\xde\xe2\x7f\x5b\xe9\x96\x9f\x4e\x1a\xd4\x1b\x06\x71\xe3\x79\xcf\xd8\x46\xb9\xa8\x6b\x65\xd3\x3c\xcf\xc0\x74\xa4\x8f\x9a\x44\x25\xc6\x79\x0e\x68\x67\x92\x0f\x67\xc3\xf8\xb6\xd4\xa9\x49\xca\x45\x05\xbe\x7b\x0d\xa5\xdb\xea\xa9\x77\xa6\xd8\x7c\xdc\x2a\x6b\xdc\x00\xf4\xf9\x1b\x3f\x3c\xc8\x83\x6e\x7e\x0c\xee\x38\x23\xca\xdc\x27\x1d\xd7\x4d\x95\x6b\xf7\x57\xa8\xc2\xdf\xd3\xfc\xfd\x75\x81\xb3\xe8\xa0\x25\x16\x0f\x86\x6e\x81\xbc\x6c\xde\x89\xe8\x32\xb9\x25\x55\x2d\x21\x60\x15\xcc\x4a\x2f\xe8\x78\xd2\xa4\x23\x4f\x58\x9f\xf7\x50\x1e\xd2\x96\x3b\xf9\x93\x90\x75\xed\xc4\x05\xf4\xca\x8f\x05\xa4\xee\xa3\x1c\x0e\xf0\xe4\xed\xb8\x73\x2a\x60\x71\x4c\x2a\x32\x8e\x51\x53\x7a\xc7\x3b\xe1\xab\x40\x17\xe2\xc1\x2c\x7a\xbc\xa5\x2d\xa5\xda\xec\xcc\xd7\xd8\xf8\xef\x6f\xf4\x0d\x7c\xfc\x52\x65\x9a\x67\x32\x15\x5a\x25\x31\x87\xf8\xfc\x1d\xa6\xc4\x4e\xa5\xc1\xff\xe4\x2a\xf2\xc5\x42\x4a\x45\x64\x9a\x6c\x54\xf3\xf5\x48\xc2\x4c\x32\x45\x16\x27\x45\x29\x9b\xf6\xac\x17\x12\xc9\x43\x68\x7b\x1c\xb9\x3a\xbf\xbf\x85\x25\x3c\xd4\x8d\x3a\x7b\x1c\x93\x26\x9e\xc1\x17\xe1\xb8\x85\xa2\x9b\x32\xd9\x37\x91\x7b\x0f\xb9\x9b\x42\xd1\x46\x15\x33\xb5\x67\x08\xed\xc5\xf9\xa8\x58\x7a\x06\x15\xf1\x42\x6d\xc4\xa8\x6f\xb4\x0f\x7f\xaa\xa3\x27\x8f\x54\xb7\x8e\xe3\xd1\x24\x58\x65\x94\x8e\x1c\x06\xc9\x12\xdf\xab\x2e\x0c\x60\x0b\xcc\x28\xa2\x0b\x09\x20\xb1\x1e\x5b\x2c\x8c\xbd\xa7\xb2\xb4\xab\xf7\xe0\x90\x13\xcd\xe4\x81\x7d\xa7\x28\x0b\x12\xf1\x38\xce\x7e\xf4\x20\x3d\xa3\x5a\xf9\x36\xf3\xeb\x09\x53\x8e\x27\x96\x7c\xcd\xd8\xb5\x98\x05\x84\x47\x51\xb4\x07\x9d\xda\xc1\x0a\x35\xaa\xa4\xcf\x14\x94\x48\xb3\x0e\xb8\xf4\x03\x41\x6a\xa6\xa6\x50\xf8\x38\x32\x19\x1d\xea\xd7\xac\xff\xb0\xd4\xa1\xcd\x32\x82\xdc\xcd\xaf\x0f\xff\xae\xe4\xbd\x6a\xa2\x97\xcf\xbe\xa7\x3c\xbc\xba\x2d\xfc\xc4\xf8\x90\xe3\x8a\x60\x8e\x95\xdb\x5f\x7a\x02\xc0\x47\x0b\xed\xa2\x0c\x83\x3b\xad\x1a\xe9\xa3\x99\x6a\xb9\x5e\xcb\xa4\x34\x27\x1c\xc1\xdd\x7b\x64\xcf\x2c\x58\x48\xea\xbe\xf7\xa1\xa8\x13\x1b\xcd\x1b\x1f\x06\x0b\x5f\xb5\x31\x97\x98\xc4\x2c\x8d\x29\x2a\xc0\x5c\xea\x5c\x12\xb5\xbd\xf9\xc3\x24\x40\xf7\x86\x74\xfc\x15\xc6\x55\xa1\xee\x11\x2f\x3e\x59\xa6\xa2\x9d\x62\xcf\x53\x94\x8c\xdf\xc2\xa6\x1e\xf2\x9b\x85\x9e\x2c\x45\x1f\xa8\xab\x0f\xcc\x64\xf8\x98\x62\x8d\x2a\xae\x53\x60\xf0\x5a\x97\xf1\xa1\xde\xa1\xbc\x33\x46\x77\x16\x07\x9e\x3b\xb4\x57\xc2\xf1\x79\x64\x51\x26\x3e\x5c\x51\x45\x70\xe1\xaa\x83\x99\x19\xfe\x7d\x4e\x48\x7c\xae\xae\x21\x99\x2d\xf3\x2c\xd4\x85\xe9\xa2\xd5\x39\xc8\xd8\x4f\x36\x62\x04\x11\x6a\xcd\x0e\x9f\x15\x52\x72\x16\x60\x1d\x54\xa9\xb4\x89\x03\xdb\x2a\x9c\x4c\x93\xce\x94\x7d\x1a\xb3\x99\x79\xdc\x59\x75\x56\x2f\xc0\xd9\xc7\xb1\x31\x2f\x76\x4f\x63\xf9\x89\x27\xbc\x7d\x95\xb0\x1e\xbf\x7e\x22\xae\x0a\xe4\xd7\xa4\xec\xed\x1d\xa2\xf5\xc6\xd9\xd7\x47\xba\xcd\x47\x98\x45\x14\xab\xd9\x9e\xf8\x1a\xd8\xee\x61\x10\xe7\x05\x96\x81\x79\x85\xf3\x8c\x59\x0d\x2f\x06\x21\xa4\xb7\x90\xb8\xcb\x54\x37\x99\x3a\xd6\x7c\x16\xe2\x75\x3f\xbe\x99\x6c\x7e\xcd\x25\x01\x8b\x2b\xb3\xa9\x4b\x21\x0b\x75\x49\x2d\xf5\x07\xb8\x63\x1d\xd9\x16\xb5\x59\x8b\x73\x6b\x91\x3e\xd3\xbc\xaf\x9d\x18\x0a\x0b\xb9\xba\x02\x97\xcb\x24\x73\x6d\x85\x3f\x6d\xc9\x11\xa5\x94\x11\x3a\xec\xc1\x8d\x22\x4c\xe4\x89\x5e\x37\x66\x68\xa3\x90\x3b\x21\x13\x81\x44\xc1\x2e\x4e\xd3\xb1\xb0\xdc\xd5\x3e\x6b\x9a\xf0\xcf\xe1\xd1\x08\x72\xa4\x21\x49\x71\xb2\x7b\x68\x8a\x38\x96\x7e\x25\x73\x8f\x7c\xdf\x8e\xef\x2f\x76\xca\x5a\x73\xa1\x51\x4f\x82\x1e\x32\xc3\x45\xab\xfb\xb4\xd8\xfa\xcc\x73\x05\xc2\x21\x38\x96\x2c\x3b\xe0\x91\x43\x6d\x5a\xa2\xb3\x1d\x01\x4a\x8a\x48\x0d\x30\xc4\x7a\x0c\x65\x50\xb7\x89\xd7\xdf\x00\x48\xe6\xc6\x4d\xe1\x68\x16\xb9\xa9\xf9\x53\x6c\x36\xa6\x5c\x3d\xce\x45\x8f\xb3\xbd\x89\x80\xe7\x18\xa0\xb2\x52\xb6\x54\x36\x31\x07\xd6\xd6\x7a\x62\x88\xcd\xc8\x6a\x5e\x18\x54\x3a\xc7\x35\x24\xf2\xfb\xeb\x9b\x8e\xbb\xa0\x8c\xbe\xc5\x0a\xbf\x1c\xab\x67\x2f\x07\x3e\xc1\xb7\xf1\x20\xb7\xdc\x82\xa2\x6b\xe0\x0c\xc2\x39\x36\x99\xf3\x6f\x54\x9f\x73\xc2\x5a\x21\x0e\x9c\x04\x0c\x92\x61\x87\x74\xdb\x01\x21\xef\x9c\x8a\x06\x1b\x6e\x7e\x73\x26\x92\xc0\xd6\x03\x0b\x82\x24\x2f\x64\xa1\x77\x40\x3f\x9e\xb2\x78\x81\x01\x60\x9b\x56\xf5\xf2\xb9\x7e\x13\x96\xc9\xd4\x14\x9d\xda\x19\xdd\x62\x22\xbe\x1e\x92\x26\x60\x5e\x35\xec\x96\x38\xd6\x32\xdc\xaa\x4c\xfc\x89\x05\x6f\xd2\xdc\xf2\x8e\x7e\xe4\xe0\xc3\x86\x88\xf0\xcc\x85\xe1\x38\xfa\x78\x40\xfe\x9d\x37\xe1\xad\x0c\xff\x62\xeb\x63\x73\x2b\x06\xe2\x0c\xc5\xf3\xa5\xd0\x08\xe4\x55\x84\xbb\x2a\x83\x0b\x23\x46\xa9\x82\x13\xfb\xfb\xfd\xa3\x09\x93\x47\x22\x48\x39\xbd\x39\x15\x08\x7f\x61\x66\xbb\xa4\x9a\x5c\xf0\x0e\xea\xd7\x0c\xb4\x78\xa7\xe1\x9f\x87\xc4\x49\x32\x2f\x22\x6e\x74\x21\xe2\x75\x73\xe9\x28\x01\xcf\x07\x1d\xac\xcd\x1b\x5b\x39\xc9\xd6\xd1\xc5\x5a\x8e\xe8\xe4\x46\x6b\x94\x20\x11\x03\x77\x76\x86\x56\x9a\xbb\x67\x1b\x96\xfb\x37\x74\x51\xa3\x39\xb1\x57\xd0\xbb\x43\x03\x11\x0f\xc3\x89\x69\xa6\x54\xb4\x3f\x6e\xed\xb4\x2d\xde\x9b\x08\xb5\xda\x79\x98\x44\x02\x63\xcf\xa6\xdf\xb0\xe1\xe0\xd6\xf6\x57\xf8\xe4\x07\x52\xce\x04\x60\xc0\x9c\x4c\x34\xd4\x82\xe5\x3b\x88\xc6\x65\xa8\xc5\xd9\xee\xcc\x9d\x61\x2e\xde\xa4\x00\x0b\x81\x94\x8e\x2a\xd0\xe2\x03\xd9\x47\x21\xe3\x2c\xb0\x92\x8f\xdc\x66\x44\x2f\xde\x9a\x2a\x67\xa9\x2d\x90\x3f\xc0\x06\xe0\x41\x16\x38\xa4\xcf\x9e\xce\x1a\x6d\xde\xa5\x06\xae\xad\x3a\x3c\xb7\x1b\x29\x15\xf2\xb5\xb4\xff\x35\x5e\x9c\x8b\xc4\x0e\x5c\x4d\x40\x08\xea\x65\x0b\x97\x8a\xa6\xa5\x03\x14\xc8\xac\x7f\x48\xb8\xfb\xbc\x3b\xe6\x01\xc4\x74\x61\xfe\xd6\x8b\x0f\x72\xbb\x30\x34\xdc\x55\x3a\xe9\x73\x67\xea\x4b\x94\x99\x48\x40\x56\x68\x14\x68\x81\x07\x8a\x5d\x07\xae\xcc\xea\x7f\xca\xa8\xfb\xaf\xaa\x00\x4d\x60\x77\x6f\x61\xc6\xb7\x3f\x8c\x0a\x69\xc8\x8e\x8d\xf2\xff\x35\xd5\x0b\x6b\x3f\xb5\x08\x42\x4c\x62\xb6\xbe\x0d\x0f\x3f\x09\xaf\xbc\x20\xe6\x61\xa9\x87\x60\xaf\x9d\x38\x6d\x92\x64\xd6\x6a\x33\x59\x44\x5c\x80\x01\xc0\x6f\x7a\xce\x9b\xce\xb6\xbf\xa7\xb1\x94\x98\x3d\x0e\xe5\x36\x80\x7f\x00\x2e\x7e\xf4\x11\xb7\x84\x0a\x39\xd4\xb7\x4e\x6c\x94\xdd\xd6\x3d\x4b\x7a\xa7\x2c\x89\x55\xc0\xed\x69\xe0\x8d\xae\xdb\xa8\xc4\x9a\x0b\xb1\x9c\xe0\xf3\xfe\x4a\x5a\xc7\x61\xe1\xfc\x74\x54\x13\xe5\xf1\xd3\xa7\x42\x96\x02\x7a\xc3\x33\xc2\x2f\x12\xc7\xe9\x99\xf9\x9c\xed\xc9\xc4\x47\xdb\x23\x33\x31\x87\x61\x7c\x2e\xf9\x98\xa7\x01\x8d\xe9\x4a\xb5\xd1\x04\x48\x75\x2a\x9b\x6b\xaf\xf9\x78\x26\xb2\x85\xb6\xb5\x2b\x61\xd7\xb2\x4f\xc2\x09\xba\x8a\xe3\x38\x09\xdb\x6d\xaa\x46\xe7\x4b\x11\x67\x4a\x16\x78\x2a\x94\xea\xa0\x9d\xec\xd2\x33\x1b\x7c\x3e\x2e\x74\xa3\x05\xc2\x93\x26\x50\xe6\xf6\xa1\x31\x8b\x18\x72\x36\x88\xa5\x34\x4d\x85\xdf\xc7\xb5\xbe\x10\xfc\x26\x2c\x70\x38\xc4\xa1\xe5\xbd\xd4\xe2\x54\x64\x15\xea\x12\xd8\xab\xee\x6e\xbe\xba\xc8\x46\x76\x33\x11\xc4\x02\x39\x4a\x77\xc8\x3e\x32\x0e\x34\x9d\x30\xc3\xd0\xc0\xd7\xfc\x08\x82\x05\x39\xac\xa6\x62\xbe\xf1\xcc\xea\xaf\x73\xb9\xd2\xc3\x67\xdf\x0d\x9d\x39\x48\xa1\x66\x99\xba\xa5\xfd\x55\x4b\x10\x24\xeb\x61\x1f\x2a\xfa\xfd\x57\x81\xeb\xfd\xdd\xb9\x9e\x2b\xd4\x95\xb7\x07\x1e\xf8\x1c\x05\x56\x9a\x47\x95\x9c\x9d\xa0\x5c\x3e\x9b\x37\xb5\xd4\x64\x9b\xa6\x61\x5b\x7d\x49\xe8\x4c\x0f\x9a\x74\x36\xf7\x09\xdd\x62\xd5\x1f\x9e\xdc\xdf\x18\x88\x79\xda\xe4\xcc\x88\x82\xfd\x30\x6c\xdc\x8d\x3e\x47\x00\x6e\xf6\x10\x6e\xa2\x0d\xcb\x32\x40\x68\x4e\x62\x06\x29\x5b\xe0\x71\xa0\x04\xfa\x46\xc2\x43\xf3\x96\x19\x61\x2e\x9d\x7d\x47\x92\x79\x4d\xc5\x40\x81\x7b\x59\x58\x79\x87\xb2\x92\x94\xad\x7e\xc4\xfa\xa1\x4c\x77\xa1\x28\x6f\xc2\xc8\x5e\x24\x9f\xff\x47\x78\x88\xc5\xbb\x9c\x86\x71\x0a\x57\xef\x23\x8a\xa0\xae\x72\xb4\x1c\x98\x32\x3a\x13\xd7\x86\x3c\x66\xa7\x65\xa7\x8e\xf6\x11\x22\xe6\xaa\xc1\xd8\x7a\xa1\x58\xd3\xdf\x7d\x4a\x18\x51\x85\x6e\x6e\x13\x71\xc6\x3a\x47\x85\xc2\x0e\x9c\xc2\xfb\xc8\x71\x5a\xca\xae\x62\xc9\xec\x22\x68\xa5\x4c\x39\x2f\x91\x31\x85\xc9\x97\xe7\x16\x7e\x3f\x0f\xdf\xe8\xf0\x0d\x4d\xbf\x89\x2a\x87\xa1\x29\x30\x60\xae\x34\x1b\x2a\xdd\x45\x5d\xc2\x1e\x95\xf5\x4c\xfd\x3b\x69\x98\xd8\xdf\x5b\x8e\x23\x9c\xd2\xc8\x6e\xa9\xfa\x95\xae\xeb\xe3\x56\x78\xac\x9d\x6c\x89\xe7\xb2\xff\x8b\x32\xfb\xdd\x0e\x29\x8b\x35\x6e\xdf\xf6\x0d\x99\x9d\x4b\x54\x92\xd4\x84\xbb\x0c\xa9\xbb\x75\x3f\xf1\xfd\x76\x76\xc3\x9b\x5c\xd7\xd6\x00\x04\xa6\xe9\xaa\x5e\x95\x5f\x95\x33\xd5\x36\x8d\xb8\x44\x3d\xd1\xa5\x29\xbf\x8e\xd3\x39\x55\xaf\x9c\x5b\x85\x36\xf1\xa7\xc4\xfa\xa2\x5a\xf5\x16\x12\x7d\x70\x53\xbb\x83\xda\x75\xfb\x50\x68\x0a\xc7\x62\xf0\x87\x7d\xe1\xec\xc4\x7f\x7b\x0c\xc2\x54\xd0\x3c\x00\xca\x57\x40\xee\xf9\xa2\xee\x7a\x35\xd1\x9a\x60\xca\xc4\x33\xb5\xfb\x09\x7d\xe1\x51\xc1\xc0\xb4\xc1\xdd\x3f\xda\x96\xd8\xc3\x55\x6c\xe4\xc6\xb3\x6d\x3b\x47\x5c\x86\x19\x7f\x56\xf5\xde\x89\xd2\x64\x84\x56\x97\x91\x74\x01\x53\xdb\xe0\x02\x2c\x0f\xa1\x3d\x3f\xbf\xd1\x95\x50\x79\x22\xe4\x83\xa0\x5e\x9f\x1d\xb0\xbc\x4a\x6d\xff\xed\x4d\x87\x27\x09\x0b\xca\xc2\xed\x7a\xe3\x2a\xba\x10\xb2\x61\xbd\x0c\x81\x6e\xd9\x77\x66\x72\xa8\x54\xcf\xf4\x18\xe7\x9e\x41\xba\x98\xd6\x90\x83\xa3\xce\x0b\xa3\xb8\x7b\x8b\x17\xe8\x6f\xb3\xa9\x52\xce\x99\x9a\x76\x80\x34\x52\xb4\xd9\xe3\x72\x65\x9e\x4e\x9c\xde\x93\xb7\x37\x20\xf5\x33\xc5\x5d\x40\xae\xda\x19\xc0\x68\xcb\x4f\x18\x4b\xeb\xe3\xd1\x05\xfe\xf3\x05\x75\x0b\xd1\x3f\xe8\xda\xfa\x8c\xe2\x0b\x11\x70\x68\x12\x11\x3a\x74\x8b\x6c\x54\xf3\x3e\x07\xc4\x82\xf6\x27\xfe\xaf\x42\x33\xda\xe1\xc8\x2a\x9c\xe7\xe0\x14\x1c\x99\x0c\x9d\x88\x97\x7f\x04\xf3\x55\x69\x9f\x97\x44\xb1\xd8\x42\x1d\x56\xb5\x3f\xcd\xc0\x18\xbc\xff\xf8\x77\x05\x8a\x5b\xf1\x08\xc6\x29\x36\xa4\x71\xda\xc5\x99\x60\x46\xc4\x27\xc5\xe0\xb4\x86\xad\x3f\x11\x8c\x0e\xa6\x64\x19\x63\x3b\x46\x3d\x61\x54\x1b\x8b\xda\xa3\x58\xc9\x46\x69\xdc\xd1\xbc\x33\x35\x08\xed\xe6\x4c\x70\xd2\x92\xaa\x77\x4e\x33\x12\x45\x1e\x2b\x15\xe7\xd0\x2b\x66\xea\x9c\x72\xbc\xfa\x9f\x32\xe6\x1e\x11\xec\xb0\x65\xce\xc0\xa8\x31\xca\xbd\x02\x55\xda\x2d\xcd\xcc\xa2\xec\x7d\xa0\x8f\x84\x2f\x5a\xe8\x9e\x30\x50\x27\xe4\x21\x89\x9e\x93\x1a\xcd\x22\xc9\x70\x43\x8e\x77\xf9\x71\xe2\x47\x7f\xc1\xd7\x57\xa1\x97\x92\xf7\xf9\xb9\xdc\x1f\x33\x94\x27\xda\xe3\x0a\x97\x46\x71\xe3\x9c\x8f\x63\x79\x41\xea\x58\xb7\x3c\x05\xd5\xad\x4f\xed\xf8\x0d\x0f\xcd\x5c\x88\x70\x42\x77\x4b\xf7\xe2\x4f\x3b\xb9\x85\xc1\x31\x7d\x75\x41\x2d\x4b\x81\x81\x79\x0a\xe7\x46\x50\x5f\x8b\x8c\x03\x0d\x7e\x43\x77\xc7\x53\xfb\x4b\x2a\xf5\x08\x81\x78\xbd\xd5\x9b\x59\x66\x27\x47\xa5\x45\xb2\x28\xf3\x2a\x32\x78\x1f\x9e\xa8\x7c\xf0\x5c\xfc\x5d\x56\xb7\xbe\x71\x06\x12\xa9\x46\xbd\x25\x19\x1e\xbc\xd8\xc3\x38\xd9\x7b\x18\x0a\x53\x79\xf6\xf9\x65\x95\x86\x91\xc0\x4f\x08\x65\xa6\x08\x24\x7d\xa0\xd0\xfb\x54\x0f\x94\x8b\xea\xfd\x72\x09\x9a\xec\xb5\xa8\xa1\xdd\xab\x91\x61\xe7\x6f\x39\x83\xda\xd4\x36\xb3\x8f\x28\x76\x51\xfe\x55\x34\xb8\xca\xfd\x32\xa5\x48\x23\x76\x10\x5e\xfd\x17\x60\x8f\xa3\xb7\x00\xbc\xf3\x1c\xb0\x78\xe0\x07\xa2\x72\xb0\x01\x8b\x60\xf6\x61\x40\x2e\x61\x48\xcf\xa1\x9c\x8d\xcc\x5f\xc9\xa1\x7f\x38\x17\x1b\x0a\xde\x64\x20\x26\xd5\x26\x9d\xda\x45\x0c\x58\x7e\x92\x4e\xca\x52\x17\x06\x82\xad\x4c\x88\x58\x2f\xff\x71\x1b\xa8\xd0\x67\xce\x04\xc0\x3e\x38\x25\x06\x45\x63\x66\x66\xd7\x93\x8e\x9a\x52\xd6\x47\x64\x1a\x2a\xc1\x72\x59\x32\x29\x0c\x72\x43\x50\x0f\xb8\x57\xce\x7d\x11\xf6\x39\x15\xcc\xb8\x60\x25\x76\x5c\xe4\xc7\x1e\xd8\x5a\xea\x4a\x18\xc7\xda\xe1\x9e\xe4\x39\x22\x27\xf9\xbb\x1c\x5a\x02\x1b\x50\x9d\xf5\x85\xf3\xfa\x87\x4f\xb3\xe5\x43\x26\xd8\x5e\xa9\x47\x27\xac\xe3\x14\x9a\x02\xfc\x6e\x3c\xab\xcd\xae\x5d\x2f\x4e\xab\x4c\x82\x01\xe7\xa5\x64\xb2\xaa\xd4\xce\x11\xa9\xc4\xdb\x41\xe2\xdd\x68\xd1\x8a\x9e\xde\xde\xfe\xba\x97\x30\x44\xf2\x58\x89\x42\x68\xaf\x19\xae\x75\xcc\xfc\x78\x6f\x69\x62\x30\xda\xda\x6a\xb7\x54\xf3\x77\x62\xce\xf3\xe9\xb4\xf6\x64\x29\xf0\xe6\xed\x95\x0b\xd3\x84\xa5\x30\x4a\x4f\x1d\x01\x33\xc0\x9b\xad\x92\x7d\xc8\x7b\x36\x5d\x84\xf7\xd0\xb0\x01\x5f\x71\x61\xd8\x7c\x58\xc6\xc4\x19\x2b\xf6\x50\xfe\xc4\xd6\x5f\xc9\xe0\x0f\xde\xbc\x3b\xe3\x35\x07\x36\x94\xfe\x6d\x5a\x87\x3e\xc9\xda\x61\xfa\x1c\x7c\x87\xa1\x71\xba\x5f\xa6\x03\xf2\xc0\x7e\xbd\x0b\xea\xbf\xb8\xdc\x7d\x99\xfb\x12\x7d\x35\xec\x90\x48\xe6\xf6\xe3\xc1\x91\x44\xda\x2e\xe3\x55\xf1\x1b\x16\x25\x39\x99\xe3\x7c\x04\x2f\xaf\x61\x3f\x9e\x25\xe7\x8f\x01\xe3\x40\x68\x90\xcc\xee\xfd\xed\x8d\x1d\x00\xf7\x15\x65\x1b\x5b\xb2\xd7\xb8\xf1\x3b\xbb\x45\x0a\xf5\x27\xc9\x00\x62\x14\x51\xdf\x2c\x97\x56\x2d\x00\x48\x5a\x92\xd9\xc7\xe7\xca\x89\x01\xcb\x42\x95\xba\xa5\xdb\x10\xcb\xa4\x97\x7d\x92\xd9\x31\xeb\x59\x26\xd0\x38\xb9\x09\xf9\xd3\xe2\x76\x24\xf0\x67\xb1\x30\x35\x60\xbb\x3d\x19\x8d\x8c\xf9\xf1\x9d\xe5\xe2\xa3\xf2\x99\x24\x3d\x1a\x3e\x04\x53\xf1\xe2\x1c\x47\xf7\x87\xb5\xe3\xf5\x7e\xfc\xf8\x77\xe5\x7d\xcc\x68\x75\xf7\x39\x2f\x90\xbb\x8d\x55\x7a\xef\xa8\x4b\x6c\xe1\xb2\x98\x6c\x55\x47\x4b\xe3\x24\x34\x65\x8c\xa9\x22\xe5\x13\x28\x2d\xe1\x71\xf8\x64\x37\x56\x85\x5d\xff\x30\xf1\x45\xa5\x5c\xc1\xdf\x30\xe1\x81\x77\x99\xca\xc0\xcb\x2d\x7e\xec\xee\x0c\x10\xb2\x79\x82\x69\xf4\xcc\x3c\x4e\xb6\x73\x84\x11\x0c\xb9\xe4\x59\x94\x39\xf6\x66\xa5\x89\xc0\xa7\x42\x08\xa6\xeb\xbd\x02\x78\x40\xe6\x2e\xf3\x5e\xdb\x13\x87\xca\xa8\x7b\x86\xf8\x3c\x55\x63\xa6\xd2\x6d\x3a\xb0\x8c\xe3\xae\x05\x34\x58\x5c\x31\x83\x86\xde\x05\xfd\x6a\xe7\xda\x19\x33\x7b\xdb\x3f\xba\x1f\x64\x2c\xd2\x60\x31\x08\x40\x48\x18\x97\xab\x7e\x77\x74\x54\x39\x9c\xe7\x28\x1e\x0e\x45\xfe\x2a\xe1\x6d\xc3\xab\xe4\x12\xff\xe3\x81\x30\x9b\x6c\xce\x80\x6a\x1a\x0e\x49\x1d\x30\x10\x17\xcc\x2a\x1c\xe4\x5e\x0a\xd5\x1e\x8e\xdf\x98\x7d\x31\xe1\xf4\xed\xd2\x8c\xfd\x4d\x37\x2e\xd3\x63\xa2\xda\x2a\xab\x77\x1d\x80\x79\x77\xca\xba\xd0\xc8\x37\xb1\xc0\x20\x91\x82\x80\x19\x76\x8b\x88\x92\x62\x7f\x13\xcf\x96\x19\xac\xa1\x64\x54\x07\x8b\xf1\x6e\x24\x6a\xf6\x67\xfd\x1b\x0f\x0b\xdd\xc2\xb9\x54\xb1\xcf\xf9\xc1\x0a\xd6\xe8\x10\xdd\xd2\xe7\x32\x6d\x82\xac\x4e\x2f\xf8\xd8\xb4\x40\xdc\x17\x48\x41\x52\x69\x90\xe3\xf1\x0f\x8e\x18\x27\x74\xc6\x39\xaa\x90\x66\x35\xd5\x0c\x19\x27\x95\x80\xfd\xfe\x8d\xc2\xcd\x6c\x42\x28\x34\x1f\x80\x31\xc3\x18\x7b\xd2\xf2\xa0\xbf\x79\x10\x0e\xe8\x0f\x3b\x02\xbf\x2d\x66\xca\xc4\xf3\x77\x2b\x7b\x46\x3c\x5d\xc1\x0a\x7b\xef\xe3\xc3\x52\x19\x29\xa7\x3c\x15\x18\x34\x7d\x59\x7f\xd2\xa4\x81\x35\x1f\xb7\xdb\x95\xb5\x25\xf3\x24\xd4\x79\x00\x2e\x99\xa4\xe0\xd3\xd4\xf3\x8a\x04\xa4\x77\x75\x2c\xa4\x85\x34\xb3\x82\x23\x48\x96\x06\x14\x65\xc3\x28\xcc\xb4\x12\x92\x5e\x14\x18\x99\xb7\xbd\x87\xcb\x15\x4f\x99\x3d\x3a\x51\x7d\x4b\xfd\x98\xf5\xe5\x3f\x2c\x6b\xcb\x06\x1a\x2f\x1a\xd2\xcd\xfa\x57\x77\xc7\x2f\xf0\x35\xb9\x8e\x56\x6e\xf2\x39\x5f\x31\x8d\xe5\x4a\x2c\x92\x07\x82\xf8\x71\x93\x9f\xe0\xfd\xf2\xae\xae\x70\x78\x6e\x08\xe1\xa7\xed\xb3\x45\x25\xc4\x9c\x92\xe4\x1d\x2b\x78\xe8\xf4\xbd\x48\x43\x9a\xee\x56\xaf\xfd\xf8\xb8\xc8\xbb\x5c\x1e\x65\x76\xb1\x73\x50\xc2\x6b\x4f\xfe\x5d\xa9\x46\xc0\xe4\x74\x02\x53\x12\x6b\x5d\x5b\x99\xc7\xea\x25\x78\x9c\x3b\x4d\xbe\xbc\x84\x7e\x00\x85\xf0\x28\x36\xbe\x31\x3d\x09\x83\xbc\x21\xa3\xc9\x6a\x7c\x6b\x97\xc0\x11\xd9\xb6\x73\x70\x58\x50\x77\x38\x05\xd1\xe4\x0c\xe5\xf4\x89\xdb\xda\xce\x74\xad\x11\x8a\xbb\x2a\x21\x64\xc6\xa1\x25\xf0\x2d\xc4\xc3\xb7\x3f\x37\xee\xed\xfb\xed\x03\x99\xa9\xe7\xbe\x10\xf3\x55\x06\x16\xb2\x20\x91\x06\xcd\x69\x03\x8f\x85\xcb\xc6\xf1\xfb\xf7\x0f\xd2\xa7\xc8\xd3\x55\x0c\x94\xa1\x8f\x04\x24\x5a\x66\x4c\xaa\x88\xe5\xb9\xa7\x39\xb4\xf7\x7c\x08\xfb\xe7\xd8\x26\x32\xb2\xf9\xae\x94\x9e\x5a\xd3\x87\xa7\x21\x3f\x90\xb2\xea\x35\x64\x70\x2e\x33\xca\x7c\x56\x27\x0b\xcf\xde\x16\x78\x52\x57\xa0\xc7\xe2\x10\xf6\xcb\x7a\xab\xdb\x1d\xe7\x95\xa3\x31\xcd\x9e\x2c\x0c\x30\x18\xa6\xf3\xc8\xd1\x8c\xbc\xd1\xa8\xf0\xc0\xe9\x38\x1e\x80\x5b\x74\x02\x85\x40\x0f\xbc\x2e\xc4\x06\xee\x00\xc8\x2d\x41\xfd\x43\xa4\x97\x37\xa7\xd7\x80\xbc\x2f\xaf\x3a\xbe\x88\x46\x9c\x48\x4e\xd4\x36\xa5\x91\xde\xe1\x47\x70\x1a\x00\xfc\xf8\x47\x1f\x5e\x8d\xd7\x6d\x9f\x66\xf4\x8d\x22\x09\x5d\xa8\x3c\xcc\x66\x5c\xa4\x5a\x48\xb0\x35\xfb\x3c\xcb\x38\x48\xf4\x57\x62\x8a\x92\x85\x01\x40\x6c\x84\x2e\xa8\xd5\xa9\x31\x9d\x88\x1c\x43\x0b\x5c\x80\x3f\xb3\x9e\xea\xe5\x13\x04\x49\x0e\x24\x5c\x49\x23\x36\x79\xbb\x2d\xb2\x2f\x53\xd3\x7c\x7f\x90\xa9\xbc\x7e\x0d\x34\xa9\x67\xd9\x63\x13\x77\x31\x55\xd4\x25\x5d\xde\xc7\x07\xe3\x10\xcf\xc3\x96\xca\x6e\x1c\x65\x45\x7b\xb5\x55\x9b\x13\x36\x45\x4d\xfb\xb4\xed\xe6\x4a\xc4\x7b\x23\x36\xc5\xbb\x23\xc5\xcb\x19\x60\x34\x79\x4d\x4b\x97\xa8\xad\x2d\x0a\x69\xd9\xc8\xff\x9f\xba\x9e\x27\x04\xb1\x77\x28\xdd\x56\x18\xe3\x31\xdd\xcf\x23\x7a\x1c\x3c\xb3\xc9\xac\x5c\x3d\xde\xec\x5f\xa5\x09\xba\x2e\x8e\xb7\x7b\x73\xad\xa7\x22\xdd\x13\x8c\xc6\x66\x3e\x3f\xfb\x18\xc2\x65\x97\xe3\xf3\x10\x43\x57\xbc\xa6\x07\x24\x7b\x2c\xb9\x6a\xf7\x7f\x20\x90\xb1\xa0\xbe\x4c\x2e\xb6\x3c\x2a\x39\xfd\x70\xaf\x13\xc2\x29\xa9\xd9\x62\x89\x2d\x41\xa0\xef\x4f\x89\x2b\xd9\x59\xe4\x52\xc9\xa8\x74\x14\x8b\x73\x9c\xce\x1c\x3f\x6b\xb7\xbb\xd0\x4d\x5d\x9d\x02\x8e\x0f\xb7\x2d\x92\x42\xc0\x9c\x46\x64\x39\xd2\xe9\xe4\xc1\x63\x55\xe6\x91\x51\xa0\x59\xe7\x7d\x3b\x0a\x5b\x47\xb7\xdd\x4c\xa8\x8a\x2f\x48\x9c\x59\x18\x4e\x62\x65\x9f\x7f\xca\x71\xdf\xe0\x58\xa6\xc9\xc8\x9b\xcf\x3f\xa8\x10\xd8\xd6\x4b\x6a\x89\xa3\x93\xbb\x2f\xf8\x9e\x39\x05\x51\xca\xd4\x6b\x2c\x2c\xd6\x99\x61\x57\x24\x3d\x64\x8d\x62\x74\xe4\x01\x33\x30\x5d\x49\xd2\x2f\xaf\xea\x25\x78\xcb\xc1\x09\xe7\xd0\x59\xc4\x4b\x3e\x91\x95\xce\x5b\x7e\x28\xae\x98\xc3\x30\x96\x20\x29\x9c\x45\x39\xf9\x79\xbb\xfc\x03\x86\x39\x98\xf5\xd9\x5e\x54\xe7\xdc\xb9\x0d\x11\x37\x09\x02\x43\xe9\xfd\xdf\x57\x82\x7a\xfc\xf7\x8f\xeb\xde\xfd\xf3\xe7\xe6\xad\xcc\x91\xb1\xd8\x00\xd3\xab\x5e\x98\x6b\x90\xb6\xe2\x64\xa2\x3a\x4e\x00\x0e\x87\xa4\xc2\x74\x84\x6b\x38\x33\x0f\x5e\xd7\x81\x02\x96\xcc\xac\x00\x89\xd4\x2f\xa7\x27\xba\x04\xc0\x6b\x80\xaa\xcb\xb4\x10\xde\x49\x16\x6e\x7f\x80\x39\xdd\x6c\x90\xdd\x37\x15\x64\xd2\x73\x87\x2f\xa7\xca\xcc\xb1\xd2\x34\x0e\x9e\x8b\xc8\xb6\xba\x9b\x49\x21\x47\x93\x9a\x49\x18\x44\x22\xed\xb8\x2c\x08\xc0\x2f\xc8\x80\x0f\x9f\xbf\x07\x0c\x31\x3d\x14\x24\x89\xb7\xd8\xc9\x29\x43\x82\xab\x12\xb4\x9b\x8c\xca\x03\x73\xa0\xf7\x7f\x1d\x21\xf0\xce\x5d\xa7\x41\xd4\xcf\x08\x15\xe4\x28\xb9\xcc\x29\x13\xa9\x54\x54\xdf\x7f\x58\x8a\xc4\x90\x7a\x9c\x22\x66\xd7\x56\x4e\xdb\x61\x56\xdd\xc4\x7b\x66\xe9\x96\xb8\x40\xe0\x22\xf2\x44\x87\xd3\x01\x6a\x08\x2d\x2c\x56\x68\x15\x2a\x0f\x05\xed\x37\xbb\x40\xd1\x12\x64\xc2\xf6\xfd\x19\xe6\xe3\x91\xb9\xe4\x19\xf3\xc9\x7d\x15\x8c\x83\x7b\x5e\x78\xce\x09\x3a\xb8\x27\x9e\xbe\x0d\x1a\x66\x58\x86\xb5\xc4\xb9\x8c\xa3\x8d\x35\xc7\x24\x7b\xc6\x9d\x09\xf7\xd8\x32\xb7\x86\xb9\x2d\xc0\x14\x9e\x6f\xdf\x77\x7a\x65\xd0\x84\x3e\xbe\xe0\xeb\xe3\x9b\xe8\xe3\x23\xe9\xac\xba\xdb\x79\x7f\xd7\xb8\xe1\x87\x7a\xee\xbe\xeb\x2e\xfd\xf3\xfb\x11\x39\x39\x06\x69\xf9\x47\x7c\xac\xd3\xf3\x97\x67\x6a\x6a\x1f\xa2\x5e\xc0\x17\x53\xf2\xdb\xa9\x4c\x6f\x21\xe5\xf9\xa9\x10\x70\x9d\x80\xf4\x23\x76\x62\x52\x0f\x9d\x77\x14\x89\x29\xcc\x22\x93\xe7\x48\xf4\xc7\xc3\x14\x0a\x59\x25\x3a\x1a\x6c\x35\xb9\xe7\x38\xb6\x83\x7f\xb4\xed\xc4\xfb\x9d\x0d\x30\x8c\xc5\xbd\x26\x44\xf5\x8a\x74\x10\x9c\xac\xf0\xbc\xad\xf7\xd8\x6a\xe0\x10\x87\xf2\xfb\x74\xf7\x3b\x99\x5a\xa6\x8f\xe3\xbf\x33\xce\x47\xe9\xf6\x02\x03\x35\x73\x64\xd3\xde\xb2\x38\x30\xa5\xb1\x0d\x47\x48\xdb\x9e\xc4\x52\x89\x39\x71\xb5\x93\xc8\x70\x60\x93\x1f\x0e\x92\x35\xe6\x21\x75\xb4\x10\xa6\xc4\x07\xa2\xd8\x2e\x61\x91\x8b\x01\x36\x50\xe5\x40\x85\xec\x30\xb9\x68\x38\x6c\xe2\x56\x26\x04\xb9\x4f\xc4\x15\x49\x93\x83\x6e\x48\x12\x21\x7d\x24\x4e\x3c\x10\x18\xd0\x38\xdf\x1f\xdb\x69\x77\x1d\xf9\xb0\xff\x27\xee\xda\x2d\xc6\x7d\xbd\xf9\x6e\x3f\x1e\x9f\x4b\x7d\x42\xc7\x96\xcf\x98\x84\xd3\xf3\xf6\xf5\x85\xd9\x74\xa1\x57\xc4\x6b\x36\xba\x27\xec\xe0\xfd\x5d\x12\xf1\x9a\x9a\x26\xb6\x5e\xf3\x7f\x25\x17\x9a\x1d\xac\x84\x3c\x07\x79\xad\x2a\x17\xac\xf3\x99\x35\x35\xf5\xa3\x1e\x74\x1c\x3c\xbd\x81\x53\x03\xa6\x04\xd6\xec\x25\xea\xb6\x6f\xac\x6f\xce\x40\xdb\xb0\xd4\x69\xce\xd6\xb2\xc8\x61\xda\xc4\xd4\xb6\xf9\xe8\x43\x74\xea\xa6\x71\x16\xc4\xdf\x3e\xf5\xe3\xed\xfb\x1b\x0f\xed\xd5\xc4\x71\x93\xee\x61\xc6\xa3\x3b\x9d\xf6\x25\x79\x73\x4a\xa5\xce\x18\xa5\x67\x09\x59\x32\x9f\x09\x18\x85\x8f\xef\x9f\xdf\xaf\x77\x1e\x90\x77\x45\x26\x1a\x2c\xeb\x39\x7a\x28\x59\x6f\xe8\xc7\x33\xe6\x97\xf5\x0f\xec\x47\x6d\x16\xae\xb4\x5a\x86\x4d\x29\x59\xcc\x55\x3f\x54\xaa\x64\xf1\xd4\xfa\x73\x2f\x46\x9c\x9f\xd3\x63\xe6\x73\x2d\x3f\xe3\xfb\xfb\xe7\x07\x69\x42\xb7\x1e\x05\x03\x5e\x78\xa3\x4c\x7c\x82\x80\x94\x2d\x41\x10\x8d\xa3\xb6\xc9\x0f\x8e\x51\x95\x54\xf8\xe1\xac\x49\xc5\x05\x52\xb9\x14\x1e\xec\x52\x0b\x3b\xe2\x14\x92\xd6\xf2\xe4\x4c\x45\x64\xde\x3b\xc5\x38\x74\x2c\x23\x77\xa7\xfb\xbf\xfb\x17\x78\xe1\xd6\xb0\x72\x02\x9f\xd9\xb9\x33\x13\x71\xab\x7d\x26\xd1\x29\x43\x2d\xae\xb4\x76\xbf\x44\xff\x0f\x87\xf4\x36\xf5\xac\x30\x39\x77\x52\x4f\x1e\x24\xf3\xa7\x76\x72\xc7\xb9\x67\xa5\x91\x48\xa3\x2d\xaa\xce\x44\x30\x07\x3c\xd1\x02\xda\xe9\xe1\x18\x40\xaf\xa4\xc9\x65\x56\x37\x3d\x24\x64\x17\xc4\x88\xd5\x35\x14\xc9\x30\x52\xed\x50\xbd\x8a\x6f\xfe\x39\xff\x76\x3a\x9d\x6c\x25\xa6\x23\xe3\x53\x7b\x94\xdc\xb3\x0f\x2b\x48\x18\x27\x21\xa1\x7e\x89\x27\x51\x81\xb7\x26\x8f\xa4\xbb\xfd\x75\x3c\x42\x25\xf8\x32\x4d\xe6\xae\xa9\x9d\x93\x77\x6d\x71\x06\xd5\xa5\x04\xde\x35\xe6\xb3\xd0\x44\xe5\x8e\x43\x0a\x6a\x0e\xe4\xe8\xf7\x81\x2e\xe5\xa6\x9b\x8e\x02\x0f\xc5\xfb\x2c\x3e\xfe\x24\xc2\xe0\x4b\x83\xee\x26\x54\x4c\x38\x37\x09\x4a\x83\xbe\x96\x97\x4e\x4a\x69\x5f\xfd\x53\xb7\xf0\xef\xf6\x8e\xa0\x2a\x95\x39\xd2\xb7\xbe\xad\x37\x3c\xd5\x5f\x9e\x0f\x9c\xfc\xcf\x8f\xbd\x8b\xa0\x7e\x3a\x9c\x8a\xe9\x64\x7f\x9e\x29\x92\x85\x3e\x61\x3d\xec\xaa\xd6\xd7\x51\x29\x2b\x07\xc9\x2a\x51\x47\x72\x6b\xb0\x2c\xde\x17\x8d\x59\x56\xb7\xd4\xe6\x0d\x7a\xa4\x81\x58\xf7\xe5\xca\x4a\xb1\x45\xcd\x4c\x72\x6e\x25\x25\xff\x3e\xce\xcf\x0f\x3c\x60\xee\xe5\x5d\xdc\x24\x4e\x5e\x4e\x28\x93\x03\x81\x66\xf6\xb5\xdb\xe9\x42\xb6\xca\x67\xf3\x69\x78\x96\x3b\x14\x42\x95\x81\xeb\x53\x94\xf0\x7e\xa2\xa3\x7a\xb1\x26\xf1\x2f\xce\x85\xbb\x77\x03\xcc\x1d\x4a\x03\xcc\xc7\x88\xa8\x87\x92\xa0\x84\x4f\x4b\xb3\x70\x8e\x6d\xf2\xcc\x65\xa5\x69\x12\xcc\x8b\x3c\xdb\x40\x7a\x85\x11\x68\x0d\x8e\x76\x5a\x3a\x66\xf8\xc1\xa3\x03\xc9\x73\x4b\xab\x60\x4c\x60\xea\x0f\x36\x74\x98\xa3\xcb\xa8\x87\x80\x09\xd8\x9f\xb5\x3d\x75\x3d\x23\xb2\xb4\xbc\x14\x82\x4e\xac\xa3\xbe\x89\x25\xf8\xbe\x8f\x9f\x8b\xbb\x78\x5f\x24\x09\xf1\xa2\xb7\xe0\x4e\x76\xf8\xd9\x06\xe3\x89\xbe\x13\xed\xbf\x0f\x5c\xcf\x04\x9f\xf9\x14\xb3\xa4\x0e\xdd\x11\xc2\xcd\x3c\x1f\x8e\xef\x49\x84\xa6\xe8\x0e\x62\xc7\x6d\xd6\x94\x3c\x33\xa9\x0e\xac\x23\xaa\x02\xfa\x2e\xcf\x89\x41\xed\xe0\x23\xee\x78\xac\xaf\x24\x97\x30\xe9\x1f\x44\x61\x66\x2a\x9d\xdc\xd2\x76\x8f\x23\x46\x12\x1d\x79\x58\xbb\x95\x75\xac\xe5\xf8\xdb\x83\x95\xe4\x8a\x64\xcf\x0d\x8e\x7b\x12\x25\x5c\xa8\x1b\x3b\x7b\x5d\xf1\x53\xa9\xd7\x9b\x42\x43\x3e\xb9\xa4\x91\x54\xc2\x19\x15\xb4\x5c\x26\x89\x8f\xe1\x93\xbf\x36\x93\x81\x11\x69\xf1\xc6\x97\x4e\x7e\xd3\x04\x5f\x38\xdd\x93\xaa\xdc\x60\x1e\x15\xe4\x60\xd7\x69\x76\x5d\xad\x12\x0d\x39\xa4\xed\xcf\xe5\x94\xf4\xcb\xfb\x63\x43\xd6\xd1\x44\x45\xe4\x6d\xbd\x80\xc1\x65\xb2\x10\x4e\xaf\x48\xfa\xa2\x93\xc7\xa9\x91\x29\x8d\x17\xf8\x7e\x97\xa3\xf7\x7f\x57\xe8\x21\x9e\x0a\xb5\x61\xd4\x45\x78\x37\x0b\xef\xdf\x33\x0c\x4c\xee\xef\xa7\xc0\x40\xd2\x01\xe5\x00\xf4\x62\xa6\x29\xce\xf8\x02\xa6\xc1\x8a\xb1\xa3\x0a\x69\xc7\xe3\x37\x11\xc3\xaf\x69\x6c\xe6\x0b\x12\x51\x57\x0f\xaf\xd3\xad\x04\x21\x9c\x85\x82\x44\x71\xa6\x5b\x1e\x78\xfa\x8c\xe2\x31\xba\x39\x11\x30\x40\x9d\x3f\x9f\xdb\xf3\xf9\xcf\xd5\xd1\xf3\xee\xdf\xfe\x60\x1d\xcf\x47\x24\xbb\xf6\x88\xec\xe3\x76\xfc\xea\x26\x94\x56\x0b\xd3\x96\xc7\x00\xf4\x89\x6f\x39\xc3\x1d\xf8\x20\x1e\xfc\xe3\x08\xba\x02\x3b\x13\xbc\xfb\xf7\x9f\xf7\xb9\x3d\x5f\x07\x1e\x79\xb6\xf0\x78\xf6\x45\x65\x11\x73\xe9\x98\x94\x66\xcf\xb5\x0e\xbc\x8a\x66\x3e\xd0\x4c\xa0\x15\x73\x9d\xe8\x40\x88\x18\xce\x3c\x6a\x2a\x9f\xd9\xc7\x90\x32\xff\xbc\xb1\x47\xdb\xb7\xc1\xcc\x2a\xce\xe2\x60\xb6\x8b\x2a\x21\x4d\x3a\xc8\x43\x98\x0a\xd3\xcf\x52\x33\x20\xc1\x94\x08\xba\xb1\x76\xac\xc9\xea\x23\x20\x32\xfe\x2f\x0c\x3e\x2f\x0e\xce\x40\x1e\x56\x95\x81\x2c\x98\xb9\x07\xc6\x97\xde\xbc\xd9\xb0\x1d\xcc\x3d\x49\xb8\x0a\xe6\xba\xc5\xe7\x13\x28\x61\x33\xb6\xea\x40\xe8\x8a\xd6\xfd\xf9\x7a\x0f\x75\xb7\xa2\x81\x82\xdd\x9d\xdf\xbf\xfe\xed\x0b\x08\xc8\x7c\xe5\x44\x0f\xef\x04\xdc\x7f\x3c\xff\x05\x4c\x23\x2a\xc8\x82\xfe\x73\x1a\x19\xf2\x02\x30\x53\x31\xbb\x13\xe5\x40\x94\xac\x13\xca\xbb\x54\x0a\xf6\xd0\x7c\x0f\x25\x45\x69\x95\x98\x28\xc7\xda\xd8\x43\xc9\x3d\xa9\x26\xe1\xcc\xe8\x77\x16\x9a\x28\xc4\xb5\xb8\xdf\xc4\x17\x05\xe7\xf7\xfd\x7c\xe3\x50\xdc\xe9\x0c\x2c\xcc\x7e\x62\x3b\xab\x8f\x47\x29\xf4\xdb\x69\xe5\x92\x38\xda\x4b\x13\x33\x86\xc7\x58\x5a\xc0\x1b\x8a\x51\xf6\x04\x3f\x11\x5d\x2d\xb1\xcb\xee\x41\xac\xe4\x68\x79\x88\x51\xc2\x8e\x03\xe7\x40\x98\xfe\x67\x64\xc5\xfe\x63\x08\xc4\x76\x8a\xef\xf7\x3b\xda\x31\x6f\xf7\xf6\x13\x64\x36\xfb\x22\x70\xbb\x3b\x11\xa1\xcc\xea\x9e\x6d\x3d\xfc\xa3\xf6\xc7\x7d\x42\xca\x6e\x7b\xa8\x97\xda\x14\x54\x81\xf2\x91\x5d\xa0\xb4\x90\xd8\xbf\x8a\xd5\x33\xe8\xe2\x74\x4d\x03\xc9\x1d\x9a\x01\x8c\xfa\x70\x31\x7c\x12\x3c\xb2\x31\x1c\xe7\x88\xe7\x1e\x33\x85\xb9\x0d\xf3\x73\xff\x00\xdf\x13\x06\xc3\xd3\x43\x9d\x72\x99\xaf\x52\xd0\x93\xbd\xc6\xe5\xc5\xc1\xde\xb5\x1e\x58\xf0\x98\x3a\x25\x38\xc7\xbd\xbd\x7a\xfb\x5b\xc5\x18\x82\x4e\xd5\xfc\x93\xbf\x80\x12\xf7\x12\x55\xc7\x69\xe2\x5e\xc8\x0b\x2a\xb9\x7d\xb2\xe4\x46\x38\xf7\x90\x2f\xaa\x66\xb4\x91\xd5\xe3\x91\x68\xfe\x67\xce\x9a\xe3\xf2\xf8\x37\x74\xcb\x17\x53\xac\x3e\xc7\x54\xc3\x66\xbd\x39\x14\xc9\xd8\xdb\xd7\xfa\x38\x57\x04\xf2\x68\x40\x0a\xc6\x91\xe3\x18\xdf\x02\x27\x74\x7f\x7c\x38\x8d\x4c\x05\xf2\x0d\xc6\x56\xef\x3f\x6f\xcf\x81\xee\xce\xea\x1e\x10\x9b\xef\x5e\x4d\xcb\x40\xb6\x4d\x9c\x55\x9a\x1c\x1f\x46\x9b\x5f\x26\x46\x81\xce\xff\x22\xad\xa0\xa9\x34\xb3\x33\x24\x72\x12\x42\xbf\x10\x19\xb4\x95\x26\x05\xb3\x48\x1b\x7b\xa9\x5c\x9b\x43\x03\x98\x55\x61\xaf\x9e\x8f\xe8\xa4\x2e\xf0\xfe\x6d\xfc\x6a\x6a\x85\x86\x19\x5e\x0e\xd5\xe8\x67\x4a\xad\x7a\x4b\xd0\x6c\x76\x33\x75\x8c\x6f\x4c\x90\xdd\x2b\xfa\x1b\x76\x6f\x5a\x8e\x88\x0e\x52\x6c\x05\xb9\x98\x70\x06\xaa\x57\xc4\x00\x21\x7b\x3a\x4a\x01\x60\xec\xf0\x5c\x88\x99\xee\x0b\x64\x02\x23\x45\x35\x65\x73\x38\x75\x1b\xb9\x18\x6e\x1e\xe2\xc1\x46\x1d\xd7\xa1\x51\xab\x30\x4b\x29\x5f\x26\x38\xad\xeb\x26\x8f\x64\x44\x6c\x35\x89\x2c\x27\xac\x24\x44\x08\x4f\x70\x15\x93\xc7\xa7\x62\xcb\xa9\x7e\x33\x3c\xe6\x95\x8f\xe6\x28\x81\x3a\x15\x62\xd6\xd3\x10\xca\x9c\x77\x8c\x73\x26\x0c\xe6\x64\xee\xba\x43\x78\x2a\x40\xde\x35\x36\xf8\xf7\x39\xad\x1f\x55\x81\x83\x54\x2f\xa2\x20\x84\x21\x9e\x91\x62\x66\x3d\x9c\x4e\x9a\x14\x99\xbb\x91\x63\x29\x9d\x2d\x6d\x64\xa4\x83\x6e\x66\x61\xdf\xf2\xce\xde\x1c\x9f\x95\x4b\x9c\x84\xd7\xe4\x84\x1b\x6b\x31\xd8\x9c\x4e\x9f\xe2\xa5\x1c\x2e\xca\xb6\x0d\xfb\x69\xfb\xc0\x91\xdf\x08\xcf\x53\xd6\x70\x5b\x9c\x21\x08\xba\xe2\x6a\x87\xbc\x75\xdf\x04\x4d\x14\x15\x01\xf3\x0f\x98\xab\xed\xd1\xb0\xb6\x14\xfe\x93\x53\xcb\x53\x19\xd0\xeb\x89\x47\xae\x52\xb3\xbc\x12\x32\x0e\xd9\xeb\xd9\xde\xda\x16\x1e\x6b\xb1\xc0\xda\xa5\xaf\x9a\x72\xf8\x1b\xeb\x0b\xa9\x28\x16\xe8\x30\x0b\x38\xbc\xed\x9b\xd5\x76\x99\xab\x7a\x89\x1a\xa6\x50\x3b\x15\x29\xfa\xc9\x7c\x5c\xfe\x0c\xb5\xd2\xef\xa7\xf1\xdf\xad\x7a\xcd\x26\xa8\xc8\x9e\xce\x86\xf3\xe8\xa3\xdc\xc8\xfc\x1f\xb7\xeb\xed\xe6\x4b\x10\x6f\x8f\x1d\xef\xe1\x85\x2e\x7f\x57\x0b\xfc\x18\xfb\x5d\xd2\xca\x91\x9a\x97\x21\x84\x8d\xd3\xaa\x86\x32\x75\xee\x26\x34\xba\xbd\x61\xb3\x1e\xa0\x3e\x12\x49\xb6\x0f\x4e\x56\x26\xfe\x4a\x3b\x47\xc2\x23\xdf\xdf\x3f\xaf\x3f\x1c\x10\xd8\xf9\xeb\x1e\xb7\xeb\x7d\x46\x5e\x6e\xea\x6e\xd9\x55\x85\xb3\x95\xb2\x7c\x83\x46\xa7\x8a\x1c\xe3\x2e\x11\x0e\xa0\xbb\x05\x38\x05\x05\x6b\x6e\x4a\x81\xff\x2a\x64\xdc\x5c\x37\xb3\x59\x24\x2d\x13\x53\xb6\x5e\xe2\x81\x43\xba\xe6\x41\x94\x66\x62\x5e\x9f\x2f\xf7\x88\x9a\xd0\x9c\x86\x2c\xd0\x90\xf9\x50\x44\x1b\xed\x83\xff\x07\xe5\xa0\x29\x2f\xa9\xd9\x40\x3c\x02\xa3\x4f\x7e\xcf\x21\x8a\x8d\xe7\xb2\xd7\x2a\x38\xea\x4e\x51\x6c\xc1\xe3\x95\xa4\x3f\x8f\xf5\xeb\xe6\xb7\x89\x19\x8f\x28\xb8\xbe\xa2\x88\xb3\x68\xda\x1d\xfc\xb5\x91\xfb\x62\x29\x3c\xf1\x07\x72\xbd\xa8\x64\x2a\x3c\x40\x21\xcc\xae\x43\x2b\x6e\xc2\xb0\x6e\x3d\x0e\x5c\xd8\x95\x8b\x06\x8d\xa0\x02\x76\xd1\x7a\x7e\x1d\xbe\x7e\x91\xc9\xf8\xfc\x9e\x66\xf0\xa3\x7d\x7e\xfd\xeb\xef\xa8\x84\x8e\xd3\x35\x92\x27\x6d\x1b\xf6\xeb\x82\xaa\xf4\xe9\xdf\xe5\xf6\x39\x56\xa5\xc9\x57\x44\x2e\x7e\xcc\x99\xa1\xb3\xd3\x36\x11\x4a\x26\xc4\x61\x67\xae\x03\x5b\x81\x6b\x5d\x61\x97\xbb\x32\x18\x0a\x25\x54\xe5\x7b\x0a\x05\xf7\x92\x6f\x65\x24\xba\x1a\x75\x56\x8b\x81\x36\x3d\x20\x22\x1e\xa3\x53\x99\x63\x18\x73\x4f\x2d\xe0\x28\x03\x5c\x62\xab\x86\xe0\xc2\x81\x4d\x44\xe4\x92\x4a\xf7\xd9\xfb\xed\x1f\x92\xb1\xde\xc3\x3e\x90\x24\x29\x4f\xa2\xb2\xf6\x7c\x20\x67\x82\xf8\xe0\xbe\x24\xf7\x61\xea\x34\x66\xd7\x87\xa2\x8b\x60\x76\x5d\x81\xfe\x58\x1c\x02\x2d\x62\xd9\x3b\x7b\x8d\xc8\xa2\xc8\xf8\xca\xdf\x8f\xc3\xaf\x9c\x6f\xa2\x25\x3a\xb3\xd9\xbd\xc5\x6b\x61\x49\x6a\xe0\x14\xee\xf1\xa1\xa9\xac\xd3\xff\xcd\xd4\x95\x6c\xa9\xae\x04\xc7\xbd\xff\xc2\x2c\xbd\x6a\x66\x58\xf9\x4b\xbc\xd0\x50\x12\x42\x13\x68\x44\x9c\xe3\x7f\x77\x46\x44\x16\xd7\xef\xbe\x3e\x57\x07\xba\x6f\x83\xa8\xca\xca\x8c\x8c\x8c\xb0\x7d\xeb\x17\x11\x16\x88\x23\x12\x69\xff\xf3\xf5\xb7\x85\xcc\x6e\x22\x38\x87\x8d\xd2\xfd\x47\xf5\x78\x06\xcb\x06\x79\xe9\x85\x61\x50\x51\x11\x90\xeb\xab\x0a\xb1\xc5\xc7\x9b\x14\x6c\x29\x33\x6e\xdb\x49\x3a\x38\x49\x5c\x62\xb4\xfb\xf8\x7d\xdc\xef\x98\x5e\x57\x2b\x4e\xd0\x3c\x8b\xfa\x00\xb2\x22\x35\x86\xb0\xd3\xc9\xc5\x64\x73\x56\x88\xc6\x1a\x2c\xdd\xe1\xd4\x3a\x04\x30\x99\x4d\xc8\x00\x8b\x1d\x62\x97\xa5\xfb\x4f\x3e\x5f\xbb\xfb\x46\x6a\xb9\x74\x74\x53\xcd\x25\xe3\x18\xdc\x46\x65\xeb\x25\x3f\xb8\x59\xbc\x96\x45\xc7\xe7\x70\xaa\x6a\xbc\xcd\xbf\xcb\x31\xdf\x9e\x1c\x87\xa4\x06\x0b\x85\x7a\xbe\x53\x5b\x64\x6f\x45\x86\x97\xcc\x0d\x27\x28\x40\x72\xfd\x6c\x6d\xbf\xde\x76\xde\xd0\x65\x72\x63\x9f\xeb\x89\x86\x5b\x2e\xbd\x48\xfa\xb0\xb7\x73\xb9\xd2\xba\xc4\x95\xa8\xfa\x62\xf2\x64\x01\xd0\x64\xc8\x75\x22\x91\xed\xee\xba\x61\x40\xdf\x33\x57\x87\xe8\x5c\x6f\x27\xf1\x59\x99\xca\x15\x06\xe6\x27\x1b\xb5\x90\x5a\xe2\xcf\x3f\x31\x57\xa4\x0d\x1f\x19\x59\xb4\x5f\xfa\x8d\x63\x0b\xa5\xea\xed\x54\xcf\x23\x14\xe9\x69\xb4\x85\x86\x35\x3a\xd2\xbd\xe7\x2a\x28\x46\x2c\x80\x45\x1c\xa1\xf4\x16\x98\x5a\xbd\x4c\xc3\x12\x0d\x31\x22\xa9\x60\x64\x68\x5e\xe2\xa0\x27\x76\xf6\x55\xaa\x9f\x68\xf1\xe2\xfa\xa3\x18\xb1\x12\x8d\xa2\x71\xaf\x3a\xc0\x8b\x95\x5a\x41\x57\x3b\x27\x37\xc4\x58\x94\x17\x3b\x21\xfd\x3b\xb9\x60\xee\xe4\x91\xb8\xa3\xaa\x4c\x54\x9c\x28\x96\xfc\xa9\x0a\x05\x5d\x34\xa7\xb4\x96\x89\x73\x4d\x64\x06\xcd\xf8\x60\xeb\xdf\x9b\x99\x65\xf3\x9b\xf3\x8e\x2a\x2a\x1a\x81\xd4\xb0\xa1\xc5\x8c\xde\x69\xd3\x10\xa6\x90\x8f\x2b\xfc\x31\x24\xd5\xd4\x53\x04\xde\xe7\x41\x74\x2a\x42\xf2\xf4\x23\xb4\x37\xb3\xe4\x4f\x95\xdd\xec\xb2\x01\xc0\x2b\xb6\x88\x24\x3a\xb6\x6f\xe7\xb6\xc8\x28\xa4\x86\x7e\x99\x74\xcd\xaf\xae\x68\xa9\x14\x02\x0e\x12\x3f\xef\xc1\x03\xd3\x7d\xb4\xf0\x48\x6a\x7e\xf4\x8c\x4a\xb2\x66\x3c\x90\x9e\x95\x58\xa9\xc1\x5e\x9b\xa5\x4a\x73\xc3\xae\x58\xe2\x81\x39\xeb\x91\xc1\x30\x3f\x80\x1b\x2f\xcb\xaf\xf7\xa1\x7e\xe1\xe7\xf2\x4b\x7f\x7b\x11\xb7\xd9\x40\x87\x91\x77\xa0\x95\xaa\x59\x4c\x18\xdc\x89\x31\xc3\x40\xd7\xe8\x4f\xe2\x8b\x97\xa3\x6c\xb9\xdb\x6f\x78\xb1\xd1\xd7\x6e\x2e\x8b\xd6\x61\x3c\x91\x7b\xaf\x8f\xa2\xb4\x68\x4d\x44\x51\x33\xbd\xae\x74\xea\x9e\x2c\xaa\x88\x68\x44\x6d\x51\xdb\x33\xa1\xa1\x41\x8d\xfd\x46\x4a\x33\x86\xd5\x6e\x25\x71\x48\xd8\xf6\x08\x76\xad\x7b\x32\x39\xea\xee\x67\x02\x09\x66\xd5\x43\x51\x05\x74\xdd\x2e\xf6\xbf\x15\x5d\x62\xaf\xc3\x52\x72\x2d\x3f\x1c\x03\x70\x3d\xe7\xa5\x67\x85\x20\x83\x88\x5d\xbd\x60\x3a\x9a\xb9\x58\x4f\x40\x7b\xa9\x06\x69\x6e\xda\xc7\xfa\x3c\xb2\x79\x0e\x79\x06\x99\x72\xa1\x52\xa5\x50\x43\x03\x11\x73\xc2\x5c\xfb\x38\xdf\x7f\x90\xeb\x8d\x15\xf0\xfe\xf6\x52\x2a\x75\xf8\x30\x70\xe7\xe3\x37\x94\x47\xa5\x0a\xc0\x37\x79\x7f\x46\x04\xf7\xcf\xa0\xb1\x84\x7f\xa2\x50\xb4\xa2\x14\x09\x51\x29\xf8\x04\xe5\x22\x39\x41\x93\x77\x8e\xc7\x5c\x04\xc8\xb5\xd9\x8e\x57\xf2\xfa\x4e\xa7\xe8\x87\x72\xbc\xdc\xc2\xd3\x62\xf9\x4e\xc9\x89\x1a\x88\x9d\x3a\xf3\x5d\xe5\xa0\xa8\x3d\x92\x4c\xb1\x8f\x38\x08\x4f\x73\x9d\x62\x25\x57\xaf\x7a\x6a\x3f\x62\xdd\x5a\x81\xec\x66\x6a\xe1\x23\x8d\x00\x78\x96\x6b\xe5\xdf\x96\xf3\x91\x1a\x36\xfd\xbd\x3e\x3c\xd9\xf9\x81\x7c\xbf\x86\xbc\xed\x8a\xbe\x01\xa2\xd8\xf2\xb9\x79\xa0\xe6\xf6\x2e\x2a\x45\xb8\x31\x75\x1c\x0e\xd8\x9f\xae\x87\xf3\xcd\xf9\x8a\x64\xd9\x08\xd8\xdc\x3b\xbe\xf9\x77\xd7\x30\x36\xc9\x9b\x68\xe1\x8e\x02\xce\xa0\xbc\xa1\xb8\x24\x0f\x0f\x8e\x15\xc5\x51\x1f\x97\xfc\x4f\x13\xe8\x60\x05\x35\x4f\x9a\xb4\xe7\xd2\x8d\xac\x76\x4b\x7a\x92\x54\x59\x43\xd9\xbb\x6e\x26\x62\x96\xe6\x70\xe0\x7c\xe8\xa4\x6f\xb9\xbd\x30\x90\x5c\x2f\x97\xa1\x6c\xde\x24\xbb\x9f\xd9\x56\xbe\x9e\x8f\x6a\x1e\xdf\xf2\xea\x91\xe1\x5d\x5c\xee\x9a\x0c\xda\x91\x44\x79\xbd\x46\xcf\x57\xce\xf2\xd1\xee\xca\x1f\xa8\x7d\x8a\xc8\x0b\x16\x5b\x7a\x3e\xdb\x59\xfc\xe0\x71\x20\x22\xb2\xc8\xef\xf8\x9e\xf8\xf6\x60\x66\x2e\xea\x14\x6d\x99\xf7\x7e\x91\x46\x29\xda\x25\xec\x8f\x13\x45\xc0\x2c\xe1\x70\xc5\x2a\xb2\xd2\x84\x7c\x5b\x78\x9b\x34\xfa\x9a\xd9\x56\x94\xc9\xa6\xd5\x4d\x02\x6d\x5b\xaf\x84\xe0\x41\xe3\x4e\x16\xcc\x88\x98\xf8\xe2\xd2\xfb\xab\xfd\xe0\x53\x23\x30\x11\x71\x28\xb3\x75\xb9\xd4\x77\x77\x39\x1e\xd8\x77\xee\x81\x7a\xf0\x68\xfe\x49\x69\x20\x92\x9c\x1c\xef\xb1\x07\xe7\x4e\x0c\x9d\x25\x34\xfd\x3f\x41\x50\x7c\xc8\x6a\xa5\xcc\xc1\x8d\xe5\xc0\x54\xb3\x33\x81\x39\x6a\x9a\x08\xdb\xa1\x6f\x11\x4b\x4b\xbb\x23\x6a\x60\x11\xd3\xc0\x4b\xbd\xac\xdd\xe0\x64\xd0\x59\x5c\xab\x3c\x3c\x5e\x9b\xc8\xf6\xcb\x36\xca\x80\xa3\x7b\xbe\x33\x16\x2d\x9d\xd5\x57\x3e\x86\x12\x7d\xa0\x49\x2e\xee\x57\x7e\x9b\x25\x7a\x9d\x83\xbe\x78\x54\xd2\x6c\xe9\x1c\x0b\x28\xe0\xbc\x62\xfe\x54\x51\x6a\xce\x1b\xe8\xe0\x0c\xb8\x77\xea\x06\x7e\xc8\x4e\xc3\x51\x3e\x56\x8e\x4b\x09\x1b\x81\xfa\x16\xc8\xb3\x7b\x7c\xbf\xe1\x7e\xb8\x23\xee\xd2\x31\x4e\x5d\x5f\xcb\x39\x1f\xbc\x51\x18\x1a\xd3\x2b\x81\x2d\x2b\xb4\x1d\x70\x79\x7e\x15\xac\xa7\x42\xce\x6e\x49\xb0\xcf\xb5\x69\xbd\xed\xc3\xe9\x8a\x59\xf0\x4e\x28\x74\xf6\x58\x3d\xf6\x95\x65\x04\x38\x70\xb8\x61\x35\xda\xab\x3c\x27\x08\x0a\xab\x61\x3c\x5b\x5c\xdd\x4b\x07\xc9\x93\x6f\x3b\xda\x85\xb4\x23\x06\xa3\x37\xbb\x93\xb0\xba\x0f\xec\xac\x7f\x7f\x13\xcd\xee\x99\xb2\x49\x21\x32\x19\x9e\xb2\x8a\x82\x9c\x27\xf3\xcf\x2e\xdf\x44\x1c\xd8\x4b\x5f\x96\x29\xc7\x85\x64\xf9\xfd\xf5\x6f\x8f\xaf\x1d\x87\x12\xb4\x79\x0e\x17\x26\xa8\xb6\xe4\x1b\x17\xa9\xe8\xa4\x9c\xb6\x55\x93\x62\xd2\x3f\xce\xde\x6f\xe4\x60\x72\x05\xef\x89\xba\xcf\x0c\xe4\x53\xf2\xb5\xff\xf9\x24\x88\xe6\x2a\x0a\x08\xff\x6b\xec\x1b\x24\x9a\x56\x0f\xa2\xb5\xd4\x3b\xa1\x6f\xf0\x31\xc4\xe3\x7b\x79\xb3\x0c\x3a\xaa\xaf\x61\xa1\x4a\xad\x97\xd1\xf2\x34\xc5\xeb\xaa\x7d\xb0\x91\xc2\xae\x11\xcb\xc7\xf1\x35\x7d\x4e\x92\x93\x07\x26\x27\xec\x78\x18\x75\xfa\xbe\xa2\xa4\xf2\xab\x3b\x3f\x97\x55\x3b\xc6\xe1\x53\xfa\xfc\x7b\x8c\xf6\x3d\x87\xb6\x3c\xd3\xdb\x49\x9d\xd9\xe9\xf1\xab\x4f\xd4\x87\xe6\x26\x1d\xa2\x09\xf5\xfe\xe0\x7a\x3b\xba\xbf\xa7\xab\x43\xca\x04\x17\xe1\xb4\x9a\xf0\xf4\x85\xaa\xe2\x20\x82\x13\xe8\x41\x8e\x23\xa5\x0a\x53\xc9\x37\xd1\xfe\x84\xa4\x81\x4e\xba\xcb\xdc\xe4\x0b\xfe\xa9\xdb\x71\xbb\xbc\x00\xd3\xdf\xf4\x1f\x6e\xc9\xd4\x2c\x5c\x80\x18\x3b\x3f\xab\x51\x3c\xd8\x2b\x23\xc0\x03\xf1\xb0\x91\xdf\x26\xd7\x3b\x05\xbd\x21\x38\xda\x8e\x4b\x05\x1f\x5a\xb6\x78\x27\xfb\x97\xdf\xf5\x39\x19\x65\x3b\x22\xc1\xee\x94\x57\x61\x89\x91\xe6\x69\x99\x1e\x4a\x21\x21\x58\x0f\xfd\x68\xb5\xc8\xc9\xd4\x3e\xfe\x8d\xe1\x46\xc4\x74\xef\x4e\x79\x5d\x30\xcc\xb9\xcf\xd6\x22\x42\xaa\xcd\x8d\x41\xb8\x44\xf5\x5f\x52\xfe\x31\x51\x2c\x93\xbb\xcb\x0a\x8e\xb5\x36\x6c\xdf\x35\xce\xa0\xea\xa7\xc8\xbd\x72\x5f\xc7\x36\x29\xaa\x1f\xcb\x4a\xcd\x68\xe8\x3f\x15\x4e\x4e\x74\x75\xb7\xf7\xfb\x71\x3f\x70\x7e\x28\x6b\x8b\x5c\xea\xf0\x83\x1d\x49\x83\x23\xc7\xca\xc1\x5e\x53\x9a\x3f\xb0\x32\xa6\x79\x98\x94\x11\x45\xc1\x7d\xad\x09\xbb\xa5\x05\x3e\xdf\xb9\x0c\xcf\x85\x12\x69\x29\x0f\x9a\xfb\x7e\x3f\x81\x86\x88\x47\x32\xf2\x52\xd0\xfe\xf2\x49\x57\x3b\x91\x1f\xc2\x98\x1a\xc1\x1c\x56\x52\xba\xdf\x6a\x02\x29\x2b\x4a\x36\xf4\x98\x3a\x96\x08\x3f\xb6\x37\x27\x8d\xfa\x21\x49\x45\x46\x4a\x7b\xd7\x6c\x4d\x71\x1a\x69\xf4\x1b\x96\x64\x3e\x4b\xdf\xcb\x7a\xd4\x87\xea\xb1\xe9\x2f\x87\x32\x7d\xef\x9c\xda\xc8\xa0\xf6\xaa\x0f\x6f\xbc\xb0\xf0\x5a\x9e\x29\x5b\x9f\x5d\xba\x48\x00\xd7\x3b\xba\xed\xdc\xf9\xda\x5f\xab\x4c\x3a\xfc\x07\x79\x54\xa6\x96\xc9\x6d\xf2\x64\x4b\xc1\x75\x56\x07\x6a\x74\x3c\xd5\xf6\x50\xa7\x93\x2d\x85\x56\xa6\x46\x42\xed\x84\x97\x7a\xc5\xb6\xd8\x27\x76\xe6\x54\xdc\xd6\xb1\x44\xdf\xc4\xb0\xfc\x36\xdf\x62\xe0\x28\x6a\xdf\x2c\x5c\x27\x56\x1e\x3a\x49\xf4\xbf\xa2\x3f\x1d\xea\xb9\x52\xbd\x4a\xcc\x2b\xea\x4c\xfd\x3c\xde\x9c\x5b\xa7\x34\x89\x84\x1b\x2d\x97\x39\x71\x43\x1e\xeb\xea\x74\x20\xac\x84\xd8\xad\x40\xf1\x88\x5e\x1c\x63\x14\x11\x45\xef\xd8\xfb\xc7\x23\x65\xfa\xc5\xfb\xe5\x70\x02\x7f\x05\xf2\xba\x4a\xbd\x2a\x14\xc0\x6a\x2b\x70\x6c\x89\x17\x56\xe9\xac\x7c\xfa\x15\x29\xc1\x13\x4b\x1e\x1f\x8f\x9a\x7c\xde\x83\x48\xd2\xfe\x57\x27\x12\x23\x6f\x5d\xc3\x08\x91\x43\xf8\x44\x58\xdf\xfc\xab\x8a\x22\x4d\xfb\xbd\x8b\x2e\xc9\x47\x7b\x2f\x26\xb0\x4a\x38\xca\x9e\x54\xaa\x0c\x21\xe3\xa5\x31\x36\x8c\xc8\xab\x32\x8c\x52\x49\xe0\x07\x8b\x5e\x58\xce\x03\x0e\xab\xeb\x21\x3f\x4f\x78\x29\x97\x3f\xfc\x41\xfc\x58\xb3\xf7\xd3\x19\x29\x3e\x4b\x0f\xfd\x49\xfe\x50\xf1\xb3\xe7\x2e\x03\x2b\xea\x32\x7d\x64\x05\x59\x26\x96\xe6\x78\xf2\x53\xcc\xc9\xfb\x4b\x48\x38\x89\x5e\xb6\x80\x8b\xec\xc3\x5c\xf8\x06\xa7\xc4\xc1\xbe\xa8\xa6\x37\x26\xac\x70\x46\xe2\xb5\x52\x26\x0d\x4b\x43\x28\x37\x77\xc7\xc9\x7c\x70\x45\x6f\x28\xfc\xfb\x60\x6c\x98\x33\xe7\xe0\x93\xe1\x87\x28\x90\x4d\xae\x28\x60\xf1\x20\x59\xc5\x31\x19\xa9\x81\xe0\x11\x60\x88\x2e\x51\xe2\x5b\xbf\xef\x73\x4b\x8e\xa0\x65\x41\xee\xd8\x43\x80\x48\x9e\x48\x22\x2a\x63\xd5\xcc\xe1\x56\xbc\x3c\x02\xe8\xb4\xb3\xa2\xf0\x48\x85\x5f\x2b\x74\x40\x4a\xd5\x1c\x4c\xf2\x8d\xc2\xf9\xf3\x54\xb9\x4d\xe4\xaf\x23\x94\x87\x67\xb2\xd0\xdc\x60\xfe\x58\xf8\xc6\x9e\x4e\x97\x2a\x9d\xb8\xb9\x6b\x97\xd4\xac\x35\x19\x83\xe6\x98\x0a\x3a\x8b\x24\xca\x6a\xe2\xa1\xa4\xb2\x4f\x5d\xee\xa6\x59\x5d\xd2\x62\x06\x7b\x69\x2d\xe3\xde\x96\xd8\x2a\x4a\x88\x46\xc3\x23\x74\x7e\x67\xfe\x48\x61\x3d\x6e\xf9\x62\x1b\x38\xb1\xda\x42\xee\x60\x94\x81\x6f\x5f\xae\x8c\x28\xed\xd8\x7d\x38\x1c\xde\xae\xef\xcb\xbb\x61\x17\x01\xec\x66\xde\x7a\xbb\x8f\x9b\xf3\x87\x16\xfb\x4b\x03\xba\x32\x30\x60\x35\x71\xbe\xcb\xcc\x61\x7f\x91\x68\x98\xc5\xc1\x44\xd9\x84\x2c\x8e\x30\xdb\x23\x75\xc1\x34\xe4\x0d\x6b\x16\x7b\x4c\xb8\x02\x70\x31\x7c\xef\xc7\xca\x23\xd2\xf0\xfe\x9b\xff\x61\x7d\xcc\xb6\x51\x79\xb2\xcf\x9d\xd3\x8a\xc6\xb9\x0e\x52\x1b\x5a\x2b\xc9\x9b\x1d\x20\x25\x27\x60\x28\x7c\xb4\xcd\x07\xcd\x4f\x82\xd1\xa6\xc3\x6b\xac\x43\x98\xa2\x8e\x6b\x9c\xb3\x66\x57\xdd\x1b\xd2\x8a\xb8\x56\xca\xd8\xd6\x76\x77\x9f\x46\x6c\x0b\xdb\xec\xb9\xb7\x99\x1e\xb4\x1d\x60\x86\x0c\xfc\x88\xb3\xa7\xed\xf3\xd3\x09\x45\xa1\xa9\xc0\x44\x52\x74\x73\x28\xaf\xf5\x71\xf7\x43\x93\xc5\xe9\x2c\x0a\x7c\xed\x04\x29\xb9\xf3\x4f\x1b\x3b\xea\xa0\x77\x32\xc4\x8a\x93\x82\x05\x5a\xbd\x26\xe5\xab\x54\xf9\x1e\x15\x01\x14\x08\x34\xa3\x7e\x3a\xdc\xce\x1e\x18\xc0\xfb\xdb\xeb\x29\x6a\x22\x0d\x68\xc8\xaa\x5e\x6b\x3a\xef\x72\xa3\xfb\x37\xfb\x3a\x02\xd7\x04\xef\x98\xa6\x4f\xac\x9a\xed\x84\x11\x79\x1e\xe1\x44\x85\xda\x38\xea\xa1\x47\x66\x59\x2a\x33\x63\x34\x60\x3c\x1a\x0c\x89\xc3\x84\x76\x15\x09\xa5\xa8\xe3\x94\x36\xb4\x22\xd4\xdf\x96\xe7\x97\xb7\xf3\x7a\x23\xe7\xd7\xfe\xd2\x59\x78\x9b\xab\xe4\x8b\x73\xd3\xf5\xc6\x4f\xd7\xd3\x33\x5f\x78\x77\xce\xe7\xfd\x98\x29\x49\x3a\xff\xc5\x21\x33\x96\x76\x3c\x3b\x1f\x91\xb9\x8e\xee\xbc\x50\x5f\xe4\x30\xb2\xf3\x42\x35\x37\x49\x34\x81\xd6\xbe\xd5\xcf\xbd\xc2\x92\x0c\x25\x23\x7d\xe9\xbc\x6b\x08\xa7\x88\xd2\x98\x55\x16\x83\x35\xc3\x86\x98\x13\x3d\xa7\xfb\x5c\x27\x7f\x6f\xcb\x54\xa1\x85\xbd\x6c\xee\xa4\x7e\xb0\xbc\x52\x71\xe7\xd1\x6e\xa5\xfb\xcc\x57\xce\x87\x79\x25\x00\x2f\x5c\x3a\xa2\xfb\xc7\x5a\xec\x00\x89\xa8\xbb\xfd\x48\x5c\x98\xa0\x03\x2a\xc4\xd1\xe7\x15\x7f\x70\x51\xce\xcb\xc6\xa1\x93\xcf\xe7\x18\x8a\x49\x20\x57\x54\x7c\x85\x6d\x82\x08\x6f\xf3\x50\xef\x6f\xe4\x5f\xe7\xcd\x67\x26\xc8\x35\x97\x10\x58\xdd\x91\x88\x53\xa9\xe6\x98\xd7\xa1\xb9\xb2\xa1\x0d\xa7\x1a\xcf\x44\xda\xa2\x7b\x71\xb6\x23\x64\x95\x68\x6e\x96\x8f\xa5\x95\x6b\x79\xea\x5c\xcf\x6d\x2f\x24\xd2\xbb\x05\x82\xe1\xd3\xc2\x5d\x35\xba\x3f\x93\x14\x7f\xf8\xef\xc1\x14\x05\x0a\xe6\x7c\xd4\xde\xbc\x4f\x26\x01\x27\x8b\x42\xb0\xa5\x0e\xd9\x2a\xfd\x74\x23\x79\x37\xff\xaa\xac\xbe\x11\xf0\x1a\xf2\x36\x62\xb1\x00\x49\x3b\xde\xb4\x7c\x71\x57\x13\xd8\xed\xe1\x65\xd5\xdd\x2c\x9a\x0e\x51\xee\xc2\x49\x73\xbe\x52\xb1\x20\xb4\x9e\xe5\x2d\xea\xcf\x56\xf2\x7d\x6e\xfb\xa7\xb0\x36\x0a\x14\x38\x05\x61\x70\xc5\x8c\xa5\x4e\x3e\x99\xd0\x29\x3b\x53\x5c\x0a\xa6\x6f\x1c\x90\x59\x8a\xfc\x51\x61\x75\xda\x92\x1a\xa3\x97\xcb\xf2\xfa\x3a\xb0\x9e\xfb\x20\xd2\xca\x09\x6a\x62\x55\xd5\xfb\xfb\x9d\x24\x04\x09\xd5\x16\x37\x85\x16\xc0\x7b\xbf\x9e\xf0\x85\x4b\xa9\x1a\xe1\xea\x7d\x58\x8f\xe1\x34\x9c\xc9\x01\x3e\xb3\xc0\x3e\x1c\xce\x6e\x81\x61\xd5\xec\xaa\xab\xd4\x99\x28\xcc\xac\x32\xaa\x20\x7f\x29\xc2\x8c\x5f\x3f\x65\x09\x01\xf5\xb5\x77\xc6\xcc\x47\xc7\xc2\xe7\xf9\xed\xde\xcc\xbc\x82\x5c\x46\x70\xf9\x58\x3b\x26\x82\x56\xbb\xc9\x22\xfb\x78\xc7\x1f\xfc\xde\xc2\xd6\x2c\x11\x0a\x5b\xfa\x0e\x25\x28\x3d\xe2\xd5\x03\x72\x7e\xea\xc9\x85\xc4\x6b\xea\xb1\xea\x64\x25\x36\x5a\x56\x22\x65\xad\xb1\xad\xaf\x47\xa6\x3a\xb0\x26\xf4\xb6\xcc\xc8\xe1\x5a\xa5\x56\xd4\x4f\xe2\xa5\xd5\xb7\xb2\xf0\xfe\xf5\x59\x5f\x70\x93\x45\x3b\xf1\x95\x57\xe2\x7f\x47\xb1\x4b\x91\x86\x07\xf1\x45\x30\xbe\x22\x44\xbf\x7f\xb1\xc8\x9c\x7a\x1f\xf6\x44\xeb\xf2\xa1\xf3\x53\xfa\xdc\xad\x06\x26\x67\x17\x9f\xb6\xf2\x12\xe6\x3f\xbc\x2c\xbb\xf9\x2e\x85\xa5\x2e\x24\x6c\x90\x62\x14\x94\x24\xa1\xbe\xd4\xa0\xe8\xd0\xb7\x73\xe3\x76\x89\xb9\x65\x8c\x85\xf3\x86\x48\x27\x3e\xb9\x64\x21\xe8\xaf\x8a\xba\xf4\x00\xe4\xa2\x4b\x1a\x4b\xa1\xc4\x83\x4c\x9a\x7b\xc2\xf9\xfe\xa4\x6f\xa2\x85\xbb\x8f\xb6\xbc\xc0\xbf\xe3\xb7\x0f\xa3\x12\x39\xe7\x37\xa6\x69\x2a\x74\x3e\xf9\x44\x94\x1a\x0a\xbb\xdc\x38\xc9\x0a\x2c\xce\xa9\xc7\x79\x11\x9c\x69\xb8\xd6\x22\xf3\x00\xc7\x64\xb5\x05\xcf\x00\x46\xb2\xdb\xf9\xe4\xb2\xcd\xf4\x95\x21\x73\xab\x2b\x2f\x07\xbc\x97\xf3\xf9\x34\x7f\x5f\xfc\xa8\xcf\x27\x9e\x25\xb0\x56\x66\xd4\x3e\x1f\x98\x71\x82\xf7\xdf\xbb\x34\xde\xe0\x59\x62\x85\xbc\x97\xa5\xe0\xaf\xb6\xec\xbf\xc2\x38\x8a\x46\x78\x71\xf1\xf5\x61\x42\xba\x74\xf8\x88\x25\x28\xcf\xca\x00\x55\xfa\x0e\x73\x1c\xb8\x69\x47\xd7\x33\x50\xe3\x1f\x17\x24\xc7\x08\x09\xa3\x36\xa8\x9e\x9d\x20\x63\x87\x9c\x2a\xef\xdf\xcb\xfb\xc8\xa7\x37\x57\xcf\x7e\x89\xd1\xed\xa4\x81\xc4\xf3\xa8\x1e\x8c\x04\x97\x9a\xea\xd0\xf0\x62\x28\xef\x36\xa9\x69\x62\x21\xcc\x61\xa2\x89\xdb\x3b\x2b\x5a\x19\xed\x6e\xc5\x8d\x25\x15\x2c\xdf\xe3\x14\xbe\xa5\x8b\xe2\x33\xb0\xa3\xc8\x5f\x42\x11\x2a\xcd\xf1\x0e\xd5\xa2\xb9\x5e\xcf\xe7\xed\x81\x73\xc2\x0f\x3b\x5f\x74\x9a\xdd\x6f\x04\x57\x93\x72\x5b\xfa\x81\xa1\xb9\x89\x12\xbe\x59\xef\x16\x30\x59\x3f\xfb\x5c\x96\xfc\xf5\xdd\xa2\x6a\x55\x30\xcc\xb6\x6f\xcd\xfa\x94\x52\x16\x1a\xba\xce\x0f\x96\x21\x31\xa8\x27\xf0\x02\xa1\xee\x76\x1e\xae\x2d\x4d\xdd\xbb\xe4\x5b\xce\x12\x8e\xb4\x64\x22\xea\x5c\x7c\x05\x9a\x4d\xfa\x95\x60\x49\x7a\xd9\x43\xa7\x03\x11\x12\x86\xce\x4f\x7c\x2b\x32\x6b\xe5\x2a\xa1\x2b\x81\x3d\xb2\xfb\xd8\xb8\xeb\x44\x4d\xed\x32\x75\x0c\x52\xa5\x5f\xa0\x35\x6b\x58\xcc\x9d\xb5\x2c\xd6\xf9\xe6\x44\x74\x16\xbb\xcb\x12\x34\x69\xe7\xad\x71\xfe\xd9\xee\x89\x3a\xbd\x6b\x22\x9f\x48\x82\x5a\x3a\x62\xab\x2e\x12\x58\x9f\xd1\xb0\x6a\x2f\x9d\x80\xbd\x9d\x55\x1a\x1f\xdf\x8b\xf7\xb2\x1f\xa2\xf5\xd8\xe1\x6f\xff\xb4\xa4\x13\x1f\xa7\xc5\x55\x7e\xf3\x9b\xb1\xc2\xa2\xa9\x33\x8f\x11\x57\x63\x2f\x53\x18\x2f\x4e\x05\x71\xcd\x2d\x4f\xad\x98\x5c\xac\xcb\xf3\xdc\x91\x75\x3d\x9f\x02\xf5\xbf\x25\x60\xc0\xc3\x00\x45\x4a\x13\x48\x9f\x42\x67\x61\xbf\x8b\x22\xad\xc4\xc7\xec\x86\xb8\xa6\xc7\x1f\xdd\xdf\xd9\x4f\xf8\x93\x99\xeb\x2f\xd9\x9d\x9e\x49\x2a\xc0\x0c\xa7\x08\x21\xaf\xa9\xed\x02\xe9\x57\x35\xba\x8a\xdc\x20\x75\x68\xfc\x8a\x26\xb0\x12\x9f\x7e\xf9\xac\xb5\x3d\x96\xb9\x1b\x2c\xfc\x47\x24\x83\xd0\x34\x24\x41\x52\x84\xae\xeb\x45\x48\xa1\x79\x25\xff\x1e\x7d\x6c\xa9\x57\xc6\x16\x29\xc8\x16\x4f\x7d\xfe\xb2\x9e\xcb\xf6\x8a\x25\xd6\x04\x2b\xea\xc8\x76\xc7\x7c\x12\xbe\x76\x1c\x37\x8f\xb5\x18\x04\x60\x5b\xb5\x5d\x9f\xbd\xfe\xf0\xb2\x53\x45\xd8\x56\xf9\x0f\xb1\xde\x0a\xf5\x90\x41\x75\x73\x32\xe6\xb7\xe3\x41\x8b\x6a\xd8\x7d\xbc\x06\x00\x21\xdc\x66\x56\x4b\x7a\x10\x4e\x5c\xdc\x81\xfe\x0a\xd2\x68\xda\x9f\xf6\xde\xd0\xc0\x78\xc7\x8e\x6d\x54\x82\x6d\x03\x72\x45\xf2\x37\x31\xc4\xe4\x60\x85\x6d\x34\xaf\x8f\xb1\x8f\xf1\x24\x7a\x5e\x7a\x5d\xd4\x17\x89\xbd\xd3\xaf\x33\xab\xe7\x8c\xb8\x0c\xb5\x8d\xd9\x5e\x4b\x7e\x5a\x34\xd7\x3a\x0d\x3c\x37\x5c\x6e\xf4\x92\x3e\x17\xaa\xf9\x9c\x9b\x2d\xe4\x54\x88\x92\x71\xea\xf9\x70\x57\xc6\xca\xd9\x74\xc6\xd2\x6b\x33\xac\xac\x0c\xf1\xc2\x46\x3d\x39\xe9\xf0\xf9\x7f\x83\x56\x83\x05\x31\xa1\x63\x45\xf5\xc8\x0b\x44\x3b\xb9\x32\x89\xa3\x5d\xf6\xae\x48\x5e\x26\x41\xe2\x44\xc5\x3a\x26\xb9\x4e\x84\xdc\x0b\xf1\x26\x6f\x49\xe0\x2c\x3e\xc7\x69\x96\xbe\x7b\xaa\x52\xd3\x29\x1d\xfc\x07\xa2\x90\xcb\xf0\x69\xa7\x9a\x19\xe7\xcc\x1d\x03\xab\x6b\x96\x6b\xf9\x1c\x27\x3f\x40\xd7\x26\x61\xbb\xff\x36\x56\x29\xae\x78\xb6\x5f\x8e\xc9\x93\x82\x1a\x7d\xf6\x53\x9a\xac\x93\xcd\xb9\x9c\x59\xb9\x2d\x8e\x98\xda\xb6\x1a\x32\x17\x36\x91\x23\xd0\xf2\x0c\x25\xde\xf7\xfb\x61\xf5\x27\x8f\xfc\x21\x34\xb3\x28\x8b\x13\x10\x70\x86\xd5\x19\x8c\x80\x9d\xfa\xb7\xa3\xab\x60\xcd\x6e\x4a\x25\x94\x4e\xad\x8b\x44\x32\x94\x49\x18\x7a\xec\x81\x1d\xa1\x39\xed\x89\xac\xc1\x98\x85\xc8\x9d\xbf\x59\x91\x58\xaa\xe4\xa1\x01\x61\x84\x71\x76\x7b\xa9\x08\xcc\x21\xc2\xaa\x9c\x78\x91\x54\x4a\x3f\x77\xee\x72\xdb\x85\xcf\x3c\x72\x8e\xac\x77\x2d\x0f\x5b\xc0\x45\xcf\x31\x10\x50\xbb\x26\xc5\x58\x47\xe4\xb0\x92\x25\x16\xc5\xbe\x88\xf3\xd4\x63\xa5\xc5\x57\xb3\x93\x1b\xb1\x5a\x9e\xb6\x9f\x5d\x4c\x06\x4d\x88\x4e\x63\xca\xb3\x76\x1f\x87\xf8\xf3\x20\xcd\x5f\x84\x05\x85\xec\x5e\xd4\x92\xb0\x74\x2d\x32\xcb\xc7\x5c\xf6\xf8\xda\xd1\x94\x50\x59\xf5\x42\x60\x84\xe3\x29\x3f\xfa\x08\x48\xab\xf9\xee\x7f\xfe\xf7\x3f\xfe\x2f\x00\x00\xff\xff\x9c\x84\xb0\xba\xce\x07\x01\x00") + +func dataPasswordsJsonBytes() ([]byte, error) { + return bindataRead( + _dataPasswordsJson, + "data/Passwords.json", + ) +} + +func dataPasswordsJson() (*asset, error) { + bytes, err := dataPasswordsJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/Passwords.json", size: 67534, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dataQwertyJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xb4\x98\xd7\x52\x23\x3d\x10\x85\xef\x79\x0a\x18\x72\xce\x39\xe7\x9c\x33\x98\x9c\xc1\xe4\x8c\x31\xcf\xfe\x6b\xf8\xb7\x56\xdf\xa9\xb2\xc6\xbe\xd8\xbe\xd9\x6a\x2f\x33\x5f\xb7\x5a\xad\xa3\x63\x67\x8a\x8a\x8b\xa3\xc9\xa7\xa3\x87\xcb\xa8\xa7\x38\xfe\xe0\x3e\x96\xb8\x70\xf7\x37\x74\x1f\x0e\x7f\xa2\xba\x3f\xf1\xdd\x6b\x3a\x9d\x2b\x8e\x5a\x86\xfe\x3e\x13\x3d\x2e\xcb\xf3\xbf\xe1\xde\xff\xff\x13\xa5\x22\x92\x7b\x7b\xfc\x5b\xbb\x19\x1f\xef\x65\xf3\x67\x6c\x1c\x8c\x84\x5c\x4a\x30\xca\x09\x02\xda\xca\x7c\xc2\xb3\x71\x1f\xbf\x6f\x2a\xb8\x8c\xe0\xd6\xd2\xfc\xe0\xf6\x72\x0f\x7b\x5a\x91\x24\x02\x2e\x27\x18\xd5\x04\xc1\x1d\xfb\x1e\xf6\xb2\x26\x49\x04\x5c\x41\x30\x5e\x0a\x82\xbb\x6a\x3c\xec\x75\xdd\xc7\x9f\xdb\x0a\xae\xb4\xda\xbc\x2a\x82\x51\x4d\x10\xd0\x54\xed\x13\xde\x2f\xfa\xf8\x6a\x5a\xc1\xd5\x04\x77\x57\xe5\x07\xd7\x1f\x78\xd8\xc3\x92\x24\x11\x70\x0d\xc1\x9d\x15\xf9\xc1\x48\x1e\x57\xc9\x7e\x0b\xb8\x96\x60\x54\x13\x02\x4b\x12\xf4\x3e\xde\x13\x01\xd7\x11\x7c\x3b\xef\x1f\xbc\x99\xf5\x71\x7a\xce\xc7\x0d\x03\xc1\xe4\x02\xae\x27\x18\x1b\x13\xac\xb2\xbf\x36\xf7\xe4\xb8\x7e\x0b\xb8\x81\xe0\xba\xbe\xdc\x55\x72\x0c\xdd\x58\x15\x54\x71\x23\xc1\x58\xa6\xc0\x2a\x9d\x56\x15\xd2\x7c\x21\x37\x59\xcd\x5b\xb3\x95\x22\xb7\x10\xdc\x5c\x92\x1f\x0c\x09\x8c\xb5\x92\x49\x04\xdc\x6a\x25\xc8\x6d\x56\x82\xdc\x6e\x25\xc8\x1d\x04\xa3\x9a\x20\x18\x82\x12\x8b\x30\x93\x08\xb8\xd3\x4a\xe9\xbb\xac\xe4\xad\xdb\x4a\xe9\x7b\x08\xa6\x40\xf0\x54\x51\x6d\x78\xbe\xa9\x1c\xb1\x20\x08\xb9\xd7\x8c\xdc\x67\x25\xc9\xfd\x56\x97\xc8\x80\x95\x24\x0f\x9a\x49\xf2\x90\x95\xc0\x0d\x03\x2c\x00\xc8\xad\x00\x9e\x57\x7d\xfc\xb5\x13\x96\xe4\x11\x56\xfc\xb6\xe1\x5f\xba\x98\xf4\xf1\xe5\x94\x8f\xef\x16\x0a\x6b\xf2\x28\xc1\x1f\x5b\x1e\x70\x3a\xe6\xe3\xf3\x09\x1f\x23\x79\x22\x78\x8c\x60\x2e\x93\x3a\x4e\xe9\x65\x92\x93\x51\x1f\xbb\xa2\x04\x3c\x4e\x30\x7b\xc9\x4d\xe2\xc5\xc1\x24\x5c\x95\x2b\x4a\xc0\x13\x04\xf3\x41\x02\xa8\xe9\xec\x3d\xf7\xc4\x55\x2f\xe0\x49\x82\xb9\x4c\xc2\xa8\xe9\xdc\xc8\xe3\x11\x49\x22\xe0\x29\x82\x59\x0d\x61\xd4\xf4\xeb\x99\x9c\x13\x12\x27\x11\xf0\x34\xc1\x04\xf0\xb2\xa0\xbe\x53\x86\xa9\x54\x2e\xa1\x80\x67\x08\xe6\x32\x99\x84\x97\x05\x61\x94\x43\x57\xbd\x80\x67\x09\xe6\x32\x09\x63\x95\x54\x27\xaa\x96\x4b\x22\xe0\x39\x82\x59\x0d\x61\x94\x7d\xaa\x13\x55\xcb\x25\x11\xf0\x3c\xc1\xdc\x0c\x56\xcf\x84\xa8\x32\xf1\xe4\x2d\x10\xcc\xf1\x61\xbf\x99\x04\x7d\x4d\x04\x2f\x12\xcc\xbe\x72\x12\x78\x39\xb3\x2d\xec\xb7\x5b\x95\x80\x97\x08\x66\x5f\x09\xa3\x2d\xe6\xd5\xca\x7e\xbb\x24\x02\x5e\x0e\xe9\x31\x44\x5f\x6c\x31\xf5\xe4\x68\x38\xac\xc7\x2b\xac\x98\x8a\x46\xe1\xa1\xc9\xe4\x51\xa7\x04\x38\x9d\x11\xf0\x2a\xc1\xa8\x40\x2a\x63\x42\x0a\x15\xf5\xdb\xdd\x26\x02\x5e\x23\x98\x8a\xc6\x2a\xe9\x5e\xa9\x21\xd4\x16\x57\xbd\x80\xd7\x09\xe6\x4b\x74\xac\xd4\x0d\x4e\x0e\xc7\xd0\x8d\xa7\x80\x37\x08\xe6\x8d\xc0\xfe\xb1\x32\xcc\x7a\xe2\x1c\x6f\x12\xcc\x9b\x99\x93\xc0\xdb\x84\xfd\xe6\x55\xe6\xf6\x47\xc0\x5b\x04\xe3\x3a\x97\x97\xb8\x61\x58\x55\x62\xc5\xdb\x04\x73\x94\xb8\x61\xec\x37\xe5\x94\xc7\xde\xb5\x4b\xc0\x3b\xa1\x03\xc2\xd1\x63\xf5\x18\xb1\xc4\x8a\x77\x59\x31\x75\x80\xc7\x98\xdf\xfa\x69\x31\xc5\x2d\xbb\xf3\x2d\xe4\x54\x8a\xe8\x02\x7e\x5a\x2a\xd8\x16\xee\x11\x4c\x89\x41\x9d\xd2\xa4\x54\xea\x3b\xf7\x1f\xe2\x05\x08\x7a\xdf\xea\xeb\xde\x81\xd5\x2f\x2d\x87\x81\xc9\x08\x82\x13\x7c\xb4\x80\x8f\xac\x3c\xf2\xb1\x95\x47\x3e\xb1\xf2\xc8\xa7\x56\x1e\xf9\xcc\xca\x23\x9f\x5b\x79\xe4\x0b\x2b\x8f\x7c\x69\xe5\x91\xaf\xac\x3c\xf2\xb5\x95\x47\xbe\xb1\xf2\xc8\x69\x2b\x8f\x7c\x6b\xe5\x91\xef\xac\x3c\xf2\xbd\x95\x47\x7e\xb0\xf2\xc8\x8f\x56\x1e\xf9\xc9\xca\x23\x3f\x5b\x79\xe4\x17\x2b\x8f\xfc\x6a\xe5\x91\xdf\xac\x3c\xf2\xbb\x95\x47\xfe\xb0\xf2\xc8\x9f\x56\x1e\xf9\xcb\xca\x23\x67\xcc\x3c\xf2\xb7\x95\x45\xce\xda\x59\xe4\x9f\x7f\x6e\x38\xdd\xbf\xd9\xa2\x6c\xd1\x7f\x01\x00\x00\xff\xff\x4c\xae\x50\xc0\xce\x20\x00\x00") + +func dataQwertyJsonBytes() ([]byte, error) { + return bindataRead( + _dataQwertyJson, + "data/Qwerty.json", + ) +} + +func dataQwertyJson() (*asset, error) { + bytes, err := dataQwertyJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/Qwerty.json", size: 8398, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dataSurnamesJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x54\x7d\x5b\x62\xf3\x3a\xcc\xdc\x5e\xfc\xdc\x15\x74\x0d\xdd\x41\x9f\x28\x89\x96\x18\x51\xa2\x0e\x29\xda\x9f\xd3\xcd\x17\xc0\x0c\xe8\xfc\x4f\x27\x27\x5f\x12\x4b\xbc\xe0\x32\x18\x0c\xfe\xdf\xe3\xff\xa4\x76\x3f\xfe\xf7\xff\x7d\xb4\x23\xdd\xdb\xe3\x7f\x3d\x7e\xca\x76\xb6\x72\xca\x57\xef\x94\x73\x0a\x47\xb3\x6f\x9e\x51\xff\x3b\xd5\xf2\xd6\x7f\x5a\xc2\x2b\xe9\xff\x1f\xf2\x23\xb1\xe2\x67\xf1\x4b\x47\x29\x35\xca\x7f\xef\xf0\xc9\x45\xff\x25\x9c\x4b\xac\xf8\xb7\x9f\x30\xef\xfc\xd3\x5b\xba\xf5\xa7\xb6\x50\x2b\xfe\x50\xa8\x77\xd2\x7f\xb9\xb7\x72\x5c\xf8\xa1\x35\xd4\x39\x85\xf1\x8f\xf1\x57\xbe\xac\x65\x4a\x7c\xbc\x39\x87\xba\xdb\xb7\x96\x9a\xd6\x6e\xff\x9c\xe3\xdb\xfe\x5c\x8e\xfa\xd7\xdf\x21\xef\xf6\x74\x5b\xc8\x59\x1f\x45\x1e\x56\x7f\xf3\x53\xfa\xb9\xea\xb7\x63\x3d\xf5\xf1\xf4\x37\xf7\x64\xdf\x7a\xcb\x9f\xda\x6e\xfd\x0b\xe5\xb2\xef\x6f\xc9\x7e\x75\xad\xd1\x7e\x35\x2c\x58\x90\x29\xe0\x2f\xaf\xe5\xfc\x0d\xd9\x7e\xf2\x8c\x5c\x82\x59\x1e\xd7\xfe\x51\x56\x74\xde\xa2\xfd\xfe\x15\xab\x3f\x7f\xac\xb7\xfe\x85\xbb\xd7\xd3\x7e\xea\xd2\x8f\x48\x57\xb3\xdf\x3c\xae\x89\xbf\x20\x2f\x67\xff\x1c\x5f\xe1\xd4\x7f\x8b\xcb\x3b\xd4\xc5\x7e\xaa\xc8\xcf\xdb\xf7\xda\x1d\xe5\x9b\xfa\xb8\x2d\x9c\xf2\x51\xbf\xb6\x01\x5c\xd2\x5a\x56\x59\x78\xfd\x22\xc6\xc5\x7e\xad\xec\xf8\xf7\x35\xe8\x63\xf2\x83\x8e\x5e\xaf\xed\x63\xaf\x94\x72\xd4\x2f\x6a\x7a\xc5\x1a\xf0\x1b\x97\x3d\x43\x4d\xf3\xa6\x1f\x8e\xd7\x2b\xff\x74\x5d\x8a\x3e\x8e\x2d\xb2\xfd\xe7\x96\x8f\xb5\x23\x72\xc5\xdb\xf7\x7b\xad\xc1\xfe\x5e\x38\x12\xde\xfe\x1d\x6e\xfc\x8b\x9c\xa3\xb2\x37\x3c\xf7\x82\xa7\xbc\xe4\x43\xa2\x3d\xd6\x79\xc6\x5b\xdf\xe9\x5d\xca\x62\xcf\x55\x71\xf8\x6a\x69\xcd\x76\xed\x7b\xa2\x64\x29\xe2\x61\x6f\xf3\x13\xcf\x1d\x8b\x22\x8f\x5c\xf5\x63\xaf\xf2\xc6\x1b\xe6\x62\x5b\x7b\x85\x7b\x3c\xd9\xd6\xd7\xcd\xfe\xe6\x53\x0e\xa9\x7d\xf1\x0e\x6d\x93\x23\x70\xe3\xf1\xfa\x8d\x63\xdd\xd2\x71\x14\xfb\xab\xcf\xd2\xee\xbf\x3b\x8e\xdb\xf0\x09\xe7\x6d\x07\x2b\xfe\xb3\x17\xb1\x97\x4e\xcf\xa7\x1d\xe5\x25\x05\x3b\x41\xe1\x63\x3f\x7d\x7c\xf0\xa2\xcf\x62\x0b\xb6\xc9\xaa\xe4\xdb\xd7\x49\xfe\x4f\x3f\xae\xcb\xce\xbe\xec\x7d\xe4\xec\xe6\x60\x0b\xa2\xcb\xc0\x6d\xb7\xff\x8d\x4d\x3f\x52\x5e\xee\xc4\xe6\x7e\xce\x92\xed\x07\x9e\xa9\x6d\x38\x32\xf2\x57\xda\xb8\x5d\xf8\x88\x34\xf1\x7e\xce\x4b\x39\x43\xb6\x03\x51\xfb\x2f\x6e\x57\xe3\x05\x29\x72\xcf\x7e\xed\x1d\x0f\x9c\xa5\x5e\xb1\x85\x4f\x39\x43\x58\x67\x5d\x53\x5b\xaf\x38\x4d\x58\x20\xde\x56\x59\x9e\x17\x1e\xe9\xee\x33\x8e\xee\x55\x78\x11\xb6\x34\xdb\x6e\xcf\x35\xbc\xf9\xfa\x53\xf9\x2c\xf6\xe1\x6e\x36\x2a\x17\x75\xd7\xfd\x5f\x3e\x38\x59\x35\x62\x21\xff\xd9\x0f\xc9\x41\x2a\x7c\x67\xac\xbf\x5c\xa1\x66\x8f\x5b\x17\x3c\xc3\x16\xde\x76\x36\xf3\x81\x13\x83\x23\xc5\x4b\xc7\x9d\xb7\x1d\x5b\xc2\x99\xa2\xbd\xc8\x15\xe4\x87\x71\x5b\xf1\x66\xa7\x1c\xf6\x62\x5f\xc9\xbe\xd8\x0f\x3f\x63\x5d\xbb\xbf\xa5\x58\x42\x5b\xda\x37\x8f\xdb\xd2\xcf\x13\xa7\x8e\xdf\xd8\x3a\x2f\x4a\xbb\xe2\x39\xe3\x4c\xc8\x1d\xc1\x65\x97\x55\xba\x36\x2c\xd3\x15\x3e\xf6\xa7\xae\x14\x2b\x4f\x3e\x0e\xee\x21\x07\x75\x8b\x6f\xfd\x19\x39\xfa\x25\xe3\x96\xad\xa7\x1b\x5a\x6c\xae\xdc\x25\x7e\x60\xf9\xda\x9d\x5a\x6c\x1f\xe5\x99\x66\xdb\xad\x76\x7e\x16\x5a\x40\x33\x13\xb3\x3c\xac\x9c\x72\x9c\xb6\x1c\xec\xf3\xe5\xe0\x56\x7c\x5a\xed\x09\x07\xb6\xe2\xda\x3f\xed\xa6\x57\x9a\x85\x50\x8f\x76\x57\xdc\xa5\x59\x7f\xe4\xc4\xe6\xbe\x63\x78\xf1\xe4\x8b\x8d\x8c\x3c\x7f\xc5\xae\xb0\x98\x8d\x97\x9d\x24\x39\x27\x5f\xe3\x60\xbb\x9c\xf1\x57\x9f\xb2\xc6\x7b\xb6\xfb\x92\xc3\x1b\x2f\xf2\x94\xad\xb1\x13\xbd\xf6\x5b\x16\x07\xb6\xa3\xcd\xdb\x91\x96\x9b\xef\x29\xff\x79\x85\xf6\x1f\xac\xfe\x1c\xda\x2d\xcb\x52\xf4\x61\xb6\x18\x71\x75\xe5\xa3\x2f\x1c\xd9\x92\x13\x1e\x50\xae\xf2\xad\x47\xbb\xc2\xca\xc1\xa6\x3d\xbe\x8e\x0e\x4e\x4a\xfd\x1f\xcd\x80\x3c\x9a\xdd\x5c\x39\x6f\xfa\xfb\x93\x5c\xb0\x72\xd9\x25\x9a\xcb\xc7\x0e\x1a\x4d\x4c\xc8\xaf\x50\xff\x98\x5f\x1c\x35\x31\xdc\x76\x7e\x9f\x7f\xfc\x8c\x1c\x85\xdf\x80\xb3\x8b\x0f\x39\xd7\xfe\x89\xf4\x8e\x65\xc2\xf1\x4e\xba\xe5\xcf\x4e\xdf\x9a\x3f\x62\xdb\xf1\xab\x15\x96\xb1\xea\x4b\x14\xdc\x46\xfb\x27\x71\x85\x5c\xba\x1a\x7e\x13\x1e\xb6\x8b\x03\xe1\x53\xe0\x8a\x89\xdd\x2c\xf6\xd9\xf2\x8c\xf1\x2c\x76\x09\xdf\x58\xa2\x23\x2e\xe9\x0c\xb6\xe5\x6f\x7c\xe8\x24\x67\x02\x27\xa7\x3c\x9f\xf8\x21\x59\x77\x9e\xb4\x96\xe4\x7d\x6d\x3b\xfd\x73\xe5\xc6\xc8\x71\xb2\xc7\x16\x8b\x0c\x5f\x2a\x26\x19\xef\x2f\x6b\xb3\x06\xbb\xb0\x1f\xbb\xfb\x1a\x3d\x2c\xfe\x7b\x17\x4f\xf1\x61\x86\x66\xd3\xed\x36\xe7\xf3\x0e\x8b\x3e\x7e\x2b\xb7\xbd\x68\xc8\x3c\x39\x67\x0c\xd9\x1e\x26\x2f\xc3\xbe\xbf\x23\x3e\x4e\xcf\x36\xbc\x73\xa5\x0f\x91\x2b\xfc\x32\x53\xf0\x93\xe4\xfd\xe1\xd1\x0b\x57\x5e\xac\x65\xf6\x8d\xf6\x95\x2d\x53\x4d\xf1\xe4\x99\xb2\x25\x6e\xfd\xbe\x69\x39\xe5\x49\x4f\x3b\xb4\xb9\xcf\x81\xe1\x0f\x3d\x93\x84\x20\x7e\x18\xe5\x72\x4d\x78\x54\x59\x14\x0b\x25\xec\x1b\x37\xd6\x46\x23\x82\x8a\xeb\x7b\xe3\x51\xef\x08\x5b\x6d\xd6\xbd\x6e\x65\xa1\x1b\xb5\xfd\x98\xe2\xbc\xdb\x4b\x73\xa3\x36\x35\x1a\xf6\xd1\x33\x4c\x18\x37\xd6\x3e\x7a\xea\x6d\xb3\xe5\x16\xef\x66\x36\x49\x62\x08\x33\x51\x7e\xb1\xc4\xdb\xde\x29\xac\xfa\x5a\xa7\x87\x09\x7a\x09\xf4\x9d\xc4\x32\x45\x7b\x84\xb9\x7f\xfd\xa7\xbd\x86\xdc\xbc\x9e\xef\x5f\xac\x13\xc3\x9e\xfe\x8b\xe7\xb9\xc2\xaa\xbf\x73\xf4\xb3\xe0\x07\x6c\x47\xec\x76\xf3\x12\x9e\x0b\x23\xc4\x38\xf1\xc5\xb3\x3d\x65\xfe\xc0\xb1\x8a\x51\x6f\xb6\xa8\xef\x92\x9f\x11\x1f\x77\xca\x0d\xc0\x8d\xed\x1e\xea\x48\x58\xd0\xdc\xc6\xd7\x0b\x67\x37\x72\xef\xf0\x87\xe7\x7e\x1c\xdc\x7f\xf1\xe4\x70\x10\x7a\x48\x12\x5c\xac\x7a\xe5\x1b\xcb\x93\xb1\x5c\x5b\x9f\x26\x04\x2f\x2d\xe4\xf0\x1b\x2c\xd2\x89\xf1\xc5\x78\xa0\x0e\x8b\xfd\xf2\xcf\x96\x3b\xb5\xc6\xc6\xb8\xe5\x36\x5f\x74\x07\x0b\x64\x67\x06\x27\xab\xff\x9a\x2c\x8f\x1d\x9a\x30\x23\xe8\xb2\x7f\x95\xe0\xb6\x9e\x7e\x9a\x56\x8b\x51\x9f\x62\x56\xed\x17\x96\x98\xd7\xb0\xe8\xd6\x84\xb5\xa7\x6c\x4f\xf3\x8a\xab\x1e\x82\x35\x97\xd7\xf8\xa3\xb8\x5b\x73\xd9\x22\xce\x43\x3d\xe0\x1b\xcb\xe2\xe1\x5e\x99\x26\xac\x99\x9c\x1a\x9e\xef\x1c\x12\xfc\xf0\xba\xe2\x9f\xe4\xaf\x54\x73\x02\xf2\xc2\xcd\x5e\x40\xfe\x34\x3d\x9c\x58\xc6\x9d\x97\xf9\x96\x70\x5f\xee\xf0\x62\xc7\xe1\xf6\x00\xa8\x70\x51\xf5\x52\xf2\xc3\xdf\x30\x35\xc7\x85\x6f\xa8\xe3\xb7\x47\xd7\xa0\x0b\x7f\xf6\xed\x76\x48\x7f\x9f\x56\x47\x76\x42\x82\x11\x7b\xe9\x0f\xef\x81\x1e\x78\x04\x31\xfa\x18\x6e\x24\xe4\xdd\xe0\xcf\x0b\x22\xa1\x13\x8b\x1c\x16\x1a\x0f\x39\x5c\x0c\xcf\xe4\x6f\xba\x87\xd6\xd0\x0d\x16\xc9\x4f\xb2\x18\xd8\xc9\x76\xa3\xd8\x91\xff\xaf\x27\xf8\x6e\x09\x73\xf5\xa1\xdb\x24\xdb\x63\xc7\x79\xd6\x18\xde\xa2\x62\x49\x2c\xd4\x22\xe9\x23\x4a\xe0\x55\x25\xfe\xc7\xee\x2f\xe5\x65\x76\x48\x02\xab\x09\xb1\x02\xb6\x58\x0e\xd9\xaf\x6c\x04\x22\x2c\xf1\x23\xbb\x3d\xf8\x52\x3e\x76\xb7\x5a\xe8\x1e\xef\x4a\xa2\x62\xeb\x5e\x32\x03\xb4\xaf\x23\xc1\x8a\xa8\x3b\xb5\x28\x2a\x2c\xf2\x6f\x30\x89\x6e\x03\x3b\x4c\x99\x5e\x37\x9e\xe0\x79\xd3\x4c\xc0\x3c\xd0\x2c\x36\xcc\x6c\xe7\x56\x3a\x3d\xd9\xbc\xc9\x65\xbf\xdd\x1e\xef\x39\xda\xfe\x5d\x35\x98\xd1\x93\x9f\x5f\x57\x84\x24\x6a\xce\x61\x5e\xb2\x5a\x11\x38\xe6\x5f\x89\x82\x63\xc5\x9e\x49\x24\x08\x6f\x34\x75\xbd\xdc\xc1\x83\x37\x44\xe3\x57\xe4\xc1\xb9\xd2\x7d\xe3\x17\x26\x79\x9d\x0f\xd6\xb4\xd4\x23\xd9\x75\x50\x6f\x21\xf9\x83\x65\x1d\xb5\xd8\xb7\xae\x82\xf0\x36\x17\x66\x27\xa1\x31\x2f\x34\x6b\xb1\xd4\xb0\x23\x18\xa6\x6b\x79\x3e\x3d\x96\xbf\x90\x06\x1e\x6e\xd6\xc3\x34\x21\xf8\x68\x6e\xff\x4e\xff\xa7\xad\x3f\x9f\xf6\x47\x1b\x4c\xce\x53\xf3\xc6\x5a\x2c\xd7\x71\x4f\x36\xf9\x61\xb1\xa8\xb1\xb9\x7f\xc0\x1f\xb8\xf1\xa2\x6a\xd1\x1f\x8c\xaf\x47\xce\x50\x70\xee\x66\x3d\xfb\xe6\x08\x34\x3f\xb5\xd3\x14\xee\xcd\x4c\x6d\x93\x1f\x16\x0f\xe0\xc9\x35\xcf\xee\x1c\x6c\x91\xed\x60\x30\xe5\xd9\xb8\x08\xe2\x72\xe2\x29\xfe\xfc\xc1\xa4\x0f\xe1\x40\x37\xcf\x20\x61\x64\xbe\xb0\x55\x62\x2f\x2c\xe7\xd6\x7d\xc7\x45\xd1\xbf\xee\x0f\x7f\x06\x5b\xc1\xd6\x75\x13\x2d\xa8\xf4\xc0\x51\x7e\x0a\xc9\x9c\xee\x16\x2f\x16\xa2\x32\x59\x76\xba\x33\x8d\xb1\xe1\x1a\xe7\x22\xa7\x08\xfb\xbc\x05\x3b\xbb\xe2\xc7\xe3\xa9\x41\xbe\x3d\xb2\x3d\xf9\xca\x6b\x1c\x3e\x21\xe3\xa6\xbc\x11\x3b\xbd\xc2\x2f\xff\xe2\x92\xe6\xf1\x6c\x76\xb3\xf5\xc7\x67\x49\xaf\x2c\xfe\x90\x60\xe7\xb4\xbb\x76\xa5\x13\xd1\x0a\xe3\x71\xa6\x09\x67\x2d\x11\xbb\x2d\x46\xe7\x01\x24\x81\xb9\x78\x51\xbb\x60\x98\x43\x33\x4f\x0d\x6f\x53\xf1\xe3\x19\xf1\xcd\x9e\xea\xf4\xe1\x49\xc0\xf9\x94\x8b\x77\x00\xb2\x58\x8a\xfa\x0f\x3c\x64\x61\x98\x21\xc7\x19\xe6\xf6\xb0\x5b\xbe\x8b\xd1\x64\x3c\x7d\xce\x38\xb8\xab\xde\xc1\x75\x63\x9c\x4f\xc7\x23\x4e\x4a\x0f\xa8\x7d\x85\xf5\x79\x0f\xd3\xab\xc7\x01\xf1\xb6\x5c\x89\x8c\xcd\x97\xd4\x6d\xc4\x05\x66\x07\xda\x81\xff\x1e\x1e\xa2\x68\xd2\x80\xbd\x99\x60\xd5\x96\x8f\xa7\x9b\xc8\x75\xe4\xe5\x6f\x0d\x9d\x6c\x63\x3f\xbc\xd8\xe1\x1f\xac\x62\x3b\x6d\xb1\xc4\x0d\xe1\x6f\x48\xe8\x23\xe7\xc7\x2c\x87\x86\x8e\x70\x25\x85\x5e\x66\x8a\x81\x3f\x86\x70\x3d\x0e\xc4\x66\x8b\xc1\x92\xb6\xc8\x54\x76\xfd\x26\x98\x92\x3d\x33\x68\x57\x1f\x67\x3b\xff\x42\x6c\x20\x7b\x67\x7f\x41\xde\x50\xf6\xee\x9b\x8e\x30\x9f\x94\x73\x03\x13\x76\x74\x8f\x1a\xf6\x78\xa8\x87\x17\x8f\x18\xfd\x6a\x99\xe7\x16\x67\x12\x19\xfb\x89\x69\xe3\x2d\xb2\x07\x8d\x81\x76\x4e\xb6\x39\xda\x99\x7f\x69\x32\xc4\x3b\x8a\x30\x71\xeb\xc7\xb5\x55\xbc\x97\x3d\xb7\xd9\x95\x8e\x23\xbd\x75\x09\xcc\x1c\x59\xda\xe0\xe3\x97\x52\x61\x26\x26\x89\x42\xb0\xd9\x62\x13\x98\xfa\xc7\xc0\x50\x96\xfb\x23\x21\xad\x1d\x78\x4d\x2b\x1e\xe6\x71\xe7\x9d\xf1\xe9\xa7\x98\x81\xb2\xc4\x02\xff\x74\xca\xb5\x96\x05\xbb\xcc\xa2\xc4\x57\xb2\x60\x5c\x82\x10\x39\xa3\x0e\x03\x15\x60\x22\x3d\xe1\xee\xe9\x21\xdb\x68\x6c\x25\x82\xf8\x04\xbc\xda\x82\xe0\x46\x7d\x94\x05\xf6\x92\xdc\xf3\x43\xe5\x3a\x3d\x99\x6a\xeb\x09\x8d\x6b\x21\x76\xd2\xfe\x9a\x1f\x5f\x5e\x5c\x20\x39\xda\x15\x9f\x07\x13\x41\x57\x8e\xe8\x84\x6e\x79\x2b\xf0\x77\x77\xe0\x0d\xdb\x4f\x98\x90\x20\x07\x78\xb6\xf7\x60\x8a\x0b\xb7\x96\x61\xc7\x6b\xf9\xb1\x57\x6b\xfa\xa4\xf6\xba\x07\x8d\xb3\x62\x03\x38\x0a\x51\xac\x23\x76\xa5\xbd\x35\x93\x44\x54\xca\x8c\x53\xef\x4a\xaf\xb0\x84\x27\x5c\x47\xc5\xa9\x90\xc4\xe1\xc4\x66\x3c\xc7\x5e\x9b\xc7\xc7\x3d\xaf\x06\x97\x9c\x84\x10\xde\x31\x21\x12\xab\xfd\x87\x29\xa3\xa1\x25\x38\xc3\xb9\x00\x4b\xea\x4c\xe6\x24\xcc\xa1\xc7\x15\x7f\x18\xe1\x97\x0a\xed\x99\xfa\x64\xf9\x38\xb3\x12\x1a\x2f\x00\x26\x94\xa4\xd8\x3e\x57\x73\x54\xfe\xfd\xc0\xcb\x22\x3f\x6e\x16\x31\xfe\xbb\xe9\xb7\x2c\xeb\x97\xd8\xda\x9e\x38\xea\xb9\x98\x1f\xc4\x58\x11\xe5\xbd\xc4\x9d\x7a\x92\x2b\x9f\x6f\x27\x4b\xbd\xee\x6a\x7f\x47\x6f\x0b\x36\xd5\xdc\x90\xbe\xa5\x1e\x4f\x5d\x88\x42\x53\x21\xd7\x2c\xc3\x7a\xcb\xde\xce\x88\x2b\xd4\x43\xdb\x33\xca\xd9\x07\x10\xa0\x36\x87\x69\x93\x1d\x03\xd9\x6a\x73\x27\xa1\x13\xfd\x7b\xe1\x83\xd4\x95\x13\x62\xb9\x24\x38\xc0\x03\x02\xd6\x44\xe6\x21\x11\x12\xc3\x9d\x65\xc0\x3a\xe6\x29\xd4\xde\x5c\xc4\x0b\x63\xdc\x79\xc8\xe5\x85\x0a\xee\x92\x27\x61\xf6\x4b\x92\xae\x6b\x1c\xcf\x38\x39\x2d\x8b\xfb\xcc\x66\xf9\x26\x1e\x84\x41\x48\xd6\xdb\x63\x7f\x0e\xf1\xb0\x1c\x52\xbc\x82\xc5\x88\xb8\xf7\xe1\x36\x40\x61\xdc\x18\x5b\xbd\x02\x14\xe5\x29\x61\x9b\xe5\x89\xcc\xe4\xec\xde\xaa\xcf\x7b\x58\x0a\x76\x0e\xf7\xae\x76\x8a\x50\xe7\x33\xb9\x97\x9c\x93\x66\x01\xfa\x20\x7b\xb1\xe7\x91\xcf\x55\x5b\x81\xc5\xb1\x0d\xdd\xf0\x3b\xb2\x86\xc8\x80\x25\x7c\x62\xd0\x14\x7f\x0c\xdc\xde\x81\xc2\x48\x7e\xe3\xd8\xa3\x44\xdf\xf6\xe7\x25\xc0\x94\x6f\xc2\xa0\x1d\x61\x59\x80\xc6\xf4\xd6\x0a\x36\xe9\x24\x54\xad\xbf\x61\x6b\xcd\xc4\x42\x81\x2c\xf8\x69\x79\x39\xf3\x76\x12\xc8\xac\xb6\x2d\x04\xc1\xe4\xca\xe0\x52\xfa\x91\xea\x75\x9c\xad\x07\x6c\x18\x63\xe7\x43\x2c\x7e\x31\x67\xf5\x0c\x3d\xef\xb8\xf2\xe2\x1c\x11\xad\xee\x67\xb8\xd4\x88\xed\x34\xbb\xb2\x08\x16\x4c\x01\xca\x20\x88\x8f\xb4\x5e\xce\x1c\x41\xc0\x8d\x41\xb6\x9e\x09\x2c\xce\x16\x99\x1f\xcb\xad\x59\x22\x6c\xa0\xad\xed\xa7\x12\xc6\xcf\xb4\x3d\x19\x96\x02\x10\xa6\xa3\x5e\xe7\xdd\x71\xd4\x92\x07\xd2\x1a\x3d\xd8\x3d\xe8\x0a\x52\xd9\x7d\x97\xef\x32\x1e\x95\x6f\xb9\x77\xb3\x75\xdb\x61\x68\x24\x5e\xc1\x9a\x78\xc6\xb9\x4a\x90\x67\xb7\x69\x19\x89\x88\x24\xeb\x37\xe3\xf8\x53\x0c\x20\xe2\xc6\x89\x80\xc5\x1c\xeb\x2b\xf0\xe3\x36\x26\x44\xe9\xf4\xc0\xb3\xd2\xf1\x1a\x26\x28\x5f\xfc\x06\x8d\x9a\x1f\x9a\xf8\xd0\xbe\xe9\xa2\xea\x4f\xb8\xf1\x11\xe7\x7b\x5b\x06\x52\xba\x1d\xde\x63\x16\xfb\xc6\xf0\xba\x05\x87\x5d\x65\xc9\xe8\xb5\x81\xd4\xca\xa5\x1a\x00\xaf\x5c\xa1\x6e\xb1\x59\xf4\xe4\x48\xae\x2b\xb1\x02\xcd\x29\x80\x18\x05\x3e\xda\x56\xae\x8b\x51\xcc\x88\xce\x35\xe9\x33\xf4\xa4\x7c\x46\x36\x6c\xab\xac\x39\x6a\xad\xdf\xac\x89\x16\x86\xf1\x03\xa1\x70\xc5\xf6\xcc\x25\x88\x45\xf3\x07\xff\x20\x21\xba\x34\x08\x44\x94\xce\x3b\x2d\x67\xb2\x98\x51\x3a\x73\xb8\xec\xae\x7e\x96\x48\x57\x45\x30\x60\xde\xed\xa1\xe6\x22\xb1\x15\x53\x0a\x31\x70\xe6\xff\xdf\x9e\x16\x17\xbf\x3b\x72\x07\x69\xb0\xe9\xa8\xe6\xc2\x54\x54\x8e\xd1\xc2\x97\x41\xea\xf0\x8c\xee\x37\xf4\x30\xf1\xcb\x67\xa7\x67\xcf\xc5\x5d\xb0\xfc\x16\x2c\x77\xf1\xb4\x6b\xf3\x0a\xc9\xc4\x1b\xa4\x80\x05\x30\x3f\x82\x8c\x6a\xbd\xf4\x8f\xc4\x97\xfe\x7f\x59\x86\x59\x9a\xe8\x6a\x17\x7d\xd2\x88\xd7\xd0\x7b\x0a\x30\x20\xf9\x27\x84\x4c\x43\x28\x7f\xd0\x00\x22\xa6\x6a\x7a\x55\x23\xff\xe4\x61\xeb\xf6\x7c\x22\xa5\xb9\x7f\x25\x4e\xaa\x48\xb4\xcc\x84\xfc\x4a\x60\x85\x32\x1a\x5c\x57\xc8\x0c\x0c\x8e\x59\x83\x40\x9c\x23\x71\x46\xaf\x68\xfe\xc1\xc0\x30\xd6\x7f\x0c\xdb\xa8\x7a\xdb\xb1\xf0\x9e\xdf\xab\xad\xe1\x16\xac\x72\x54\x60\x6c\xc2\xd3\xd6\x29\x47\x96\x4c\xde\x08\xe5\x0d\x68\x27\x54\x93\x90\xac\xde\x81\xf7\xa2\x9d\x04\x7a\xc4\x52\x8d\xa2\x0a\xcd\xda\x1b\xeb\xb3\xc1\x56\xd9\xa6\x99\x71\xd2\xda\x0c\xb2\x86\x81\xc7\xe9\x67\xca\xb5\x86\x5b\xd1\xbf\x1e\x91\xa6\xe7\xc0\xfa\x43\xd8\x08\xdf\x00\x0f\xd3\x2c\x95\x81\xa0\xbd\xa1\x1a\xea\xc0\x3b\x62\xf8\x92\x99\x1d\x89\x78\xdd\x71\xdc\x21\x7b\x62\x34\xa7\xc0\xda\x03\xcb\x6c\xe1\xce\x09\x69\xe5\x3c\xfb\x1d\x5c\xf0\xac\x7b\xe8\x9e\x65\x14\xfb\x91\x19\xb9\xd8\x54\xb2\xa3\x40\x4f\xff\x59\xf3\x64\xe6\x09\x18\x2f\x48\xaa\xe2\x30\xcc\x2e\xc7\x48\x9f\x48\x02\xc9\x01\xc5\xfa\xfa\x4b\x8c\x8c\x93\x98\x35\x49\x79\x20\x8c\x22\x14\x9b\xe0\x25\x9b\x2c\xae\xad\xc2\xf9\x85\xdc\x01\x62\x55\x0d\x58\xb0\x47\x2f\x7a\xee\x37\x51\xb9\x76\x88\xa7\xc1\xb6\x25\x5a\x69\xee\x88\x9c\x1e\x16\x83\xec\x78\xa1\x46\x5b\x68\xbe\x74\x6d\x59\x58\x7a\x79\x08\xb9\xc4\x9f\xd8\xba\xed\xe2\x67\x41\x7c\x52\x27\xfb\xb8\x15\xc8\xfb\xc3\xa0\xfe\xad\x26\xd6\xbb\x6e\x24\x24\x1d\xc0\x9e\x1c\xc8\x6c\xe9\xcb\x44\x14\x45\x5c\x5c\xd8\x86\xb3\x3c\x79\x80\xe4\x46\xe8\x8e\x76\x37\x2c\x9a\xba\x61\xd3\x24\x44\x7d\x67\x26\x49\xc5\x52\x72\x0d\xac\x3c\x1f\xd5\x7d\x76\xa3\x81\xd8\x40\xd2\x1c\xfb\x8b\xbd\xb1\x46\x7d\xfb\xe6\x7f\xfc\x40\x44\x9a\x10\x5d\xca\x04\x20\xee\x84\x3f\xe0\x75\xc8\x7d\x06\x6a\xa4\x51\x8d\x59\xb6\x66\x88\x8a\x1f\x48\x3b\x44\xe5\x1b\xa5\x48\xea\x69\xa9\xeb\x54\x3a\x33\xc1\x50\xf9\xc5\x54\x70\xe5\x97\xf2\xb5\x14\x28\x9b\xda\x32\x9d\x91\x21\xff\x4c\x18\xee\x8d\xd7\x78\xca\x72\x12\x68\x9b\xdc\xfa\xbe\x91\x6e\x2a\xfe\x42\x17\x18\x50\x7b\x92\xe4\x07\xd9\xdb\x27\x54\x09\x40\x11\xc0\xac\x8a\x46\x01\x28\x2a\xf3\x5d\xe0\x41\x10\xbd\x65\xc9\xcd\x11\xc6\xc3\x8b\xc9\x3a\xac\x96\x9b\x4d\xe2\xfa\xed\x68\x58\x10\xd2\xa3\xd5\x09\x24\xf5\x0b\xf1\x39\x2e\xba\x99\x99\x2d\x66\x54\xd2\xcb\xc7\x9e\x60\x05\x7e\xd6\x6e\x3f\x35\x19\x88\x4f\x52\x7b\x64\xc7\x97\x29\x9a\x2d\xf2\x6b\x04\x66\xfa\xd6\x74\x60\xc1\xc1\x75\x45\x5d\x99\xb9\xe1\x06\xbc\x0b\x81\x58\x31\xdd\xbb\x2d\xa5\x5d\x28\x7b\xeb\x8a\x6c\xcf\xbe\x26\x4c\x18\x2c\xff\x7c\x11\x76\x5b\xcc\xf0\xb6\x4b\x83\x6c\xfe\xf9\x8d\xe6\x6f\xf1\x9a\xf9\xa4\x85\x18\xc0\x33\x92\x29\xb2\xda\xb6\x0e\x63\x4d\x74\x43\xe3\x56\x2b\x61\xbd\x03\xad\x99\x64\xe4\xf6\x5b\x77\xb8\xfb\x01\x1b\x02\xe0\x58\x31\x0d\x5b\xe8\x6e\xa0\xde\x55\x3f\xb6\xfe\xa5\x96\xdf\x19\xf1\x5f\xd0\xbc\xe5\x26\x24\x64\x98\xbe\xd6\x55\x08\x3f\x14\xb9\xa1\x48\xd8\xc4\x5e\xca\x83\xd1\xe2\xcb\x59\x69\xe5\x40\x40\x09\xfc\x99\xe5\x0a\xe2\x10\x7a\x50\x68\x99\xd3\x61\xdb\xb3\x96\xe5\x89\xa4\xf9\x29\xff\x16\x56\xda\x7a\x7b\xd8\x59\xeb\xae\xb6\xc1\xb1\x49\xc0\x67\x90\xf5\x32\x92\x97\x26\xd6\x87\xb8\xb3\x46\x24\x5b\x37\x93\x5d\x7b\xe4\x22\xce\xab\x98\xef\x84\xcf\xa8\x84\xc2\x61\x52\xb5\xb6\x4c\x97\x2d\x76\x02\x09\xa9\xc4\x8f\x2c\x08\xdd\xc8\x52\xb4\x7e\xa0\xe7\xb5\x38\xa2\xa0\x27\x67\x25\x20\x26\x46\xd9\x0c\xdf\x25\xa9\x8b\x59\x80\x1a\xc6\x65\xc6\xc2\x8b\xa9\x9e\xc4\xd5\xc3\x8d\xd4\xfd\xeb\x32\xff\x62\x7a\xea\xa2\xfd\x61\x37\xe4\x44\xee\x86\x80\x33\x5b\x7c\x16\x56\x20\xe7\x12\xba\x60\x0d\xae\x82\x18\xef\x4a\xc4\xff\x3e\x8e\x19\x20\xa2\x3b\x34\x4d\xb3\xc7\x4a\x07\x2b\x26\x53\x47\xa0\xa5\xd9\xbd\xfd\xb0\x18\x18\x43\xf3\x70\x6a\x3a\x4c\xcc\x61\x96\x32\x4d\x13\x41\x5a\xe6\xa2\x72\xc9\x79\x03\x22\x53\xa8\x2b\x1b\xda\x67\x7f\x87\xe8\xd6\xec\xd0\x55\x1d\xe5\xf9\xe4\xce\xff\xa9\x9f\x7a\x16\x33\xee\x34\x70\xb5\x4f\xc9\x50\x68\x25\x17\x30\xe8\x8b\xf9\x0b\x1c\xa2\x54\x2e\xbb\x6f\x78\x6e\xe2\x7d\x13\x0f\x85\x27\x91\x2d\x85\xe9\xd9\xc3\xed\xa0\xdf\xc0\x1b\xd4\xb2\x36\x66\x83\x92\x56\x55\xa0\xb2\x33\x00\x3d\x8b\x8b\x08\x5c\x62\x19\x73\xdc\x68\xc6\x46\xe9\xfa\xb7\x4b\xf2\x63\x90\xb8\xd6\xcd\x80\x68\x85\x27\xcf\x8c\x23\x7b\x60\xc7\x18\x4a\x23\xe6\xbe\xc2\x09\x9e\xe9\x9f\xdd\x83\x98\x59\x6a\x0f\xbc\x38\x08\x91\xe4\xfa\x4d\x76\x26\xc4\x28\x30\xe9\x48\xe7\x4e\xe2\x05\x0a\x57\x17\x2f\x81\xae\x0c\x13\xab\xb5\xd0\x2e\x55\xb5\xde\xfa\x85\x1a\x3e\xfd\x8e\x96\x18\xca\xa8\xd8\xc5\x7a\x20\x98\x1c\xf9\x10\xcb\x72\x8a\x7d\x21\x32\xf1\x2c\xd0\x22\x41\xda\x41\x7d\x63\x1e\x64\xb5\x2e\x38\xc7\x8e\x34\x7a\x96\x5b\x1a\x37\x67\xfa\x20\xbf\x0a\x35\x31\xa3\x21\x2c\x3d\xe1\x8a\xc7\x7c\x0f\x18\x57\x22\x7e\x10\x06\xe4\xd6\xc2\xa0\x79\x00\x7d\x77\xa6\x3a\x33\x5f\xe9\x0a\x1f\x8f\x59\x62\xae\x56\xfe\x9e\x15\xbb\xf7\x3a\x6b\x41\x00\xa1\x11\xf9\x20\x51\x2d\x7e\x2e\xf4\xb2\x93\x99\x30\x15\x10\xbe\x64\x07\xf5\x60\xdc\x25\x33\xf9\x5b\xa2\xe4\x34\x08\xe7\x92\xbc\x55\x2d\xc0\x8b\xbc\xc8\x2b\x37\xda\x16\xe2\x95\x56\x0b\x34\xee\x70\x25\x78\x9e\x84\x47\x17\xff\x49\xf8\x5c\x41\xa3\xee\xd9\xab\x91\xd1\x12\xe3\xd6\xbd\x5b\x20\x68\x8c\xab\x40\x1e\xca\x49\x33\x7f\x47\x49\x6a\xcc\x13\x81\xd1\x61\x74\x06\xfe\xc5\x59\xd9\x4d\xf6\x69\x31\xe2\x6a\x17\x5c\x70\x46\x9a\xd7\x96\xae\x0b\x78\x02\x2e\x76\x48\xb0\xeb\x01\xe0\xac\xfc\x49\x46\x97\xca\x62\x00\x20\xa3\xcf\x80\x93\x04\xb0\xdb\x8e\xe7\x54\xde\xb0\x2f\x2f\xa0\xe4\xb6\xe5\x6f\xd4\x63\xab\xd2\xc9\xf0\xd4\xea\x50\x22\xe0\xa5\x2b\x5d\x34\x51\x12\x0a\x32\xf1\xd7\x7a\x21\x50\x40\xb1\x5a\x1b\x0b\xc7\xb7\x6d\xe3\xe2\x89\xb9\x16\x23\x8c\xef\x17\x9f\x1a\x29\x30\xc6\xce\x6a\x43\xe5\x16\xc3\x7c\x2a\x4f\x00\x41\xc6\x11\x0d\x8b\x97\x88\x12\xee\xd3\xc2\x16\x78\x58\xcf\x9d\xee\x72\xe4\xc1\xcd\x1b\xbb\x3a\x25\xfc\xcd\x87\x59\x53\x71\xb2\x76\x7a\x1d\xd5\x6e\xe6\x9c\xbc\x66\x14\xcb\x95\x79\x55\x24\x36\xb3\xcf\x55\x3a\x60\x70\x0a\x13\xf9\x45\x38\x76\x06\xc2\x15\x04\x1d\xca\x0a\x6c\x6e\x83\x71\x4c\x66\x62\x9a\xcd\xcb\x62\x72\x10\x81\xc2\x91\x89\xa3\x20\x87\x07\x63\xd5\x8e\xaf\xee\xc4\xa2\xb8\x87\x43\x4c\x0c\xfb\x42\x1e\x39\xc9\xd1\xc5\xe3\x99\x9b\x98\x4a\x7b\x3b\x81\x8e\xf0\x84\xde\xf5\x1b\x41\xdf\x15\xc4\x74\xdb\x36\x1b\x9d\x09\xa1\x02\x73\xa8\xf3\x2c\x58\xba\x74\xc2\x4e\xd9\xef\x01\x4d\xc8\xfd\x74\xca\x1b\x36\x5a\x63\x90\x08\xf2\x84\x78\x64\x98\x7d\x2e\xd7\xd6\xbd\xa2\x70\x27\xa7\x42\xb4\x3f\x6c\x4b\x45\xad\x89\xac\xeb\xd1\x38\x17\x2e\x90\xb2\x13\x1f\x56\x51\xe3\xc1\x09\x5e\xe0\x5c\x58\xab\x09\x53\x05\xcb\x51\x52\xcf\xd7\xa8\xf9\x9a\x8b\x96\xbc\x00\x56\x96\x94\xa1\x49\xa9\x2d\x86\x7c\x7a\x51\x58\x5e\x90\x7c\x1e\x85\x34\x02\x63\x42\x04\x09\x17\xc9\x2f\x6a\xea\x17\xc6\xb6\xef\x41\x37\x71\x90\x62\x76\x78\xc9\x99\x9d\xf6\xd2\xa4\x7d\x14\x16\x98\xaa\x1b\x40\x35\xd9\xfc\xb8\x99\x69\x6d\x3a\x1d\x2e\x32\x9e\xa1\x9d\x82\x64\xc9\xe9\xd2\x77\xb7\x52\x12\x3c\x99\x7d\x0b\x5f\x47\xab\x51\x63\x75\xdf\x41\x78\xfa\x8b\x5a\xc9\x39\x5e\x40\x86\x8b\x83\x3a\x91\x6a\x1b\x5c\x92\xa7\xbb\x4e\x4d\x3c\x90\xe5\xc8\xad\xc7\xb3\x2d\x08\x6e\x35\x98\xb1\xd4\x2e\x5c\xd9\xf3\xb8\x43\x79\x48\x08\x9d\x73\xb1\x54\x5e\xfd\x61\x72\x00\xd2\x8e\x50\x05\x90\xc1\x24\xa6\xa5\xdf\x48\xa7\xae\x25\x46\x7c\x40\xbf\x10\xcc\x34\x59\x27\x5b\x96\x78\x4b\x84\xf8\x7c\x78\xdc\xec\x95\x0d\x46\x0a\x4f\x87\x7a\xe7\xd0\x3d\x7a\x76\x02\xe5\xda\xb5\x78\xc0\x8b\xac\x0c\x40\x8b\x47\xcd\xf7\xbd\x35\x5b\xc5\xde\x88\x65\x03\xd0\x8d\xfd\x50\x4c\x04\x37\x03\x3c\x0c\x3c\x43\xc3\x69\xd9\xbc\xb2\x83\x83\xf1\xec\x66\x45\xe6\xe2\xa5\xc5\x2b\x48\xd2\x88\xda\xfe\xaa\x55\x10\x4b\x10\x66\x24\x18\x9b\x1a\x7e\xa0\x51\xcd\x03\xf0\x0b\x77\x3c\x9e\x83\x75\xd3\x82\xb3\x27\xd4\xa3\xc5\x3b\xb1\x74\x9e\x9c\xa4\x26\xf6\xd8\x73\xa1\xd2\xc9\xea\xcb\x49\x72\x57\xfb\x90\x5b\x7c\x4f\xf6\x92\x39\x10\x98\xe2\xa9\xd6\xc1\xa2\x97\x46\x95\x6f\x58\x14\x6c\x1d\x2c\xbe\xa1\xbc\xe5\x41\xe8\x18\x64\x0c\xb5\x5a\x4e\xb7\x94\x4f\xed\x04\x0c\xe8\x2b\x2f\x42\xce\x72\xa4\x59\x62\xb9\x87\xb3\x64\x7a\x23\xa7\x82\x06\x0e\xd5\x93\x6e\xe4\x54\xbb\x12\x62\x8f\x19\x75\x6c\x1d\xc1\x4d\x3f\x80\x48\xc4\x33\xa1\xf2\x1c\xaa\x39\x02\x56\x59\x70\x2b\x43\x5f\x12\x71\xa7\xb0\x5a\x09\x3d\x28\x2f\x17\x3e\x44\x62\xf3\x6a\x81\xd0\x9a\xae\x61\xc0\x5f\x08\x17\x98\xc2\xbc\x80\x21\xc9\xb9\x25\x1a\xd6\x5a\xb2\xba\xbe\x98\xfd\x41\xe1\x9a\xb5\x4a\x6d\xa9\xc1\x52\x70\xc0\x17\x86\x67\x9a\x31\x68\x4e\x25\x8e\x3d\x02\xd1\xc8\x8c\xfa\xdd\xf4\x6a\x21\xd3\x7e\x53\xa9\xe5\x8c\x13\x3b\xdd\x89\x12\x15\xdc\x56\xcd\xf8\xfb\x8e\x96\x28\x27\xe3\x76\x16\x4a\x43\xf9\x6c\x2b\x49\x1f\xac\x26\x03\xa7\x73\x5c\xf4\xde\x31\x98\x13\x3b\x4e\x93\x23\xfb\xcf\xf4\x38\x62\x27\x3f\x12\x00\x90\xb7\x8a\x38\xa4\xc9\x53\x7b\x02\x77\xe1\xc3\x3a\xaa\x5f\xea\x3c\x80\xbe\x89\x7d\x74\x6a\x80\x13\x64\x24\x53\x64\x24\xa1\x06\x09\xa6\x75\xea\x9e\x9b\x2a\x55\xd1\xd9\xab\x28\xca\x19\xc1\x97\xc8\x24\xd9\x43\xca\x7e\xe0\x61\xe9\x92\xa0\xb3\x8e\xe1\x11\x5e\xe0\x7f\x7f\x53\x5c\xc9\x53\xbe\xe4\x1a\xb3\xb4\xb1\x85\x85\x31\x78\xe5\xd3\xb6\x7e\x90\x94\xd4\xbd\x28\xf5\x1b\x5e\x2c\xd0\x6f\xb0\x90\x7a\x79\x19\xec\x88\x3d\x6c\x33\x89\xa4\x61\xcb\x38\xcf\xc0\xc4\x2a\x1c\xa4\x3d\xd7\x7d\x06\x64\xac\x7f\xfa\x04\x0e\xc9\x32\xc0\xb8\x3d\x70\xfe\x7e\x0a\x8d\x71\x0b\xe4\x81\x6d\x71\x61\xa6\xb5\x71\xb9\xf5\xbf\x66\x16\x12\x42\x14\x89\x38\x33\x56\x52\x6e\x3e\x3d\xbd\xfc\xb9\xf6\xd7\xbe\xd2\xec\xae\x3d\xa1\x96\x65\x10\x6e\x22\x6a\xc9\x1c\x44\x5d\x2d\x8e\x45\x4b\xf6\x6b\x0e\x0a\x04\x9a\x8c\x78\x82\x2f\x23\x2f\x12\x58\x3f\x1d\xf8\xad\x51\x2f\x4e\x2f\xaa\x9e\x44\x44\x32\xe2\x9f\xe8\x60\x87\x96\xea\xf0\xbe\xf0\xa5\x57\x0c\xa4\x05\xc4\xee\xec\x51\xc9\x6f\x9c\x89\xa4\xdc\x2a\x37\x61\x16\x0d\xb9\xf9\x63\x21\xee\x00\x4b\x36\x0f\x52\x3c\xbe\xad\x3c\x7a\x06\x6d\xb3\xa7\x39\x11\xa1\xe3\x3d\x08\xea\x65\xc3\x3b\xec\x91\xc4\xb0\x83\xc6\x16\x1c\x27\xa3\xa5\x34\xbe\xae\x25\xe5\xa7\xc4\xc6\x01\x95\x93\x16\x09\x70\xa9\x2f\xb2\xc8\xd9\xec\x8c\xfe\xd5\x00\x87\xb9\x77\x44\x51\x24\xde\x3c\x50\x92\x76\x0e\x8f\xbb\xf9\x7e\x27\x00\x1d\x6f\x7c\x68\xe3\xf5\x51\xcf\x4e\xaf\x7a\x79\x31\x2f\x7f\x70\x0d\x32\x41\x61\xcd\x7c\x71\x66\x96\xc1\xad\xde\xfe\xa4\x5a\xce\x26\xfa\x0c\x4a\x4e\x40\x49\x59\x83\x5d\x56\x12\xd6\x8e\x6d\x8c\xf6\xac\xb9\xfc\x85\x02\x9d\x76\xef\x21\xaa\x18\x5f\x52\x10\x36\xef\x45\x90\x9c\x3e\x7b\x0a\x21\xb9\x51\xb2\x9b\x6b\xa8\x9a\x5d\x06\xcb\x35\x4f\x5a\x16\x96\x55\x65\xbd\xf8\x57\x2c\x8e\xc0\xf9\x0d\x6c\x1a\xb1\x3e\x13\xf5\xea\xfa\x17\x3f\x8e\x63\x35\x05\x93\x19\x12\x6b\x7c\x6e\x11\x81\xf6\x68\x30\x7d\xfd\x86\xd6\x62\xf4\xf8\xb7\x2d\xcc\x02\x21\xed\x6d\xf9\x28\x7c\x5a\xc6\xe6\x1c\x86\x5d\x63\xc1\xbe\x09\x59\xe0\x49\x5b\x9d\x31\x8e\xdc\x03\x47\xdf\x2c\xe3\x19\x2e\xb8\x99\x56\xba\xc5\x65\x59\x29\xa5\x88\xf7\x90\xb7\xbc\xa3\x1d\x95\xc2\xb0\x56\x4c\xa9\xd3\xf7\x25\x2e\xd0\x3b\x61\x86\x2c\x4c\x3c\xf4\x12\xa0\xdf\xd8\x82\x26\xa6\x29\x22\xe1\x23\x9f\x4b\x7e\xb7\x59\xd2\x14\x6e\xae\xf1\x1b\x68\xf9\x6b\x30\x2d\x2f\x43\x6c\x2d\x02\x3d\xc3\xc7\xd7\xca\x01\x9c\x27\xb0\xe7\x5e\xf9\x8c\x53\xcc\xfe\x8a\x4a\x1d\x7d\x3e\xc8\xaf\x04\x86\x7e\x9a\x9b\x20\x7b\x09\xc8\xcd\x07\xa1\x52\x7b\x3b\x39\x41\x6c\x2b\xda\x98\x2e\x92\x83\x90\x2a\x2d\xfd\x15\x68\xfd\x40\x16\xfa\x97\xc0\x41\x50\x38\x9f\xd8\xc2\x16\x11\xce\x2b\xd8\xce\xf2\x6d\x49\xb7\xbd\x4d\x46\x85\x50\x31\x13\xbe\x56\x9a\xbd\xb2\xf0\x72\xd0\x98\x55\x21\x09\xf7\x91\x75\xbf\xed\x2c\xd1\x55\xe7\x17\x72\x27\x79\x7b\x22\x21\xd1\x5e\x6f\x8f\x0e\xfb\x2f\x0e\x63\xc9\xfd\xe4\xd5\x95\xf3\x93\x90\x33\x5b\x1d\x42\xcd\x97\x9d\x5e\x65\x9a\x58\xdc\x32\x31\x3e\x13\x4b\xb5\x74\xd4\x35\x79\xac\x25\x21\x25\x58\x78\x97\x89\xcc\xce\xb6\xb1\x0a\xbe\x15\x66\xc5\x8a\xd4\xe0\x80\x0f\x7e\x90\xc4\x12\x2f\xbb\xb1\x5a\x29\x1f\x3c\xa0\x8b\x5b\x16\xd1\x9d\xf1\x53\xb4\xca\xd0\x1c\x75\x4b\x03\x1d\xce\x65\xc2\xf3\x86\x5e\x09\x9d\x9e\x12\x14\x24\xb7\x62\xf0\xa0\xa4\xab\x68\x9e\xd8\xae\x52\xbe\x66\xc4\x36\x4e\x36\xd7\x96\x5d\xb6\x56\xd2\x80\x05\x0f\xc7\x1a\xb7\xc6\xf5\xfa\x0d\x6f\xe7\xc8\xbd\xed\xf8\x6d\x73\x6a\x1a\xda\x5a\x36\x7a\x6f\x2c\x8c\x35\xe7\x39\xab\x8d\xc4\x1d\x94\x70\x9a\xd8\x02\xb9\x26\x4e\xf4\x5a\x71\xce\x02\x69\x68\x4a\x38\x7a\x18\x1a\xee\x0c\x48\x83\x88\xe7\x4e\xb8\x27\xd8\x5a\x2e\x8e\x07\x07\x40\x3b\xb6\xf4\x28\x72\xc6\x76\x8f\x64\xe5\x2e\x3c\x80\x12\x47\xf0\xaf\x1d\x7d\xb0\xf8\xc9\x02\xf4\x0a\x9c\x62\x88\x76\x98\x7e\x98\x56\x6e\xa3\xf4\x5e\x16\x52\xab\xe6\x9e\x5f\x5e\xa6\x84\xf3\x89\xdc\xc1\x33\xae\x95\x01\x9f\x57\x22\xf4\xd3\xcd\x2d\x77\xad\x5d\xd2\xd1\xea\x79\x60\x99\xfc\x26\x8e\x6f\x70\xa1\xa4\x28\x83\x9e\x51\x24\xa0\x35\x67\x7c\xfe\x61\xf8\x1d\x1f\x7a\xfb\x9f\x6e\x90\x3b\xa8\x01\x5e\x0e\xb4\x3f\xbd\xc0\x1f\x69\xca\xc5\x94\x2e\x80\x5b\x3d\x75\xd0\x17\xb4\x4f\x6f\xf1\x96\x8a\x81\xb7\xe7\x70\xe0\xee\xdc\x5f\xaa\x8b\x7e\xf5\x09\xbf\xa0\x4c\x0e\xc3\x7d\x39\xb7\x73\x4d\xce\x89\x9a\xdd\xcf\x83\x19\x9b\xbc\x55\x43\xee\xb1\x36\x27\x90\x3d\x5e\x4f\x22\xf9\x62\x86\x26\x7b\xdf\x83\x39\x8e\x5e\x61\xec\x11\x48\x87\xa8\x64\x00\x3a\xb0\x5d\xc5\x21\x61\x5b\xcf\x4a\x33\x2e\x31\x8a\xbc\x07\x48\xde\xcb\xc2\x1b\x93\xfb\x0f\x49\x0d\x6f\x33\x06\x3f\xf2\xb6\x04\x86\xb6\xfe\x39\x51\x2f\xec\x8e\xfc\x2c\xde\x8e\x50\xb7\x12\xf0\x9c\xc5\x88\x73\xb0\x72\x7b\xf2\x8c\xeb\x0f\x8c\xbd\x81\x04\x89\x04\x85\x5c\x1b\x23\x42\xcb\x1b\xd4\x08\xb4\xd7\x36\x47\xa3\x48\xa6\x24\x2b\x2b\x98\x45\xb2\x0a\x83\x38\x63\x5a\x69\x76\x41\xe9\xb8\xe8\xce\x94\xe0\x95\x1c\x48\x79\x5b\xe8\x23\xf7\x54\xbe\x65\xce\x73\x63\xf3\xc6\x82\x53\x56\x95\x04\x7e\x3c\x10\xd1\xe3\x2a\xc9\x8b\x79\xc5\xc8\x96\x56\x21\x0c\xc0\x96\x28\xce\x5f\xcc\x54\xc3\xc7\xfb\xa3\x0c\x98\x63\x0e\x34\x3b\xd3\x49\x72\x05\xb8\x02\x59\x7c\xa6\xf0\x7b\x60\xf4\x21\x26\x09\xdf\xf2\x03\xba\x8d\x45\x2c\x87\x65\x49\x12\x93\x22\xf6\xc8\xc1\x16\x62\xaf\x28\x17\x48\xc8\x1d\x2d\xe7\xd3\x16\x08\x4b\xad\xb2\x64\xce\x96\x31\x86\x09\x05\xb1\xb2\x0d\xce\x04\x36\xfb\xe8\x0b\xf9\x1b\x1e\x91\x4e\x19\xa4\xb3\x1a\xd9\x8c\xf2\x14\xff\x0f\x4a\xed\x41\xff\x55\x78\x9a\xce\xa0\x68\xd0\xc3\x38\x7d\x2f\x04\x74\x92\x70\x8f\xa6\xab\xca\xbc\x76\xa4\x8a\x56\x51\x7a\x80\xdf\xc2\x9c\x65\x50\x4f\x73\xd2\x95\xde\xcf\x4e\xd6\xcf\xd3\xc1\xe5\xc5\xf9\xda\x9b\x86\x7f\xaf\xb2\xc2\x71\x81\x0b\x5f\xb5\x96\x03\x84\xd2\xd9\xa9\x6a\x83\x12\x13\xd3\x99\xbf\xfb\x1b\x2e\x60\xe7\x1b\xb9\xa6\x9b\xa4\xd0\x8c\x7b\x8c\x2a\x64\x9f\xf3\x82\xe7\xed\x8b\xbc\x7a\xff\x67\x57\x20\xac\xc3\xf4\xd1\x21\xdd\x35\xfe\x60\x49\x07\x27\x44\x0d\x26\xd3\x86\xbc\x00\x1a\xdb\xbc\x19\xcb\xda\x70\x0a\x0f\xe7\xc6\x6e\xa5\xa2\x9d\x19\x40\x96\x77\x76\x07\xae\x23\xad\x7a\x16\x10\x19\xc4\xdd\x36\xe7\x44\x6a\x59\x83\x1d\xcf\x4f\x46\x68\x12\x59\x35\x14\x9a\x1b\xb2\x19\x79\x68\xe7\x61\xcf\x19\x88\xf2\xc6\x44\x20\x36\xd9\xa7\x57\xc4\x96\xb1\xd3\x59\xe1\x1b\x5f\x26\x6f\x6b\xc8\x7d\x79\xdb\xfd\x91\x8d\x72\xc0\xd0\xb8\xa3\xc8\x78\xf8\xf7\xe3\x2f\xfe\x85\xf0\x23\x0c\xf2\x07\x38\x5b\x39\x6d\x0f\x4e\x80\xd2\x46\xae\xb0\xe3\xa1\x89\x1c\xaf\x03\x0e\x85\x42\xeb\x76\x68\x25\x23\xe6\x13\x55\x76\xff\x2d\xa3\x25\x64\x66\x09\x3d\x5c\x5a\xf2\xf1\xfb\x82\x4c\xdc\xe2\x5f\x5c\xbd\xb7\xf7\x67\xe4\x42\x36\xa3\x96\xf0\xf0\x1a\xff\x9c\xef\xce\x97\x00\xaf\x36\x39\xae\x26\xef\x09\xce\x0f\xb9\xf6\xd1\xfa\x21\xec\xe7\x1c\x50\x95\x38\xa7\xfc\x00\xef\x7e\x3a\x85\x43\xdc\x35\x69\xc8\xac\x2d\x69\xf4\x60\xb0\x48\xf9\xd3\xd0\x46\x73\x3c\x95\x77\x63\xbe\x55\xc5\x21\xa1\x84\x93\x10\x89\x99\xf5\x1d\xa6\x0f\x10\x36\xab\x2c\x7d\x06\xc3\x45\xb9\x02\xcc\x66\x99\x33\x3f\xfb\x0a\x26\x88\xa6\xc5\x48\xca\x03\x3a\xd4\x15\x8d\xb2\x87\x6f\x6e\x4b\x01\x96\xbd\x47\xac\xa9\x05\x54\xf0\xb2\x99\xd1\x4c\x85\x5d\x61\xcc\xd1\xe4\x3a\xd8\x9b\xcc\xf4\xef\xb2\xff\x16\x9b\x06\x92\x7d\x64\x39\x16\x42\x5f\x0a\xd8\x9a\xc5\x4c\x60\x11\x4e\x1f\xfe\xcf\xa8\x7c\x19\x0f\x17\xac\xbf\x66\xc1\xd8\x6f\xbc\x50\x83\x30\xd4\x7e\xbc\xb8\x96\xd1\x9d\xd7\x65\x1b\x21\x8f\xcc\xb4\xd8\x5a\x86\x82\x5d\xf9\x0a\x54\xa7\x46\x96\xf7\xcf\xf8\x26\x8b\x44\x33\x30\x84\x9a\x7d\xc2\xb2\x06\xee\x9e\xdc\xe0\xb6\x04\x46\xbd\xba\x49\x91\x75\xa5\x99\x2c\xe4\x0f\xf0\x2d\x6d\x63\x75\xc3\x43\xb6\x84\x2c\x7b\x44\xe6\x8f\xb8\xd7\x9a\x66\x48\x90\x91\xe4\x71\xc3\x46\x5b\x31\x99\x5c\x24\x2d\xfa\xf2\xaf\xd3\x75\x79\x05\x6d\x10\xfa\x9e\x39\x38\x54\xb7\x7c\xbc\xdd\x06\x21\xb8\xd8\x17\x1e\x83\x5b\x23\x30\x64\x8b\x4f\xf2\x06\x4a\x20\x61\xe8\x15\x7e\x0b\xeb\xb3\x4e\x74\x55\x4b\x0b\x06\x76\x20\x51\x5c\x92\x64\xfa\x2b\xd9\x22\x27\x5c\x94\x81\xe4\xb0\xea\xf0\x1e\x40\xa7\x93\xa0\xa6\x18\x6d\xfd\xac\xa9\x0b\xb4\xaa\x4b\xe3\x1c\x42\x3a\x84\x9b\xe7\xd2\x6f\xb0\x9b\xc3\xd7\x8e\x77\x25\xc8\x22\xd8\x8a\xe6\x95\x16\x72\xaf\x27\x60\x6c\x93\x86\xd0\xa0\x7e\xc6\xaa\x7c\x30\x5d\x97\xc8\x9a\xfa\x12\x47\x29\xe6\x76\x4a\x9b\x3a\x8b\x93\xd9\x33\xa9\x31\x5a\xf8\x64\xbf\x1b\x2c\x6f\xe9\x0d\xe4\x17\xb9\x8d\x12\x18\x03\x86\x77\xb6\x43\x42\x62\x6d\x0c\x76\x7b\x91\xff\x3a\xe3\x8e\x51\x7d\x42\x8c\x62\x27\xce\xd8\xcb\x33\xf2\xc6\xd3\x7e\xd1\x10\xa9\x07\xb3\xc7\x37\x57\x5a\x6d\xb7\x7c\xd5\x33\xb3\x8b\xb6\x15\x67\xc0\xea\xee\x23\xe6\x60\xa1\x9b\x2c\xee\xec\xb5\x48\xb9\xfc\xde\x96\x6e\xf1\x04\x8b\x16\x4c\xbc\xfe\xd3\xbe\x18\x8f\x00\x34\xe1\xbd\xd4\x4c\x19\x20\x90\xae\xc6\x83\x3e\x7b\xaf\xff\x1c\x26\x23\x9a\x1a\x3c\x96\x58\x3e\xd7\xbb\x07\x9f\x74\x1b\x95\x9c\xa7\xa9\x54\x4f\xba\xd8\x7f\xa0\xd4\xc9\xd1\x9f\x08\x26\xb0\x15\xf8\x18\x6d\xad\xac\x06\x99\x4a\x82\x61\x13\xc1\x5e\x7f\x4b\x15\xb7\x78\x01\x0f\xeb\x2a\xc9\x5d\xbc\xd2\xbd\x07\x54\x1f\x58\x73\x89\x60\x3d\x07\x64\x23\x77\xf5\xd8\xdf\xe0\xff\x07\x4a\x55\xf2\x33\x50\x84\x20\xa4\x9d\x03\x5b\x7a\x67\x39\xca\x97\x9d\x88\x13\xf5\xdb\xb7\x6c\x27\x5c\x58\x6c\x13\xab\x92\x6c\xfe\xfc\xd1\xc2\xa5\x77\x0a\x28\x55\xe7\x41\x01\x05\xbb\x82\x4e\x6b\x3d\x5c\xcf\x41\x93\x10\x67\x0d\x19\x5b\xdc\x9d\x14\xb0\xa7\x5a\x9e\x78\x7b\xb4\x71\x74\x27\x7d\x9d\xdd\xf9\x67\xf1\x6d\xa6\x2e\x27\xad\x3a\x6b\xa7\x84\x1d\x37\x76\x43\x9c\x4e\x0d\x8c\x23\xf7\x67\x02\xc5\x8e\x2a\x44\x75\xd5\x3a\xd2\x2d\x7d\xbc\x6a\x27\xed\x7d\xde\xf0\x54\x47\x98\xec\x87\x8c\xfd\x8e\xeb\x53\x09\x04\xcb\x76\x8e\x44\x29\xac\xcc\xde\xf9\x0c\x6d\x76\x59\x82\xb2\x79\x73\x8a\x98\x66\x43\xd0\xb7\x32\x84\x4a\x4e\x9c\x10\x74\xa6\xae\x88\xa4\x7e\x63\x22\x9a\x61\xcc\xa1\x4c\x5f\xe1\x7a\x12\x92\xf4\x18\xe5\xc8\x36\xdf\xdb\x57\x36\xea\xaa\xcc\x5f\xcd\x8b\xb7\x73\xcf\x3c\x5c\xda\xdd\x94\xc9\x51\xf9\x0d\xf5\xdb\x6e\x30\x7c\x9e\xd6\xae\xc8\x16\xb8\xd0\xfc\x3c\x1a\x23\x66\xed\x87\xc6\x99\xb4\x45\x68\x17\x43\x3c\x5b\xf8\x81\xb0\x62\xdf\xbc\x63\xc6\xdc\xb1\x5e\x2f\xd6\xc9\x66\x4d\x38\x02\x83\xf7\xc6\x12\xd7\x44\x2c\xa3\x5d\x68\x5b\x94\xc8\x99\x45\x5e\xbd\x86\xd6\x1d\x7c\x21\xf6\xd0\x8e\x31\xc2\xd0\x12\x85\x90\xdb\x5b\x9c\x6e\xab\x46\x8f\xb1\x53\xea\x76\xb4\xfc\x1a\x6d\x1e\xc8\x6e\x0a\x9d\x12\x72\x92\xac\x29\x93\xfb\xcb\x10\x4d\x8c\xcb\xc2\x54\xe2\x62\x4c\x1b\x07\x59\xce\x58\x96\xf6\x5f\xbf\x92\xe2\xd0\xc9\x12\x19\x60\xb3\xda\x39\xef\xe3\x91\xb8\x35\xa7\xd8\x71\xe6\x76\x77\x7c\xef\xb0\x8f\xc5\xd2\xde\x2a\x3a\x29\x03\xce\x11\xf2\xbe\x13\x1d\x24\x35\x08\x56\x32\x17\x25\x79\x59\x11\x2d\x7e\xfb\x2b\x79\xbf\xf4\xc1\xd9\x6b\x15\xdd\xd9\x6a\xd3\x54\x4c\x53\xf4\xac\xdd\x1b\xb3\x9c\x2a\x15\x14\xb2\xb3\xc4\x04\x74\xae\x5e\x27\x24\x3f\x6f\xbc\xba\x3c\xdc\xb2\x56\xf4\xe0\xa8\x4b\x61\x8d\x55\x0c\xab\x73\x80\x8b\x99\x72\x75\xd6\x7a\x48\x11\xdc\xe0\x18\x4b\xf2\x82\x4b\xb1\xb1\x19\xe7\xa3\x84\x1c\x33\x1c\x1a\xc4\xb3\x8a\x4e\x0b\x98\xc5\x9a\x32\x78\xc9\x86\x2a\x6f\x7d\x59\x9d\x48\xdf\x86\x56\x86\x16\x19\x60\xbc\x66\xd2\x52\x08\x33\xbd\x3d\x81\xb9\xd8\xfe\xaa\x26\x61\x08\x62\xac\x9e\x03\x1c\x5e\x9f\x8f\xa0\xc5\xbc\xd5\xb2\xe3\xca\x66\xf2\xc3\x14\x2a\xd5\x15\xff\x41\x58\x94\xe9\xe0\x16\x67\x24\xc9\xee\x1a\xfe\xd3\xc9\x09\xa9\x31\x50\x3e\x84\xa5\x58\x24\x0f\x70\x75\xee\xcf\xf5\xba\xd0\x96\xc3\xbf\x53\xbc\x63\x53\x9e\x15\x7c\x6b\xf4\xa6\xe4\x03\xd8\xa5\x49\x05\x21\x99\x56\x7f\x1f\xf0\x10\x1e\x3a\xc8\x61\x65\x91\xd2\x98\xc7\x56\xaf\x33\x3f\x4c\x1d\xa2\xe8\xe1\x4d\xf3\x60\x5e\x92\x0a\x4a\x3a\x1c\xe8\xff\x32\xc4\x3c\x1b\x00\x27\x97\xe4\xcb\x60\x5b\x3a\xa9\x3e\x8d\xe2\x43\x92\xeb\xb0\x90\x10\x2a\x8e\xff\x93\xf5\x68\x09\x08\x36\x0f\x46\x25\xa0\x95\x4d\xb4\x74\x17\xe5\x50\xbf\x8f\xde\x5e\xba\x39\x6b\xb9\x7a\x77\xbe\xd2\xfa\x3c\x41\xd2\xe5\x9d\x19\xde\xfe\xa1\xa8\x9a\x3d\x12\xc7\x85\x73\x27\xe6\xdb\x70\x01\xe3\x84\x93\x49\x2e\xd9\xaa\x83\xf4\x3b\x0f\xa5\x98\xb8\x9b\xc5\xac\xc8\x26\xcb\x1b\x57\x45\x99\x5c\xe6\x44\x1f\xa8\x40\xb0\x32\x1c\x16\x9a\x83\x77\x71\x4b\xd7\x89\x0d\x9b\x62\x14\xa3\x14\xb9\xa9\xc6\x57\xfb\xe1\xe3\x28\x6a\x30\xfa\x1a\xec\xea\xe9\xc5\x42\x80\xa9\x95\x3d\x3c\xf9\x83\x8d\x55\xcd\xd7\xfc\x64\x7f\xaf\x0a\x03\x10\x14\xa9\x86\xca\x5b\x3d\xb4\x72\x4d\xfe\xeb\xda\x59\x01\x78\x59\x0d\x0b\x5e\x08\xb6\xc8\x5e\xfd\xc7\x41\x27\xd3\x99\xe1\x0e\xa5\x0c\x44\xea\x61\xfe\xbe\x5d\x86\x15\xa5\xdd\x3b\x28\x49\xf3\x30\x3e\x2d\xb3\x7c\xcd\x70\xd0\x20\xf6\x79\xb1\x2d\xd0\xb2\xd7\x85\x95\x92\x77\x20\xfe\x2f\x21\x45\x03\x9f\x4e\xbc\x0c\xab\xb8\x92\xf5\x07\x76\x2b\x51\x90\xe2\xed\xc9\x69\x93\x34\x05\xed\x40\x65\xb4\x32\x6a\xb5\x1d\x2d\xf0\x97\xe7\x81\x9a\x20\x91\x6e\x81\x3e\x24\x25\x13\x06\x14\x67\xad\xbb\x92\x8d\x3d\xbd\x01\xf6\xa2\x4b\x54\x39\x0e\x74\x73\x1e\xe9\xd7\x9e\xea\x43\xbe\x99\x83\x34\x73\xf0\xce\x04\x67\xf2\x24\x09\x57\xf4\xab\xd4\x42\x98\x11\x3e\x29\x05\x66\x2a\x5c\xbc\x8d\xca\x49\xb7\x5b\xdd\x97\xe6\x19\x3b\x59\xa3\x07\x4a\x74\x2d\x01\x05\xde\x7a\x76\x0b\x46\x77\x61\xb4\x72\xe2\x44\x2f\x4d\xf0\xe1\xb1\x09\x15\x49\xb8\x30\xfa\x25\x2d\x1f\xc3\x65\x77\x0a\x43\xd9\x63\x34\xf9\x0a\xf9\xfe\x44\x8c\x98\xc1\xf6\x53\xfd\xb5\x9b\xbd\x49\x97\x9b\x37\x3b\x29\x2a\xeb\xb7\x5c\x8b\xc7\xee\x52\x0c\xc1\xb7\x45\xd8\x8b\xea\x65\xec\xe9\x01\x36\x31\xf0\x50\xf1\x21\x33\x18\x12\x72\x81\x0d\xb2\xad\x68\xf4\x91\x33\x16\x99\x22\x3b\x43\x3e\x7b\xac\x66\x14\x1e\x0b\x32\xbc\x17\x69\xe2\xce\xbf\x3f\x1e\x43\x7b\xc5\x42\xc5\x04\xa6\x07\x61\x2f\x5e\x75\x75\x38\x8d\xa1\x08\x3b\x6b\x00\x49\xdc\x9b\xf8\x17\xd6\xb6\x95\x4f\x6e\x5b\xb0\xba\x83\x90\x5b\x80\x7c\xfe\xea\x95\x3a\x00\xef\xcd\x75\xa1\x0e\x54\xad\x71\xee\x29\x28\xa2\x36\x1f\x5f\x82\xac\xac\x3f\x16\xc9\x86\x82\x10\x1c\xc4\x11\x82\xa6\x18\xce\x2e\x73\x85\xa2\x9b\x7d\xf6\x83\x92\xa0\x4d\xb5\x4d\x5c\xcc\xe7\x31\x78\x56\xa4\xfb\x59\x59\xcc\x1b\x25\x2a\xcb\x4c\xcf\x32\x52\x75\x00\x80\x12\xff\x49\x82\xe2\xa1\xed\xb9\xe2\xb3\x65\x25\xec\xc1\x9e\x5e\x2f\xf0\x0e\x05\x6d\x6a\x65\x29\x57\xcb\x0f\x6b\x00\x75\xf1\x3d\x64\x66\x7c\x87\x15\xa5\x60\x8f\xa7\xd7\x74\x20\xe1\x00\xf9\x2d\x74\x13\x92\x9b\x6f\xe1\x80\xed\x72\xa7\x92\x99\x04\x4b\x08\x1c\x7a\xbd\xe1\x2d\x5b\xcc\x38\x1a\x21\x11\x57\x15\x53\x7a\xb3\xf1\xa9\xe7\x2b\xb2\xb7\x6b\x2e\x23\xea\x50\x9b\xe5\x07\x1a\x00\x1d\x1e\x71\xf7\xd3\x41\xb6\xd1\x1d\x2d\x77\xd2\xe6\xbb\x87\xf5\xfd\xe2\x59\xb1\xf2\x3c\x1a\xb0\x0e\x3b\xda\x6c\x36\x0f\x67\xd7\x70\x50\x9f\xa9\x37\x92\x4a\xeb\x45\xcf\xe4\x2d\x28\xaa\x29\x40\x6f\x02\x6c\x20\x61\x69\xad\x55\xf3\xab\x6b\x15\xce\x5f\x36\xcb\x51\x0c\xaa\x16\x67\xbf\xc9\x9f\x28\x5f\xd6\xf2\xf9\x21\xd0\x7c\xcf\xde\x96\x33\x18\x8a\x47\x71\x77\x4e\x15\x00\x94\x80\x00\x2e\xfd\xbd\x7f\x1f\x8b\xa5\xea\xe8\xbd\xba\xbc\x5a\x70\x8d\xea\xb1\x2e\x0b\x9e\x6d\xfa\x2a\x82\x21\x30\xc9\xdf\xde\x84\xd0\xf4\xb4\xd9\x53\xca\xf9\x67\x00\xdf\x12\xcb\xb6\xc5\xfb\x4a\xac\x8f\x8d\xe5\x9c\xda\x57\x1a\xb9\xc9\x99\xbd\x1d\x60\x4b\x37\x3c\x1c\x34\x4b\x1c\xe7\xd5\x8b\x38\x9d\x72\x33\x46\xfc\x44\x5f\xf1\x33\x7a\x41\x67\xd6\x0d\xa1\x9b\x57\x6a\xd7\x11\x00\xfd\x89\x59\x59\x08\xfd\x6d\x49\x02\x5b\x3b\xdc\x4f\x0f\x93\xf4\xd4\x3c\x40\xd0\x23\x90\x71\x2b\xd1\xa9\x9b\x75\x31\x94\x1a\x50\x9a\x25\xf4\x20\xc7\x4a\xc6\xeb\xe2\x37\x15\xb6\x5d\x2c\x55\x23\x32\xe2\x52\x49\x68\xfc\x63\x30\x04\x2e\xab\x2c\xd1\x2f\xe4\xa8\xda\x9d\xac\x05\x5a\x7b\x3f\x50\x7f\x33\x4a\x3b\x62\x02\x6e\xed\x4a\xf0\x28\x0e\xde\x70\x66\x1f\xeb\x57\x0d\xc5\x3b\x97\xcb\xe4\x12\x69\x49\xc1\xae\xc6\x7b\xcf\x70\x60\xd6\xc6\xc8\xb3\x03\x51\xec\x15\x06\xff\xa2\xef\x1a\x0a\x95\x4e\x08\x8b\xaf\x41\xa4\x77\x24\x6d\x0b\x97\x31\x87\x83\xb3\x5d\x25\x7f\x17\x6f\xf8\xcf\xbb\x2d\xe5\x6e\xda\x17\xb3\x22\x22\x09\xbd\x00\xe2\x4e\xfe\x3d\xd8\x91\x80\x73\xee\x3a\x20\x5b\x01\x06\xf9\x86\xea\x5d\xf3\x36\xb7\x16\x4e\xb6\x58\xee\xee\x6b\x57\xf7\x91\xf2\x7d\x47\x95\xc5\x5a\x64\x04\x43\x13\x0d\x8a\xd3\xdf\xad\x54\x64\x1f\x36\xfa\x30\xd5\x3a\x78\x19\x9d\x21\xd0\x8b\x84\x4a\xe7\x38\x99\x53\x61\x04\x00\xbe\x80\x76\x37\xc3\x88\xcb\x9a\x77\xe3\x74\x6a\xdd\xf2\x6f\xd1\x33\x90\xa3\xbb\xf6\xf0\xc3\x74\x00\x1b\xa9\x6a\x28\x2c\xa8\x42\xd7\xc2\x79\xc9\xb1\xfe\x16\x2b\x30\x29\xa2\x0d\x8d\xcd\xb6\x79\x33\xe1\x9b\x2e\x6a\x04\xd7\x72\xc4\x00\x83\x66\x9c\x0a\xb4\x2e\x3b\xb3\x8d\x45\x86\xa9\xe0\x86\xb8\x5b\x92\x98\x9a\x01\xf0\x9d\xaa\xb3\x04\x4d\x93\x0b\xd5\xf5\x82\xcf\x3d\x8b\xb7\xdb\x9d\x08\x01\xa3\x27\xeb\xba\xcc\x80\x01\x87\x90\x8e\xc7\x04\xef\x33\xb3\x59\x5e\xdc\x3e\x52\x43\x2d\x76\x19\xda\x84\x20\xab\x64\xca\x69\x32\x45\x82\x2f\xef\x1e\x24\x3c\x9f\xd8\x2d\x49\x48\x47\xb5\x75\xd2\xea\xe2\x03\x2d\x60\x5d\xf1\x0d\x3b\x0e\xb0\x33\x92\x05\xb2\x0f\xef\x7a\xc6\xc4\x20\x50\x83\x10\x06\xa8\x91\xa4\x25\x57\x2a\xdd\xa2\x6b\x46\xad\xd6\xfd\x4e\x28\xa8\x1c\x9e\x89\x6c\xaa\x6a\xe7\x09\x68\x26\xea\xf3\xa2\xca\xa4\x3e\xd3\xf4\xb5\x51\x88\x38\xbb\xb9\x57\x5c\x6f\x4b\x07\x8b\x97\x55\x25\xe0\xa2\xfc\xc7\xed\xff\x8d\x66\x08\x24\x1f\xf5\x9f\x69\xb7\xb7\x05\x69\xa7\xa6\x9b\xdc\x62\xa2\x17\x38\x10\x95\xd6\x6c\xf3\x08\xca\x24\x4a\x24\x56\x80\xf6\x1d\xb4\x06\xb4\x01\xca\xfb\x9f\xb6\x04\xf4\x72\xed\x5f\xfa\xb3\x7c\x5a\xfb\xdc\x1b\xc2\xd0\x15\x48\xbc\x1c\x5b\xe7\x67\x68\x7b\x79\x75\x80\x6b\x27\xd7\x65\x80\xd9\xbd\x26\x43\x6d\x6b\xfa\xfd\x85\x5a\x1a\x35\x3c\xbf\x44\xea\x75\x84\x51\x0a\x8d\x90\xf4\xa4\x38\x33\x02\x15\x12\x14\xd6\x4e\xa4\x72\x4d\xf2\xf6\xa8\x31\x5a\x23\xf1\x68\xa0\x5c\x9c\x3e\x4b\x1a\xe9\x25\x77\x0d\xbc\x26\xad\x2f\x11\x25\x27\x0d\x8a\x22\x66\x96\xf8\xd7\xa8\xa5\x8a\x07\x42\x09\x42\x8f\x9e\x5d\x56\x7f\x48\x57\x1e\x04\xe2\x44\xae\x82\xd7\xb8\x0d\x36\xf8\xc0\x2a\xca\x5a\xce\x11\x8c\x1b\x12\x35\x8f\x81\x44\x47\x92\x86\x4c\x06\xce\x42\x5c\xcf\xd5\xad\x62\xc1\x00\x7f\xec\xa4\x92\x71\xb0\xd3\x65\xfc\x8d\x63\x3e\x3b\xf1\xb8\x53\xfe\x08\xbe\xb5\x6a\x8a\x85\x7d\xae\x8b\xcb\xdb\x31\x75\xd5\x36\xca\xea\x0a\x92\x0a\x76\xa0\xf8\x04\xfa\x9d\x69\x84\x51\xe0\x66\x75\x05\x46\x55\xa7\xc4\xe2\x2b\x8b\x08\xf7\x5f\x2c\x42\x7f\x50\x23\xd5\xd2\x8f\xbd\x46\xb3\x6d\x3f\xc4\x7e\xd0\x2b\xc4\xa3\x1c\xc7\x2b\xa8\x75\xa4\xcb\x3d\x59\x5e\x2e\x68\x9b\x6b\x1a\xfa\xd9\xb9\xae\x41\x33\x7f\xd2\x0b\x6e\x87\xc6\x0e\x38\x5f\xb9\xea\x41\x2d\x91\x6a\x21\x46\xb3\x49\xda\xde\x88\x0f\xd5\xf6\x5b\x5b\xd0\x27\x41\xa1\xd9\xf1\x75\x40\xa8\x0c\x39\xa8\x13\x60\x25\x79\xa0\xae\xfd\x9c\xb1\x70\x9a\xab\x77\xa4\x5c\x5f\x79\xbc\xa0\x14\x01\xdb\x3a\x92\x65\x74\x03\x5a\xa9\xd6\xc5\x65\x3a\x7a\xe4\x14\xb0\x02\xf8\x2c\x60\x4f\x68\x76\x05\x57\x32\xef\x5e\x27\x88\x5e\x1d\x38\xe8\xc1\xc4\x91\x02\x8f\xc7\xa7\x69\xce\x27\x11\x00\x68\xcc\xaa\x51\x61\x7f\x51\x92\xa6\x3a\x0a\x74\xe3\xee\xbe\x3f\xd9\x3c\x9f\x84\x75\xd4\x9f\xba\xba\xd7\x3f\xcc\x0b\xd9\xc5\xec\x6e\xa4\x26\x63\xc2\xe1\x6e\x58\x9f\x8f\xea\x5c\x21\x33\x20\xd4\x10\xea\x3f\x7b\x5c\xd8\x25\xed\x34\xe9\xe4\xc7\x33\x20\x9d\xbe\x4d\xf7\x72\xf2\x0f\x0b\xf6\x8d\x6e\xf1\x00\x53\x89\xbe\x1b\x77\xa1\x53\x09\x33\x7a\xc5\xe7\x9d\x66\xe7\x42\x65\x17\x0e\xbd\xb7\x34\x95\x85\xde\xe5\x24\x46\x9c\xc3\xab\x40\x65\x02\x19\xe5\xcc\xb4\xdd\x4a\x1a\x8d\xcd\x42\x48\x79\x02\xc4\x01\xb2\x15\x36\x2c\x43\xda\xe5\xb1\xcd\x70\x1d\x44\xb6\xb7\xea\x61\x96\x24\xdb\xa8\x4b\xbf\x63\x3c\x90\x91\x6f\xe8\xe5\xf1\xb4\xa9\x19\x52\xe9\xb7\x4c\x15\xfc\x6c\x8b\xa1\x27\x17\xeb\x82\xda\x9e\xe2\x61\xbf\x7f\x1f\x5e\x7f\x33\x88\x83\x5e\xd0\xb1\xab\x27\x96\x42\x3a\x31\x79\xeb\x85\x78\x0b\x42\x6e\x3f\x85\xaa\x35\x5a\x59\xb2\xa3\xb8\x7b\x5c\xaf\x64\x5b\x70\x13\xd0\x78\x8f\x9a\x94\x37\xe5\x04\x05\xe4\x58\x4e\xbd\x02\x94\xb1\x23\xfd\xef\x51\x7e\x92\xc5\x0d\x7b\x97\xbc\xdc\x29\x34\xf2\x6f\xe6\x24\xa2\x64\x5b\x87\x37\xdd\xda\x55\xf8\xe0\x12\x3a\x51\x56\x8f\x9f\x27\xd2\x2f\x0d\x59\x1f\x0a\xe3\x0d\xf9\x12\x79\xd3\xf5\x42\xec\x74\x6b\x78\x85\xb8\xbb\x76\x84\x07\x6d\x08\xbb\x0d\x29\xae\xea\x7b\xad\xf8\x15\x14\xbe\xb6\xd1\x6c\x6e\x5d\x18\xa3\x8c\x2c\xf1\xac\x9e\x13\x0b\x24\xdb\x03\xc4\xa9\x88\xd2\x97\x17\x83\xc8\x63\xc9\x65\x6d\x0b\xcb\x54\x1a\x0f\xc2\x92\xa4\x35\xf2\xef\xb2\x6f\x4b\x23\xa7\x27\xc5\xbe\x34\xe4\xfa\xa2\xef\x92\x44\xef\xbc\x64\xde\xd6\xc9\x16\xf3\xf7\x30\xe4\x5f\xd9\x39\x0a\x93\x4f\x09\x6b\x60\x6a\x19\x0f\x00\x5a\xe6\x6d\xe3\xa5\xe4\xaf\x05\xe7\x31\x29\xa1\xc9\x3a\x90\xaf\x5a\xd4\x97\xa0\x13\xed\xf4\x80\xb5\xb5\xc4\xf0\xe1\x04\x43\xe8\x08\x89\x55\x0f\xca\xea\xaa\x2a\x4a\xc1\x06\x9d\x05\x3d\xbd\x53\x60\x8c\xaf\x4d\x0a\x66\xbc\x5d\xdd\x7b\x2e\x68\x7b\x36\x1a\xbc\x9d\x92\xe4\x4a\x43\x33\x41\x10\xc9\xd8\x89\xa9\xdf\xc1\x43\x74\x48\xfd\x3e\x00\x9c\x21\x84\x5d\xbb\xeb\x05\x4b\x44\x16\x67\xe7\xc5\xb4\xa1\xc3\x39\x17\xba\xbc\x29\x7c\x49\xc8\x68\xdd\x79\x4b\xf0\xfb\x1e\x04\x3e\xcd\x4c\x2c\x2b\xb7\x8a\x07\x16\x71\x08\xf6\x06\x23\x03\xa8\xda\x1c\x2a\x44\xfd\xf0\x4d\x11\xdb\xfc\x19\x02\x15\x86\x61\xaa\xa8\xb9\xb7\xab\x7d\x65\x3d\x72\xf4\xe8\x46\x79\x01\xf0\x43\x2b\xe1\x83\xe7\x90\xef\x9c\x3c\x90\x97\x98\xe1\x2f\x24\xf0\xa7\xf3\x8e\x9d\x29\x57\x90\x70\x6b\x22\x20\xae\x9d\xca\xf6\x12\xe7\x6a\xd5\x9b\x0d\x5d\x05\x5e\xe8\x3d\xac\xe2\xfd\x60\x7b\x93\x2d\x46\x64\x7b\x31\x1e\x49\x52\x39\xb6\x9f\xdf\x24\x0c\xbf\x83\xa7\xf1\x97\x07\xfb\xe5\xa6\x14\xe3\xe1\x44\xfa\x83\xfb\x22\x97\xbd\x83\x61\x13\x4f\xa7\x74\xf0\x88\x2e\x29\x80\x31\x7b\x24\x34\xc3\xc8\x46\xf7\x8b\xe8\x6f\x21\x24\xe1\x0a\x36\xb0\x9e\xd6\xed\xe1\x8c\xa8\xb9\x8e\x06\x09\x79\x78\xab\xc4\xb2\x07\x08\x58\xf2\x4d\x37\x7f\x23\x2f\x68\x89\xe0\x1d\xe0\x1a\xcd\xc8\x1a\xff\x4b\x66\xb5\x96\x7a\xb1\x4d\xf3\x68\xf6\x9d\xc3\x33\x02\xb4\xcf\x8d\x3d\x4f\x2a\x1f\xc1\x48\x06\x42\xd5\x6a\x83\x32\x13\x64\x05\x9b\xd7\xd1\xb2\x96\x9c\xc3\x20\xef\xf0\x0d\xd3\x49\xd0\x70\xb2\x7f\xbb\xa1\xc1\x60\x81\x24\x39\x6a\x62\xd9\x9f\x15\xcd\x38\x6d\x28\xd0\xab\x06\x65\xc2\x42\x9c\x8e\x5e\x6a\xc9\x8c\xf6\x90\x50\xfe\xb3\x30\xc5\x75\xbf\xaa\x25\x22\xf2\x99\x6b\xf8\xc2\x37\x64\x3d\x07\x04\x4f\xc1\x45\xf1\xed\x38\x19\xf0\x42\x95\xd2\x76\x80\xb6\xd9\x32\xe5\x10\x54\x6c\x94\xfd\xb8\x38\xbe\x1d\xa2\x64\xdf\x40\x44\x8b\x9b\x16\xb6\x74\xaf\x9f\xb8\xf2\xdb\x97\x3a\x89\xc7\x50\x0a\xd6\xc3\xb2\x2e\x7a\xa6\x50\x71\xdc\x54\x61\x3d\x2d\x83\xfb\x3e\x0e\xf9\xe6\x15\x1b\xf1\x8f\x20\x97\x02\xfa\x38\x25\x20\x62\x59\x21\x7b\xa7\x9b\xe9\x41\xa1\x0e\x21\xa1\x15\x4a\x4e\x12\xc5\x82\x86\xfb\x53\x26\x40\x1e\x15\xac\x31\xb1\xab\x68\x30\x63\x23\x9d\xb5\x44\x23\x6a\xf6\xcc\xea\x2a\x0b\xba\x12\x0d\x19\x46\xa9\xb5\xa3\xb4\x74\x01\x88\x92\x9c\xc8\x23\xca\x2c\x8e\xf2\x54\x1d\x2c\x03\x62\xf7\xa0\xfd\x6d\xf6\xa5\xc4\x2d\xc1\x75\x4c\xbb\x13\xf2\x3c\x38\x0d\xca\x63\xb5\xfd\x4f\x2e\x0e\x96\x31\x78\x42\x25\x52\x8a\x35\xa2\xef\xf2\xaa\x16\x0c\x1a\x61\x93\x6d\x31\xb2\xc7\xcd\x8e\xfd\xf3\xdb\x09\x32\x4b\xda\xe3\x7a\xa1\xa0\x56\x62\xf1\xd0\x27\x0c\xa8\x04\xac\x0c\x89\x4f\xc8\xbc\xbf\x3a\x8a\xc9\x72\x01\xe1\xfe\x67\x6f\x51\x9a\xc3\xc4\x3a\x77\x67\x53\x4c\xa3\xd0\x18\x34\xfb\x87\x2b\xf2\xee\xc0\xf3\x03\x8b\xe0\x3e\x63\x3f\xbb\xf3\xb5\x94\x0f\x83\x27\x5f\xcb\x93\x5b\x2b\x9f\x5d\x2c\x2f\x98\x32\x9a\xed\x40\x94\x26\xe3\xe3\x64\xc2\xde\xa8\x7d\x57\xd1\x5c\xa8\xd4\x1c\x4e\xef\x80\x18\xf8\x6e\x2d\x32\xe8\x04\x29\xf5\x05\x4d\x07\x71\xbb\x24\x01\x3c\x25\xe2\xf5\x52\xba\xdf\xbf\xb9\xe7\xaf\xd6\xbf\xdc\x64\xef\x89\xd7\x49\x01\x10\xc5\x35\x15\x86\xc4\x83\xea\x47\x31\xfc\xf9\x2d\x89\x12\x6c\x47\x4c\x42\x6a\x50\xfa\xc1\x50\x24\x04\x87\x42\xc7\x9d\x7e\xb4\xaa\x13\x78\x72\x1f\xd4\xcb\x74\x6d\x63\x79\x61\x72\x39\x0f\x2a\x56\x30\xee\xdf\x0a\x04\x5a\x96\xa8\x81\x21\x3a\x5e\x92\x37\x07\xb3\x6a\x0c\xd2\x15\x75\xcc\xc9\xbf\x72\xd9\xf2\x3b\xf9\x84\x8c\x26\x41\x17\xca\xf8\x62\x28\x33\x59\x6e\xf4\x2c\x97\x02\xff\xf6\xe1\xe7\x8c\xda\x4b\x4e\x16\x0b\xab\x88\xa7\xb3\x56\x3c\xdf\x9d\xb5\x27\xd2\xd6\x4f\x3b\x4a\x07\xec\xea\xe5\xbd\xa9\x00\x92\x52\xe7\x19\x56\x2f\x6e\xea\x63\xfd\x82\xd2\x66\xa4\xbb\x41\xbf\x8b\xae\xba\x28\xfe\x06\x04\x93\xe6\xd5\x22\xa3\xdc\xc1\xf4\x98\x36\xdb\x03\x64\x30\x6f\x41\x5d\x57\x32\xb9\xa2\xab\x92\x2d\xf1\x05\x57\x66\xbc\x56\x36\x48\x98\xd5\x0d\x33\x84\x70\x5b\x61\xaf\x63\x1b\x7c\x0b\x45\x14\xd9\xeb\xa0\xab\xe1\x05\xf0\xa2\x61\x21\x97\xe7\x27\xc0\x22\x40\xa3\x2c\x7d\x7d\x90\x1f\x7d\x17\x46\x21\x56\xde\x7d\xe2\xcb\x14\x2e\x0d\x30\xec\x5d\x35\x9a\xe1\x6b\x25\x04\x85\xde\x48\x65\xba\xe5\x0f\x30\xb3\x48\xd8\x4f\xa4\x4b\xb3\xba\xa1\x11\x15\x6b\x9c\x69\x5d\x08\x2a\x6b\x23\x0a\x40\x99\x70\xb1\x11\x63\xdc\x45\xc9\x47\x40\x8a\x93\x80\x2e\x11\xc4\x8a\x2c\x4b\xca\x9d\xb7\x8f\xd5\xd2\x1b\xda\x35\x0e\x86\x99\xcc\x37\x7e\x02\x65\x57\x36\x70\x57\xb4\x7e\xf2\xb4\x3b\x64\x47\x53\xe5\x10\x8d\xa1\xc1\xe9\x3d\x26\x29\x7f\x72\x2a\x88\x69\x41\x57\x9e\x64\xb1\x4c\x01\x45\x7d\x58\x10\xeb\x6a\x32\x0f\x69\x14\x64\x58\xa2\x13\x66\xf3\x42\xd7\x9b\xb7\x73\x53\x1c\xd1\x6d\x61\xa9\xd0\xd5\xc8\xda\x93\xf9\x84\x5f\xa2\xc6\x0f\x44\xdc\xb5\xa3\x78\xc0\x02\xe7\xd0\x64\xf5\xf3\x3a\x5b\x7a\x38\x21\xe2\xf9\x4d\xba\x9a\x30\xca\xb7\x23\x33\x77\x95\xe7\x18\x7a\xa8\x97\x8d\x92\x78\x80\x1f\x93\x5d\x06\xf2\xf0\x4c\xf9\x0d\xcd\xbc\x63\xd8\xe1\x68\xde\x7a\xe4\x94\x3e\xdc\xc4\x25\x59\xb5\x8b\x17\x99\x3a\x39\x38\xb2\xf6\x9a\x2e\x96\x3f\x78\x33\x07\x42\xb0\xcd\x2e\x2e\x9c\x73\x81\x7a\xad\xa9\x52\x31\xa1\x12\x0b\xe6\x3d\x8b\x70\xd4\xd6\xb1\x0d\x50\x4e\x83\x46\xe2\x5c\x26\x42\x49\x93\xa5\xc7\xc1\x68\x01\x5a\x64\xa0\xa2\x7f\x82\xe8\x3a\xea\x01\xf6\xd9\x30\xdb\xc9\x73\x64\x53\x1c\xf6\x5b\x9d\x1d\xc6\xd9\xfc\x2e\x64\x73\xed\x04\x78\x47\x8d\x93\xb3\x52\xbc\x4d\xe4\xd6\x35\x96\x74\xcf\x15\x0e\xa6\xc8\x50\x12\x14\xbc\x81\xf2\xb1\xd5\x67\x87\xf1\x63\x4f\x84\x9d\x2a\xd3\x67\x70\x2a\xca\x4c\xcd\xd2\xd9\x65\x33\x8d\x0f\x01\x4e\x45\xc9\x4b\xb7\x7a\x80\x29\x3b\x71\x9e\x94\x83\xb2\x60\x90\x1b\x5d\x41\x76\xd6\xe5\x62\x03\x28\x6a\x2d\x4d\x03\xbd\x7a\xb2\x9b\x6a\x36\x41\x31\x70\xe3\x32\xa9\xc0\xc6\x7b\x71\xbd\xa9\x73\x58\x21\x26\x1d\x8a\xfa\xd8\xa9\x33\x5f\xbd\x44\x86\xaa\x64\xed\xcf\x23\xcb\x19\x03\x58\x9c\xe2\xfd\x1b\x2a\x12\xe0\xf6\xf6\xa1\x3c\x0d\xdd\x5d\x95\x94\xef\xcb\xf2\x6f\xec\xc9\xcb\x19\x5e\xe2\xec\x10\xd8\x3c\x73\x34\x80\x47\xad\x93\x41\x45\x96\x71\x43\x1f\x71\x5d\x47\xa3\x43\xa4\x4f\x1b\x95\x61\x6d\x60\xe5\xc8\x1e\xa8\xe6\x9c\x0f\xb6\xdc\x80\x77\x2d\xb9\xa1\x77\x0c\xb8\x04\xcd\x03\x1e\xa1\xba\x0b\x0f\x43\x39\x0e\x9b\x5f\x51\x3c\x9d\xb4\x8b\x0b\x21\x94\x9c\xcd\x09\x97\xc5\xdc\x66\xe3\xc1\x9c\x9d\xcd\x8f\x62\x41\x2b\x9e\xcd\x39\x6c\x70\x78\x01\x3d\x7f\x35\xda\x24\x0f\x62\x94\xbc\x17\x48\x89\x46\xe6\x64\x5b\xeb\x78\x34\x87\x1a\xeb\x8b\x5f\x2c\x0b\x68\x91\xa4\x9d\xd5\xaf\xcd\x16\x7f\xf3\x4d\xa1\x6e\xbe\x68\xbb\x03\xd9\x60\xc5\x89\xa1\xa1\xd3\x28\xbb\xe8\xa0\xbc\xfd\xac\xc7\xfa\x92\x70\xc5\xbb\xf4\x83\xa7\x74\x34\x3d\x79\x58\x50\xfb\x78\x05\x4d\xcc\x12\x3e\x51\x94\x15\xfb\xf3\xcb\xde\x1e\x6b\x20\x7c\x00\x94\x5b\x0a\x01\xe5\x09\x91\x42\x1d\x29\xed\xe5\x23\xcf\x8e\x32\xa8\x61\x6f\xde\x51\xf5\xdd\xf6\xd0\x6a\xf2\x0d\x75\x22\x9c\x8d\x17\x77\x59\xbd\x17\x69\xf7\x7a\xac\xf9\xb6\xef\xe0\x00\xa5\x4f\x97\xb2\x12\xb6\x57\xb0\xe5\x5c\xd9\xd3\xa6\xca\xfe\xf9\xd5\xc7\x67\x2c\xf1\x3b\x5b\xa2\x82\x56\x30\xbb\x4c\x9c\x5e\xc9\x1c\x9d\x8e\x35\x19\xe5\xce\xbe\xf0\x49\x62\xa4\x83\xbb\x26\xc7\xed\x83\x97\xc2\xc7\xb5\x74\x51\xe6\xa2\xc1\xb4\x30\xb5\xbb\x7e\xc7\xe1\x85\x1f\xf1\x55\x1b\xe2\x3e\x92\xaa\x36\xf6\xcb\x3d\x3b\x67\x34\xcd\x4e\x4e\x99\x46\x27\xea\x6d\xd7\xd5\x6e\xb5\xb2\x0f\x58\xb0\x8a\xab\xdb\xcc\x8b\x83\x7e\x1e\x24\x31\xa0\x52\x5d\x28\xd1\xa5\xd0\x0a\xc2\x6f\x2a\xe7\xaf\x1a\x96\xb0\xc9\x8f\x6f\xf1\x1c\x40\xcc\x42\x39\x94\x59\x36\xdf\xf3\x23\x13\x27\xc7\xdb\x53\x3d\x45\xbc\x4c\x31\x0c\xeb\x95\x6e\x2c\x8c\x45\x90\x48\x50\x29\xda\xd9\x56\x2a\xfd\x7b\xdc\x36\x8d\x72\x82\xa7\x21\x6f\x6f\xb0\xa0\x61\xb5\x08\xf1\xe5\x4a\x06\x2a\x18\xb3\x23\x7f\x91\x8d\x3e\x59\x05\xfa\x3a\x1d\xda\x83\xe2\x8a\x34\x47\xb4\x02\x03\xbd\xa9\xf7\x6b\x61\x55\x57\x9a\xe0\x35\xbb\x18\xe5\x4a\x6c\x37\x51\x8b\x0e\x63\x20\xac\x79\x07\xbe\x9e\x32\x91\xb7\xab\xcf\xb6\x61\x96\x6b\xf9\x70\xe5\xcb\x10\x0e\x3d\x7a\x22\x89\xc4\x25\xe4\xb3\x9b\xff\xfd\x4b\xdf\xd8\xd5\xc9\x60\xdd\x09\x28\xad\x9c\x06\x00\xf6\x1d\x52\x5b\xe0\x05\x1f\x8a\x78\x68\x35\xfb\x03\x9c\x64\xa4\xd6\x2e\x11\xa3\x03\x7f\xa8\x76\x6b\x9d\xa5\x78\xf5\x35\x8d\x2a\x30\x2e\x91\x0d\xc5\x41\xea\x16\xc5\x45\xa3\x67\xa9\xf5\xe3\x1a\x8a\x4d\xb1\x12\x6c\x30\x0b\x65\xe9\x1c\xfc\x88\xfe\xcb\x92\x00\x0f\xc0\x65\xcd\xa0\x0d\x6b\xde\xea\xb5\xc3\x00\x55\x8a\x49\x2e\xbe\x37\x4f\x7f\xe7\x0e\x39\x66\x97\x13\xff\x4d\xcd\x3a\x99\xe9\xb7\x49\x45\xdb\xc9\xee\x2e\x2d\x71\x23\x63\x6a\x8a\xd4\xf9\xa4\x0e\xe5\xc1\x75\x0e\xf4\x5a\xb3\x37\x41\x45\x0c\xe2\x61\x0f\xca\x62\xfa\x8c\xc8\x35\x50\x46\x90\x00\x9e\x9d\x9f\x19\x06\x7b\x1e\xda\x7f\x96\x4c\x79\x4f\xa7\xc4\x34\x88\x5c\x15\x26\x44\x73\xac\xeb\xf6\x19\x98\xc6\x99\x06\x13\xb0\x0c\xee\xea\x8f\x5b\x0e\x08\x2c\x9a\xdd\xda\xe2\x13\xc7\x54\x35\xe1\xd9\xb1\xe4\x7e\x40\x52\x21\x97\x18\x2f\xa3\x47\x31\x07\x52\x5c\x67\x04\x7d\xda\x73\x6b\xee\x7e\x0c\xf4\xba\x71\x41\x9b\x87\xdd\x67\xf8\x41\xa9\xd5\xb4\x4b\x1d\x72\xa2\x7e\xd8\xe5\xb0\x8e\x62\x3d\x60\x41\x8e\x1a\xf5\x52\xd8\x86\xf1\x61\xd7\x31\x7b\x98\xe7\x31\x93\x4c\xb6\x1c\x96\xd3\xa8\xe7\x16\xfd\xcb\xd9\xb4\xff\xca\x4d\x1e\xf1\xe6\x31\xa1\x06\xdf\x6e\x08\x68\xb4\xcb\xab\x6e\x36\x8d\xe4\x70\xf6\xcc\x3b\x3a\x99\xad\x05\x3e\x2a\x08\xfb\xb8\x42\x1c\x33\x15\xc1\x33\x8f\xd6\xc8\xf7\x74\x41\x37\x31\xcb\xa3\x76\xab\x08\xcc\x98\xb3\x32\x66\x4b\x99\xf7\xe6\x56\xf4\x8b\xfd\xdf\xad\xfc\x15\xdb\x6a\x83\xb5\xd3\x38\xd1\xef\xe0\x95\xb2\x66\xb7\xb6\x3b\xf2\x27\x3e\x8a\x00\x6d\xee\xa3\x93\xc4\x78\x26\x74\x8b\xf2\xe5\x8f\xb9\x44\x1d\x5f\x40\xa0\x30\xdc\x89\xf2\x83\xc7\xc4\xea\x12\xf1\xf5\x69\xc8\xb5\x80\xed\x41\xd9\x00\x66\x13\x77\x5f\x51\x5c\xb9\x0b\x86\x6f\xdd\xde\xc3\xa9\x49\xa2\x6d\x1a\x14\x28\x28\x58\x36\xba\x82\x50\x1a\x45\x78\xe6\xcd\x21\x7a\x09\x71\xa4\x28\x36\x75\x7f\x47\x7f\x49\x8e\x40\x45\xba\x76\x39\xd7\xab\x52\x4e\xd1\xe4\x09\x11\xb3\x2b\xe8\x77\xa2\x3f\xe5\x62\x1f\xbc\xb5\x9c\xb1\xf9\x3c\xba\x5e\x59\xbc\x7f\xb3\x43\xe8\xd4\x11\x34\x3c\x13\x71\xcf\x0c\x66\x80\x56\xc4\xbd\xa1\xf9\xf9\x74\x51\xea\x5a\x59\x98\x53\x29\x28\x43\x19\x5e\xf8\x1c\x3f\xae\x57\xfc\x8c\x44\x23\x2e\x6c\x90\x9e\x77\x67\x80\x91\x94\xa7\x93\x54\xc6\xd4\x4d\x6d\x3e\x44\x72\x4b\xb1\xe2\x38\x9f\x54\x67\x65\x0b\x47\x50\xba\x1d\x4c\xb9\xd7\x38\x6f\x30\x33\x6c\x69\xf8\xe0\x31\x7a\x79\xe4\x3b\x2f\x31\x27\x74\x20\xee\x3e\xa2\x61\x27\xa6\x7a\x1b\xdc\x20\x59\xdb\xca\x0e\xd6\x42\x55\x13\x9d\x4b\xc9\x56\x2d\x4d\xc1\xa8\x95\x74\x5a\x51\x07\xeb\x0e\x99\xaf\x07\xe0\x01\xf8\x47\xc6\x0d\xc5\xc5\x91\xeb\xc1\xf1\x2d\xae\x52\x63\x7c\x4b\x78\xb1\xbe\xba\xe4\xc9\x31\x54\x39\xf2\x30\x28\xe9\x1c\x4d\xcf\xfd\x58\x83\xb3\xe2\x54\xbb\x18\xc5\x51\x2d\x08\x80\x55\x76\xeb\xd9\xb2\xf3\xa1\xcd\x57\x08\xe0\xb5\xfe\x6a\x27\x61\xc8\x1a\x90\x48\x6a\xd3\x6c\xf5\x3d\x3b\xe5\xc8\x23\xbb\xc7\xe4\x04\x2e\xcb\x00\xe2\x5f\x3a\xac\x04\xaf\xfc\x21\x01\x6c\x52\x61\x5c\xb4\x19\x4e\x46\x06\x08\x1e\x43\x7f\xe9\xff\x88\xe1\x64\x11\xa6\xee\x58\x19\x09\x92\x65\x94\x6b\x4a\x4b\x5e\xbd\xea\xcc\xa4\xd9\x17\xfb\x9b\x1d\xac\xfc\x29\x63\x0c\xe1\x68\x42\xc1\x8c\x04\x59\x99\xe2\x1a\x92\xe9\x1a\xe4\x2c\x7e\x4a\x22\xc5\xe3\x52\xa7\xf0\x63\x84\x7a\x49\x6d\x21\x3d\x5b\xd0\x72\x60\x8d\x45\x66\x03\x76\x8d\x9a\x11\xb0\xf9\x48\x35\x31\xb2\x44\xce\xe3\xe9\xcd\xfc\xae\xaa\xb4\x71\x3e\x93\x58\x76\x07\x32\x54\x5e\x11\xfc\x0e\x2d\xa6\x74\x10\x27\x15\x24\x28\x00\xc4\xa9\xbf\xb7\x7a\xdf\xc3\x93\xb1\xa8\x26\xe9\x9e\x98\x7e\x7c\xbc\xd1\xe6\xcc\x9e\x77\x32\x08\x47\x7f\xb0\xdf\x43\x80\x7f\x30\xeb\xb5\xff\xd7\x27\x7f\xb0\xa8\x0b\x55\x1e\xd4\xba\x29\x4a\x08\x81\x89\xf2\x67\x36\x6b\x09\x18\x2b\xe5\x94\x86\x57\x20\x43\xa6\x92\x96\x25\x31\xc9\x66\xae\x6a\x3f\xe1\x06\x7e\xe2\xdb\xbb\x4d\x5c\xa4\xd2\x7a\x6a\x6d\x81\x94\xa6\xf4\x80\xf0\x2c\xc0\xb5\xdf\x38\xa6\x2a\x23\x97\xb1\x26\xdd\xe4\xe0\x45\x7f\xba\x94\x72\x3f\x29\x61\xab\xf7\x86\xc9\xe4\x1c\x9e\xcf\x3a\x8c\x37\xf6\xa9\xa2\x31\x58\xe3\x03\xea\x28\x74\xea\x52\x5a\x6b\x86\xae\x67\xf0\x2c\xe0\xc5\xce\x7d\x40\x66\x72\x8f\x00\xe2\x68\x5f\xc2\x48\xb3\xe4\x6b\xdc\x0e\x4c\x41\x81\xe1\xb8\x7d\x44\xc0\x51\x46\x2b\x5e\x1c\xbd\x60\x9c\x38\x79\x0d\x56\xe2\x11\xfa\x45\x38\x64\xc4\xd2\xca\x88\x77\x54\xb9\x35\x2f\x86\xf8\x7e\x6d\xc1\x25\xce\xb5\x42\x87\xc8\xfc\xfe\xfd\x33\xa2\x37\x6c\xd4\x1a\x0b\xe7\x98\x32\x9b\xd9\xed\xe4\xfc\x28\xfd\x4a\xf6\x3a\xa1\x63\xb6\x7c\xc5\xff\x24\x81\x6a\x18\xf1\x43\x7f\xac\xed\xbb\x19\x6c\xb1\x63\x8e\x6f\x8e\x17\x01\xc9\xfb\xd9\xff\xeb\x76\xb6\xe5\xb0\x0c\x7a\xca\x8c\x0c\x7d\x92\x20\x82\xdd\x89\xda\x6a\xd6\x6c\x99\x10\x96\xc8\xf1\x39\xa2\xc7\xef\x13\x29\xd3\x62\x2d\x60\xcb\x9b\x35\xfa\xb0\x38\xfb\x42\x13\xed\xa5\x4d\x6d\x88\x72\x24\xea\xb9\xd8\xe4\xa9\x85\x65\x30\x54\x36\x8a\x7d\x43\xfb\x9a\x47\x0c\x93\x08\xab\xd3\xb9\x75\x78\xef\xe2\x7d\xa6\x94\x96\x51\xce\x1c\xdd\xf0\x27\x70\x1e\x1d\x06\x01\x8a\x33\x76\xc1\xc9\x37\x0a\x0a\x6d\x50\x74\x6d\x24\x1a\x07\x3e\xb2\xa9\x40\xc7\xae\x0d\x91\x50\xb1\x43\x9c\x56\x52\x39\x94\x73\xd7\xb2\x34\x07\x05\xa1\x95\x03\xe4\x7d\x9c\x42\x55\x31\x65\xf7\xe5\x66\xaa\x37\xde\x37\xf8\x27\x05\x6b\x6f\x4c\xc0\x7d\x3a\x05\x70\xf1\x36\x29\xcc\x58\xc2\x6d\x0a\xce\x9f\xc0\xc0\x31\x7c\xf5\x2a\x08\x0a\xa7\xc2\x19\x3e\xae\x7f\xae\xfe\x13\x20\x49\x61\x21\xc9\x47\x56\x64\x96\x22\xc2\x64\x01\xed\x8f\xd8\xb7\x7e\x3d\x7c\x18\xab\x2b\x8e\x93\x6a\x61\xf2\xd0\x27\x59\xf5\x1a\x4f\xe1\x18\x44\x13\x53\xb6\x03\xd1\x41\x44\xd1\x16\xc6\x05\x89\x74\xce\xfe\x51\x6a\x20\x91\x90\x69\xff\x32\xcc\xd5\xc9\xab\x2b\x09\xf4\xe4\x15\x1a\x96\x9d\x9b\x73\xa9\x2a\xdd\x84\xc4\xb8\xae\x9d\x77\x68\x44\x3e\x0a\x86\x26\x8e\xf1\x6d\x0b\x64\x7a\x79\x92\x6f\x8e\xfa\xf8\x80\xea\x75\xf1\x8c\x35\xe7\x35\x19\x85\x71\x9d\x46\x16\x28\xfd\x9b\xae\x8b\x82\x94\x95\x38\xb0\x2a\x3b\x0e\x35\xf4\x53\x32\x02\x53\x58\x4b\xdf\xa4\xce\x5b\xea\x6c\xce\x97\x59\x98\x8c\xfd\x97\x70\x2c\x2c\xa8\x99\x49\xde\x03\x5e\x7b\xf4\xef\x18\x6b\xd0\x9f\xe4\x0a\x2e\x69\x57\x4d\xd2\xc2\x0a\x03\x57\xba\x2b\x98\x25\xec\x04\xb0\xd9\xcf\x48\xf2\xc4\xd3\x17\x16\xa8\x65\xad\x36\xa2\x35\xde\x5f\x9e\x25\xf4\xa4\xe0\x83\x87\x2e\x73\x27\x04\x33\xfb\x34\x73\x9d\x4a\xe4\x1a\x79\x13\x18\x24\xda\xe6\x40\x5e\x14\xe6\xb9\x4e\xce\x85\x08\x1d\xc3\x9e\xc4\x2e\x41\x4c\x4f\x89\x99\xb6\xb2\xec\x77\x96\xc5\x5c\x06\x35\x82\x6c\xbe\xb3\xfb\xf4\x20\xed\xf0\x65\xaf\x80\x3e\x06\x2b\x5f\x3b\x98\x4b\xcf\x38\xbd\x40\xcd\xe6\xc0\x57\x59\x99\xf2\x4e\x2c\x20\x5d\x17\x02\x4a\x33\x88\xa0\x38\x22\x19\x59\xe0\xdb\x39\xab\x0f\x75\x62\x95\x77\x22\x1b\x80\x6d\xae\x0a\x4c\xa9\x79\xfb\x4e\x6e\x07\x1a\xd2\xee\x0a\x69\xce\x46\x19\x26\x68\xce\x96\x11\x12\xb1\x13\x67\x1e\xe4\xfb\x32\x66\x71\xea\xfc\x1d\x4e\x63\x91\x70\xc0\x9e\x33\x21\x57\x07\x4b\x61\x28\x1c\xba\x2d\xa7\x03\xe2\xfc\xd2\x27\x47\x10\x4e\x48\xa0\xc3\x57\xb3\xf4\x9d\x24\x3e\x89\x0c\x67\xc4\x82\xbe\x5d\x90\x5b\x23\xd5\xc3\x6f\x06\xa8\xb1\x6e\xbb\x8f\x82\xb0\xb1\x7f\xe1\xc5\x0e\xd0\xbd\x6c\xc8\x8b\x03\x0b\xc7\xa6\x4d\x45\xe7\xc3\x95\x7e\xda\x7d\x20\xdd\xfe\xc9\xe9\xf9\x0b\x0a\x25\xea\xe2\x1d\xfd\x1d\xd7\x6f\xf2\x36\x68\xa3\xbf\x52\x84\x43\x25\x40\xa1\x16\xe7\xcd\x6f\xed\x00\x80\x07\x11\x45\x3b\xba\xd6\xf7\x87\xd9\x2c\x44\x19\x25\x35\x18\xa4\x91\x1c\xc1\x17\x1c\x57\x9b\x34\x41\x8d\xb6\xec\xfc\x79\x67\x8b\xb6\xe8\x05\x78\x95\xec\xc3\x2f\x35\xdb\x73\xd8\x8b\xc3\xd0\x0e\x8e\xda\x01\x38\xa1\xcb\xa0\x15\x03\x32\x68\x5d\x8c\x3c\x7a\xd3\xc3\xc2\x6e\x13\x0c\xa6\xe5\x9d\x58\x3c\xb9\x5a\x82\x0f\x81\x96\x13\xc0\x1a\xf8\x1c\x48\xa9\x9d\x6a\x77\x76\x52\x58\xa6\x01\x20\x9b\x92\xcd\xc3\x8a\x29\x2c\xcb\xca\xa6\x53\xf0\x52\x76\x49\x99\x22\x07\x4e\xa7\x85\xdc\x61\x72\xdd\x3d\x32\x00\xef\xf8\xc3\xe6\x33\x67\x03\x5d\xb0\x01\x67\xa9\x62\x5e\xd0\xa9\x47\x61\x36\xad\x54\x3d\xd0\x01\x0d\xda\xd2\x1d\xe9\x2a\x54\xed\x7a\x4c\xcb\x8e\xdd\x27\xa5\x9c\x44\x4a\x66\xa0\x3c\xea\x29\xf9\x4e\x81\xf5\xc5\xa9\xc4\x0d\x15\x19\x18\xf0\x4f\xf1\xfe\x3a\xae\xd8\xed\xe4\xc2\xe6\xf1\xb4\xf1\x51\x90\x21\x2e\xae\xd5\x20\x11\x5a\xdb\x47\x45\xec\xcf\x14\x07\xab\x06\x53\x4e\x21\xf8\xbc\x39\x6d\x5f\x27\x09\xec\xa4\xf2\x7b\xa5\x79\x5e\x4d\xcb\xda\x30\xf1\x94\x1d\x12\xa6\x90\x5c\xb3\x1a\x4b\x60\x1a\x6f\x98\xbf\xb8\x85\x5e\xe1\x01\xd8\x51\x6a\xd1\x9b\x1c\x52\xfc\x0f\xa3\xb8\xef\x14\x8d\xa6\x33\x7c\xb3\x53\x0f\x59\xdf\x86\x64\xda\xe9\x10\x30\x06\x2d\x92\x08\xd7\x35\x03\x03\xbc\x07\xaa\xfb\x83\x45\x7d\x84\x79\x87\xa3\x43\x3b\xc7\xd4\xef\xe5\x05\x00\xcc\xe4\x03\xd8\x43\x34\xb4\xac\x35\x86\xdc\xc6\x44\x24\x71\xc0\x7c\xac\x48\x31\xa4\xd3\x39\x41\xda\xd4\x82\x14\xc3\x09\xfc\x93\xea\xdd\xa0\x38\x35\xfa\x32\xdf\x0e\x88\xbc\x51\xab\x95\x68\x03\xad\x67\xa8\x5b\xda\xae\x21\xbf\xd1\x09\x40\x24\x45\xc4\x0f\xe9\x27\xd0\xdd\x45\xcf\x7c\x85\xe4\x13\xa5\xfd\x7f\x71\x0c\x1d\x30\x3b\xc5\x2f\x91\xe0\x93\xbd\x33\x1a\xb9\xad\xe6\x4a\x5c\x93\x48\xc5\xc3\x1c\xa7\xca\x8b\x48\xba\xe2\x3e\xaa\x6e\x9b\x1e\x2b\x80\xa5\x9b\x0f\x40\x5b\xa9\xbf\xd1\x89\x29\x85\xbc\xb2\xb6\x54\x00\xbc\x58\x4b\x00\x60\x6f\x1f\x05\x71\x72\xce\xca\x81\x6e\x3d\x6d\x72\x1c\x42\xdb\x43\x9c\x5c\x7d\xb4\x7d\xbc\xd2\x3a\x98\x21\x7c\xb9\x17\x9d\xc7\x68\x2d\x71\xb2\x34\xef\x99\xa1\x21\x3c\x77\xcf\xec\xe7\x9c\x98\xf0\x7a\x33\xf3\x83\x68\xbd\xdd\x6e\x4b\xbc\x7d\x22\xab\xc2\x5c\x08\x7d\x13\x48\x1b\xd5\x15\xeb\x4e\xa0\x96\xc7\x6c\x8c\x6d\x0c\xa4\xb1\xe9\xb9\x18\x09\x17\xa8\xf7\x89\x60\x7a\x0f\x8d\x89\xb8\x5b\xf0\xa7\xf6\xc2\x5a\xc3\x59\xa1\xf8\x4a\x57\xb1\x28\x2a\xe7\x4c\x75\x94\x2b\x46\x8b\xe1\x5b\x87\xbf\xde\xc4\x60\xd9\xf1\x83\x7e\x46\x5b\xd5\x78\xd1\x84\x36\x1d\x48\xce\xce\xdb\x9e\x7f\x71\x22\x54\x99\xea\x41\x0d\x42\xf3\x85\x53\xfd\x90\xfb\x61\xbe\x4a\xa3\x4c\xc8\xdd\x7b\x37\xbf\x4e\xe7\xc7\x69\x4e\xec\x25\xda\x5c\x22\x7b\xea\x56\x56\xd5\x19\x65\x18\x8b\xe3\x44\xf3\x49\x62\x15\x4f\xbc\x46\x2a\x64\xd2\x9f\x0f\xab\x46\x93\xd9\x7b\x43\x3d\x59\xe2\x8c\xe7\x93\x8a\x25\x15\x65\x67\xea\x32\x98\x1c\xc9\xce\xd9\x25\x3e\x92\x32\x62\xc6\xce\x0e\xa7\xbb\x21\x48\xf4\x29\x69\xb5\x8d\xa9\x22\x4e\x92\xef\x11\xf1\x9f\x0e\x23\x43\x6a\x91\x7e\x7f\x07\x97\x1b\xee\x4a\xbd\x0b\x55\x95\xd2\x93\x71\xb2\xd7\x45\xb5\x14\x15\x7e\x02\x82\xa9\x5f\x57\xe4\x2e\xa9\x31\x2d\x51\x62\x63\xa6\x64\x1c\xb5\x56\x59\x4d\xb4\x5e\x59\xd8\xd4\xa3\x05\x60\x44\x68\xbb\x28\x90\xae\x3e\x0a\x4d\xea\xae\x23\xdc\x71\xbe\xd7\x88\xa9\x2d\x72\xa9\x4c\x48\xdf\xec\x0b\x61\xa3\x5d\x47\xf1\x83\x45\xa9\xfe\x91\x64\xb7\x5a\x30\x8c\x08\x39\xd4\xb3\xc3\x22\xd8\xf0\x0c\x16\xbb\x7d\x10\xfe\x0d\x38\xcc\xa4\x83\xad\x01\x21\x91\x71\x21\x6e\xc1\xac\x0c\x49\xe8\xed\x62\x30\x2e\x67\xc8\x49\x8b\xe7\x87\x6d\x55\x79\x88\x48\x4f\x78\x25\xb6\xa1\xfb\xd9\x97\x97\x29\x6f\x6c\x19\xfb\x03\x33\x5b\xdb\x54\x87\x3b\x8d\xee\xbd\xf3\xdb\x3f\xe1\x56\x51\x7c\xdb\x9f\x11\x23\xfa\x7f\xd1\xb5\xec\x31\x6f\xc2\x6e\x2d\x10\x66\x1d\x7e\x3d\x76\xe8\x98\xdc\xac\xd6\x7d\x8c\xca\x53\xdf\x49\x47\x2e\x3f\xe8\x04\x79\x82\x89\x16\xb5\xd3\xb9\x98\x4c\x08\xa1\x1c\x09\x7f\x6f\xea\x98\xe2\x70\x6a\x25\x76\x1b\x9d\xb5\x1b\x21\xf2\x00\x51\x9f\x8a\xd3\x52\xd1\x0b\xa8\xd6\x95\xbc\xff\xa4\xe1\xce\xb7\x1c\x01\x2e\xac\x8b\xb7\x9d\xe4\xa8\x28\xaa\x0c\xe8\x79\xa4\x0a\x3f\xe2\x17\x3a\x8a\x3d\x30\x85\x6b\xe4\xe5\x73\x3d\xaa\x65\x60\xc5\x8b\x9c\x22\x8a\x4f\x6b\x3c\x0b\x98\xdd\x9b\xfb\x4b\xf8\x8e\x34\xb1\x8e\xe3\x42\x4a\xdb\x42\x56\x94\xf6\xb2\x83\x02\x33\xb9\xc4\xbf\xd9\x6e\xe2\x4c\xd9\xe8\xb6\x96\xbb\x29\xbf\xc7\x3a\xc0\xe4\x93\xe1\x77\xe5\xf5\x9c\x84\x6a\x96\xc4\xab\xc0\xda\x4b\xc9\x17\xf3\xd8\x39\x90\xb6\xba\x8a\x75\xf3\x42\xd8\x53\x4f\x9d\x11\xeb\xac\xd9\x1e\x72\x32\x16\xb6\xa3\x90\xe1\xad\x8a\x3e\x3c\x60\x62\x05\x74\x72\xcd\xe9\xc9\x45\xc0\xb4\x6f\x81\x70\x14\xcf\x95\xf6\x21\xc0\xd1\x70\x14\xe9\xc3\x62\x30\x0e\xd7\xbb\x7c\xba\x55\x0b\x98\xd3\xa9\xc5\xf4\x4a\x94\x27\xbb\x02\x3f\x2d\xba\x26\x8e\x4e\x8c\xbb\x3d\x19\x90\x07\xa7\x2e\xa3\x2a\xa0\x31\xfa\xdb\x3e\x74\xe2\xba\x6b\x56\xfa\x56\x2e\x18\x5e\x10\xb8\xc4\xe2\x0d\x8e\xd6\x39\x4a\x9d\xb0\xd4\xd8\xc8\x11\xfe\xd1\xdf\x6f\x1f\xcf\xc5\x56\x02\xbe\x27\xcb\xb7\xf2\x95\x9c\x56\x1e\xdd\xe4\x76\xdd\xaa\xbc\xac\xf8\x79\x48\x20\xaf\x68\x17\xf3\x52\xca\x87\x61\x05\x97\x58\x06\xa7\xa4\xca\x82\x81\x28\x1d\xce\x5f\x90\x49\x4c\x7b\x91\xb5\x90\x65\xc5\x47\x28\x9b\x43\x91\x69\x33\x2f\x5a\xca\xe5\x05\x78\xc2\xdd\x68\xea\x28\xc1\x4f\x63\x09\xd9\xb6\xed\x23\x56\x45\xfc\x12\x94\xe0\xc0\xaa\x50\xa1\x71\xab\xb8\x6e\x1c\x29\x43\x32\xff\xcd\x45\x46\x01\x58\xf9\xad\x3f\xc4\x68\x31\x0b\x40\xa1\xfb\x05\x0f\x49\x55\x36\x6f\xf0\xb6\xae\x14\x2c\xb5\xc4\xce\x17\x8d\x22\x4b\x89\xaa\xde\x42\xef\xaf\x31\x82\x17\x19\x46\x7d\xd8\x87\xee\xcc\x92\x8a\xa2\xd8\x3d\x69\x1a\xb9\x22\x4e\x76\x4e\xf9\xc4\x34\xcb\xed\x41\x26\xae\x7d\x79\xa0\x76\x05\x4b\x64\xcf\xee\x93\x54\xa8\x5b\xa4\x97\x8d\x21\x92\x6b\x3c\x6f\x63\x24\xa6\xd6\x0f\x57\x3b\x96\x51\x67\x06\x02\xbe\xd3\x59\x10\x1c\x3a\x14\x39\xea\x69\x72\x70\xf3\xfd\xe5\x62\xdf\xce\x62\x36\xe6\x97\x3b\x85\x8b\x65\x40\xa2\xb5\x0a\x02\x61\x8d\xe4\x35\x54\xce\xe3\xe0\xe7\xe3\x41\x46\x07\x60\x0e\xbf\xb8\x64\xb7\x0f\xc6\x57\x46\x10\xd7\xe5\xe4\xee\x2a\x9d\xcc\xba\xfe\xa6\xd3\x2d\x29\x91\xe8\x37\x87\x0a\xd8\xa8\x2e\x42\x80\x56\x97\x6a\xfc\x6a\x51\xbc\x19\x06\x94\x49\xdd\x35\x6a\x33\x62\xc2\x07\x8e\x7d\x45\xbe\x3a\x2a\x57\xd6\x35\x05\x36\xcd\xd9\xef\x6f\xac\xc7\xb0\xf4\xf7\x17\x09\xe7\x7a\xf6\x41\x7c\x22\xf3\x63\x2f\xbf\xd0\x47\x09\xe7\xee\x05\x04\xc9\x3e\x7c\xee\xb1\x44\x04\xce\xd9\xaa\x6f\xd7\xaa\xd6\xe1\xf7\x2c\xaf\x7c\x48\x5b\x60\xb3\x79\x27\xf3\xc9\x5c\x02\x68\xe7\x61\x60\x73\x13\xe4\x9f\x78\x50\x32\x14\x6d\x72\x8a\x43\x31\x49\x51\x6b\xc8\x34\x66\x4b\x04\x01\x78\xa0\x03\x66\x03\xa7\x4c\x62\x4a\x0c\x64\x29\xab\xcf\x81\x1d\x18\xa2\x58\x43\x4e\x46\xd1\xa9\xfe\x9c\x12\xa2\xcd\x84\xe0\x70\xa1\x39\xa3\x01\xf8\xf4\x84\xe7\x95\x58\xea\x56\xdd\x10\x2f\x31\x47\xe7\x8c\xc8\x26\x38\xfc\xb1\x0d\x6c\xf5\x28\xde\x2f\x9f\x93\x8f\x46\xc9\x66\xc0\x73\x78\xb3\x05\x56\x5b\xfa\xf5\x2c\x55\x04\xa5\x62\xe0\xc6\x1c\xda\xac\x58\x1d\x39\x58\x84\xd6\x36\x2d\x99\x5a\xd4\xb2\xca\x49\xa1\xe0\x87\x78\xdf\x21\x93\x01\x1f\x56\x32\xe7\xaa\xf9\xd4\x16\x9b\x23\xeb\xc3\xc7\x27\x96\x84\x13\x02\x5f\x1f\x52\x98\xb2\x37\x82\xbd\x3f\x38\x59\xf2\x92\x2b\x5a\xb9\x6c\xc4\x29\x4e\xdb\x3b\x06\x9b\x53\x80\x13\x29\x87\xca\x22\x30\x09\xe3\x26\xd7\xf4\x48\x43\x0f\xe1\x76\xa6\xe1\x19\x38\x97\x50\x33\x33\x84\xeb\xff\x86\x9e\x09\x00\x2e\x7f\x6b\x74\x3f\x66\x6d\x5b\x28\x48\x4f\xe5\xde\x10\x11\xa8\xc5\xa2\x55\xd6\xea\x16\x57\xe7\x91\x58\xd6\x04\x49\x92\x2b\x94\x7e\xa6\x00\x6d\x42\x09\x6f\x59\x04\x31\x0e\x27\x2a\x32\x56\x0e\x7e\x7c\x8b\x49\x4c\xb6\xf3\xa8\xcf\x7c\x29\x7e\xc8\x64\xb0\xc2\xf8\x4a\x9b\xa4\x6d\x6d\x65\xfd\x9d\xd6\xac\xf2\xa7\xa8\x8b\x0c\x05\xa7\x51\xa1\x98\x86\xda\xba\xcd\x53\x7b\xd8\x70\xe7\x89\x82\xc2\x35\xf6\xdb\x13\x32\x0b\x57\x95\xb6\x73\x70\x4e\x81\xfc\x51\x5e\x9e\x63\x28\xfa\x3a\xfd\x8b\x80\x7a\xf6\x27\xae\x94\x9f\x43\x1f\xfa\x4f\x5f\x7c\x5a\x4f\x52\xcd\x3f\x70\xe3\x15\xac\x82\x6f\x51\x59\x30\xaa\x8f\x8a\x2f\xb6\xa0\xcf\x7a\x6c\x71\x23\x96\x05\x97\x20\x62\xe0\x9e\xfa\x16\x02\x9c\x2a\x22\xc5\x40\xc7\xf2\x7a\xcb\x87\x87\xdc\xa2\x56\xe1\x69\x48\x9b\xc6\x31\x10\x0a\xd7\xb0\x05\x00\x50\x59\xcc\x79\x9c\x5a\xf5\x24\x0f\x49\x2c\x3f\x20\x03\xf3\x48\x4a\xd6\x41\x99\x7c\x4c\xea\x07\xa9\x52\xa7\x73\x11\xaf\x75\x94\x63\x21\xaa\x64\x93\x55\x79\xf8\xbf\x2c\xfd\x27\x78\xcc\xf2\x81\x68\x34\x58\x06\x3d\xed\x0b\x4e\x4e\xfd\xdf\x98\xa9\xce\x51\xaa\x0a\x3e\x9f\xd6\x9a\x3b\x45\x46\x21\x72\xfc\xbb\xf9\x4c\x6b\x5c\x64\xe5\x46\xb3\x26\xfe\xf3\xda\xc1\x30\x0a\xae\x4a\xf9\x21\xe9\x5e\x2c\x5d\xfb\x83\xee\xd2\xb0\x19\xf5\xc2\xbe\x9a\x39\xfb\x7a\x02\x6c\xbf\x11\xb7\xbf\xbc\x00\x50\xd0\xbe\x60\xaa\x0a\xdc\xe4\x85\x4a\x01\x84\xde\x4c\x88\x40\x7f\xe6\x67\x28\x77\x2b\x61\x8d\xda\x74\x36\xb7\x2c\x60\x78\x0e\x3d\xac\x0a\x4a\xa3\x4b\x75\xb6\x6e\x32\xaf\x34\x7a\x93\x4a\x91\xad\xf2\xa5\x88\x75\x34\x03\x9a\xde\x69\x64\x27\xdd\x2f\x9a\xac\x35\xf0\xd8\x5c\x63\xcd\x07\x51\xd8\x20\x98\x07\xab\x04\xf4\x3e\x43\x7a\x40\x23\xfa\xe2\x31\x96\x36\x3f\xa0\xa0\xea\x66\xf1\x4a\x8e\xe0\x5c\x1b\x41\x0a\xf9\xe1\x72\x9f\x78\xf5\x31\xc8\x58\xc3\x6a\x1c\x01\xc8\x55\xad\xde\x79\x25\x57\x79\x76\xe5\x8e\xac\xb2\x1c\x48\x8f\x5f\xa3\x03\xfa\x20\x7b\xc9\xc1\xca\xdb\x59\x48\xe0\xb0\xa0\x09\x14\x62\x2a\xed\xa4\xd6\x3e\xa9\x8b\xd7\x70\x02\x9a\x6e\x78\x38\xae\xb3\xd7\xaa\x43\x8c\x6f\x67\x83\x1e\xe0\x33\x69\x61\xd4\xd5\xac\x95\x22\x8f\xb6\xb6\x3e\xe2\x3e\x2d\x92\xc2\x5a\x49\x30\x25\x3e\x1a\x24\xa8\xf4\x8f\x35\xae\x18\xbc\x59\xfa\xa9\xca\x30\x80\x5a\x3d\xca\x5b\xbc\xfc\xb3\x44\x1b\x22\x62\x5b\x5b\x4f\x74\xa1\xcc\x3e\xae\xc6\xec\xa6\x9c\x3d\xa8\xbb\x97\x8f\xb7\x8a\x68\x59\x00\xf1\x82\x92\x81\x39\x1b\x45\xa3\x27\xd4\x64\x51\x5c\x97\x0b\x4c\xba\x8b\xe6\xcb\x0f\x83\x0b\xa0\x45\x2a\xfe\xb6\x78\x6b\x86\x55\x34\x57\x9f\x98\xa4\x24\x37\xea\x87\x84\xf7\x0c\x94\x21\x42\x5a\x44\x29\x1c\x2b\xee\x80\xd8\xca\x3c\xe2\x73\x72\xc4\x25\xb6\x77\x7a\xa3\x0f\x4c\x99\xc2\x97\x62\x3e\xfd\x99\xc2\xf6\x2a\xa6\xb4\xae\xe9\x80\x73\xb8\xef\x82\x89\x6a\xda\xe2\x44\xf2\x7a\x55\xe3\x03\x71\x13\xc4\xcc\x97\xa4\xbb\x85\xa1\xcd\x0d\xc0\xe8\x27\x1c\xc9\x73\x27\xe5\x77\xfa\x1e\x18\x07\x04\x0f\x2f\x01\x8d\xf7\xfd\xed\xfe\x00\x72\x4d\x09\x6a\x6d\xa6\x40\x39\x7b\x5b\xab\xc2\x38\xd4\x4d\x1b\x62\x77\x9d\x3a\x8f\x3a\x4c\x70\x88\x7b\xfb\x78\x0c\x56\x5b\xb4\x99\x51\xff\x90\xb3\x58\x1b\x67\xf4\x54\xe5\x5d\x42\x91\x3a\x91\x9b\x59\x29\xb6\x70\x25\x8f\xd3\x5c\xc7\xee\xe0\x54\x6c\xe5\xcb\xfa\xc4\x38\x05\x57\x3b\x80\x9c\xc5\xc0\x17\x1d\xbb\x80\x14\xb1\x42\xf5\xf9\x29\x79\x1f\xd4\x86\x9e\x98\x7c\x6c\x83\xb8\x9c\x1f\xc5\x4c\x64\x72\x04\xcb\x00\x61\x9d\xfd\x62\x1b\x60\x1a\xb8\x3e\x0e\x0f\xc9\x99\xb5\xdb\x56\x98\x35\x30\x75\xc4\x9a\x41\x89\xc5\x28\x77\xd9\x73\xbc\x3f\x93\xe5\x73\x14\xb3\xd3\x21\x41\x5d\x49\x18\xd1\x44\x22\xa0\xaf\x17\x0c\x10\xd5\x63\x77\x29\xee\x3c\x86\x47\xa0\x61\x56\xb7\xa4\x3b\x3b\x5f\x45\x83\x5c\x7d\xd9\x27\x94\xc6\x1f\x94\xdf\x39\xe7\xc5\x57\x3f\xe2\xd0\xd8\xf8\x46\x72\xce\x5e\x25\xad\x28\x39\x96\xf7\xe4\xfb\xdd\x8a\xc4\x47\x68\x8f\x67\xa7\x68\x2d\xdb\x82\x33\x25\x77\x26\x50\xe4\x01\x9a\xf6\x64\x97\x9f\x3e\x65\x04\x1d\xce\x18\x1c\xe5\xcd\x5e\xaa\xfc\xb7\x20\xd9\x5a\x86\xea\x82\xb5\x16\x2b\xe7\xac\x43\x89\xd1\x89\x32\xcf\x78\x32\xc7\x43\x20\xb8\x18\x79\x01\x12\x99\x63\xec\xdb\xec\x43\xaa\x59\x8d\x9a\xc3\x2f\xa9\x76\x4a\x2f\x3d\x31\x84\x79\x72\x39\x12\x39\x28\x2e\xd4\x34\xa1\x57\x9c\x97\x8c\x94\x83\x3b\x9c\xcd\xbd\xa5\x09\x70\x1d\x18\x3b\xc8\x5c\xa1\x5a\x1b\x8b\xbe\xab\x98\xf0\x93\x62\x9c\xb3\x4e\x34\xb5\x17\xee\x83\xcd\x7f\x47\x1b\x1f\xf2\x30\xb4\x82\x3a\x1f\xde\xeb\x7c\x70\x3c\x84\x1c\x05\x6b\xe9\x47\x48\x8f\x06\x25\x94\xde\x94\xa8\xfe\x00\xce\x08\x2e\xed\x3d\xda\x11\x5c\x0c\x6e\x95\xc0\xc3\xab\xb7\xae\x17\xe1\x52\xd4\x24\x33\x2d\xb1\xfd\x98\xae\x0d\x91\x01\x90\x0c\x4d\x06\x15\xd5\xe6\x34\xe0\x5f\xb7\x5d\x93\x0b\x1b\x5a\x75\x3c\x43\x57\xec\x8f\xca\x1b\x7a\xa2\xf5\x94\x94\xc6\x21\x84\xd6\xd6\x5b\x99\x76\xdb\x4e\x5c\x60\x95\xa3\x02\xcd\x15\x51\x5e\x30\xa8\x94\x3a\x52\xcc\x9c\x98\x92\x82\x20\xd3\x9f\xc1\xe2\xf6\xe6\x2f\x14\x3b\xe2\x50\xb0\x51\x85\x21\x32\x39\x2a\x1b\x6b\x34\xf0\x78\x80\xea\x64\xa5\x37\xbd\x47\xe6\x07\xe5\x8a\x36\x56\xbf\xc5\x12\x21\x73\x37\x4d\x6e\xfa\xc1\x8e\x99\x68\xb7\x62\x3e\x0f\xeb\x99\x2e\x9c\xa6\xa4\x2b\xec\x99\xa6\x93\x3a\x1a\x4b\x64\x72\xa0\xd9\x58\xd9\xd2\x7a\xb0\x75\x40\xab\x4e\x76\xef\x17\x17\x6e\x8c\x72\xa4\x41\x28\xa7\xae\x4c\xe6\x64\x02\x54\x45\x72\xd8\xc8\x00\x58\xbd\x3a\xf9\xe3\xac\x7c\x65\x1d\x3d\x90\xf7\x24\x1f\xbd\xf5\x1c\x5a\x3f\xde\xb8\xb1\x99\x58\xb1\x43\x5e\x12\x48\xb3\xfc\xc9\x0a\x43\x5c\x0e\x12\xe4\x97\xe0\x73\xd5\xe7\xaf\x8e\xbc\x36\xe3\x0c\x31\xe5\x8b\xad\x83\x43\xfe\x78\xc2\x9c\x93\xb7\x43\xb1\xaa\xf2\x6f\x86\x0f\xf8\x16\x66\x41\x7e\xd5\x38\x39\x6a\xbc\x95\x4c\x1d\x95\x5a\xe2\xd4\x39\x48\xfe\xed\x2c\x4d\x34\x1a\xde\xb0\xc4\x57\xa0\x56\xf6\xca\x01\x8c\x88\xa6\x72\xdf\x59\xf1\x19\x3a\xe5\x3f\x62\xa8\x92\x83\xb6\x04\xd1\x55\x5d\x81\x8f\xba\x48\xe2\x00\x7f\x3c\xbb\xc2\xff\xcc\x2c\x77\x0e\x57\xbf\x01\x7b\xc5\xf7\x57\x09\x22\x2e\xae\x04\x96\x91\x82\x5a\x40\xfb\x66\x59\x43\x92\xf8\x93\x1a\xa9\xc1\x1c\xac\x22\x60\x20\x80\x52\xe3\x05\x50\xdd\x95\x2c\xb0\xbe\xc2\xf7\x54\xef\x43\xac\x35\x4a\xbe\x42\x3c\x61\x0c\x1b\x46\x5b\x9f\x97\x91\x50\x26\xc9\x54\x2a\xcf\xe1\xe5\xc5\xf9\xbd\x86\x08\xf7\xb7\x33\xe9\xdf\x13\x3b\x7e\xb6\x82\x63\x21\xf1\xf0\x1f\x3e\xd0\x40\x0c\x4d\x32\x39\x71\x58\x64\x98\x1c\x98\x30\x45\x1d\xd6\xca\x03\x0b\xda\xcf\xe0\x7d\x4b\x2a\x22\xd3\x60\x1f\x82\x55\x56\xaa\xa7\x11\x06\xd7\x2e\x92\xe1\xea\x22\x28\x1a\xd3\x88\x17\x6a\xe3\x2a\x3d\xe2\x5b\xac\x91\xe9\xc8\xeb\x3a\x69\x85\x86\xf7\xc9\xbe\x71\x47\x9c\xba\x7b\x94\x63\x9a\xac\xe1\x48\x54\x13\x10\x1b\x89\xd3\x39\x87\x8e\x54\x6b\x24\x05\x3a\x83\x02\x02\xfb\xf9\x09\xe8\xc9\xb9\xa2\x87\x85\xa0\x18\xa9\xc8\xc6\x0b\x50\x0a\xed\x72\xbd\x90\x7e\x6e\xe1\x97\x0d\x1a\xf9\xe2\xab\x13\x47\x7e\x62\xd8\xbc\xca\xd4\xe1\xbf\x19\x47\x56\x92\x0b\x40\x9c\x9c\x9f\x81\x80\x1f\xe3\x7c\x27\x09\x62\x3a\x63\x7e\x03\xca\x82\xb6\x95\x60\xde\x43\xf0\xf1\xc8\xaf\x70\x2a\x9e\xfb\x00\x1d\x35\x8c\x40\x6c\x60\x21\x9c\xc0\xdf\xd8\xed\x0e\xa1\xab\x87\xc1\x04\x07\xd1\x53\x0a\x73\x9e\x81\x0d\x31\xc7\xbc\x17\x72\x26\x51\xdf\xd8\x1d\xd8\xd8\x8a\xac\xc2\x9e\xc8\x85\x68\x1c\xda\xef\xfa\x7a\x2b\x07\x0b\x4a\x92\xce\xe9\x14\xd1\xe7\xf8\x1a\x17\x9e\x36\x20\x90\x21\xab\x56\x7d\x05\xee\x69\xfd\x0f\x56\xa7\x99\x81\x16\x7c\xd8\x07\xa1\x27\x60\x54\x88\xbd\x03\x3c\xfc\x1d\x37\x66\x9d\x8c\x05\xdb\x3b\xba\x13\x0c\x7f\xa3\xb5\xc4\x68\x4c\x76\x03\xea\x90\x1f\xc8\xed\xd6\x72\x81\xc3\xa7\xfd\x54\xf6\xfa\xd1\xeb\xf4\x18\x33\x89\x6a\x66\x47\x51\x46\xef\xac\x0e\xfe\xb3\xd5\xe8\x07\x55\x82\xbc\x68\x8d\xba\xf0\xe9\x55\x8f\xdd\xe7\x06\xec\x71\x38\x90\x93\xec\x9c\x6d\x4c\x13\x05\x72\x8b\x12\x5e\x3e\xd8\xe0\xa7\xf7\xca\xac\x88\x7c\x95\x26\x7a\x18\x3b\x31\x6c\xd8\xd4\x88\x82\x65\x54\x57\x0e\x9e\x8a\x4f\x1b\x0f\x1f\xb6\xf9\x05\x42\x93\xc6\x05\x45\xe7\x8a\x77\x36\x6b\x8f\x0a\xc8\x5c\x31\x21\x49\x6b\xbf\xfa\x4f\xb8\xb6\x88\x3e\x3a\x4b\x62\x6b\x79\x8d\x29\xee\xef\xe0\x1d\x5b\x3e\x64\x3d\xd5\x9b\xf8\x2c\xe7\x47\x89\x35\x9d\x19\x68\x88\x51\xfa\xd3\x37\x89\xd2\x8f\xac\x33\xa8\xf6\xbb\x26\x4b\x98\x53\xb5\x67\xa0\x6f\x1a\x04\xb5\x42\x66\x01\x46\x24\xac\xea\x8e\xed\x9d\xe3\xc8\x5d\x3e\xbb\xde\x61\x3b\x59\x2e\xd9\xbc\xc4\xd9\x05\x14\x16\x9f\x2e\xb7\x00\x22\xd3\x45\x1a\xe2\xa3\x86\xf5\xb2\xc4\x5c\x86\xae\xf6\x06\xa6\xd8\x8c\x3e\x40\x33\xc9\x13\x48\x63\x07\xb3\xac\x4f\xf0\x29\x86\x9c\xe6\xf0\x1e\xd3\x27\x22\xdb\x28\x5e\xd6\xb6\x7e\x81\x0d\xad\x2b\x88\xe6\x67\xad\xc1\x90\x0c\x55\x15\xe6\xb4\x2f\xe2\x31\x5c\xc2\xf5\x44\x97\xf7\x15\x3d\x97\x47\xeb\x0c\x86\x64\xd6\x00\xed\x5a\xc8\x2f\x07\xad\xf5\x5c\x38\x74\xa8\x06\xcb\x3f\x38\x52\xa9\x32\xe3\x75\x54\xa1\xc8\x64\xd9\x86\xe9\x5a\x6c\x3c\xd9\x01\xbb\xb3\x71\xc2\x80\x6a\x3e\xbb\xaf\x13\x47\x05\xea\x4c\xf9\x0a\x21\x83\xe0\x3a\x79\x87\x82\x17\x83\x95\x57\x04\xdb\x84\xd2\x41\x22\x2e\x46\x1a\xa8\x42\x7c\x9b\x33\x68\x0d\x12\xec\xd3\x30\xbd\xef\xd3\x2f\x29\x69\x11\xa9\x3a\xe5\x3c\x0f\x5a\x6f\x8a\xf0\x51\x15\x12\x90\xf6\x15\x97\xf9\xfa\x8c\xce\x0e\x98\x29\x05\x65\x69\x0d\x74\x8d\xe2\x6d\x52\x2b\x76\x14\xb4\xa8\x87\x96\x84\x85\xfa\xd7\x1c\x4e\xb2\xf9\xbc\xcd\x8d\x48\x9a\xfc\xf2\xc4\x10\xf7\x3b\xb0\x7a\x0b\x9f\xd1\x02\x78\x24\x3a\x7f\xb2\x2b\x2a\xb9\x70\x98\x21\xab\x8b\x4a\xe5\xa7\x79\x34\xed\xc8\x7a\x3f\x8c\xf9\xb2\x91\x12\x36\x6f\x1b\xf2\xe6\x09\x72\x3b\xde\x63\x43\x56\x5d\x18\x3a\xa1\x81\xfa\xb2\x4a\xf3\xf9\x32\x63\x2e\x8c\x7a\x79\x69\xc7\x1e\x04\xeb\xb4\x55\x9f\x82\x80\xf7\x2f\x6d\xde\x56\x89\x8a\xd7\x0f\x28\x5a\x97\x5a\x7b\xbb\xa9\xaa\xb4\xb1\x7a\x66\x40\x94\x5f\x73\x00\xfc\xf7\x5c\x31\x73\x43\x12\xa2\xc5\xfe\xba\x1e\x21\x92\x61\x02\xa3\x81\xbe\x81\xee\x5d\xbd\x0d\xfb\x38\xfc\x9c\x1d\xcc\xbb\x9f\x5e\x7a\x5e\x0a\x78\x8e\x4b\x1c\x23\x5d\x30\x7a\xca\xa0\x69\x06\xc6\x83\x86\x3e\x51\x68\x6f\x4a\xa6\x15\x6c\xc2\xd1\xca\x2b\xb2\x0b\xa9\xd2\x3d\x00\x4d\xdf\x1f\xf1\x4a\x9c\x5c\x53\x8d\x2e\xe1\xa4\xbe\xa6\x61\x33\xb8\x21\x62\x32\x01\xb5\x49\xa4\x32\x7a\x16\xac\x91\x89\xd4\x2f\x09\x66\x0e\xb0\x2a\x74\x78\x74\x42\x26\x55\xbd\x8d\xac\x86\x99\x3a\x2b\x72\x4c\x2e\x8c\x50\x0c\x2a\xe7\x0e\x84\x3a\xe6\x2d\x9c\xc3\xaa\x79\x63\x7a\x5c\x59\xd9\xcd\x61\x88\x18\xec\x18\xd1\xb5\x57\x06\x55\x3f\xd4\xd7\xdd\xd2\xf0\x95\x1c\x9a\x63\x93\x46\x32\x58\x2e\x36\x2f\xcd\x8e\xd6\x3a\xd4\x73\x5b\xb5\x3e\x12\x44\xd4\xb9\x7e\x38\x36\x66\xf6\xea\xfe\x1c\x06\xc9\x47\x87\x31\x01\x78\x92\x34\x94\x25\xbe\x32\xc4\x1b\x95\x06\x0b\x9b\x02\x1d\xe8\xb7\x8f\x7e\xbc\xad\xb8\x41\x3a\x87\x16\xf3\x9b\xe3\x3a\x96\x8f\xe0\xea\x89\x47\x80\x54\xc5\xa5\x85\x01\xa4\xdf\xdf\xe6\x7c\xad\xd0\x41\xd7\x42\x63\x23\x0a\x48\xc6\x17\xe9\xdb\xa7\xf7\x18\xca\x21\x02\x8f\xa9\xd0\x03\xb2\xed\x62\xd5\x4b\x6a\xff\xa2\xcb\xe5\xfa\x0e\xc8\x5f\xc4\x94\x6b\x6c\xc0\xc9\x6d\xed\x00\xa4\x60\xa0\x0d\x88\x38\x55\xfd\x29\xca\x99\x6e\xd5\x23\x06\xbd\x29\x79\xd5\x9a\xc3\x94\xb7\x42\xc1\x2e\xb9\x66\x54\xeb\xbd\x5b\x81\xc4\x93\xce\x0b\x32\x52\x8f\x1c\x0e\xd4\x52\x34\xd2\xc0\x77\x34\x15\x4d\xa8\x9b\x56\xd8\x83\x5a\x0c\xe5\xab\xdb\x57\xcc\x5d\xdc\x9a\x51\x87\xd5\x74\x72\xa4\xe8\xc1\x89\x48\xdd\x3e\xd9\x6e\x5d\x1d\xe1\xeb\x31\x5b\x1f\x07\x20\x08\xc7\xe0\x72\xa1\x74\xbf\x6a\x2a\xe1\x10\xee\xdd\x4d\xbd\xff\xd0\x8a\x92\xd1\xfa\x2d\xb6\x3a\x59\x70\xf5\x2c\xce\x44\x3f\xa9\x31\x1e\x9d\x4b\xa6\xcd\x89\x38\x41\xa4\xa6\x29\xd3\x18\x23\x62\xd8\xcc\x68\x49\x98\x93\x42\x25\x8a\xf1\x01\x6b\x3a\x36\x8d\x3e\xf3\x43\xb0\x30\xfd\xe3\xd0\x8d\x91\xbb\xc7\xd1\xd0\xa1\xb7\x9c\x3e\x56\x2c\x85\x19\x95\x5f\x7a\x00\xb9\xbf\x5b\xa4\x3d\x23\x00\xfa\x4a\xcc\xaa\xb5\x1f\xf3\xfe\x7d\x5a\xb0\x6b\xec\x88\x05\xfb\xd1\x51\x82\xa5\x70\x56\xed\x93\x77\x01\xc9\xd9\xf7\xd5\x54\xb8\xfd\x2b\x4e\x8f\xa4\x40\x02\x38\x4d\x63\x39\x9c\x75\x00\x1c\xe5\x90\x83\xf4\x30\xe5\x22\xc3\x38\xf4\x9c\x90\x4e\x97\x5d\x72\xd4\xcb\xc8\x7f\x86\xa4\xca\x6a\xc2\xbb\x99\xcf\x25\x6c\x6f\x35\x2c\x56\xdb\xc9\x18\x28\xb8\x17\x16\x56\xb1\x0e\xb3\xa4\xa1\xa7\xa5\x3e\xb8\x7a\xea\x3b\xe8\x63\x12\x9e\x03\xa2\xd4\x56\x51\x28\x10\x2a\xeb\xd5\x87\x12\xce\xd8\x83\x3e\xc8\x94\xa4\xae\x8b\x2b\x42\xab\xda\x87\x90\x1d\x35\x38\x48\xe8\x0b\xd5\xa7\xa1\x18\x4a\xf9\xeb\x58\xe1\xdf\xf0\xd9\xce\xec\x0b\xb0\xa3\x6b\xca\x59\x4c\xa8\xff\xd5\x4e\x46\xb0\x2d\x4d\xea\xe7\x41\xb0\x81\x23\x40\x15\x89\xf2\xc4\xb5\x76\x0e\x4f\x91\x8f\x64\xcd\xcb\xa4\x13\x16\x48\x9d\xe8\xe4\x2a\x1e\x7f\x30\x4d\x4e\x9d\x28\x8a\x73\xfe\xd2\x1a\x9d\x5d\xd0\xdd\x8f\xb1\xce\x75\xf2\xcc\xce\x74\xe0\xb8\x27\x18\x79\xeb\xf0\xe9\xf6\x0d\xe5\x4c\x92\xd6\xfb\x52\x70\xe9\x56\xd4\xe0\x56\x76\xcc\xac\xda\x54\x6b\xd1\xf8\x1a\x07\x51\x53\xb3\x12\x5c\x8c\x4c\x55\xa7\xe8\x6d\x15\xa8\x63\x3c\x20\x28\x12\x79\x69\xec\xa6\xd4\x21\x31\xe7\xba\x65\xbc\x08\x7d\xd4\x1a\x21\x00\x87\xbd\x63\x7d\x7d\x02\x14\x31\xc5\xbf\x78\xba\x09\xb3\xf1\x96\xc0\xdf\x6b\x96\x83\x86\xe5\xe4\x16\x4a\x71\x10\xfb\xcf\xea\xdc\x4c\x38\x91\x5b\x89\xdc\x0f\x4b\x72\xbc\x4b\xf9\x18\xa2\xb2\xea\x43\x01\x5f\xcb\xd3\xb3\xbf\xde\xc6\xe4\xe9\xc1\x2f\x63\xa2\x45\x99\x2a\x9e\xe0\x00\xe6\x72\x30\xe1\xd3\x7e\x31\xe0\xa4\xe2\x1d\x21\x4b\x75\x2e\xce\xf5\xc8\x3a\x0f\xca\xbe\xb2\xf2\xea\x03\xc5\x08\x0b\xe3\x87\x3f\xde\x21\x87\xfa\x13\xd9\x2a\xa6\xa3\xca\xfc\x1e\x95\x0e\x00\xd1\x67\x5e\xaf\xbd\xdd\x54\xaa\xf6\x06\x37\x4a\x53\x89\x37\x39\xc9\x26\x22\xd1\xbb\x9f\x0b\x8a\xc6\xb2\x5f\x99\x3d\x85\xaa\xd7\x06\x8e\xbb\xcf\xd9\x56\x6e\x10\x81\xd7\x8b\xd1\x45\xf7\x32\xb0\xab\x89\x82\xbb\x39\x06\x8f\xa7\x7a\x7c\x49\xa8\xec\xc9\x9b\x02\x88\x45\xbf\xe1\x63\x4f\x21\xd7\xc4\x2c\xd1\xed\xb9\xcf\xed\x0d\xd3\xda\x48\xf0\x00\x0f\x21\xfc\xb2\x2f\xcb\x87\x66\x2a\x8f\x1c\xa5\x37\xa5\x47\x82\xbb\xd0\x06\xc1\x2e\x9e\x88\x38\x0e\xe4\xec\xa7\x57\x64\x21\x43\xe5\x4f\xb4\x33\xe6\xdd\x06\x70\xa6\x58\xb5\xeb\xb9\x47\x62\xd4\x3c\xd7\xe2\x44\xff\x0e\x65\x60\x55\xb1\xbb\xe8\xcf\x64\x58\x91\x1e\x36\x85\xed\x2c\x12\x90\x55\x57\xc1\x9c\x29\x39\xaf\x09\xb3\x2a\x63\x5a\xfc\xc8\x91\x27\xa9\x7c\xec\xfe\x6b\x26\x41\xd5\x8d\xd9\x76\xa8\xef\xba\xb8\x79\xa8\xc5\x27\x04\x87\x09\xfd\x29\xa0\x65\x3b\x47\xfc\x52\x22\x31\x08\x51\x72\x6a\xd0\x48\x3c\xae\xc4\xa9\x90\x79\x72\x8a\xc2\x20\x09\x1e\xb3\x69\x3b\xdb\x57\x4c\x1e\x25\x23\x32\x9b\x61\x89\x65\x25\x0b\xef\xa2\x02\xa6\x3c\x26\xee\xdf\xce\xd1\x23\x03\xb6\x1c\x57\x5e\x07\xb2\x62\x50\x48\x69\x2e\x74\xac\xb6\x2b\x7e\xbf\x7a\x50\xd2\x07\x09\xe0\x13\x3b\x15\xb7\x9a\x51\xd9\x45\x5f\x7f\x41\x0d\x05\x06\x01\xb7\x01\x5a\xbc\x19\xa6\x6c\x0e\xde\x64\xd1\x4f\x12\x64\x26\x4b\xbc\x27\x9d\x44\x3b\x84\x4b\x83\x73\xe1\xc5\xb7\xbc\x50\x6e\xd2\xb9\x31\x9c\x4d\x15\xa8\x20\x26\xef\xfe\xb9\x31\xbd\x53\x1b\x8d\x91\x71\xfd\x9e\x29\x00\x31\x94\xec\xdc\x89\x01\x86\x85\xa3\x98\x0a\xa3\xe0\x13\x6c\x8e\xee\x38\x61\xed\x28\xbd\x68\x08\xee\x33\x84\x64\xa3\x9e\x5f\x7d\x5b\xe3\x6b\xbc\xa9\xf4\x55\x24\x15\xb6\x3c\xa1\x9f\xa8\x26\x14\x9f\x9c\x4c\xb8\x94\x1e\x31\x8f\x59\x09\xbb\x6b\x68\x5b\x0b\x81\x7d\x27\xfd\x92\x1f\xa1\xc1\xa0\x35\x88\xfb\x0c\xbd\x1f\xdd\x6d\xdd\xa1\x3e\x8d\x91\x1a\x6e\xe6\x3b\x55\x8f\x0a\xb1\xd3\xe8\xc1\xec\x22\x09\x6f\xc0\x80\x39\x24\xa2\x73\xaf\xd1\x5b\x8d\x9f\xb4\xca\x63\xfc\x70\xf2\x55\xd0\xaa\x3a\x4b\xea\xa0\x84\x86\x69\xe9\x1a\x2f\xd9\x2a\x56\x56\x7a\x34\x89\xb5\x12\x5b\x1f\x1d\x1f\xd6\x85\x85\xa0\x18\x10\x4f\x63\x67\x4e\x0b\xa0\x09\x48\xde\xd8\xd8\xfd\xe2\xe2\xb1\x98\xea\x02\x87\xd8\xe6\x1e\xf2\x63\x64\x13\xf8\xb2\xee\xae\xc4\x57\x7e\x21\x96\x57\x9a\x0f\xe2\x32\xfa\xad\x9d\xe9\x4d\x5c\x24\x72\x3e\xc2\xb5\xb0\xb7\x24\xa9\xfc\xc8\x09\x29\xc4\x6e\x64\xbd\x80\xbe\xb9\x58\x8d\x0d\xd1\x71\x6d\x7d\xce\x54\x01\x4f\x52\xdf\x8b\x79\x18\x85\x16\xc4\x4c\x8c\x86\x0d\x2f\x71\x28\x98\xee\x24\xf0\x02\x6f\xa6\x8a\xe3\x08\xa4\x2b\xae\x05\x86\xe4\x93\x73\xd9\xa9\x68\xd0\x7e\xc1\x20\x6b\x61\xb4\x47\x9a\xbd\xa9\xfd\xa6\xe9\xaa\x28\x91\x5e\xe4\x8a\x5d\x91\xdc\xc2\x22\xae\xc0\x4c\x83\x4d\xa9\x27\xef\xb0\x71\x02\x14\x67\xc2\x1e\x9e\xf1\xab\x4a\x2b\x75\x07\xda\xe8\x63\x4d\x3e\x7a\x6b\x8f\x23\x6e\x30\x99\xce\xcd\xf2\xb9\x15\xa1\xe7\x5a\x96\x02\x98\xcd\xa7\x50\x8f\x61\x3d\x72\x35\x59\x4d\x91\x5f\xda\x7d\x54\x96\x13\x10\x16\xd2\xd7\x97\x31\x35\xd4\x9a\x8c\x33\xc7\x75\x54\x5c\x1e\x03\xf9\x75\x33\xed\xe6\x7c\x5d\xa0\xde\x29\x12\xe8\x17\xa2\x97\xe4\x02\x24\xe2\x65\x6d\xf3\x5a\x96\xc2\x22\x11\x62\xa1\x95\x64\x0d\x14\x9f\xa3\xb7\x7b\x66\x17\xd7\xa9\x63\xf0\xa0\x4a\x31\xe0\x92\x7e\xd5\x7c\x0e\x3d\x72\xe6\xad\x69\x1b\x0b\xdf\x65\x1f\xca\x73\xaa\xcd\xd8\xb0\x77\x5b\x27\xce\xb5\x75\xcf\x55\x37\x39\x07\x81\x1a\x65\xff\xec\xa0\xbd\x5c\x5c\xf4\xa6\x6f\xb1\x81\x40\xcc\x40\x5c\xb2\x42\x47\x62\x51\xcd\x10\xc5\xc4\xb5\xd0\xa4\x3c\x95\x9f\x82\x23\xf3\xfc\x2a\x5c\x5d\x11\xa9\x89\x9a\x08\xc3\xf8\x20\x62\xa9\x9c\x2e\x5c\x6c\x6d\x66\xea\x0e\x49\xf5\x8a\xee\x6d\x8d\x92\x0d\xb1\xab\x14\xf3\x52\x97\x3c\x06\x4c\xdd\x43\xbe\x52\xce\x95\xcd\x1c\xb2\xd4\x15\x7d\x86\x7a\x3d\x43\xa7\xda\x97\xf6\x05\x1b\x74\x74\x29\xc1\xe2\xc1\x01\x57\xfc\xc2\xbd\xf6\x19\x94\x14\x79\xb3\x78\xd4\x25\xa5\xde\x00\x07\x64\x30\x7d\x76\x88\xc1\x6c\x85\x74\x80\xed\xcf\x84\x87\xcd\x0e\xe6\x49\x9e\x50\x80\xeb\xb2\xc1\x06\x62\x47\x35\xb2\x59\x59\x43\x7b\xf6\x8d\xf6\xea\xe9\x7a\x52\xa6\x2e\xa3\x4b\x32\xc4\x3a\x16\x50\xd2\xd8\xf2\x9c\x6e\x8a\xdf\x01\x9a\x37\xd1\x20\x06\xab\x63\x34\x87\x36\xff\xd0\x33\x35\xd4\xa7\xfa\x0a\x8c\x80\x73\xe0\x19\xb6\x20\xb3\x34\x48\xd3\xc7\xf8\x66\x82\x61\x26\x87\xc1\x93\x2c\xdf\x61\xb7\x4b\x70\x4d\x46\x8d\x8a\xc0\xe8\x71\x16\xed\x6d\xc3\xa1\x40\x76\x39\xfe\x50\x7a\xe5\x6a\xf8\xcc\xf3\x56\x76\xe0\xa6\xd1\x07\xf2\x69\x17\xcf\x98\x69\xc1\xac\x45\xd3\x0f\xf2\x61\x8e\x91\xfd\xd6\x70\x79\x64\xd1\xf3\x3f\x9c\x7f\x67\x7f\xfb\x14\x5d\x53\x4d\x87\xb5\x80\xc2\x92\x49\x6d\x0d\x95\xe7\xcd\xa5\x17\x55\x6f\xc5\x76\x35\x77\xff\x85\x9f\x88\x9a\xed\x26\x0e\xfc\xc3\xc4\xde\x5a\x38\x12\x4e\x75\x3a\x78\xed\x9e\x20\x1f\x98\x4f\xf7\xde\x1a\x37\x21\xe7\x68\x9c\x8c\x99\xae\x6f\x51\xef\xe8\x43\x7f\xad\x26\x07\xc6\xa2\x67\x6f\xb5\x3b\x1b\xc7\x7d\x9a\x95\xc7\xf0\x5f\x07\xdb\x24\xee\x76\x52\x66\xe2\x6c\x12\x71\x6a\x3e\xcb\x57\x05\x64\x08\xf6\x64\xad\xb7\x60\xee\x9b\xea\x54\x44\xff\x8a\x22\xe1\x6f\x47\x91\x55\x71\xee\xe3\xeb\xba\x01\xd5\x71\x85\xdc\xc4\x02\x28\xc7\x26\xa3\xf8\xb5\x47\x97\xd2\x6d\x63\x36\x2c\x6a\x59\x4a\xb3\xf2\x01\x14\x79\xc8\xf9\xe7\xe0\x83\x69\x76\xea\x26\xee\x85\x92\xcd\xc9\xe7\xb2\xfd\xa4\x83\xf4\xce\x4d\x19\x36\x6e\x5a\x2a\x53\xee\xf0\x4b\x18\x67\xb5\xf9\x1e\xc8\xe5\x4e\x56\x1f\xac\x76\x02\x0b\x2e\x36\x89\xf3\xd8\x95\x87\x00\x24\x4d\xa7\xed\xc3\x13\x1e\x18\xaf\xa9\x53\x92\x4e\xd4\xa7\x81\x55\x83\x9e\xc7\x1d\xa0\x56\x8d\x0e\xf3\x46\xfa\xa6\xad\x2c\x5e\x87\xb2\xb7\xb4\x3e\x85\x46\xd1\x77\xa5\xde\xb1\x13\x5b\x47\xb4\x3c\x1f\x44\xba\xc7\xc8\x17\x8c\xfb\x11\x23\x74\x03\x7d\x1c\x7c\xc5\xcb\x37\xe0\x4c\x72\xb4\x61\x6e\xe8\x24\x25\x6e\xa4\x74\x03\xe7\xfb\xb1\xfd\x54\xa2\x2f\xab\x4e\x80\xcc\x20\xcb\x3b\x06\x95\xe5\xfe\x95\x86\xf2\x99\xe3\xb9\xc7\x17\x8f\xb6\x4e\x59\xb4\xff\x26\xe4\x68\xcf\xa7\xce\x59\x7f\x68\xfd\xe5\xc9\x68\x77\x4b\xa7\x03\x49\x18\x43\x2f\x81\xc3\xc3\xe0\x38\x14\xf4\x9a\x1e\x2c\x0e\xeb\xf0\x02\xff\x12\xa8\x9c\x34\xa3\x56\xac\x53\xae\x77\x45\xd3\xc1\xe0\xd1\x5a\x02\x43\x2b\xd5\xa9\xf4\x23\xbb\xa5\xc7\x90\x76\x7e\xa0\x69\x2e\xa1\xba\xeb\x94\x0d\xb1\xf7\xe6\x2d\x6f\x56\x6d\x25\x33\xff\x7c\xcd\x82\x7c\x25\x56\xd9\x15\x7d\x0f\x3a\x22\x6a\xad\x25\xb5\x7f\xf6\xf6\x24\xdf\xaa\x81\xae\x2b\xc5\xed\xb3\x49\x79\x44\x1e\xbd\x46\xe5\x20\xb6\xca\x1b\x06\x01\x8e\x20\xc6\x0b\x79\x4e\x69\x53\x0e\x88\xc3\x89\xd5\xf6\x3e\xdf\xa0\xda\x61\x0f\x6a\x18\xf0\xd3\x74\xd0\x9f\x3d\xa1\xc2\x99\x5e\x93\x12\xa3\x6c\x57\x72\x66\x4a\xa3\x41\xd8\x48\x3d\xd5\x37\x21\xe6\x6a\x9b\xf3\x7d\xa1\x2c\x32\x79\x55\xcb\xc0\x3b\x18\xe2\xb7\xd7\xb7\x5e\xe2\xe7\xb7\x48\x59\xc7\x6e\xd4\xd9\xb6\x55\x50\x06\x6d\x54\xbb\x57\x58\x02\x2c\xaa\x52\xe7\xa9\x4f\x23\x9e\x94\x43\xe2\x7e\x13\x49\xa1\x6d\xd0\x74\xaf\xc4\x9e\x93\x8b\xf3\x5e\x4e\x2f\x65\x9e\xf0\x74\x12\x7f\x5e\x1b\x8f\x9a\x58\x04\x2f\xfb\x8b\x0d\xf8\x33\x43\xd9\xe4\x9b\x01\x65\xb2\x10\xa6\xeb\x4d\x72\x09\xf8\x05\x3a\xa2\xda\x9b\x57\x2c\xb8\x90\xb8\xfa\x85\x03\x26\x5f\x2d\x94\x21\xb0\x59\xfb\x76\xb3\xfb\x8d\x00\xe2\xfe\xf5\x82\xe4\x82\x54\x0f\xcb\xb8\xc4\xc3\xcb\x82\xd4\x92\x9f\xf5\x05\x38\xad\x80\x3a\x1f\x62\xf3\x87\x36\x3f\x27\x5c\xea\x30\xc7\x93\xe4\x5c\x5d\xe3\x2f\xd5\x20\x79\x88\xf3\x56\x48\xcc\xb6\x5f\x6d\x26\x4c\x41\x42\x7c\x76\xab\x50\x01\xff\x26\x3b\x44\x5b\x67\x5c\xd3\x4c\xaf\xc0\x75\xdd\x6e\x6f\x2e\x6e\x91\xd8\x8d\x64\xbd\x3f\x16\xd1\x5c\x9c\xe7\x6d\x5f\xae\x28\x02\xa2\x3e\x24\x77\x9c\x2a\xc6\xc6\xdf\x5f\x88\xf9\x1d\x81\xb1\x7b\xee\x36\x9b\x0b\xe3\x05\x51\x8a\x90\xab\x8e\x76\xdc\x38\x8b\x01\x54\x95\xde\x9d\x5d\xb7\x0a\xd0\x00\xe2\x44\x4f\xb3\x24\x1a\x1e\xe6\x45\x6a\x08\x4a\x22\x71\x39\xdc\x4c\x3b\xb8\x8e\xae\x78\xe0\x58\xcd\xfb\xf2\xb0\x03\x92\x50\xd2\xa6\xbe\x1d\x35\x8b\x43\x81\x40\xe9\x3f\x4e\x39\x95\x1d\x4d\x15\x4c\xfd\x53\x49\xd9\x08\xf0\x00\x2b\xc1\x03\x82\x4a\x93\xaa\x2b\xc3\x1f\x83\x85\x05\x8a\x44\xf6\xe1\xc0\xe1\x4d\x71\x02\x6c\x8a\x31\x71\x41\x93\x8c\x95\x7d\x22\xda\x80\xe6\x3a\xb7\x1b\x6a\x5c\x4d\xeb\xa8\xce\xca\x6d\xf1\xc5\x81\x36\x12\x4b\x42\x5e\x68\x09\x95\xba\x6e\x0b\x95\xb3\x4f\x5c\x13\xad\x4c\xe0\x8b\xf9\x20\xff\x23\x50\x23\xfb\x40\x17\x6c\x0e\x3f\x18\x39\xb4\x17\xdf\xe5\x3d\x0d\x51\xbe\x9d\x14\x91\x8f\xcf\xe3\x55\x55\x49\xa2\x00\x56\x8a\x07\xaf\xe6\xf7\x7f\x98\x18\x08\xf9\x3e\x61\xc8\x11\x40\x80\x04\x5b\xa3\xa7\x23\x72\xcb\x5c\xab\x1d\xe3\xe3\x19\x00\x7e\x58\x8f\x9e\x94\xec\x43\xbe\x85\xab\x85\xd8\x5c\x72\x80\x08\x55\x65\x8d\xed\xab\x9f\x39\x81\x59\x7e\x7e\x25\x8c\x95\x8e\x81\x03\xff\x1d\x9b\xf9\x32\x2d\x20\x8c\x37\xb0\x36\x03\x8b\x4c\xad\x11\x05\x18\xf2\x98\xdc\xaf\xe8\x10\xb1\x88\x3e\x68\xe8\x9d\xf2\xbf\x65\x30\x35\xb8\x41\x99\x92\x6e\x1b\x35\x22\xda\x57\xbd\x94\x3a\x30\x92\x61\xbb\x9d\xa9\x7a\x66\x20\x02\x58\x32\x6b\x77\x0d\x24\x5d\xd5\x6e\x06\xf9\x55\x87\xc3\x93\x1e\x9e\xa9\x81\x20\x51\x21\xc2\xc3\x9c\x89\x78\xb2\x66\x9a\x3d\x9c\xca\xa3\x41\x21\x8b\xdd\x48\xa0\x77\x14\xc0\x19\x11\x9e\x7d\xeb\x3e\x73\x35\x3b\xd8\xc2\x72\x03\x37\xf1\x73\xb2\xb3\xbc\xee\x2e\x1c\xa2\xa2\x05\xe6\x25\x94\x17\x9b\xa2\xe9\x64\x55\x60\x09\x2a\xba\x0f\x36\x94\x38\xf9\xdd\x51\x68\x4f\x2f\xb5\x32\x76\x78\x3f\x7a\xa8\x4e\xb1\xd7\xd4\x17\xc6\xec\x83\x83\x6d\x52\xcb\x1c\x23\x8a\xce\xcf\xe9\x6f\x86\x4e\xaf\x51\xff\x6c\xe3\xb9\x90\xa5\xaf\xb3\xbc\xf2\x77\x7c\xa8\x2a\x4b\x90\x3b\xe3\x53\x3c\xdb\x97\x47\x21\x81\x5d\xc5\x84\x80\x8a\x33\x7b\xe9\x08\x9c\x87\x12\x2d\x19\x23\x9f\x72\xcb\x3d\xe8\x95\x58\x8b\xe3\x5d\x94\x91\xc9\x59\xc9\xc7\x2c\x79\x7f\x42\x40\xb9\xe8\xb0\x3b\x58\xb6\x1a\x38\xa4\x57\x7b\x34\x70\xaf\x4e\x5e\x3e\x55\xdc\x81\xe0\x4e\x56\x02\x26\x65\xb6\x20\x91\xb8\x93\x7d\xeb\xb2\xb4\x12\xae\xb7\x41\xb6\x41\x2b\xc6\x50\xd6\x26\x71\xb3\xfa\x98\xe2\xf4\x13\x60\xa4\x56\x15\x43\xa6\x81\xe3\x96\x46\xde\xbe\xd9\xf1\x87\x79\x04\xe6\xb3\xab\xcb\xcf\xe2\xee\x67\x8e\xc2\xd3\xe4\x74\xd4\xb4\xfb\x9f\x0b\x33\xb1\x2f\x4e\x25\x53\x4f\xfc\xf7\x2b\x36\xab\x24\x28\x0c\xcf\x4d\x36\x18\x0f\xe3\xe5\x7d\xf4\xb1\x46\x40\x50\xfa\xb1\x06\x7b\xce\x83\x90\x7d\xf1\x86\x96\xcd\x95\x7a\x55\x00\x88\xf3\xc2\x4c\x11\xc9\xa2\xcd\x7e\x20\xb6\xc1\x8c\x1b\x33\x6b\x2a\x8a\xe3\x2c\xbc\xcb\xb9\x55\x47\xa1\x4f\x38\x6c\x38\xdb\xe4\x6c\xa9\xbd\x13\xc6\xe3\x87\xac\x15\x85\xea\xd5\xda\xe9\x2c\x43\x95\x90\x1c\xf4\x57\xe4\xe8\xe2\xd5\x9d\x9d\x1f\xb5\x29\xc3\x4b\x5f\x87\x93\x3d\xe3\xf2\xa5\x00\x54\x94\xdf\x95\xaf\xcf\xbe\xb2\xae\x51\x31\xb2\x7a\x54\xa4\xb5\xf6\x45\x35\x6b\x50\xaa\xe4\x40\xee\xae\xb4\x24\xbe\x20\x68\x30\x0c\x40\x2a\x65\x6a\x7d\xbf\x55\x68\x9f\x72\xdb\x4c\x8c\x25\x36\x8a\x63\x92\x95\xb6\x61\xca\x4e\x18\x4d\x80\xed\x3f\x77\x5c\x9c\x22\x18\x9d\x26\xdf\xc4\x51\x25\xe6\xa3\x8c\xc8\x74\x62\xad\xbc\x8c\x41\x06\x5a\x77\x64\x57\xbd\xde\x00\x57\xbc\xf9\x0d\xe0\x03\x2b\x15\xc0\xa2\x55\x95\xfc\xb2\x28\xb6\xb0\x26\x28\x61\xc6\x4c\xfa\x0a\x15\x7b\x21\x9c\x7b\x90\xb2\x92\xdd\x9b\xc0\xf6\xa8\x54\x3e\xce\xf2\xfb\x4f\x91\xf2\xcb\x4c\x76\x99\x4d\xf2\x01\xb6\xb0\x8e\xd2\xd6\xca\x79\xd9\x4a\xb5\xcf\x4e\x2e\xd4\x2b\xcd\xa6\xb9\x43\x9b\xcb\x38\x2a\x27\x0d\x2b\xb3\x84\x0f\x2d\x0c\x5d\xa7\xdc\x9c\xce\x4e\x09\x0c\xf2\xed\x37\x27\x8b\x46\x12\x4a\xef\xcf\xe8\xe0\xb9\xb5\xa3\x8a\x0d\x99\x80\x51\x55\xce\x40\xfd\x87\x7e\xa9\x9e\x19\x3c\xc4\xf2\xd5\xc0\xad\x11\x91\x92\xfc\xd3\xc6\x71\xcd\x92\xc8\x2b\x63\xca\x6c\x37\x18\xae\xb6\x40\x1f\xba\x5b\xbf\x66\x47\xe0\xe4\xbe\xa8\xb2\x1a\x66\xc6\xbf\x0e\x37\x5b\xef\x11\x39\x1a\x38\x19\x3a\xf0\x11\x56\x24\xfe\xc4\xce\x64\xe0\x17\xa9\x91\xcb\x5c\x7b\x05\x58\xf3\x01\x26\xa0\x45\x3e\x9f\x57\x66\x1b\x21\xd2\xea\xa0\xb2\xb6\x8d\xb3\xdb\x1f\x0b\x18\x3b\x26\x20\x9f\xdc\x09\x28\xb6\x3b\x45\x68\xe1\x9a\xca\xc7\xa3\x9c\xbe\x7c\x6b\xbb\xf8\xd6\xfd\x71\x1e\x91\x6a\x44\xa1\x04\xfe\xf6\xa6\x43\x65\x65\x4c\x63\x3e\x86\x18\x9c\xa1\xa8\x9f\xda\x49\xbc\xb1\xf9\xec\xc3\x16\x5c\xf6\x5b\x35\xef\xb5\xf1\xd4\x0e\x2e\xd5\x8f\x90\x40\x17\xb6\x2b\x89\xa5\xfe\xaf\x83\xfd\x0a\x84\xc5\x8e\x26\xa7\xdd\xe9\xf4\xbc\x03\xbb\x94\x7d\x26\x51\xf6\xb6\x8d\x1c\xc9\x2d\x7f\x51\xf4\x16\x34\xff\xad\x70\xf9\x38\xdd\x6a\x53\x66\x80\x2d\x53\xf7\x2d\x8a\xff\xcc\x75\xc5\xd7\x40\xb2\x3a\x57\xdf\xa4\x48\x7c\xe2\x04\xdb\x59\x51\x53\xb5\x07\xb3\x1a\x0a\xa2\x3f\x1d\x46\x4d\xe5\x2d\x9f\x30\xa3\xa9\x84\x1b\x5f\x0d\xe6\x69\x6b\xc5\xf9\x77\x9f\xcd\xe1\x74\xf2\xd6\x8f\xea\x27\xf7\x4b\x38\x6c\xe4\x36\xb5\x21\x2e\x1e\x28\x9f\xa9\x41\x15\x96\x4d\xb1\x11\x24\x46\xa8\x8a\xcc\xab\xb2\x78\x38\x43\x24\x51\x77\x50\x4c\x55\x40\x2b\xc1\xa8\x58\x27\x79\x8d\x2d\x71\x88\xfa\xcb\x55\x34\xcf\xca\xce\x29\x45\xda\xf0\x40\x5a\xa5\x46\x03\x9a\x97\x97\x9f\xe8\x35\x93\x1b\x1f\x51\x0b\xa3\xb0\xb6\xf1\x23\x2d\x56\x28\x95\x63\x4c\x75\x01\x08\x14\xea\x35\x7b\x52\xf2\xa7\xc8\xee\xd9\x28\x05\x93\x40\xf7\xa8\xda\xf3\x4d\xf1\x17\xbe\xe8\x53\x59\x48\x4c\xd0\x84\x90\x9a\x7f\x41\xf3\x0b\x54\xab\x01\x2a\x71\xae\xee\x18\x96\xa7\x14\x04\x42\x23\xcb\xe0\x40\x28\xc4\xed\xfd\x89\x9e\x14\x29\x53\xeb\x4b\xcf\xca\xa5\xb3\xab\x3e\x79\x15\x5e\x75\x59\xfc\x94\xab\x6d\xeb\xac\x2d\xd6\xc3\x3a\x21\x1f\xd0\x7b\x27\x41\x50\x13\x27\xb3\x23\x27\x4d\xb3\xa6\x7e\xc8\xdd\xb5\x8d\xc2\x92\x47\xfd\x54\xa5\x9f\x91\x41\xe8\x74\x19\x33\x34\x0c\xef\x95\x8b\x8d\x3c\xea\x5d\x87\x4c\x44\xf4\x7e\xf7\x77\x66\x52\x4b\xfd\x82\x11\xee\x99\x40\xc4\x8c\x7e\xca\xad\x80\x5d\x2c\x26\xfa\x4f\x70\x6f\x0d\xfc\x34\xd3\xef\xdd\x7b\xe4\xef\xf1\x03\xde\x63\x01\x25\x2a\x09\x6f\xc4\x47\x83\xbb\x30\xa0\xd5\x67\x47\xe0\xff\xe4\x90\x5d\x8b\x19\x2d\xca\x93\xff\xda\x2d\xa9\xbc\x66\xb3\xea\xa7\xbb\x44\xa2\x4b\xc6\x2b\x0b\xbc\x23\x59\x72\x88\x52\x5b\x52\xf8\xa5\x75\xac\xe8\x2f\xfc\x92\x1a\x96\x08\x0e\x8a\xdb\xf4\xb3\x77\x43\xdc\x9d\x44\x63\x09\x44\xfe\x79\x45\xfb\x8a\xbc\x2b\x01\x2a\xd0\x36\xe9\xcc\x35\x53\x19\xca\xeb\x00\x2c\xd6\x21\xcf\xdb\x44\x1c\x51\x1f\xa6\xfa\x91\xfb\xd5\x7f\x66\x9e\xb8\x56\x55\xc7\xc7\x99\x53\xad\xd1\xf5\x56\x7d\x96\xcb\x59\xa8\x9d\xf7\xcf\xd5\x1a\xfd\x92\x9b\x80\x9b\x43\x94\x62\x80\xe8\x31\xbe\x53\x79\x73\x84\x38\x42\x76\x82\x86\x49\x0d\xa1\xd8\x3e\xd2\xb0\xc8\x29\xf3\x26\x61\x5a\x39\xd9\xac\x78\xc3\xeb\xef\x2f\x06\x32\x8c\x2e\xdb\xaf\x6e\xb5\x69\x48\xd9\x46\xe9\x8c\x18\xbb\x9c\x2c\x30\x99\xac\xa0\x43\x41\xec\x85\x96\x2c\x06\x93\xf0\x38\x49\x40\x8b\x1a\xe4\xf3\xa8\xd2\x04\xb7\x8e\xd3\x2e\xcb\xbc\xff\x09\x29\xb3\x03\x6a\xa4\x94\xa4\x3f\x83\x56\xa6\xf4\x37\xfa\xe4\xf4\xb2\x29\x6c\xa0\x07\xca\x36\x4d\xd5\xc3\x46\x87\xc2\x3f\x65\x63\x10\xc5\xbb\x72\x3b\x8b\xe1\x86\x4a\x33\xea\x5a\x5a\x5b\x09\x0f\x0a\xb3\x80\x3c\xde\xef\x6b\x73\x75\x0c\x3a\xfc\xb4\x17\x1c\x0d\x26\xe2\x26\xcb\x35\xc4\xf5\x87\xaf\xb6\xd1\x0e\xe4\x66\x51\x9c\x44\xb6\x7a\x4e\x9c\x01\x2f\x07\x9d\x02\x9c\xce\xef\xcc\xdd\xa8\xbd\x85\xd0\x46\xfa\x65\x75\x96\xca\x08\xa6\x2b\x3a\x5a\xb8\x00\x71\x9a\xbe\x76\x19\xa5\x98\x85\xd8\x72\xbd\xdb\xf7\xf6\x71\xd6\x7b\xa9\x08\x85\x9e\x92\xaa\xd9\x07\x68\x58\xe2\x51\xd3\xd2\xe5\x82\xdf\x63\xee\x24\xac\x69\x2d\x5e\x65\x91\x10\x1e\x49\x80\x91\x9b\x89\xe8\x99\x8a\x45\x44\x2c\x55\x6f\x09\x18\x80\x36\x87\xad\xb0\xed\xdd\xc5\xb9\x8c\xfc\x45\x54\x23\xbe\xb9\x6d\x9a\x24\x0c\x77\xf7\x1d\x7e\xed\x8a\xda\xdf\xd2\x85\xe6\x1d\xa4\x6d\xdc\x2e\x0d\x14\xd1\x0e\xf8\x0a\x33\x65\x8f\x6f\xda\xfd\xd6\x97\xa5\xdf\x23\x05\x77\xb9\x80\xbb\x94\x8b\x14\xc8\xb7\x23\x2c\xf6\xe1\x08\x1e\x4e\x70\x7b\x4c\xaa\x7f\xf0\x05\x26\x40\xad\xd5\x24\xcd\x1e\x9e\x64\xa8\x95\x50\x31\x05\x63\x0e\x98\xe4\x1a\x50\xd8\xa7\x42\xc0\x00\x62\x2d\x7d\x84\xf9\x2c\x20\x07\xb4\xdb\xe5\x13\xb2\xcf\x99\xda\x23\x8b\xd8\xb2\x17\xbc\x5b\x3a\x1c\xed\x2b\x5c\x0b\x5f\xa8\x9a\x67\xe4\x10\x95\x17\xef\xe2\x9d\x7d\xa2\x7e\x1a\xf5\x19\x17\xe6\xe8\x3e\x97\xf9\x99\x03\x7b\x8c\xc5\x2b\x20\x62\x95\x68\x36\x11\xe1\x93\xcb\x9a\xb8\xd0\xca\x47\xf7\xc4\x6b\xe9\x4f\x79\xb3\x93\x08\x4c\x23\xa3\x64\x19\xba\xec\x33\x04\xcd\x8c\x10\xf6\x60\x49\x8d\xc2\x64\x95\x65\x35\xb6\x75\x7d\x4a\xdb\xc0\x91\x33\x9f\x0a\x34\x25\x22\x9c\x35\x9d\xd2\x7e\x33\x35\x9f\x37\xc2\x8a\xd9\xf1\x45\x5e\x25\xd5\xb3\xfc\x78\xcd\x81\x79\x4e\x63\x74\xd2\x36\xa4\xe2\xd5\x26\x36\xd8\x26\x6e\x8c\xac\xa3\x2c\x99\x6d\xce\x89\x64\x84\xa9\x76\x27\xb7\xe3\x14\x47\x12\x4d\x9c\x43\xee\xa9\x9b\xd4\x6b\x63\xbb\x24\x0a\x11\xf6\x65\x34\xaf\x0a\x3b\x3b\x67\x24\x42\x4a\x4d\x29\x64\xe7\xd0\x39\xc6\xf4\x03\xaa\x88\x04\x90\x17\x6e\x6b\x78\xaa\x34\x7a\xa0\x15\x9e\x20\x40\xf1\x13\x9c\x7a\x1f\x03\xef\x65\xf3\x76\x70\x58\xdb\x30\x04\xb3\x13\xaa\x0d\x5a\x14\x45\x89\x22\x0d\x1b\xbb\x7a\xd1\x72\xf9\xa0\xe1\x4a\x2d\x2a\x22\xa2\xbe\x31\xc4\x84\xc3\x9f\xcb\x84\xd1\xc4\x8a\x37\x53\x8e\x69\xfa\x20\xae\x32\x63\xeb\xa2\x0c\x23\x47\x9a\x12\xef\x81\xce\x54\x43\xa5\x74\xed\xde\x79\x73\xe0\x9e\x85\x19\x1f\xff\xe9\x40\xd5\x3c\x6c\x7f\xa7\x95\xa3\x4e\xde\x31\xb2\xf2\xf3\x4a\x4b\x85\x9f\x79\xe9\x38\x76\xd6\x4b\x49\x73\x93\x9b\x68\xfd\x1e\x6d\x4b\xae\xd7\xa4\xca\x57\x0c\x83\x7c\x6b\x54\x80\x5c\x47\x28\x06\x12\xab\xd4\x00\xda\xba\x96\x86\xda\xd6\x99\xc8\xc3\x3b\xc7\xb0\x7f\x4f\x70\xb4\x32\x7a\x8e\xaf\x48\xb1\xd0\x38\x75\xe8\xc2\xcc\x3a\x2b\xe2\x74\xb0\x79\x4c\x39\x52\x84\x86\x15\xf0\xc0\x53\xa5\xa4\x65\x40\x66\x9a\xd8\xd8\x76\x9a\xe5\x57\x3e\x3f\x3d\x6a\xad\xac\x88\x93\x86\x27\xa1\x10\x02\x21\x6b\x00\x5a\xdf\xbc\xc4\x34\xc6\xfa\xd2\xec\xc0\x56\x6d\x3c\x58\xde\xa7\x05\xa0\x0f\x0a\xbb\x47\x0a\xbb\x9b\x2c\x83\xdd\xc3\x72\x96\x67\x25\x1c\xd1\x2c\xc3\xe4\xc4\x07\xaf\x70\xcc\x5e\xa4\x33\x45\x00\x90\x7a\x6d\x13\x41\x06\x52\x9e\xe4\x9c\x10\x08\x1d\x7d\x49\x20\x8c\x8b\x1d\x78\xb1\x54\xda\xc6\x00\x51\xef\xc6\xbe\x7d\x2c\x89\x7a\x44\x90\x33\x39\x89\xa2\x79\x3e\xa4\x60\x33\x89\x71\x2c\x0a\x57\x6c\xad\x24\x15\x07\xb3\x0b\x50\x13\x74\xdf\x98\xc6\x1b\x7f\x03\x88\x4c\x86\xd0\xf0\x21\xee\x7f\x9a\x86\x92\xbb\xe9\x7f\xda\xd7\x14\x52\x97\x2f\x96\x82\x4d\xf9\x14\xa0\x46\x2a\x2a\xe6\x5d\xef\x3a\x40\x16\x8a\x93\x62\x82\x90\xd2\x2d\x85\xb9\xb0\x29\x73\x3e\x4c\xf9\x95\xc8\x9f\x26\xbf\xb6\x50\x3f\xe9\x0f\x7d\x53\xfb\x3f\xbf\x0d\xd1\x53\x60\x3f\xf8\x77\x40\x28\x8a\x3d\x0a\xb0\x2d\x70\xe2\x9c\x76\xf2\x80\x4a\xc5\x37\xbf\x41\x84\x94\x5c\x7a\x3c\xba\x18\xca\x13\xc0\x8e\xca\x43\xa1\xeb\xad\x5f\x95\x1d\xe5\x57\x8a\xa0\xbd\x2e\x3e\x18\x71\xce\x3e\xbf\x4c\x8b\x01\x2e\x2b\xe0\x75\x55\xe5\x40\xc3\x2b\xda\xc9\x75\xba\x33\x1d\xc1\x4b\xbb\x44\x2d\xae\x1d\xfa\xe1\x37\xe9\x2a\xb7\x37\xaf\xdf\x61\x0f\x6a\x85\xcc\x6f\xea\x9f\x21\xbf\x0e\x1b\xd3\x4e\x6a\x5f\x6e\xde\x75\x53\xa8\x40\x65\x38\x86\xdd\x82\xab\x38\xd1\x1b\xda\xec\xd1\xbf\x7a\x18\x15\x0c\x74\x8c\x4b\x7b\xb3\xf8\xc5\x0e\xf0\x83\x1a\xea\x59\x92\x1d\xfb\xd9\xf3\x6f\xa5\xf0\x48\xcb\x4e\xfd\xa4\xe8\x12\xe5\x3a\x20\x1f\x2a\xac\x12\xfe\x5f\xf8\x20\x94\x83\x16\x24\x32\x4e\x99\xc8\xac\x62\xef\x27\x07\xfa\x25\x96\xe5\x3c\x3f\xc1\xff\xaf\xfd\xb2\x2b\xa1\xc2\x0f\x43\x8c\x40\x2e\xe5\x90\x32\xea\xd9\x00\x42\x55\x6b\x86\x7d\xb1\x59\x88\xf8\x8a\xd3\x5d\x6d\x30\x9b\xf7\xc8\x13\xcf\x14\xaf\xf9\xe1\x5d\x05\xd6\x34\x40\x96\x25\x7a\xcb\x91\x76\xd2\xbb\x82\x3f\xca\xa4\x5d\x05\x8b\x51\x29\xb2\x9b\x04\x9e\x25\xda\x16\x4e\x2c\xa2\xa2\xbb\x0c\x9c\xd2\x60\x63\x87\x4a\xa6\x64\xe1\xdb\xab\x64\x22\x44\x73\x6c\xac\xd3\xa8\x40\x90\x66\xd5\xd4\x5c\x8d\xce\x59\x34\x6c\x55\x88\xec\x7f\x5b\xd8\x55\x65\x99\x5c\xab\x00\x63\x71\x41\x4d\xe9\x74\xf9\x2a\xcc\x5c\x60\x47\x64\xce\x2d\x5c\xf6\x95\x37\xad\x81\x60\xaa\xd7\x99\xbc\x56\x67\x16\xf0\x96\xc2\xda\xa2\xa5\x55\xec\x2a\x65\x8a\xa1\xb7\x46\x95\x54\xd5\xd7\xc1\x7f\x41\xe8\x0a\xdd\x1b\xf5\x77\x1c\x4a\xed\x28\xa5\xdd\x45\xde\x68\x7d\x81\xe8\x0a\x58\xb3\x1f\x4a\x31\xad\x63\xcc\xcf\x53\xb5\x1f\xe0\x4d\xd9\xc1\xb1\xa4\x2f\x70\xb0\x04\x17\x8d\xa9\xe2\xbe\xfe\x94\x23\x28\x24\x69\xe3\x7f\x3d\xd4\x1d\xd9\x27\x6a\xfd\x5f\x92\xaf\x62\xb7\x43\xfd\x03\x3c\x6b\x10\xc3\x26\xf8\x7a\x08\x1d\xe9\x4f\xfe\x2a\xb7\x8d\x43\x40\x16\x96\xba\x65\xf3\x86\xec\x1d\x94\x81\x1f\x94\xda\xc5\x2e\x27\x2f\x7e\x1a\x57\xd9\xd2\x89\x5e\xff\xeb\x6c\xd2\xb9\xd1\x68\xae\xb2\x29\x64\x69\xb3\xc6\xf1\x0e\xb6\x0f\xad\x8f\x0d\x66\x41\x4a\x1c\xe5\x49\x14\x2c\xdc\x10\xaa\xf5\x51\x55\xb9\xc0\xdb\x25\x4a\xbd\x67\xe7\x78\xed\xf6\xaa\x66\x0c\xbb\xfb\xe8\x2d\x99\x31\xb6\x89\x9e\x63\x12\x52\xf0\xde\x39\x4a\xf7\xea\x05\xb5\xd6\x9e\x6f\xca\xa1\x81\x27\x9e\x08\x2d\xa9\x0b\x7a\x3e\xb4\xb0\x6d\x5e\xad\x57\xe8\xac\x9c\x4a\x72\xe3\x7c\x70\xd5\x50\xe3\x10\xc4\x1c\xd0\xe0\x13\x5a\x1a\x7a\xcf\x15\xa1\xbf\x7c\x95\x01\xa5\x4a\xa0\x73\x6d\x08\x73\x34\xa9\x01\x9d\x88\x2a\x1d\x71\x10\x4e\xa6\xc8\x82\x92\x82\x43\xd8\x49\x53\xd8\x7d\x18\x24\x44\x01\x3e\xa3\xed\xc1\x16\xe8\x04\xf6\x07\xa7\x50\xa3\x22\xcb\x72\x2c\xeb\x94\x36\x38\x09\xb3\x61\x9b\xa3\x9b\xe6\x21\xb5\xc1\x87\x56\xb6\x16\x26\x29\x3a\xd9\xc6\x54\x54\x1f\x26\x57\xb5\x22\x2c\xbb\xba\x1c\x63\x84\xae\x97\xb6\xff\x1a\x8b\x76\x83\xe1\x3c\xb5\x33\x13\x3a\xbc\x87\x16\xc5\x92\xdf\x45\x70\x2f\xbf\xc3\xff\x24\xb7\x47\xae\xc8\xc5\x27\xa3\xe9\xc7\xa7\x1e\x6c\xa4\x0c\x6d\x92\x5f\xd9\x76\x95\x6f\x0f\x87\x09\xbe\xa3\x5d\x59\xff\xb0\x8b\xa1\x35\x6f\xc3\x3d\x41\x12\x1a\xf5\x6a\xb1\xac\xd0\x48\x48\xa6\xee\xe2\x72\x33\x49\xad\x8f\x5d\xbf\x95\xda\xdd\xd0\x23\x71\x47\xab\x37\x9e\x12\x9a\x9e\x64\x68\x97\x33\xf6\x1f\xa1\xde\x5c\xc3\xd3\xa9\xcf\x63\xf6\x2d\x3f\x55\x4e\xc1\x10\x59\xfb\x16\xce\xbd\x31\x58\xf6\xe0\x43\xf4\xe0\xa4\x4a\x97\xcb\xd5\xaa\x3a\xe7\x97\xae\x67\xf3\xe1\x8d\xc9\x7a\x12\x26\x57\x9b\xfa\xb4\x5b\x07\xda\xb9\xd6\xca\x9c\x0e\xe8\xf3\xf6\x3a\xdd\x2a\xff\x1b\x51\xc0\x11\xaf\xe7\x23\x92\xe4\xe0\xba\xa8\x2b\xe7\xf2\x7d\x67\x00\x8f\x3a\x91\x21\x46\x73\xed\x66\x8c\x63\x82\xf5\xbc\x74\x8a\x0f\xe8\x28\xf4\x90\x54\x0a\x3b\xca\xdb\x8d\x70\xc8\x6c\xa9\x70\x89\xa6\xe4\x92\xd2\xc7\x57\x62\x5c\xfb\xfb\x9c\xbc\xf6\x15\x23\xcc\xe0\x5b\xa7\x3f\x03\xc7\x69\x86\xbd\x71\x2f\xc7\x0b\x7d\x1b\x39\xa8\x04\x91\x59\x65\x49\xda\x2a\x32\x56\x89\xe7\x03\xb2\x58\xba\xa0\xf4\x42\x41\xb8\xc7\xc9\x73\xd9\x65\x65\xc1\x79\x0b\x43\x2c\x42\xc2\x4f\xb3\xc0\xa6\x93\x89\x22\x4d\x67\xbf\xbb\x84\xf3\x34\xcb\x3e\xd0\x6c\x19\xf0\xd3\x32\xba\x6f\x96\xe8\x5b\xa6\x2d\xf0\xec\x23\x92\x6b\xe8\xea\x88\x4e\x7c\x51\x9f\xca\x48\x58\x85\x4c\x31\x8a\xa4\x74\xad\x00\x80\x5c\x08\x61\xa7\x09\xad\x54\x3a\xb5\x79\x1e\xd1\xf0\xa8\x0e\xbe\x03\x86\xb2\xbe\xd0\xd0\x75\x7f\x50\x5d\x23\x74\xe8\x7d\xd6\xed\x3d\xae\x74\xf7\xa1\x39\xe1\x7c\x52\xb5\x53\xb5\x5b\x48\xbc\x6c\xd9\x25\x49\x5b\xba\xd0\xe5\xda\x60\x9a\x95\x48\xc2\x6a\x27\xd4\x12\x15\x45\xfa\x77\x86\x8f\x4b\x5b\xd8\x46\x2b\x77\x03\x85\x0d\xf6\x9b\xf4\xfc\x62\x81\x1a\x44\x8e\x2b\x9e\x3e\xaa\xef\x4c\x2a\x1c\x68\x47\x41\xdb\x8b\x11\x39\x3d\x43\x1d\xc0\x61\x77\xc9\x14\x94\xe8\x02\xd9\x02\x61\xad\xdd\x5d\xc0\xe6\xc8\x30\x78\x46\x39\xf8\xb4\x97\x1f\xf1\x28\x6c\xda\x01\x19\x38\xff\x3a\xe5\x83\x8d\xe6\x09\xa6\xc1\xbb\x6b\xe5\x8f\x02\x07\x5d\x13\x69\xf0\xf2\x28\x6c\x66\x95\x50\x98\x02\x10\x0e\xe6\xca\x17\x63\x06\xc8\x02\x2d\x84\x37\xd2\x1c\x37\xfd\x9a\xa4\xbf\x10\xed\x8b\x7b\x70\x45\xcc\x62\x9a\x30\x8f\x01\x4c\x01\x67\xf4\x0e\x65\x2d\xb4\xb2\xe3\xb3\x57\xf2\xea\x6d\xc6\xe7\x90\xad\x19\xbd\x00\xda\x8e\x49\xaa\x54\xe8\x9e\x9b\xe9\x25\x20\x2e\xe1\xf9\xd8\xad\xcf\x13\x90\x14\x49\xe8\xb1\xa2\xde\x92\x39\x73\xa3\xf5\xe4\x53\x53\x83\x47\xa7\xcd\xb8\x48\xcc\x75\x73\xe7\x64\x96\x4b\x03\x40\x83\xed\x93\x49\x79\xeb\xe3\x88\x95\xa2\x3a\xbb\xa1\x7e\xd6\x31\x60\xb3\x1d\xe0\xb9\x9f\x4f\x44\x46\x47\xbc\x25\x20\x7e\x22\xf0\x8a\xfb\x98\xf6\x11\x07\x8b\xd5\x87\xd8\x9a\xd6\x89\x13\x5a\x55\x10\x17\xed\xb9\x95\xa3\x2f\xb3\x26\x44\x68\xc2\xd0\xa6\x62\x34\x64\xec\x20\x92\xee\xcc\x2e\xe4\xb2\x6b\xec\xf5\xa7\xfd\x73\x2b\xef\x5f\x94\x05\x94\x0f\xe9\x71\xb4\x2a\x0f\xb8\x54\x88\xf6\x2f\x02\x31\xc1\x24\x35\x8b\x6f\xd7\xde\x46\x69\x31\x7a\x2b\xc7\x00\xfc\x57\x5b\xf4\x07\x5a\x7d\x31\xfe\x4a\x32\x28\xc4\x8b\x18\x7e\xab\x5f\x7c\x2b\x60\xca\xcb\x67\x33\x9f\x0e\x72\xa5\x1e\xe7\x41\xe0\x42\xe2\xee\xd0\x90\x58\x4d\x63\x5e\x84\x26\xf1\x0b\xec\xdb\x34\xd2\x1a\x7d\x4e\x16\x0e\xe6\xbd\x71\x02\xb6\xbe\x28\x63\x98\xc9\xe7\x22\x4e\x61\x8c\xc4\x27\x81\x53\x75\x35\x18\xc4\x95\x7a\xbb\x9f\xb8\xc7\x4c\x60\x63\x61\x65\xb9\x96\x96\x2a\xaa\xe9\x28\xb7\xcf\xc9\x5e\x8d\xf8\xd7\xbe\xb3\x82\x8c\x43\x37\xbe\x0e\x07\xdb\x26\xa0\xf3\xd2\xa2\x73\x57\x66\x6b\x2c\x80\x90\x89\xcd\x97\x83\xa9\x40\x27\x71\xb9\x37\xc7\xf4\x34\x7c\xb0\xe5\xbc\x86\xe0\xb9\x29\xbd\x3b\xc2\x12\xcf\xa1\x86\x5d\x09\x5a\x5d\xda\x24\x66\x87\x8f\x1d\xa0\xaa\x60\xe0\x32\xb7\xab\x33\xca\x0b\x59\xd1\x12\xf4\x92\x15\xcd\xb1\xe6\x8a\xa5\xdb\x79\xa9\xb0\x2e\x7a\x2c\x99\x75\x57\x76\x46\xfe\x48\x06\x74\x71\xfa\x61\x3a\xa8\x8a\x60\x11\x24\xc2\x0c\x17\x54\x52\x28\x2c\xb1\x2e\x64\x03\x05\xa0\x33\xeb\xd9\xf0\xb3\x62\x64\xa1\x16\xa6\xb9\x23\x51\xfc\xba\x89\x73\x6b\xf9\x0f\xc4\xe8\x48\xe9\xa5\xa5\x7c\x70\x60\x34\x94\x23\x77\x77\xf6\x3f\x65\xb3\x32\x39\x1b\x42\xfb\x92\x11\xc5\xbb\xbc\xcf\x24\x2e\xc2\x92\x6e\x76\xe1\xbc\x3f\x4d\xcb\x15\x0f\x42\xd1\xc8\xb8\x73\x82\x70\xa1\xd3\x4f\x9a\x41\xf3\xa8\x53\x73\x41\x15\x23\x71\xea\x90\x0e\x72\x61\x21\x88\x38\x95\x32\xbb\xbc\xd5\xe8\x7a\x7a\x9f\x8f\x76\x71\x78\x54\x76\x11\x99\x2b\x7d\x42\x28\x58\x94\x78\x6c\x9c\x23\x9d\xc7\x36\xa8\xab\x0b\x88\x41\x90\x05\x34\xd6\xac\xd6\x8d\x28\xf3\xaa\x50\x8e\x15\x1a\xc4\x88\x9e\xec\x7c\xd8\x29\x80\xab\x85\xad\xdd\xf6\xec\xa0\x32\x6e\xce\xa4\xfa\x99\xd7\x27\x78\xad\x8d\xf7\xd8\x3b\x3a\x02\x00\x24\xc9\x3b\x5f\x37\x94\x53\xd6\x5e\x21\x78\x2a\x1e\x60\x62\x71\x09\xd7\x72\xa5\xed\x5b\x03\x1a\xb5\x56\x27\xc3\xad\x26\xfc\xeb\x02\x8c\xde\xb3\x35\x08\x43\xe2\x1c\x78\x70\xf5\x62\x57\x30\x6d\x0a\xfb\x14\x1d\x39\x36\x65\x7e\x0c\x54\xcb\x71\xa5\x0e\xb6\x76\x31\x72\xbe\xc5\xfc\x9d\xb8\xa7\x7f\x23\x71\x4a\x5e\xb6\xe1\x0e\xd3\x87\x30\xa0\x4e\x6c\x59\xbc\xbc\xa8\x23\xe2\x46\x09\x83\x85\x5d\x89\x22\x0a\x4d\x04\x07\x9c\x6d\xc8\x1d\xb4\x9e\x4f\x99\x13\xea\x1e\xe9\x35\xe6\x48\xb6\x51\x1d\xba\x3d\xd8\xc3\x0c\xc9\x87\x57\x16\xed\x5b\xf3\x98\xba\xd3\x4c\xaa\x07\xb4\x07\x1f\x58\xdd\x42\x00\x45\x67\x89\xe2\xd6\x1e\x06\xc9\x8c\xe6\x9f\x1a\x50\x18\xf6\x79\xf7\x12\xc1\xcd\x1a\xdf\x04\xde\xfc\x31\xa8\x3c\xb7\x5f\x1f\x6c\x26\xa9\x20\x2e\xbc\x8f\xcf\x3d\x53\x6e\xde\x1d\xf4\x22\x3d\xc5\x06\x86\xd9\x59\x93\x5c\x1a\x9d\x10\x07\xa5\x51\x29\x0a\xea\x3a\x6d\x63\x30\xf7\xac\x2c\x18\x4a\x8a\xcc\x1e\x07\x1a\xd4\xfa\xf6\x21\x0c\x1a\x6f\x1c\xc9\x52\x3f\x39\x7b\x83\xa0\xad\x7d\x15\xde\xea\x2a\x16\xca\xc6\x99\x32\x16\xff\x29\x0c\x33\x6a\xfc\xd3\x9d\x15\xc7\x98\xce\x0b\xb0\xbd\xae\x60\x5a\x98\xb7\x3c\x79\xb8\x3a\x25\x6e\xd8\x0d\x1b\xd3\x6d\xca\x98\x2a\x2e\x4f\x93\xab\xcd\x04\x26\xc8\x01\xea\x7f\x19\x3a\x4c\xc9\xcf\x9b\x24\x4d\x6c\x16\xc8\x97\xfd\x67\xed\x94\xa8\xd1\x84\x90\x1a\x08\x3a\xdb\x0f\xbd\x4a\x85\x83\x82\x24\xe8\x22\x17\x75\x0e\x90\xcf\x0b\x8b\xbf\xed\xe4\xba\x96\x56\x52\x21\x3b\xfe\xdf\x04\xd6\x07\xe9\x43\x93\x86\xcd\xde\x72\x10\x07\xab\x26\x54\xd7\xb0\x9c\x02\x41\xcd\x49\x89\x63\xbf\xa8\xac\x05\xd8\xe4\xf0\x61\x2d\x51\x49\x58\x48\xe6\xac\x54\x63\x49\xcf\xc4\xea\xe4\x77\xf6\xf2\xad\x31\x58\x70\x8e\x0e\x53\x2c\xf9\x0a\x33\x38\x4e\xea\x11\xda\x60\x00\x10\x1b\xb6\x94\x99\x00\x4a\x8c\xbb\x60\x68\x51\xe0\xc4\xc2\xa6\x21\x0a\x4e\x32\xa5\x79\x2a\xd4\x76\xea\xa0\x7c\x69\x81\x9c\xa5\xa4\xeb\xe9\xce\x55\x29\x12\xce\x62\x70\x56\xfd\xd9\x4f\x87\x93\xe4\x29\x48\x2f\x39\xbd\x1b\xec\x28\xcb\xb7\x7b\x67\x70\x7c\x7c\x98\xd9\x11\xd4\x69\xf2\xa5\x73\x4c\x93\xf3\xec\x54\xbf\xf6\x17\x13\x9e\xe5\xc1\x58\x60\x2d\x93\x36\xc7\x1b\x38\xba\xf9\xd0\x44\x89\x70\x0f\x6f\xfc\xd9\xc6\x6c\x2f\x2b\xb7\xb2\x59\x62\x4c\xce\x34\x63\x6c\xcf\xf9\x1c\x05\x07\x39\x55\x2e\xe0\x55\x02\x18\x97\x4a\x1d\x87\x65\xd3\xd3\x35\xda\xa1\x74\x9b\xbd\x33\xf5\xa7\x54\x96\x8e\x26\x25\xcd\x62\x30\x2e\xcb\x67\x92\xa6\x7a\xc2\xaa\x2d\x4f\xae\xa8\x44\x05\x93\xfb\xed\xfd\x6a\x3e\x2f\x55\x63\x57\x57\xbf\xf9\xe3\x05\x4d\x58\xf7\x03\xd6\x09\x05\x02\x53\x1c\x04\xe4\xc8\x65\xbe\x18\x53\x03\xac\x45\x76\x9a\xa0\xc0\x7a\x26\x27\x36\x1e\xdd\x85\xd1\x74\x72\x14\xcb\x6a\x26\xd8\x67\x5f\x59\xf9\x73\xec\x51\x3a\x7f\xa1\xce\xee\x23\xcf\x54\x98\xc9\x1f\x2a\xa7\x8b\x9d\x2b\x67\x72\xf2\xda\x19\xb9\xd3\x3b\x45\xaa\x76\xdc\xe4\x1f\xce\xf2\xda\x94\xaf\x5a\xd8\x55\xcd\xa1\x05\x6a\x48\x57\x34\xbe\x52\x8b\x38\xce\x6c\x85\x54\x90\xdc\x02\xc0\x87\xf3\xfe\x01\xde\xca\x7e\x5b\x05\x43\x12\x90\x08\x02\x83\xce\x3a\xfe\x78\x11\x34\x74\x54\x3e\xb4\xeb\xc4\x29\xc9\x1e\xf6\x9b\x9e\xfd\x20\x2a\xe8\xdb\x7a\xbd\x5b\x1c\xed\x50\x1f\x4b\xd6\x90\x35\xa9\x30\x1b\x75\x19\x26\x42\xe1\xa1\x4f\x6c\xd8\x38\xd4\x36\x21\xf5\xd0\xfa\x95\x5d\x54\x26\x90\x2a\xdf\x6b\xb7\xf9\x17\xe3\x92\x6d\xaa\x07\xc6\x23\x71\x2a\xce\x3b\xb0\x0c\x75\x73\xac\xa4\xa9\x91\x3f\xc0\x70\x61\x21\xa7\xde\x8e\x10\x7a\xef\x77\x85\x30\xa3\x05\xbf\xac\x62\xa8\x19\x70\x6d\x3f\x65\x3a\x92\xef\xc0\x22\x5e\x08\xf6\xd0\xd5\x37\xc8\x48\x77\x68\x85\x0e\x3b\xa9\x48\xc3\xe0\x5c\xde\x81\xa4\xc4\x75\x97\x2b\xcd\x61\xe1\x24\x55\x9d\x0f\xc9\xb9\x04\xb7\x8e\x6a\xa4\xce\x6b\x3e\xbd\x74\xb7\x51\xec\x78\x0d\xde\x2b\x42\x42\xb7\x7e\x35\x0a\xeb\xe0\x57\xdf\x37\xba\x75\xb4\xeb\x91\x34\x4f\x09\x7f\x87\x92\x5a\x7a\x21\xa5\x55\xe7\xc3\x17\xd5\xb2\xad\x55\x6d\x0d\xeb\x50\x9a\xc0\xfc\xfb\xd9\x71\xfc\xc6\x84\xe8\xe2\xf8\xcd\x8f\x0a\xc6\xc2\x77\xa6\x05\xd0\x07\xf2\x9d\x4e\x4a\xce\x36\x7a\xb7\xb6\x91\x59\xae\x9d\xac\x96\x55\xdc\x16\xf3\x61\x15\x8e\xd3\xa3\xb6\x4a\xf0\x80\x98\x29\x4e\x84\x74\xd7\x6f\xf6\xf9\x2c\xff\xfc\xec\x28\x6c\x69\x73\x89\x0c\x8f\xc4\x69\x45\xd0\x30\xa7\xc3\x65\x79\x5d\xf5\x5e\xa9\xad\x8e\x8a\xb9\x02\xba\xc3\x21\x9a\xe6\x30\xd8\x9c\x54\x59\x07\x9e\x83\xc7\x26\x7c\x48\x9f\x59\x48\xd8\x79\x7b\x90\xfa\xe2\x74\x00\xed\x3e\x91\x33\x6b\x67\xea\xcd\xca\x52\x43\x37\xdb\x8b\x0a\x8e\xfa\x6e\x1b\x25\x4a\xc5\xdc\xe2\x34\x61\x92\x86\x23\xcd\x98\x3a\x8d\x33\x85\x92\xbe\x86\x3e\xf5\xc9\x2f\x6c\x69\x6d\x42\xff\x7f\x9d\x33\xe2\x47\x2c\x5c\x87\xce\x8a\x7c\x0a\xfd\x84\xb1\x17\xa8\xf7\x8f\x0c\x59\xbb\x0e\x03\xe3\x18\xa6\xc7\x73\xca\x3e\x89\x59\xce\xd2\x86\x43\x35\x53\x36\xd2\x4a\x4d\x93\x9d\x1d\x1b\x32\x1c\x9c\x60\x05\xed\x0a\xb9\x3b\xce\xaa\x0a\xe8\xee\xf9\xb1\x61\xb6\x1d\x7e\xa2\xa1\x11\x61\xeb\xcb\x19\xbc\x6f\xc2\x49\x28\x2a\x8b\x47\xcc\xb4\x82\x7b\xa8\x34\xf3\x38\x06\xa6\x85\x0e\x92\xda\x33\x34\x27\x39\xda\xcd\xd7\x3d\x40\x8d\x62\xcb\x14\xf7\x97\x88\xb7\xa3\x74\xe4\xe0\x38\x5b\x8e\x48\x42\x2f\x59\xbc\x14\x9a\xf7\x8b\xd6\x96\xec\x5f\xb3\xaa\x67\xda\xab\xcd\x81\xc3\x27\x27\xa7\xa3\x4e\x94\xc9\x9a\xca\x1c\x54\x55\xdb\xd0\x91\x21\xa9\xaf\x43\x00\xf5\x24\x5a\xaa\x5b\x43\xc2\xdc\xf8\x93\x17\x37\x64\x58\xac\x5f\x57\xf5\xe1\xd4\xf8\xe8\x82\xa8\x6f\x2f\xcd\xbf\x82\x0f\xf7\x96\x8b\x60\xc5\x10\x33\x4c\x6f\xd8\x25\x67\xb8\x89\x6d\x76\x85\xb6\x4e\x8d\x75\x2d\xd4\x3c\x39\x61\xfb\x9e\x3f\x76\x5e\xb4\x4f\x03\xd1\xb3\x96\x33\xed\xc7\x13\x3a\x85\x08\xa5\x81\x4a\x60\x02\xe3\x66\xaa\x1a\xce\x4f\x74\xf6\xdd\x62\x1a\x5b\xf8\x5a\x4f\xfd\x8d\xaf\x86\x72\xbc\x76\x4c\xe0\x95\x2a\x44\x69\x6b\x08\x13\xcc\xd8\xe2\x72\x04\x56\x2d\x7d\xd8\x18\x68\xd8\xb8\xa3\x7c\xce\xc4\xa1\x2a\x8a\x40\xdc\x5e\xda\x1e\x0c\x04\x39\x72\x7f\xd4\x75\x31\x1c\x31\x74\x97\xdd\xab\xb5\x3f\x71\xce\x7c\xbc\x56\x66\x24\x27\xf6\xc9\x7b\xf0\x51\x69\xdb\x03\xba\x17\x20\x40\x8e\xa3\xb8\x21\xa3\xf8\x09\xca\xfe\xb0\xe3\x37\xe2\x63\x85\x41\x60\x99\x82\xc7\x16\x6b\x92\x13\x58\x68\x7c\xd8\xd8\x5d\x7c\xc4\x89\x31\xc2\xec\xbf\xe6\xf7\xd1\x12\x9b\x38\x6a\xc6\xa8\x4d\x88\x2c\x17\xce\x0c\xc0\x61\x85\xe8\x2f\x96\x1c\x9f\x38\x44\x71\x95\x57\x46\x51\x60\x53\x76\x65\x83\xc9\x4c\x32\xd5\x64\x1c\x33\x78\x47\xf6\x48\x44\x65\x59\x9c\x5e\x40\xb3\xab\xae\x9c\x03\x92\xfc\x64\xab\x2b\xb2\x1f\x6b\xd8\x32\x8b\x13\x66\xf6\x32\x6a\xb2\xe6\x3d\x8e\xfa\x8f\x24\x1b\x9d\x24\x85\x72\x44\xd4\x46\x4a\x7f\x78\x37\xd2\x8a\x8a\x2b\x91\x35\x8d\xb6\x59\xf0\x97\xe0\xce\x85\xa8\x6c\xc8\xc8\x77\x12\xf5\x56\xfc\x94\xd1\xae\x59\xa1\xf0\x64\xbd\x3c\xfa\xdc\x7a\x1d\x4f\x01\x0c\xd7\x73\xb4\x8d\x72\xa9\x61\x54\x9f\xeb\xb7\x41\xa9\x3a\xb1\xeb\xbf\x0e\x0b\xa8\xbd\x48\x3c\x72\xfa\xca\x70\xa6\x92\xe4\x1b\xd1\xc7\x39\xa2\xe5\xcb\xde\x38\xbf\xf3\x7c\xb4\x8d\x15\xc8\xcd\xa1\x41\x0c\xf0\xc1\x0a\x6a\xd6\x81\x32\xab\x0d\xf9\xa3\x4a\x40\x63\x63\x92\x55\x6a\x99\xed\x49\x3e\x04\x24\xb8\xdf\x94\x5c\x5f\xd8\xee\x9c\xcb\x18\x0b\x29\x67\x99\x3d\xd8\x8d\x89\x32\xfc\x26\x68\xe2\x7a\xfc\x69\xb6\xf7\x74\x78\x43\xf2\xf7\x9b\x4a\xb3\x01\x9f\x06\xdd\x97\x54\xf6\x30\x5c\x11\x3d\x21\xac\xab\x6f\xcc\xaf\x56\x1d\x42\x9b\x51\xc2\xc7\x0c\x1a\xf9\xe0\xe6\xa1\x5f\x1a\x8d\xcc\x21\x53\x68\x02\x3d\x15\x94\x5e\x33\x41\x5a\x27\x3e\xd6\x81\x3a\x13\x1d\xa2\x85\x17\x8f\x30\x51\xd8\x71\x76\x62\xa0\x61\xa8\x96\xd5\xb1\x01\x11\x75\x62\xad\xc2\xbd\x87\x34\xea\x54\xd0\x2f\xa5\x8a\x03\x48\x01\xb9\x22\x73\x18\x6d\x55\xa4\x85\x4e\x9f\x2f\x8f\xb5\x33\x06\x9e\x38\xa9\x47\xa9\x1e\x34\x89\xe1\x76\xf4\xc1\xda\xde\x0f\x57\x01\x0d\x8c\xb5\x43\x6e\x06\x94\x4a\x12\x20\x3e\x8b\xd2\xc8\x64\xbe\xbd\x0a\x35\x6a\x94\x50\x14\x59\x2a\xb6\xbb\x7e\x0f\xe9\x88\xf6\x8e\x43\x6a\x4d\x05\x8f\xc8\xeb\x51\xb4\xc7\x35\x9c\x25\x0b\x30\x13\x50\xe3\x81\x73\xf8\x3f\x84\x44\x29\x7b\xf5\x82\x55\xf4\xda\xd5\x85\x5b\x0a\x08\xf1\xc5\x32\x52\x79\x3e\xd9\x46\xa7\xc7\x23\xb9\x87\x55\x55\x00\xce\x74\xde\x49\xbe\xfa\x10\xe3\xee\x1c\x78\x43\xb3\x6a\x1a\x0d\x85\x26\x34\xd4\xa1\x0d\x20\x7f\x07\x7e\xfb\x9f\xab\x5f\xd4\x3f\x67\x98\xf5\x2d\x67\x3d\xca\xf9\xb0\x00\x4a\xcf\x61\x60\x5b\x87\xdc\x0e\x6f\xdd\xe6\x50\x08\xad\xb4\x40\xad\xba\x8f\x3a\x25\x1b\x57\xed\xbb\x35\x70\x1c\xe5\xea\x2d\xfd\x2a\x01\x83\x9e\x6e\x13\x71\x04\x87\xc4\x87\x9f\x12\xd4\xf2\x87\x1a\xa3\xd6\x0c\xd5\xce\x43\x48\x4c\x03\x3a\xd0\x31\x7d\x5c\x8f\xd5\x0a\x4d\x3c\x46\x52\xaa\x8c\xb6\x79\xad\xf5\x31\xa4\x53\x3d\xa4\xc4\xb6\x86\xba\xff\xa1\xf3\x0d\x0d\x38\xf3\xe4\x77\x18\xe2\xb3\xb9\x73\x16\x05\xfd\xbf\x43\xee\x92\x87\x74\x92\x91\xf5\x88\x22\x13\xc9\x24\x49\x58\x07\xb2\x4f\x00\xbe\x1d\xe6\xd6\xa6\x6a\xce\x47\x7b\x59\xb8\x6d\xca\x97\x01\x67\xf8\xd6\x1f\x44\x6e\xc1\x9b\xfd\x60\xea\xc9\x2e\xfd\xc6\xe5\x12\xcb\x0b\x7c\x5b\xb6\x11\xdc\xde\x16\xc6\x7c\xc4\x32\xa4\xa7\x1a\x9e\x84\x58\xc6\x59\x14\xdb\xb2\xfc\xd3\x74\x6b\x1e\x46\x43\xa9\x30\x71\xbb\xd3\x51\x16\x4e\xd9\x10\x7f\x4c\x60\xf6\x88\x3f\x9c\xe9\x3c\x1f\xfd\xdb\x78\x8e\xea\x91\xe6\xa2\x0e\x0c\x1c\x6c\x23\x3e\xa0\x50\xca\x48\x50\xeb\x68\x9c\xb7\xc4\x9c\x43\x72\xbb\x6b\x10\x25\x20\x01\xe2\xa3\xdb\x0c\xfc\xc6\x5f\x96\x2f\x47\xc7\xd5\x14\xd8\x92\x5e\xc9\x06\x75\x2e\x84\x72\x60\xbe\xd3\x74\x9b\x6b\x10\xe7\x81\x74\xe1\x10\xba\xca\xbd\x99\x3d\x62\x5b\x1c\x93\xb6\x06\xce\xd3\x59\x6d\x1a\x36\x07\xbe\xa8\x88\x03\xe8\x86\x09\x75\x6a\xa5\xa2\x6d\x78\xfc\xa8\xf5\x0e\x54\x0b\xac\x7b\xce\xc0\x2d\x37\x79\x4b\x94\x5f\x65\x21\xbe\xfb\xf0\xec\x59\x65\x9d\x0c\x36\x57\xa9\xf3\xe1\xcc\xc5\xe3\x26\xbe\xa2\x9a\xa9\xaf\xf9\xf3\x49\x18\x28\xa4\xfc\x1d\xae\xa7\x33\x31\x50\x87\x09\xd0\x53\x55\x58\x6c\xe4\xcf\x5a\xcb\x27\x4b\x95\x7a\xdd\xf5\x0b\x7c\xfd\xb2\x5c\x07\x40\x67\x82\xab\x1c\x95\xb8\x60\x1a\x44\x0f\x74\x4b\xe9\x0f\xfc\x6a\x03\xa9\x99\xcd\x77\xaf\x3e\x75\x1b\x1d\xe1\x8b\x8b\xc5\x84\xd5\x6f\x89\xca\x2f\xdd\xe8\xfc\x56\x83\xa8\x42\x63\x2c\xfa\x79\x0f\xb1\x0b\x89\xc8\x6f\x40\xb7\xab\x65\x88\x8d\x68\x71\x12\xb1\xe6\xba\x92\x39\x4e\x08\xb5\x46\xcc\x6d\x79\x98\x01\x75\xdf\x76\xa1\xfc\x31\xd4\x2e\x2f\x12\x01\x2f\xa2\x5b\x9a\xf8\x55\xb3\xef\x27\x47\x28\x1f\xca\x39\x02\xee\x1a\x31\x8a\xfb\xf0\x41\x0c\x7a\x54\x69\xfe\x56\xae\x7f\x76\xc2\x5f\x1e\xfd\xea\xec\xd0\x16\xc7\xb0\x23\xda\x9c\x5c\x56\x5c\xcb\x26\xf6\x4b\x9a\x0e\x5b\x65\x20\xb9\xa8\xd3\xae\xcf\x65\x69\x70\xaf\x20\x3d\x6a\x76\xf3\xff\xb9\x7a\xb3\x05\xd5\x75\xdf\x69\xf4\x5d\xb8\xfe\x5e\xca\x49\x4c\xe2\xce\xe0\xfc\x32\xc0\x86\xa7\x3f\x2a\x55\xc9\xac\xff\xb9\xd8\x1b\x77\xaf\x9e\x80\xc4\x96\x4a\x35\xa8\x25\x99\x9a\xd7\xd6\xf4\xc3\xcd\xf0\xa8\x24\xd9\xe9\x27\x78\x1b\xdd\x25\x9b\xc7\xb3\xae\xc9\x9a\x27\x99\x0f\x3e\x7f\x69\xa9\x6e\x5e\xfa\x70\x46\x00\xeb\xf4\xe1\xa0\x13\xc8\x50\x23\x86\x27\x13\x80\x5d\x12\x1b\x24\xbe\xee\x03\xb5\xd7\x3d\x88\xcd\x62\x03\x08\x89\xdd\x04\xe8\xf7\x61\x4b\xea\x61\x66\x72\x95\x76\xca\x6b\x43\x68\x6e\x97\x67\xd1\xa1\xab\x03\xa3\x43\x69\x5a\x0b\x27\x2b\x56\xa3\x7e\x7c\x88\x82\x1b\x99\x71\xaf\xb3\x9c\xd1\x9c\x8b\x28\x1c\x15\x83\x06\xdf\x57\x21\xcd\xa2\xb4\xcc\xbf\x2a\xb9\x1a\xe5\xeb\xd8\xb2\x57\xd9\x9f\xb0\x09\x7b\xd7\xe5\xa9\xa1\x61\x95\xdc\xef\x55\x5b\xe6\xf5\x41\x4f\x0b\x7b\x1f\xfe\x0b\x05\xe5\x41\x5f\x15\x4f\xca\xe4\xc6\xb9\x97\x9f\xc4\x17\xac\x04\x72\x8f\xec\xfc\x1e\x3d\xec\xce\xd5\x2a\x2d\x6b\x38\xb9\x35\x97\x75\x1d\xad\x6a\xe5\x71\x0b\x09\x84\xcc\x13\x4b\xdf\x83\xab\xec\xa4\xce\x7c\x04\xd7\x60\x64\x91\x0f\xee\xf0\x75\x7b\xc3\x5e\x9b\x64\xac\x0e\xb0\x95\xf6\x8b\xd7\x5f\x24\x9c\xd8\x41\xc5\xb6\x4d\x58\x17\xea\x51\xa3\xeb\xb1\xbf\xa8\x57\x5c\x53\x5a\x6e\x47\x11\x30\x9c\x62\xd2\xba\x55\x5a\x8d\xa4\x92\xce\x76\xbc\xcd\x6f\xeb\xf0\x7f\x1f\xd9\xe5\x47\x84\x96\x15\x11\x72\x63\xc3\xe0\xfe\x13\xfb\xe9\xab\xa9\x2b\xe2\x68\x99\x12\xcf\x4d\xdb\x56\x9b\xed\x71\xf6\x8b\xce\x37\x56\xb5\x49\x8e\xc8\x78\xb5\xf8\xb4\x83\x36\xa4\xb2\x4f\xee\x66\x31\xf5\xc8\xc0\x99\x49\x5c\xda\x26\xfa\x82\xd0\x37\x00\x0a\xce\x5f\x22\x5b\xf8\xe0\x77\xe1\xd1\xe1\x6e\x2c\x24\x6d\xea\x2c\x84\xfd\x8a\xb6\x23\x8e\x97\xed\xef\x16\xcb\xf8\x62\xe9\x74\xb5\xfc\xee\xf3\x2d\xc7\xf6\xf3\x65\x1d\xdf\xf0\xcb\x59\xd2\x8c\x09\xfc\x74\xa5\x36\x34\xed\xe3\xd9\x6c\xcf\x4f\x72\x34\x74\xb6\xb4\x00\xb5\x33\x48\x76\x3e\xc1\x54\xf2\xda\x5a\x20\x06\xf0\x2b\xe3\xa3\x22\xca\xae\x15\x62\x56\x47\xab\xd3\xad\xc1\x73\xea\xc0\x7e\x2f\x99\x2a\x27\x70\x8c\xf8\xf3\x37\x5d\x44\x80\x88\xc3\x67\xbe\x0c\x43\x0a\xdc\x6e\x71\xac\xd5\xbe\x8f\xfb\xcf\xc5\x7a\x6f\xbe\xff\xd2\x9b\xc7\x27\xf4\xdc\x7c\xaf\xc1\xc3\xf7\x31\xaf\x9d\x38\x8b\xfa\xed\x09\x51\xe6\x82\xdc\x32\x1d\xb5\xa6\xbc\x47\x9e\xcf\xba\xc5\x62\x0d\xe2\x5a\x33\xb7\x60\xa2\xb9\x37\x68\xa3\x77\x24\xdc\x8a\x10\x87\x54\x42\x98\xca\xe4\x78\x7f\xdf\xfd\xe5\xf5\xad\x2a\xb0\x9b\xb4\xcc\xfc\xf1\x56\x6d\xa8\x51\x1b\x6e\x9e\x79\x3e\x7e\xd6\x41\x9a\xc2\x5a\x11\x4f\x44\xad\xf2\x94\x86\x5f\xa4\x2b\x8c\xf7\x5a\x2f\x40\x34\x99\x2a\x6e\x28\xa8\xe8\x81\x76\x04\x27\xb3\xab\xef\x58\x2c\x83\x34\x38\x3a\x52\x6d\x2f\x57\x2e\xa9\x2d\x8b\x7c\x18\xbe\x31\x59\xee\x9a\xe8\xd2\xd3\x07\xa2\xb2\xa3\x49\x15\xcd\x7c\xf8\xfc\x61\x93\xcb\x0b\x02\xfa\x0d\x9e\x25\x57\x64\x67\x5b\x3b\x55\x3b\xd6\x2e\x9e\x3f\xf0\x1b\x6a\x8e\xc1\x7a\x51\x6f\x87\xfd\xc8\x8f\xc7\x3d\xf7\x24\x33\x9f\xb5\xc5\x41\xae\x59\x58\x8a\x03\x81\x7e\xa5\xf6\xb5\xb9\xe8\x25\xc2\xdb\x87\x33\xaf\xdc\xb4\xac\x8d\x8d\x4e\x5e\x7f\x4b\x98\xa4\x54\x7e\x62\x94\xdf\xab\x58\x3f\xf0\x25\x7b\x38\x94\xe3\x9b\x56\xb4\x58\x8c\x6d\x88\x21\x53\xd8\xbd\xee\x59\x50\x33\x8d\x55\x1e\x9c\x3b\x11\x34\xc4\x36\xd7\x93\xc5\x6b\x4d\xdf\x6f\x32\xaa\x91\xc7\x40\x61\xd8\x1a\xd5\xcf\x8a\x19\x06\xbb\x17\xf7\x05\xa1\xc8\x3c\x2f\xa3\x46\x52\xd0\x67\xd3\xc7\x0f\x54\x2c\x81\x02\xab\xac\x79\x96\x0f\x4f\x29\x1c\xd7\x38\x61\xfd\xa6\xf8\x74\x61\x9c\x9c\x5f\x52\x16\x8d\xcd\xa4\xfa\x99\x22\x7d\xd3\x2e\x9b\x90\xf7\xcb\x76\x6d\xf6\xb3\x71\x06\x67\xf5\x9c\xf1\xe4\xff\x52\xe0\x7a\xb0\xc2\xfc\x39\x60\xfa\xdd\xf4\x16\x06\x33\x31\xe7\xd5\xbf\xaa\x08\x5f\x03\x69\x5e\xcd\x77\x91\x41\x32\xa6\x5c\x34\x91\x18\xb1\x3d\xd0\xf1\xd2\xba\xcc\xb8\x31\xc2\xc5\xed\x19\x3c\x9f\x67\x8a\x30\x5c\x94\x42\x1a\xcd\x87\x64\x26\x93\x60\x34\x88\x1a\xd8\xc6\x31\x40\x48\x02\x26\xc1\x9c\x97\x69\x11\x0c\x0c\xeb\xad\xf2\xde\xa6\xc6\x0c\xf3\x31\x4c\xb3\xa4\xaf\xfe\x7a\x91\x24\xb0\xd4\x0f\x19\x01\xa9\x00\xd6\xe3\xc8\xff\x5e\xfe\x89\xcf\x91\x19\x9d\x1d\x41\x8a\x2a\xe8\x23\x4f\xdf\x09\x00\x72\xe3\xc4\xed\x1c\xa3\x39\xc5\x6f\xd6\x61\x93\x6a\x5f\xdb\x1a\x16\xbd\xdf\x7e\x8b\xec\xec\xa7\xc8\xa4\xb7\xfa\x74\xaa\x92\xc8\xc9\x68\xe0\x1d\x29\x3a\x90\x9a\x57\x9e\x04\x52\x71\xa0\x96\x50\xe4\xe5\x75\xb4\xb1\x5e\x26\xd1\xfd\xb2\x56\x29\x45\x3e\xdf\xf9\x19\xe2\x44\x08\x57\x08\x87\xc2\x25\xad\x5a\xaf\xc2\xad\x1f\x1b\x03\xff\x15\x4b\xd1\xdc\x62\xfd\x60\xff\x2f\x01\x48\x96\x37\xb9\x7b\x53\xd2\xa6\xf5\xd4\x20\xe4\xa0\x17\xd2\x71\x2b\x66\xba\xec\x3b\x41\x02\x69\xd8\x6c\xe1\x35\xed\x01\x2e\x5d\x74\x53\xff\xbb\xa9\xff\x03\xe5\x88\x88\x15\x47\x25\x5b\x24\x90\x6d\x1b\x37\x1e\xe4\x73\xbd\x5b\x83\xcf\xb7\x16\x3a\x82\x81\x7b\x3e\x66\x43\xa1\x1a\xb8\x83\xb3\x76\x29\xac\xdd\xae\xbe\x4d\x63\x89\xf9\x90\x06\x44\xdb\xdd\x9c\x78\x31\xfe\xe5\x3d\x62\x11\xc8\x5a\xb5\x22\x42\x8f\xfc\x58\x41\x39\x1c\x28\xea\x66\x74\x30\x24\x1c\x32\xbf\x55\x59\x89\x73\x18\xc1\xae\x30\xbc\x7d\xb8\xe9\xb6\x2e\x6a\x6b\xd1\xd4\x9f\x8f\xcb\x1d\xb0\x14\x3d\x3b\x1d\x9f\x6a\x81\x53\xa3\xbd\x54\x7e\x47\x3f\x23\xa6\xef\x29\xe0\x30\x7f\xe8\xb7\x71\xb6\xee\x30\xa7\xc8\x5b\xb7\x7b\xac\x84\x2b\xfa\x02\xc9\xbe\x84\x61\x88\xff\x0a\x68\xf5\x12\xfa\xd5\xb7\x88\x7d\xbb\xb6\x9b\xe3\x66\xf8\x23\x20\x5d\xcb\xcb\x51\x14\x2a\x5b\x14\x2a\x57\x0e\x4b\x04\xe9\x0b\x61\x90\xe6\xbf\x5a\xe0\x27\xb3\xfa\xed\x56\xeb\x63\x2b\x7d\x37\xfb\x4d\x51\xa2\x70\x61\xc7\x5f\x6e\x4d\xd6\xcf\x9b\x53\xaa\x0a\xa2\x4e\x2e\x1a\x04\x81\x83\xf2\xc1\xa4\xcd\xe9\x8e\x3e\xf8\xba\x35\xf3\xbd\x1a\xd2\x7f\x95\x65\xd4\xc8\xe7\x8a\x67\x64\xd7\xb0\x48\x96\x84\x64\x4e\xca\x49\x44\xa1\xa1\x07\x5a\xb4\x3f\x07\x19\x24\x47\xe5\xa8\xbb\x93\x67\x1b\xae\x56\x0d\xbd\x77\x58\xc3\x3d\x5c\xa5\x2d\x7d\x13\xfb\xbe\x1a\xec\x2d\x09\xf9\xb6\x4f\x7c\x62\xb3\xd2\x1c\xb9\xf1\x58\xa6\x36\xf6\x05\xbe\x80\x07\xb7\x31\xa4\x5b\x31\xc8\x33\x7a\xd4\xef\x5d\x7f\xcc\x99\xd2\x34\x8b\x7d\x63\x70\x06\x25\x17\x15\x33\x2d\x74\xd6\x34\xff\x0c\x09\xff\x72\x5b\xb6\x69\xd2\x72\xcb\x1a\x53\x30\xb0\x95\xad\xcd\xa3\x01\xcd\x9e\x7f\x4d\x92\x5b\x69\x14\x49\x2e\x51\xe5\xb9\x80\x3b\x51\x86\xb0\x9e\x00\x1c\xe8\x03\x70\x0e\xff\x0a\x79\xfb\xc0\x48\x40\x1c\xef\xa5\x58\xd5\xa2\xf3\x01\xb4\x06\xc9\xe3\xc4\x27\x47\x39\xbd\x0b\xa7\xf8\xb9\x0a\xd8\xee\x46\x24\x0d\x05\x96\x9f\x1d\xc0\x5c\x45\xf3\xa1\xc1\xcf\x15\x57\x3d\x2e\x6e\x04\x8f\xfa\xd1\x50\xd5\x80\xda\x13\xfe\x1d\x0c\x32\x30\xb0\x3f\xfc\x94\x07\x39\x06\x11\x11\x37\x0c\x2f\xcf\xed\x2b\x9e\xd8\xa2\x01\xb1\x9d\x0a\xed\x75\xe9\x3d\x68\xde\x57\x53\x49\xba\x5d\x80\x5e\x2a\x2e\xce\x7a\xc5\xdd\x7a\x6a\xf6\x8a\x2c\xaa\x8e\x3a\x27\x85\xd8\x23\x5a\x4a\x07\x04\xb7\x7c\x64\xca\xa9\x67\x2c\x2d\x3f\xc6\xd3\xf2\x89\xd8\xca\xdc\xc3\x4a\x1c\xa5\xf7\x47\x38\xd2\x37\xfd\xa5\xfe\x21\x09\x42\x15\x42\x21\xd9\x64\xcb\x23\xb0\x97\x2d\x0a\x31\xcc\xdc\xbd\x15\x0c\xc8\xe9\x72\xb7\x66\x3a\x13\xdc\xc1\x41\x8e\xf9\x2f\xaa\x30\x1a\xe9\xd7\xff\x63\x58\x8c\x39\x21\x8b\x7f\xc4\x43\x7b\x6d\x56\xc6\xe8\x22\x43\xb4\xe0\xe7\xac\x08\xea\x6d\xbe\xb6\xd2\xbc\xb4\xb1\x47\x4f\xf0\x7e\x1e\x4d\x44\x9f\x44\xf0\x21\xef\x0f\x16\x37\x85\x1e\x26\x4e\x81\x80\x5f\x57\xe1\x94\x65\x6f\x11\x10\xdb\x27\xac\xa4\x1c\xfa\x70\x2a\xc6\x86\xee\x8d\xfc\x00\x2b\xb7\xaa\x14\x2f\x56\xee\x84\x73\x2f\xd5\x0d\xd4\xf5\x76\x61\xd1\x0d\x0c\x18\x90\xa2\xdf\x0b\x78\xc3\x97\x90\xca\x92\xec\xf1\x64\xb4\x24\x7c\xc8\xe5\xbe\x76\x11\x6a\xb0\xea\xea\x16\x51\x28\xf5\xfc\xd4\x2c\xd4\xc8\xdb\x0f\x62\x7c\x24\xf8\xcc\x29\xc8\x93\x78\x0f\x1f\x60\x48\xab\x0d\x81\x78\x9f\xa6\xe3\xb2\x0c\xb4\xb2\x4a\x06\x94\x42\x42\x56\xa2\x73\x56\x71\x17\x11\x59\x2f\xfb\xbd\x9c\x03\xcb\x93\x02\x6c\x14\x41\xeb\xc3\x1d\xde\x7d\x43\xa5\x66\xaa\x8c\x05\xbe\x00\x9b\x7b\x5c\xe5\x68\xab\x06\x14\x7f\xf4\x1e\x3b\x8a\xbc\x7f\x8f\xdd\x25\x26\xb6\xb0\xa3\x9e\x95\x93\x2c\xcd\x40\xd1\xde\x74\xfc\xf7\x22\x40\xb8\xdb\x5e\xc0\xc7\x41\xe8\xf5\x45\xa3\x0c\x1c\x63\x50\xa1\x3a\xbb\x62\xf8\xb9\x1f\x63\xa1\x0b\x6b\xfc\xce\x67\x1d\x74\x7a\x05\x46\xe2\x67\x4e\xd2\x88\xef\x37\xfe\x4a\x11\xb3\xf0\xbd\x55\x0d\xbe\x9b\xfe\xc3\xb9\x4d\x67\x9c\x0f\x11\xc4\x17\x21\x4b\xf6\xc3\x5d\x15\xe6\xf7\xc2\xbd\xee\xba\xdc\x05\x8b\xe2\x58\x20\xc0\x5c\xe2\x82\x5d\x1a\x8b\xdc\xf1\x0f\x6f\x3a\xec\xee\x20\xea\x71\x51\x87\x73\xaa\x15\x38\x42\x95\x0f\x76\x34\x09\xd0\xa2\x52\x85\xcc\xbc\x92\x62\x88\x58\x60\x4d\x80\x7d\xeb\x70\x23\xe9\x5e\x83\x60\x4d\x54\x56\x98\xf6\x08\x64\xde\xe2\xc2\x4d\xbe\x0d\xb2\xf3\xff\x2d\x7c\x23\xcf\x9c\x54\xec\x52\x2f\x07\x03\x63\xc6\x64\xc7\xc7\xbc\x39\x6d\xe1\x2d\xd4\x86\x9a\x2e\x5d\xce\x82\x8d\xdf\x01\x24\xcb\x16\xa4\x53\x13\x1c\x68\xcf\xf8\xdb\x2b\xc7\x5b\x36\x30\x76\x35\x3f\x5c\xcf\xcc\xc9\x19\xd8\x97\xa4\xb1\xe1\x30\x6f\x38\xf1\x27\xfc\xbf\x97\xaa\x8b\x34\x54\x95\xde\x47\x0f\xcd\x81\xa8\xbf\xb5\x15\xd7\xa8\x4b\xec\x8e\x6e\x04\x7a\xf8\x3c\x96\x2b\xb6\xd7\xd2\xa6\x63\xea\xe9\xbb\x5b\x9b\x69\xb6\xfe\x35\x29\x64\xe4\xc6\x50\x89\x99\x75\x50\x5c\xaa\x62\x21\x1e\x8d\x47\x22\x6f\xb6\xb5\x7d\x71\x45\xbb\xe9\x6a\x96\x86\x63\xa0\x04\x14\x8d\x2f\xef\xc0\xe4\x5d\xf3\xe5\x1a\xc1\x77\xa8\xca\xde\xda\x14\xad\x8d\x71\x3a\x87\x73\xa7\x84\xca\xb9\x43\x8c\x9e\xc9\x25\x12\xf3\xf5\x8f\x70\xfe\x74\xb3\x76\x5f\xa4\xf0\xac\x80\x8b\x99\xae\xbe\x7a\xcf\xcc\x60\x03\x3f\x91\x7d\xaf\x06\x64\xf0\x12\x12\x47\x3c\x38\xdd\x27\x70\x44\x0e\x54\xf0\xea\x49\x4f\xe2\xc8\x1c\xdb\xaf\x23\x7b\x81\xbb\x6b\x98\x82\x9c\x37\x46\xb5\xfd\x93\x9a\x6c\xc5\x88\x04\x0c\xd0\x8c\x75\xec\xa8\xed\xfb\xbf\xff\x0a\x78\x4f\x2d\x25\xb9\xb7\x8a\x92\x3a\x68\x90\xa9\x08\xe8\xac\xa0\x08\x56\x7d\x72\x88\x09\x5b\xbf\x51\xeb\x03\xbd\x67\x11\xfb\xd4\xae\x48\x32\x07\x96\xe6\x6c\x0b\x63\x6e\x31\xf8\xdc\xfe\xd9\xaf\xe2\xc0\x2b\xe7\x72\xf0\x52\xf3\x4c\x25\xd2\x17\xd4\xc1\xfc\xd1\xaf\xc9\xce\x43\x31\x20\x6d\x67\x55\x88\x43\x73\x0a\x4c\xa2\xf8\xda\x5f\x1f\x23\xe2\x3d\x90\xe8\xdc\x54\x8a\x87\x22\xce\x80\xef\x04\xbc\x93\x35\x25\xe1\x56\xf4\x94\xf6\xea\x59\x82\x81\xfb\x94\x92\xfd\x9f\xe1\x31\xae\x78\x3d\x13\x4c\x4a\x24\x62\xcb\xd2\x81\x0e\x08\x36\xe3\x5d\x40\xc8\x62\x28\xe7\x7a\x47\x30\xb2\x4f\x53\x7d\x09\x3b\x02\x96\x22\x83\xb5\xe5\x61\x5d\xb6\x3d\x5b\x0f\x4b\x72\xcf\xa2\x43\xa3\xe7\xec\xaf\x87\x2a\x5a\x2d\xaa\x24\xe8\x7d\xe4\x8a\xf5\xe9\x7d\xc9\xfe\x23\x29\xe7\xc2\xfd\x27\x49\x9e\x58\x6e\xc6\x9f\x3a\xa0\xad\xa0\x98\xe6\x27\xc0\xb0\x6e\xec\x18\x4a\xea\xba\x69\x1b\xb1\x4a\x07\xb9\x3c\xed\x14\x4f\x1a\x4d\xbe\x43\xc0\x85\x4b\x54\x43\x44\x0c\x55\x04\x13\xb9\xcc\xa5\x0b\x31\xec\x41\xec\xd2\x4e\x6b\x3b\xe2\x1d\x9f\xa1\xa7\x8d\x6d\x08\x7a\x0b\xae\x8f\xd7\x4c\xd7\x3b\xb2\x7b\x55\x98\xd3\x26\xc4\x17\x9b\x72\xe8\x81\x6a\x86\xc8\xc6\x37\xa1\x8e\xcd\x24\x7c\x41\x55\x4a\x9d\xe9\x4c\xba\x6f\xf6\xbd\xcd\xd5\x4f\xf7\x81\x9d\xa3\x3d\x9d\x78\x1d\xb0\x53\xc5\x77\xd9\x21\xf6\xc7\xb7\x60\xf7\xf7\x6c\xb7\xd7\xb6\xd1\xe5\x6d\xcf\xd3\xb8\x66\x0a\xbf\x28\x4f\xe1\x63\x19\x0e\xa2\x79\x8e\xb0\x1b\xb5\x49\xf5\x3f\x4c\x1c\xfd\x38\x84\x23\x04\xef\xc7\x7a\x34\xf6\x32\xef\xbe\x83\x36\xb1\xf0\x92\x3c\x64\x81\xdd\x9c\x6a\xfa\x59\xaf\x3d\x49\x69\x4a\x2e\x95\xc8\x06\x3d\x8e\x46\x92\x42\x8b\x97\x9b\x9b\xfd\x22\xe2\x28\xec\x2e\x54\xe7\x37\xd3\x48\x34\x87\xac\x65\x3a\x3f\x03\x1c\x4e\x85\x18\x27\x1c\xe1\xc9\xc8\xc0\x79\xd2\xa5\xfd\xc2\x6d\x8b\x9b\xed\x6b\x45\x50\x61\xe0\x27\x82\x96\xea\x29\xf1\xc6\x84\xd1\xac\x22\xba\x30\xa4\x54\xc7\x6b\xc7\x8a\x4e\x95\xa2\x3d\x0d\x18\x98\x9f\x1d\x20\xb7\xd0\x33\xe1\x54\x4d\x83\x3e\x9d\xa5\x3c\xad\x51\xd1\xb8\xfa\xc7\x0e\x1b\x06\x2a\x03\xce\x9b\x6a\x41\x2b\xeb\x27\x7f\xb5\x78\x99\x2b\x09\xb1\x77\x80\xdb\xf9\x16\x56\x57\x46\x27\x0a\xd5\x41\x34\xc1\x77\xe8\x7b\xee\x16\x44\x11\xd6\x7e\x38\x72\xc8\x47\xd2\x6b\xd9\x05\x4f\xba\x93\x9d\x14\x8c\x72\x26\x1f\xf3\xd4\x31\xfd\x42\xc6\xfe\x99\xa5\x47\x67\x9d\x0e\x1d\xed\xee\xd3\xa0\x09\x7f\x1a\xe6\x00\x63\xbe\xde\x8c\x12\x63\xa5\xb2\xb8\x1e\xff\x68\x8d\x83\xf4\xec\xdd\x31\x1d\x75\xfc\xc9\xc4\x0b\xe1\x74\x54\xef\xb8\x91\x2a\x98\x34\x0c\xca\x9a\x06\xdc\xd9\xe9\xc5\xbe\x4e\xef\x08\x2b\x79\x87\x98\xf9\xaa\x7e\x3f\xf8\xaa\xe3\xf7\xe6\x18\x28\xdb\x2f\x79\xe5\x16\xed\x90\x9c\xc7\x79\xc6\xdf\x70\x4a\xc5\x9a\xc3\x93\x98\xe9\x7b\x4a\xd2\x3a\xa1\x1e\xa4\xd1\xdd\xfd\x9b\xc4\x40\xe9\xb3\x45\x99\x60\xbd\x1c\xe1\x13\x18\xf9\x48\x10\xb1\x43\xc4\x2d\xdc\x96\xce\xb2\x41\x24\xe9\x04\xd4\xec\x59\x25\xd7\xb5\x91\x90\x5c\xff\xa1\x8d\x57\x57\x2b\xf0\x6e\x3a\x7f\xba\x94\x07\xdb\x01\x2e\x64\x45\x81\xb0\xdb\x68\x04\xe0\xf5\x33\x8a\x40\x62\xbd\x19\x8f\x0a\x59\x1e\x46\x00\xe3\x22\xce\x32\x82\x49\xdd\xd5\xd2\xaa\x75\x15\xf6\x5e\x56\xfe\x55\xb9\xfc\x3a\xbf\xce\x27\x9c\x3e\x42\x60\x85\xdf\x6a\x23\x08\x20\x64\x84\x10\x16\x5a\xb8\x4d\xc8\x05\x5e\xa4\x0e\xc8\x0c\x59\xb1\xe7\xc5\x79\x7e\x1d\x48\xe9\xa4\x41\x82\xb7\xcc\xb9\xe8\x26\x1a\x22\x26\x80\x7e\x99\x48\x3e\xe2\xdd\x87\x13\x8a\x6e\x7c\x8d\x93\x88\xbb\x41\xb3\x88\xe6\x77\x6a\xdb\x19\x26\x48\x3d\xcb\x2b\x54\xbf\x2a\xde\x46\xee\xea\x79\x40\xf5\xaa\x31\x56\xba\x56\x49\x14\xdc\x6b\x12\xa6\x43\x4c\xbd\xc0\xd4\x75\x69\x7c\x94\xdf\x11\x66\x2d\x08\xa4\xc1\x5a\x47\x7f\x92\x5b\xa7\x35\xe4\x3f\x96\xc4\x76\x6b\xeb\xa2\xeb\x01\x18\x8a\x50\xb5\x4b\x68\xde\xd7\xf1\x8c\x49\x08\xd4\x5b\x7e\xd3\x16\xbb\xbd\xbd\x4f\x27\x03\x93\xae\xb2\xec\x2f\x50\xa3\x8b\x5d\x0c\x30\xab\x53\x71\x58\x9b\x40\x23\x74\x9c\x6c\x4d\x22\x2f\xbf\x13\x8f\xa9\xcb\x2f\x9d\x84\xd7\xa4\x19\x4b\x96\x69\x83\xd5\x90\x2c\x25\xcf\x5f\xa0\xe5\x42\xa2\x7e\xf8\x60\xe8\x18\x85\xa3\x25\x6d\xb1\x86\x39\x60\xb7\x4f\x4b\xbc\xb1\xc3\xd2\x73\x5e\xc9\xca\x9a\x6e\xd1\xb2\x4a\x98\x37\x67\x45\x4f\xbc\xaa\x10\x8f\x57\xf8\xd2\x7a\x6a\x56\x11\xe8\x15\x5c\xb6\xf3\xa6\x95\xef\x99\x2f\xb5\x36\xbd\xc8\x2b\xe8\xc6\x27\x3e\x1e\xf9\x47\x48\x14\xf6\xb5\xd2\xac\xf0\x50\x92\x5c\x1b\x20\x31\x77\xdc\xc7\x26\xe9\x37\xa4\xdb\xeb\x6e\xc7\x35\x71\x5a\x9f\x7e\x3c\x5c\x79\x9c\x74\x5f\x05\x5e\x80\x9b\xe8\x33\x70\x6a\x31\x82\xfa\x49\xf2\x5f\x95\x55\x6e\x0d\xca\xfb\xd2\x4c\x29\x86\xbb\x7f\xc8\xe7\x85\xf9\xa8\x89\x74\xc1\x35\x3a\xef\x3e\x1c\xa1\x0f\x36\x24\x73\x55\x84\x89\x2c\x20\xff\xd2\x2f\xaf\x6b\x8c\xc9\x04\xfd\xcc\xa6\x50\xbe\x4f\x39\x45\x7e\x37\xf5\xc7\x23\x1b\x42\x90\xb6\x94\xa2\x6a\x77\x1a\x5b\x96\xf1\x97\x39\x39\xfe\xc0\xa9\x71\x89\x59\xf7\x13\xfb\xcc\x49\x46\xb6\x75\xfe\xe2\xc7\xc2\xcf\x8d\x96\xe0\xf0\xc0\xf1\xbb\x67\x39\xb5\xe5\xe6\x85\x42\xc0\x1c\xa5\x51\x16\x7d\x65\x38\xea\x2d\x04\x2b\xec\xdb\xca\x57\x86\x06\xf6\x4f\x1a\x0f\x12\x79\x67\xe0\x0c\xdb\x7d\xb4\x44\xc1\x45\x54\x51\x78\x87\x39\x54\x7d\x2b\x1d\x03\x6c\x6e\xfe\x9d\xe4\x75\xa7\x70\x3e\x19\x58\xf5\x38\x38\xd5\x71\xff\xee\x8e\x08\xf7\xc7\x5e\xab\xf2\x10\x52\xc1\x9e\xdc\x9b\xba\x28\x22\xa9\xab\xcd\xc8\x66\xfb\x51\x14\x73\x1a\x24\x87\xbd\x75\x5b\xd0\x69\xd8\x9b\xab\xef\xed\x6f\x24\xa8\x89\xba\x3b\x0e\xdb\x80\xe1\x55\xce\x3b\xa5\xf0\x78\xec\x35\x35\xfb\xe4\xdd\x4b\xfa\x8f\xcb\x1f\xde\x6d\x03\x84\xa7\xfa\xcf\xdd\x18\x80\xa8\x8a\x4b\xec\x28\x0f\x72\x20\xfc\xfe\xf4\x44\x86\x07\x01\x30\x21\x60\xe9\x08\x73\xb2\xab\x04\x52\x75\xe9\x8e\xd8\xc1\xe7\x0e\xc1\xb4\x7d\x10\x3b\x15\x52\x66\x97\x36\xa8\xe4\xf7\x54\x2f\xd4\xad\x23\x73\x15\x97\x00\xaf\xf2\x7c\x8a\x10\x71\x0f\x81\x0e\x14\x9a\xf0\x82\x21\xe1\x0b\xbc\x5a\x78\x11\x30\xea\x80\x22\xfe\xf6\x89\xe1\x7e\xbb\xb8\x6c\x5f\x1a\x51\x92\xd6\xe9\x76\x83\x89\xd8\xc6\xf8\xc0\xb5\x89\x5b\xad\xd6\xfa\x91\xd0\x72\x52\x61\xb8\x35\xe1\x0b\x62\x90\x78\xa3\x7d\xab\x8f\x36\x31\x13\x09\xef\xef\x2a\x27\x12\xb0\x25\xd8\x73\xb9\xa8\xcd\x21\x2b\xf0\xdf\xfd\x9e\xb2\x6b\x98\x37\x19\x52\x77\x83\x44\x51\xb7\x23\x91\xf3\x23\x98\xf1\x2f\xc2\xfa\xfe\xea\xef\xe4\xf3\x3b\x90\x6c\xdd\x63\x8c\xd1\xbb\xdf\x86\x25\xe8\xde\xd6\x83\x69\xde\x2e\xa7\xce\x49\x54\x77\x18\x04\x47\x49\x04\x5f\xe0\x16\x73\xdc\x35\xbb\xf1\xbb\x44\x6d\xa2\xb9\x4a\x79\xd0\x81\x56\xb7\x2a\xee\x50\xbf\x70\x9f\x07\x0f\xcf\x67\x8d\x2d\xd2\xca\xcb\xfe\xe6\xbc\xd1\xeb\x71\x67\x59\xca\x91\x84\x61\xe1\x6c\x16\xb3\x60\x96\x01\xe9\x48\x0f\x5a\x08\x1c\xe4\x1a\x65\xd8\x92\xd1\x75\x82\xaa\xf2\x87\x33\x39\x48\xb9\x3c\x40\x17\x21\x8c\xcf\x90\xd4\x60\x11\x85\xf3\x5d\xdf\xa6\xf9\x04\xd0\xb4\xb4\x3f\x65\x8b\xbb\xae\x59\x16\xa7\x6f\xcb\x54\x14\x43\x00\xe7\x18\x07\x8a\x2e\x4f\xea\x60\x5d\xfe\x10\xec\x76\xb2\x4c\x42\x30\xf6\xe6\x77\x4c\x97\x36\x99\x16\xc9\x7e\x03\x4d\x2a\x91\x34\x76\xa3\xf0\x49\xd6\x63\x14\x78\x08\x83\x38\x1c\x38\xff\x64\xf6\x62\x6f\x8c\xf6\x38\x7f\x43\xc1\x19\x2d\x9d\x67\x80\x39\x69\xb8\x2e\x73\x98\x5b\x43\xae\xa0\x3d\xc7\x7e\xd5\xa2\x44\x7d\xf2\x97\xce\x4f\x88\x94\xdf\x0d\xed\x3e\xaf\xdb\x76\xf0\x97\xf2\xf1\xec\x36\x9d\x49\x4f\x29\x41\x10\x18\x23\x2a\x68\x14\xb4\x6b\x77\x5c\x0b\x7a\xb5\x9a\x52\xb3\xfc\x66\x9b\x2c\x77\xc1\x12\x36\x74\x6b\x98\x77\xd8\xed\x06\xec\x5b\xe3\x97\xfd\x3e\xca\xd3\x07\x6d\x7b\xb3\x81\xb1\xed\xbd\x51\x91\x77\x7b\xc6\x4a\x7e\xdb\x53\x4b\x96\xa4\x3f\x51\x3d\x23\x3f\x3a\xc4\xb4\xdb\x67\x4c\xdc\x13\xb7\xfc\xee\x65\x40\x64\x77\x2a\x33\x63\x63\x20\x93\xe1\x36\xc8\x46\xce\xeb\x0f\xf1\x93\xc5\x82\x5a\xfb\xf5\x27\xfa\x48\xc1\xd7\xe3\x63\x58\xfc\x8e\xe2\x74\x2f\xb9\x45\x7d\xda\x55\xc7\x56\xed\xe0\x86\xe4\x86\x0a\xfc\xa7\x5a\x95\x43\xf1\x97\xd9\x51\xd9\xbd\x08\x16\x0e\x4b\x51\xa2\x7f\x2e\x45\xe5\x4d\x78\x36\x8f\xe0\x30\x1d\x95\x97\x3d\x44\xef\x07\x41\x85\xf1\x10\xd4\x89\x05\x6f\xff\x71\x49\x43\x54\x50\xf6\x1e\xd5\x67\x5a\x78\xe3\xb5\xb1\x8a\xbd\xd5\x9d\x5f\x65\x79\xf8\xd7\x91\x43\x02\x61\x7c\xea\x66\x39\xf8\x4e\xac\x05\x4f\xc9\xec\xad\x76\xe9\x25\x16\xb1\x3b\x53\x54\xd2\x2b\x2b\x30\xc9\x2e\x52\x87\x11\xfa\xda\xe4\xbe\xfd\x72\x33\x1f\x3b\x9d\xfa\xc6\xb4\xdf\xe1\xfc\xb5\x09\x05\xea\x13\x0c\x57\x65\xf6\x71\xea\x28\x3b\x82\x19\xdb\xd5\xe3\x4f\xca\xa6\xf0\x50\xdc\xf8\xe4\xe4\x74\xca\xfb\xa6\xe7\x2f\xfa\x26\x77\x4a\xd9\x65\xd3\x16\x3e\xa7\x91\x1c\x5d\x42\x71\xee\x37\x06\x1b\xb1\x49\x26\x78\x57\x8e\x3c\x10\x78\x6f\xe8\x50\xf9\x88\x1c\xe7\x59\x07\x7c\xe4\xc9\xe4\xb2\x6b\x9e\x55\x35\x6e\x89\x2b\x0f\x0d\x4f\x94\x31\xa3\xed\xdc\xee\x82\xf1\xf0\x21\x7d\x9c\x59\x82\x57\xc1\x96\xa6\xcb\x50\x84\xc7\xc2\x03\x24\xd2\xf9\xa8\x70\x55\xcb\x7c\xd0\xec\xd6\x9a\x03\xe5\x31\xef\x20\xac\x8a\x89\x7a\x2f\xa5\x72\xc5\x40\xb2\x3d\x32\xb5\x41\x4a\x55\xfb\xef\x36\xac\xb8\x48\xc8\x08\x4c\xda\x9a\x80\x90\x13\xa9\xaa\x34\xcb\x80\x56\x3b\x87\x5b\x55\xec\x32\xec\xd6\x38\xf5\xbc\xb7\x60\x6b\xff\x94\x20\xd0\x4a\xf1\xb4\xeb\xef\xae\xd3\x08\x14\x58\x96\x68\xfb\x87\x8e\xb6\x97\x4c\x20\x31\x91\xba\xc8\x05\x38\xe0\x42\xa5\x62\x72\xd5\x6c\xf3\xd6\xa6\x61\xb7\x10\x3b\x3a\x85\x1b\xce\x59\xd8\x2d\xd2\x1c\x48\x05\xb4\x67\xea\x0e\x38\x53\xd6\x50\x7a\x8a\x50\x84\x29\x8d\x3c\xbb\x06\x3d\x89\x91\xee\x6d\xc8\x3a\x72\xa7\x86\x48\x71\x3e\x5b\x64\xde\xa9\xc1\xa6\xef\x6c\x3c\xcc\x52\x0b\x2b\x7e\x3a\xd0\xf4\x2c\x9c\x27\x3d\x19\xdf\xcb\xdb\x09\xf3\xd4\x80\xd8\x6d\xa3\xdc\x28\x57\xc1\xd6\x27\x02\xc0\x7a\x44\xad\xb9\x84\x87\x05\x68\x11\x9c\x09\x15\x69\x59\x40\xce\xa4\x5c\x20\x0b\x8f\x94\x7d\xf7\xd1\xca\xa9\xbe\x2a\xf5\xbf\xce\x41\x92\x25\x6b\x76\x89\xb4\x0f\x4f\x63\xe2\xf9\x37\x25\x19\x56\x61\xa5\x00\x18\xd1\xd5\x7c\x75\xec\x25\xac\x33\xfc\xd6\x0b\x6b\x40\x0a\xd9\x7f\xce\x19\xf8\x88\x8a\xc2\x23\x3a\xa9\xae\x46\x4c\x4e\x07\x97\x78\x2a\x0a\x69\x16\x82\x0c\x45\x39\xd7\x76\xb0\xe4\xe5\x02\x3f\xf7\xe3\xbe\x59\x10\xbf\x07\x60\xbf\xaa\xd4\x02\x74\x8f\x69\x91\x96\x4c\xa5\x7c\xc7\xfd\x8e\x72\x52\x70\x12\x18\x07\xb4\x95\x78\x15\x1e\x61\x6e\x4b\xed\x37\xca\xbd\xcd\x1b\xed\xfb\x2a\xd1\xaf\x2b\xa9\xde\xba\x30\x2b\x73\xc6\x8c\x1d\x67\xbd\xb4\xad\x8b\xfc\x73\x4f\xf7\x9d\x52\x30\xc0\xba\x87\x91\xc7\xfd\x69\x64\x5b\x44\xaa\x86\x37\xcc\x27\xa8\x09\xdf\xa8\x2a\xd1\x65\xa6\x17\x29\x09\x22\xb8\xe5\x2d\x34\xf8\x2e\x11\x79\x38\x95\x2d\x30\xa1\x43\x41\xbe\xbb\x84\x32\x7b\xdb\xb7\xf7\x2a\xa4\x65\x21\xdc\xbf\xff\x3c\x01\x77\x2b\x0e\xfd\x4b\xe0\x5d\xcf\x13\x07\x76\xe6\x1f\x3f\x68\x9c\xdd\xa0\x62\x10\x0e\x20\x74\x56\x2e\x79\x95\xfa\xca\x8e\x3d\x22\x85\x6b\xa3\x52\xc0\x51\x3b\x29\x55\xa5\xcf\xd4\x60\x64\x99\x63\xe3\xd8\x3b\xb5\xfd\xc1\x91\x21\x4b\xc1\x93\xae\xf3\x16\x2d\x7c\x8d\x3b\x1b\xc0\x26\xe7\x5d\x1e\x31\x44\x5f\x1f\x1f\xd2\x02\x6e\xd2\x18\x21\xbf\x23\x2b\x65\x69\xa2\x34\xb7\x98\xf4\x53\x12\x61\xec\x0f\x2a\x2e\x82\x03\xb7\x0b\x4b\x99\x33\x09\x45\x33\x55\xa0\xb3\x93\x5f\xd8\x55\xe6\xa7\x35\x7a\x3e\xf2\x9a\x3e\x67\x84\x9d\xdd\x67\x06\x50\xcc\xbb\xdf\x6a\x82\x00\x71\x06\x99\x54\xa0\x74\xd5\x00\x2d\x98\x77\xae\x0b\x92\x31\xfb\x92\xbe\x01\x84\xf2\x67\x3c\x8f\xea\x93\xde\xe7\x72\xc7\x5c\xef\x19\xac\xaf\xa7\x70\x9b\xc0\x8a\x20\xf9\xa5\x47\xa2\x95\xce\x32\xc9\x23\xc7\x7e\x80\xea\x86\x75\xa6\xbb\xa5\x52\xe0\x7b\xe6\x9f\x00\x78\xd4\xbd\x2d\x46\x4f\x2f\x8b\x66\xec\x9f\xf6\xb2\x8a\x9f\x6c\x87\xf7\x2d\x4f\x3a\x3b\x2b\x23\x0f\xc5\x27\x49\x9d\xdd\x00\x9a\x10\x2c\x6a\x59\xad\xc3\x3e\x97\x36\x63\x93\x2d\x4a\x07\xdd\x0d\x9d\x0b\xe6\x59\xca\xf1\x60\x3c\x7a\xf0\x3d\xcb\x4d\x8c\x5f\x56\x8a\x31\xac\x05\x1a\xc2\xf0\x54\x3d\x26\xe7\x6d\xbc\x41\x8f\x1c\x34\xa1\x26\x0d\x7d\xc7\x04\x11\x23\x5f\xea\x1f\x5e\xc1\xd8\x45\x51\x99\x5a\x4e\xad\x86\x75\xd5\xee\x3e\xc2\x9d\xaa\xd2\xe0\x20\x5f\x62\x54\x97\x1d\x67\xb7\x73\x15\xdd\x11\x2d\x8f\xe3\x4d\xb4\x13\x98\xc1\x0e\x57\x0c\xe5\xec\x88\x9c\x82\xfa\x06\xf7\x62\x21\xdc\xa0\x12\x78\x9d\x0a\x99\x4f\x58\x67\xc4\x93\x38\x93\xfc\x1c\xe1\x5a\xec\xdd\x20\xf2\x46\x39\x86\x3f\xe4\xbe\xf0\x33\xd5\x3f\xe8\x10\xab\x94\xf9\xa3\xa9\x9f\x8f\xb4\x33\x7f\x05\x93\x67\x19\xa8\xd8\x81\xfb\x24\x6d\xc4\xfe\x0c\xab\x33\xe9\xa4\x4d\xa0\x63\x53\x63\xb6\x95\xb8\xc3\xf5\x79\x14\xfa\x2c\x31\x3f\x93\x22\xa3\xf5\x7a\x5a\x21\xfc\x57\x5e\x62\xa2\x8e\x8b\xbe\xca\x0e\x59\xd9\x10\xad\xe9\xbf\xb8\x25\xfb\x12\x46\xe8\x9b\xd7\x71\x88\x8e\xd1\x30\x9f\x08\x20\x6f\x46\x78\x22\xea\x76\x8c\xf1\xf8\x52\x22\x11\x11\x34\xd6\x34\x2d\xba\x57\x45\xa9\x70\x22\x45\x84\x74\x58\x5d\xfb\x6e\x66\x0b\x1c\x43\xcf\x9b\x68\x2a\x08\x54\xcd\x91\xbe\x35\x67\xb2\x89\x6c\x2b\x79\x09\x98\x95\x3f\xf2\x1f\x36\x66\xd6\xc1\x1f\x3e\x80\x67\xba\x09\x99\x0d\x53\xef\xe5\x27\x38\xc5\x69\x4f\x7b\xef\x85\x79\xd7\xb6\x18\x73\x34\xa6\xa1\xc0\x9f\x42\x28\xe2\x9e\xb6\xfc\x37\x59\x5e\xfd\x54\x4a\x63\x25\x08\x0b\x33\x69\xc4\xbd\x3f\xdc\xba\x61\x54\xde\x51\xba\x11\xf7\x7e\xfb\x92\xd9\x5a\x5e\x09\xc8\xdf\x8c\x5d\xf1\xb3\x7a\xab\xfa\x6c\xee\x02\x3e\x7a\xf4\xaf\x08\xda\xa1\xd5\x00\x14\x5c\xe0\x5d\xd5\xa1\x6e\x7f\xee\xfd\x65\xaf\x6a\x15\x09\x55\xa7\xf7\x15\x0d\x14\xf4\x2f\x9c\xbc\xab\xae\xef\x2b\x77\x07\x58\x7c\xe1\x4a\xd6\x29\x9f\xdf\x41\x0e\xc4\x5c\x47\x83\x91\xab\x9f\xa4\xd6\x73\xd7\x23\x7a\xe1\xdd\x8b\xe0\xd0\x3b\x6f\x47\x0d\x57\x3d\x82\xaf\x8c\x81\x38\x92\x8c\x57\xef\xe5\x4d\xb3\x5a\xec\x28\x64\x71\x75\x25\x9a\xe0\x72\xd0\xae\x08\xe2\xee\x10\x2b\xba\x13\xa3\x6f\x1a\xb7\xb5\x0c\x97\x94\x87\x0b\xaf\x48\xa8\x14\xfc\x33\x9f\x9a\x66\xa2\x44\x65\x81\x5f\x9f\x6f\x0f\x53\xd1\x3d\xf5\x96\x76\x88\x1f\x84\x8e\xf7\x95\x4e\xf1\xda\xa8\x4f\x1c\xc4\x1a\x51\x1c\x1d\xb4\x34\xe2\xd5\x56\xbe\xb5\x57\x1c\xa3\x57\xf1\xf2\x01\x14\x24\xb7\xca\x68\x36\x48\x32\x7a\xdd\x73\xb0\xab\x5c\x00\xad\x3e\x37\xbc\xb1\xad\x72\x27\xd6\x44\x18\xe7\x0c\x9f\xd6\x73\x0b\x67\xa0\x53\x9b\x4d\x78\xec\x63\x90\x76\x35\x4f\x1e\x38\xf0\xe2\x31\xbf\x4a\x10\x04\xc2\xab\xe6\xb4\xf7\xf4\xb5\x45\x01\x71\x45\x05\x51\xcf\x9f\x09\xa3\x27\x3c\x70\x26\x84\x29\xa3\x2c\x0d\x78\x05\x1c\xe1\x59\x77\x20\x5e\x50\x69\x69\xa4\x86\xd8\xe6\x13\x41\x60\x3b\xf9\x24\x56\xda\xfd\x8a\x82\x3d\x38\x6d\xfe\xd4\x59\x63\xef\xc8\xde\xf3\xaf\x04\xe9\x57\x1d\x76\xe2\x1e\x24\x58\x64\xbd\xc9\x07\x5c\x1b\x98\xbd\xc2\x7a\x87\x75\x41\x38\xe7\xdb\x76\xa3\xf7\x09\xb6\x94\x94\x3b\xd8\x13\x73\x2a\xae\xc4\x98\x55\x93\x4f\x2f\x06\xca\xbe\x8b\xda\x38\x6b\x17\x21\x9b\xca\x6a\x37\x2f\x6d\xbd\x0e\xf0\x32\x6e\xce\xad\xea\x87\xe7\x11\xbb\x64\x30\x53\xed\x81\x05\x52\x51\x55\x8d\x6e\x87\xfc\x82\x03\x72\x36\x72\x0c\x28\xf0\x9a\x6a\x9e\x4f\x9a\xd5\x4e\xf9\x56\x5f\xbd\x48\x9c\x3c\xe5\x5f\x7c\x04\xc2\x20\x63\x1f\x21\xdf\x7f\x62\x35\xe3\x15\x02\x6b\x4e\xbb\x97\x7d\x47\xa8\x43\x27\xfb\x4b\xdc\xde\xe4\xd1\xc3\x56\x85\xab\x8e\x5b\x89\x5c\x9a\xc7\xb0\x1d\x1a\x3d\x28\xfb\x11\x9e\xe6\xfe\xe2\xc0\x57\xb9\xd0\xe4\x48\x4c\xca\x24\xad\x6c\x8e\x14\x9e\x2c\x28\x2f\xb7\x14\x65\xa6\x98\x73\xc4\x36\xdc\x3d\x4d\x48\x07\xbd\x8c\x83\x1d\x28\x7c\x51\x3c\x10\xa8\x17\xb1\xac\x05\x62\x82\xc8\xa7\x71\xcd\x7d\x8a\x8e\x70\x34\x8b\x9d\xfe\x28\x1a\x2e\xf5\x07\x3b\xf3\x6a\x07\x95\x3c\x17\x91\xd1\x25\x9b\xb4\x25\xfe\x16\xb4\x51\xca\x01\xee\xe3\x64\xef\x93\x20\xcd\x3e\xb9\x7f\x0d\x3b\x07\x3b\xdd\x7f\xfa\xd0\xf2\x4f\x70\x00\x44\x32\x67\x18\x68\x89\x5b\x4f\x98\x4d\x56\x38\x2d\x8e\x28\x85\xb1\x9f\xed\x53\x21\x53\x61\x5a\x4a\x57\x83\xdb\x8f\x12\x4f\x13\xa2\x2c\x8f\x26\xc9\x67\x7c\x40\x8e\x5d\x89\xc6\x1c\x48\x2a\x0a\x36\xd1\x81\x58\x1d\x02\x84\x80\x11\xa9\x50\x85\x4f\x38\x6f\x9f\x2f\x5a\x36\xa6\x61\xbf\x6d\xab\xd2\xfe\x85\x3e\xa5\xa8\x51\xb1\xba\xad\x70\x4c\x74\x5e\x71\x2b\xdb\xed\x11\x34\x69\x8c\xf9\x14\x8c\x5e\x44\x70\x7b\x01\xbd\x77\xb4\xcb\x56\x4a\xeb\x77\xad\x7d\x63\x30\x79\x4d\x44\x5a\x98\xe0\x6f\xfb\xec\x16\x38\x78\xfc\xc0\x73\x97\x4d\x31\xd8\xc8\xda\x8e\x68\x4f\x9c\x89\x75\x3e\xfe\x9f\x6c\x09\x7d\x91\x0a\x8d\x2c\x6e\x9f\x18\x03\x6c\x38\x78\x4a\x1c\x35\x24\x28\x47\xe1\x18\xd5\x76\x34\x9d\x25\x47\xb4\xac\x18\x39\x04\x17\x3b\x0d\xb4\xbc\x2e\x4a\x1a\xdc\xc3\x6a\x74\xff\xff\x65\xbf\x50\x18\xb8\x67\x6b\x5d\x19\x46\xb3\x63\x97\x20\xf4\xb0\xb9\x76\x0c\xa1\x43\xf4\x23\x73\xb6\x68\x48\xb6\xef\x63\xbc\x0b\xad\xa5\x6a\x78\xdf\xab\x0d\x94\x71\xa1\x32\x7f\xec\x28\x91\x29\xd6\xda\xfb\x8b\xa4\xd9\x71\xf8\x70\xa0\x48\x22\xad\xf4\x66\xc4\xc8\x61\xf5\x11\xa9\xd7\x47\x1f\xf1\x23\xdb\xcf\xa4\x7a\x4d\x1c\xc0\x02\x56\xf5\x9a\xe9\x1e\xb8\x23\x2d\x95\xfa\xdb\x42\x47\x58\x17\xe6\xaa\x3a\x5b\xec\xfe\xd4\xb7\xdb\xd6\xa6\x6c\x7f\xbd\xb6\x0b\x94\x63\x51\x18\xdd\x0b\x03\x2e\x62\xca\x3f\x33\xc8\x4c\x9c\xee\xf3\xfa\xe5\x9a\x7c\x2a\x39\xdb\xcb\x53\xbc\x1b\xf8\x4c\xb2\x67\x51\xd4\xd0\x58\x5b\x1b\x53\x6f\xfb\xfd\xbe\x5d\x2d\x81\x50\x8f\x0a\xcd\xc8\x92\xca\xc2\x1e\x91\xe4\x58\x7b\x73\x7e\x0c\x6e\xb0\x2e\x7c\xf5\x17\xa2\xdf\xe7\xf2\xf1\x3b\x1a\xde\x3d\x92\xcc\x05\x0b\xe2\xc9\x49\x61\x3e\x9b\xeb\x5a\xf6\x9a\xe4\xd0\xc0\xba\x9c\x94\xfe\x4a\x4d\xd7\xfc\x06\xc0\xad\x51\x33\xb4\x84\xfe\xe1\xa5\x46\x76\x48\x41\xef\x8e\xda\x65\x51\x02\x0d\xb9\x54\x42\x35\x5e\x6d\x75\x34\xef\x3d\x37\xf2\x51\x7e\xd9\x19\x29\x80\xae\x0e\x1e\x89\x26\x8a\xc1\x7a\x47\x56\xa7\xbd\x60\x82\x2f\x22\x86\xc7\x97\xd2\x89\x5a\x89\xb3\x09\x8d\x86\x64\xfd\x4c\xb2\x74\x0c\x46\x6b\x67\xad\xe2\x25\x7a\xec\x36\x6b\xa4\x90\xe8\xa5\xe9\xbd\xa9\x26\x68\x18\x2b\x0b\x77\x44\xd5\x47\xac\x23\x66\xab\x88\xbb\xe6\x03\xdf\x4d\xbf\xea\xb6\x7c\x3b\x15\xf6\x85\xa9\x11\x77\x85\x13\xbf\x9e\x5c\xac\x2d\xaa\x9e\x57\x1a\xb6\x44\x4b\xc0\x77\xe4\xcd\xc0\x89\xe9\xe0\x22\x70\x8c\x0b\x73\x7a\x61\x9b\x99\xf4\x8d\x2b\x2d\xbf\x9c\x3e\x50\xcd\xc1\x0c\x24\x7c\xf9\x96\x36\xfe\xdd\xa4\x7f\x17\x1c\x36\x7d\x11\x3e\x0f\x57\xea\x62\xda\x76\xb7\x04\xcc\x88\xd4\x25\xa6\x77\x96\x10\xa1\xc3\xf5\x78\x67\x8d\x54\x9e\x31\x06\x87\xae\x5f\x44\xf3\x60\xb7\x27\xaa\x16\x09\xa3\x70\xf8\x75\x84\x2b\xda\x71\xc7\xeb\x75\x54\x46\x71\x1d\x31\x20\xa3\xdb\x93\x0f\x1b\xf2\x44\x9d\xa0\x02\x7f\xed\x84\xf0\x9f\x86\x82\xe4\x57\x53\xed\xcd\x5e\x6a\x5f\x04\xea\x60\xa6\xa7\x32\x48\x67\x40\xfd\xbf\xbe\x29\xf5\x9f\x64\x12\x2b\x4c\xa8\x4d\x23\x47\x33\x6b\x28\xb0\x05\x5c\x82\xdd\xa9\x85\x53\x55\x34\x78\x8a\xbf\xa9\x03\x8d\xf3\xd7\xf2\x49\x01\x9c\x04\x30\xbb\xe6\x2e\xcc\x15\x41\xc1\x94\x9f\x22\x86\xb1\xdc\xa2\xec\x56\xa2\xfd\xc4\x72\x33\xf6\x6f\xa9\xaf\x48\x82\x6f\xa4\x1a\x05\xc0\x63\x1f\x3a\xc3\x29\x65\x18\xb4\x09\xbd\xb4\x2f\xfd\xb3\x45\xf5\xe1\xf6\xe9\xf6\x13\x41\xf2\xdc\x6b\x51\x72\x39\x50\xde\xd0\x66\x69\x3c\xe7\xa3\xfc\xbb\x2b\x89\xf6\xc2\x48\x3d\xf3\x5d\x2b\x6c\x8e\xe7\xd4\x7f\x23\xbb\x09\x00\x4c\x58\xb1\x48\xaa\x88\x6c\xa8\xb0\xcc\x08\x71\xef\xd8\x58\x35\x57\x88\xae\x50\x62\x4d\x51\x62\x3d\xc3\x93\xe5\xe5\xe6\x42\x4f\x84\x4a\xf9\x23\xcd\x24\xc0\x4a\x73\xfb\x03\x6b\xbd\x65\x5d\xfd\xd4\x3b\xf5\x84\x51\x5f\x6c\x4c\x4f\x7b\xae\xcd\xc2\x93\x43\x6e\x87\x61\xdd\x3a\x63\x95\xa0\x23\x0f\x63\xbb\x2b\x72\xe3\x46\xfe\x42\x7f\x6e\x04\xf8\x90\x09\xfa\xe1\xa0\x71\x79\xe5\xde\xba\x2c\x16\x53\x7e\x3c\x80\xcf\x11\x29\x34\x8d\x0b\x53\xaf\xeb\x88\x41\xff\x99\x5e\x51\x22\xb5\x64\x1a\xdb\xa1\xc2\xc0\x78\x8f\xaa\x69\x0d\x7a\xe8\xf2\x54\x60\x1f\xbd\xea\x90\xbf\x79\xcb\x17\x9f\xd1\xd9\x00\x80\xec\x1d\xf4\xa3\x0b\xf8\xec\xbb\x95\x48\xe9\xd2\x46\x77\xcc\x0d\x0a\xf3\x58\xe2\xc6\xaf\xf9\x63\x5a\x11\xc5\x62\x44\x7e\x76\xdf\xbf\x90\x8c\xe3\xcf\xe3\xa3\xc8\xa0\x8f\x6f\xcc\x4e\xe3\x8f\x17\xd2\xae\x41\xc1\x40\xf6\x94\xac\x5e\xf1\x69\x39\xf3\x74\xdf\xd0\x8c\xcb\xde\x00\x45\xe8\xc6\x6d\x47\x2a\x30\x46\xa6\xf0\xc6\xb0\xdd\xe4\x08\x2a\xff\x1e\x5e\xb4\x4b\x93\xb9\x03\x10\x61\x88\xe7\x14\x57\xd9\x99\xed\x96\x2e\x22\xc4\x9c\xc9\xdb\xee\x63\xfa\xac\x82\x5b\xbd\x9b\xc6\x6c\x90\x33\x90\x85\xc2\x5d\x6b\x6c\x0e\x82\xa6\xe9\x8a\x19\x08\x08\x99\x3a\x60\xf7\x44\x3b\x49\x20\xa6\x21\x0c\x16\x6f\xc6\xae\x2b\x6a\x74\x37\x36\x2d\x6b\x30\xeb\x3c\x88\x2e\x29\xac\xa3\xf7\xa1\xce\xea\x94\x54\x61\xa5\xe1\x4f\x88\xab\x44\xa4\xec\x2e\x07\x25\x5b\x9d\xf2\x2a\x9b\xc5\x55\xa7\xf9\x9a\xac\x6d\x91\xd0\x40\x57\xe5\x72\xef\xd1\x1b\x09\x40\xf1\x27\x2a\x78\x79\xba\xb7\x33\xac\x02\xbc\x3e\x0c\xef\x1f\x40\x26\xdf\x9e\xad\xca\xc4\x6e\x1d\xfc\x57\x5e\x7b\xc8\x35\x8f\x69\x22\xf7\xef\x09\xb6\xfb\x4a\x88\xc9\x63\xf8\x2e\x64\x65\x83\x30\x22\xa6\x0d\xf7\x2f\x8c\xe6\x1d\x06\xb1\xa2\x91\x45\x88\xd5\x50\x72\x05\x07\xe8\xc5\x9b\x6e\x0c\x6b\x1f\xbb\xba\x07\x71\x73\x14\xb1\x37\x36\x44\x62\x94\x73\xe9\xf3\xf8\x24\xc2\xac\xb9\xf5\x77\x4f\x18\x15\xea\xa6\xfe\xef\x3f\x7f\x38\x27\x91\xe5\x90\x3f\xfe\x20\x57\xce\xef\x5d\x18\x2b\x33\x17\xf3\x45\xcc\x28\xab\xb8\xce\xcb\xdc\x6c\x71\x04\x25\x0f\xf7\xa1\xd2\x44\xcc\x64\xfb\x8d\xe7\xcc\x3b\x74\x88\x81\xc4\xe0\x48\xb5\x2f\x14\x54\x31\xe4\x75\xe7\x24\xd4\xfa\x57\x6d\x00\xb6\x47\xf2\x6b\xe8\x95\x30\xb0\xd1\x18\x00\x7f\xbb\x7c\xd9\xe5\xd9\x5d\xe2\xae\x05\x3b\xb2\xb8\xe2\xac\xa7\xda\x22\x09\x47\x7e\xa3\x56\xf5\x08\xfc\x9d\x02\xaf\xc5\x30\x21\x0a\x19\xd6\x34\xdb\x6f\x4d\x56\x9d\x13\x8e\x84\xf2\x6c\x41\x8f\x3d\x22\x44\xbb\xab\xb0\x76\x52\x7b\xb4\xdc\x61\x64\xd9\x2d\xce\x8c\x13\x57\x21\x2b\x11\x32\x7d\xa4\xbb\x00\x51\xfb\xe1\x54\xb9\xfb\x4f\x69\xda\x33\x0f\x8b\xa4\x77\x52\x49\x2f\xdf\xbb\x91\x46\x29\xfa\xe1\x35\xf2\x65\x65\xf8\x3e\x6a\xd7\x98\x29\x60\x05\x34\xb2\xec\x70\xd2\x72\xf5\xed\x6c\xc3\x1f\x5b\x36\x0c\xa9\xce\x6b\xa4\x3b\xee\x5b\xe4\x6a\x40\x41\x8a\x45\x3b\x54\x80\xdb\xdb\x23\x8d\x6a\x2a\xc2\x6f\xaf\x36\xde\x53\x2a\x93\x76\x2a\xab\x5d\xa2\xa1\x97\xd3\x01\x19\x46\xc0\x80\x7d\xe6\xa4\x4a\xc6\x57\x25\x98\x20\xe7\xde\xd4\xa7\x7b\xe2\x9d\x7b\xda\xc9\xed\xe1\x85\xbe\xf6\x5f\xb4\x48\xda\x79\x4e\xc7\xa7\x45\xb2\xc3\xa9\x49\xbf\xcf\x4e\x36\xfd\x3a\x68\x78\xe5\x4c\x08\xc3\xcf\xf3\xd2\xb1\x7c\x04\x60\x73\x4c\x6c\xe4\x31\xb3\x23\x17\xa9\x6c\xf2\x1a\x62\x60\x9f\x1f\x90\x7b\x18\x49\x38\x35\xc2\x6f\xa7\xbd\x31\xdb\x27\x39\xe5\xc2\xa8\xb7\xca\x09\x01\x90\x87\xd7\xc5\x56\x35\x70\x5c\x5c\x23\xcd\x76\x63\x25\x42\x81\xc9\xc3\x85\x79\x8d\xbe\x44\xd6\x8f\xb7\x59\xb4\x55\xb5\x3d\xb7\x4b\xac\x57\x2e\xc1\x5d\xb6\x9a\xd8\x87\xae\xde\xe1\xf2\x73\x8b\x78\x60\x60\xef\xc2\x58\xc6\x83\x00\x6d\x1f\xfc\x64\x1a\xb5\x42\xe7\xa7\xe6\x0a\x83\x12\x6f\x9f\xee\x75\x9f\xa3\xa6\x79\x65\x52\x01\x96\xfa\x94\x35\x11\xe9\x7e\x4b\x89\x7e\xd0\x36\xbf\xbd\x79\x3b\x2e\xf9\x39\xff\xe3\x03\x2e\x89\x6c\xba\x49\xcf\x5b\x22\xc5\x15\x83\xcf\x48\xa7\xbb\x0f\x4f\xb5\xf0\xd2\x87\xcd\x56\xcb\xf4\x0d\x5a\xc4\x8c\x9e\x12\x8b\x3f\xa6\xcc\x72\xb7\x75\x84\x76\x3a\x8b\x4b\xcd\x26\xbd\x0a\xb6\xf1\xea\xd7\x4f\x9c\xc1\x4c\x35\x3f\xb9\xcf\x82\x1e\xf5\x70\x38\x7a\x56\x7a\x68\x0b\x33\x1a\xeb\x02\x98\x77\x21\x78\x64\x87\xb8\x9c\x94\xee\x45\x47\xa3\xb5\x7a\x97\x8c\xbe\x8e\xac\x19\x54\x20\xa2\x4f\x7b\xef\xc9\xc6\xf7\x8b\x65\xe3\x34\xba\x1e\x6d\x90\xf4\xb4\x77\xda\xb7\xbf\xe8\x2d\x7d\x02\xad\x0d\x30\x8b\xf1\x2c\x19\xf1\x70\x6f\x8c\x58\x1b\xea\x96\xc4\x14\x2e\xda\xd0\xca\xbf\xce\xb1\x03\xe0\x4b\xdd\xcf\xbd\xf0\xb6\xde\xaa\x5c\x56\x73\x7d\x8d\x44\x86\xfa\x0f\x93\xa4\x87\x14\xd9\x1f\x1d\xe1\xc0\xbb\xe0\x58\x72\x0f\x4f\xaa\xd8\xc1\x8a\xe6\xd1\xcb\x8f\x0e\xac\x3c\x37\xbc\x5e\x02\x7a\x5a\xe7\x15\x2a\xd9\x8e\x25\x7f\x97\x74\x0b\x76\x1c\xa2\x76\xbf\x3d\x31\xdd\x76\x20\x4e\x9a\x64\x7d\x93\x06\x25\x40\x73\x64\xde\xd4\x71\x17\xf2\x57\x05\x5d\x54\xef\xa3\x61\x41\x37\x3e\x64\x06\x36\x49\xd5\xe2\x47\x50\xd6\xeb\xa8\x21\x96\xd9\x7c\x93\x75\xac\xe6\xcf\x3b\x74\x10\xf9\x03\x16\x71\x6f\x53\xb2\xfb\xc5\x31\x72\x07\xbd\x96\x91\x2c\xa4\x1a\x43\x0e\x6e\x28\x20\x60\xf9\x75\x76\xc2\x0e\x90\xbd\x56\xf0\xdc\x6d\x47\xcc\xf5\x20\xac\x0c\xcd\xb2\x6f\x40\xc7\xef\xfd\x3e\x11\x20\xc9\xef\x69\x1c\x6f\xa4\x52\x65\xec\x84\xbe\x9e\xc3\xed\x1a\x3e\xac\xaf\x98\x67\xdf\xff\x3a\xa1\x1e\xb1\xa8\x6d\xcb\x52\x5f\xe8\xfe\xa2\x04\xa4\xce\xd4\x6a\x3b\x80\x86\x5e\x75\x45\x4a\x6c\x3d\x75\x2e\x21\x0d\xe0\x4a\x02\x41\x8e\x48\xaf\x3c\xf2\x28\x07\x4a\x8d\x60\xa0\x1d\xce\x9b\x26\x99\xb4\x74\x11\x99\x0b\xb9\x4e\xba\xbf\x3d\xf1\x82\x0c\x2f\x28\x9c\x15\xdc\x2d\x39\x4e\x7d\xff\x84\xf4\x5b\xea\xb9\x65\x05\xc3\x7c\x6d\x15\xea\xda\x03\x78\xf1\xc5\xf4\x9b\x96\x41\x52\xb6\x68\x1f\x0a\xc7\x35\xe9\x92\x45\xfb\x45\x13\xa0\xf6\xea\xcb\x71\x36\x3c\x19\x7c\xa3\xa9\x5b\x40\x05\x60\x76\x3c\xe8\x1c\xf8\xe6\xc9\x37\x97\x28\x6a\x67\x64\xc9\x3c\x98\xbc\x04\xfb\x16\xfc\x9d\x1e\xf9\xae\xba\x76\x02\xc9\x89\x44\x2e\x77\x9a\x4f\x6a\xa8\xa7\x7a\xfe\x58\x96\xb5\xa9\xec\x6d\x19\xfc\xcc\xda\xc9\xf0\x6a\x2a\x0b\xcb\xbb\xac\xfe\x6a\x64\x12\xde\x58\x47\xb6\xc0\x90\xc9\x09\xd0\x1b\xd3\xd0\xc9\xed\x05\x9b\x39\x6f\x2d\x1f\x5a\xad\xea\x9a\x7e\x8c\x4e\x34\x4d\xa2\xac\xf8\xae\x96\x8b\x80\x9f\xe1\x43\x8a\xa6\xed\x1b\xba\x25\x90\xf8\x16\x7a\x1f\x58\xfb\xb0\x80\x82\x99\x9e\x3f\xf9\xc1\x36\x1e\xcd\xbb\x72\xa0\x39\xcd\x9a\x99\xd0\xa4\xa7\x30\x93\x02\x3d\x45\x11\xfe\x4b\x1e\x81\x4d\xff\x3f\x36\x2f\x42\x9e\x53\x23\x4a\x87\xce\xdd\x89\xd0\x2d\x02\xb8\xab\x11\x72\x7e\xb4\x68\x8e\xa0\x63\x7a\xb7\x24\x08\x9b\xd9\x81\x3e\xe4\xb6\x3f\xc5\x6d\x51\xbe\x38\x2e\x0e\xca\xf0\xbe\x89\xdb\xe4\x27\xc9\x78\x9a\xb2\x7e\x0e\xc0\x1b\xd5\xe8\x9d\xc3\x23\xcc\xca\xc5\x2b\x52\xd2\x87\x7c\xf3\x7d\xbe\xee\x27\xa7\xd7\xee\xfb\xc6\x05\xf9\x59\x57\x84\xa2\xb9\xdc\x87\xff\x56\xbd\x2a\x01\x34\x63\xbb\xac\xdf\xde\x0d\xe2\x39\xaf\x1c\x42\x35\x0c\xaa\xc2\xa0\xc9\x7e\xbb\xd8\x66\x30\x00\xe2\x2e\x82\x2c\x3d\x3e\x0e\xf9\x9f\x15\x77\x0b\x09\x5b\x3b\xfd\xcb\x56\x79\xc1\x7b\xea\x17\xbf\xa6\x44\xa2\xdd\xc5\x61\x56\x4d\x4c\xfd\x0e\x43\x78\xdb\x3c\x68\x94\x60\xdb\x04\x77\x6b\xaf\x6b\x36\xde\xff\x67\xcc\xab\x16\xe5\xf1\x77\x65\x10\x0f\x14\x09\x69\xdc\x06\x94\x4e\x5b\xfe\x0b\x0a\xe7\x7b\x69\x73\x2a\x5b\xa7\xb0\x72\x72\x5e\xe7\x0b\xdb\x35\x47\xe8\xd9\xdf\xc6\x0a\x87\xb9\x83\xe1\x37\x43\x6b\x3e\xb7\xdb\x07\x0a\x0f\x9a\x78\x28\x72\x91\xdb\x41\x4b\xc8\x05\x4e\xe3\xfb\x43\x58\x75\x94\x05\xc2\xee\x07\xd1\xe4\xe6\xe5\x01\x93\xa7\x1c\x54\xb6\x5f\x18\x89\xcc\x98\x81\x75\xf2\xbb\xf1\xbd\xe2\x82\x36\x52\x4d\x0a\x69\xcb\x9a\xc2\x43\x3c\x61\xef\xcf\x5a\x22\xed\xc0\xd1\x95\xf0\x80\xc5\x60\xbe\x70\x2c\x7f\x37\x16\x5c\x69\x9b\x86\x03\xcc\x82\x9b\x16\xcf\xd0\xe0\xd6\x53\xf7\xaa\xf4\xc7\x74\xde\x02\x74\x5c\xec\xf9\x20\x58\xa3\xfc\x83\x53\x46\x07\x1b\xef\x65\xeb\xd5\x1b\x8c\x85\x24\x6d\xb1\x26\x66\x78\xfb\x71\xb7\x72\x8e\x79\x12\xdf\x76\x8a\x42\xe7\xc6\x50\x99\xdb\x53\xe4\xa9\x84\x3e\xaa\xaa\x3b\xc1\xa2\x71\xc8\xcb\x15\x2b\x9f\x84\x4d\x8d\xb3\x3f\x42\x73\xba\xc9\x94\x2a\x4a\xa3\x65\x10\xfb\xa6\x8a\x49\x64\x57\x77\xf2\x23\x96\x87\x1f\xf7\xad\x4b\x68\x2d\x7c\x50\x45\xb9\x13\xd6\xe7\x76\x93\x21\x9d\xda\xc9\x56\x81\x41\x86\xff\x50\xbb\x52\xc4\x93\xcb\x2e\xe6\x91\xba\x26\x8c\x7a\x90\x14\x46\x8d\xd3\xad\x30\x28\xf8\xa7\x86\x8d\xd5\x1b\xe1\x76\xc4\x7e\x16\xb4\x5f\x25\xa2\xe9\x86\x28\x83\x8e\x86\x73\xf4\xf5\x15\xc0\x8f\x55\xec\xaa\x11\xad\xcb\x2b\xa4\xc3\x4e\x32\xf4\xb9\xe4\x37\x04\xee\x1d\x8e\x71\x61\x41\x5b\x0a\x86\x8f\xb3\x74\x34\xdb\xeb\xbc\xf2\xa3\x6d\x16\x9a\x37\x4d\xe1\xa1\xf8\x5d\x42\x45\xef\x0f\xe1\x63\x95\x0e\x71\x53\x15\x1d\xe5\xbb\xdb\x72\x29\xa7\x0d\x81\x54\x43\x7d\xa9\xb7\x53\x35\x54\x64\xb8\xfb\xc5\xc9\x40\xa2\x0f\x78\xe7\x57\x43\xaf\xe9\x9c\xc5\x31\x3d\xde\x04\x69\xa4\x70\x68\xd3\xe7\xe2\x6d\x1b\x64\x7c\xc1\x3f\x25\xe0\x8b\xe2\xb1\x4b\x89\x37\x90\x08\x87\x52\xe8\xfa\xd1\x69\xf0\x13\x79\x4b\x5c\x22\x44\x83\x66\x1b\x25\xeb\x09\x25\x2e\x91\x20\x3b\x92\x03\xc0\x72\x61\xbe\xe6\x59\xb6\x9d\x7a\x55\x24\xc8\xc0\x8b\x9f\x23\x42\xf8\x30\x02\x26\xf4\x5c\x56\x9a\x0a\xb8\x4b\x96\xec\x86\xa6\xd4\xc0\x25\xbb\xfb\xdd\xdc\xc4\x1d\xb3\xb8\xbb\x25\x58\xe0\x88\x33\xa4\x46\x0d\x42\xdd\x26\x90\xac\xdf\xe0\xe8\xaa\x0a\x9a\xe0\xde\xc7\x46\xee\x9f\xac\x0b\x57\x18\x78\xd1\x13\x4a\x20\x1f\x93\x11\xd9\xdd\xd3\x27\x11\x88\xf2\xdb\xd3\x0a\x42\x96\x1d\xb6\x70\xdb\x85\x87\x3b\x02\xd4\x30\xbd\x81\xcb\x96\xb6\xf0\x2d\xbf\x3b\xee\x00\xb0\xdd\x1e\x69\xb4\xb8\x1e\x49\xc1\xb2\x97\x06\x50\x2b\x72\x4a\x64\x5f\x84\xf9\x74\xf3\xf2\x0c\xc3\x00\x28\x8f\x88\x16\xdf\xde\xbb\xd8\xd6\x73\x25\x46\x7a\xf9\x9f\x84\x49\x96\x88\xbb\xd6\x4d\x2b\x97\x1f\xa4\x34\xa5\x80\x21\x63\x94\xfe\xb3\x1d\xee\xde\x07\xd9\x7c\x78\x5d\xca\xd7\xde\xae\x4c\xd1\x02\x70\x3a\xf2\xf3\xd4\x10\x39\xb5\xe7\xc1\x96\x49\x34\x9d\x4f\x98\xbf\xd9\x2d\x7a\x36\x23\x65\x21\xa8\x58\xb5\x08\x0e\x2f\x76\x94\xfa\x01\xfa\x8c\xf2\xe7\x8e\xa6\xff\x77\x30\x19\x63\xd1\x07\x9d\x8c\xf4\xef\x69\x6b\xb1\x5d\x23\x8a\x68\x59\x48\xfa\x21\xa2\xe0\xe3\x3a\x52\xd3\xe5\x46\x5f\x9a\x31\x8d\x9c\xd6\x3c\x6f\x6d\x3b\xe4\x29\x41\x4a\xab\x7d\x19\x28\x14\xad\x97\x3f\xf4\x5a\x1c\x3e\x49\x0d\x56\xb3\x15\xb0\x43\x5e\x06\x48\x8b\x32\xb3\x7d\x43\x0b\x05\xe5\xa9\x7a\x27\xe8\x51\x7d\xc4\x8c\xf7\x61\x90\x87\xa9\xbd\xea\x9f\xbd\x4d\xde\xfa\x14\x8c\xc9\xee\x73\x28\x15\x33\xba\xa2\x23\x47\x80\x8c\x8f\xea\x1e\x31\x48\x8f\x9a\x48\xd3\x8f\x9f\x83\x8c\xad\x08\x76\x3f\x34\x45\xd7\x3c\x9d\x24\xdb\xae\x6a\x6c\x16\xf6\xcf\x56\xe5\x69\x25\xa7\xa0\xae\x41\x2c\x70\x27\x8f\x9c\xd7\x2e\x97\xd0\x6f\x4a\x35\x43\xd3\xea\x44\x73\xcb\x7e\xd2\x8b\x98\xf4\xf7\xd8\x6e\xa5\x5b\xd9\x7d\x3e\x19\x78\xb6\xc4\xd4\x22\x2d\x14\x09\xa0\x23\x25\xe4\xb4\x28\x4f\xfe\x13\xe5\xdf\x27\xff\xbb\x7d\x2d\x57\xb3\x6b\x2d\x8a\x63\x9f\x8a\x54\xbe\xe0\x4c\xad\x61\x74\x68\x55\x9b\x5d\x80\xa2\x1f\x82\xe0\xa4\x0e\xeb\x4a\xdb\xdc\x52\x4d\x56\xa1\x45\xf0\x4d\x17\x95\xe8\x48\x72\x36\xa0\xb9\xbb\x5d\x75\x94\xa0\x81\x42\xc8\xc6\xa9\x8c\xe2\x1e\x4e\x4a\xbd\x38\x73\x52\x6c\xa0\x15\xc1\xbe\x25\x9c\x50\x8e\x34\xfd\x27\xc9\x66\xf6\x46\x0e\xe4\x03\xad\x85\x93\x7a\x0d\xe5\x29\xec\x13\x17\x51\x47\xe7\x4e\x51\x8a\x15\x05\x2c\x9e\xea\xd4\x02\xd8\x20\x05\xf7\xc3\x05\x24\x37\x15\xd3\xb6\x54\xff\x87\xf7\x99\x07\x78\xb5\x6b\x9e\x4a\x7e\xdb\x7d\x9a\x8d\x53\x0c\x80\xb6\xa2\x6d\xe7\x96\x86\xdc\x95\xf2\x8e\x79\xdf\x11\xd8\x09\x7b\xd8\x32\xf1\x86\x45\x80\x65\x58\xc5\x7a\x2c\x54\x56\xa9\x94\xb7\x01\xc4\x63\x5f\xb6\x3a\xac\xe7\x97\x73\x47\x5a\x5a\xa6\x8a\xec\xd0\x15\xe8\x53\xa2\xc2\x02\x58\xec\xb5\xd1\x9d\x87\x6b\x56\xed\xb4\x9d\x72\xfb\x5a\x60\x7a\x95\x14\xef\x62\xa5\x9a\xc6\xef\xfb\x14\x0a\x83\x67\x8d\x32\xc9\xfd\x35\x2b\xfe\xff\x07\xc0\xc1\xff\x00\x64\xdf\x38\x9f\x3e\xa4\x30\x56\xd9\x8e\xf2\x30\x99\x49\x0a\x98\xee\x90\xe7\xd4\x41\x7c\x14\x28\x77\x02\x52\x4f\x7d\x78\xbf\x9f\x4c\x6f\xb7\x3d\x2b\x2d\xbf\xf8\xf5\x08\xda\xdc\x68\x9b\x8e\x83\x4c\x5f\x16\x74\xa1\x43\x49\x04\xe0\x26\x70\xb1\xae\xb2\x8f\x87\xb3\xed\xd6\xe8\x42\xf4\xb0\xbd\x7b\x89\xe8\x92\x17\x76\xd6\x8b\xb6\xa4\xfe\x71\xe4\xc8\xdd\xda\x11\x27\x04\xdd\x87\x6e\xf0\xe1\xee\x92\xb0\x1f\x0a\xea\xc4\x12\xda\xc1\xb9\x4b\x0a\xea\x46\x30\x6c\xb0\x14\x69\x9b\x80\xec\x4e\xd7\xe5\x0e\x80\xa8\xbd\xdf\xec\x5b\x82\x5a\x5f\xc3\x42\x7e\x09\xcb\x5d\xd8\xb4\xf9\xd5\xdc\xff\x13\xf1\xe3\xaa\x04\x4e\xbc\x60\x68\xa4\x6f\x16\x97\xa3\x47\x09\xc3\xfe\xee\x73\x88\x1d\x74\x8f\x2d\x54\xef\x57\x38\x74\x00\x47\x1d\x04\xe6\x07\xe7\xbf\xde\xf3\x02\x4d\xbb\x5a\xd5\x0a\x6a\xd3\x63\x35\xd7\x2d\x55\x63\x82\x8e\xb7\x46\x47\xd4\xd3\x5d\x2a\xe8\x12\x0e\x98\x8a\x6a\x62\x5f\x52\xc4\x6e\x17\xa1\x5c\x2c\xba\x1f\x49\xc5\x19\x08\x94\xca\x2e\x83\xb6\x2b\xde\xf9\xe0\x3e\x4d\x69\x0d\x75\x79\xe0\xf4\xbe\x29\x71\x47\x92\x79\x68\x26\x1e\x05\x45\x9e\xed\x1f\x7d\x98\x45\xf8\x5f\x78\x8b\xcd\x77\xd1\x52\xf2\xd2\x78\xd8\xf6\x9d\x46\x7e\x3c\x88\x24\x00\xa3\xfe\x05\x83\x5e\x18\x29\x6f\x5c\xf0\xeb\x9a\x87\xfc\x45\x73\xa4\xd3\x7e\x64\xb8\x47\xc4\x76\x01\x4b\x7c\x8f\xc3\x99\x4b\xc7\x3d\x8b\xee\xa3\x53\x46\x6c\x8d\xef\x5d\x65\xa0\xb3\x44\x5f\x03\x4b\xe2\xeb\x70\x7a\x76\xba\x55\x0d\x95\x9b\x97\xa0\xa1\x8d\x37\x08\x7a\x37\x79\x44\x58\x07\x2c\x39\x1f\x7a\xe1\x74\xce\x2d\xdf\x34\xee\x71\xf4\x7e\x3e\x69\xcf\x4d\xca\x20\x2d\xd9\x7a\x6b\x97\x5f\x9d\xcf\xc1\x80\xdc\xaa\xac\x21\xc8\x17\x38\x85\xfb\xd7\xc7\x11\x49\x11\x97\xe4\xb7\xab\xcc\x91\x7a\x0f\x77\x88\x4d\x66\xca\xbf\x5d\x46\xdd\xe4\x0a\x86\x09\x9b\xbc\x03\x88\x2d\xbf\x40\xc6\x8e\x6e\xfc\x15\x3e\x4a\xb3\x70\xa2\x57\x60\xd4\xc0\x73\x0e\x51\xaa\x35\x66\x83\xc6\x17\x8c\x0a\x6f\x02\x17\x40\xec\x41\x13\x8a\xc8\xa9\x85\x39\x1c\xf3\xbd\x7d\xb9\x35\x49\x48\x9f\x77\xdf\xdf\xe6\x30\x22\x9b\xf1\x37\x34\xeb\x74\x8d\x63\xf0\x4e\x9f\x7c\xcc\xc1\x9b\xfe\xb6\x56\x6c\x8b\xf6\xd1\x36\x85\xc0\x7b\xa6\x54\x24\x91\x48\xbc\xdc\x46\x0e\x97\x47\xbc\x5f\x6c\xcb\x40\xc9\x53\x14\x0f\xaa\xa9\xa4\x04\x06\xa6\x63\x3e\xbc\x6f\x63\x12\x1e\x64\xf9\xfa\x42\x3b\x56\x42\x97\x5f\x65\xb0\x0a\x71\x88\x33\x8f\x60\x6d\x58\x48\xa2\x0e\x91\xd1\x08\x49\x7e\x74\xdd\xcf\xfb\xe0\x80\x07\xf8\x37\xe1\x6f\x64\xed\xf9\xa1\xfa\xac\xe2\x2f\x23\xa9\x19\xb3\x28\x2c\x61\x85\xe1\x7b\x5c\x3f\xab\xbd\xa1\x91\xbb\x26\xf9\x29\xdc\xbc\x3b\x25\xb2\x08\x82\x72\x15\x41\x8a\x91\xde\x92\x76\x92\x87\x6c\x63\x2b\xbd\x84\xc4\x22\xef\x0f\xa9\x09\xf7\x0b\x6b\xa1\xfe\x70\x3b\xc7\x21\x46\x79\xd2\x3c\x9e\xaa\xde\xaa\x5d\xfb\x01\x8e\x5f\xdc\x10\xe5\x6c\xd5\xcb\x48\xd6\x23\x80\x72\x90\x97\x60\x16\x2e\x06\x51\x77\xaf\x3b\x5d\x28\x6f\x89\x93\xba\x20\xfd\x77\x1a\xd6\x3b\x40\xdf\x15\x1f\xea\xd3\x9a\xf8\x68\x3b\x14\x83\xfe\xbb\xac\x14\xb1\x2e\x12\x22\xd5\xec\x22\xc3\x18\xb9\x72\xec\xee\x2e\x5d\x95\xc0\xbf\xbf\xfe\x88\x6a\x82\x50\x78\xd6\x89\x4c\xe3\xbe\x32\xc8\xd6\xfe\xa3\x64\x22\xdb\x68\xce\x70\xef\xb3\x96\xef\x5b\xc8\x48\x8a\x9d\xed\xba\xf5\x52\x5c\x53\xbc\x9b\x17\x50\x09\x81\xda\x45\xf0\xb3\x1c\x6a\xc1\x01\x60\xc3\x77\x41\xc0\xb5\xc7\xd2\xf7\xb7\x33\xa8\xe1\x27\xdc\xc9\xa4\xa3\xec\x4b\x28\xc8\x6d\x43\x12\x1c\x95\x97\xdd\x77\xa8\x9c\x22\x5e\xfd\x8e\x21\xf3\x89\x69\x6b\xf3\x92\xba\x34\x1b\xc5\xb2\x99\x4b\x83\x84\x7d\x86\x8c\x4b\x1e\xe5\xde\xf7\x1c\x48\x6c\xf5\x7d\xcb\x8a\x10\x2f\xbf\xf2\xa6\xd6\xda\xda\x3b\x16\x66\x59\x37\x11\x34\x20\x3a\x7b\xec\xec\xf4\x16\xef\xc8\x2b\x29\x8f\x0c\x70\x47\x54\xc5\x45\x1e\x42\x8d\x19\x2d\xe4\xea\xd1\xd0\xa2\xf0\xc4\xc3\x14\xa9\xed\x5e\x7c\x79\xb7\x1d\x6e\xb4\x57\x78\xbf\xc0\x83\x8a\xd2\x65\x64\x44\x64\xc9\x98\x63\x0f\x58\xbd\xb8\x85\xd4\xe4\xe1\xc5\xd6\x57\x54\x23\xfb\xd4\x99\xb4\xfa\x99\xd6\x92\xe9\xb3\xf6\x40\x4d\x44\x4d\x00\x65\xb2\x10\x3b\xdf\x14\xe3\x94\xd0\xc5\x90\xa8\xb7\x46\x4d\xa7\x57\x1b\x3e\xb5\x9c\xde\x21\xc1\xf1\x22\x62\x75\xe8\x4d\x42\x2f\x29\xf1\xa7\x8e\x4d\x48\xa4\x6f\x0a\xc4\xac\x15\xd9\x3a\xca\x3f\x6f\x62\x24\x40\x3d\xd5\x61\xce\x6f\x9f\xb2\xce\x6f\x72\x8e\x8e\x5b\x76\xd0\xf7\x4e\x55\xb5\xdf\x98\xb3\x5d\x32\x92\x8d\xf5\x93\x7c\x3d\xc5\x48\x0a\xf3\xa0\x39\x9c\xf5\xe7\x9f\xa0\x68\xce\x1a\x48\xcf\xf4\x4b\x9c\x1b\x13\xe5\x0f\xf2\x05\x7c\xea\xaf\x2a\xe1\xfe\x2f\xb7\xc9\xcd\x9f\xb8\x1a\xd3\x1d\x76\xca\xb8\x0f\x83\xeb\xb4\xd5\x3f\x51\x35\x9f\x91\x1d\x7a\xc5\x88\x65\x92\x3b\xfc\xf4\x6b\x68\xdc\x4d\x28\xcc\x1e\xb1\x83\xbe\x3f\xbe\x6b\xc2\x6b\x97\x01\x93\x72\x5f\x78\xda\xe6\x23\x5a\xc6\x33\x62\x6c\x9f\x34\xd3\x7e\x46\x50\x2b\xf8\x12\xf4\x6f\x4f\x32\x00\x87\xb7\xa3\x47\xe9\x6f\x2c\xff\xec\x59\x7c\x39\x0d\x8c\xb0\xdf\x9c\x8e\x58\xb0\x73\xbd\x23\x13\x79\x38\x9a\x75\xda\x60\x57\x78\xa0\x63\x47\xa0\xe0\x83\x0b\x09\x38\x24\xe4\x38\xd1\x36\x09\x07\xb5\xb5\x46\xe7\x94\x46\x29\xc5\x39\x3b\xf2\x40\x0d\x51\x1b\x7c\x77\x97\x2f\x5e\x95\x3f\x2f\xd2\xf3\x9a\xf8\xa5\xb6\x99\x42\xaf\xea\x1d\x98\xfc\xbf\x58\x59\xe8\xa3\xd0\x09\x4b\x18\xb7\x5d\x8a\xc5\x6c\x0b\x19\xcc\x28\x76\x41\x27\x84\xcb\x5c\xd4\xf6\xde\x6d\x1b\xae\xde\x57\x59\xa3\x3b\x48\x40\x97\xce\x7f\x69\x12\x98\x09\x70\xe0\xd8\x2c\xc3\x5c\xe9\xe2\x25\x1e\xac\xcd\x13\x6b\x94\x14\x9d\x6c\x68\x5f\x30\x1d\xc4\xe3\x10\x56\xda\xa9\xd3\xe9\xf4\xa5\x81\xcb\xa7\x49\x5e\x34\x49\xc3\x5b\xdd\xc8\xe3\x25\x9c\xa1\x7c\x33\xd6\xc5\x04\xd8\xad\x59\x8b\x45\xf2\x42\xd3\xc3\xb9\xe0\xce\xa3\x75\xdc\x91\x68\xe3\x98\x72\x03\xf1\x88\x35\xbd\x97\x4f\x1d\xcf\xfc\x7b\x1f\xca\xcc\x51\x84\xb2\x87\xaf\xba\xd3\x6f\x13\x61\x11\xac\x19\x25\x6b\x87\x79\x26\xa9\x16\x77\x17\x2d\x32\xa9\x52\x97\x2a\x33\x47\xed\xc4\x51\x4f\x57\x54\x93\x56\x06\x76\x31\x69\x84\xa8\x2f\x26\x18\xe9\x37\xcc\x48\x91\xad\x85\xc0\x62\xf9\xd6\x03\x93\x08\x4c\x86\xa3\x09\xff\x74\x04\xaa\x9f\x2d\xb4\xda\xea\xd3\x4d\x5b\x93\x9b\x51\x68\x1c\xa1\xa3\x20\x2d\x91\xea\x7e\xc8\x66\xfe\x28\xdf\x2f\x73\x8f\x65\xa9\xd4\x8b\x68\x81\x81\x69\x66\xe9\x9a\x78\x59\x1f\x56\x8e\x9f\x62\x95\x21\x9e\xe2\xe1\x7a\x5b\xee\xea\xbe\x3f\xef\xe9\xb5\x14\x8e\x2a\xec\xea\x7c\xb2\x82\xaa\x76\x7e\x90\x8c\x56\x67\xb2\x3b\x37\x4e\x0b\x36\x4e\x0f\x6e\x2a\x29\xd6\xfa\x95\xbf\x92\x27\x42\x91\x0d\xb1\xf6\xaf\x20\x75\x79\x56\xb2\xe2\xb8\xfb\xa7\xfe\x22\xf7\xa0\x68\xbd\xb1\x12\x20\xa5\xcb\xc6\xbb\x4d\xa7\x40\x9c\xb2\x01\xd4\x95\x88\x91\xd2\x69\x89\x9c\xf2\x07\x41\xbd\x4d\x7c\x89\xcf\x2a\x20\xef\xad\x5a\xd5\x5d\x93\x4f\xed\xc2\x1b\x3d\x67\x34\x04\x99\xed\x49\xe8\xa6\x99\x9d\x27\x30\xb7\xb7\x14\x06\x6e\x5a\x41\xe0\xeb\xbb\x68\x92\xca\x70\x8a\xa2\x7d\xa2\x6f\xe8\x74\xff\xa6\x9d\xdc\x48\x27\xf6\xd0\xcf\xb5\x19\x8f\x4e\xf9\x1d\x7e\xe5\xaa\x5d\xff\x68\x60\xd8\x79\x1c\xf1\x48\x12\xe4\x78\x13\x75\x19\xc1\x92\x63\xe1\x79\x64\x5e\xcb\x63\x8c\xd0\x9d\xa5\x16\x2b\x45\xbc\xd7\xb7\x52\x9c\xfd\x96\xe6\xa4\xa1\x8d\xb7\x41\x4e\x0d\x9f\xf3\x63\x23\x7f\x77\xd4\xeb\xee\x0a\x40\xbd\xba\x4f\xea\x63\x9e\x0e\x3c\x91\x19\x8f\xdb\x39\xc2\x02\xa3\x9c\x85\x1f\x35\xeb\xa8\xac\x79\x57\x76\xeb\x3e\xff\xcc\xa6\x11\x1d\x0c\xc5\x1a\x53\xd5\xa5\xd7\xda\xf5\x07\xec\xf2\xaa\x97\x87\xf2\x7f\xba\xf3\xb3\xf2\xfa\xb4\x15\x04\x3d\x03\xf7\xdf\x1c\x3c\xb6\x41\x6e\x70\x50\xb2\xd2\x91\x11\x3d\x11\x79\xe2\xb0\x88\x67\x81\x0a\xa3\x97\xd5\xf5\xfa\xfa\xf0\x57\xcb\x8a\x9d\x26\x6d\x5d\x1f\xfa\xd0\xbe\x6a\xca\x31\xaa\xc9\xb6\x1e\x3f\xac\xda\xa7\xfa\xbf\x5b\x7d\x50\xef\x3d\x86\xb7\xfe\xa0\x22\xc1\x4a\xce\xd7\xcb\xa4\x5e\xfc\x3e\x64\x04\x0a\x6a\xbe\xb2\xb9\xee\x7e\x8a\x3e\xff\x9e\xb8\x4d\x93\xc6\xd1\x45\x60\x5f\x57\x24\x5a\x56\x3a\xba\x55\x97\xb6\xa7\xe2\x85\xfe\x0a\x22\xf8\x7a\x12\x36\xc9\xab\x87\x76\xd0\x0f\xf4\xab\x93\x0a\xe0\x7b\xf1\xb3\xc0\x1d\x51\x05\x12\x96\xb0\x1b\x70\x8b\xc8\x08\x75\xe2\xc5\x62\xbb\xef\x2e\xeb\x54\xb0\x8c\x02\xa5\xb6\xad\x76\x0d\x1b\xc8\xb4\xd0\x1b\xf8\x75\xb4\xfb\x03\x99\x9d\x65\x09\x95\xb3\xd3\x56\x41\xb6\xa2\x6e\x51\x91\xb3\xef\x88\x77\x3b\x01\xa1\x71\xca\x0b\x6b\x2c\x16\xc2\xf0\x84\xb9\x64\xe3\xe8\x29\xca\x1a\x03\x3f\x93\x46\x83\xb6\x5f\x86\x97\xc8\xc5\xf9\xc1\xb9\x23\x4d\x92\x64\x5a\xec\xe0\xfe\x55\x75\xf8\x67\x1e\xa2\x48\xb1\xa9\x2a\x38\xde\x6e\xb3\xc6\x04\xb1\x5e\x91\x17\x11\x2d\xb3\x62\x30\x92\xb6\xc0\x25\x95\x1c\xaf\x1d\x07\x67\x3e\xf7\xd6\xd0\x24\xb6\x5c\xbc\x43\x8e\xcf\x07\x2c\x9f\x1c\x85\xd4\x38\x78\x5f\x48\xa3\x40\xb8\x94\x78\x6a\xf9\xe8\x0b\x07\x06\x7b\xd2\x17\x51\x73\x0c\xbb\x73\xdf\x47\xd1\x30\x11\x96\x94\xab\x0e\x34\x42\x0e\x46\x46\x51\x7a\x37\xdd\xc8\x5a\xe5\xee\x63\xe5\xb6\xcc\x61\x6d\x2d\xba\xa6\x15\xc9\x8a\x72\x76\x8a\x7c\x68\x32\xd7\x9c\x49\x20\xf1\x7c\xd2\x22\xd4\xa0\x0f\xc1\xc8\x9a\xd8\xbb\x81\xbe\x1b\x64\x3c\x1f\xe4\x6a\xa4\x3b\xfd\x4a\x62\xa1\x99\x49\x09\x10\x56\xe9\x8b\x91\x8f\x1d\xc2\xff\x04\xe0\x23\x56\xae\xb2\xa1\xc1\x36\x4c\x18\x80\xc2\x6b\x3b\xe3\xfd\xd1\xed\x6b\x38\x4a\xf1\x5d\xee\x0f\xac\x6c\x2f\x39\xff\x72\xc4\x1a\xfd\xa9\x00\xb7\x46\x2b\x48\x68\xd0\x04\x68\x38\xfb\x0f\x9f\xe4\x08\x7a\xa5\xed\xb2\xb1\x08\xe6\x70\x91\x9c\x75\x92\x22\x73\x22\x20\x35\x35\x8c\x6d\x72\x6a\x67\x58\x10\xed\x6d\x42\x43\xed\x3b\xf6\x4b\x99\xc9\xe6\x41\xbc\x79\x44\xab\x2c\x9c\x82\x20\xa2\x4d\xf4\x93\x1b\xb5\x9b\xb8\xc3\x50\x2a\xc8\x84\xd5\xea\x5d\x09\xab\x0b\x0d\xf0\x1e\x3e\xfb\x9d\x05\x83\x0e\xa2\x4b\xbb\xb1\x33\x05\x03\x02\x9f\x6d\x77\x25\x78\x8a\x19\x27\x47\xa7\x43\x94\xc3\x43\x58\xb9\xd9\x26\xb7\x38\xa1\xd5\xea\xd0\xab\x0d\xe4\x6c\x8f\xbb\x28\x36\x42\x52\x32\xa7\xae\xf5\xe8\x38\x7e\x29\xa9\xb9\xcf\x1e\xa2\xe6\x1f\x9d\xa8\xb8\x5d\x33\xe9\xe8\x14\xe2\xde\x29\x4a\xc4\x0a\x46\x2f\x08\xba\xa2\x69\x2c\x4c\x07\x35\x0b\xb4\xf2\x51\x6c\xb5\x4b\x69\xd9\xe9\xdc\x54\xea\x7a\x66\xbf\xf3\xd5\xfe\x8b\xd0\x16\x1e\x6b\x4e\xbb\x6a\xfe\xfa\xb0\xfe\x92\x2f\x98\xff\xa3\x5b\xf8\x30\x87\x08\xfb\xde\xa7\x84\x0d\x9f\xe0\xc5\xfa\xd7\x17\xeb\xb3\x02\x25\x82\xad\x17\xa9\x0b\xae\x5c\x94\xd9\x0a\xfd\x61\xde\xad\xdf\x4f\xbf\xcd\x6c\xce\xe1\xdb\xa7\xe6\x09\xec\x36\x1f\xd0\x36\x61\xc6\x55\xc3\x41\x29\x3c\xa8\xac\xbc\xa2\x23\x34\x3a\x26\x55\x88\xb8\x3a\xbc\x32\xfb\xb2\xec\xc0\xee\xa6\xcd\x4d\xad\xc3\x59\xb9\x2f\x95\x55\x97\xb5\xed\x50\xda\x98\xd2\x2d\x03\xdb\x97\x7c\x59\x88\xc6\xdb\x63\x7a\x4a\x44\xb4\x84\x89\xe7\x99\x1c\xac\x3c\x3e\x2d\x01\x1e\xd9\xa4\x1c\xd9\xa6\x83\xda\xc6\x66\xae\x34\xb5\x38\x4b\xae\x7b\x2d\x45\xca\x6d\x27\xb8\x6d\x6b\xfa\x96\x42\xa5\x24\x6c\x9e\x09\x5b\x12\x95\xda\x8f\x3a\x7b\xc2\x05\xec\x5b\x48\x6b\x13\x92\x6b\xbd\x30\x1c\x99\x1f\x4e\xd1\x9d\x44\x73\xf4\x70\xd0\x4d\xcc\xb6\x83\x0e\x4c\x5b\x78\x9c\xd9\xe5\x16\xf3\x9a\xa3\xcc\xf8\x8b\x90\x25\x41\x53\x96\x1b\xfe\x6b\xab\xf2\xf7\xac\xe2\x24\x08\xc9\xf9\xca\x83\x2c\x17\xee\x79\x07\xda\x13\xd4\xd6\xfe\xd1\xc6\xc0\xd1\xfe\xa5\x84\x61\xe4\xd1\x28\xb5\xbe\x77\x97\x83\x66\x55\x1d\x49\xcc\xe9\x0c\x45\x64\x50\x58\x24\xfe\x5b\x93\xdf\xbb\xcb\x4d\xcd\xa1\x73\x52\xfc\x51\xe1\xa4\x91\x55\x53\xfa\xf0\x7a\x12\xc9\x05\x94\x79\xcd\x61\xc6\xc0\x47\x13\xc5\x45\xe7\xac\x20\x28\x28\x59\xf9\x0f\xbb\xae\x97\x59\xdd\x07\xa2\x78\x0f\x85\x37\xdb\xb3\x0e\xd9\x91\xb2\x10\xac\xce\xa4\xbb\xd3\x5f\x96\x34\xc3\x36\x7c\xaf\xc7\x81\x41\xcb\x3f\xc7\x1a\xf3\x9b\xb6\x12\x50\x4c\xb4\xcc\xf2\x77\x6c\x94\xd2\xcd\x4d\x6d\x1c\x0c\xec\x74\x62\xba\xfa\x24\xe0\xbc\x11\xd3\x26\x17\x34\xb8\x03\xd2\xc3\xc7\x3b\x31\xa4\xbe\xbe\xcd\x2c\x78\x2b\xe1\xd3\x46\x1e\x0a\x06\x3e\x2d\x01\xb8\xf9\x48\x21\x0c\x78\x90\xf0\xc9\x5a\x7f\x7f\xbc\x07\x0e\x76\x38\xbc\x16\xcb\x00\x1f\x24\xd5\xae\x3c\x4c\x80\xbb\xca\x95\x82\xb3\x0d\xc0\x07\xcd\xbd\xfb\x14\x7e\x0d\x40\x8f\x56\xf9\xba\x87\x9f\x9f\x27\xf1\x84\xbf\x42\x8b\x54\xc9\xa6\x60\x54\xc4\x37\xe6\x59\x17\xba\x16\x7a\x54\xa6\xf8\xc6\x4c\xcd\x54\x63\xfb\xcc\xe2\x7a\x3b\x93\x26\x72\xad\x7e\xf2\x8a\xfd\x0e\x28\xe1\xdf\x4c\xec\x96\x7e\x36\x38\x01\x21\x50\x84\x45\xe8\x87\x0b\x2e\xbc\x3e\xcd\xab\x26\xe3\x51\xee\x92\x5d\xd2\x1f\x4a\x36\x91\x55\xb1\xd3\x03\x6f\xc9\xcd\x79\x41\xf7\x28\x02\x79\x0d\xf6\x2d\x23\xb1\x87\xd8\x50\x4c\x1b\x6b\x63\x45\xbf\xd9\xc0\xa0\xe0\x60\x9d\x7b\xb9\x6d\x88\xec\x72\xec\x95\x53\xed\x79\xd7\xb0\xd8\x79\x0b\x48\x81\x13\x2b\x2b\xd4\x23\x02\x7d\x5c\xa9\x3e\x29\x09\xa1\xab\x92\xfa\x43\x97\xde\x2c\xeb\x36\x1d\x16\x3f\x9c\xe1\xd0\x79\x71\xc7\x16\xd4\x69\xde\x8f\x97\x4b\xa4\x77\x30\xaf\x5f\x42\x5e\x93\x17\x59\xbe\xc8\xe4\x08\x03\xca\xed\x6f\x4e\x9b\x80\xe5\x49\x49\xf4\xfd\x79\x81\xbe\x5b\x34\x57\xd9\xe6\x06\x15\x50\x9f\x8e\x3f\xe8\x45\x0b\xf5\x17\x0c\xfa\xb7\x81\x42\xd3\xcd\xde\xe8\x2c\x77\x8d\xac\x27\xe8\x34\xc6\xc3\x8e\x1a\xa5\x2a\x77\x51\x77\xda\x36\x26\x80\xcf\x8e\x39\x44\x97\xde\xe1\xab\x75\x13\xe7\xb5\x5d\x6e\x0e\xbf\x7f\xed\x83\xbe\xe3\xff\x93\x22\x4e\x46\xf3\xfe\xcb\x73\xd9\x73\x56\x2d\x5c\x9d\xca\x02\x31\x7b\x04\xdb\x5b\x6f\x1a\xcc\xe6\xb5\x71\xa5\xd1\x54\x2e\xad\x1a\xb7\x9d\x79\xa7\x0f\x65\xf4\xfe\x2d\x02\xf3\x44\xc2\x7f\x64\x5b\x02\x7a\x3a\xa3\xc6\x95\xf9\x2c\x38\x3f\xfd\x14\x82\xd4\xf0\xfc\x62\xca\x11\x4e\x96\xc6\x6d\xdc\x74\x44\x0c\x31\x10\x66\x4e\x74\x0b\xdb\x9d\x78\x0c\xd8\x2d\xeb\x08\x32\xd8\xce\x3c\x2f\xee\xcd\x8b\x97\xbd\x2a\x9c\x63\x5f\x58\x87\xef\x61\xc6\x4f\x0f\x75\x96\xa3\x98\x84\x15\xd9\xcd\x92\x2b\x0f\xcd\x03\x43\x4e\xa1\x9b\xe7\x75\xbb\xa7\xe1\x5e\x58\x1e\xd7\x0f\xcb\xe3\x22\x09\x14\x8a\xdc\x4a\xc0\xe0\x3e\x1c\x1c\x87\xe9\xd7\xa5\x47\xd6\xb4\x88\x32\xfb\x23\xe6\xd0\xa2\xd2\x71\x3e\x04\x47\xfa\x28\xcd\x52\x68\xfb\xf2\x54\xd8\x46\xf2\x8d\x30\x06\x53\x41\x3c\x69\x44\x36\x0c\x52\xb9\x8b\xc7\xb2\xc4\x4d\x12\x84\x23\x24\x1a\xf8\x03\x3d\x0d\xdc\xa9\x8e\x71\x67\xf6\x34\x7c\x7b\x3f\x48\x9b\x98\x17\x3a\xc3\xfe\xdd\xf2\xba\x76\x37\x60\xff\x59\x65\x5d\xa2\xe2\x55\xbe\x59\xa1\x8d\x03\x8c\x00\xa5\x30\xad\xef\xc6\x3e\x73\x62\xe2\x1a\xcb\x41\x59\xd7\xd5\x99\x59\xfa\x8a\x30\xb8\x2d\x61\xfa\xce\xdf\x8d\xfd\x4c\xfb\x34\x0a\xd7\x26\x7a\x43\xda\x1f\xc1\x06\x48\x55\x8b\x98\x46\x11\x5b\x83\x17\x8f\xcd\x0d\xcc\x05\xc3\xef\x71\x54\xdc\x9a\x1d\xb8\x57\x08\x6b\x9f\x32\xff\xb6\x47\x6a\xe0\x3c\xba\x55\x1b\xf7\x73\x09\x83\x75\xc4\xbc\xc3\x49\x84\x5d\x3c\x65\x72\xc3\x11\x19\x4b\x70\x77\x1f\x27\x7f\xed\x6c\x2f\xa5\x57\x75\x96\x3e\x1e\x11\x83\xb9\x65\x0c\x9e\xfb\x11\x75\xb1\xf6\xd7\x26\x29\xe8\x6f\x16\x66\xbd\xf3\xa7\x65\x26\x78\xb7\x68\xb1\x1e\xe8\xbe\xef\xaf\x25\x1c\x24\xd5\xf2\xf5\x53\xb8\x34\x23\x9d\x21\xfe\x4d\x34\x20\x68\xbb\x99\xb5\xb6\x68\xec\xd5\xb9\x92\xfb\x0c\x33\xc1\x74\xb7\xf3\x0d\x80\x2c\x39\x38\x0f\xa9\x3e\x1a\x17\xa9\xf9\xc5\xd7\x2e\x0d\x52\x42\x77\xd5\x09\x6e\x6e\x10\xbf\xa8\x32\xe8\xf2\x8f\x22\x69\x37\x8c\x94\x53\x7e\xfe\xc4\xac\x5e\x7b\x2c\xcc\xc0\xe9\x28\x92\x96\x93\xec\xc7\xce\x07\x0c\xe9\xeb\x93\xc9\xf4\xa6\x9a\xff\xbe\x5c\x17\xc9\x62\xfb\xa2\x7d\xfc\x82\x0e\xc6\x93\x21\x3a\xfa\xeb\x7e\xa3\xb9\xf9\x7a\xcc\x04\x82\x78\x67\xf1\x8f\x50\x1c\x9f\x0f\x8a\x68\x05\xe3\xbc\xa1\x5c\x66\xa5\x8d\x23\xd0\x6b\xef\xa9\x5c\x9a\xb0\xbe\x6d\xff\x69\x4e\x48\xce\x0b\x7b\x7b\x95\xf4\xc6\xda\x21\x0a\x9c\x6a\x51\xa9\x6f\x29\x5a\x76\x3b\x39\x31\x8e\xf5\xdd\x5a\xec\x26\xdf\xb5\xd7\x24\x33\x91\x4d\x6c\x0d\xf0\x77\x07\x62\x0f\x45\x20\x84\x9d\x8d\x3e\xee\xb4\xbf\x6a\x97\x3b\xce\x15\x94\x9e\x4b\x3a\x7d\xf2\xa0\xc8\x82\x9a\x53\xcf\xcd\xdb\x4a\xeb\xc0\x6b\x8f\x3b\x48\xb9\x0e\x5c\xc8\x2f\xe0\xa7\x9e\xbb\x88\x6b\x3a\x04\xd1\xb8\x9b\x91\xc7\x7f\xa2\x04\x88\xec\x25\xdc\xd4\xda\x24\xce\x60\x60\xc6\x1c\x18\x91\xa4\x0f\xf7\x4f\xe4\xbd\x00\x2f\xdd\x25\x29\xa5\x54\x00\xcf\x4e\xc9\x8d\x3d\x48\x11\x57\xe2\xf2\xd9\x23\x06\x0c\x45\x77\x54\xd8\x7e\xe3\xd7\xd3\x8d\xa8\x7c\xef\xfc\x84\xae\xe4\xf8\xc7\xc3\x7c\xab\xdd\xc2\x9d\x18\x55\x5d\x41\x21\x8e\x75\xe6\x91\xb5\x09\x95\xdd\x12\x48\x94\x4c\x7e\x5b\x6f\xb2\x51\xd7\x2a\xdb\x89\x55\x5a\x03\x47\x16\x7c\x97\x0d\x9f\x7b\x58\x0c\xa3\x16\xe1\xd6\x3b\xb7\xf9\x5d\x8f\xad\x4f\x1a\x62\xe8\x2b\x58\x99\xd3\x4c\x89\xcb\xad\xc4\xce\x3c\xde\x89\x94\xa8\xe5\x15\xa3\xbc\x24\x35\xdd\xbd\xaa\x79\x5e\x6a\x94\x6f\xb6\xb3\xb0\x5c\x07\x44\xc4\x7d\x3a\xff\x6c\x1e\x3d\xf3\xe9\xe1\xf5\xb9\x86\x76\xc9\x31\xac\x5f\xbc\xde\x11\x0e\xad\x74\xab\x9b\x89\x68\x58\x0b\x84\x77\x62\xde\x34\x6b\x9e\x65\xf4\xc6\xfe\x6d\x4e\x54\x64\xcd\x9a\xb8\xff\xdd\x27\x8b\xb2\x12\xdc\xa8\xfb\x57\x14\x4e\xf7\x28\xfe\x82\x75\xf7\x84\x2f\x04\x2d\xd9\xfd\x48\xc2\x10\x48\xfa\xe2\x81\xfe\x9c\x67\xed\x96\x6f\x76\xef\x1e\x13\xce\xc5\x12\x01\x34\xb6\x8b\x87\x88\x79\xed\x88\x0d\xdf\x8d\x13\x3a\x88\xc5\xe0\x41\xe2\x27\x97\x3d\x5e\x50\x5f\x2f\x59\x66\xd2\xe3\xcf\xdb\x3c\xcb\xc3\xdc\xf6\x1d\xe6\x0b\x3e\x83\xf5\xf2\xd4\xfc\xf1\x99\x1a\x08\x7c\xb0\x1f\x00\x84\x4f\x3d\xf2\x5b\xac\x05\x7b\xdd\x29\xaf\x39\x7b\x70\x65\xdc\xf0\x69\x3b\xd7\xe6\xa9\xe2\x01\xcf\xa4\x32\x2c\x0e\x4e\xba\x2a\xd5\xdb\xcb\x4c\x15\xed\xf0\x39\x55\x79\x23\x40\xd1\x4f\x89\xe2\xf8\x90\x0f\xec\x8a\xc4\x3a\xf9\x3a\xc2\x0c\x2a\xa4\x27\x43\xde\x79\x70\x60\xa3\x10\xcd\x11\xb2\x9d\xd3\xce\x23\x1e\x15\x50\xf5\x3f\xa8\x5c\x86\x45\xb2\xab\x98\x51\x0d\x8b\x6a\x0b\x37\x5a\xd9\xa6\x1f\xf4\xe5\xec\xeb\xe1\xcd\xa3\x5d\xfe\x23\x5f\x30\x17\x51\xe8\x88\xc0\x08\xca\xcb\xdd\xfe\x1f\x7c\xa5\xc6\xa9\x31\x40\x71\x2d\x27\x0d\xe0\x6b\xe2\x90\xc2\x66\x9a\xf6\x5b\xee\xc8\x1e\x96\xd0\x35\x0d\xc1\x99\x10\x87\xb8\x83\xbb\x0d\xb7\xff\x9f\x4b\x0b\x26\x16\x64\x98\x1e\xce\xe6\x73\x22\x80\x26\xef\x88\xc6\x92\x27\x9f\x47\x2e\x73\x5b\x5e\xbb\x12\xd8\x88\xf6\x56\xb9\x1d\xbe\x70\xd6\x39\xac\xf8\xca\xdc\x0d\x5f\x49\x2d\x33\x2c\x9c\x96\x0f\x3d\x5c\x50\x20\x1d\x83\x28\x59\xb6\x0f\x84\x3e\xd3\x0e\x10\xf7\xaa\xb8\x9a\x6d\x08\x1c\x97\x1c\x38\xb8\x92\xf6\x94\x0b\x9e\x53\x72\x8f\x7b\xa7\xcf\x97\x20\x09\x4e\xc3\x7f\x4c\xd8\x45\xa9\xb3\x9f\xbb\xc8\xf3\xb2\x8d\xc8\xae\x30\xca\x3e\x77\x25\x20\xec\x25\xfc\x7a\x7c\xc9\xc2\xee\x5c\x38\xa4\x3a\x71\x6f\x2b\x2a\x94\xb2\x39\x0a\x04\xab\x62\xa0\x4e\xbd\xc2\x56\x78\xe5\x3e\x11\x87\xd1\xdd\xe1\xf2\x9f\x66\x8b\x1b\x7a\x41\x18\xeb\xf9\x9f\x99\xe8\x61\x73\xc2\x9f\xdb\x1f\x97\xa0\x65\x02\x81\x41\xd1\x4d\x03\xdc\x7a\x16\x61\x2b\x9b\x0c\x1c\xac\x20\xd4\x8a\xf4\xfa\xcc\x54\x56\x70\x2b\x38\x02\x52\x40\x8a\x7b\xee\xfb\x0f\x94\xfa\x68\xd7\xc9\xb3\x0b\x6f\xb7\x72\x87\xc0\xfd\x1e\x0a\x78\x98\xe8\xca\x43\xb7\x70\x4a\xb4\x23\xf7\xe1\xe7\x8a\xfd\x8e\x7a\xfb\x2c\x2a\xb8\x7b\x46\xaf\xd4\x8b\x33\x54\x5c\xdd\x5c\xf8\x9c\x90\x0e\x22\x95\xcc\xa6\xda\xe3\x4a\x91\x69\xa4\x1f\x20\x3e\x0b\xd8\x4a\x16\x8e\xb0\x79\xd4\x2d\x95\x49\x22\xf5\x6d\xcd\x3c\x17\x94\x49\x99\x41\xd8\xe5\x27\x86\x47\xef\x2a\x05\x9e\x12\xee\x20\x7a\xd2\x3f\xe2\xa3\x8d\xff\x16\xce\x7c\x89\x74\x4c\x2f\x5e\xad\xd6\xaa\xb9\x33\x4c\xae\xe4\x71\xb5\x30\x8a\x4c\x34\x89\x05\x87\x93\x76\xb3\xa5\xe6\xb7\x4a\xf5\x57\x73\x89\x29\x17\xd9\x66\xcb\x8f\xee\xb3\xe4\xf0\x9e\xb1\xed\x8f\xd8\x0e\xb2\x57\x9c\xf0\x91\x73\xb8\xcb\x30\xfd\x64\x09\x07\xfe\x25\xc8\x8f\x50\x61\x4a\x50\x99\xc2\x8e\x6d\xde\x22\x46\x10\x1e\xc7\x7c\xc4\xef\x9b\xd6\xe2\xcd\x0a\x1c\xd1\xc2\x13\x8b\x25\xd7\xdf\x1d\xf4\x1f\x0f\xfe\x26\x94\xa3\x0b\x69\xaa\x7b\xd8\x57\xd4\xa5\x19\x2d\x4f\xb5\xf9\xfe\x16\x19\xe8\xe7\x12\x74\xb8\x2c\x1f\x9e\x29\x32\xf2\xec\xec\x28\xfc\xc4\x5f\x26\x29\x0e\xde\xa8\xfe\x1e\x8e\x77\xcc\xfe\x51\xe7\x2b\xf9\x09\xd2\x62\x9a\x69\xd5\xa6\x6f\xca\x34\xf8\x83\xf7\x1f\xd5\x98\xb6\x0d\x31\x3b\xce\x7e\xd4\x12\x33\x44\xd6\xfd\x61\x51\xea\x1a\x6d\xdf\xe2\x95\x0e\x99\x45\xa8\x76\x99\x86\x1a\x83\x3c\x68\x1b\xbf\xb3\x1c\x2b\x8e\x30\xf4\x8b\x4c\x7f\xdb\xfe\x6d\xff\x29\xd2\x5e\x0a\x8d\x81\x7b\x45\x8c\x04\xdd\xf6\xcc\x57\x61\x2d\x86\xb4\xcf\x8b\x5f\xaf\xfc\xbf\xfe\x9b\x7b\xed\xf7\xa4\xb7\xd9\xd5\xb7\xd3\x8b\xb8\x8e\x83\xfc\x6c\x96\x70\x93\xec\xcb\x1e\x6c\x1f\x44\x18\x5d\x9c\xce\x41\xe4\xed\x7d\x43\xb6\x1a\x47\x7b\x67\x8f\xfb\xfb\x92\xa9\xb1\x66\x8b\x89\xe0\x06\xcc\x6d\x8a\x02\x37\x26\x9e\x02\x56\xde\x0b\x34\x41\x5b\x45\xb0\xfd\x73\x0a\x62\x79\x91\xd9\x51\xe5\xfb\x27\x3a\xf0\x42\x5b\x63\x20\x8b\xfe\x43\xe1\x7c\xad\x53\x81\x74\xb9\xa5\xf5\x19\x2e\x97\xe2\x27\xdd\x62\x8a\x47\x06\x3a\x19\xf6\x0b\x5f\x11\x90\x11\xb9\xc7\x76\x24\xfd\x13\x97\x23\x56\xef\x03\x3d\x40\xe6\x41\xf9\xf9\x15\xff\x92\x4e\xc3\x04\x43\x28\xcc\xac\x29\xe2\x29\x1b\x96\x77\xdc\xdc\xef\x38\x2b\x5f\xb2\x7f\xc6\x71\xc2\xaf\x81\xe1\x17\x21\xfa\x70\x02\xc1\x38\x4a\x1e\x5f\x6f\x69\xc8\xc3\x53\xf9\x52\x33\x7a\xa5\x7a\xac\xdc\xc1\xc0\xaa\xc8\xed\xd3\x01\xc6\x58\x09\xc7\x62\xfd\xc7\x9f\xb8\x5a\x1e\x81\xd5\xc5\xcd\xd5\x8b\x84\x8a\x22\x5d\xbc\xf7\x57\x52\x4c\x71\x02\x72\xea\x8e\x77\x22\xeb\x2f\x9d\x57\x09\x45\x67\x80\x3a\x69\xe7\xf5\x00\xa9\xb3\x57\xf4\x94\xce\x40\x48\xaf\x90\xb9\xef\xf7\x96\xe7\x85\x8c\xbd\xb2\xc4\x0f\x49\x1f\xfb\xec\xde\xc1\xf2\x3b\x92\xed\xf7\x16\x85\xb4\xdb\x6e\xab\xbb\x7e\x07\xa2\xe1\xb7\xea\xae\xad\x7e\xf1\x89\xbe\xf6\x7f\xd9\x43\xec\x21\x76\xc3\x99\x18\x27\x13\xa8\x45\xb9\xe7\xa8\x6d\x4f\xff\x71\xc7\x42\xa4\x05\xfe\x10\xc9\xad\x9c\x6e\x4c\x36\xdc\x5d\x7e\x81\xf0\x32\x9b\x58\x49\xd1\x5c\x5b\x9c\xcd\xca\x53\x78\x45\x07\x23\xaf\xa0\xa5\x44\x78\xc2\x30\x84\x59\xd0\x1a\xbd\x12\x54\x0f\x39\x47\x46\xd0\x0f\x9c\x4f\xc4\x59\xfa\x92\xff\xc9\x8a\x47\x32\x22\x8d\x32\x28\xd1\xb5\xea\x33\xf6\xdf\x77\x18\x7a\x59\xa9\xa7\x28\xd7\x14\xdd\xcc\x1c\x1d\xe4\xbc\x51\xda\xe5\x71\xd8\xe4\xcd\xa5\x83\x0f\x0b\x4b\x20\x38\x7a\xd1\x9c\xb9\x46\x9e\xab\xc6\x77\x7f\x2d\x15\xe1\x2f\x91\x74\x1a\x16\x4c\x53\x33\x6a\x70\xdd\xfa\x36\x9c\x6d\x5a\x58\x85\xac\x77\x0c\x12\xca\x0a\xcd\x99\xe2\x7a\x99\xd2\x18\x61\xf4\xc3\xe0\x57\x1c\xdc\x86\x4a\xb3\x1b\xb2\xe3\x4e\x6c\x6d\xab\xb0\x4e\x0a\x6f\x3c\x03\x8c\x95\xb9\x1d\x48\x2f\x72\x34\xbe\x2d\xbb\xe1\xe6\x2c\x31\x85\xb5\x36\x26\x60\x7e\x86\x3c\xeb\x16\xf0\x06\x89\x1b\xe2\xd4\xd1\xbe\xff\x09\x27\x5b\xa2\x5a\xcf\xd4\x4a\x77\xbb\x91\x5d\x52\x8a\xb3\xd0\xeb\xf4\xc2\x9d\x68\xa8\x41\x91\x1e\xc0\xc9\xa4\x9c\xe2\x50\xd6\xd4\x10\xcf\xce\x36\x5b\xff\x38\x69\xe8\x30\x28\xb5\xdb\x97\xa2\x92\xd8\xc2\xa9\xc6\x47\xe8\x6b\x7b\x69\xdd\xed\x56\x09\x6e\x05\x36\xf6\xc0\x68\x22\xbe\xa8\xca\x25\xc3\xe5\xaf\x0c\x5b\xa9\x9e\x14\xf4\xf8\x7f\x4c\x9d\x0d\x41\x7d\x8e\x3b\x96\xd6\x42\xa9\x05\x41\x04\xd4\x83\x27\xb9\x68\x33\x1e\x05\x83\x3f\x9f\xb7\xf4\x17\x72\x1e\xb3\xf2\xa5\x89\x2c\x30\x3a\x09\x82\x72\xcb\x2b\xe9\x00\x2c\xf1\x73\x5b\xda\xc5\x7b\xec\xea\xda\x45\x36\x59\x79\x89\x7d\xe7\x86\xaf\x10\x9e\x2d\x94\x9b\x8d\xa1\x2a\x1b\x02\x48\x6f\xa6\x1f\x2d\xcb\x0f\x80\x3b\xcf\x82\x3c\x54\x01\x42\x42\xf1\x61\xb9\x1e\xfe\xcb\xe9\xc3\xa8\x4c\xd4\xb8\x03\xcf\xa6\x64\xa5\x15\x21\x4a\x3b\xe2\x07\xb1\xf3\x00\x6d\xf2\x0b\xe7\xf6\xad\x32\x33\xc2\x17\x7c\x53\xc8\xfe\xed\x92\x97\x70\x63\x23\xb0\xf3\x86\x2c\x81\x1c\x3d\xeb\xa5\x7f\xee\x45\xea\xb4\xde\x4d\x2f\x9b\x08\x2f\xd8\xa3\xca\xad\xd7\x2f\xb8\xdf\x6e\x5e\x16\xcd\xb7\x3c\x8a\x2e\x86\x8d\x5d\xc0\xb0\x1f\x0e\xb3\x6f\x3d\xfd\x09\xae\xa3\xfe\xba\xe4\xcb\xd5\x59\x6e\x30\x92\x6e\x29\x4d\x4e\x67\x58\xfd\x7c\x8f\x44\x96\xc1\x8e\x2f\x99\x5a\x85\x8e\xb7\x31\xf1\x64\x6a\x8f\xb7\xbf\xf9\x23\xe5\x67\x16\xd7\xc4\xae\xb8\xac\xd5\x16\xac\x93\x88\xc0\xb9\x5a\x3e\x06\x22\x47\xa3\xc3\xb8\x0f\xcd\x93\xce\xe6\x49\x74\xee\x39\x72\x9f\x4e\xb4\x99\x7e\xa2\xcc\xb5\x72\xde\xab\x84\xab\x93\xa1\x66\xe7\x74\x47\xf2\x94\x5b\x9d\xaa\x13\xca\x92\x88\x9f\xb6\x7d\x47\xe4\x8e\x22\xd5\xbc\x2c\xf5\xa6\x05\xa1\xe4\xbf\x76\x64\x6b\xae\x26\x25\xd2\x75\x30\x3c\x67\x4f\x82\xd3\xe8\x2b\x45\xef\x19\xb4\xf0\x21\x3f\x6f\x1e\x56\x8e\x6c\xf8\xf9\x74\xdb\x51\xed\xbd\x86\x55\x04\x4a\x52\xe5\x00\x79\x15\x45\xdc\x39\x61\xf8\xb9\xdb\x50\x18\x06\xb0\x94\x16\x03\x40\x9b\xa6\x23\xc5\x67\x80\x7c\xfd\xac\x28\x3d\xb5\x98\xd9\x71\x4d\x38\xb5\xdf\x8a\xa1\xdb\x6b\x90\xe3\xf7\xba\xef\x82\xaf\x24\x96\x29\xca\xf5\xb1\x86\x3e\x18\xe4\x11\xe7\xc3\x75\xd2\x88\xe0\x92\xb7\x9d\xec\xa2\x40\xb2\xf7\x5f\x22\x79\xd9\x0e\x16\xea\x03\x27\xdb\x8a\xb0\xa2\x87\x37\x28\x92\xb3\x7c\x82\xf2\xad\x00\xeb\xb5\xb6\xc6\x42\x56\xf9\x6b\x7d\x3e\x93\x7f\x49\xd1\x49\xb9\x96\xad\xb9\x29\x84\x5a\x70\x45\x21\x5a\x35\x55\x08\x43\x84\xbe\xff\xed\xbd\x6b\xb3\xd9\x5f\x09\xe4\x84\xb8\x2f\xa4\x3c\xa9\xf7\x53\xdf\x13\x5a\xd8\x8a\x60\x44\xd3\x70\x63\x97\x13\xf2\x0a\x58\xf2\x14\x5c\x46\xed\xb0\xb6\xbd\xd9\x6d\xae\x99\xf2\xae\xb6\x63\xe2\x17\x93\x99\x6c\x9d\x7d\x72\x33\xc7\xf9\x8e\xe4\x61\xb0\xc8\x39\x88\xfe\xbb\x9d\x7f\xf4\x27\xe8\x0e\xe1\xe6\xde\xad\xdb\xd9\x57\x4f\x1e\x82\xd4\x30\x2b\x77\x7c\xaa\x1c\x1b\xd4\x21\x8e\x31\x64\x90\x3d\x7c\x80\x3c\xb7\xc9\x71\xe4\x33\xda\x55\xf4\x55\x6c\x81\x08\x9e\x76\x20\xc2\xa3\x40\x33\x88\x77\x90\xc6\xc5\x95\x04\xed\x5c\x8c\x04\x70\x1b\x23\x0b\xd3\x2e\x1d\x8a\xcd\xec\x95\xf3\x20\x2e\x6f\x49\xec\x4f\xd5\x28\x18\x0e\x0a\xfe\xa9\x06\x41\x83\x1d\xeb\x9c\xc9\x54\x02\x1c\x79\x2e\xa0\xce\xfb\x26\xff\xc4\xc8\x77\xd1\x42\x04\xe1\x67\x59\x44\xcb\x78\x5a\x89\x74\x90\xd5\x83\x1c\x4d\x07\xa1\x90\x99\xa5\x61\xb0\xda\x98\x29\x46\xc1\xf9\x59\x82\x40\xae\x4e\x70\xa8\x30\xe5\x89\xc5\xa8\xb9\x05\xd4\x10\xec\x60\x36\xe1\x57\xff\x02\x52\xc1\xb3\x1f\xda\x46\x62\xf7\x2a\x6c\x69\xc9\xf7\xc9\x9e\x4d\x4d\x7f\x2a\x99\xa1\xf6\xf7\x25\x75\x65\x64\x4e\x3f\xfc\x0c\xe5\x80\xac\xe7\x3d\xec\xcd\x88\x63\xcb\x8d\x67\x5e\xdf\x24\x0c\xd5\x96\x0b\x88\xbb\x2f\x3c\xcf\x77\xf2\x1f\x21\x0f\x12\xed\xfc\xfe\x99\xd2\x28\x86\x7a\xed\xc2\x9c\x66\x6d\xe7\x50\x27\xc0\x06\x98\x96\x42\xaa\x49\x34\xbf\xb1\x6d\xd0\xe6\xa1\x71\xbc\x9b\x3b\x34\x30\xe9\xb1\xf2\x94\xf4\x1c\x5c\xc9\x97\xbb\x22\x81\xf7\x3f\xf2\xdf\x0e\x26\xa6\x14\x5c\x17\xda\x41\x58\xdf\xa9\xce\xe5\x68\x0d\x4b\x17\x22\x98\x2e\x49\x2b\x6d\xc7\xa5\x57\x2b\x00\x12\x44\x80\xf1\x28\x08\x3f\x0c\x97\xfc\x9f\xb3\xda\x1f\x3a\x0e\x95\x82\x7d\x87\x4a\x42\xb6\x07\xef\xcf\x36\x13\xc5\x02\x52\xa6\x83\x8f\xca\x91\x17\xc1\xb2\xf2\x45\x3c\xb7\xe3\x65\x71\x93\xbd\x44\x0c\xe4\x6c\xf9\x37\xa6\xb0\x0f\xb4\x59\x5e\x77\xeb\x66\x18\x6e\xe6\x10\x9a\x5d\x6a\xb2\x6c\xbb\xf2\x7b\x8e\xc2\xfd\x4a\x1c\x4d\xe8\xb5\x3f\xdf\x32\x4e\x86\x8d\xb1\x06\x78\x3c\x0a\x85\x8d\xd9\x7a\xd0\x8c\x62\x8d\x63\x2f\xf7\x8d\x9d\x4e\xc8\x6b\x27\xa5\xc0\x2d\x26\x74\x7a\x55\x3f\x0c\xce\x99\xac\x94\xb3\xac\x6a\x8b\x9a\xe9\xaa\xfd\x5a\x5d\x6c\x67\xe6\xae\x7b\x06\x26\xe2\xd3\xe7\x60\x50\xae\x61\x36\x02\x6f\x87\x62\xcd\x1f\x4f\x93\xae\xdd\x90\x58\xf7\x93\xb0\xfc\xc3\x6d\x6e\x98\x2a\x65\x97\xa3\x48\x49\x83\xd4\x2b\xc8\xdd\x89\xd5\x44\x1e\xd2\x01\xf7\x8d\x93\x6d\xd3\x1d\x4d\x18\xd8\xeb\x1c\x18\xec\x37\x5f\x9e\x1d\xe2\x4c\xff\xc4\x4f\x4c\xbb\xd7\xeb\x25\xa6\xa6\x1d\xe1\x67\x21\x1f\xf3\x48\x03\xdd\xbc\x77\xeb\x22\xc2\x87\x10\x85\xd3\x45\x4e\x7b\x7d\x73\xa4\x58\x2f\xbd\x10\xee\xa2\x29\xb0\xab\x9e\x82\x25\xac\x50\x57\x4f\x25\xe9\x1b\x21\xb0\xfb\x94\xcf\x36\xca\x77\xbf\x7c\xb6\xca\x93\x0a\x9c\x6b\x65\x94\x58\x13\xab\x21\x0b\x49\x3f\xd6\x87\x89\x11\x8e\x00\xc7\x38\xa3\x38\x2f\x5a\x5d\x1d\xf6\xf8\x7f\x4c\xac\xf2\xe3\xa4\xef\xd9\x29\xb9\xcf\x05\xe9\x9a\xd7\x79\x33\xf4\xca\x3e\xa1\x73\x74\xf5\xf4\x59\x2e\x66\x21\x67\x08\xc0\x55\xf7\xb5\x49\x1e\xba\x51\x0c\x8d\xa3\xc9\x93\x20\x97\x4f\x17\xc8\xd1\x22\xfb\x64\xb8\xa5\x04\xf1\xc5\x11\xb3\xf1\x0c\x05\x14\xb6\xa1\x87\x0f\x52\xae\xb2\xea\xbc\x0a\x03\xe6\xf9\xd6\x0d\x34\xab\x8c\x42\x98\x8e\x2c\x0a\x17\xb7\x16\xc5\x7c\x48\x34\xa8\x99\xa7\xd4\xfc\x4f\xf7\xe2\xb9\xf6\xe1\x7f\xc0\x0f\xd4\xd6\x79\xb9\xfc\x07\x77\x7d\x3c\x72\xa6\xf9\x97\x9f\x7d\x4d\x04\xc5\x82\xac\x87\x55\x90\x59\xa6\xfc\xab\xb9\x91\xcf\x2c\x87\x66\x5b\x2e\x4a\x8b\xcd\x0a\x2e\x85\xd1\xcf\xff\x4f\x68\xea\xcb\xbc\x89\xe5\xd4\xee\x3d\xb8\x6a\xb1\xc3\x8b\xe2\x75\x52\x12\x37\xea\x97\xb8\xf9\xec\x80\xfb\x51\x70\x47\xb1\x32\xc7\x72\xc8\x32\x67\x2c\xb5\x88\x22\x2a\xe5\x23\x56\xf6\x2b\xa2\xe7\xe3\xf1\x26\xad\xd9\x98\x64\xa6\x32\xb2\x68\x47\x33\xc8\x9d\xc5\x87\xf3\xed\x42\xb4\x63\xc4\x19\x9a\xcf\xd6\xcd\xd9\x4a\x60\x1b\x42\x32\xc9\x98\xb4\xbe\x51\x1c\x82\xe7\xe2\xe9\x1b\x51\x89\x3c\xdd\xf3\x58\x21\xb6\xbc\x99\x9e\x90\xa9\xfa\x23\x47\x6a\x59\xf6\xea\x39\x66\x6d\xd6\x8a\xea\xc8\x1c\x94\x3b\xed\x63\x38\x29\xb1\xce\x33\x5c\xf1\xef\x83\xc1\xe1\x3e\xd9\xd7\xae\x00\xb6\x7f\xbd\x68\xe0\xe8\x9b\x17\xa5\xaa\x47\x04\x88\x1d\x5b\xc4\x04\xca\x46\x1d\xfe\x8c\x6e\xe5\x8e\x86\x90\xae\x74\x3d\x50\x58\xb6\x08\xde\x1b\xae\xe1\x3f\xeb\x00\xa0\x47\x27\x91\x56\x75\xca\xa7\x06\xe3\x1a\x9d\x7d\x68\x5e\xc3\x6f\x76\xe3\x44\xd1\x5d\x8b\xe4\xea\xb8\x84\x22\xab\xcb\xdf\x14\x2b\x61\x7b\xd7\x25\x41\xff\x4d\x27\x25\x9e\x89\xa7\xa2\x2f\xc0\x63\x09\xa2\xd4\x4d\x61\xa8\xe7\xe7\x86\xa5\xc8\x71\xaf\xe2\x47\x45\xb3\xd1\xc9\x75\xb0\xb3\xca\x23\x93\xe1\x82\x2d\x25\x64\x05\xa9\x89\xf9\x35\x72\xc5\xed\xd0\x91\x35\x63\x7f\xe7\x10\xd4\x42\x0c\x0a\x8f\xb0\x77\xfe\x16\x3b\x53\xf1\x15\xdf\x14\xda\x0c\x8c\xf6\xc7\x18\x5f\x7f\x70\x2f\xd1\x88\xf1\x53\xbd\x20\x7f\xdf\xba\x90\x50\x67\x91\x9a\xfa\xae\x7f\x97\xd5\x14\xbd\xd4\xb5\x72\x92\x2c\x8b\xba\x7d\x98\xba\x21\x3d\xc0\x5b\xc9\x7c\xd6\x66\x7e\xe6\x29\x21\xca\x98\x4f\x8b\x6f\x45\xaf\x7a\x31\xeb\x50\xba\x58\x68\x25\xd9\x56\x3b\x23\xcb\x0f\x40\xdb\x98\xcb\x7e\x52\xd4\x7f\x1d\xa5\xf9\xcb\xc5\xd8\xf3\x0a\x6f\xbe\xcb\xfe\x70\xc7\x3d\xd9\xc5\x91\xaf\xfb\x74\xdf\x9f\x0b\x81\x93\xb2\xdf\x3a\x3f\xf4\x07\xb0\xee\x56\x2e\x4c\xde\x30\xf2\x98\x04\x76\xab\xd5\xd6\xd0\x00\x68\xb4\x1e\x24\x6d\x69\x24\x14\xc2\x2a\x6b\xed\xc2\x5a\x60\x72\xd9\xa2\x83\x89\x7a\x94\x84\x17\xf2\x3e\x1d\xd1\xc8\xa9\x57\xf7\x87\x76\xae\x8d\x78\xcf\x20\x0c\xa1\x63\x8b\x5e\x91\xdc\x2c\x6f\xb6\x3c\x40\x09\x1e\xe7\xfe\x81\x54\xf3\x02\x70\x8e\x48\xfe\x3a\xd0\x1e\x72\x94\x34\xea\x6c\x74\xa1\xb4\x98\xb7\xb7\x97\xe5\xfb\x01\x56\xe1\xc3\x3b\x30\x1e\xf8\x7b\x09\xa7\xca\x32\x2a\x07\x7c\xa2\x8d\xd5\xde\x86\xab\xbb\x82\x1c\xad\xe9\xba\x69\xec\x74\x04\xb6\xb3\x27\x50\x10\x1c\x46\x86\x73\x9d\xe0\xcc\x2a\xb6\xdf\x16\x9e\x67\x1b\x25\x66\x1b\x72\x2e\xc5\xd5\x52\xea\xaa\x46\x80\x2b\x03\xe9\xd6\xba\x28\x40\xce\x4e\x11\xa6\x8c\x2f\x3f\x0b\xde\x86\x12\xac\x34\x8b\x59\xfb\x4d\x0a\x4f\x1c\x8a\xc7\xa6\xf3\xb1\x69\x16\x5c\x31\x3f\x6b\xed\x65\xdf\x9b\x87\x9d\xe6\x89\xab\xbb\xa5\xf3\xe4\x04\x46\xcb\x03\x30\x74\x0e\x6e\x14\xad\x7e\x6d\xd9\x39\x09\x06\x5a\xb9\xc9\xac\x62\xf9\xe8\xae\xb2\xe6\x87\x74\xaf\x7b\x5d\x15\x47\x67\x47\xe3\x24\x95\x9a\xad\x11\x2f\xa2\x7c\x15\xf1\x82\xab\xea\x97\xc5\xf7\xbe\xf0\xff\x25\x83\x21\x3f\x45\x9b\x5c\x72\x0e\x61\xf1\xa0\x58\x48\x58\xbd\xc8\x24\x2f\x8d\xda\xb5\xe6\x26\xd5\x9e\x85\x49\xce\x9b\x68\x0b\x41\x7b\xb0\x7b\xf4\x0a\xa9\xf0\xa2\x2a\x6d\x4e\x00\xc5\x7d\xb1\xeb\xaa\xb7\xa3\x34\xef\x93\x9f\x64\x77\xff\xd3\x01\xbb\x9e\x67\xaa\xcf\xdf\x29\x3c\x55\xc2\x7e\x93\x5b\x5d\x87\x82\xc2\x4b\x77\xff\x1e\xda\x8d\x4d\x32\x53\x08\x57\x3a\x6c\xbd\x41\x46\x3b\xec\x0a\x69\xa4\x86\xf0\x56\xbf\x39\x3f\xb5\x47\x9e\x7f\x47\x6a\x4e\xec\xe4\x31\x60\xd1\xe4\x15\x34\x2f\x05\x41\x38\x7a\x12\xac\xdb\x6b\x8d\xb1\x95\xce\xc6\xaa\x36\x64\x2c\x37\x55\xdc\xd6\x56\xaa\x61\x1d\x73\x1d\x27\x05\xd7\x8d\x76\x2d\xe9\x70\x65\xbe\xeb\xf3\x66\x75\x84\x40\xab\x07\x7d\x44\x19\x1c\xf0\xd4\xbc\x98\x15\x9f\x0c\xf8\x02\x1e\x77\xd7\x22\x76\x74\xb6\xdf\xda\x7f\x90\x71\x0f\xf6\x12\xf8\xa7\x0e\x4f\xe1\x78\x90\xe3\x36\x69\xc2\x05\x49\x84\x8e\x42\x0d\xae\xfe\xf9\x94\xd8\xbd\x03\x27\x18\x8a\xb2\x16\xad\x11\xcd\x21\x8a\xc9\x55\x6b\x12\x1b\xbe\xe9\xaf\xf9\xc7\xc2\xad\xbd\x04\xdd\xa1\xf5\x8c\x9a\x2b\xf6\x87\x4c\x71\x11\xbb\xeb\x8f\x3f\xf3\x2d\xe4\x07\x73\x85\xb8\x52\x1e\x76\x1f\x75\xdb\xc8\x74\x50\x37\xdc\xb7\xf8\x4e\x82\x45\x08\xb8\x16\xad\xc6\x27\x5f\x04\x57\xed\xc8\xe3\x97\x77\xc7\xdd\x32\x2a\xd1\xd9\xfc\x43\x95\xe3\x11\x57\x3f\xe1\xb2\xd1\xd5\x78\x66\x5d\xa5\x3d\x1a\xec\x92\xd9\x6b\xb2\xf0\xf5\x16\xd2\x8a\x73\xb1\x2b\x9a\xa7\x47\x17\x5c\xc1\x2e\x5a\xb3\x70\xbc\x21\xf5\x39\x6f\x9e\xf7\xe0\xcb\xa5\x6a\x6a\x96\x25\x7f\x69\x2a\xf2\x2e\x7d\xda\x0e\xdd\xa5\x66\xcc\x83\x4d\x55\x5d\x68\xc4\x0b\xa2\x3e\xe1\x77\xfc\x82\x52\x94\xc7\xe5\xc7\x31\xb6\x61\x35\x18\x08\x0f\x75\xa6\x33\xcc\x2e\x15\x47\x8a\xbd\x8f\x4e\xad\x40\x96\xf0\xb3\xbf\x37\xe1\x6a\x74\xa3\x9b\x46\x6f\x4b\x33\xfd\xb2\xa2\x59\x38\x2d\xa9\x54\x34\x9c\xf7\xc5\x10\x70\xed\x42\xa8\x16\x42\xef\xe3\x12\xcb\x8e\xd5\xce\x4b\xd1\x25\x2f\x22\x1e\xf6\x4a\xf9\xcd\x66\xcd\xeb\x37\x58\x1f\x1b\x5f\x93\xeb\x56\x19\x73\xa1\xa7\x0a\xfb\x67\x62\x67\xf0\x3b\xdc\xb5\x2a\x0e\xef\x5f\x14\xee\x5b\x1b\x7a\x3a\x21\xdd\xcf\x5d\xda\x4d\x5c\x95\xe6\x23\x28\xb6\x73\x04\x9f\x1e\xd3\x4d\x06\x49\x22\x09\xf1\xbc\xd1\xd6\xfa\x62\x8d\xfc\xc2\x2c\x25\xa9\x1f\xc7\x3a\x22\xeb\x42\x1b\x83\x33\xb8\xce\x8b\x48\x82\x67\x0b\x5c\x3c\xa7\x98\x46\x43\x61\xd3\x72\x80\xfc\x42\xe1\x6a\x54\x84\xf4\x99\x05\x9f\xe6\x10\x5f\x43\xd9\x49\x86\x05\xd0\x55\xc5\xaa\x1e\x4c\xf3\x3c\xc8\xc3\x83\xde\x3f\x44\x36\x37\xbd\x9f\xeb\x25\x43\xd8\x5f\x90\x6a\xb1\x4f\x91\x41\x75\x48\x3b\xee\x1e\x12\x2f\x0e\x04\xb7\xb0\xc0\x47\x24\x16\x53\xb1\x0f\x2a\x02\x5c\x90\x4d\xdc\x54\xac\x2a\xb4\xb4\x53\x5d\x57\xd2\x3e\x4a\x18\x5b\xb8\x27\x45\x6c\x7d\xde\xed\xfe\x33\x2d\xf4\xcf\xd5\xe5\xab\xb6\x37\x11\x29\xdf\x9d\xba\x1c\xd3\xc2\x31\x0e\x7c\xcf\xec\xf1\xa6\x18\x47\xe7\x8d\xdd\x75\x0f\x05\xbc\x2d\xd6\x30\xb2\x05\xc0\xe2\xc7\xfb\x57\x04\xd2\x7a\x44\x17\x7c\x0c\xce\x5d\xa5\xb6\xc0\x36\x15\x92\xb7\x93\xd8\x7c\x35\x8c\x7c\xad\x1b\x66\x49\x01\x1a\x37\xe9\x05\xd6\x58\xb9\xd1\xc5\x06\x34\xf3\x41\x1a\xf7\xc3\x0b\x02\x96\x9b\x2b\xf9\xb6\x76\xfc\x6b\xc7\xb7\x55\x27\xa1\x0f\xa8\xcf\xa2\x6b\xf7\x79\x79\x47\x3a\x09\xdd\x97\xa3\x5d\xee\xfd\xd5\xf5\x18\xc7\x68\x93\x8f\x25\xcc\x3f\xac\x25\x7e\x91\x53\xb0\x26\x9f\xce\x2f\x77\xd8\x7a\xdc\xbd\x0e\xf3\x43\x31\x91\xcb\x2f\x68\x68\x08\xa6\x77\xe3\x86\x84\xb6\x77\xf1\x11\x14\xe1\xd9\xe1\xa6\xbf\xd1\xad\x61\xd9\x2c\x4b\x88\xd9\x5e\xa6\xdd\xab\xec\xd9\x03\xdb\xe1\x84\xe4\x33\x4b\x5d\xd2\xb3\xc6\x39\xb3\xed\xc1\x85\xf9\x28\x2a\x6e\xe6\xf0\x16\xfb\x93\x1e\x10\x12\x20\xef\x5a\xd1\x52\x6b\x12\xf9\x56\x58\xca\xc6\x0a\x04\x8a\xc8\x9f\x36\x32\x11\x58\x85\xbf\xb6\xeb\x2a\xdd\x86\xe5\xc7\x1a\x8f\x84\x11\x40\x89\xa1\xa8\x44\x14\xb5\xfe\x35\xc5\xf9\x7d\xce\x2d\x89\xf6\x8a\xc6\x19\x9d\x95\xce\x6f\xec\x51\x91\xdc\x76\x8f\xd6\x86\x33\x6f\x19\xc3\x4e\xce\x02\x9c\x66\x2e\x88\xc4\x7a\x61\xba\x77\x2f\xe2\x4b\x8d\x68\x26\xfc\xd6\xf1\xaa\x9d\xfb\xd6\x98\x06\xd9\x2a\x85\xeb\x77\x10\xe3\x9f\xd6\xd9\x2f\x4d\xf1\x73\xff\x5c\x93\xad\xf9\x1d\xb9\xb3\x3e\x43\xdf\x6d\xfd\xed\xaa\x2a\x05\x31\x2b\x9a\x8f\xe6\xee\x26\xfa\xab\x28\x17\x27\x34\xfa\x01\xff\x12\x57\x65\x8e\xb3\x08\xcd\x6c\xdc\x74\xc3\x47\xa4\x95\x67\xeb\x69\x61\x4c\xe9\x6f\x99\x1d\xf4\xbb\x22\x56\x04\x0a\xfb\x79\x6d\xb7\xc6\x37\xf9\xbf\x47\xe7\x34\x60\x64\x47\x82\x2d\x12\xfa\x38\x71\xcd\x2b\x6f\x4d\xca\xda\x0f\x8d\x56\xef\x2e\x1a\x62\xc2\xbc\x39\xb5\xdc\x15\x59\x8d\x78\xeb\xc9\x3e\x57\xaa\x57\xf4\xbd\x57\x3b\xb6\x8f\x35\x87\x54\x48\xd3\xd6\xf4\x54\x86\x33\x5e\xb3\x49\x90\x2e\x0f\x7e\x9c\xd5\xde\xbb\x1e\xf0\xed\x20\xd7\x1d\x94\xe9\x18\x66\x2e\x4a\x6b\xee\x6a\xe8\xb0\xba\x3a\xc8\x80\x24\x8e\xd7\x4d\xba\x26\xef\x66\x75\xfa\xfe\xe3\x9e\x99\xee\x17\xe3\xde\xb0\xdc\x15\x64\xf9\xe1\x6b\xdf\xb5\x8b\x0c\x31\xfb\xf4\x8f\x4a\xbc\x6a\xad\x89\x61\xcb\x1b\xad\x6f\x7f\x93\xbe\xbe\xcd\xfa\xcc\x88\x97\xc2\xf9\x61\xe2\xc0\x7e\xdf\x25\x2a\xdf\x2f\xe2\xbe\xf0\xf8\xcf\xdc\xf1\x9b\xa9\x33\xfe\x08\x10\x03\x75\x72\xa2\xf6\xd4\xad\xe6\xc6\x90\xcd\x7b\xe4\xaf\xf7\xb9\x99\xa3\x82\x77\xfa\x3f\xae\xc0\xae\x51\x73\x62\x65\xb3\x34\x7f\x85\x9e\xd7\xb1\xe0\x57\xd6\xcc\xeb\x05\x6a\xb5\x3d\xde\x67\x30\x5f\xf4\x78\x2b\x43\xfd\xaa\x82\x0c\xed\x67\xcf\x72\xbb\x0b\xb6\x65\x87\xd9\xb1\xff\xdb\xd4\x32\xba\x2f\xaf\x48\x78\xbc\x26\x46\x08\xb5\x20\x3c\xef\x8b\x3d\xf3\x8c\x47\xec\x48\xce\xcc\xf1\x0f\x42\xfc\x7c\xb2\x61\xdd\x19\x1b\x75\xc2\x3d\xec\xe1\x87\x69\x48\x95\x72\xc8\x87\x7c\xdf\x13\x61\x72\xd5\x7b\x72\xfa\x25\xa7\x7e\x96\x1b\x26\x9c\x8d\x48\x89\x81\x53\x0a\xa1\xa6\x23\xac\xca\xd0\xca\xa7\x50\xa3\x7a\x34\x25\xc7\x8e\x9e\x1d\x11\xc2\xd5\xc8\x99\x39\x52\x59\x4e\x0d\x6e\x6c\x1b\xe7\xc8\x03\x3d\xac\xce\xb7\xb0\x13\xc3\xd1\x47\x38\x18\xef\x2d\x4f\xb7\x5a\x2e\xd2\xb4\xf7\x72\xf6\x25\x42\x86\x76\x2b\xcd\x0f\xd2\x21\xdf\xfe\xff\x23\xeb\xc3\x4d\x70\xef\xce\xf4\x30\x8c\x18\xa7\x70\xee\xb3\x3d\x9d\x57\x31\xb7\xd6\x4a\xc8\xa7\x72\x77\xa3\x75\xbb\xdc\x48\x71\x6f\x10\xdf\xae\x63\xfc\x75\x70\x42\xf1\x33\xe9\xde\x7a\x06\xe2\xd5\x77\x47\x9f\x0d\xd4\x80\x5b\x28\x5d\x35\xfb\xb3\xb3\x95\x23\x48\xbe\xd3\x6b\x91\xe8\x15\xf4\xb4\x42\xa5\xff\xba\xf2\x33\xf6\x9c\xfe\xa1\xe2\xc7\xd5\xb8\xfe\x83\x7b\xae\xbe\xb3\xbb\xdd\xcc\x83\x9d\x33\x4f\x40\xef\xf3\xc2\x41\xb0\x69\x67\xd6\x5e\x64\xb8\xb5\x0f\x38\x1c\x86\xf0\x99\xdd\x70\xc3\x04\xed\xcc\xe4\xce\xb2\x02\xc1\x26\x6b\x27\x7c\x18\x97\x7a\x07\x47\xff\xac\x1f\xe6\x4c\x9c\xae\xa3\xb2\x1d\x90\xd9\x12\xd9\xdd\x4e\x96\xdc\x71\x6a\xa9\xa3\xcc\x16\x41\xdf\x84\x9b\xe9\xc5\x32\xd1\x0e\x51\xba\x64\xb5\xa6\xd7\xb7\xb7\x99\xfb\xa4\xbb\x65\xcd\x3c\x5b\x97\x8a\xbe\xeb\xef\xe1\x78\xb2\x20\xe4\x96\x42\x3f\x2b\x5b\x6b\x0e\xc1\x8e\xf5\x25\x62\x09\xcc\x56\xad\xe0\xcf\xfa\xab\x34\x38\xfe\x0b\xa2\xc3\x1f\x72\xa5\x94\x72\x41\x4b\x24\x6c\x5e\xee\xb7\xce\x53\xca\x2a\xd9\xaf\xd2\x9e\xa7\x5b\x6e\x2f\xf7\xc0\xb3\xf7\x0e\xe1\x1c\xb4\xb7\x71\x0c\xd3\x36\x3a\x7f\xe2\x80\xdd\x2e\x69\x03\xf2\xa0\xf9\xc2\x94\x3e\x3a\x54\x3f\x3d\x84\xe9\xbe\x84\x45\xc3\x8f\xce\x79\x34\xaf\xd5\x68\xb3\x80\x43\x53\x59\xd0\xca\xe5\xa9\xbd\x98\x53\x8a\x0c\xa8\xc9\xc7\x61\xde\xe8\xde\x3f\x53\x69\x82\xe6\x08\x8d\xef\xfd\xa9\x8e\xd5\x43\x5c\x78\x0c\x37\x28\x02\x5e\xe8\x1c\xb4\x46\x58\xb7\x67\xfb\xdc\xca\xf6\x61\x35\x0d\x92\x83\x58\xa0\x76\xcc\x2b\x12\x03\x46\x5e\xfa\xa4\x47\xe1\xf1\x9b\x0b\x4b\xec\x7f\x40\x79\xba\xb0\xf3\x80\x05\x39\xf3\x2a\x74\xbc\x8f\x21\x32\xea\xd7\xa5\x0d\x14\xf1\x91\x7d\x70\x45\x0f\xee\xb7\x55\x2e\x3f\xd7\xc4\x61\x53\x0e\x62\xe6\x53\x56\x64\x5a\x58\xd1\x08\xa0\x96\xb9\x42\x58\x45\x0d\x32\xdc\xc7\xc9\x3c\x32\x45\xa8\x9c\x69\x79\x69\x74\x2b\x4d\xad\x35\xdc\x6b\x34\xe1\x81\xa0\x7a\x56\x22\xcf\x64\xc1\xc7\x87\x4c\xc2\xc2\xc2\xcf\x5a\xed\x40\xae\xd3\x25\x1f\xd9\x1a\x97\x67\x1f\xf1\x26\x7d\x8d\xd8\xa1\xf4\x1f\x8d\x1a\x97\x48\x9f\xb0\x15\x50\x0e\x5e\xbe\x7d\x8b\x7b\xb2\xeb\xcc\xed\x1b\xf9\x81\xc8\x4f\x7f\xc4\xad\xcf\x14\x7e\x0f\xec\x5d\x5d\x47\x9c\x95\x61\xbd\x39\xa3\x1b\x78\xf7\x37\xc2\xac\x31\xa4\x95\x8f\x4d\x34\xc0\xf7\x28\xd9\x14\x3d\x1c\xf9\xaf\x56\x20\xf0\x82\xeb\x0e\x69\xe1\x8e\x38\xb3\x5c\xcb\xd0\x62\x1b\x05\x69\x1f\x79\x26\xf4\x7d\xa8\xef\x82\x42\x8e\xf2\x90\x2e\x64\xeb\xce\xbd\x3a\x7d\x06\xd9\x85\xbf\xed\xd8\x12\x4e\x9a\xb1\xad\xce\x2d\x4f\x7b\x94\x3b\x07\xca\xc9\xe8\xd6\xa3\x59\x2f\x5f\xd6\x14\x11\xe2\x2f\xab\x32\x34\x19\xe1\x6b\x56\xe5\xbd\x0d\x2e\xcd\x46\xab\xdb\x21\xad\xfd\xf7\x83\x27\xf4\xc9\x22\x98\xd8\xc2\xbb\x0e\x98\xed\x8c\xb8\xa9\x1f\x4e\x9e\x92\x79\xd7\xbb\xb2\xe1\x2e\xff\x55\x96\x09\xd8\x6a\x13\x57\x60\x1b\x3a\xba\xed\xde\xdc\x6c\xe2\x33\xdd\x9b\xde\xff\xb7\xfa\x7e\x13\x0b\x79\x63\x83\x6d\x59\xba\xee\xe6\x93\x22\xf1\xca\xfa\x61\xba\x9a\x20\x2d\xfd\xdb\x53\xaf\x61\x0d\xbb\x4e\x18\x74\xac\xa7\x82\xe9\x6f\x3f\x96\x15\x0b\x78\xdd\x47\xaf\xc7\xae\xe5\x40\x6b\x08\xfd\xf0\x52\xe3\x9a\x44\xa0\xb2\xf5\xa4\xe0\xdd\xb6\xd9\x21\x90\x80\x47\xfb\xc7\x5e\x27\xf2\x96\xde\xbf\x50\xb9\x77\x91\xc7\xa6\xad\x82\x4a\x25\x3e\xa6\xbb\x41\xb5\x0a\x23\xba\x79\x00\xf4\xe4\x5e\x11\x6b\x3e\x45\x8b\xb7\x8a\x8f\x1e\x6d\x11\xf3\xc4\x0a\x44\x86\x4e\x40\xd5\xa3\xaf\x0f\x81\x22\x05\xd0\xdf\x58\xdf\x0b\x7f\x4e\x3f\x39\xa7\x46\x94\x5f\xa0\xad\x2c\x4c\x6e\x2b\x23\x22\x6e\x5c\x48\x2f\xd0\x30\x36\xef\x27\xcb\xf0\xa3\xb6\x41\xb6\x6f\xe6\x47\xe1\xc0\x5a\x27\xc6\x91\xd7\x36\xa4\x0e\xcf\xcc\xbe\xd0\x9f\xec\x20\xd5\xf1\x48\xf4\x54\xde\xe1\x38\x25\xc6\xd3\xe7\x9a\x44\x32\xd9\x69\x7d\xb1\xd7\xb9\x92\x49\x0e\x51\xb4\xc8\xba\xaa\xf5\x6d\x11\xaa\x8d\x2d\xac\x33\x3e\x11\xeb\x09\x17\x2a\x5f\xec\x28\x48\x68\x57\x58\xef\x4b\xb3\x15\xe4\xa5\x05\xaa\x86\xd8\x18\x62\xd3\xdb\x1d\xb2\x69\xf9\x8d\x6e\x38\x12\x1f\xa8\x45\x8e\x8b\xf2\xa5\xf5\x17\xb9\xba\x22\xb6\x44\xf3\x67\xe6\xfd\x7a\x39\x41\xaa\xc0\xaa\xf4\xa7\xb5\x44\x67\x1e\xe5\xf7\x0a\x33\x0e\x75\xdd\x91\xbe\x62\x45\x05\x72\x94\xd4\x8a\x1f\x3f\x1e\x70\x33\xc9\x00\x5d\xba\xb2\xf5\xae\x74\x8d\xc3\xfd\x1c\xfd\x96\x5b\x63\xa9\xb5\xae\x9d\xd2\xc9\x85\x3d\x2e\x0d\x28\xf7\x90\x06\x18\x0e\xf1\xc3\x29\x1c\x3a\x26\xb6\xe4\xd4\x08\x5b\x41\xab\x16\xdd\xca\x79\x19\x18\x2c\x29\x1c\xe2\x86\x77\xa1\x43\x9c\xf0\xdc\xf9\xfe\xae\xf4\xe3\x44\x6b\xa0\xc1\x75\x65\xce\x0c\x45\x04\xb3\xa3\x1c\x33\x58\xe3\x00\x30\xfe\xa6\xc6\x27\x96\xf1\x0f\x1c\xb0\x38\x18\xbe\xbd\xf2\xc1\xb4\x48\x55\x81\x74\x7e\xf5\x19\x1e\x9b\x41\x80\xa7\x60\x3b\x54\x38\x76\xc1\xd3\xbb\x08\x3b\x5a\x6b\xb8\xe3\x90\x3f\x2e\x05\xf1\x85\x78\x3c\x2d\x31\x90\x56\x1a\x07\xbd\x89\xf8\xf4\x01\xab\x7b\x23\x7d\xb7\x19\xe3\xe8\x54\x0d\x5f\x64\x59\x24\x7b\x50\xf1\xe2\x17\x04\xdd\x90\xc3\x53\xce\xff\xaf\xac\x85\xb1\x6e\xcc\x3d\x1c\x79\xc8\x81\x2a\xa9\xb6\x70\x0c\x15\xd0\xd8\xb2\xe7\x47\x98\x20\x06\x77\x79\x95\x5f\xf2\xe2\x2f\xe5\x98\x7e\x55\xc4\x52\xc0\x87\x7b\x78\x0e\xa0\xbf\x7c\x98\x59\xb3\xb0\x80\xe6\x26\x45\x80\x97\xfd\xf1\x7e\xb9\xa0\x49\x67\xc5\xe0\xd9\xaa\x2a\x0e\xec\x06\x52\x36\xea\x66\x05\x8c\xf7\xf0\xf6\x2e\x28\xf6\x98\xbe\xa4\xaa\xa0\x70\xfc\xeb\x9e\xf9\x49\x99\x87\xdb\x9a\x6b\x97\x8c\x1c\xf5\x4b\xe3\x8e\xb3\xaa\x39\xa7\x17\xef\x80\x33\xcc\x8b\x83\xfc\xc7\xfd\x61\xc0\x70\x71\xe5\xd7\x3c\x05\xda\x7b\x6a\x8f\xaf\xba\xa5\x0a\xaa\x67\x0f\xdb\xdf\x8e\x63\x78\x02\x8a\x2a\x85\x4a\xfb\xc9\x3e\x4c\x18\xbc\x8f\xe7\xe2\x18\xd8\x1f\xf4\xc8\x61\x51\x25\x87\xc8\x94\xf1\xe0\x6b\x65\xeb\x38\x65\xed\x8e\xfa\xd5\x02\xc8\x3b\xfd\x85\xc8\xdb\x66\x59\xda\x88\xfb\xd2\xe3\xf0\x1b\x7f\xc7\x96\xd8\xd3\x69\x0d\xc4\x2f\x6b\x91\xc9\x3f\xeb\x69\x27\xec\x97\x49\x77\xcb\x27\xe4\x8e\x88\x9e\x26\xd9\xb7\xf3\x3e\x0c\xd2\xec\xb8\xff\x82\x04\x46\x7e\xd6\xd1\x22\xe2\xbb\x43\xdc\x90\x4e\xe6\xd2\x76\xbe\xff\x4f\xf1\x1b\x04\x1a\xc2\x09\xdb\x03\x3a\x34\x04\x98\xc2\xb6\xf4\x9b\xe5\x3f\x15\x35\x47\x0e\x2e\x77\xfe\xc9\xe9\x33\xa2\x2b\x00\xf1\xe0\x03\x8f\x58\xb8\x82\x32\x26\x46\x75\xf5\x6b\x9b\x19\xb4\x94\xbc\xdc\xa4\x99\xd9\xfb\x6e\xef\x80\x97\xda\xf0\x3c\x55\xbc\xd0\x11\x4a\x7c\x37\x57\xd9\x7c\xb3\x45\x25\xe8\xef\x04\x34\x67\x62\x90\xa1\x74\xf2\xba\xf9\x53\x45\xd3\x7d\x7f\xfc\x96\x7a\x7f\x7a\x96\xa2\x6e\x7f\xca\x29\x80\x1d\x9d\x51\xee\xe2\x14\x25\x2a\x0d\x80\x62\x15\xc6\x9f\x9b\x2d\xcd\xbb\xc5\x07\x4a\x3c\x3f\x51\xbf\xf2\x76\xf7\x46\xf2\xd2\x14\x72\x63\x0b\xfb\xf9\x01\x44\x2c\x1a\x6d\xd2\x2b\xf5\x95\xbd\xa9\x7f\x31\xf7\xfe\xc5\x69\x26\x94\xab\xf2\x81\xbb\x28\x49\xbe\xea\x51\x3a\x7f\xe2\x5e\x11\x68\xc2\x1e\x06\xaa\xd8\x34\xdb\xf1\x09\xd3\x54\x2f\x22\xb2\xba\x7e\x2b\x2d\x49\x34\xba\xd8\xd0\x5d\x2e\x87\x25\xc4\xef\x4f\xe5\xbc\xee\x86\x36\xd4\x66\xee\x57\x83\x59\x63\xef\xd4\x14\xe4\xeb\x4d\xbd\x3e\x5c\x53\x97\xfe\xa6\xfd\xdf\xcd\x33\x7c\xcf\x41\xcc\x26\xd3\xf8\xac\xdc\xeb\xce\x55\x3e\x7c\x30\xd5\x7e\xa8\x84\x38\x36\xe6\x5d\x9c\x11\x2d\x74\xc2\xdc\x81\x0b\xd5\x31\xb9\x6f\xc3\x80\x24\x97\x16\x4f\x81\xbb\xb4\xa4\x7b\x23\x42\x4c\x5c\x81\x26\xd8\x83\xa3\x4a\x2c\xd2\x8b\xcf\x52\x6b\xae\xd2\x21\x3f\x41\x85\xad\x9d\x2d\x44\x2d\xfa\x08\xb1\xde\xbd\x6a\x80\xb9\x89\x30\xcb\xa3\x91\x8e\x0e\x76\x14\x56\x10\x6c\x74\xb7\xb6\x36\x87\x44\x94\x23\x8f\x32\xfd\x3c\x22\x77\x00\x1e\x17\x7c\x3f\x44\xe7\xdf\x0f\x51\x3b\xf7\xf8\x44\xfd\xc8\x2b\x40\x26\x33\x04\x46\xb0\x70\xdb\x3e\x22\x24\x02\xec\x77\xb7\x7d\xb0\xf7\xb5\xa9\x48\x37\x29\xe6\xf6\x4c\xe3\x1c\xf6\xa4\x3b\xb2\xd5\x12\xab\x11\x6b\x3e\x12\xbb\xde\x5d\xf4\x0e\xeb\x73\x7d\x63\xab\x83\xdf\x36\x5b\x7d\x55\x67\x01\xd4\x2a\xef\xd8\xb7\xee\x87\x0d\x44\x6f\x3c\xea\xe0\x5c\x23\xc1\x62\x05\x21\x45\xab\x25\x18\x71\xae\xcf\x23\x40\x22\x81\x51\x09\x75\xce\x8a\x20\x7c\x32\x04\xf0\x7a\x63\xd1\x0b\x60\x91\x23\x41\x22\x6f\x7b\x0b\x13\x6d\x00\x20\x0b\x9d\xf4\xd6\xbe\x44\x71\xbb\xf6\x69\xa8\xac\x54\x5c\x73\xca\x85\xed\x64\x0a\x36\xff\x06\x47\x40\x66\x06\x10\x59\x90\x1f\xf0\x97\x43\xc9\x64\xd5\x2e\x73\x5c\x2a\xd1\x0e\xf5\x1e\xcb\x9d\x3b\xc6\xba\xdc\xf4\x1b\x83\x8f\x4b\xf2\xad\x76\xa9\xbe\x4f\x2e\x4e\xdf\x15\x04\x52\xf8\x8a\x78\x35\xfb\x60\xc9\xb3\x05\x2b\x80\x26\xee\x4b\xe3\x83\xce\x2c\x99\xe6\x60\x80\x88\xc2\x3a\xcb\xc9\x6f\x5e\x0a\x2b\x9a\xf2\x0f\xb9\x0e\x30\xb4\x33\x42\xe6\xb2\x8a\xcb\x34\x07\xd5\x70\x2e\x5d\x47\x36\x9e\xed\xe6\xce\x19\x08\xd9\xcf\xcc\x43\xf2\x2f\xeb\x05\x70\x83\x07\x56\x3a\xc7\xd2\xdd\x74\xb0\xd9\xce\xb8\xdf\x41\x27\x48\x14\x73\x4c\xf5\xbf\xc2\xc7\x38\x95\xdd\xb1\x71\x0b\x64\x6a\xaa\xe1\x7a\x31\x05\x42\x3e\xc1\x91\xc8\xaf\x54\x94\xf1\xff\x30\xf2\x58\xf3\x78\x9e\x16\xab\x9e\xbb\x93\x40\x74\x8a\x93\x10\x93\xc0\x12\x25\x51\x09\xe6\x5e\xfb\xd5\x69\x6c\x2e\x0a\x8a\x7a\xbf\x1b\x43\xef\x10\x08\xe0\x35\x51\x04\x44\xd4\x88\x23\x85\xd9\xb9\x80\x92\xe5\x47\x4c\xff\x0d\x30\xb0\x53\x2c\x98\x5f\xc6\x87\xcd\xfe\xd1\x1f\x3b\x61\x10\x63\x73\xd8\xb1\xfb\x67\x91\x80\x56\xf0\xe9\xf3\x08\x33\xa2\xa7\x40\xbc\xe7\x02\xfd\x16\xbd\x22\x19\x8c\xe3\x9f\xb5\x1e\xea\xe9\x96\x2a\x10\xd4\x0b\xf7\x58\x22\x29\x5e\xe4\x5b\x5c\x12\x72\x5c\xe8\x39\xcd\xb4\xca\x24\xc2\x01\x63\x14\x71\x87\xdb\xd9\xf1\x09\x4f\x6d\x64\xc7\x27\x49\x72\x39\x86\xa8\xaa\x83\xb4\xa1\x0e\xe5\x5c\xe5\x93\x6f\x17\x89\x5d\x7a\x4a\x16\xb2\x0f\xe4\xc8\xf3\xce\xb2\xe8\xb1\xee\x48\xb6\x0d\xb8\x5c\xc4\x64\x68\x26\xcb\x30\x69\xd8\x14\xd4\xb3\xc8\xce\xf7\x81\x7a\x69\xf3\x9a\x8a\xb1\xf3\x2a\xd8\xc0\x76\xbf\x54\x33\x9d\xa7\x5b\x88\xfb\x07\x19\xf3\x8d\x36\x1c\x11\xb5\xe1\xba\x82\x34\x78\x89\x5e\xdb\xfb\x93\x92\xf3\xef\xd9\xe4\x66\x0c\xa9\x70\x2f\xe0\x20\x1c\x76\x5d\x98\x05\x89\xfa\x62\x47\x03\x6b\xa4\xc9\xde\x5b\x37\x00\x86\x19\xbe\x94\x68\xf0\x03\x24\x19\x62\x5f\x52\x8c\x57\x84\xb8\x74\xdc\xbb\x41\x8a\x08\xb7\x5f\xc4\x66\xcb\x55\x08\xa4\x83\x98\xb9\x9c\x92\x03\x59\x49\x75\x37\xf2\xb4\xe3\x29\xc2\x47\x38\xff\x84\x1b\x9b\x10\x93\x23\xa2\x62\x2b\xb1\xf8\x4e\xc1\xa7\xe4\xd8\x8b\x4e\x51\x8e\xe1\x8c\x60\xc5\x41\x31\xbb\x5d\x8a\xf2\xe8\xaa\x62\x30\x1c\x9c\xc2\xdb\x6a\xd3\x63\x9f\x37\xd1\x1b\xb6\x20\x1f\xf6\xac\x65\xed\x1a\x54\xe6\x61\x8a\x69\x61\x0b\xe7\x08\xd2\x62\x83\x22\xbd\x27\x39\xb9\x08\xc5\x15\xc2\x84\xf4\x88\x0a\xcd\x7f\x40\x4b\x70\xf8\x56\x71\xf1\xcf\xaa\x48\x8f\xf0\xd9\x7f\xe3\x86\xf2\x9a\xc9\xde\xf9\x12\x8b\x90\x04\xdb\xba\x0f\x3f\xf9\xcf\x0a\xaa\xbb\x2f\xe9\x23\xf5\x26\x2d\xdf\x1e\x72\x84\xef\xf3\xb5\x82\x11\x86\x26\xef\x2f\x9a\x82\x60\x5c\x53\x8f\x7f\xec\xe2\xa6\x5a\xdd\x2d\x6e\x93\x8d\xc3\x1d\xd3\x93\x8b\x66\x89\x30\x59\x0f\x3b\x6e\x5b\x8f\xcc\x34\xaa\x76\xcf\x2f\x11\x90\xad\xe1\x25\xd0\x11\x0e\x72\x42\x55\xfc\xd6\x71\x6d\x8b\x48\x90\x39\xdf\x00\x43\x88\xb5\x80\xee\xf9\xf8\x7f\xf4\x52\xfe\x49\xe1\xee\x35\xaa\xa8\x9b\xe8\x37\xba\xe6\x6f\x09\x04\x66\x54\x8a\xe4\x55\x64\x06\xe0\x2e\xf5\x64\x4f\x5c\x41\x73\x06\xcb\x82\x1e\xf7\x4b\x92\xcf\xdf\xe9\xe2\x59\xbf\x53\xdc\xbb\xc8\xc7\x3b\x93\xdd\x9e\x87\x16\x68\xa3\x02\x88\x06\xd9\x42\xf2\xe9\x2e\x7d\xfd\x4b\x33\x8b\x20\xa4\x8c\xa8\x5a\x7a\xa7\x2d\x70\x99\x23\xdb\xf5\x34\x52\x90\x8c\xea\x0a\x95\x45\x88\xac\x8b\x22\xea\x50\x2d\xc5\x90\xf5\xb8\xbf\xf6\xe7\x7b\xd9\x53\xd9\x02\x1c\x76\x07\x24\xd6\x30\x28\x4a\x84\xe1\x40\x0e\xc9\x08\x39\x38\x54\x05\xfd\xc9\xaa\x2c\x5d\xff\xc0\x76\x0b\xc9\x17\x25\xe0\xb5\x23\x0f\x2a\xe9\x6d\xbb\xe0\x9c\xe9\xbd\x04\xa1\xed\x88\x7c\xfb\xb0\x68\xfc\xdf\xad\x67\x61\x95\xe8\x4e\x6b\x13\xb8\xdf\x31\x36\x6d\x3f\x6c\xf3\x95\x29\x13\x06\x38\xc2\xf6\xc1\x8e\x1c\x48\xaf\xb4\xb3\x8b\x0b\x7b\x5e\x2a\xb2\xbc\xf2\x70\xd6\xc3\xfe\xa4\xc8\xc5\xca\x2b\x47\x9b\xf6\x9c\xce\xa0\x5d\xf8\xb7\x41\xb9\x40\xc7\x68\xbb\xc1\x46\xb2\x2a\x46\x5a\xb2\x01\x1e\x65\x5d\x85\xc3\xb1\x65\x6c\x8a\x0b\xb4\x15\xbf\xe9\xe0\xce\x21\xef\x54\x95\x58\x87\x32\xe9\x6a\x04\x39\xad\x21\x07\xaf\x85\x55\xd5\xf7\x48\x8e\x73\x2a\x10\x1b\x83\xa7\x0f\xf3\x58\x5a\x6e\xc7\x5a\x66\x72\x8e\x31\x5f\x5a\x55\x7a\x15\x72\xb3\xd7\x1e\x2a\x4a\x71\x2e\xfa\x11\x58\xba\x3e\x9f\xdf\x8d\x9b\x71\x6a\x47\xc7\xba\x65\x98\xc3\x9f\x5b\xac\x4d\x0a\x76\x54\x6e\x5d\xee\x1b\xce\x25\x9c\x2a\x42\xea\xd0\xec\x41\xc2\x58\x61\xf5\x7c\x53\xf6\xb7\xa8\x0e\x38\xb7\xda\xe4\x5f\x95\x02\x6c\x81\xab\x35\x0b\xaf\x90\xe6\x83\x79\x21\x7f\xeb\x12\x0a\x07\x2f\xb2\xca\xfe\xab\xc8\xa2\x77\x5b\xb2\x60\x4c\x92\x0a\xb8\xc8\xfa\x76\xab\xaa\xba\xe0\x4b\x2e\xe9\x3d\x09\x66\xba\xae\x12\x18\x54\x0b\x2b\x06\xab\x33\xd8\x23\x76\xc8\x5d\x4c\x24\x5d\x99\xcc\xb9\x24\xa2\xb1\xf3\x91\x9a\x4c\x7e\x5e\xaa\x44\xee\xff\x04\xbf\x9c\xd7\x2f\x0d\x46\x85\x1c\x32\x67\x1e\x98\x68\x7d\xdf\xd4\x7b\xfc\xa5\xf9\xee\xe2\xde\xc0\xb4\x12\x3f\xd9\xca\x3d\xaf\x19\x8a\x0f\xb2\x59\xc5\x0d\x8d\xfe\x79\x9f\x2d\x9c\xdd\xad\x26\xe0\x37\x18\xd5\xa3\xf3\x40\xbd\x9a\x2b\xe3\xf4\x54\x98\x69\x11\x50\x95\x1b\x47\x24\x13\x94\x9d\xf2\x10\x01\x5d\x9f\x1f\x9c\xd5\x92\x09\xbc\x66\xf3\x47\x19\x1b\xda\x2b\x20\x97\xd9\x99\x53\x22\x3b\x5f\x4f\x96\xea\xb0\x6b\x57\x12\x4d\x3f\x77\x72\xf9\x18\xef\x56\xc1\xf5\x92\x26\x3a\xd6\x15\x44\x14\xa7\x9c\x88\xf9\x03\xa3\xd9\x23\x9c\x66\xe1\x6d\x44\x2e\xe9\xd0\xd1\x6e\x67\x5c\xd4\xca\x8c\xf2\x72\x1e\x4b\xcb\xca\x19\x1d\x4d\xe1\x88\x76\x74\x69\x02\x0d\x50\x96\xc8\x3e\xf2\x18\x05\x3e\x26\x32\xb1\xac\x92\x53\x8e\xf5\xd3\x7a\x22\x0e\xbe\xbe\x1a\x80\x35\xdb\x75\x64\x1e\x76\x51\xd6\xda\x07\xac\xfc\x34\x35\x02\x91\xd1\xe7\x58\xb6\x0d\x58\x8b\x88\xbf\x3b\xa3\x6b\xd3\xbf\xa2\x05\xf7\x4d\x3c\x33\x4e\x33\xf7\x2d\xf0\x46\x41\x88\x07\xd5\x02\x83\xa0\x7f\xa7\x9a\x28\x5f\xc1\x33\x8a\xc2\x5c\x71\xe5\x35\x81\x62\x8c\xb1\x4d\xb6\x6a\x38\xcd\x90\xee\x9d\x59\xd9\x83\x13\x48\x0a\x0b\x33\xa2\x52\x07\x3d\xc1\xfb\xfa\x4d\x44\xa9\x9c\x8e\xc9\x4f\xad\x32\x43\xe9\x17\x41\x40\x76\x27\x0e\xcd\xa0\xae\xb7\x67\x95\x07\x55\x4e\x9f\x20\xa6\x9c\xff\x86\x49\x37\xb3\xdb\x45\xf5\x55\x65\xd4\x09\x36\x0d\x6a\xe5\xef\xaf\x0a\xa5\xfb\x54\xf9\x64\xad\x88\xde\x32\xcf\xc9\x09\x2b\x14\x3f\x58\x9e\xa2\x4a\xe3\x6f\x08\x1b\x14\xa0\x1b\x41\x47\xad\xdb\xd3\xdf\x66\x5f\xd3\x87\x08\x19\xb1\xfe\x58\xa0\x39\xf1\xc5\xc2\x1b\xa9\x0b\x8f\xe6\x2e\x47\x42\x35\x4b\x55\x56\x52\x8a\x27\xe9\x72\x4c\x72\xbd\xca\xca\x62\x65\x58\x55\xc5\x9a\x6a\x51\xba\x19\x6e\xaf\x83\x38\x69\x97\x26\x7e\xae\xd7\x21\x9b\x74\x40\xa2\x28\x23\x12\x55\x94\x7d\xdd\x2c\xec\xbe\x10\x72\x33\x80\x27\x7c\xfa\x68\xda\xf8\x50\x52\x44\xa2\x1a\x23\x38\x8b\x0e\x4b\xb1\xa8\x92\xae\x1f\x97\xfa\x25\x44\xaa\xaf\xff\x69\x34\x35\xad\x31\xb4\x4a\xa4\xb3\xb2\x9a\x22\xc6\x25\xac\x0a\x46\x59\x5e\x68\xb8\x3c\x92\x90\xdb\x2b\x32\x96\x59\x43\xd9\x8b\xd6\x8c\x5f\xfc\xcd\x7f\xb5\xdd\xd8\xee\x10\x4a\x3e\x3e\xaa\x91\xc8\x60\xba\x00\xbb\x84\x23\x3b\x15\x68\x58\xe6\xff\xac\x5c\xa3\x1b\x8c\x13\xd4\xaf\xb4\x87\x9d\x93\x95\x43\x1a\x18\x5d\x52\x31\xdb\x82\x2d\x0a\x4e\x51\x2f\x36\x70\x03\x13\xec\x41\xe3\x19\x02\xfc\xb0\x12\xb3\xab\x54\xa0\x0e\xe7\x50\xac\x4a\x0a\x60\x0a\x16\x2e\xbf\x0c\x89\x49\xb6\xaf\x18\x4e\xc5\xe7\x30\x97\x10\xb8\x14\xc8\x84\xff\x6d\x02\x87\xd8\x41\xd0\x6c\xac\x4d\xb1\x0e\x25\x08\xa3\x26\xaa\x4b\x5c\x2a\xac\x90\x1a\x66\x0d\x14\x2a\xd1\x7a\x07\x41\x40\xf1\x87\xa5\xb5\xa9\x46\x96\x22\xb7\x78\x19\x8e\x7d\xd8\x0f\x1d\xbc\x1b\x59\x12\x61\xce\x7d\xd3\x84\x52\x46\x34\xa4\x6b\x1d\x19\xb8\xad\xd4\x24\x6d\xda\xb5\x49\xab\xd0\xb8\x42\xf0\xf9\xfd\x93\xc6\xb2\x3e\x83\x65\x73\x69\x72\x87\xe9\x16\xef\xcd\x1d\x73\x86\x91\x0a\xcb\xc6\x99\xab\x74\x59\xaf\x07\x3d\x12\x20\x45\xd6\x61\x82\x25\xfc\xe4\x9d\x51\xb3\x55\x99\x4e\x56\x6f\x05\x79\xa6\xd6\x49\x43\x80\x2a\x4b\xa9\x9a\x23\x53\xae\xfb\xc8\xeb\xf2\xfe\xba\xa8\xcc\xf9\xa5\x04\x99\x88\x35\x6f\x01\xee\x6d\x6e\x9a\xa0\xdc\xdf\xa4\x12\xca\xfa\x52\x5a\x5c\xd6\xc8\xfe\x5e\x6b\x40\x51\x63\x84\xb4\xaf\xda\xb3\xad\x1c\x42\xf4\x07\x2b\x21\x6c\x12\xac\x8e\x40\x45\xf0\xda\x04\x0a\x04\xff\x3a\xc8\x53\xb4\xf0\xdc\xd1\x15\xd1\xb1\x2c\x76\xc0\x42\x12\xfd\x16\xd6\x01\x0b\xfd\x9d\xd6\x08\x7e\x71\xb6\x6a\xd8\x0d\x80\xa4\xda\xfc\x71\x8e\xfe\xb7\xf3\xae\xc8\x64\xdd\xd2\x20\x4f\x81\xdc\x08\x38\xe2\xdd\x6c\x63\x51\x54\xdd\x29\x2f\xfb\xed\xb2\xde\xc8\xd1\xd2\xc5\xbd\xf1\x7c\x2c\x96\x75\x36\xd9\x22\x09\x51\x92\x83\x24\x82\x3b\x53\x04\xa4\x8b\x6e\xb2\x90\x6b\xb8\x24\x45\xb7\x22\x52\xe9\x94\xf9\xbd\xae\x94\xf9\x0e\x73\xa2\x79\xf3\x56\xac\x8b\x50\x8e\x99\x84\x72\x94\x58\x9a\xdf\x42\xa3\x12\x50\x14\x3c\xaf\x55\xcd\x58\xab\x47\xce\x3f\x21\x27\x15\x36\xc1\xd4\x11\x7b\x60\x4e\x0a\x7f\x56\x86\x88\x3f\x6d\x3a\x8c\xf2\xb3\xb9\x45\x8b\xa0\xa7\xf7\x9d\xf2\x2f\x2f\x5e\x41\xc2\x4e\xbf\x0f\x4e\x0f\x8e\xcc\x12\x3e\x65\xd3\x3d\xaa\xb1\xb6\xd5\x28\x5f\x83\xfa\x0e\xe3\x65\xd6\x3b\x35\x0c\x33\x81\x63\xb1\x02\x52\xa6\x10\xae\x60\xbd\x68\x53\x08\x73\x7c\xc1\x1a\x07\xc9\x92\xc4\xad\xae\x2b\x45\x5e\x9e\xed\x94\x44\xad\xe0\x48\xc7\xb4\x64\x7f\x12\x51\x07\x0d\x21\x26\x0d\x21\x0b\x5a\x7f\x55\x35\xb6\x64\x89\xed\x4a\x18\xce\xe9\xca\x4f\x42\x2a\xd9\x28\x0d\x9a\x7d\x09\x5b\x75\xf9\x07\x75\x1a\xe7\x25\xb8\xa7\xfa\x3f\x3f\x3f\x4f\x59\xe9\x1f\xfc\x59\xcf\x7b\xc1\x66\xf5\xf4\x19\xdb\x83\xa5\x8c\x4a\x9a\xa0\x50\x3c\x59\x33\xd9\x03\x5f\xda\xa7\x33\x18\x7d\xa1\x11\xaf\x87\x52\x73\xc1\xea\xa7\x76\x6e\x55\x8a\x92\x87\x5c\x71\xd4\x3b\xbc\x9e\x9e\x40\xfb\xca\xc1\xae\xe9\x99\x29\xa1\x78\xb6\x91\xe5\xb3\xed\xa8\x08\x7e\xf7\x5d\xdb\xdd\xa0\xf5\xb9\x5e\x3a\x93\x1c\xe1\x3c\xc3\xbd\x11\x81\x19\xee\x30\x92\x3b\x32\x99\x96\x83\x50\xb5\xa1\x68\x8e\x3f\x14\xbd\x39\x43\x69\xda\xd3\x5c\x22\x42\xba\x5f\x54\x03\xbd\xfd\xff\x38\x3f\xe8\xcf\xb0\xcd\x2c\x83\x6c\x0b\x19\x54\x11\xf5\x54\x53\xf7\x62\xd0\xc2\x52\x34\x6c\xe6\x8e\x9d\x0f\x94\xa3\xd6\x3d\x3e\xbf\x9d\x65\x88\x28\x80\x2d\x6a\x0f\x5b\x76\x95\x28\x56\xaf\x60\xc8\x5e\xc6\x58\xfd\x92\xdf\x8c\xac\x0a\xb6\x3b\x7d\xea\x52\x54\xff\x3d\xca\x08\x3a\x60\x5b\xcb\x2d\xb2\x0f\xcd\x6f\x44\x0f\x6a\x85\x56\x09\x7a\x10\xf2\x35\xf6\x49\x14\xa2\x63\x8d\x37\x12\x7a\x1f\xa1\x87\x30\xc0\x66\xb9\x74\x43\x8a\x46\xaa\x8f\x4c\x1e\xd2\x97\x51\x44\xee\xa5\x14\xb0\x95\x5c\x4e\x8f\x34\xc8\xde\x08\x16\x10\x99\x5a\x1f\xcf\xa5\x28\x5c\x76\xb4\xc0\xae\xd7\x24\x74\x6b\xd2\x24\x90\xdf\x84\xfa\xc3\x17\xb2\xb1\x13\x55\xbe\x6b\x52\xba\xce\x4e\x1d\xc1\x5b\x25\x6b\x26\x99\xdd\x13\xbb\x52\x13\x24\x05\x90\x52\xaf\x95\x38\xd0\x85\x12\xa3\x0b\xc4\xb4\x4b\xdf\x80\xc4\x84\x8f\xb6\x72\x2d\x10\xb2\x10\xfb\xf0\x4d\xee\x52\x0b\x37\xb3\x42\x3a\xea\xb4\x2b\xe0\x30\xf1\x2d\x1c\x0f\x7b\x38\xdf\xc8\x3f\xbf\x80\x46\x24\xec\x8b\x39\x92\x8e\x81\x25\x0d\x18\x21\x05\x72\x2a\x52\xe7\x9f\xf8\xde\x59\xe2\xae\x6f\x8d\x9a\xe1\x53\xe7\xfa\x61\x9d\xf8\xa9\xdc\x36\xde\x9f\x85\x0c\x38\x2b\xea\x38\x14\x7b\x53\xbb\x6f\x0f\x21\xbd\x2d\x4b\x2b\xf3\xd6\x86\xa1\x2d\x89\x35\xda\xdb\x8f\xfd\x57\xd6\x88\x11\x69\x21\x84\xd4\x30\xd1\x51\x0f\x69\x6b\x75\x2c\x2f\x6b\x91\x79\xd9\x05\x3e\xe6\x5b\xec\x4b\x7e\xfe\xf7\xa8\x34\xe3\x0b\x8a\x19\x86\x3e\xdb\x2d\x42\x3c\xe3\x6a\x96\xc3\x57\x19\xf8\x00\x4e\xb3\x17\x7c\xb8\x70\x65\x7b\x46\x2d\xaf\xaa\xbf\xe4\xc1\x89\x14\x0d\xb8\xa9\x2c\x2b\x41\x0f\xe1\x75\xe0\xe9\x9d\x9d\xc3\x55\x1a\x66\x26\x94\xe2\x84\x59\x16\x37\x2b\xf8\x7a\xaf\x7c\x8c\x11\xa3\x9d\xf9\x1c\x3b\x42\x1e\x21\xf3\x6f\xbb\xed\x45\x79\xc7\x2d\xb1\x89\xb6\xc4\x3b\xdd\x17\x25\x4b\x02\x6d\x1f\x71\x67\xc4\xc2\x27\x85\xfb\x11\xb3\x46\x64\xe0\xb0\x42\x5b\xe9\xb0\xc4\x52\x10\x46\xb5\xaa\x28\x37\x47\x24\xe8\x16\xee\x8b\xfc\x14\x93\x0a\xdd\xf8\xff\x6e\x5a\xd7\xde\xe1\x1d\xee\x32\x32\xff\x63\xed\x82\x93\xa8\x58\x9c\xb2\x96\x04\x11\x38\x5b\x95\xff\x02\x38\xda\x6d\xf0\x8a\x78\x6a\x9a\xd4\x92\x63\x01\x39\x1e\xd3\xcc\x6a\x23\xb9\x3a\x98\xe6\x9b\x3f\x92\x21\xd5\xe3\xd8\xd9\xc3\x6d\xfe\x98\x14\xe7\x79\xe4\x7d\xd1\xe1\x67\x4d\xa6\xc4\x39\xb6\xe3\x88\x55\x05\x87\x26\xfe\x9b\xdf\xc1\xff\xbb\x13\x3d\x08\x0f\x9f\x96\x84\x99\xed\x10\x3a\xe2\xea\x03\x47\xeb\xca\xbc\x5e\xb4\x43\x01\xa3\x53\xce\x24\x47\x5d\x28\x7b\x4c\x5a\xad\x9c\xfc\x8d\x1a\x8f\x7f\xb5\xc8\x76\xfb\xd8\x4f\x62\x91\x41\x2f\x0f\x9e\x1a\xf5\xfe\xfa\x0f\xab\xbf\x30\x41\x24\x64\x91\xaa\xad\x5b\x0d\xb8\x86\x17\x97\xb3\xfd\xc0\x8b\x03\x4b\x72\xfe\x36\x6a\x03\xb6\x92\x65\xe1\x89\x0c\x13\xb9\xdf\xaa\x78\xb1\x05\x47\x64\x5b\xe4\xad\xd9\x56\x10\x45\xdb\x51\x59\x49\x7e\x02\x71\xb3\xae\x84\xf8\x13\x1d\xb1\x34\xd7\x6c\x30\x1c\x30\x05\x31\xc0\x99\xe1\x66\xf7\x15\x65\xd3\xf9\xd2\xdc\xdc\xde\x02\x19\x2e\x82\x9d\xf1\xf8\x7f\x2d\xfa\x98\xd6\x8c\x99\xe1\x4a\x98\xce\x16\xd5\xa2\x31\x19\x41\xe2\xe6\x30\x04\x21\xeb\x0e\x23\x65\x56\xa1\xc1\x71\x03\x3f\xab\x36\xa2\x56\x11\xbc\x76\x0b\x34\xd3\x6c\x36\x1d\x41\xa6\x87\xc4\x20\x4c\x1d\x97\x18\x89\xaa\x44\x1d\x03\x29\x84\x0f\xa2\x6c\xe0\x53\x27\x89\x55\x48\xad\x94\xc8\xb3\xdc\x9a\x72\xd6\x2e\x29\xcb\xf3\xa5\xf4\xb8\x5f\xf4\x16\xd2\x96\x64\xe1\xb3\x84\x1d\xc6\x82\xc3\x4a\x0b\x79\x60\xb9\xa3\x05\x8f\x2a\x7c\x80\x89\xf5\x43\x00\xdb\x11\x0c\xaf\x18\x27\xcd\x76\x51\x32\x88\x29\x88\x94\x33\x62\xf7\x7d\xeb\x9d\x97\x24\x82\x83\x15\xa8\x51\x9d\x6e\x9f\x58\x00\xbd\xaa\x2c\x46\xdf\x71\xdd\x60\xa9\x50\x2b\x27\x91\x7f\x7c\x91\x36\xc7\x80\xf1\xb5\x91\x2f\x51\x4e\x1f\xec\x17\xb6\xe9\xb0\x92\x0c\xbf\x5f\x8c\x7d\x88\xbf\x85\xb6\x06\x0e\x5c\xbf\x9a\xb0\x54\x19\xff\x36\x21\x88\xbd\x82\x4b\x99\x48\x21\xdb\xa2\x5a\xb3\x9e\xf4\x15\xf5\xe6\x67\xba\xe9\x91\x35\x25\xb7\xe9\xe3\x2a\x87\xb1\xb0\xcf\x69\x02\x9f\x6b\x7e\xc0\x56\xd4\xa4\x57\x18\x74\xd9\x09\xab\xa9\x25\xe2\x0a\x78\xd6\x83\x24\x16\x45\xa9\x46\xea\x23\xe7\x36\xa3\x9d\xd9\xba\xa4\x47\x9c\xda\xf2\x9f\x97\x9b\xd3\x88\xe2\x4d\x26\x29\xa5\x59\x1f\x8f\x3e\x84\x7e\x38\xbd\xdc\x93\x50\xed\xaf\x56\x75\x9b\x02\x71\x93\x17\x71\x6a\x59\xc2\xb0\xcd\x7a\x90\x60\x7e\x8a\x3f\x16\x11\xfb\xe7\xa5\x47\x09\xbd\xe2\x1e\x7f\xd6\x16\x6d\x03\xa3\x4c\xff\x29\x1a\x83\xc0\x02\xcc\x91\x34\x5e\xed\x39\x62\x2a\xf3\xae\x72\x20\xdb\x35\x44\x86\x99\x15\x5b\x4d\xe5\x31\xdc\x17\x75\x5f\xf6\x6d\x99\x9f\x58\x29\x6d\x1a\x0e\xda\xb2\x0d\xf5\xad\x5a\x03\x3b\xe9\xe4\x44\x9c\xa1\x56\x95\xa9\xb5\xab\x9a\xa6\x72\x2c\x5a\xd4\x4d\x5a\x4d\xda\x55\x45\x48\xd9\x31\x91\x2f\x16\xa3\xd6\x8c\xc9\x3c\x65\x77\xe1\x25\x72\x4f\x36\x25\xed\x0e\x3c\xb3\xfb\xcf\xde\x0c\xc1\x14\xd4\x7f\xd4\x9e\x73\xd2\x12\xae\x28\x87\x64\xcf\x3d\x0e\x41\x45\x9f\x72\xbe\x59\xd7\xbd\x6a\x1c\xba\xa2\x2c\x66\x39\x4a\x26\x57\x0f\xe5\xd5\x2b\x48\xe5\xf0\x47\x69\x5c\x32\xe9\xc9\x1d\xc5\xe2\x6e\x0d\x4e\x92\x68\x63\xf5\x7e\x6b\xca\x89\x72\x2e\xa8\x60\x31\x95\x3c\x52\x4c\xbe\x50\x23\xfe\xef\x6e\x51\xd6\x7c\x84\x11\x9e\x57\x72\x56\xf8\x8a\x68\xb6\x24\x15\x81\x22\xf0\x77\x53\x9a\x2f\x62\x6e\x3a\x61\x03\x2e\xea\x22\xfd\xa3\x4b\x56\x77\xb8\xa8\x01\x09\x10\x5e\x62\xed\x92\x11\xa5\x35\x6a\x33\x5a\xe2\x61\x42\x2c\x7f\xb2\x34\xd3\x75\xf3\x1b\x56\x21\xdf\x70\xff\x7d\x7f\xc2\xf7\xe4\xa3\x44\xd5\xda\x92\x57\x3d\xe5\x04\x77\xa2\xb8\xac\xef\xa9\xaa\x56\x7e\x03\x30\xe7\xf8\xd1\x2b\x2e\xf1\x11\xde\xb6\x83\xab\x0e\x2b\x7a\x02\xef\xe6\x40\x07\x76\xb8\xd7\x28\xbe\x9e\xc2\x84\xf3\xfa\xe9\x7d\x90\x6e\xd8\x1c\x56\x08\x45\xbd\x0a\xa6\xfd\x61\x54\xb6\x30\x9a\x0f\x90\x1c\x7e\xcb\x2d\xb6\xc4\x1d\xe9\xf6\x3e\x62\x97\x11\xe7\x3b\x3b\x68\x7f\xdd\xd5\x37\x15\xb8\xcd\x44\xca\x8a\xe7\x9d\x3f\x94\x95\xf5\x90\x04\x9c\xdf\x55\x85\xd9\x51\xba\x84\xd3\x77\x13\x72\x77\x30\x83\xcb\x16\x49\xbe\xce\xf9\x8a\x0a\xd0\xae\x2f\x4a\x29\xad\xd6\xba\x02\x5b\xc1\xab\x36\x71\x6a\x89\x98\x06\x0d\x2b\x61\xfe\x15\xea\x6b\x7c\x34\x04\x91\xdc\x2e\xb6\xbe\xec\x53\xcc\x34\xa3\xdd\x90\x74\x9c\xab\xa0\x92\x59\xc9\x28\xf0\x6f\x3f\x5a\xa6\xd6\xfe\xfb\x61\x7b\x60\x71\xb8\x51\xa3\x86\xf4\x6e\xc5\xcb\x3a\x28\x98\x68\x9a\xe6\x55\xd2\x59\x8e\x90\xc3\x15\x08\xa3\x93\xff\xb6\xd2\xc6\xb8\x25\x54\xa4\xe7\xa4\x88\x09\xcc\x50\xc5\x63\x8f\x29\x6c\xef\x24\xb0\x07\xeb\xb8\xd2\xa6\xa5\xef\xf0\x59\x83\xbd\x1f\x56\xe9\xb3\x54\x05\x81\xbb\xba\x55\x8e\x9f\xfe\xe5\xd6\x36\xf0\x39\x27\x58\x36\xf8\xe8\xb2\x4a\xb2\x5e\x65\x8f\xc6\x01\xb7\x15\xa8\xa4\xe2\x1f\x68\x95\xf8\xa8\x48\xc9\xd2\x28\x8d\xc7\xcf\xc8\xe2\x40\xac\xa7\x78\x66\x7b\x14\x7a\xab\xa8\x30\x21\x7d\xd9\x3f\x87\x9c\xd8\xa2\x43\xdf\x8f\xef\xa7\xfb\xa8\x80\xdc\xad\x82\x6c\xc5\x9e\x6c\x27\x76\x9d\x0a\x3b\x93\x5f\xf9\xed\x59\xf1\xe5\x3b\x84\x3a\xab\x2f\x7a\xaf\x61\xf6\x8c\xa3\xc6\x57\x24\x41\x87\x17\xa8\x34\x7f\xd4\xdf\x15\xa1\x86\xb4\x61\x8c\x58\xd8\x0a\x63\x1e\x0e\x46\x3f\x8c\xc8\xb3\x27\x64\x0b\x67\x9d\x65\x9e\x39\xa0\xc2\x2b\xe0\xe6\xcd\xdb\x94\xaa\x3c\xad\x46\xe7\xd5\xcb\x9e\xed\x08\xdb\x1a\xfb\xab\x6f\x96\x6f\xcf\xa7\x6f\xe9\x6b\xf9\x13\xdf\x1c\x6a\x79\x2a\x3c\x1e\xac\xcf\x0a\x6d\x45\x56\x48\x91\x06\xe5\x22\xe4\xbf\xaa\xa6\x0f\x4c\xb4\xeb\x6a\x7a\xf6\xf0\xad\xc1\x38\x2f\x56\xcb\x8b\xab\xfc\xe3\xa9\xf5\x55\xe5\x16\xce\xe6\x1c\x13\x4f\x39\x77\x63\xb0\xc3\xc5\xe5\x2e\x83\xbe\x3c\xc3\xfc\x26\xe2\x2f\x8f\x6f\xd8\xdc\x1c\x11\x8b\xe6\x81\x5d\xc1\x71\x1b\x15\xc6\x1e\x70\xa2\xcf\x4f\xbd\x4c\xbb\x39\x3c\x3d\x39\xa7\x5b\x30\x4b\xd7\x3c\xb5\x0b\x15\x60\xd9\x83\xad\x76\xca\x73\x6e\xf1\x18\x67\x8e\x4d\xe9\x5a\x8a\x11\x80\x1c\x4d\x8f\xa8\xd8\x76\xe5\x22\x4b\x85\xea\x52\xc0\x5e\x2b\x8e\xfe\xe6\x3b\x36\xc1\x19\xc3\x5e\x2f\xd1\xed\x86\x44\xc3\x42\x21\xe0\xc4\xa2\x6d\x3b\xc3\x47\x2e\x7c\x6e\x7c\x42\x2a\x22\x5b\x2e\x2a\xee\x24\x70\xf9\xbb\x1d\x44\xc4\x14\x37\x73\x62\x6a\x3b\x18\x3b\xca\x72\xa6\x70\x3c\xfd\xec\x82\x0a\x5b\x38\xe6\xbd\xb0\x5c\x3b\xfc\x39\x4e\x4a\x2d\xe6\xe4\x08\xb4\x35\xcd\x38\x33\x84\x3c\x82\x09\x25\xc0\x17\x71\x2e\x3a\x89\xc9\x55\x69\x41\xf0\xd7\x60\x62\x8a\xc1\xcf\xe4\x87\xd4\x45\x51\xd9\xa4\x63\x6f\x24\x8e\xe5\xba\xfb\x1a\xc3\x4e\x98\x30\x38\xe0\x77\x88\x84\x86\xf1\xa7\x98\x47\xa3\x4c\x7d\xc6\x66\x33\x6e\x25\xc6\x2f\x9c\x62\xac\x52\x7f\xf8\x40\x94\xc4\xb7\xb2\xd0\xbd\xd4\xd7\x22\xb9\x75\xb4\xb0\xcb\xe4\xc8\x00\x6b\x9c\xc2\xa0\xb5\x29\x87\xc6\x1c\xc6\x74\x63\xa4\xf1\xc3\x67\x27\x87\xe3\x4e\x4e\x0a\x1c\x2a\x34\x26\x27\x6f\xd9\xc1\xc1\x16\xbd\xf1\x0b\x8b\xf3\xcf\x3b\x3c\xe0\xe7\xd5\x33\x2f\x4d\x14\x20\x26\xbf\xe8\x6f\x31\x18\x45\x77\xe4\x15\x93\x75\xc0\xcd\xb3\x7d\x20\xf3\x72\xb0\x83\x6c\x8a\xf6\x4b\x35\x19\x8b\x32\x99\xeb\x94\xff\x8a\x8a\x31\xbf\x2f\x39\x3f\x4d\x8b\x2a\xb0\xbe\x5e\xcd\xb5\x6e\x67\x20\xd4\x10\x16\xcd\x43\x5e\x6f\x25\x4f\xd8\xdd\x2e\xf9\x00\xa4\x6e\x03\x67\xae\x4f\xe9\x6c\xe1\xe0\xed\x3f\x2e\x2d\xe1\x9f\x5e\xc6\x66\x1c\xde\x7f\xba\x5b\xbb\x27\xb8\x6b\x12\x16\xd6\x43\x52\xc1\x43\x49\xf0\x56\xb1\xd1\x10\xc0\xde\xd4\xce\x1f\xb9\xcd\xba\x22\xf0\xc3\x05\x76\xf5\x20\xb0\xd1\x3b\xb7\x4f\x97\x5b\x84\x73\xae\x8a\x4d\x61\xbc\x29\x35\x60\x45\x26\x69\x40\xc4\x4c\x59\x99\x07\x52\xc5\xd5\x8c\xf0\xfc\xf1\xaf\xc8\xf9\xe6\xc3\x87\xfb\x4b\x96\x67\xa7\xe3\xc6\x67\xb0\x0a\x20\x7d\xca\x1a\xe0\xf8\xe6\x6f\x40\x0d\xa0\xbb\xf9\x83\x5d\xe6\x5b\x14\x84\x5d\x00\x85\x7a\x6b\xba\x66\x60\x61\x65\x07\xdf\x06\xaf\xf8\xf4\x39\x78\x8a\x71\x2e\xab\x8a\xef\x1b\x06\xd8\xae\x74\x4b\xfd\xff\x6e\x95\x84\x8e\xdc\xba\xc3\x9e\x06\xb2\x6d\xc6\x82\x11\x70\xd4\x9e\xe9\x5e\x9b\x69\x8e\x7d\x30\xd4\x10\x13\x14\xe2\x82\x76\xcc\x0e\xb7\xa8\x71\x91\xa9\xb1\x09\x77\xe9\x52\x04\xf7\xf7\xa1\x4a\xc4\xd6\x54\x64\x03\xe4\xde\x05\xb0\x9a\x75\xbd\x01\x9d\x3c\xac\x99\xe8\x03\xf3\x7b\x38\xfd\x0d\x3f\xf2\x8b\x00\xf7\x77\x28\x0a\xe6\xca\x70\xff\x1a\x5e\x2c\x56\x93\x68\xe4\xfc\xc6\x6c\xfd\xe1\x70\xde\x45\x47\xbe\xf1\x57\x0f\x3a\x29\x8e\xf2\x5b\x44\x74\x84\x39\x50\xb1\x66\x57\x39\xc3\x6f\x17\xd2\xf9\x22\xd8\x19\x56\x52\xca\x57\x28\xa1\xe1\x08\xf7\x3e\x2b\x8e\xfe\x29\x34\x83\x1f\xe2\xf1\x51\x7a\x11\x5f\x56\x1f\xc2\xf2\x49\x4b\x62\x60\x2f\xbc\xd9\x3e\x07\x86\x27\x0f\x6b\xd2\xb4\x4d\x0e\x2e\x78\x4a\x6b\xd1\x5e\x63\x1f\xe0\x6a\xc0\xab\x78\xef\xd6\xce\x1c\xb4\xf9\xba\x3e\x1c\xa6\x21\xdf\x8e\x13\x3d\x19\x24\xd0\xa2\x28\x2c\xde\xaf\xa2\x9a\x03\xfe\x36\x42\x0b\x3d\x2d\x4c\xd6\x7b\x77\x98\x31\x80\x41\x27\xa6\x9c\x15\xa4\xa1\x3c\x38\x7e\x7c\x53\xf0\xe1\x0e\xd5\x86\x4a\xa3\x71\xa5\x81\xc2\xfe\xc2\x02\x70\x4d\x2d\x1d\xd0\x75\x06\x84\xf1\xe8\xcc\x74\xda\xad\xfa\x7c\x86\x17\x91\xf2\x9e\xdd\x7e\x48\xc5\x5c\x0a\x9f\x04\xa4\x1e\x79\x35\x75\xc3\x6e\x9e\xe0\xdb\x5b\x56\x42\xf2\x50\x70\xf3\x3f\x66\x1c\x1d\x95\x1c\x7c\x2b\x4a\xfe\x77\x8b\x99\x7f\xd4\xb1\x71\xdd\xf2\x7f\x61\xd3\x9e\xe5\x57\x67\x5b\xc6\x97\xff\x14\xf5\x5b\x9e\x74\x43\xc3\x5f\x9a\x15\xdd\xf3\xc9\x82\xce\xfd\x90\x7d\x95\x3c\xf8\x1b\xc6\x2d\xa7\x4a\x37\x4f\x38\xd9\xeb\x1d\x62\x95\x5d\x2e\x0b\xab\x07\xd3\xee\x0b\x15\x33\x52\x13\xe8\xda\xf0\x4c\x70\x1e\xc6\x7b\x58\x27\x62\xa3\x3c\xf5\xe8\x3f\x1a\xef\x52\x08\x1b\xad\x2d\x2d\x72\x71\xdf\x46\x05\xc1\x6e\x7d\x15\x70\x68\x37\xc8\xf7\x4b\x4b\x6d\xbc\x46\x1c\x23\xbf\xe0\xf1\xcc\x81\x32\x19\xf8\xf5\x68\x86\x93\x4a\x02\x61\x42\x15\x41\xba\x81\x8e\xf0\x89\xa3\x8f\x2d\xfd\x71\x3e\xfb\x39\x97\x02\xd1\x8d\xaf\x55\xbc\xdd\x92\x5b\xaf\x6e\xff\xaf\x29\x71\x70\x59\x57\xbb\x8a\xf8\x99\x05\x6d\xbd\x4a\x44\xda\x52\xac\x7a\x07\x51\xec\xfe\x69\x96\x5c\x07\xf9\x3d\x88\x1d\xba\x96\x19\xd3\x4c\x8d\x95\x85\xc0\xe5\xeb\xfb\x33\x38\x5c\x54\xdf\xfd\xef\x96\x7c\x61\xcf\x99\x85\xe1\x96\xd5\x3c\xac\xfd\x68\xc7\xfd\xa4\x2f\x1c\x27\xfe\x8a\x7e\x08\x0b\x53\xc0\x7b\x6b\x17\x78\x9e\x87\xcd\xf8\xb2\xcb\xf2\xa6\xff\x4c\x2c\x07\x56\xb1\x4b\xe1\x82\x48\xd1\x17\x8a\x3d\x0e\x87\x3f\x0c\x28\x5a\x6e\xf5\xbb\x0b\xb1\x68\xa8\x18\x54\xff\x2f\xee\x61\xb4\xd4\xa7\x88\x6f\xb5\xaf\x52\x33\x70\x72\x4c\x00\x0f\x64\x7e\x7f\xb4\xfb\x8c\x85\x5d\x86\x6e\xed\xc3\xda\xb0\x04\x7d\x18\x66\x10\x6f\x3d\xde\x99\xb1\xba\x3a\x23\xed\xa8\xff\xf2\x81\xe6\x4b\x18\x64\xc2\xbd\x4c\xa3\xe7\xe6\xbc\x36\xcb\xa5\xc4\xea\x43\xb1\x6d\xe7\x43\x7e\x88\x47\xcd\x31\x87\xbe\xb3\xda\xea\x59\x20\x82\xeb\x1f\xe2\xb4\x9a\xcb\x12\x75\xf7\x2c\x67\x87\xf9\x67\x41\x0c\x96\x1f\x2b\xca\x10\x9a\x3b\xf8\x47\x4a\xe8\x2c\x27\x7a\x8c\x12\xfc\xef\x26\x05\x62\xfa\xf1\xe8\x6c\xd5\x71\xbc\x7c\x84\x25\xdf\x74\xc7\x9c\xf9\x1f\x77\x62\xdb\xb8\x5b\x3b\x3e\xa9\xb1\x06\xfb\xee\x97\x3d\x13\x33\x6f\x2b\x1e\x17\xd9\xee\x0b\xf4\x87\xeb\x68\xe5\x3c\x3a\x25\xc6\x7d\x5d\x71\x5f\xd0\xf5\xc1\x4b\xb8\xd6\xb8\x03\xc6\x13\x33\xee\xa0\x37\xac\xea\xc2\x98\xe4\x8f\x4b\xf8\x35\x5a\x71\x97\xc8\x78\x83\x43\x17\x89\xc5\xcf\xc3\xa3\xb9\x34\xfd\x05\x27\xe6\x41\xd9\x26\x2b\x94\x27\x90\x5f\xff\x94\xa8\x80\x4f\x95\xd4\x59\xba\x0a\x6c\x0f\x4f\x79\x38\xc8\x67\x38\x23\x0f\x45\xb3\x5c\x84\x75\x3c\x5c\x52\x50\xac\xae\x65\xb8\x2d\x7c\x93\x56\x6c\x6b\x72\x4e\xe2\x16\x8c\x32\xeb\x95\x47\x55\x59\x25\xb2\x2b\xdd\x7e\xc6\x47\xbc\x24\x0b\x0d\x76\xea\x32\xfc\xae\xbf\x77\x99\xc5\x42\xfc\x57\x7d\x56\x88\x98\x60\x15\x4b\x04\x74\x5d\x90\xf9\xf3\x20\xe6\x35\xd2\x07\x56\xec\x8e\x0e\x17\xbf\xb1\x36\x3a\x0b\xe1\x74\x8e\x58\xeb\x38\x2d\x4d\x50\x50\x54\xbe\x29\xdd\xbd\x36\xeb\xb0\xde\xef\x66\xfe\xde\xb2\xd7\x30\x72\xb2\xfd\xa1\x9d\xc2\x80\xf3\x07\xcd\x79\x71\x39\x5e\x21\x3c\xd8\x77\x29\x75\x29\x42\x70\x61\x42\x0e\xd7\xfe\xb3\x79\x0d\xf6\x71\xc1\x7a\xba\x3c\xf1\xbd\xa4\x49\x7f\xef\x06\x93\xa2\xd9\x15\x69\x3f\x8f\x5f\xfe\x71\x8d\x62\xa9\x57\x6c\xae\x3d\x22\xfc\xd2\x57\x6b\x47\x7d\xe5\x27\x48\x78\xe0\x88\x45\x0c\xbc\x62\xe4\xef\x9e\x25\x61\x3f\xe3\x5d\x67\xb1\xc6\x8a\xb5\x3b\x3e\x1c\x16\x97\xc6\x19\x44\x90\x32\xd3\x73\x8e\x9f\x8f\x44\xfd\x85\x21\x57\x77\xec\x17\x0a\xb8\x85\xf1\x63\x11\x9d\xdb\x6a\x41\xa6\x11\x00\x07\xf4\xdf\x9a\xc3\x3a\xd2\xb6\xd1\x78\x8c\x38\x4d\xaf\xfd\x58\xbe\xc1\x7b\x4a\xd3\xdd\x41\x04\xec\x46\x24\x4e\x88\x07\xd6\xcb\x81\x17\xc6\x5f\x04\x7b\x2d\x6e\xca\xc2\xd2\xd0\xc4\x99\x49\xba\x8a\x4f\x84\x98\x7d\xfc\x6a\x47\x64\x32\xa9\x76\x42\xe2\x31\xa6\x7d\xc5\xbb\x88\x0f\xec\x15\x18\x27\x0e\x6c\x9d\x65\x2b\xed\x02\xad\x3d\xa4\x10\xf4\xaa\x6e\xa1\x22\x14\x35\x08\xab\x5f\x3b\x73\xbc\xfc\x03\xce\xf9\x52\x69\x17\x86\x57\x6f\xf9\x84\xbd\xf1\x0e\xfb\xa1\xff\xaa\xf5\x10\x20\xf0\x72\xd7\xde\x07\x85\xa2\xc2\x63\x62\x5b\x7d\x65\x8a\x41\x5e\x09\xde\x60\x27\xe9\x7a\xdb\xfb\xa3\x60\x03\x4f\x7b\x96\xc3\xaf\x17\x75\x9c\x4d\xde\x6b\x58\x9e\x5f\xef\x90\x8e\x22\x19\x97\xb9\x3f\x79\xa4\xbc\x74\x8d\x60\xa0\x56\xd7\x4d\x35\x58\x7e\xdc\xb9\xae\x14\x16\xcf\x91\xb0\x43\x73\x7b\xbc\x0d\x81\xfa\x85\x76\x00\x1e\x8a\x2d\x9b\xc2\x9a\x99\x59\x9a\x86\xcb\x0f\x75\x40\x7f\xaa\xee\xf6\xa0\xe2\x58\x51\xd7\x10\x3a\xeb\xa8\x13\xb3\xe1\xe6\x9f\x5f\xb5\xab\x20\x54\x20\xce\xcd\xfa\x79\x8e\x81\xe8\x59\x22\xb6\x5f\x96\x7c\xf6\x0c\xad\x9f\x68\xda\x8c\x12\x91\xff\x82\x24\xa7\xb8\xcf\xec\x5a\x15\x17\xe9\x6c\xf6\x9e\x30\xb0\xf3\x3f\x20\x17\xa1\xfd\xa7\x9c\x12\x00\x0c\x36\x6b\x4a\xce\xd0\x81\x06\x36\x0a\xa1\x7b\x6e\x11\x0f\xbc\x5b\xe8\xdb\xe9\x1b\x34\x60\x41\x5d\xae\xb6\x94\x83\xa5\x95\x92\xd0\x22\x3d\x58\x4d\xf2\x71\xa3\xaa\x82\x9c\x9c\x03\x1b\x92\x30\x41\x57\xff\x41\xec\x42\x17\x3d\x41\xf2\xfb\x91\x6f\x19\x59\x58\x13\x42\xa1\xab\x27\xd4\x71\xb5\xd4\x9b\x1c\xa2\xdd\x36\x91\x9b\x8f\xb0\x54\x15\xf3\x17\x66\x17\x1f\x29\xe7\x77\x51\x12\x77\x3b\x52\x16\xe2\x8a\xf0\x9b\xcc\x84\x48\x76\x68\xd4\xb9\xf0\xd2\xef\xc1\x7a\x4f\xf7\x58\x1d\xed\xcc\xc5\xa3\xbb\xf6\xd1\xe4\x02\xde\xa0\x7e\x99\x6d\x75\x10\xc6\x27\xc4\x66\x0b\x6b\x3d\x5b\xb8\x5b\x84\xd3\x00\x0f\x4d\x6a\xf9\xc6\x58\x79\xe7\x90\x1c\xa4\x80\x2c\xe8\x36\xff\xa5\xee\xa9\x15\xfa\xd2\x2b\x6e\x97\x35\xc7\x76\x89\xda\xec\x8a\x29\xea\x8c\x99\x5e\x83\xf0\xb2\x6a\xb3\x9b\x11\x7a\x3d\xa9\x48\x18\xc1\xca\x26\xc8\x7d\x2b\xf5\x49\x98\x48\x46\x36\x76\x55\xa6\xb0\x67\x3b\xfc\x72\x85\x3e\xe2\x63\xb8\x14\x22\xb0\xba\x4b\xe1\x66\x20\x07\x56\x65\xa2\x06\x41\xd7\xb5\xaa\x81\x0a\x2e\x9a\xd0\xb2\xd0\x4d\xe5\x6a\x6a\x89\xc9\x5f\x13\xeb\x24\x11\x09\xcd\x42\xec\x23\x91\x2a\xcf\xd5\x05\x45\x6d\xcb\x27\xaa\x27\x4b\x3e\x24\xcd\xb2\x22\x07\xd9\x30\xf5\x72\xbc\x0e\xbb\x8e\xf0\xff\x4a\xe5\x4b\xff\x2f\x99\xac\x2e\xd0\x95\x12\x00\xf4\x44\x7b\x0a\x5b\x9f\x32\xd4\x5b\x12\x0f\x0f\xf1\x0e\xef\xa3\x28\x2d\x42\x85\x9a\xe7\xff\xb1\xc2\x4c\x47\x4b\x9b\xd8\xce\x66\x1a\xb6\xf5\x8b\x0a\xc6\x95\x49\x82\xc9\x89\x84\xd6\x70\x34\x1e\xe5\xec\x17\xb7\x7f\xfa\xc7\x7b\xf0\x88\x56\x61\x85\x4b\x10\xf1\x67\x04\x22\x68\x59\x9a\xc4\xa2\x84\xe2\x13\x2b\x89\x2d\x72\xd8\xcf\xda\xdb\xce\xf9\xc8\x1c\x71\xe8\x33\x47\x65\x7f\xd5\xdf\x81\xbf\xb2\x6a\xef\x28\xfa\xc9\x98\xcc\x92\x71\x78\x58\x99\xe2\x52\x07\xda\x3b\x4c\x7e\x03\x4d\xf5\x54\xf0\xf5\xa4\x0e\x70\x52\xc6\xd9\x04\xe7\x50\xfd\x0c\xa7\x4f\x72\x01\xe7\x2e\xaf\x16\x8b\x0a\x45\x3c\x99\x70\x1a\xa1\x2c\x13\x87\xe7\xb7\xb2\x66\xdc\x84\x44\x6e\x7a\x02\x93\xc6\x1f\x53\x1e\x89\x43\x9e\x11\x4b\x7e\xec\x2c\x29\x0f\xc9\x31\x08\x58\x8e\x76\x21\x04\x43\x71\x15\x4d\x74\x14\xaa\x6d\xdd\xa9\x2c\x43\xde\xe1\xc6\x5d\x9b\x59\x77\x38\x75\xe7\x98\x13\x5b\x91\x29\x39\x6c\xa3\x3a\x16\xcf\xdb\xf5\xef\x00\xa5\x84\xb0\xe1\xb1\x05\x9b\x31\x78\xa2\x10\x5b\xb8\x69\xc8\x1d\xc4\xfa\x27\xda\x49\x87\x1e\x90\x31\x2c\x53\x24\xe4\x61\x88\x47\x78\x7b\x94\x08\x63\x2e\x60\xa7\xe5\xc5\x67\x8b\x09\xce\x07\x99\xec\x59\x29\x15\xf6\xe2\x94\xd1\xff\x81\x15\x86\xe3\x86\xfa\x52\x08\xcb\xbd\xc1\x84\x55\x04\x87\xc5\x4a\xed\xc9\xf2\x54\x1a\xac\x71\x66\xb0\xd3\xbd\xf5\x01\x4f\x0d\xc0\x31\x18\x95\x78\xf7\xf4\xf8\xae\x88\x5a\xe2\xd5\x38\xe8\x36\x02\x17\x31\x86\xc2\x3e\xac\x0f\x79\xc6\xaf\xe0\x85\x48\xe7\x64\x36\xd2\x90\xff\xd8\xdd\x01\x41\xa1\xa5\xdb\x90\x7b\xcd\x85\x73\x0a\xbf\x5e\x98\x9c\x88\xea\x98\x5a\xf5\x1b\xf6\xd9\xf0\x43\x08\xed\xec\xbb\x99\x96\x6d\x4d\xcc\x71\x74\xac\x89\x35\x36\xb5\xa2\x57\xc1\xe9\xd0\x45\xf0\x4b\xa4\x3e\xe9\xb3\xb8\x22\x3d\x0c\x5c\x06\xc1\x8b\xf0\xa3\x50\xd9\x28\xcf\xed\x96\xe7\xd3\x35\xf9\xb5\x4b\x62\x05\x18\xda\x5b\xfa\x8f\xcd\x58\xe0\x84\x35\x1c\xc4\xf8\xc3\xbc\x4e\xa4\x2d\x78\xbd\xce\x36\x48\x3e\x24\x88\xfd\x31\x0d\x23\x5a\xcd\x0e\x5a\x89\x66\xa3\xc9\xf2\x8c\x05\xc1\x23\x56\xa6\x87\xa8\xb6\x84\x2b\x49\x3e\x94\xc4\x7e\xfc\x32\xaa\x8e\xa8\x2a\x2f\x3d\x0e\x81\x27\x0e\x24\x39\x62\x57\x67\xd2\x64\x38\xbf\x83\xdb\xe2\xdf\x0c\xa4\x5f\x30\x63\x5c\x9f\x9e\x6d\x55\xe8\x88\x06\x6d\x11\x1f\xc1\x15\xf6\x55\xe3\x28\x16\x4d\x4c\x52\x40\x3e\x68\x07\xe4\xc1\x68\x5f\x3f\x53\xe4\x61\xaf\x3a\xac\x09\x89\xda\x82\x11\xf3\xfd\x45\xad\x26\x79\x38\xe3\x71\xe0\x48\x2c\x0d\xcc\x7e\x4a\x1d\x63\xe5\xbf\x99\x26\x2c\x30\x47\x8d\xb1\xf7\xea\x2f\xb8\x2d\x3f\xc0\x3a\x69\x99\x3a\x2a\x77\x9e\xf4\x40\x17\x8d\x9c\x3f\x00\x92\x7b\x07\xb1\x48\x8a\x85\xdf\xf9\xa3\x29\x75\xf6\xf0\xc5\x4a\x93\x33\xc5\x0d\xbf\xb9\x0b\x13\xaa\xcc\x6d\xf8\x9d\x39\xeb\x78\x67\x96\x6f\x72\x43\x09\x7a\x22\x88\x9e\x5e\x86\xf2\xaa\xf0\x92\x7d\xf1\xa7\xfd\x2a\x7a\xb9\x5f\xbe\x3f\xbc\xec\xd3\xa0\xe1\xe0\x9f\x3c\x64\xc4\x51\x15\x58\x9d\xd3\xf3\xec\xa8\x7f\x3f\xf5\xa8\x55\x95\x3b\xdb\xc4\xab\xde\x1a\x6c\xdb\x16\xe8\x5f\x58\x57\x0a\xa8\xac\xe2\xb0\x7b\xc8\x17\xc1\x53\x14\x69\xe9\xca\xe2\x63\x5f\x9c\x0e\x5c\x34\x4d\xb8\x1c\x49\xf7\xaa\x0c\x66\x6a\x78\x74\xd7\x34\x95\x95\x10\xfd\xca\xb6\x8c\x00\x32\xd4\x2c\x21\xf3\x2d\x0a\xbc\xcc\x41\x49\xcc\x63\xd8\xac\x25\xe1\xa8\xe7\xbe\xa4\xb7\x17\xa6\x56\xea\xb2\x32\xf4\x29\xf6\xcf\x3e\xfd\xe3\x9f\x5c\x15\x09\xb6\xf8\xbe\x61\xbf\x7c\x0f\x58\xc1\x2a\xda\xaa\x69\xf6\xda\x38\x8b\x65\x70\x4b\x10\xe7\x22\x06\xb2\xe9\x94\x79\x01\xac\x13\x0c\xb4\x94\x62\x79\xc8\xcd\xd0\x6a\xd8\x68\xf8\x4f\xeb\x68\x8b\xe4\x2f\xef\x44\x2c\xc8\x45\x2f\xed\xa7\x41\xfd\xab\x2f\xc8\x51\xf1\x82\x82\xe5\x1c\xcb\xb4\xf2\x2a\x3a\xee\x41\x83\xc5\x03\x89\xd9\xfe\x78\xff\x13\x30\x76\xa9\xd6\x81\x97\x1b\x49\xa8\x47\x5d\x83\xd9\x72\x48\xbf\x11\x51\xc1\x18\x3a\xa0\xcd\xc3\x72\xaa\x52\x09\x4f\x9e\x48\x75\xb8\xa2\xce\x27\xe7\xd6\x12\xfa\xc3\xdd\x84\xc4\x69\x67\x39\x0c\x5d\x70\x94\x66\x47\xe2\x65\x89\x12\x99\x67\xfe\x0e\x75\x3f\xcb\x60\xd6\xae\x7b\xd9\xa8\x9a\xf7\x90\x4b\x2e\xc0\xd9\xd3\x14\x1b\xfa\x65\x89\x62\xe0\x3c\xeb\x78\x6b\x06\x45\x98\xfe\x2b\x12\xd7\x40\x48\xa3\x34\xcd\x9f\x0d\x2b\x48\x90\x2c\x45\xf7\xc4\x70\x18\x54\xcc\x4f\xbf\x97\xeb\x25\xfb\xa0\x7a\x5e\x52\xde\x70\xf0\xa8\x54\xee\x0a\xf7\x2a\xbe\x7c\x35\xfa\xad\xad\xaa\x9e\xc6\x88\xdc\x17\xf9\xad\xc2\x13\x60\x6a\xd1\x4a\xae\x68\x9b\x93\x12\x2f\x95\xd9\x5d\x4b\x92\x3e\x84\x52\xde\x34\x75\x43\xb8\x99\x8a\xd7\xaa\xa8\x95\xfa\x4f\xbf\x0f\xbf\x77\xee\x64\xb8\x78\x04\x8c\xda\x6f\xf0\x6f\x28\xa7\x0c\xea\xd7\x12\x5a\xe0\xdc\x24\xa0\xc0\x48\x8b\x6c\x8c\xd6\x5f\x01\x6b\x55\xf7\x41\xef\x1f\xf7\x9d\x53\x5f\x6d\x15\xe1\x3f\xd5\x34\xfc\x89\xf8\xd9\xfb\xe4\xa3\x8f\xc9\x63\x3e\xee\x1a\xe3\xac\xda\xba\xfd\x09\x84\x21\xad\x8c\x8e\xa3\x62\x75\xda\x8d\x2f\x86\xe3\x1e\x59\x2e\x93\x94\x87\xb2\x78\x0b\xdd\xd4\x52\x5b\x60\x1a\xfa\x79\xcd\xc7\x59\xef\x2d\xd8\x45\x6e\x55\xc7\xb6\xb7\xb7\x5e\x76\xc9\xaf\x43\x03\x74\x7b\xbf\xe3\x16\x05\x33\xc9\x1f\x9e\xcc\xb5\x5d\x32\x0f\x57\x38\xd2\x8b\xdb\x48\x65\x8c\xd4\xd9\xf3\xed\x66\xcb\xaa\x7d\xeb\x1a\x63\xf3\xa4\xa9\xf9\x06\x9b\x4a\xc2\x9d\x95\xf9\xd5\xb3\x95\x1f\x2c\x70\x65\x11\x39\x17\x82\xc4\x1e\xd6\xc6\x7f\x82\x47\xbc\x3f\x96\x6b\xe2\x9b\x6d\xcb\xa7\xc6\xe8\x83\x4b\x5a\xfe\xc0\x88\xf1\x8d\xfb\x0f\xb7\x94\x24\x3a\x56\x01\x69\x90\x7e\x6f\x57\x73\x94\x9a\x64\xca\x72\xb3\x53\x9b\xdc\x37\x90\x55\xee\xd9\xd4\x36\xc8\x75\x25\x9b\xca\x6b\x60\xff\x21\x55\x41\x63\xb6\x83\x9c\x01\xa6\xc1\xe0\x3e\x0a\x63\x7b\x3d\xe5\x43\x53\x3a\x7d\x2e\x7c\x10\x26\x52\xdd\x29\xd0\x09\xef\xdd\x1c\xf1\x70\x01\xa5\xda\x4f\x0a\x83\xdd\x08\x1c\xc0\xb5\xac\x8a\x66\xe4\x6b\xec\xe3\xf7\x44\x11\x6c\x78\xec\x79\x05\x0c\x8f\x80\x77\x62\xb4\x8d\x57\x59\xbe\x80\x80\x90\xb2\xe5\x83\xd0\xcd\x08\x2a\x9c\x72\x6f\xb6\xa1\x89\x8d\x37\x11\x48\x46\x7f\x25\xfd\x0b\xe9\xf1\xcc\x29\x29\x3e\xd0\x4a\x16\x7e\xc1\xe2\x1c\xed\x5d\x02\x5c\x46\xf6\x64\x5c\xbe\xb0\x71\xcd\xbb\xff\xd9\xa0\x31\x86\x74\x99\x75\x08\xe6\xf1\x11\xac\xf9\xbc\x35\x7a\x78\x1e\xaa\x44\x6d\x91\x17\x9e\x40\x1e\x32\x47\xe4\xb7\x56\xa2\xbe\x6b\x47\x81\x0f\x19\xbc\xcf\xe5\x73\x51\x03\x54\xfe\x87\x3d\x8c\x1a\x1f\x0d\xeb\x1c\x97\xf5\x47\x78\x22\x70\xa6\xcf\x8c\x39\xb7\xe9\xc5\x02\x09\xf9\x3c\x05\x9f\xe1\xf2\xfe\x14\xb5\xd7\xd9\x54\xf8\xa6\xac\xed\x01\x1c\x2a\xa7\x6a\xda\xdf\xa6\xe4\xb9\x70\xf8\xd3\x86\x36\x04\xff\xdd\x4b\xee\x93\x35\x37\xfc\x77\x55\x68\xdb\x0b\xdb\xcb\xd3\x66\x09\x8a\xe6\x70\x70\x9f\x43\x7c\xab\x1c\x3b\xe1\x55\xe3\x0f\xcb\x33\x62\x5c\x97\xbe\x90\x9b\x89\xf8\xb9\xac\x15\x77\xb4\x21\x67\xd9\x03\x2f\x2e\xb6\xec\x63\xa2\x04\xd2\x75\x20\xc3\xb7\x6d\x19\x6c\x94\xa0\x9f\x16\xf3\xc9\x96\x00\x2e\x20\x02\x7b\xb0\x32\xff\xd9\xde\x90\xa3\x69\xbb\x83\x78\x9b\x76\x52\xb1\x15\xea\xed\x94\xd7\x63\x44\xfa\x10\x92\xfe\xc9\xc4\xfb\x96\x62\x0f\x39\x91\x44\x1c\x3d\xf3\x9e\x91\x25\xd9\x09\xc0\xb3\xb5\x86\x39\x7d\x6b\x6f\xad\xc5\x79\x5b\x09\x70\x04\x9f\xa0\xea\x4f\xb5\x3b\x49\x90\x35\x88\x79\x2c\xf0\xc3\x3c\x14\x4c\x02\xc9\x92\x52\xb8\xec\x00\x38\xcd\xb2\x0e\x8c\xe4\xd6\x23\x6c\x05\xeb\xff\x47\xd6\x9b\xa5\x3b\xcb\xf3\x4c\xa3\x73\xc9\xf1\x3f\x29\x03\x0e\xb0\x68\xcc\x0b\x38\x79\x92\xd1\x6f\x95\xaa\xe4\xdc\xdf\xb5\x8f\xf0\x4a\xb7\xd2\x80\x6d\x95\xaa\xf9\x2f\x6e\xb1\xaa\x9c\x8e\xff\x30\x14\x8e\xcd\xbf\x1c\x09\x61\x1a\xcc\x01\xa4\x44\x2d\x64\x1d\x84\xc9\xb0\xc1\xd9\x25\x30\x22\xd5\xdf\x77\xfa\x0a\x09\x0a\x42\x98\xed\xfa\x03\x83\x5e\xa5\x31\xa2\x12\xad\x5b\x45\x23\xee\x20\x8e\x75\xc3\x97\x2e\xf3\xbd\xa0\xe6\x73\x0a\x01\xb4\xe9\xa7\x60\xb2\x8e\xed\x49\xb7\xd0\x59\x69\xc1\x06\x69\x90\x5d\x0f\x31\xf2\xa3\xfb\x03\x77\x69\x95\x76\x68\xf1\xd3\x3e\x31\x23\x39\xdd\xbb\x5f\x0f\xb6\x3f\xf4\xcf\xfb\xa0\x6e\xc8\x0f\x9d\xc8\xaa\x88\x85\x21\x15\xd5\xa1\x7e\x0c\xd6\x21\x89\x39\xc0\x44\xe6\x7f\xb2\xa0\x52\x97\xb8\xf9\xf8\x7e\x70\x1b\x3e\xd7\x97\xf3\xd6\xa7\x68\x3e\x79\x73\xff\xf4\xae\xbb\x28\xa7\xc1\x16\x79\x2b\x34\xec\x05\x5f\x4a\xba\x0a\xfb\x6e\x9a\xbe\x82\xf3\x40\x86\xdd\x2b\xbd\x28\xef\x4e\x57\x17\x8b\xf2\x2b\xed\x30\xe6\x10\x4c\x3c\xb0\x26\xae\xa3\x2c\x27\xdd\x7a\xb8\x61\x59\x77\xf5\xb3\xc0\xde\xef\x38\xc8\x1b\xa7\x52\x0a\x77\xcb\x1e\xce\x63\xf9\x7e\x18\x31\x27\xb9\x5b\xe6\xb3\xa1\x77\xb3\xf2\x42\x89\x07\x9c\xac\xef\xa4\x6e\x2c\xa2\xfc\xf8\x72\x8a\x22\x42\x93\xc0\xb1\xd1\xb7\xac\xd5\xaf\x7a\xf7\x00\x62\x39\xde\x9b\xa9\x05\xbe\xc3\xd6\xdb\xc7\xf7\x29\x9f\x40\x18\xf9\x3c\xc4\x34\x75\x19\x0e\xf7\xdd\xf0\xa5\xd3\x80\xdc\x52\xd0\xde\x7d\xe0\xdb\x63\xa1\xd0\x63\xbc\x36\x3a\xdb\x18\x80\xfa\xa8\x30\x86\xa3\x91\x4d\x25\x1b\x2a\xff\xc7\xe4\x87\x5d\x6c\xc0\xa7\xfe\xef\xe7\xf0\x20\xb4\xf5\x91\x8b\x97\x8d\x08\x34\xcb\x9f\x47\x26\x54\x61\xd4\xd3\xb4\xe3\x53\x18\xfd\x30\x68\xee\xca\x49\x0b\x1e\x29\xa7\x3f\xa7\x64\x6d\xc8\xd3\xfa\x25\x76\x7c\x29\x62\x5e\xdb\x53\xe0\xca\x34\xcc\x40\xd4\x7c\x83\x9c\x69\x94\x81\x7d\x37\xb7\xd0\x11\x78\x79\x7e\x3a\x29\x6d\xc1\x72\x98\x83\xe6\x80\x82\x2d\xa8\x08\xe0\x38\x04\x16\x73\x16\x5b\x30\x44\x14\x3d\x7f\x3d\xb4\xb3\x0c\x84\x13\xdd\xb3\xda\x8f\xc3\x2a\x63\x9f\xc0\xab\xfb\x5e\xb2\xd7\x33\xcf\x61\xd1\xac\xfa\xe8\xcc\x0a\x94\xf8\x70\xe7\xee\x50\xb5\xcd\xbc\x2d\x2a\xf4\x7f\xd5\x5f\xcc\xb7\x92\x0f\xa7\x3c\x44\x3e\xf3\xe1\xbb\xc0\x07\x71\xec\x33\xb2\x21\x62\xc3\x9d\x43\x2a\x61\x85\xa2\x6d\xa8\xb8\xb5\x76\x5d\x89\x53\x10\x3e\xc1\x8e\xdd\xcb\x0f\xa5\x56\x38\x62\x52\xe3\x71\x4f\x12\xa6\xc3\x55\x6f\x16\xaf\x00\xf3\x6e\xf8\x9a\x39\x05\x61\xe7\x80\xd6\xcb\x1e\x0d\xe5\xfc\x72\x1f\x12\x3d\xc2\x50\x02\xa3\xc0\xc7\x00\xf7\x50\xff\x43\xd7\xc4\x87\x6f\xa1\x1b\x41\x35\x5e\xc3\x65\x2c\x0e\x81\xff\x08\x3f\xa2\x28\x70\x2f\x6c\x97\xc9\x1a\x69\x4c\xc2\x76\xb6\x4c\x2d\x4f\x96\xa3\xe2\x29\xbd\xd0\xe1\x2d\x3a\x3e\xcd\xb9\x0a\x3e\xb0\x2a\x80\xb7\x78\xe8\xbe\xff\xab\x7e\x88\x06\x2a\x36\xe8\xa5\x05\x35\xaa\xe6\x80\xf2\xa8\x92\x3d\xe2\x22\xa4\xb3\x59\x06\x6d\x47\x17\x5b\x71\x90\x5e\xe7\x06\x7f\xd7\x2f\x01\xee\xaa\x40\x27\xc5\x2c\x93\xb8\x48\xf6\x84\xbd\xb5\xa4\xbd\xba\x2b\xe9\xf9\xf6\x12\x8d\x47\xd7\xda\xab\x2b\x0c\x26\x1d\x2f\xb3\xb5\x10\x27\x5e\x35\xf1\xac\xb3\x58\x69\xee\xc1\x4b\x98\x59\xb6\x59\xab\x67\x61\x3e\x88\x46\xc7\xa6\x76\x0d\x49\xfd\xb3\xc8\x66\x74\x05\xbc\x42\xc0\x65\x61\x2c\xe6\xb2\x57\xe5\x3f\xe9\x22\x07\x11\x38\x16\x6d\xdb\x77\xf7\x12\x56\xda\x42\xc8\x1d\xcf\x32\xff\x92\x6b\x6c\xdc\x8c\x54\x96\xdc\x3c\x80\x8e\xd8\x90\x6f\x81\x45\xf3\xfa\x5c\xb4\x77\xa7\x93\x93\x93\x15\x14\xa7\xbc\xbb\xda\x81\xfa\xa5\x8d\xb6\x41\x6a\x07\xfe\xa1\x25\x44\x27\x21\x5b\x71\x98\x95\xa4\x2e\xbd\x6d\xc2\x47\xf6\x3a\x27\x9a\x57\x4e\xb3\x90\x6c\x86\xe4\x4f\x2d\x69\x71\xca\x32\x8f\xb6\x19\xe6\xdb\x76\xda\x7b\x78\x57\xda\xa6\x5b\xf3\x85\x47\x4a\xf9\x31\x94\x4b\xb2\xf2\x1c\x2b\xb1\x1b\x19\x56\xe7\x9d\x7e\x89\x67\x73\x9c\x2e\x59\x99\xb8\xe4\xad\xfa\x86\xdb\xdd\x6f\x39\x52\x14\xc4\x88\x22\x20\xa0\xe5\x9e\x3f\xc4\xf8\x4f\x00\x85\xad\x57\xdf\xe0\xa9\xd2\xfc\x3a\xad\xcd\xe4\x47\xbe\xd9\x29\x9f\xfa\xa6\x9f\x55\x0b\x10\xa2\x2e\xb8\x21\x3e\xa9\x14\x7e\xce\x25\xec\x53\x9f\x6a\x83\x3e\x49\x21\xdf\xc2\x28\xe1\x99\xe5\xa0\xff\x04\x37\xd4\x8f\x9d\x16\x36\xe4\x6b\xfb\x26\xb7\x8a\x0e\x01\x84\xd0\x07\xb0\xde\x26\x2f\x82\xe9\xd9\xa2\x44\x02\x7b\x8e\x90\xe5\x33\x44\xd1\x43\x95\x47\xf2\x10\x26\xec\x03\x88\xc1\xf4\x78\xcc\x6f\x65\x52\xb1\x56\x1d\xca\xe5\x33\x3b\xc7\x91\xff\x39\xcc\xa7\xbc\xb5\x87\xf9\x29\xab\x0b\xdb\x5a\x9c\x0b\xef\xc4\xbe\x5a\x7b\xec\x30\x0e\xda\x23\x0c\x2b\x83\x4f\xa4\x3d\xf1\xa6\x4c\x3a\xec\x98\x1d\xb3\x7f\x38\x17\x63\x8d\x38\x4b\xf6\xc3\x07\x5d\x88\xbd\x9d\xcf\x14\x2e\x60\xaf\xfc\xd1\x31\x18\x18\x95\x5e\xc6\x8e\x58\x6b\x9b\xda\xa6\x8f\x1e\xeb\xf5\x49\xaa\xa6\xbb\x39\x93\x6b\xf1\x12\x52\x5d\x95\x7f\x61\x9b\x62\xca\xef\x4b\xb0\x3a\x40\x58\xe6\xb6\x19\x00\xfd\x1e\xbc\x0d\x6e\x5a\x01\xb6\xfb\xd1\x49\x17\x1d\xb3\x2e\xfa\x19\xd6\x49\x3e\x9a\x6a\x38\x13\xf6\x48\x7e\xf9\x6d\x93\x3d\x28\x97\x9f\x1c\x05\x38\x36\xa6\xdc\xac\x7b\x07\xc3\xf7\xd5\xdc\xcf\x71\x93\xbc\x1d\x24\xdc\x01\x23\x9f\x15\x63\xee\x61\x1c\x1f\x29\xa9\x7a\x99\x70\x75\x9e\x41\x18\x2e\x91\x57\x20\xe0\xb6\x97\xca\x1a\x69\xbb\x0b\xd5\x39\x31\xf6\x53\xc2\xd4\xae\xbc\xb9\xff\xa5\xe7\x91\x00\xe5\xb2\xcb\x5c\x72\x8d\xc4\x4c\xce\xc2\xdd\xda\x78\xb1\xb8\x8e\xe4\x24\x29\x69\x2f\x93\x24\x7c\x40\x05\x63\x17\xf6\x66\x5d\x22\x5e\xd7\xb9\x0f\x39\xd1\xef\x73\x4f\x54\xf6\xa3\x0b\xa1\xa8\xaf\xb5\xab\x59\x36\x93\x11\xfd\xdf\xa5\x9f\x60\x2a\xd5\x4f\xa6\x31\x75\x0a\x57\x49\xd7\x38\x68\x6f\xcc\x9d\x9d\x4d\xb6\xb4\x03\x4e\xc1\x77\x48\x08\x3e\x91\x44\x14\x3e\xec\xfe\x3d\xd9\xb4\x3f\x3b\x71\x28\x59\xa1\xbe\xcb\x5a\x2a\x21\x91\x09\xa7\xc8\x17\x6d\x46\xdf\x26\xbb\x86\x1a\x83\x14\x06\xaf\x9f\x7a\xfb\xc2\xf2\x09\xcb\xc3\xf7\x67\xe4\xbf\x7e\xd7\xd3\x35\x5c\x95\x33\xfb\x7b\xf6\xec\x1a\x42\xd2\x90\x6d\x89\x3a\x6b\xcb\x38\x69\x1f\x13\x04\xb9\x82\xaf\xe7\xeb\xab\x63\xb3\x02\x07\x0d\x2e\x25\x0e\x7d\x0f\xf9\x4e\xff\x05\x27\xf7\x5f\x7e\xbe\xfd\x25\xe7\xef\x71\x94\x63\x85\x82\xc7\x1e\xdc\xac\x13\x8e\xb2\x3a\x59\xd3\x00\x33\xc7\x9c\xd9\x01\x8b\x91\x4f\xe9\x39\x1c\x3e\x61\xc1\x94\x77\x6f\xd1\xf2\xa2\xab\xc2\x38\xea\x4e\xb9\x5f\x75\xf6\xe9\x5d\x37\xed\xa8\x49\x2f\xb8\x4f\x8a\x60\x99\x0e\xea\x83\x00\x6e\x6f\x39\x0e\xdf\xf3\x11\x7e\x97\x6b\x23\xea\xd2\xcd\xc9\xc7\x68\x9b\x09\x77\xcf\x77\x10\x7e\xee\xcc\xa8\xcb\xdb\x49\xfd\x3d\x87\xae\x8d\x79\x00\x32\x5f\xb4\xf5\x7c\xff\xe8\xbb\x6f\x24\x94\x11\xde\xae\x8d\x5b\x51\xb5\x0b\x0f\xff\x4a\x7b\x9b\x1d\x8f\xe9\xa3\x76\x1d\xb6\xf4\x5b\x90\x7e\x5f\xaa\x35\xae\x3b\x24\xd5\xbe\x23\x6d\x00\xf6\x21\x78\xfa\x08\x77\x89\xeb\x20\x7e\x03\x76\x15\xb9\xc1\xfe\x15\x62\x1b\xaf\x6c\x1d\x1b\x32\xe7\xcb\x4e\x85\x21\x9e\xb5\x0a\x21\xbb\xb4\x88\x13\x69\xf7\xd2\xdd\xce\x84\x59\x06\x04\x6e\x40\xe5\x83\x71\x6f\xbd\x2b\xfb\x63\x6c\x9b\xff\x88\x41\x9d\x90\x6a\x1d\x9b\x70\xa7\x83\xb0\x18\x98\x3d\x2f\xcb\x36\xfd\x47\x0b\x45\x3d\xb1\xe1\xe4\x93\x52\xe0\x58\x57\x13\xa7\x45\x68\xee\x95\x37\x39\x0b\x6c\x9b\x82\x53\x15\xac\x71\xe5\xf8\xf7\x40\x08\xb8\x53\xba\xfa\x19\x4a\xfa\x5d\xd0\xbd\xed\x02\x03\xce\x0f\x7f\x85\xe6\x60\xa5\x3f\x1a\x9b\x25\xcf\xa1\x72\xcb\x59\x89\xab\x77\x18\x5a\x21\x71\x75\xe6\xe8\x24\x2f\xf1\x42\x42\x8f\x2c\x3c\xaf\x5f\x10\xdb\x95\x9a\x5c\xff\x92\x50\xfd\x94\xf7\xe6\x59\x23\xa8\x85\xec\x6a\xdf\xf9\x57\x0a\xa3\xdd\x83\x57\x78\x7e\xe9\xa2\x0b\x30\x33\x91\xef\xcc\xff\xc1\x6d\xd7\x47\x11\xe7\x9a\x77\xd6\x13\xfb\xed\xd9\xed\xbc\x2d\xbe\x44\x48\xe5\x34\x48\xcd\x11\x61\x63\xa5\x11\x9e\x59\xe1\xd6\x7c\x7c\x04\xbc\x1c\xa7\xac\xb3\xd0\x6e\x65\x0f\x00\xa3\x08\xb2\x63\x59\x62\x0b\x02\xbf\xe7\x83\x79\xe8\xf0\xd4\x4a\xea\x11\x7c\xc5\xa7\x19\x4e\x12\x79\x8e\xf4\x33\x3e\x98\x05\xbc\x1c\x49\xf5\xb6\x9d\x44\x6e\xac\x75\x76\x2a\xa8\xa8\x96\xf3\x27\x20\xe5\x8b\x26\x59\x36\xd5\xb7\x82\xc5\xdd\xd9\x3f\x3e\x6a\x6b\xef\x9e\xde\x60\x5c\x79\x7d\x20\x9a\xed\x56\x37\x06\xac\x96\xf3\x98\x58\x12\xb8\xca\x3a\x52\xbf\xb7\xf9\x93\x62\x63\xb9\xe1\x6c\xa6\x99\x80\x5b\xd2\x06\xce\x8f\xb0\x69\x92\x52\xe4\xf7\xb3\x29\x36\x0b\xd8\x7e\x4e\xf2\x02\xdd\x23\x78\xc6\xca\x8a\x39\xd2\x65\xd6\xbc\x36\x07\x51\xb7\xd9\x3c\x03\xfc\xcf\xf9\x15\x05\xc5\x1e\x49\x33\xf7\x1d\x22\xb8\xe6\x5c\x20\xa5\x07\xea\x01\xf9\x37\x42\xcc\xa9\xf2\x29\xa1\x56\x92\x52\xcf\x16\xab\x70\x6e\xde\x1a\x53\x27\x31\x5c\x7b\xfd\xec\xe4\x21\x7f\xd8\xa5\x74\xda\x0c\xcb\x87\x65\x11\x0b\x46\x47\xdb\xc3\x7b\x5d\x30\xaf\xc1\x8c\x06\xf8\x0a\xa3\x95\x87\xa3\xfd\x22\xc6\x8c\x51\x65\xe4\x81\x39\x38\x20\x46\xb3\x73\xb3\x7a\xd9\x23\x02\x8c\x6c\xd5\xbd\xf6\xe0\x72\x03\xdf\xc1\x3d\x58\x31\xb6\x3e\x3c\x89\x23\xc0\x64\x54\x7b\x3a\x30\x68\x95\x39\x8f\xbd\x98\x5a\x23\x56\xa9\xa4\x60\x53\x0f\x36\x73\xe5\xca\xd7\xb0\x9d\xc2\x4e\xb9\x5e\xc2\x1e\xa0\xe7\x48\xba\xea\xe5\xe3\xaf\xb3\x9c\x64\x23\x2d\xa7\x0e\x3a\xed\x97\x52\x9d\x6b\x66\x45\x0c\x69\x20\x70\x4c\x50\xd9\xb2\x05\x3b\x3b\x3e\xeb\x92\xc9\xf9\x59\x52\x44\x20\x2c\x11\x3d\xb9\x24\x01\x97\x7f\xde\x93\x54\xcc\x4e\xab\xbd\x6d\xb5\x67\x51\x62\xe5\xc9\x4b\xbf\xec\xc4\x96\x8e\x1d\xd4\x69\xb8\x44\xba\xde\x20\x12\xe6\xf0\xb9\xa7\x51\x41\x3c\x3b\xf9\xd3\xb6\xff\x61\xf9\x52\x82\xc6\x34\x51\x84\x3c\x15\xba\xed\x4f\x0e\x76\xad\x9a\x11\x11\x03\x91\x3b\x6d\x44\xa6\xbc\x89\x5a\xb3\x86\x13\xd8\x8e\x85\xa9\x39\xd6\xb7\xde\x41\x56\x10\xe4\x94\xec\x6e\x19\x9a\x56\x76\x15\x2e\x9c\x64\xa1\xf9\x8b\x34\x1f\x09\xef\x30\x83\x5f\xc1\xef\x8e\x44\xb0\x09\xb6\xb6\x61\xa6\xea\xcb\xf5\x58\xef\xa9\x45\xe2\xd7\xb5\x3b\x83\x70\x32\x0a\xdc\xa0\x2b\x2a\x4d\xc0\x4e\x36\x5d\x50\xcb\xda\x2e\xc1\xb1\x82\x30\x39\x1c\xcf\xc8\x06\x64\xcd\x88\xbe\x44\x94\xb5\x63\x91\xb3\xcd\x38\xdb\xd9\x91\x1e\xcd\xc5\x41\xf1\xfa\xab\xba\x17\x88\x34\xf1\xb5\x90\x85\xd8\x83\xb2\x41\xde\x09\x22\xa0\x3a\x16\xf4\x7a\xf8\x75\x23\x54\x1e\x55\x75\x78\x40\xe0\xf1\xb6\x80\xad\x05\x4a\xe4\xff\x4f\x0d\xed\xe7\x3f\xe2\x01\x28\x06\xc3\x3e\x35\xd4\x36\xcf\xf6\x51\x9f\xaa\x80\x9f\xc0\xe5\x6f\x95\x5b\xf6\xe6\xed\xe4\x73\xe8\x22\x8b\x00\x9f\x2f\x6f\x8f\xd0\x8b\xd2\xdd\xe7\xa2\xc0\x52\x25\x96\xae\x9b\x60\xe4\x50\x9d\x00\xed\x95\x4b\xf5\x95\xc3\x7e\x61\xd5\x0e\x43\x79\xb3\xcb\x10\x05\xd8\x3f\x61\xb3\xc3\xec\xde\x34\x3e\x7a\x06\xaa\x0d\x75\xb0\xce\x0f\x7b\xe7\x3c\xed\x59\x42\xb1\x34\x12\x29\x12\xfd\x85\x93\x09\xad\x18\xee\xac\xb9\xfa\x6c\x0b\x25\xef\x6e\x4e\x07\x03\x08\xfb\x72\x75\x85\x16\x81\x44\xcd\x21\xf1\x7d\x25\x2d\x1a\x43\x3a\x43\x79\xb8\x6a\x13\xe5\x55\x18\x2b\x2d\xda\xf1\x80\x23\xef\x75\x54\xb5\x0b\xce\x5f\xa5\xa7\xfb\x8e\x8b\xd6\x55\xbc\x9c\x11\x38\xec\x49\xe4\xe1\x25\x51\x69\x3a\x0d\xf3\x4b\x16\x5c\x9b\xf3\xf1\xfb\xf5\x13\x9d\x06\xc5\x9a\xf5\x39\xde\x88\x0b\x13\x67\xc9\x0f\xe9\xd7\xe5\x48\x0d\x49\x31\xb6\x43\x8d\xbc\xe2\xf0\xc2\xb1\x65\xea\x90\xea\x70\x15\x38\xd5\xd5\xf9\x3e\xc5\x23\x1a\x68\x0f\xdb\xad\x9c\x3d\x3b\x99\x61\x80\x73\x1e\xc5\x92\xf7\x8f\x83\x77\x5e\x14\x62\x54\x4a\x10\xc4\xc5\x90\xb5\x12\xea\xc7\x3f\x3f\xa1\x21\xe6\xbd\x60\xd9\x6c\x1a\x0d\x72\xb2\x88\x67\xda\xb2\xdf\xc8\xeb\x9f\xa8\xac\x7e\x2e\x0b\x1d\xdc\x25\xfd\xe8\x62\xfb\x87\x97\x59\x55\xfe\x5b\x5e\x71\x45\xf5\x35\x7b\x9d\xcd\xf2\x2b\xaf\xca\xe8\xec\x24\xc1\x75\xa3\x33\x02\x1e\x36\x6c\xbc\xf6\x95\x65\x2f\xce\x88\xb2\x89\x05\xcf\xb5\xb2\x93\x6f\x73\x87\x28\x33\xd6\x67\x39\x28\x58\x9e\x24\x61\x05\xdc\x35\x45\xe1\x76\xb2\x9b\x22\x6f\x8f\x54\xff\x23\x0a\x02\x9d\x20\x7f\xbc\x24\xde\x51\xa1\xc1\x76\x02\xda\x4a\xe6\xb8\x4d\x3d\x07\x67\x75\x80\x28\x44\x31\x51\x92\xd1\x13\xcd\xe5\x2f\xfe\x54\x7e\x1d\x29\x84\x9e\xa9\x1b\xd0\x5f\xc5\xf3\xbe\xa2\x95\x7c\x23\x38\xf8\xeb\xb8\xde\xdb\x47\x7f\x73\x9f\xd9\xd5\x58\xfc\x27\xf8\x04\xf3\xec\x0d\xc9\xae\xbc\x32\x6c\x57\xd8\xdc\xea\xdf\x10\xf6\x68\x20\x03\x0e\xab\xce\xc2\x8a\x23\xd4\xdc\x1e\xba\x24\xee\xbc\x0d\xc3\xec\x36\x47\xe0\x21\x7e\x52\xc5\x9a\xbe\x73\x0b\xec\x79\x4b\xd2\x6d\xe5\x59\x78\xac\x59\xd9\x66\x67\x17\x26\xf8\xd7\x29\xdf\xd6\x17\x34\x01\x5e\x8a\x15\xbd\x15\x08\x44\x75\x15\xbd\x50\x5a\x53\xdb\xec\x74\xfc\x9e\x5c\xab\xd7\x1c\x62\x2b\xe4\x3f\x4a\x3a\xb9\xc7\x6e\x19\x32\xca\x7f\x54\x94\x36\x78\xb1\xf7\xe7\x7f\xa0\xd3\xac\x3f\x92\x15\xf7\x9f\x9f\xe9\x6e\x2f\x74\xaa\x5e\xbc\xa2\xec\x3e\xf2\x97\x70\x3d\x71\x20\xac\xd3\x26\x26\xed\x83\xef\xf2\xde\x9b\xe2\x52\x71\x55\x50\x26\xdb\x47\xf1\xd3\xcf\x4b\x3a\x9e\xf0\xb0\x71\x63\x94\x54\x8a\x4e\x1f\x4a\x3a\x36\x67\x4e\x7a\xe6\xbe\x4b\x47\xa6\xf6\xf5\x9e\xa5\xf6\xb9\x60\x39\xc4\x5a\xfc\x12\x13\xc0\x8a\x38\x15\x0d\xb7\x3a\xa4\x97\x67\x63\xb3\xb7\xd2\x74\xe9\xd0\xe8\x04\x19\x6a\xde\xa3\x93\x76\x15\xc2\x64\xb6\xb1\x66\x12\x14\x24\x68\x0f\xef\xab\xb0\xe8\x00\x13\xd8\x9f\x6e\x5b\x83\x44\x62\xd2\x14\x14\xa1\x6b\x2a\x6f\x15\x99\x53\xd6\xa3\x72\x64\x75\x5c\xf4\xaa\x45\x80\x94\x5c\x81\x5b\x7c\xab\x73\xf5\xef\x89\x10\x39\x43\xb2\x95\x91\x1d\xb9\x44\x50\x81\xea\x8a\xbb\x40\x45\xa7\x7b\x6f\x0d\x99\x02\xa9\xfb\x52\x13\x83\x07\x35\x37\x87\x5f\xee\x34\xaf\x14\xce\x21\xa8\x8b\x54\xff\x28\x89\xdb\x4a\x22\xef\x82\x7c\xe2\x72\x82\x0b\xb0\xf7\x4c\xb8\xb3\x38\x29\x27\xd1\x52\x8e\x37\xef\xbb\x5d\x26\x72\xcb\xe3\x6d\x97\x0d\xf0\x47\xa5\x4e\x25\x6a\x88\x85\x58\xb5\x4f\x13\xd7\xda\xf8\xdf\x3f\x3a\x9d\xcb\x1e\x4f\xcf\xda\xe7\x79\x73\xc7\x65\xd7\x00\xbd\x90\xce\x94\x88\xd4\x82\x2f\x85\x54\x2b\xaf\x64\xd0\x31\xf2\x8a\xa8\xfe\x32\x51\x0f\x04\xdd\xed\x7d\x52\x53\x26\x5c\x0d\x50\x2a\x85\xbb\xdf\xd1\x64\x53\x47\xa1\x1c\xb5\xa1\x58\x68\xdc\xab\xec\x82\x87\xda\xaf\x19\x76\xcc\x0a\x77\x3e\xb0\xec\xd2\xce\xc5\xd5\x08\xfe\xd8\xbc\xa7\xe7\x2a\xcf\x91\x95\xfe\x91\x18\xc8\x8e\x24\x49\x92\x6c\x03\xee\x91\x61\x3c\xc7\xc2\xcb\x63\xb9\xc3\x61\xa4\x5c\x61\x5e\x54\xce\x6f\x46\x03\x9d\x1b\xf4\x66\x74\xec\x6f\x00\x5e\x81\xf4\x9d\xf3\xb0\x5e\xee\x36\x19\xd7\xa9\xbc\xce\x33\x42\xa1\x11\x9c\xb5\x84\x8e\x7f\xe7\x7c\xbf\xcf\x5c\x59\xf7\x39\x98\x57\x7b\xae\x08\x45\xf2\x91\xae\xda\x3d\x89\x94\xb6\x7d\xe8\x75\xb8\x55\x5a\x32\x6d\xee\xec\x7e\x8a\x8d\x45\x28\x0e\x80\x25\x82\x24\x63\x38\xf2\xd6\xf9\xab\x6d\x2d\xba\x45\xfe\x5a\xce\xab\x61\x57\x06\xe7\xaa\x6e\x53\xd1\xb7\xc6\x67\xdf\xe6\x85\xf3\xdd\x06\x63\x57\x0e\x82\xd5\x89\xad\x3c\x83\x11\xb6\x1c\x6d\xa1\x3c\x8f\xea\x2b\x85\xca\xf5\x4c\x11\xd5\xd5\x2e\x75\xd4\x7a\xbd\x34\x75\x88\x2d\xcf\x11\x3b\xea\xdb\x3d\x0e\x87\xa2\xb4\x09\x10\x12\xe2\xb5\xac\x50\x60\x00\xf8\x96\xbe\x73\x3a\x59\xd8\x55\x49\x2a\x22\xe8\x1c\xff\xe4\x8a\xaa\x30\xd8\x60\x67\x78\xfe\x63\x19\x66\x07\x89\xe0\x14\x0a\x43\x3d\x66\xdc\x9b\x6a\x38\xfd\xfb\x0e\x13\x57\xa9\xb5\xf2\xdb\x5f\xab\x17\x51\x04\x62\xd7\xe2\xfd\x45\xaf\xb5\xca\x2e\x7a\xd8\x25\x7d\x33\xc2\x48\x22\x62\x62\xa7\x79\x0a\x1c\x84\x59\xc4\x01\xb2\xfc\xaa\xf3\x74\x93\xb7\xb8\xfe\x43\x21\xc0\x52\xdf\x52\x25\xdc\x75\x40\xc3\x9d\x7e\x04\x6e\x91\x73\x4a\x72\x31\x46\x93\x73\x11\x22\xee\x16\xcd\xf2\x6a\x5b\x38\xbd\x59\xc9\x76\xa8\xfd\xe4\x00\xdd\x32\xab\x6c\x3b\xa5\x9b\x84\x64\x36\x85\xaf\x8a\x7d\xe5\x4e\x7f\x41\x33\x49\x35\x1c\x55\xb3\x7f\xf9\x08\x1a\xd8\x19\xdd\x9f\x58\x5e\x66\x49\x47\x27\xf7\xd5\x98\x00\x40\xb2\xb9\x84\xdc\x1b\x3a\xa8\xd8\xef\x37\xf2\x27\x06\x41\x4c\x75\xe6\x74\xd2\xd2\x03\xab\x8f\x6a\xac\x22\x68\x7b\x0a\xb3\x21\x54\x70\xa2\x86\x9d\x2c\x35\x3c\x75\x95\xcd\x2a\xb1\xa9\xa6\xac\x84\xe9\xf0\xd0\x63\x01\x96\x23\xc2\x12\xa5\xdd\x5b\x4a\xdb\x88\x29\x4b\x57\x96\x14\x69\x92\x4e\x6d\xfa\xa7\xaa\xb6\xba\xfe\x29\x61\xcc\x64\x93\x0a\x1b\x4f\x75\x8e\x7a\x6c\x97\x6e\xa2\xee\x3f\x86\x18\x89\x53\xe3\x29\x9b\x95\x33\x54\x24\xce\x0b\x63\xd1\x96\x44\xc2\x1c\x11\xdb\x4c\x4b\xbe\x12\xd0\xd1\x58\x5a\x3f\x2c\x5c\x78\x6d\xe4\x1b\x33\x18\xbb\xc8\xa1\xa5\x74\xf2\x72\xd9\xd5\x9f\x1b\xb1\x33\xba\x38\x18\x64\xe8\x12\x2a\x60\xd8\x49\x91\x47\x96\xc3\xb7\x1b\x96\xd2\xd1\x0c\x0b\xe1\xc0\xa8\xb2\xd6\x4a\xb8\xaa\x7f\x88\x5d\x5c\xb4\xd5\xd6\xc1\xce\x00\x6a\x34\xa2\x2a\x7c\x42\xdc\x13\x66\xd1\xef\x55\xb5\x9d\x26\x27\x9c\x55\x51\xd8\x31\x34\x55\x36\xd0\xe9\x11\x75\x5d\x69\x23\xda\xc1\xec\x73\xbc\x70\x56\x3b\xc1\x06\xb2\xf9\xa3\xff\xd3\x33\x35\x27\xe9\x14\x7a\x97\x27\x5d\xff\x9f\x20\x3c\x68\x34\x9f\x22\x98\x3f\x94\x48\xaf\xec\xb4\x5f\x7c\xf4\xf0\x81\x03\x09\x06\xa8\x8e\xee\x34\xb0\x0c\xdc\xf7\x28\x0d\x97\x30\xa0\x66\xbb\xad\x46\xec\xcf\x50\x3b\xbf\xfe\x87\xf2\x9f\x02\xd5\xf6\x4d\xa8\xe9\x50\x86\x51\xbd\xb6\x4b\x22\xdb\xa1\x39\xa5\x0f\x33\xf0\x2b\x9a\x0d\xda\x4f\xc4\x5c\x8f\xf9\x1f\xdb\xbf\xd9\xf1\x48\xba\xce\xfc\xd4\x1c\x43\xf6\xde\x32\x4a\xc9\x8b\x24\x36\xb7\xd6\xf0\x8c\x61\x52\xd7\x52\xb4\xfa\x32\x25\xc9\x43\x7a\x29\xe3\x63\x1e\xd5\xa8\x1b\x86\xc4\xbd\x5c\xff\x45\xc4\x85\x90\x26\x77\x0f\xa5\x9a\xb9\x76\x1d\x1b\xdd\x36\x5b\x47\x76\x01\x38\x50\x2c\x5e\x91\x58\xcb\xc9\x13\x52\xe8\x39\xe2\x6a\x3f\x3e\x55\xf9\xf3\xdd\xc3\x1a\x4b\x34\x81\xc8\x1e\x34\x5c\xca\x9f\xa5\x5d\x45\x99\x52\x98\xa0\xd4\xc3\x3f\xeb\x0e\x62\xd9\x27\x78\x65\x25\x22\xd7\x6c\x03\x3a\xb2\x01\x98\x90\xa3\x1d\xcd\xb5\x30\xd7\x44\xb4\xa3\xba\x7e\x14\x42\x76\x1f\x76\x9b\x90\x21\xe0\xb5\x9d\x0b\x02\x23\x09\x7f\xc9\xea\xc2\x11\x50\xe9\x20\x1a\x18\xa3\x1b\x37\x45\xe0\x9a\x9c\x4b\x70\x1c\xa5\x68\xf3\x94\x5c\x49\x4d\xd0\xae\xcb\x54\x3b\x75\x44\xa3\x7d\x54\xd2\x10\xa6\x9c\x98\x30\xb4\xa0\x78\x1d\xc9\xc7\x96\xba\xec\x9a\x48\xba\x9f\xd8\xd2\x87\x5b\x84\xbf\x5d\x49\x16\x87\xa5\x15\x95\x9b\x5b\xd3\x44\x85\xa9\x94\xdc\x35\xd2\xf1\xd7\xcc\x32\xad\x9b\xc5\xac\xb4\xc1\xd2\x0a\xc3\x1b\xef\x42\x32\x97\xa8\x23\xa3\x8c\xf4\x44\x68\x1f\xa6\x08\xd8\x17\x75\xcf\x21\xde\x87\x68\x70\xe4\xc8\x85\x88\x65\x9f\xe4\xb3\x6e\x63\xba\xee\x59\x25\xb9\xbe\x33\xad\xb5\xe7\x2b\xda\x7e\x3c\x09\xbb\xc4\xd6\x17\x08\x6c\xe4\x47\x41\x09\x48\xfe\x5d\x6a\x25\x2a\xba\x68\x4a\x90\xab\x5f\x54\xe2\x0f\x6f\x11\x7a\xe9\x78\x51\x06\x97\x04\x83\x00\xd5\xb4\xb9\x15\xa3\x41\x55\x26\xe6\x21\x96\x94\x65\x6d\x92\xc0\xaf\x1c\x2a\xbe\xe9\x5b\x69\xf7\xf1\x4d\xee\xf3\x86\x8f\x81\x28\x15\x99\xe2\x80\x9a\xc1\x34\x3a\x4d\x4e\xb8\x1c\x78\xa9\xbd\x5d\xca\xec\x2a\x95\xb9\xb9\xe9\x58\x79\xa9\x62\x90\xc2\x3c\xd6\x8f\x2e\xdc\x66\x51\x29\x7e\x1e\x06\xe2\x79\xa0\xfb\xa7\x44\xdf\x51\x48\xc2\xab\xd0\xde\xe4\x05\xa3\x24\xaa\x68\x5e\x2d\x22\xec\x25\x0e\x93\x12\x56\xd4\x07\x74\x97\x36\x4a\x54\xaa\xb6\x7f\x6e\xdd\xc8\xde\x5d\x5d\x59\x0b\xd8\x28\x64\x2b\x5a\x43\xd1\x7b\xed\x56\x6a\x5c\xea\x8f\xaf\x87\xc8\x44\xef\x99\xde\xf6\x31\xc8\x6e\xbc\xe7\x9f\x88\x7b\x24\x76\x78\x43\xc1\x38\x71\x90\x25\x7d\xc6\xee\x9c\x3e\xe0\xf9\xed\xba\x18\xc4\xff\x8b\x9b\x47\x8f\x9f\x14\xf6\xd4\x9f\x57\xac\x39\xd0\xc6\xe0\xab\x21\x3b\x0f\x5b\x88\x08\xb3\x43\xe7\xbb\xf9\x3f\x2a\xdd\x0f\xdf\x61\x44\x0b\x9f\x29\x40\x13\xe8\xc0\x1b\x03\x6f\xde\xf5\xed\xca\xdc\x3b\x58\x71\xc7\x1c\x12\x1a\x4f\x98\xf5\x42\x6a\x07\xac\xe5\xcf\x73\x58\x88\x8d\xb8\x3d\xca\x3e\x0f\xb4\xa6\xe2\x7b\x2b\x2c\xd0\x82\x14\x74\xcd\x6a\x1d\xca\x37\x14\x1a\x99\x25\x64\xe0\x4d\x4d\xde\x4c\xc7\x00\x27\xdd\x6a\xc8\x89\x75\x07\x6b\x3f\x8a\xd8\x6d\x83\x91\xd4\x40\x3b\x25\xe9\x07\x29\x7a\x0b\xed\x0c\x04\x8c\x91\x2d\x33\x51\x94\x60\x95\x64\x11\x1b\xcf\x2b\x49\xe9\xc2\x63\xe0\x67\xd0\x09\x29\xbe\x1f\x37\xf1\x07\xcf\x3a\x05\x55\xaf\x7c\x7d\x9b\x73\xa2\x74\x89\x66\x87\xad\xe9\x82\xd9\x4f\x45\x7f\xda\x91\x5f\xe5\x59\xd8\xfe\x08\x19\xee\x39\x2b\xc2\x19\x9d\x34\xaf\xf3\x26\x91\xfa\x00\xad\x88\x74\x97\xc3\x88\xea\x74\xcb\x3b\x1f\xd9\x2c\xee\xef\x8d\xee\x1c\x27\x98\xe9\xbe\x53\xb0\xe2\xe4\x9a\x5b\xa5\x7a\xb8\xed\x96\x55\x84\x7d\xa1\x98\xc8\x0b\x42\x0d\x28\x62\x3d\xce\x30\x87\x3d\x4e\x32\xd3\x8e\x93\xb1\x80\x07\x64\x8a\xfe\x2a\x2b\x63\x1c\x8f\x95\x6c\xbd\x03\x84\xdf\x3b\x7b\x25\x39\xef\xa4\xfe\x80\xc8\x35\x2b\xae\x0f\x8a\x43\x7f\x1e\xec\x8c\x5e\x5c\x60\xe1\x4e\xe8\x87\xe9\x0c\xd7\x4a\x0a\x00\xdd\xa3\xdc\x8f\xf4\x57\xb7\xc2\xb0\x6f\xbe\x8c\x47\x52\xef\x2e\x81\x8d\x47\xfb\xa3\xf0\x20\xd0\x0e\xc0\xdb\x17\x82\x22\xe1\xdd\xc9\xca\xb0\xea\x78\x02\x71\xc6\x60\x40\x72\x0f\x19\x1a\x85\xae\x35\x0f\x54\x84\x57\xa2\x6c\x87\x4e\xa2\x3b\x9c\xd1\x9a\xe8\xfd\x24\xd5\xf0\x9e\xa2\x1b\xb0\x55\xc2\x04\x5b\xf9\xb2\xd7\x66\x6b\x1e\x45\xec\xe5\xfe\x2c\xad\x24\x64\xad\x67\x85\x60\x93\xe7\x38\x2e\xf5\x88\x3e\xdf\xc3\x85\x3a\x6a\xa2\x29\xcd\x7f\x9b\x7f\x11\x9f\x1b\x3a\x11\xd2\xf8\xb8\x2b\x2f\x1b\x77\xee\x81\x19\x3c\x42\x39\x98\xcf\xc3\xcf\xff\x28\xed\xd1\xf4\x53\x48\x0e\x62\xc2\xfd\x2e\xab\x02\x97\xf0\x3c\xd2\x44\x80\x1a\x8f\x25\x59\xfd\x97\x0e\x38\xac\xe1\x7e\xf9\x95\xd5\xa5\xf6\x4f\x36\xb0\x39\x85\x7e\x3d\xb6\x2d\x22\x44\xec\x9e\x47\xac\x54\x93\x4e\x11\x1b\xcc\x5f\x3d\x63\xda\x94\xdd\x93\x5a\x98\xfe\x06\x23\x75\x14\x2a\x48\x7e\x9b\xb2\x6f\xaf\xe0\x7a\xa4\xee\x1b\xfc\x20\x58\x39\xd9\xce\x83\x9d\x3b\xa4\x37\xb7\x56\x1f\xfa\x8c\xec\xd8\x65\x7d\x6f\xab\x2c\xd6\x91\xbb\xa3\x1b\xdc\x65\xd5\xbb\x62\xf4\x5c\x70\x19\xbb\x1f\xc3\xb8\xf2\xa4\x2f\xff\x52\xc2\x9f\x88\xe0\xdf\x52\xa6\x75\x93\x90\x7b\x29\x21\xb3\x5b\x5a\x7c\x84\x6d\x2c\x9c\x06\x6c\xcb\x89\x5e\x79\x0d\xfa\x86\x8b\xda\x59\xe1\xc9\xcb\x68\x26\xef\x74\x99\x57\x87\x6f\x96\x38\xe5\x96\xdc\x08\xba\x0b\x1d\x57\x96\xe4\xcd\x9c\xbf\x22\x5f\x90\x3f\x44\x7a\xfb\xc8\x6a\x1d\xab\x39\x7c\x37\x35\x2b\x67\x61\xaa\x57\x78\x22\x39\x63\x52\xba\x9b\x4a\xfb\xdb\x49\xbd\x7a\xdb\x3f\x50\xa0\x8e\x7d\xc4\x02\xa9\x86\xdf\x6b\xd5\x01\xef\x1d\xb5\xfc\x4e\xd8\xd6\xf9\x4d\xde\x77\x7b\x38\xe7\xf0\x9a\xa3\x84\x13\xbd\x64\x82\x21\x25\xc5\xf4\xf6\x6b\xab\x86\x83\xda\x9f\x0f\x03\x4d\x4e\xd0\x93\x87\x8d\xad\xf1\xd8\xd4\xfa\x6d\xdf\x36\xc8\xab\xc4\x32\x53\xc4\xd6\x21\xda\x90\x37\xbc\x17\x1e\xaf\xd6\xc4\x7b\xeb\x43\x87\x11\x88\x47\xb5\x84\xe9\x67\xcc\x03\x53\x1a\x76\x2f\xa6\xbd\x38\xa7\x7e\x88\x09\x0a\xae\xa4\xf7\x02\xad\x34\x57\x9e\xb1\x28\x4f\x6b\x8c\x5c\x43\x20\xc5\x7c\xd4\xa4\xec\x1f\x30\x06\x58\xe1\xb5\x16\xc2\xc8\x84\xfe\x31\x5c\x38\xe3\x53\x7a\x03\x78\xd7\xda\x35\xc2\x44\x42\x75\xdd\x18\x64\xc7\x73\x54\x3f\xf5\x59\xd1\x76\xf4\x13\xe7\x59\xff\xe6\x37\x2d\x01\x30\x64\x60\xcf\x29\x06\xf6\x53\x11\x60\x30\x61\x97\x2d\x54\x51\xa1\xf9\x8c\x55\xf3\x09\x97\xe8\x55\x05\x5e\xa7\x9b\xec\x1d\x11\xe1\x7a\x12\x9f\x91\xcd\x07\x95\x40\x33\x94\xbb\xcc\x47\xd4\x2e\x11\x11\x82\xde\xb6\xbb\xa6\x70\x76\xcf\xe4\x91\xc2\x46\x98\x7c\xc9\x33\xcc\x26\xf0\x5f\x1e\x0c\xc9\xf6\xe7\x12\x69\xfb\x25\x0b\x01\x7f\x89\x27\x4d\xfa\xce\x50\x3f\xc6\xf3\xad\xe4\x03\x54\xc9\x36\x5b\x5d\xdd\x80\x71\xa8\x30\x04\xc5\xe0\x94\x51\xd6\x50\xae\x50\x15\xf5\xa4\x4d\xbe\x66\xd5\x74\x98\xa8\x28\x20\x3a\x9b\x96\x1c\x56\xa1\xbc\x8d\x08\x14\x8b\x35\x65\xb6\x0f\xe1\x75\xeb\x46\xef\x7e\xf4\xce\x21\x96\x01\xfe\xc5\x64\xa5\xc1\x76\x5a\x61\x4a\xda\xb1\x14\xed\x3f\x92\xb2\xf6\x08\x81\xf2\x0a\xa8\x5e\x08\xa3\x67\x6b\xef\xe2\xc7\xe8\xcf\xc2\x0d\x94\x9b\x5f\x15\xde\x86\x3d\xdf\x2e\x72\x8f\xdb\x5d\x91\xf8\x58\x4e\x01\x43\xb6\x0e\x4f\x7a\xd2\x1e\x06\x57\x5e\xf7\xd2\x1f\x6b\x94\x56\xb7\x0f\x9c\x05\x46\x55\xe8\x5a\x4a\x3b\x84\x25\xe2\x8f\xd6\xa5\x90\xc2\xcb\xf7\xbb\x47\x2d\xa1\x4a\x0e\x64\xac\x4b\x71\x44\x87\x2a\x50\x6f\x1f\xb1\xbc\x5b\x95\xa0\xd5\x7d\x42\x2d\x61\x67\xac\xfc\x01\x6c\x1b\xaa\x3b\xc1\x9e\x8f\x9e\xde\xbb\xb9\x07\x74\x51\x76\xc5\x2d\xf3\x10\x65\xd9\x1c\xe9\x99\x4e\x9f\x94\x5a\x29\x69\x8d\xeb\xc4\x47\xea\x3c\x16\x38\x42\x8e\x9a\x43\x29\xfe\x83\x1f\xb9\xbd\xb6\x6d\x54\x25\x68\x63\x23\x61\x2f\x60\x81\xee\x4f\x42\xdd\x5d\xd1\x4d\xcd\x10\xbf\x34\xa8\xbf\x13\xd6\x8d\x3e\x20\x4a\xf4\xc9\x99\x02\x9d\x32\x0a\xed\xa8\x2a\xee\x96\x5e\xbc\x9b\x2f\x17\xb4\xb2\x8f\x29\x9f\x8f\x6e\x8e\x78\x4b\xd8\x49\x0d\x51\xd9\x31\x6b\x12\x33\x6e\xf4\x08\xcf\x06\xf7\x74\xed\x43\xa3\x83\xc8\xed\x3f\xda\x83\x11\x94\x94\x68\xc4\x6c\x83\x41\x9e\x5a\xdc\x48\x79\x64\x92\xcf\x6c\xc9\xea\x25\xac\x02\xe8\x8e\x7b\x0d\x56\xb7\xb8\xd6\x5d\x44\x42\xfa\x26\xe5\x3e\x76\x59\xbd\x79\x3e\xa4\x73\x13\xa2\x0f\x1f\xc2\x9b\x47\x5d\x86\xce\xd6\xf7\xbb\x76\x95\x77\xee\x94\xc1\x53\x33\x79\xd4\x9d\x0f\x9c\x35\x6a\x97\x73\xd4\x9c\x29\x9e\x3f\x52\xdf\xf1\x9d\x73\xc4\xc5\xda\xec\x9d\x49\x68\xfd\xa6\xe5\xfc\x86\xee\xe1\x53\x27\x3f\x25\x3f\x9e\xfe\x8b\x01\x5a\x1d\xb4\x36\x28\x9b\x2e\x81\xf7\x1c\xa9\xf5\xef\x86\xcf\xd0\xf8\x20\x47\xd1\x07\xe8\xd8\x75\x55\xb6\x34\x3c\x68\xd4\xcf\xce\x64\xb2\x2f\x7f\x27\x8c\xfd\xe2\x16\xee\x55\xb0\xf1\x60\x0c\xdd\xab\xd8\x05\xee\x9f\xf0\x35\xbf\x44\x0d\xb0\x9f\xe8\x96\xfa\x6a\x75\xe2\x1d\xef\x0e\x83\x55\x16\x83\xbb\x1a\x7b\xbb\x15\x8d\x65\x8f\x66\xa0\xfd\x91\xf7\x30\xe8\x5a\x73\x7d\xc5\x38\x55\xf2\x91\xec\x6b\x12\x09\xbb\x12\x55\xf5\x1a\x51\xdc\xad\x5b\x17\x0e\x0c\xf8\x07\x5d\x6b\x77\x04\x8c\xdf\xe5\x60\x61\xb8\xf5\xec\x9f\xdc\x65\x6b\x7b\x51\x1b\xa7\x6b\x96\x75\xc2\xaa\xce\xc4\x1d\x8e\xbe\x56\x42\x36\x13\xc3\x7b\x0e\x61\xcc\x2d\x52\xd7\x1d\xc9\x0c\x48\x5e\x6a\x56\x0c\x36\x5f\x55\x5a\x15\xb8\xdb\x03\x37\x3d\x17\xac\x82\xd8\x2a\x0c\x17\xda\x0b\xf1\xa1\x57\x0c\xfc\xc8\x8d\x8e\xc7\xa0\xab\xd0\xb1\x79\x65\xfb\xc7\x2e\x4c\xd8\x20\x54\x7d\x8a\x09\xbd\x7f\x54\x17\x1b\x4f\xaa\x14\x77\x31\x40\xa3\x71\x77\xc4\x72\x65\x23\xb2\xab\xed\x0a\x0a\x2f\xb1\xbd\x55\x79\x5b\x63\x26\x5f\x76\x7d\xcc\x4c\x1a\x2d\x30\xe7\xf4\x11\xd9\x1c\xb6\xbd\x20\x63\x73\x65\xa6\xd7\xc5\x66\xf2\x35\x33\x99\xd2\x8e\xa1\x8a\xba\x40\x41\x92\xa9\xac\xcd\x09\x61\xc0\xf0\x0f\x9d\x74\x0a\x8b\x50\xd4\x95\x7a\x87\x53\x6c\x56\x9d\xe8\x29\x7f\x86\x57\xe8\x98\x20\xc0\x6a\x5a\xa8\x4b\x61\x00\xb6\x3a\x86\x6d\x84\xeb\xca\xd5\xcc\x04\xdd\x49\xdd\x4c\x60\xeb\x2a\x4c\x73\x84\x9f\x82\xce\xf9\x93\x90\x31\xca\x81\x99\x5d\xde\xd5\x0c\xdb\x10\x11\x14\xed\xf0\x57\x59\xc5\x02\x16\xe0\xbb\x4e\x6a\x23\x5d\xe8\x99\x53\x24\x97\x00\x30\xb2\xf8\xfc\x24\x39\x40\xdc\x42\x60\x3c\x3a\xa1\x63\xb0\xff\x19\x7b\x4b\xcc\xe2\x59\x81\x3d\x67\x04\xe0\xdb\x49\xd2\xa2\xdf\xe7\x95\x8c\x4e\x85\x21\x79\xbb\xb2\x65\x57\xd1\xfa\x61\x4f\xdc\x66\xb1\x4b\xe9\x15\x1f\xe9\xe8\x87\xa8\x82\x56\x8b\x32\xb0\xca\xe6\x22\x68\xc2\xbc\x7b\xc8\xd0\x6d\xba\xa4\xb1\xc7\x08\x1a\x29\x5b\x9c\x00\xb9\xbd\x98\x2c\x68\x5c\x3f\xd8\x88\x64\xe2\xbb\x36\x32\x68\x48\x72\xdf\x70\xb8\xba\xc2\xdf\xf7\xc1\x8a\x0b\x30\xfc\x29\x8b\x88\x9b\x97\xe3\x0f\xe1\x3c\x94\x39\x6b\x47\x45\xd2\xc3\xc1\xf4\x08\x6c\x05\x7f\xd9\xdc\x17\x7f\x04\x17\xed\x48\x9c\x8a\x8e\x5f\x10\x37\x12\xe7\x07\x99\xf3\x8a\x8d\x9a\x02\x6f\x3d\x12\xbd\xaf\xed\xa8\x58\xfa\x1b\x8e\x6c\x7e\x31\x16\x69\x22\xc1\x2c\xf5\x4f\x6b\x15\x88\xb8\xa6\xc8\x05\x18\x29\x53\x2c\xbd\xbb\x5a\x78\x19\x1b\x97\xd8\x5e\x82\x46\x64\x0f\xd3\x9d\x7b\x7e\xff\x43\x45\x75\x2c\xd9\x87\xb3\x60\x9c\xbd\xa5\x0b\xed\x99\x32\x3a\xdb\xae\xf3\xd3\x6d\x95\x1e\x4d\x9b\xe3\xd3\x94\xb8\xb9\x3f\xf0\x2f\xd4\xe1\x0e\x03\x0a\x15\x8b\x76\x65\xc5\x16\x62\xc3\x62\x12\x37\x87\xc5\xdb\x4c\x34\x1e\xc5\xac\x5a\x89\x73\x2f\xc3\x5d\x58\x2c\x2b\xef\x61\x78\x39\x8c\xb0\xd9\x62\xa9\x0b\x1e\x6d\x4c\x16\xb2\x57\xb4\x28\xff\x57\x93\x03\x88\xae\x8e\xa3\x76\xce\x76\xef\x03\x7b\x95\xe0\xc8\xb0\x3f\x69\x43\x45\x6a\xf5\x03\x3d\x77\xb7\xf4\xf9\x35\x25\xa8\x6e\xf3\xee\xb5\xfc\x29\x1a\x8f\x55\x9d\x03\xfb\xe9\xe6\xcb\x77\x4b\xfe\xc7\xfc\x65\xc9\x3a\x6d\x91\xc7\x35\x0c\x2d\x4d\x9f\xdd\x04\xd0\x5a\x59\xec\xfa\x0c\xb6\xd6\xa0\xae\x7a\x07\x61\x0d\xef\x6b\xf7\x6f\x22\x75\x95\x55\xad\xcb\x1e\x34\xb3\xc2\xc8\xa2\xd1\xbd\xad\xee\xf5\x34\x87\x1c\xc0\x27\xed\x05\x58\xf3\x6e\xea\x27\xaf\x0c\x86\x59\x73\x5f\x3f\x7a\x50\xd7\xaa\xe1\x70\x7e\x3b\x75\xba\xfa\xb6\x7b\xac\xec\x5f\xee\xc8\xf8\x24\xaa\xb5\x2a\x73\xdd\x96\xc7\x1c\xd9\xb5\x5d\x92\xdc\x4e\x5a\x68\xab\x94\xc7\x48\xf7\x9a\x58\x33\xef\xcc\xd8\x87\xf0\x8e\x76\x19\xab\x4c\x2f\xe0\xcf\x11\x61\x5f\x30\x95\x50\xea\xe0\x42\x46\x27\x47\x4d\x27\xb4\xcc\xd1\x9d\x04\xa7\x7f\xe4\x2c\x0d\xbf\xe0\x10\xe3\x29\xd5\x67\x49\x84\x75\x97\x74\x70\xb7\xfe\x57\xa6\x66\x85\xf1\x97\x7f\x91\xaf\x7f\xd1\xaf\x9f\x61\x57\xe6\xe7\x6a\x6b\x04\x4f\x1f\x5b\x3b\x9c\x32\x8a\xf2\x98\xc6\xb8\x6e\x85\x71\x8a\xae\x9a\xfd\x23\x4d\xd0\x0a\xf2\x68\xeb\xff\x92\x7c\x6d\x99\xc2\xca\x6a\x9a\xc7\xb0\xcc\x08\x9b\x2d\xfb\x81\x0a\xbb\xae\x59\x90\xa5\x4d\x07\x4f\x35\x43\xe7\x65\x69\x15\x32\xfe\x6b\x52\x9a\x45\x50\x61\xa6\xfc\x4f\xb0\xed\xe7\x97\x75\x1b\xd5\x6d\x0d\x9f\x63\xd4\xbe\xe4\xbb\xda\xd2\x4e\x07\x0e\xd7\xef\x28\x82\x4c\x4e\x62\x48\xb9\x90\x09\x08\x02\xad\x6b\x23\xc2\xe6\x67\xfc\x93\x41\xbe\x04\xb0\x37\xce\x8d\xdf\xfa\xd9\xd5\x57\xfd\x8a\xb1\xaa\x38\x7f\x9b\x9e\xdd\x39\x43\xce\x27\xa3\xcc\x75\x47\x45\x9f\x8f\xf2\x96\xc6\xb1\xa7\x34\xf0\x25\xb2\xaa\xc8\x19\xd8\x1c\xb3\x14\x96\xb8\x60\x84\x30\x81\x53\xf0\x98\xba\xa2\xea\x58\x3e\x21\xb0\x9e\xf3\xea\xf4\x84\x96\xc2\x9d\x2d\x4e\x72\xe4\x9e\x45\x41\x15\x4f\x60\x61\xfb\x8f\xa3\x0a\x00\xfd\xc1\x36\x25\xeb\xeb\xf4\x52\x82\x06\xea\x5f\xe6\xea\x82\x68\xf0\x80\x69\x32\xbd\xea\x22\xbe\x09\x57\x97\x40\x18\x86\x49\x91\xbe\x7a\xbf\x67\xb5\x42\x68\x04\xdb\x76\x5c\x5e\xde\xc6\x2e\x38\x0f\x71\xa2\x67\xad\x91\xd8\x0c\xc9\xc4\x0f\xed\xcc\x2c\x9d\xd9\x80\x75\xd7\x8f\x1e\x30\x1b\xa4\x56\x76\x0a\xe7\x6e\x66\x2c\x30\x72\x31\xa6\x1c\x91\xb9\xe7\x16\x76\x75\x23\x7c\x5f\x59\xc0\x0d\x50\x82\x89\x68\x4a\xee\x2c\xf8\xf6\xfa\xb0\xc8\xb3\x96\x74\x11\x36\x59\xf4\xdb\x48\xd4\xa1\xd8\x36\xf3\xdc\xc5\x7c\xb4\xb9\x62\x8d\x5a\xf6\xe6\xe9\x63\xfb\xa9\xad\xd9\xa2\xf4\xd0\x3b\x66\x0d\xa8\xf9\xab\xd2\x7f\xd2\x73\xe3\xe1\x94\x55\x6d\xdd\xfb\x33\x87\x43\x46\xfd\x59\x35\x9f\xa1\x1a\x3c\xef\xe8\xe6\xf7\xb0\x1d\x96\x5f\x07\xbe\x07\xe5\x6f\xec\x10\x7d\xb2\xbd\xb9\x0f\x72\x5d\x2e\x6b\xb9\x28\x38\xb3\x21\x82\xbf\x7d\xf7\xd2\x17\x82\x20\x7d\xb0\x49\xb0\x8a\xa8\xbf\xd9\x33\x47\x38\x7b\x36\x3e\xab\x62\x99\x96\x62\xb0\x47\x9d\x2c\x42\x0e\xca\xe4\xa0\xd9\xe2\xaa\xfa\x7e\x45\x99\x3d\x09\xc5\xa0\x60\xe6\x71\x53\x3c\x48\xa4\x65\xf7\x29\xdc\x47\xa0\xa7\xe1\xba\xde\x7d\x76\x4a\xfa\x6a\x70\x77\xc1\xaa\x25\xe3\xf6\x24\x8e\xe0\x91\x40\x6c\x8a\x36\xfa\x6a\x8d\xa6\x66\xcd\x72\xc3\xb0\x72\x37\x3a\x9e\x5b\xab\xba\x61\x59\xa0\xe2\x79\xce\xb2\xed\xcb\xb3\xaa\xe8\x25\x8b\xcc\xd0\x85\x1f\x51\x57\xb4\x85\xef\xf0\xad\x45\xd1\x6c\x9f\x51\x83\xf0\xca\x73\xa3\x7b\x5a\xf9\xc5\xa3\x56\x6d\x70\x6c\x60\x25\x39\x87\xff\x98\x4a\xcf\x61\xbf\xdd\x4d\xaa\xe2\xed\xc8\x14\x5f\xbb\x1e\xd5\xd3\xb4\x4f\x37\xf1\x98\x9b\x8f\x60\xc0\x10\x1d\x35\x07\x0d\x6e\xf0\x2b\xe1\x2e\x4a\x15\x9e\xe2\x15\x7e\xa3\x40\x0b\x51\x85\x37\xef\x99\x4e\x56\x36\x1d\xe6\xf9\x30\x2d\x81\x45\x31\xab\xe9\xb5\xb0\x37\xea\xaf\x4d\xc2\x66\xfa\x2f\x2e\xd3\x74\x90\x8a\x92\x8a\x2c\xfe\xec\x92\x17\x9b\x36\xff\xd1\x55\x04\x92\x47\x16\xdb\xab\xa8\xab\x09\x25\x0b\xeb\xe6\x5e\x2d\xca\x2f\x16\x0c\x86\x64\x7d\x03\x5c\xfa\x12\x54\xfb\x26\x30\xaf\x59\x05\x97\x0a\x1a\x90\xaf\xe6\x9f\x42\xd8\xe0\x63\x35\x85\x6f\x3a\xde\x1f\x5e\x48\x3e\xb1\x44\x30\x49\x58\xda\xa3\x51\xba\xa9\x30\xc6\xfe\xe0\x17\x1e\x02\x95\xe3\xf9\xeb\x97\x46\x17\xd5\x7e\x4a\x2b\x7d\x2e\x8d\xf5\x4c\x8a\x05\x1f\xb2\x27\x69\x97\xb7\x4b\x2a\x99\xcf\xfb\xb6\x05\x32\x2c\x06\xb3\xf4\x6d\x0c\xd5\xd3\xdb\x7e\xbb\xe8\x92\x6d\xd7\xb1\x45\x9c\xfc\x0c\x36\x10\x73\x12\x0a\xcc\x74\xd2\x4f\xeb\x0d\x8e\xd7\xa6\x73\x09\x81\xc7\x22\xfb\x32\xe8\xca\xea\x75\x2f\xdb\xe7\xaf\x5f\x79\xdc\x6c\xbe\xe0\xca\x4d\xb2\xee\xba\x72\x03\xfe\x92\x08\xc8\x96\xc6\x4a\x4e\x6f\xe6\x14\x54\x57\x32\x6e\xeb\x44\xdb\xe7\xbb\x9e\x36\x21\x78\x6f\xd4\x56\x8c\x43\xe5\xb5\x62\x6a\x6e\xc0\x6d\xac\x9f\x27\x38\x9a\x2d\x73\xa3\xd7\x2a\xc1\xff\x86\x40\x6f\x8d\x60\x64\xd9\x0e\xd9\x74\xcf\x02\xfd\x42\x6a\x05\xc5\x74\x77\xbd\x55\xde\xba\xd9\x36\x87\x27\xed\x6f\x30\xa0\x55\x00\x58\xb6\x39\x24\x90\x67\x6e\xd5\xee\x5d\xe4\x13\x79\xb9\x0b\x8b\x9a\xc0\x94\x4e\x72\x70\xa8\xd0\x6e\x95\xef\x9d\x2a\x35\x7e\x28\xe5\xe3\xa6\x4d\x71\x75\x77\x04\xf4\xf5\x8b\xb2\x0a\x90\xc1\x17\xfd\xd2\x23\xf7\x73\xd2\x50\x05\x78\x79\x87\xf7\x09\xc3\xa1\xaf\x02\x46\x9d\x0f\x86\x96\xa1\x08\x49\x78\xc4\x38\xff\x15\x51\xc5\xae\x19\x5f\x26\x05\x8b\xb3\xad\x9f\x8a\x58\xee\x45\x4d\xbc\x58\x5e\x5d\x93\x9b\xd5\xf8\x08\x19\xbd\xac\xa5\xe7\x97\x3a\xb9\x92\x8a\x8a\x6b\x4a\x65\x25\x8b\xec\xac\xcd\xd7\x25\x34\xcd\xe6\x1b\x16\xd5\xa3\x2a\x11\x6f\xe6\x92\x04\x78\x41\x3b\xc1\x77\xdd\x4f\xf5\xd7\xc1\xad\xb2\xbf\x44\x55\x2d\x37\x5a\x28\x0d\x53\x0b\x71\x0e\x8e\x1c\x86\xf0\x55\xec\x72\x50\x8d\x69\x2e\x84\x82\x9a\x75\x74\x47\x8b\x8b\xb3\x32\x90\xc4\x8e\x76\x8b\x0f\xb2\xb7\x57\xcb\xbb\x85\x01\x16\x56\xd2\x3e\x3b\x88\x04\x7c\x51\xa1\x0c\x3d\x07\x1f\x65\x57\x87\xa0\xf8\x73\xd6\x6f\x7d\xfe\x5a\x75\xa7\x73\x19\x5a\xf0\xcc\xe6\xa7\xc0\xa9\x84\x49\x52\x7f\x1f\x4a\x99\xe1\x0c\xe4\xc5\xb4\xd7\x92\x6a\x91\xd6\x93\x12\xb7\x43\xd1\x30\xb0\xae\x53\x64\x20\x2b\x0f\x74\x77\xfb\xf9\x48\x2a\xb5\x95\x98\x86\xbc\x46\xb1\x7d\xd1\x48\x63\x55\xcd\xc2\x19\x7c\x48\x1c\xc1\x8d\x3d\xd5\xd8\xdd\xa9\x06\x38\x9e\xdc\xf2\xdb\x11\x1b\x63\x38\xb0\xb2\x93\x6b\x67\x47\x14\xbb\x75\x0d\x4b\x17\x77\x52\x7e\xb0\x8d\x3b\xc9\x59\xf1\x5c\x94\x64\xc3\x9f\xb6\x54\x3b\x31\xbc\xfc\x0d\x38\xc2\x6a\x62\x9d\x8b\xe5\xdc\x66\xf5\x7f\x4a\x0f\xaf\xf6\x99\xdc\xfe\xbd\x84\xb6\xdc\x6d\x61\x9c\xc7\x5b\xb8\xcd\xb2\x9a\x4d\x39\x9b\xfb\xac\xc8\x02\xd8\x30\x22\x50\x8c\x45\xae\x7f\xb2\xbd\xb1\x63\x3f\x11\xf5\xbb\x55\x92\x83\xe0\xb7\xc8\x96\x65\xb9\xdb\xc4\xe6\x96\x8b\xa2\xf4\x46\xdc\x20\xda\xfa\xba\x13\x6a\x9c\xca\x32\x79\xf8\xe6\x7f\x2c\x60\xd4\x22\xb5\x92\x8d\x74\xe1\x19\xc2\x37\xd5\xc6\xb3\x2b\xcb\xfc\xf2\xa6\x82\xd3\x81\xad\x0d\x04\xf1\x97\x0a\x63\x74\x3c\xd8\xda\x5d\xb9\x29\x41\x3f\xf7\x62\xc7\x36\xaf\x53\xd4\x4f\xee\xff\x22\xad\xe6\x49\x0e\x1a\xac\x5d\x9a\x6f\x79\x5d\xa3\x7b\x2b\xaa\x32\x8a\x60\x71\x70\xef\x24\x41\x67\x2f\x76\x18\x98\xba\xfb\xcf\x11\x7d\xac\x52\x6f\xee\xef\x14\x01\xdb\x29\x9a\x3b\x68\xf9\x46\xf6\xe1\xe8\x08\xf2\xaa\x8c\xba\xb5\xf2\xbc\x5d\x09\x23\x5b\x29\x6c\xab\x04\x39\xbc\xb3\xd7\xbc\x75\x60\xc0\xfe\x5a\x85\x7e\xba\x43\x7a\xf4\x76\x1b\xfb\x0e\x51\x6c\xd1\x00\xc5\xd8\xbf\x7a\xc0\xd5\xcd\xc9\x11\x32\x43\x66\x5d\xd3\xfb\x61\xe5\x17\x84\xe0\xc4\x45\x14\x60\x56\xbe\xb6\x16\xde\xf4\x64\x27\x6c\xe7\x05\x76\x13\x0c\xaf\x59\xd6\xce\x36\xf0\x2a\xc1\xc1\x6d\xda\xd1\x00\x34\x60\x8a\x4f\xaa\x4f\x15\xc7\xbb\xfb\xf4\x3c\x54\x46\x47\x11\xbd\xfd\x6e\xf5\xc6\x33\xbf\x8b\xf4\xd4\x31\xb2\x76\xc0\x2e\x7c\x40\xfc\xf9\x8d\x16\xb4\xb7\xa4\xf5\xa6\xc2\x24\x69\x41\xd8\x14\x2f\x2f\x38\x23\xd9\xb5\xc9\xb3\x61\x39\xa5\xf3\x2c\x84\x89\x16\xbb\x60\x16\xf9\xe0\x0c\x11\xb1\xbd\x27\x5e\x0f\x0b\x5d\xe3\xbd\x5a\x5f\xd3\xa4\x8a\x5c\xfd\x19\x2b\xbc\xbf\xb2\xb9\x09\x80\xc0\xb3\x1d\x23\xe0\x3b\xe7\x96\xcf\x23\x5c\x1a\xe6\xbe\xe8\x22\xdb\xd0\x2e\x5b\xbc\x9b\xb9\xcf\x60\xa8\x79\x55\xf9\x89\x30\xc7\xa1\x88\x44\x5c\x0f\x76\x96\x57\x65\x1f\xd8\x28\x72\x1a\x0b\x1a\x30\x1c\x0d\xe9\x50\x79\x2d\x47\x4a\x64\x5b\xab\x87\x6c\xef\x85\xcc\xe2\x5d\xe5\x9a\x4d\xaf\xaf\xe8\x3a\xb3\xcf\x0d\xf3\xc9\x10\x89\x0e\xcd\xde\x32\x0f\xaa\xcb\xbb\x10\x8b\x7e\x5a\xb6\x8f\x3a\xca\x03\xa9\x42\x13\x84\x3d\x99\x25\xf4\xa4\x7e\xf4\x18\x26\x0b\x63\xfd\xce\x0c\x00\xa2\x89\xce\x59\xf2\xa5\xad\xd3\x08\x78\x9f\x95\xb3\x62\x39\xc6\x13\xb4\xf8\x5d\x2e\x94\xd7\x1d\xb4\x63\xe5\x7a\x57\x59\xb9\x5f\x57\x92\x87\x7b\x98\xe2\x8e\x45\xfa\x18\x8f\xfa\xf6\xda\x5a\xa7\xcb\x38\x97\x73\xa4\x2a\xd4\x7b\x36\xb4\x72\xc7\xef\xc5\x57\xc7\xc8\xcf\xf8\x51\x76\x99\xf9\xd7\x8d\xae\x5c\x12\xc7\x96\x5b\x32\xa6\x96\x14\x9e\x24\xc1\x1d\xed\x57\x18\x55\x92\x8f\x9a\xd1\x9e\xcd\x1f\xd1\x2a\x70\xac\xb6\xbd\x3c\x6c\xd0\x33\xb5\x5f\xf2\xe1\x5d\x68\xda\x34\xb1\x25\xed\x5e\xf0\xfe\xd4\xb5\x2a\xb2\x08\xb2\x2e\x94\xd8\xfe\x00\x78\xf9\xf8\xd7\xf2\x9c\xf7\xa6\x59\xb4\x1d\x64\xbf\xf0\xee\x3e\x5a\xda\xbd\x62\xe4\x9e\xbe\x3d\x7b\x44\xdf\xda\x07\x81\x96\x64\x61\x08\x19\xdc\xa0\x9e\x69\x45\x7e\x02\x7b\x75\x7f\xea\x41\xe4\x07\xe6\xb0\x21\x77\x57\x8a\xe8\x45\xaf\x17\xb3\x10\x9c\x7e\x21\x6a\x32\x3e\xb1\x1e\x2a\xc0\x6b\xa8\xa2\xde\xc3\x21\xc0\x2b\x6d\xcc\x91\x2c\x44\x31\x14\xdf\x14\x21\xe4\x2a\xe7\x21\x11\x93\x7c\xf5\x97\xad\x34\xdf\xee\xca\xce\xe1\x4d\x16\xce\x30\x4b\xb8\x31\xcc\x48\xcb\xd4\xbd\x0b\x21\x80\x57\x78\x20\x23\xb2\x9c\x5d\x69\xec\x52\x36\xf2\x90\xcf\x1f\xb1\x1e\x6d\x8c\xad\xc8\xc7\x7e\xbe\xc5\x5d\x06\x9b\x4d\xb8\x40\x66\x66\xd3\xb4\x85\x1e\xb5\x67\xf1\x3f\xfc\x15\x92\x8d\xc3\x31\xb2\x07\x7c\x1f\x99\xe6\x3a\x5f\xb1\x96\xa8\xaa\x7f\xb7\x9e\x74\xb3\x71\xee\xdd\xb6\x82\xa2\xd4\x93\xbe\x8e\x18\xf8\xe1\x08\xbf\xcd\xb2\xbf\xa2\xc6\x9f\x18\xa5\xbe\xd6\x10\xae\x46\xa4\x8d\xed\x4c\xce\x08\x93\x82\xa3\x94\x28\x69\xb6\xa3\x63\x1a\x27\x0a\x17\x5f\x2a\xb0\x97\x10\x54\x31\x01\x09\x6c\x80\x0c\xff\xec\xd4\x74\xc7\x17\x15\xe6\x9a\x69\xa3\xea\xb7\x47\xc8\xc2\x47\x65\x7f\xcb\xe9\x87\xdd\x5d\xf3\x0e\x42\xe2\x1f\x47\xfb\x3f\x69\xec\xf6\x05\xa8\xa7\xda\x7d\xa2\x96\xad\xd8\x15\xb1\x90\x17\x25\x03\x2d\xf2\x20\x35\xc3\x2a\x86\xaf\xd9\x9d\xdf\xf2\x8d\xfe\x5b\x77\x7e\xa2\x51\x5e\xb7\xb9\x29\x64\x05\xd8\xe1\xba\x6e\x9d\xf5\x66\xa1\x7f\xce\xff\xa9\x8d\x3e\xef\xaa\xfe\x47\x25\xb7\x5a\xfd\xbf\xb5\xc0\xcf\xb7\xfa\xea\xbb\x2d\xe2\x5b\x30\xa0\x43\x1a\x02\x5f\x7f\x11\x49\xbb\xf2\xcd\x6c\xaa\xd7\x55\x4e\xff\x4d\x14\x0b\xd0\xbe\xd0\x34\xb3\x73\xa9\xb5\x0f\xa2\x0c\x2f\x91\xcf\x59\xdc\x99\x22\x88\xd0\x8a\x10\x98\x5f\x85\x26\x44\xa8\x41\x5d\xc4\xdc\xcd\x5d\x14\xf0\xfb\x33\x06\x36\x93\x88\xce\x9d\xd7\xca\x0e\xf8\xba\xa6\x96\x04\xb0\x36\xac\x40\x2e\xff\x3f\xbe\x08\x6a\x7b\x89\xab\xbb\xd6\x0b\xec\x90\x23\xca\x36\x12\xc8\xcf\x12\x07\x3b\x47\x8a\x0d\x7b\x1b\x8a\x5c\xcd\x99\xd4\xf6\x3f\xd1\x1f\xbf\xb8\x1b\x4c\x17\x59\xd6\xe0\x8b\x24\xea\x6d\x91\x66\xa6\x4a\x10\xaa\x41\xfa\x21\xf1\x9a\x6d\x05\x2d\x1a\xe4\x95\x09\xf7\x56\x7f\xea\x25\x57\x96\x56\x0a\x66\x4b\x02\x19\x70\xce\x2a\x8a\x25\x41\xd6\x1c\x1e\x14\x68\xc7\xf9\xc3\xd3\xa5\xbc\xd2\x49\x7c\xbf\x0f\xf7\xec\x1f\xa1\xfb\x1f\x10\xb5\xe9\x88\xf4\xd1\x67\xc4\x87\x70\x8f\x8d\xac\x3f\xa4\xb4\x2d\x32\x4e\xda\xc3\x87\x16\x38\xc0\x25\x39\x2f\x02\xe2\xf8\xfd\xbe\x83\xa8\xe1\xf6\x88\x81\x0d\xa0\x96\x92\x8f\x69\x92\x70\xd7\xca\x84\x7f\xac\x95\xf6\x26\xd2\x05\x43\xff\x6e\x99\xfa\x21\xe9\x4d\x08\xc7\x3f\x1e\x24\x5d\xf3\x96\xe0\x64\x59\x69\xef\xa1\xf4\x4c\xd1\x77\x33\xd4\x17\x53\x41\xfc\x0f\xcc\x24\x2c\xfc\x47\xa9\x75\xe1\x13\xf9\xe1\x88\xab\x06\x68\x7f\xf3\x16\x0c\x17\xe7\x69\xdb\xa7\x64\x57\xe0\x65\xaf\x56\x78\x4c\x5f\x41\x5b\xf5\xe6\xe7\xf6\x84\x02\xc6\x66\xd7\x3d\x78\xe9\x4e\xd0\x0e\x6a\xf7\x69\xb3\xed\x97\x94\xee\x1c\x26\x64\x18\x8a\x63\x73\x9f\x6e\x02\xe0\x0f\x28\x74\x7d\xbc\x35\xdb\xdf\x73\xe3\xee\x59\x11\x74\xff\xb1\xfb\x0f\x0f\x0e\x82\xe6\x37\x50\x7b\x3f\x6a\xf7\x78\x83\xc2\xc6\x9f\xf0\x46\x5b\x99\x9d\xe1\x0f\xa5\x0a\xd7\x7b\x16\xec\xa0\x49\x17\x28\x82\x68\xde\x34\x49\x6d\x1e\x40\xce\xc5\x16\xc3\x00\x7f\x84\xd7\x92\xfd\x54\x12\x41\x79\x23\xfe\xd7\xeb\xf2\x7e\x83\x0a\x65\x5b\xbd\xd5\x71\x87\x03\x6f\x74\xe4\xad\x12\x7c\xca\x17\x6a\x9a\x9f\x94\xaa\xda\xa8\x63\xf2\x85\x4d\x1f\x2f\xbd\x93\xa9\x6d\x14\x2f\xdb\x3a\x57\xbe\x65\x2b\x58\xb8\x01\xbe\x9a\x4f\x96\x9d\x9c\xcd\x0e\x29\x2b\x22\xc1\x76\xc6\x4f\x6e\x7c\x61\x9d\x1a\xd2\x15\xf0\x70\xb3\x3a\xe3\x6f\x69\x9d\xdc\x08\x69\xe3\x60\x83\x99\xff\xbf\x4d\x72\xff\xb8\x89\x76\x28\x57\x00\x51\x3e\x3e\xb5\x75\xb2\x4a\x3e\x3c\xb7\x5d\xfa\xcb\x81\x4b\xf7\x88\x53\xd0\xfe\xc8\x47\xdd\xcc\x52\xff\xba\xc5\xea\x16\x79\xea\xac\xe1\x7d\xa4\x44\xc8\x33\xf8\xa1\xee\xb6\xfa\x45\xf0\xaf\xff\x41\xef\xd4\x12\xf1\xff\x7a\xcc\xcc\x3a\x13\x36\xdf\x7e\x18\x74\x3f\xca\x64\x39\x1d\xb9\x11\x0b\x47\xba\x0f\xb1\xde\x0f\xb6\xd6\xc3\x7e\x75\x88\x86\xba\x2d\x34\xfe\x4a\xa9\x09\x2e\x20\x62\xc3\x3b\xb5\x53\x5e\xad\xa3\x03\xfd\x3e\x0a\x7d\x23\x38\xcf\x4d\x92\x58\xed\xc7\x5e\x1e\x29\xb4\x3d\xab\x7d\x89\x1a\x31\xe0\x44\x78\x34\x87\x6b\x9b\x06\xc9\xb5\x8e\x66\xe5\xe1\x60\xe3\x87\x23\xc9\xf9\x8e\xe8\x87\x1d\x53\x78\x93\x53\x04\xcc\x16\xfb\x89\x3e\x38\x6f\xc4\xe4\x36\x9e\x91\x44\x7b\x27\xf6\xc2\x3d\x88\x83\xda\x61\x58\x5d\x87\x4f\x97\xfd\xb1\xf0\x01\xe7\xa5\xcc\x83\x43\x21\xa6\x76\x6c\x64\x70\x2b\xfd\x3a\xf5\xd4\xd5\x6f\xb6\x25\xde\x49\x01\x58\x55\x57\x96\x20\x9e\x70\xcb\xed\xba\xff\x80\x6a\xa8\x07\x67\x86\x6a\x7b\xff\x80\xe5\x50\xb0\xc3\x22\x9a\x64\xe9\x04\x51\xec\x65\xa4\x2b\x15\x76\x74\xd7\xcc\xee\xfa\xed\x45\xe7\x0e\x7f\x00\xbc\xe2\x6e\x1f\xca\xdf\x3c\x6c\x68\xf5\x36\x76\x9b\x09\xfd\x41\x0a\xb7\xb0\x45\x67\x4e\x1c\x9c\x72\x47\xc7\x28\xd1\x92\x56\x3e\xd2\x5b\xb8\x28\x9d\x5a\xad\x21\x6e\x23\xad\xfc\x7d\x0a\x6f\x38\xe5\x13\x75\x26\x0d\xca\x19\x84\x2d\x44\xe4\xf6\xc2\x27\x06\x51\xcf\x7b\xba\xf6\x6e\x73\xcc\x22\x7c\x19\xfb\xc9\x3c\xa8\xd8\x06\x61\x2a\x05\x45\x32\x39\xdf\x33\x8c\xdc\xf9\x2c\x3b\x49\x92\x14\xc8\x54\x25\x6c\x50\xb5\x5f\xa1\x3b\x9e\xfb\x35\xe0\x0a\xd9\xca\xfa\xfc\xc4\x95\x7b\x6b\xf1\x3d\xb0\x9a\x0a\x94\xc2\xce\x04\x0d\xe0\x1b\xc4\xaf\x04\xf4\x62\x72\x71\xb7\x44\x4a\x25\x61\x8a\x70\x9e\xc2\x46\xb7\xf0\xe6\x06\x54\xf4\x44\x47\x30\xd0\x8b\x90\x59\x83\x4d\x8d\xb8\x3c\x9b\xad\x4b\x7a\xd5\x15\x12\x72\x1f\xcd\xa1\x4b\xda\x58\x11\xc3\xc0\x96\x6f\xd2\xc9\xe9\x3e\x68\x06\xb4\x98\x1a\xd8\xce\xcf\x2a\x4f\x1d\x7f\x50\xfe\x44\x81\x45\xd4\x2f\xa1\xe2\x19\x6d\xfc\x62\x1b\x4d\x06\x8d\xac\xb1\x9b\xf7\x81\xd0\x06\xf4\xc3\x28\x4b\x7e\xe9\x85\xf2\x4b\x09\x14\xbb\xca\xe2\x48\xc9\x5d\xf3\x44\x7c\x03\xcc\x3b\x01\x09\x7b\x7f\x17\x36\xe7\x37\xf2\xdd\xa5\xf7\x80\x46\xa4\xe8\x31\x92\xb1\x3d\xc0\x75\xff\x4b\x2d\xb8\x4d\x9e\x9c\xb6\xc2\xd6\x30\x87\xc2\xd9\x13\xa9\x15\x3c\xe3\x97\x36\x0f\x2c\x65\xd2\x71\x8c\x96\xbf\x6f\x9d\x96\xf9\xe5\xaf\xe7\x9d\xfe\x87\x62\x2d\xd8\xfb\xb7\x19\x77\xd4\x40\x77\x29\xc3\x68\x91\xdd\xca\xa2\x2d\xc6\x92\xc3\x82\x86\xe1\xc0\x1a\x1e\xad\xed\x1f\x46\x46\x08\x02\x24\x7f\xc0\x7e\xb6\x81\x14\x00\xff\xe9\xff\x40\x36\xc4\x07\xff\x2b\x92\xad\xfc\x15\x38\x7f\xd2\x57\xe0\x8f\x82\x51\x89\x03\xec\x84\xf0\x84\x08\x67\x03\x6c\x89\x1e\x57\xb6\xef\x09\xb9\xa5\x9d\xa6\x51\x0b\x4e\x35\xa8\x60\x53\x55\xbb\x60\xaa\xf3\x17\xd1\xe8\x3e\x1c\x43\x11\x7d\xee\x9f\x44\xa0\x43\x13\xbc\xa3\xcc\x8f\x80\x32\x3a\x35\xab\x27\xb1\x40\xa7\x79\xac\x56\xcf\x3c\xfe\x1f\xe3\xe3\xa2\xf7\x7f\x0e\xc2\x3a\x5a\x16\x1d\x35\xa7\x53\x76\x8d\x1c\xef\x43\xd6\x0e\x3b\xfa\xf6\x3c\xed\x63\xa7\xf4\xe1\xda\x69\x83\x4c\xcf\xab\xf7\x22\xab\xab\xfa\xf3\x03\x8e\x58\xba\x14\xd6\xab\xcc\xbb\x7d\x50\x69\xbd\x7e\x62\x90\x83\x26\x10\xaa\xb9\xb1\x7e\xbf\x4c\x3c\x6e\xa2\x1a\x68\xae\x43\xf1\x6c\xe7\x92\xe3\x0c\xe7\xfc\xcb\xe4\x10\xf4\x40\x5a\xd7\x58\xae\x80\x3e\xd6\x38\x0e\x5d\x50\xed\xd7\x3c\x48\xcb\x3a\xce\x67\xc4\xd6\x45\xea\x88\x53\x88\x88\x59\x84\xd3\x8c\x0d\x9e\xff\xb8\x60\x71\x47\x62\x57\x5f\x3c\xc3\x9b\x86\xb7\x46\x0f\x87\x3d\x6e\xc5\x72\x48\xa8\x09\x20\x84\x91\x79\xe9\x0c\xc9\xb5\x40\x62\x44\x77\xd0\x2c\xe6\x59\x6d\xd3\xe7\x80\x03\x2d\x30\x3d\xab\x43\xdf\xe5\xb3\x79\x81\xf9\x88\x98\x88\x55\x53\x6e\x7f\x08\x48\x84\x4b\xf9\xb3\xc4\xe3\x57\x77\x03\xb2\x03\x1b\x1b\xcf\xf9\x94\x58\x18\x9f\x64\x16\x0a\x02\xca\x16\x91\x4d\x67\x32\xd0\x97\x8b\x56\xc7\x1c\x49\x0a\x00\x67\x23\xbf\xc5\x36\x52\x04\x2a\x30\x37\x39\x06\x91\x0f\xd9\x54\x06\xcc\x11\x43\x87\x14\xb2\x70\x8c\xbc\xba\x77\x1e\x44\xf8\x3c\x81\xbc\xd1\x44\x0c\x27\x93\x24\x91\x27\xba\x15\xb5\x78\xf2\x21\x56\xa8\xa1\x1e\xa7\x32\xf8\xba\xfa\xbf\x2a\xaa\xbe\x95\x3f\x0f\x47\x3e\x56\xe1\x1e\xab\xb4\x6d\xc3\x1c\xdc\xc3\xa1\x61\x33\x43\xde\x96\x46\xd1\x7f\x38\x95\xe1\xd7\xd7\xec\xbf\xe9\x60\xd9\x8d\xad\x61\xf0\x0a\x48\x5a\x04\x26\x51\x4e\x0d\x74\x57\x68\xf8\x7b\x49\xbf\xfa\xb0\x9a\xb1\xc1\x44\x62\x39\x7c\x92\xb8\xb4\x79\x02\xb5\x4a\xfd\x72\x45\x38\xf5\x45\xf4\xbb\xf7\x1d\x9d\xa0\x8c\x60\xf1\xa3\xcc\x8c\xf8\xe9\x00\x09\xd6\x16\x6a\xd7\xd3\x8c\x2c\xfe\x48\x6a\x70\xda\x76\x95\x90\x7f\x0f\x0b\x11\x49\xb1\x53\x1d\xa6\x33\xe8\xfb\x91\x06\x22\xa2\x4c\xcf\x2e\xe4\xc3\x39\x0a\xa2\x9e\xc0\x6f\x63\x09\xbe\x02\x5f\x36\x6d\x47\xb4\x5b\x9d\x8f\x10\x8d\x7b\xe7\x24\x88\xb1\x91\x86\x12\x1c\xde\xae\xde\x4b\x48\xed\x10\xdc\x1d\x18\x85\x24\xcd\xf5\x6c\x36\x5f\x7b\x0b\x9c\x46\x2f\x8f\xe9\x1c\xd0\x65\x07\xbb\xa0\x84\x11\x57\xb6\xd5\xcc\x6b\xfc\x33\xac\x89\xcb\xa7\x59\x1d\x93\xfa\x50\xf6\xb2\x11\x3f\xa0\x79\x3f\x58\x05\xca\x72\xed\xd6\x1f\xaa\x61\x97\x46\x33\xe5\x02\xbe\x12\x3e\xcc\x4e\xa9\x22\xbd\x7e\xbf\x57\xf6\xfc\x27\x08\x08\x78\x9b\xe2\x80\xbb\x3c\x10\xc8\x01\xa3\xfe\x2e\xa4\xd9\x5b\xa5\x15\x41\x80\x1f\x2a\x0b\x51\xc2\xab\x17\x89\x21\x22\x39\x84\x0f\x84\x1f\x6a\xe7\x73\x81\xd8\x04\xa1\x3e\x48\x10\xa7\x8b\xb4\x0a\x7c\x81\x2e\x9a\x9d\x8a\x41\xbb\x6f\x24\xc3\x40\x0a\x0a\x9b\x7e\x25\x4a\xb2\x0d\xba\x84\xe8\x20\xe8\x0f\x61\xeb\x75\xe3\x56\x1f\xa1\x22\xa0\xb7\x17\x4b\x5b\x1c\xc7\x2a\x06\x7f\x38\x31\xab\xc7\x9b\xce\xf9\xeb\xdd\x1f\x8c\x77\x61\x0e\x1b\xd5\xd8\xb8\x1d\xc7\xf5\x98\x64\x06\xf6\x0b\xbd\x4e\xda\xbc\x7d\xeb\x91\x78\xfc\x99\xe6\x7c\xb3\x38\x5b\x5f\xf7\x3b\xfc\xfa\x68\x3a\xd3\xb0\xcf\xa4\x2c\x08\xea\x01\x61\xc1\x9f\x6c\xb5\x08\xbf\x32\xb7\x4b\xc7\x33\x3f\xff\x5e\xad\x9f\xd0\xef\xd8\x4c\x22\x9a\x42\x0b\xff\xb1\xd1\xb3\x21\x07\x25\xeb\x53\xbd\xad\x36\x22\xf7\x5f\xd0\xe7\x1b\x3c\x2a\xdd\x85\x47\x0b\xdd\x70\x2f\x39\x0e\x02\xd9\xf8\xc7\xf3\xf8\x1d\x72\x47\x04\x19\x2e\x91\xcf\xfd\xf9\x05\x7f\xdb\x5b\xd0\xde\xcc\x8a\x61\x5d\x46\x28\x8b\x19\x92\xf8\x2a\x5e\x97\xbd\x8a\x9f\xdf\xaf\x39\xd2\xb7\x6d\x0b\x7c\xce\xc1\x3e\x70\x37\x97\x87\x67\xb3\x10\x98\x48\x7a\xc7\xaf\x14\x6e\x3f\xb0\x2d\x4c\x91\xed\x43\xdd\x38\x99\x9b\xed\xcf\x7f\x7c\xc3\x7a\x49\x03\xdc\x27\xda\x5f\xd1\xe3\x52\x06\x0a\x6b\xef\x8f\x4e\xd4\xdb\xbe\x06\xa5\x7c\xbf\x43\xc3\x72\x57\x47\xf3\x65\xff\x05\x1c\xd9\x77\x5f\x77\xed\x42\x74\x1e\x95\x1e\x48\x07\xd5\x8f\xb6\x30\x55\x2a\x0b\xea\xa5\xf0\x16\xb7\x36\xe0\x72\x75\xc7\xe4\x7a\x13\x2b\x84\xd2\xc0\x0f\x2c\x3b\xee\x19\x79\x47\xfe\x3f\x62\x47\x77\xcf\x61\x5c\x1d\xc1\x59\x7e\xa2\xdf\xf3\x20\x42\xfd\x9d\x1d\xd6\xbb\x1b\x29\xfa\x4e\x7d\x64\xc5\x34\xd4\xa2\xca\x77\xab\xf1\x9a\xa8\x4a\x0f\xa9\xb9\xfd\x41\x6a\xc4\x19\xa1\x53\x1e\x1f\x37\x34\xd0\xc3\x6a\x54\xc5\xc7\x74\x0d\xf9\x90\x33\x75\xfa\x34\xb6\x44\xdc\x97\xc2\xca\xec\x28\x3b\xb6\x42\xe4\x41\x94\x96\x58\x0e\xf4\x23\xb0\x8f\x71\x17\x2d\xc3\xd3\xcb\x15\x23\xb9\x27\xea\xd7\x05\xf7\x5b\x41\xfa\x86\xd5\xb9\xa2\xcb\x59\x50\x82\xd3\xb0\x54\x29\x06\xa8\xa3\xb7\x85\x87\xf7\xa4\xb0\x32\xb0\xe1\x34\x33\x91\xdc\xfd\x74\xaf\xdc\xe4\xef\xe8\x5b\xed\x31\x08\x9d\xc0\xb9\x0a\x21\x89\x33\xda\x71\x91\x55\x68\x48\x95\x0b\xf4\xdc\xc8\x0e\x73\xc3\x46\xf8\x9e\xd2\xfb\x16\x74\xc8\x9c\x19\x8d\x88\xb5\xd8\x17\x1a\xa4\x70\x37\x42\x13\x32\x22\x71\x45\x4a\xe1\xa0\x70\x7e\x22\x5a\x06\xf4\x40\x07\x1e\x6a\xec\xed\xce\x3a\xec\x2d\x90\x86\x5a\x1a\xb0\xe7\x98\x4a\xf3\x56\xa8\xe4\x05\xbd\xe8\x83\xc0\x08\x09\x0f\xe2\xf2\x9f\xc1\x9c\x05\x93\xed\xd2\xd1\x9f\x33\x15\xee\xd6\x90\x97\xae\xbe\x10\x62\x07\x57\x0d\x1a\x25\xdc\xb6\x4a\x91\x49\xd3\x31\x5c\xf0\x4c\x61\xb7\x06\x8b\x7a\xce\x9b\x20\xfe\x3e\x18\x51\xf3\x70\x8c\x84\xd5\xdc\xff\xea\x4f\x1f\x0e\xbe\x84\xcc\xc4\xa1\x89\x9f\x76\xdf\x1a\x1e\xa7\x78\x12\x25\xd2\x15\x6c\x34\x9c\x61\x90\x06\xed\xb6\x72\x51\xec\x8f\x49\xb4\x02\x70\x28\xd8\x15\x3d\xca\x7c\xe9\xaa\x3b\xa0\x20\xe6\xac\x75\xac\xe5\x0e\xbf\xb4\x9b\x93\xf4\x41\xa1\x27\x60\x15\x09\xee\xe7\xbc\x44\xc6\x20\x24\x32\xfc\xdf\x4f\xda\xb5\x81\xa6\xce\x78\xf8\x7c\x37\x19\xea\x91\x01\x10\xea\x19\xc1\x19\x02\xef\x67\x2f\x2f\x11\x3a\x60\xb7\x49\xda\xc5\xdd\x74\x0e\x56\x4b\x93\xb7\x76\xa0\x2f\xc8\x27\xb9\x62\x4c\x9a\x85\x88\x00\x3c\xf8\xe3\x1e\xf4\x1d\x28\x81\xf9\x96\x30\xbd\x16\x48\xb5\x97\xb4\x88\x67\xe1\x97\x8a\xa7\x5e\x16\xef\xc5\xfb\xd0\x2f\xa4\x3d\xbf\xc9\x82\x74\x7d\x1d\x5e\x66\x67\x07\xce\xc3\xe1\x14\xe3\xb3\x10\x6e\xdc\x7f\x96\xe4\x36\xc1\xa8\x0a\x00\xd8\x31\x86\xbd\x9a\xa4\x1e\x50\x1a\x44\x4e\xcf\x3a\xdf\x0a\xea\x99\x04\x19\x30\xc6\x9b\x50\x07\x00\x0b\x9d\xda\x9b\x82\xf7\x40\xa5\xe0\x0d\xfd\x86\xb4\x78\x99\x9d\x8d\xb2\x15\xc3\xc8\x63\x7d\x42\x4c\x70\x36\x61\x41\x1f\x57\x26\xac\xb1\xcf\x57\x8b\xdd\x41\xdf\x88\x43\xd1\x13\x9d\x84\x41\xcb\xb3\xbb\x8a\x8b\x81\x73\x27\xa8\x54\x5b\x72\x84\x3d\x89\x9e\xd1\xe8\x15\x0d\x52\xa1\xfa\x6f\x6b\x3c\x8f\x24\xad\xcb\xd6\xfc\xe8\x20\xb1\xe1\xbf\x8a\x83\x1c\xd3\xec\xf4\xe1\x03\x86\x53\x20\x49\x6f\x53\x18\xa1\xf0\x4d\x54\xd9\x0d\x00\xf0\xad\x30\xfa\x1a\x70\x47\xff\xfd\x84\xae\xbe\xf6\x0a\xb1\xef\x1b\x36\x87\x9e\x8f\xdf\xe6\xde\x06\x1c\xc1\x36\x7a\x27\x31\x63\x22\xdd\x43\x70\xe8\x3a\x1f\x8c\x96\x58\xff\xf5\x10\xf5\xac\x4e\xa9\x28\xd6\xb9\xb9\x91\xe0\xb2\x74\x16\x85\xed\x43\x9d\x4c\xb3\x66\x27\xe7\xc3\xc2\x9b\xcf\xcb\x49\x09\xf5\x8a\x47\x5e\xd3\x5b\x72\x7f\xdb\x3a\x0f\x0a\x0d\x58\x53\x73\xa6\x5f\x93\xbc\x61\x16\x5b\x80\xc5\xb0\x20\xf1\x02\x2d\x73\x6e\x73\x96\xd3\xe5\x42\x91\xe8\x99\xbb\xab\x0b\x76\x85\xb2\x5c\x96\x5d\x11\x46\x80\x3e\x3c\x46\x48\xcd\xf4\xc5\xed\x08\x7c\x90\xc0\xd6\x14\xfc\x71\xcb\xdb\x1c\x34\x0b\x8f\x86\x16\x3c\xb2\x04\x4e\x32\x9e\x22\x5f\x34\x8f\x3f\x30\xf0\x5b\x1e\x91\x13\x30\x7c\xff\xbb\xc0\xc7\xe3\x01\x94\x03\xe8\xb4\xfa\x27\x7f\xfa\x2c\x7f\xe1\xa8\xf3\x57\x09\x1f\xc0\x32\x80\x3b\x0a\x44\x98\x33\x78\x88\x9a\x6f\x0c\xe7\x77\x5c\x53\x8d\x20\xe5\xaa\x0b\x3f\xd2\x43\x8e\xd6\x23\xd3\x87\x66\x6b\x7c\x67\x13\x73\xa7\xe0\x1a\x17\x4e\x03\xcf\x27\x18\xb3\xc1\xf4\x90\x6a\x6d\xaa\x91\x0c\x6a\xfb\x11\x62\x23\x4a\x04\x06\x1b\xef\xe2\x31\x52\xca\x6d\xa8\xe0\xd1\x71\xe4\x66\xdc\xd6\xb3\x44\xd5\xfc\x44\x9f\xfe\x49\x7a\x4c\x78\x0c\x34\x42\x07\x8c\x33\x9a\xa5\xdc\x6c\x55\xf1\xdc\xa0\x91\x5b\xc6\xf5\xc4\x49\x98\x97\x04\x79\x2d\xc9\x1c\xf5\xb8\x9b\x92\x62\x9c\xe4\x3e\x70\x87\xa0\x42\x0e\x05\xe9\x6c\x16\x02\xdb\x26\xd0\xc7\xb6\xdb\xbc\x65\x0d\x75\xd8\x44\xf1\xd1\x94\xc6\x86\xc1\x8c\xf1\x0e\xc7\xea\xad\xe3\x8b\x43\x30\x16\x9d\x97\x51\xd1\x98\x50\x4e\x12\x62\x97\x4a\x0c\x22\x59\xa9\xf0\x42\x02\x38\x22\x37\x02\x9d\x71\x23\x29\x4d\x0c\x2c\xbd\x62\x24\x02\x88\x14\xe8\x23\x5c\x27\x08\x77\xd4\x16\xc0\xe4\x66\x8b\x1c\xc2\x35\x4a\x8c\x8f\x96\x5d\xfe\xb4\x3d\x3e\x1d\xdf\xea\x3f\xe5\xc3\xb3\xca\x12\x1c\xbe\x88\x72\x16\x80\x09\x51\x34\xad\x9e\x72\x84\x79\xb6\xc0\x0a\x1b\x31\xcd\xea\x69\x57\x3e\xd9\x1f\x79\x8b\x52\xeb\x39\x13\xd0\xb6\x6d\x03\xe5\x17\x11\xde\xb4\x08\xd6\xb0\x4f\xab\xcc\xba\x67\x3a\x27\x17\x1b\x3d\x13\x82\x0a\xe5\x21\xf8\x4c\x23\x03\x4c\x79\xf9\xe7\xff\x56\x96\x61\xf6\x2f\x7c\xc2\x40\xfd\xe4\xd4\x0f\x59\x45\x35\x35\x0d\x1c\xc6\x15\x12\x31\xd4\x5d\x9b\x54\xa0\x16\xb3\xb4\x42\x36\x9e\x45\x79\x1c\xce\x14\xde\x71\x68\x58\x1d\xe2\x60\x94\xda\x45\x26\xf0\xa0\x7d\xc9\x10\xfa\x3c\xbb\xa4\x83\xe4\x31\xc5\x52\x3c\xcc\x17\xb1\x8e\x19\x69\xb4\x64\x73\xc0\xa6\x86\xb7\x49\xcf\x31\x5b\xed\x2b\x0f\x39\x94\x48\x3e\xb8\xd4\xd0\x47\x36\x6a\x9e\x48\xfa\x08\x83\x8d\x21\xcb\xe1\x78\xc8\xca\xd9\x82\xb5\x9c\x40\x15\x9f\xe6\x42\x82\xeb\xd1\xd7\xdc\xf5\xc1\x90\x9c\xe7\xd5\x90\x18\x95\x00\x96\x93\x64\x5e\x7d\x5d\xc3\x49\xfc\xac\xdf\x16\x9c\x3a\x78\x37\x1b\xb4\xb4\x66\x3c\x8e\x19\x95\x0b\xd3\x2f\x12\x00\xf9\x4f\xc4\x4b\xa2\x7b\x49\xaa\x87\x0f\xca\x1a\x13\xb9\x2d\x06\x81\xc8\xec\xa2\x5f\x00\xe6\x5f\x67\xf6\x98\xfa\xe2\x79\xd4\x64\x85\x74\x81\x79\xb8\xdf\x8d\xca\x9f\x1e\x93\x81\x84\x3f\xbd\x15\xf6\x76\x62\x8e\x14\x74\x4c\xe5\x6f\x17\xf3\x13\x7b\xe0\x30\x32\x00\xe5\x43\x9c\x15\xef\x23\x89\xe8\x91\x42\xd3\x71\xe9\x93\xda\x2a\xf6\xe6\xb1\x0b\x87\x84\xd4\xa5\xbf\x44\x11\xc8\xda\x83\x00\xe5\xc3\x99\x0a\x0e\xd1\x9b\x20\xa0\x22\xdf\xe3\x6c\xa2\xe7\xae\xee\x71\x54\x76\x49\x57\x83\x2d\xe1\x31\x53\xe1\x6b\x17\x1e\xe9\xb2\xa6\x9b\xe5\x92\x8e\x5e\x77\xcf\x91\xbe\x02\x7f\xe9\xe6\x7b\x2e\xf3\x70\xdb\xbf\x92\xdd\xd5\x95\x4f\xab\x03\xbb\x72\xd2\xf6\xa1\x2b\x41\xde\x98\x0a\x43\x7f\x9c\xb2\xc1\xdb\x60\x46\x42\xdf\xb7\x02\x6c\x47\xaf\xac\xb5\xcb\xf5\x1d\xa2\x48\x75\xb3\x14\xe9\x1d\x2d\x9b\xba\x68\x58\x38\x83\x51\x4e\x4b\x18\x87\xd3\x81\x48\x1c\xa4\x5d\x76\x9c\xd0\xe0\x6e\xa7\xf8\x0b\x1b\x86\x19\x7b\x68\xa2\x6c\xe0\xc8\x26\x86\xe9\x0b\xe2\x06\x9d\xe9\x3e\x52\x6c\x04\x0a\x65\x33\x97\xac\xea\xa4\xd3\x45\xcb\x43\x47\x3e\x63\x95\x60\xc6\x66\x91\x10\xda\x80\x72\x21\x92\x8d\xed\xf6\x57\x40\x24\x7c\x87\xf6\x11\xe5\xe4\x8b\xcb\xc6\x31\x8f\x54\xc9\xa1\x04\x17\x36\x3a\x3c\x49\xf8\xbb\x5d\x2e\xf1\xce\x52\x30\x60\xd3\x26\xf0\x5c\x7e\x09\xb4\x4b\xb8\x9b\x3d\x82\xd0\x63\x3a\xb1\xcf\x31\x12\xfc\x33\xff\x84\x65\x0c\xcd\xf2\x0d\x2c\x8c\xd8\x39\x69\x20\x52\x16\xc6\x23\x17\x45\x24\xce\xab\xfe\xb2\x8c\xfb\xa6\x53\x4b\xd6\x97\xee\x35\x5f\xa4\x1e\xda\xa7\x74\x4e\x48\x99\x88\xd0\xe0\xcb\x98\xe8\x66\x07\xb8\x46\xc0\x4c\xc8\xc3\x3e\x89\x0e\xdd\x36\xd7\x28\x48\x6b\xfe\x4f\xc0\x4b\x33\x58\x87\x09\xb9\x23\x24\xd3\x7c\x5f\xac\xcb\xdf\x50\xbf\xbf\x1b\x9e\x92\x3f\x22\x29\xbf\x43\x1b\x82\x8d\x8a\xc3\x3c\x24\x18\xc4\xb9\xfe\x76\x87\x8f\x9f\x53\x7c\x5a\x4f\xd2\xc8\x6d\x24\x7d\x82\xfb\xb9\x3b\x49\x04\x96\x0d\x2e\xed\x98\xed\x4b\xdf\x89\xc5\x90\x54\xf5\xca\xa7\x7c\x19\xf6\xfc\x0d\xce\x48\x8e\x44\x8c\x17\xca\xdb\xf3\x21\xcf\x3e\x5f\x13\xdd\xa5\x21\xfc\xda\x0b\x51\x03\xff\xc3\x73\x61\x32\x87\x83\xa4\x24\x75\x3a\xa5\x18\xd9\x83\xbb\x51\xd1\x68\x70\x27\x05\xb0\xfc\x68\xd6\x87\x95\x4e\x4c\x0d\x5b\x1f\xe4\xa0\x7f\x97\x8f\x00\x13\x3d\xb3\x30\x07\xa7\xb4\xb1\x3f\x0a\x00\x0a\xf1\x91\xdd\x56\x5c\xbf\xa2\x6e\x42\x41\xb7\xbd\x21\xdf\x79\x61\xb7\xf2\x43\x75\x26\x38\xf3\x73\x20\xaf\x91\x7b\x4a\xcb\xe2\x08\xf9\x1d\x67\xf9\x1d\x62\x52\x0f\xee\xba\x82\x22\x92\xee\xe6\xd5\x87\xac\x84\x16\xaa\x4b\x74\xe0\x9e\x7f\x7e\x80\x77\x6e\x26\x0a\x07\x65\x62\x82\x3e\x28\x00\xa1\x07\xa6\x9d\xec\x52\x60\xac\x3f\x37\x83\x59\x9f\xf7\x9a\x18\xb3\x49\x71\xc7\x97\xa3\x3b\x54\x1e\x27\x71\x24\x20\x21\x4d\xd6\x21\xa3\xa6\xcb\x79\x1b\xf2\x53\x78\x7b\x69\x84\x70\x04\x17\xc4\xf9\xfb\x0d\x4f\xee\x2b\x8f\x61\xfe\x03\xda\xc8\x4c\xb0\x63\xf6\xd4\x3f\xb7\x5e\x00\x14\x72\xde\xdf\xa5\x1c\xcf\xf8\xb3\x6b\xa2\x8f\x60\x91\x04\xf7\xdc\x83\xa6\xfa\xc0\x50\x9c\x69\x34\xc7\x58\x3e\xb1\x8e\x9f\xfc\x02\xb5\xde\x7a\xad\xdc\xc7\x2b\xa4\xf3\x88\xf0\xb0\xfe\x67\x5c\x76\xa5\x7a\xff\x8c\xe6\xe3\x01\x88\x8d\x7a\x50\x3f\xe2\xcb\x8d\x82\x32\xce\x4f\x80\x58\xe7\xa7\x13\xd9\x64\x0a\xbd\x47\x75\xc1\x98\xad\xc0\x11\x80\x85\x5d\x33\x9f\xcd\xb5\xcd\xa1\x94\xc0\xfe\xc1\x3d\x16\xf6\xe1\x7a\x08\x7f\xdc\xac\x36\xae\x0b\x4e\xa8\x3c\xd9\x84\xb9\x88\x2d\x03\xe2\x74\xc4\x00\xcf\x5d\x27\x44\xe5\x23\x07\x74\x6c\xf1\xfc\xe0\x93\x0a\xd0\x71\xe2\x27\x61\x3e\x7f\xed\x74\xf5\x3f\xd3\x71\xe8\x19\xe2\x45\x40\x09\x01\xc9\x0e\x45\x23\x75\x65\x2b\xea\xf0\x40\x61\x79\x08\xc6\xbf\x3b\xca\x87\x0d\x9c\x63\x85\x0a\x49\x00\xc8\x37\x06\xf7\x15\xd4\x12\x7d\xaf\x87\x07\x9f\xbe\x35\x52\x34\xca\x81\x74\xab\x9d\xd6\x0c\xe4\x00\x20\x3a\x8e\x20\x05\x61\xd9\x83\x6c\xa8\x03\xdc\x7d\x62\x17\x6f\x38\x86\xf4\xb4\x12\xbc\x99\x5e\x79\x44\x5f\xf0\x08\x56\x3b\xaa\x54\x45\x56\x01\x09\x19\x32\x1f\x4f\x40\xc7\xce\x9a\x27\xdb\x57\x3a\xd9\x4b\xe4\x67\x94\x0b\x76\xd9\xb4\x71\x68\x8a\x15\xe7\x8a\x15\xed\x19\xe1\x37\xcf\x23\x39\x4a\x85\x45\xe7\x2f\x96\x19\x16\x0f\x59\x83\xa8\x00\xcb\x60\x5f\xd1\x03\xe8\x89\xed\x74\x3d\xd6\x6b\xcf\x21\x00\xdf\xf3\xd6\xc9\x48\x68\xcf\xba\x54\x76\xce\xc3\x0e\xb3\x20\x03\x59\x64\x8e\x1f\x47\xa3\x12\x4b\xa9\x22\x47\x54\x72\x05\xb6\xca\x2d\x03\x8e\x7e\xf8\x93\x2d\x61\x65\x3b\x77\xb3\xad\x8b\x4c\xee\x4f\xd5\xcd\x5b\x09\x34\x06\x18\x3e\x29\x23\x21\x82\xc9\xf7\x97\xa4\xa0\x8d\x73\xde\x16\xa6\x7c\x5b\x26\xc0\xb7\xf5\x98\xba\x88\xad\x20\x8d\x3d\xc7\x48\xc9\xc6\x87\xad\x3b\x62\x8f\x6d\xfd\x12\x70\xd6\xd6\xcf\xb1\x8e\x80\x2e\x22\x6c\x06\xfb\x60\x3e\xb0\xaf\x7a\x49\xec\x20\x6f\xc1\x24\xff\x71\xf7\xe4\x36\x85\x4a\x29\x0b\x9f\xaa\x0d\x54\x61\xd9\x29\x02\x28\xe7\x6d\xbb\x98\x70\x8e\x9f\xd0\xdd\xe1\x8f\x16\x8e\x49\x55\xcc\x96\x26\x49\x7c\xd2\x70\x36\x64\x85\x64\x93\xb0\xbb\xc2\xc8\x21\x88\x8f\xae\xe6\xd5\xa7\x09\x51\x3e\xea\x21\x03\x1c\x9c\x2a\x2c\xd4\x57\x04\xab\x8a\x40\xba\x16\xd5\xf1\xa0\x94\xa8\x66\x59\x21\x54\x23\xf4\xf1\xca\x6c\xb9\xae\x4e\x7a\xd7\x3a\xb1\x46\x63\x77\xf5\xf4\x5a\x55\xa4\x6b\x7a\x87\x85\xc3\x5b\x86\xf9\x38\xf5\xe9\xf9\x40\x66\xd5\x9a\x84\xf1\x2d\x75\x3d\x88\x90\x34\x5e\x99\x0d\x19\xae\x5c\xbb\x72\x6b\x40\x41\xdc\x62\x1f\x58\xa0\x89\x7f\x72\x3b\x2c\xa1\xb2\x5c\x30\x71\xdf\xbc\x95\x4c\x75\x7b\x41\x2b\x20\xf4\x9a\x7b\xe9\xb4\xca\x2e\x6b\xb9\xda\x97\xa2\x3f\x7c\x04\xf5\x23\x11\x94\x53\xb0\xca\xec\x22\xd2\x36\x64\x22\x32\xf8\x18\x89\x5e\x12\x9e\x88\x4c\x22\xc9\x15\x9c\x91\xdc\x52\xd1\x04\xe9\x2d\x42\xd4\x17\x24\xbc\x11\xd0\x49\x41\x19\x58\x68\x60\xfd\x67\x9b\x81\xe2\xfb\xc4\x3f\x77\xe1\xf9\x10\x3b\x41\x76\x9e\xbb\x2d\x12\xdc\x06\x6e\xe2\xc7\x93\x7d\xfb\xf9\x29\x90\xa0\x48\x24\x37\x45\x1e\xf7\x84\x84\x0a\x62\x1e\x87\xe8\x18\x65\x09\xe2\xc0\xc4\xc0\x96\xa9\xf4\x55\xae\x8b\x58\x57\xfc\x9e\x99\xea\x52\xf8\xeb\x3b\x47\x64\x56\xf6\xec\xa4\xe0\x3e\x9b\x09\x1d\x82\xc4\xfa\xe5\x07\x51\x4e\x7a\xf9\x4d\x04\xe9\x5a\x5a\x19\x7f\xad\xbc\x21\xf2\x2c\x11\x11\x59\x45\x39\x04\x94\x12\x28\x09\x69\xa7\x53\x23\xf2\xda\x0a\x1d\x2e\x37\x36\xd1\xa0\xa2\x66\x94\xa3\xfd\x41\xcc\x60\x0a\xf0\x11\x83\xf4\xc3\x4c\x66\x21\x25\x37\xd1\x1a\xdb\x83\xea\x3e\x8f\x4d\x9b\x29\x4d\x76\xaa\x83\x98\x24\x08\x90\x72\xbc\x02\x6b\x5c\x2f\x32\x39\xf4\x35\xbb\x1f\x67\x39\x74\x3b\x54\x12\x71\x6c\xae\x83\xa4\x9b\x63\x15\x9a\x84\xeb\xc7\x6a\x10\x6e\x56\x88\xa1\x34\xef\xdd\xb1\x9d\x5f\x23\x75\xe6\x1c\xa9\x3f\x8b\x91\x2a\x95\x91\x44\xfe\xd1\xc5\x98\xfe\x46\x5d\xd1\x22\x8a\x89\x42\x83\x46\x78\x1d\xf9\xc3\x84\x19\x8c\xe9\xa5\xa3\xcd\xad\xc2\x5b\xee\x40\x75\x30\xe7\xf8\x86\x1f\xb6\xfe\x95\x9f\xf9\xa9\x28\x2c\x87\x58\x78\x43\x56\x26\xf9\x13\x32\x1f\xd9\xe7\xaf\x0a\xee\x79\x3a\x04\x1d\x1b\xb1\xa7\x00\x25\x17\xd3\xf8\x94\xfe\x54\xfe\x01\x8e\x61\xdc\x3f\x23\x1d\x3a\x18\x26\xb2\xff\x47\x33\xac\x38\xb7\xa5\xd9\x95\x3c\x73\x8b\xd0\x6e\xee\x02\x4f\x2f\x72\x1e\x61\x10\x39\x3b\x82\x22\xc5\x2a\xa6\x9d\x95\x34\xff\x2c\x52\xb9\xfb\x60\xc4\x97\xe4\xad\x7a\xed\x73\xb2\xd5\x00\xab\xf8\x21\x3b\xe1\x14\x85\xb8\x85\x2f\x34\x01\x10\xbf\x2b\x87\xec\x13\x62\x97\x41\x31\xa3\x2e\x78\x79\x08\x15\xe1\x9d\x3b\x93\xdd\x80\x8e\x3b\x98\x62\xef\x82\xd9\xae\xfe\x07\xb2\x30\x74\x5e\x0d\x39\xeb\x46\xe1\x42\x43\x72\xdb\xec\x21\x55\xf4\xcc\x09\x84\x0c\x34\x2c\x19\x92\x9c\xe4\x06\x57\xb3\xea\xfd\x5b\x11\xd9\xd1\xe9\xe2\x0c\x90\xbb\xaf\x6b\x40\x23\x55\x19\x9b\x80\x4b\x42\x3c\x53\xae\x8b\x26\x8f\x67\xf8\xca\x23\xd3\x88\x62\x9b\x33\x49\x1b\xf3\x09\xcc\x64\x97\x7f\x46\x59\x0f\xb1\x73\x01\xef\x50\x1e\x33\xfb\xe7\xec\x7d\x1f\x1e\xe9\xd9\xf9\x07\x86\x20\x86\x97\x8f\xb0\x69\x48\x3a\x99\x59\xec\x1a\xcf\xcb\x0e\xaa\x4a\x3e\x68\xfa\xde\x5b\xe5\x2d\xbf\x0b\xaf\x88\x4e\x72\x4d\x02\x06\xed\x93\x6d\xef\xbd\x80\xb4\x55\xe5\x67\x87\xb1\xca\xdf\x02\x89\xdb\x42\x6d\x12\x26\x78\x09\x64\xee\x48\x9a\x5b\xd7\x66\x40\x39\x06\x00\x63\x97\x88\x2f\x94\x48\x07\xd8\xb9\x6f\x80\x50\x26\x78\x26\x67\xb0\x4c\x58\x90\x75\x75\xf8\xb6\xf2\xbd\x62\x26\x93\xc9\x7f\xa8\x38\xce\x10\x61\x01\x4b\x19\x9b\x2c\x0f\x39\x73\xdf\x96\x2f\xc7\xff\x02\xae\xf3\xac\x9b\xe6\x4d\x82\x9c\x53\x3e\x7f\x6e\x4b\xd9\xd8\x2c\x41\xc4\x74\x1f\x8d\xdf\x59\xec\x84\xbd\x30\xac\x8c\x08\xf7\xae\x7c\x86\xcb\x0a\x46\x1f\x12\x3d\xeb\x90\x97\x4e\x41\x8c\xf0\x09\xbb\x7a\x9b\x94\xe6\x1c\xf4\xde\x6d\xdb\xf7\x4c\x64\x81\x76\x21\x4a\x77\xab\xca\x48\x14\x08\xca\xac\x2d\x8e\x65\xb8\xfc\x44\xe9\xfe\xc2\x5d\x72\x86\xe9\xb0\x0f\x7a\xb5\x08\x7d\x44\xe9\x51\xfe\x39\x4b\x9e\x12\xe9\x3b\xb3\x97\xb8\xcd\xfe\x0d\x00\x66\x8d\xd0\xf9\x2e\xcf\xa7\x32\xeb\xf0\x22\xfe\x72\xb9\xa3\x54\xc1\x29\x32\x22\xcb\xd8\x45\xe4\xaf\x61\xd3\x57\x43\x62\xb2\xe2\xc6\xcf\x3e\x8b\x1a\x43\x03\x58\x17\xe3\x28\xdc\x2e\xd2\xee\xe8\x0b\x6a\x05\x12\x71\x8f\x8b\x8b\x7a\xba\x84\x18\xa6\xf3\xcb\x48\x1a\xe0\x04\x44\x90\x12\xf5\x7d\x76\x82\xd1\x91\x83\xab\x5f\x3b\xcb\x6c\x66\x1b\x32\xb1\x18\x7d\xc3\xc9\x63\x33\x42\xfd\x85\x5c\x14\x17\xcd\x27\x82\x8a\x56\x11\x2a\x8a\xfc\x9d\x67\x16\x40\xdf\x2c\x43\x3c\x8f\x24\xf0\x23\x5e\x81\x7e\x95\x5f\x60\x33\xcc\xf1\xf9\x00\xd6\x41\x65\xf9\x89\x6c\xec\xf7\x47\x2c\x96\xb2\xca\x65\xf3\x6d\x3b\x75\x3b\x0b\xe9\x9b\xff\x76\x85\x94\xc3\x22\x91\x09\x46\xc2\xca\x3e\x22\x77\xcb\x87\xdb\x95\xe4\x74\xb9\x86\x4d\x96\xa7\xe8\x69\x3f\x00\x9a\x4b\x68\x74\x86\xd8\x17\xc1\x0b\xb3\xb5\xe1\xde\x73\x38\x7f\x4c\x45\x19\x8f\xb8\x52\xe9\x27\xf8\x56\xb3\xdf\x3e\xab\xf4\xb1\xef\x9f\x1c\xd6\x87\x7e\x24\x65\xe3\x0d\xe1\xd3\x4e\xd3\x8e\x53\x1e\x45\xef\x90\x2c\x02\x9c\x69\xb1\x7b\xbd\x80\x9b\xf8\x40\x29\x82\xd2\xdf\x54\xc6\x3e\x90\xc8\x37\x67\x5f\xc3\x5e\x50\x6b\xfb\x2d\x85\xce\xa6\x2f\xf0\xd1\x19\xb7\x50\x40\x74\x99\xf4\x36\x5e\xf3\xc9\x1d\x95\x95\x8c\xdc\x4b\xc0\x49\xd1\xef\xc9\x36\xff\xfd\x8f\xf1\x56\x2f\x9c\x3b\x95\x18\xcf\xe9\x51\x96\x04\x7e\x4e\xae\x3e\x2f\x30\xa2\x1a\xa1\x06\xea\x8e\xfc\x08\xce\xcd\xc6\x04\x2a\xc8\x20\x7c\x8f\x4e\x9a\x0d\x8b\x06\x20\x3f\xfe\xa9\xea\xa4\x65\xf1\xb6\x33\x88\x90\x8d\x7e\xda\xfb\xdd\x2c\x8c\x6d\x98\xb9\xd6\xdf\x55\xcd\x8e\xbb\x9e\x61\xb9\x76\x53\x9a\x78\xc3\x38\xd1\xd9\x06\xf7\x29\xa4\x0a\x7a\x22\xf7\x88\xe7\x98\x95\x0f\xe0\x24\xc5\x3b\xd8\xa8\xa7\xc4\x28\x51\xab\x72\x97\x43\xea\x20\xdb\xf7\xfc\x51\x60\x84\x42\x9e\xeb\xc2\x2d\x4e\xcf\x54\xb6\x4a\xaa\xcd\x94\x28\xf3\xbc\x7f\x89\x00\xb7\xb7\xd4\x05\x26\x65\x89\xf3\x6e\xab\xd6\xf9\x2e\x5a\x5c\xe4\xcd\x7e\xca\xf5\xed\xbf\xf9\x08\xef\xf4\xeb\xa3\xfe\x97\x95\x42\x89\x16\x9c\x35\x92\xf1\xea\x78\x56\xde\x32\x86\x93\xe1\x55\x95\x80\x7e\x7f\xe4\x67\x79\x0b\x7c\xb3\x19\xf2\x58\x44\xe1\x51\x66\xc4\x29\x05\x94\xe3\x54\x1c\x14\x24\xe1\xf0\xe1\x56\x49\xfe\x63\x21\xfa\x27\x93\x2a\xcc\xc4\x9b\x6c\x54\xf2\x3f\x9a\x27\x14\x02\x92\x36\xfd\xcc\x51\x26\x86\x4c\xdc\x21\x1b\x3a\xea\xa9\xfc\xc0\x43\xc8\xd3\x51\x22\xa4\xc8\x26\x22\x1a\xb6\x1c\x69\x0e\xc1\xfa\x25\x03\x98\x6b\x9b\x09\x63\xd9\x0f\x4c\xe7\x9f\xcb\x4a\x33\xa6\x47\xac\xa9\x05\x58\xd8\xa6\xe6\x0e\x53\x53\x5b\x35\x75\xf3\x90\x99\x27\xe3\x7f\x74\x2a\x87\x3c\xa3\x62\x8a\xe8\x2e\xfc\x85\x86\x94\x7f\x2c\x20\x5f\xf4\x34\x39\x68\x73\x73\xe5\x48\xbd\xe8\x4b\xc4\x1f\xce\x0a\x49\x43\x6b\x9a\x1d\x64\x4a\xa1\x7e\x4a\xa8\xca\x63\x0a\xc1\xf4\x15\x51\xba\x17\xfa\x67\x7c\xe1\x74\xb7\x88\xc4\x7d\x28\x1c\x58\x3d\xc0\x99\xf8\x54\x3c\x45\x7d\xe6\xc0\x94\xfe\x4d\x35\xb4\x8b\xda\xbf\x42\x0c\xd4\x12\x3f\x9b\x2a\xe0\x44\x82\x02\x0b\x52\x0c\xb3\x5c\x22\x6c\xbc\xc8\x19\xc5\xdf\x80\x34\xdf\xe0\xfc\xc8\x68\x14\xf9\xef\x1c\x78\xd2\xab\x4d\x13\x11\x94\x48\x32\x10\xa2\x45\x02\x64\x0a\xcb\x90\xd3\x85\x5d\x3e\xe8\x6d\xa7\x83\xcf\xf8\x3f\x2f\x29\x1c\xba\x69\x5b\x0b\xf8\x86\x9e\x2c\x22\x0e\x65\x7f\x79\x20\x3c\x81\xa5\x33\xbb\x31\xf7\x83\x04\x1f\x4a\xa2\x50\x1b\x38\x5c\x84\x7a\x8d\x32\xa3\x08\xf9\x39\xbc\x4d\xef\xaf\x35\x03\x63\x72\x6a\x8c\xed\xcb\xdd\xd6\x24\x33\x56\x05\x47\xf8\x2a\x3f\xc4\xca\x59\x84\x4c\x2d\x61\x23\x3a\x2a\x6b\x12\xe0\x14\x71\x22\xd8\xa4\x50\xbc\x54\x57\xee\xcf\x0e\xcc\x7b\xa9\xa5\x2e\x1c\x29\xf2\xe9\xed\x8a\x43\x1f\x43\xf4\x9c\x48\x7c\x29\xaf\x99\xab\x49\x18\x87\x0e\xf1\xc7\x2e\x86\x63\xc1\x14\xff\x70\xbe\x8e\xec\x54\x4e\x31\xb2\x0b\xc4\x90\x38\xee\xe5\xc9\x6d\x76\x59\x5f\x3c\x53\x4a\xb4\xf7\x8b\x55\xd0\x4f\xdf\x98\x17\x65\xa7\xee\x15\x7b\x25\x16\x84\x7b\x79\x91\xf1\xf3\x7c\x36\xbe\x82\x0c\x49\xac\x42\x13\xd1\xa7\x61\x51\x79\x23\x41\x6f\xc7\xf4\x4f\xf4\x0a\xfd\x19\x3f\x12\x45\xaa\x57\x5b\xe4\xa0\x7f\x6a\xb0\xc0\x66\xdf\x8e\xfa\xed\x1b\x9a\xcd\xaa\x6d\x30\x26\x88\x63\xdb\xe1\x2c\xf3\x6a\xc6\x2d\xd2\x6e\x90\xe3\x4e\xda\x9e\x42\x0b\x89\x4d\x1c\xe6\x4d\x45\xc8\x36\xef\xa4\xd5\xd8\x29\x24\xf6\xee\x36\x07\x36\xee\x6a\xa7\xc8\xd5\xcf\x6f\xd1\xba\xb7\x1c\x1c\x43\xfb\x4d\x84\x07\xd9\x4e\xc8\x31\x9f\x3c\x46\xde\xe2\x10\xe0\xd5\x15\xcb\xf4\xd6\xdb\xe3\x45\xe2\x80\xfe\xc9\x0b\x69\x64\x2f\x56\x67\xb3\xf9\x1f\x63\x15\x36\x8e\x61\xdf\x92\x39\x9c\xc6\x12\x8f\x69\x66\x08\x9b\x6d\xe6\xef\x8f\xa0\xb3\xfe\x94\xb0\xaa\x4f\xef\xf8\x7f\xa0\x2a\x63\x90\x3e\x74\x8b\x45\x76\x87\x7c\x4d\xef\x40\xc7\x4e\x32\x78\x08\x8a\x71\xd0\x50\xaf\x73\x91\x0e\xea\x47\xb2\x4a\xfb\x93\xff\x30\x2d\x55\x50\xd8\x10\x30\x60\x02\x57\x9d\xe2\xa6\xaa\x26\xe2\x6a\x3b\x23\xde\xf0\xe4\x87\x59\xab\x2a\x10\x20\x5c\xbc\xa5\xdc\x13\x6d\x2c\xd7\x42\xd1\xf1\x5a\xa4\xa6\x4a\x03\xda\x49\x0f\xa7\x0e\x09\x6d\x5e\xe1\x09\x11\xb2\x29\x6f\x49\xfa\x28\x2d\x85\x6c\xa1\xb7\xc8\x88\xc0\xc8\xe8\x19\xe3\x26\xa9\x04\xcb\x3c\x13\x74\xcd\xba\x96\xd7\xf4\x9e\xf8\x23\xac\x0a\x10\xb0\xa3\xc8\x45\x69\x8f\xb0\xc7\x5d\x46\xa9\xb2\x88\x49\x4c\x2b\x5d\xce\xd2\xf9\x61\x0e\x01\x55\x98\x7c\x2d\x67\xfe\xeb\x29\xae\x0a\x72\xf2\x52\xe4\x72\x5a\x82\xf6\x03\xa7\x0f\xff\xcf\x4b\xc9\xa1\xb5\xea\xaf\x39\x08\x46\xfa\x42\x17\x98\xf0\xfa\xe3\xd7\x72\x3c\x03\x18\x73\x18\x2b\x22\xeb\x3c\xc0\xd4\x9f\x9f\xcf\xce\x9f\x9e\xb7\x63\x09\xcc\x2b\x7c\xe4\x96\xc4\x50\x9a\x25\x55\x02\x5d\x2d\x43\x32\xd1\x2a\xc6\xf7\xd0\x9a\xd7\xff\x94\x3a\xf4\x97\x3e\x7d\xf9\xcf\x07\x9a\x71\xff\x12\x7b\x6c\xf3\x2b\x5a\x34\xd3\xe7\xf0\x50\x58\x52\x85\xa8\x1f\x45\x5f\x48\xfe\xa4\x55\x50\x56\xed\x9a\x44\xea\x6a\x5a\x29\x49\xa5\xd6\xef\x5b\xe6\x99\x36\xde\x82\x24\xf4\x6b\x38\xc1\x19\x86\xce\xa0\x93\xd8\xa3\x53\xe1\x53\x67\x4f\x64\x15\x04\x16\x41\x92\xa8\x83\x7e\x42\xab\x71\x8a\x66\xc9\x94\xc3\xe8\x15\x09\x1e\x04\xdd\x6c\x96\x3c\x3f\x34\x69\x5d\xd7\x1a\xc8\x97\x4c\x64\x22\x06\x1f\xdc\xa2\xb0\x60\xfd\x5c\xeb\x4c\xbf\xd5\x4f\x43\xba\x2e\xa6\xdc\xc2\x03\x29\x76\xf9\xb6\xe1\xf3\xd9\x7c\xb2\x12\x86\xe8\x17\x4b\x47\xa6\x91\x38\x32\xe4\x7b\x51\x99\xa1\x56\xd9\x22\x5b\xe1\x31\x9c\xc5\x9d\x53\x6b\xb8\xf4\x8c\xbe\x66\xf1\x39\x67\xfa\x0c\xf2\x97\x49\x5b\xb8\xba\x9c\xd4\x2c\x8e\xa5\x1e\xde\xec\x80\x5f\x6e\xd8\xbb\x14\x2c\xc6\x5e\x7b\x62\xf8\x0f\x28\x46\xa3\xd5\x22\x6c\x4b\xc9\x4d\xe3\x4f\xef\xe9\x46\xad\x34\x8b\x99\x51\x67\x05\x67\x28\xea\x20\xdb\xfe\x5f\x11\x5c\xf9\x1d\x84\x6a\xcd\x90\x48\x38\x41\x49\x92\xc5\x67\x55\x80\x1a\x5d\x5d\xea\xc2\x64\xa0\x67\x1d\x85\x67\x55\xd9\xc0\x3e\xdb\xea\x84\x5c\x13\xd5\xaf\x4f\xd8\x7d\xf9\x72\xfa\x14\x0c\xf2\x0c\x7f\x1d\x24\x6d\x79\xf2\xa5\xbd\x47\x02\x69\xfc\xd5\x9e\x84\x9d\x84\x8b\xa5\x33\xe2\x27\xed\xed\x93\xaa\x94\xb4\x13\x78\x26\x36\xfc\x32\x75\xe3\x19\x3a\xf8\x55\x43\x9a\xc0\x3a\x85\x1f\xcf\xf6\xce\xc3\x27\x06\x8e\x7d\x2d\x01\x6c\x8d\xde\xe9\x63\xc8\x0d\x99\x39\x1f\xd9\x46\x0d\x55\xf4\x1b\x12\x3d\x87\x3a\xf1\x2f\x99\xa6\x0e\x9e\xce\x79\x71\x24\x16\xd1\x89\x94\x2e\xde\xc9\x88\xc9\x52\xf4\x1b\x0f\x92\x54\x80\xfb\xa1\x81\x5f\xae\xe4\x06\x0c\x40\x9e\x31\x3d\x3e\xa8\xb2\x3a\x77\x49\x75\xad\x8e\x2c\x44\xbe\x3c\xfc\x5c\xd4\x21\xa9\xc7\x86\xc8\xae\x1f\xf2\x73\x8e\x4b\x6d\xc8\xee\x68\x87\x2d\xac\xfb\xd5\xca\x55\x60\x48\x84\x39\x06\x8f\x8d\x18\x59\xf4\x0f\xc9\xaa\x63\xfa\xca\xd8\xe2\x27\x2b\x5a\xe7\x26\xa0\x9b\x21\x25\x54\x55\x47\xad\xaf\x6c\x82\xf7\x41\xa2\x46\x9f\xa6\x17\x6c\x76\x88\x6d\xe4\x67\x49\x1f\xfa\xf7\x5e\xf5\x47\x2f\x9a\x45\x5f\xce\xaf\x7c\x5c\x8a\xdc\xcb\xfb\x12\x0a\xaf\x35\x64\x5d\x2b\xdb\xce\xd4\x6b\x05\x27\x0f\x7e\x6f\xac\xe8\xfb\xc2\x96\x4c\x5f\x84\x8d\xb7\xd8\x4c\x8c\xe7\xbd\x0f\x3a\xd4\x0c\xd2\x15\x51\x34\x45\x69\xfa\x78\xbe\x64\x3d\x83\x1f\x60\x23\xef\x08\xce\x06\xfe\x9a\x4c\x20\xf7\x21\x32\xe3\x15\xca\x02\x86\x9b\x0f\x9e\x69\xc5\x95\x68\x4b\x24\x7b\xa0\x7d\xf8\x31\xf4\x49\x4e\x33\x67\x88\xbc\xfa\xb4\xe9\x96\x4e\x6e\x34\x90\x63\x10\xb6\x3b\x7e\x16\x35\x81\xcf\xed\x7a\xab\x09\x0a\x5f\x9a\x21\xf6\xb6\x07\xe2\x11\x06\x28\x0d\x75\x6b\x5e\xb4\xc4\x8f\x6a\x03\xb5\x29\x02\xf3\x41\x38\xcf\xd8\xc5\x2b\x20\x09\x6e\xb4\xe2\x32\x21\xfa\x9c\x19\x2d\xf5\xa2\xa9\x0d\x12\xec\x1b\x5c\x16\xd1\x94\xb6\xe1\xa7\x60\x6c\xbe\x3a\xdd\x05\x02\xc9\x3f\x78\x1b\x31\x38\x47\xdb\x74\xbd\xda\xa4\xfd\x0d\x57\x97\x53\xeb\x15\x3c\x52\xde\xed\xb6\x4d\xea\x7f\xf7\xb0\x41\x39\x4d\xc8\xed\x13\x34\xa8\x77\xa4\x6e\x96\x08\x7e\xef\x3c\xbc\x97\x0f\xdb\x29\xc5\x83\xcd\xad\xdb\xe4\x72\x9c\x64\x19\x53\xb2\x88\x50\x9f\x4b\x1a\xc1\x0e\x29\x5d\x29\x94\x69\xc9\xff\xf1\x3c\x0c\xa4\x48\x89\x09\x96\x95\xc8\xd2\xd9\x36\x37\x32\x60\xee\xd8\x30\xe2\x52\x0c\xe2\xd4\xf8\x0c\x87\x5b\xb0\x53\xf8\x48\x71\x58\x5c\x17\x49\x63\x9a\x5f\xe1\xee\x90\x1a\x77\xe5\x9d\x7b\xc7\xf9\x60\x1c\x74\x67\xa4\x12\xa1\xe1\xc0\xb9\xd4\xae\xe0\xab\x31\x28\x12\x3b\x47\x60\x01\x12\x5b\xb3\x3d\x7e\x38\xcd\x9c\xcc\xb3\x4a\xb6\x98\x90\xda\x84\xeb\xd9\x6f\x01\x0e\xed\x13\x74\x92\xfd\xba\x5b\x8b\xfa\x0b\xac\xae\x2b\xb7\x43\xc8\x45\x12\x79\xad\x69\x46\x91\xed\x68\x9c\xb7\x75\x82\xdc\x34\x70\x8e\xb0\x2b\x98\x90\x1e\x4c\x78\xf1\xf8\xaf\xcd\x3f\x59\x84\xa6\xbc\x75\x14\xa0\xf5\x6e\x8f\xfb\x20\xde\x46\xc0\xed\x2d\x74\xe7\x7d\x32\xea\xf2\x5d\x34\xf3\x03\x79\xbb\x62\xb8\x6a\x9b\xf1\x6e\x85\xa8\x4d\xe7\xbd\x60\x36\x50\x09\x9b\xd9\x8d\x2a\x06\x8a\xc9\x6e\x62\x6e\x8b\xd2\x41\x67\xf1\xc9\xdf\x73\x00\xa1\x74\xc2\x51\x34\x4d\x8e\x08\x6c\x3b\x0f\x6f\xa2\x67\xca\xe9\x7b\xd3\xf9\x3b\x0c\x14\xde\x79\x0e\x98\xec\xa7\xd1\x7a\x27\x05\xab\x02\x15\x5b\x35\x3a\x89\x7e\x8d\xb4\xbc\x69\x06\x6d\xaf\xb9\x87\x4b\xad\x10\x30\x84\x13\xfa\x60\xef\x67\xc9\xca\xbe\xaa\xab\x5f\x2e\x35\xf3\xc1\xfe\x65\x06\xac\x8d\x5e\xc2\x5e\x51\xf7\x83\xb0\xa4\x9b\xff\x0f\x07\x0a\xab\xda\x2b\x8b\x31\xa5\x3f\x84\x9c\xd1\x3c\xa1\x7e\x58\x01\xd6\xed\x98\x9a\xa9\x2e\x51\x34\x9e\x84\x77\xbd\x83\x28\x75\x9e\x6d\x67\xed\x52\x34\xdd\x3f\x36\x05\x5a\xa5\xe5\x04\x9c\x6b\x98\x80\x71\x6b\x21\x63\x9c\xcd\xe3\xc7\x99\xe2\xb8\xe9\x5d\xee\x58\xe8\x6e\xe4\xaf\x11\xfa\x9a\xc0\x2f\xa3\x6d\xef\xbf\xc2\x43\x3b\xd3\xc5\x8c\x42\x2b\xdc\x31\x37\xfb\xec\x03\xb9\xaa\xb7\x5d\x08\xb4\xda\xd9\x9b\xd4\xfe\xf2\x4c\x43\x1f\x0c\x81\x1c\xd9\x67\x0a\x91\x59\xb3\x90\xbd\xc5\xcd\xc4\x44\x43\x92\xa1\xbb\xf7\x4a\x84\x65\x5f\xe9\xbb\x19\xf3\x84\x5f\x2a\x86\x13\xed\x77\x4a\x55\x68\x4e\x21\x9a\x76\xbb\xe2\x21\x72\x56\x61\xc4\x14\x34\xac\x10\xab\x85\x4a\xeb\x46\xc1\xbd\x5f\x91\x35\x78\x35\xbf\x20\xdf\xa3\xac\xba\x22\xaf\x43\x7a\x29\x48\xd7\x48\xa1\x42\x76\xab\x0a\xd8\x2b\x92\x81\xe0\xe4\xeb\xff\x67\xaf\xac\x4b\x3d\x46\x27\xb6\xa9\xd7\x16\xd9\x3e\x9b\x26\xb6\x0b\x3d\x3d\x25\xbf\x2e\x32\x13\x90\xd6\x0d\x23\xf8\x8f\xfa\x4d\x00\x7b\x66\xb6\x3a\xae\x59\xaf\x61\x2f\xa1\x4c\xd9\xa9\x28\xd1\x66\x6a\x69\x4e\xc8\xd3\x11\xe5\x6b\xee\x7e\x84\x30\xbd\x5d\x5b\x97\x76\xb6\xbf\x6d\x18\xaa\xc1\x0b\x5b\xeb\x2c\x45\xdc\x99\x95\xab\x13\x42\xb7\x42\xe2\xe6\x25\x26\xb4\x3b\xfe\xde\x77\x8c\xae\x9f\xb9\xef\x89\xfe\xc6\x3e\xd2\xb1\x8f\x71\x3b\x91\xb6\x43\x5b\x85\x0b\x09\x93\xf3\xf0\x4f\xfa\x6b\x73\x21\x73\x3e\x18\x7f\x96\x16\x10\xab\xc7\xc0\xb0\x41\xa3\x68\x95\xd3\x90\x88\x03\xc9\xd2\xdd\xa7\xaf\x6b\xe4\xb1\x66\x48\xf4\xca\xec\xf9\x21\x58\x56\x8c\x99\x2b\xac\x89\xe5\x67\x72\xa1\xfb\x1a\xa1\x3e\x2b\xc0\x0b\x7f\x1f\x09\x22\x11\x59\x12\x55\x72\xc6\x94\xa4\x46\x49\x9e\x13\xb1\xea\x20\xc7\x4d\x57\xe0\x11\xcc\xab\x21\x4f\x75\x0a\x59\x33\x43\x38\xcb\xd6\xac\x87\xff\x11\xb9\xc3\xc5\x5a\xd0\x5e\x8e\x57\xf8\x05\x91\x9c\x20\x6a\x0f\x44\xee\x86\x51\x2f\x6b\xd5\x59\x25\x68\xf7\x11\xb5\xf5\xcc\xff\x9d\xf4\xe7\x38\xdd\xd7\x84\xa3\x4d\xb4\x34\xf0\xf6\x49\x59\xb3\x79\x34\xb4\x7c\x73\x53\xf5\x91\x3d\x62\xab\x94\x9f\x65\xe8\x36\xee\x97\x6d\x12\x9d\x39\xe9\x7f\xe9\xdf\x02\x71\x10\xb3\xe9\x74\x23\xb7\x36\x5e\x78\x20\x66\x38\xfa\xad\xe8\x29\x50\x96\xf5\xbf\x8a\x5c\x3c\x87\xe3\xaa\x13\xf4\x0f\xd0\x04\xe3\x12\x3d\x6e\xda\x10\xc9\xe8\xf1\xc0\x3e\xe6\x14\x72\xe8\xe6\xc9\x82\x15\x89\x0e\x3b\x84\xe8\xb7\xc0\x4b\x49\x81\x44\x51\xd1\x1c\x10\xa8\x15\xc9\x02\x91\xbb\xbc\x47\x4c\x2e\x8d\x68\x0f\x6f\xfe\x48\x5a\x08\x9b\x1d\x09\xf8\xa6\x88\xdc\xc7\x22\x57\x7d\xf7\x7c\x48\x2e\x6c\x5f\x60\xef\x07\xa9\x6d\x8e\xac\x14\xdd\xa4\xab\xed\xb0\xef\x67\x25\xfe\x98\x5e\x32\x57\x8a\xb7\x93\xae\x10\x18\x26\x37\x97\xe0\xa3\x70\x6a\x52\xef\x77\xb8\x65\xa9\x0f\x65\x30\x77\xa4\xa0\xc5\xe9\x0d\x25\xfb\x6d\x08\xc6\x78\x1c\x92\x5e\xcd\xce\x7e\x72\xdf\xe0\x97\xf6\x70\xee\x9b\xf0\x32\x2b\xeb\xe9\x67\x61\x33\xbc\x0c\x11\x8a\x3a\x70\xc5\xde\xb1\x68\xf5\x45\x3e\x3f\x7b\x0d\x4f\xfd\x3d\x3c\xb6\x76\xab\xb5\x3f\x7e\xe1\x7b\xa0\xd1\xcc\x44\xa3\x19\x7a\xe2\x41\xa8\x63\x23\xc4\x51\x32\x63\x3f\x72\xf1\x7a\x7e\x4f\xa2\x74\xec\x29\xa1\xb6\xd9\xaa\xe0\xbe\x0a\xce\xcb\xa2\x08\xa3\x2a\x6f\x24\x9a\x5d\xb8\x97\x33\x31\x42\xad\xde\x9b\xad\x5f\x91\x7a\xb0\x95\xfe\xfb\x19\xb5\x7b\xb1\x3f\xee\xfc\xad\x5e\x74\x6c\x73\x40\xd4\x1b\x99\xf3\x5b\x98\x0e\xcd\x6b\xa1\xaf\xf3\xea\xcc\x2c\x0e\x25\x51\xda\xf0\x4d\xf0\xe9\x99\x1f\x7b\x6b\x81\x89\x36\xa2\xe7\x53\xc6\xf2\x50\x09\x2c\x9e\x81\x38\x9e\x9c\xfa\x6c\xd0\xb3\x1b\xb4\x81\x9d\x40\x58\x52\x70\xf8\xf6\xb3\x60\xe2\x1b\xeb\xb5\x88\xf8\xd8\x7e\x8b\x9b\x8c\xb0\xad\x07\x8f\xca\xe1\x11\x0c\x51\x43\xf2\x21\x90\xac\x69\x3e\xb6\x3f\xd2\xa6\x47\xcf\xeb\x4b\x26\x08\x44\x2c\x75\xb3\xfb\x37\x85\x72\x32\x85\x95\x55\xff\xcc\x4d\x99\x02\xc4\x52\x7e\xa2\x5b\x4f\xab\x3b\x90\xf6\xee\x3e\xe2\x9c\xfa\x24\x49\xd3\xd6\x23\x58\xfe\xe1\xe0\x65\x1f\xf8\xe2\xa7\x13\x56\x69\x3f\x45\x93\x4c\xea\x28\x3e\xdf\xf5\x4b\x2c\x3e\xa3\xe0\xb1\xe1\xa6\x9b\x96\x2b\x5a\x1a\xf8\xa3\xdd\xdd\xd3\x69\x7a\x83\x55\x1c\xb9\x8d\xee\x65\x9d\x64\x2d\x45\x07\xb0\x2d\xe4\x06\x5b\xc2\xcf\x47\xcb\xeb\xf1\x43\x9a\x23\xf0\x5e\x3e\x38\x48\x44\x18\xa1\xb1\x4c\xd8\xb4\x7f\x36\x5c\x75\x95\x3e\x79\xad\xa4\x48\x42\x58\x49\x62\x5e\xed\x7b\x42\xa3\x4a\x2a\x59\x21\xbc\xd1\x57\xb7\x32\x4f\x68\x2d\x32\xba\xbe\x28\xb1\x04\x63\x28\x09\x50\x0d\x0b\x5a\xc0\x87\xc2\x61\x0b\x7e\x35\xda\x4d\x85\xbb\xd2\x3a\x37\xfc\x54\x0e\xd8\xb3\x60\x46\xc7\x56\xff\xd9\xd2\x82\xc2\x4b\xc4\x14\x6f\xa3\x97\x2c\x13\x4b\x87\x8f\x2e\xe5\x6f\xac\x5c\x9c\x57\xcc\x58\x72\xbc\x5b\x31\x37\xe1\xab\x02\xb2\x4a\x94\x37\xd5\x9d\x6e\x05\x6b\x0a\x5d\xd1\x9a\xae\x48\xa4\xba\xc8\x29\x84\xb1\x39\xc1\x3e\x8c\x82\xf7\x88\xd2\x84\x0e\xf8\x98\x35\xc3\xf4\x2a\x8c\xb1\x3c\x8d\xe3\x41\x63\x6d\x29\x42\xb1\x3e\xb7\xb4\x66\xb4\x12\xfc\x28\x7c\x96\xa6\x47\x40\xaf\x83\xcf\xe8\xd0\x68\xa1\xd6\x64\x09\xb6\xde\x82\xec\x0d\x3f\x46\x2c\xe1\x52\x74\x9a\x2e\x7b\xf3\xb9\x52\xee\xbf\x8b\x3f\x79\xe4\x75\xb1\xc8\x7f\x77\x09\x2f\x23\xd7\x7f\x92\xd0\xc8\x15\x00\xd2\x4f\xcd\x01\xf4\xc6\xa2\x1e\x74\x6b\x72\x50\xe5\x94\xd9\xa8\x8f\xfd\xfc\xe2\x84\xad\x71\x0a\x71\xa9\xe8\xd4\xf6\xc2\x2f\x05\x48\x1f\xeb\x4f\x39\x5a\x7c\x2d\xc3\x49\x5e\x48\x8b\xa4\x2b\xc1\x12\x6e\xf7\x4b\xfa\xda\x05\x7d\xca\x71\x7d\x09\xbf\x11\xa0\xc3\xfe\x5e\x30\xef\x13\x1d\xfe\xb1\x0f\xfe\xe8\x7b\xfd\x17\xdb\xa5\x3f\xdb\x44\x45\xca\xd6\xdb\x11\xed\x3f\x59\xbb\xff\xa5\xff\xb9\x78\xe6\x0f\x60\xe8\x97\x03\xdf\xa0\x83\xdf\x43\x2d\xaf\xa4\x80\x2d\x9b\x78\xfa\xec\x22\x69\x4d\x1f\x56\x0a\x53\xe5\x7e\x77\x72\x79\xab\x63\xa8\x55\x1b\x2a\x4a\x4f\xeb\x3f\xd2\x53\x35\x0f\x27\x31\x67\xed\xe8\x74\xe9\xa9\xbc\xc2\xfb\xaa\x54\xa6\x78\x91\xe7\x62\x87\xe6\x8a\x45\x09\x01\x54\xa9\xee\xf9\xca\xb1\x90\x13\xcf\x03\x0b\x98\x02\xba\xf1\x9f\x81\xcc\x44\x7d\xef\x18\x44\x4d\x3f\xa3\x9a\x88\x60\x8a\xa0\x44\x68\x09\x1c\xa7\x86\xec\x29\x60\xe5\x73\x0b\xcf\x28\xec\x84\x77\xd2\xcc\xa7\xac\xa0\x31\xf7\xb6\x6c\xc0\xe2\x84\x75\x43\xd3\x20\x2c\xbf\x22\xce\xeb\x9b\x57\xb4\x53\x7d\xfc\x69\xf7\x9f\x04\x6e\xe0\x6c\x1e\x96\xe6\x2d\x79\xdb\xe6\xba\x5f\x5e\xb6\xbe\xf6\xb4\xaf\x11\xbc\xbd\x0b\xe9\x6e\x9d\x5f\x76\xad\x5b\x5a\xf7\x86\x7a\x98\xff\xe5\x6f\xa8\x1c\xd8\xa5\xd9\xfe\xb5\x9f\xb2\x53\x8b\x37\x9d\x92\x9c\xc3\xd6\xb0\xf9\xb2\xf5\xa7\x53\x76\x38\xf0\x6e\xe5\x36\x8d\x60\x78\x91\xfd\x19\xaa\xcc\xb1\xc5\x63\xc0\x7f\x85\x2e\x0c\x36\x0a\x5c\x5c\x56\xc9\x63\x61\xa3\x75\x5c\xab\x5c\xd8\xe7\xd6\x20\x06\x8a\x2d\x94\xda\xe9\x9b\x44\xae\x45\x70\x18\xb3\xd0\xef\xc4\x4c\xb3\xa4\x5e\xc5\x68\x1b\x24\x32\x96\xa1\x96\xfd\xd9\x82\x45\x84\x99\xc7\x08\x91\xd1\xc9\xcb\xe9\xe9\xb1\x88\x7a\x0e\xfe\xf0\x55\xcb\x6d\xc2\x82\x76\xfb\xb4\x8d\x2d\xe9\x98\x20\xaf\x2a\xc8\x3b\x63\x3f\x5d\x7d\x3f\xfd\x84\x98\x42\x5e\xeb\xe5\x2d\xef\xf3\xc2\x26\xd5\x73\xcd\x55\x86\x40\x36\xf4\x1e\x87\x1d\xc5\x66\x86\xad\x3a\x62\xb1\xe4\x21\x76\xb9\xd2\x82\xbe\xea\x5c\x18\x7c\x08\x44\x4f\xcc\x4f\x00\xc5\xbc\xdf\x83\x21\xfd\x69\xf1\x25\x3d\xa1\x59\xf3\xd7\xcf\xf2\x2e\x00\xce\xae\x92\xc7\x86\x07\x1f\xbd\xca\x44\xfb\x19\x3e\x04\xcf\x84\x20\x0b\xff\x57\xc9\xbe\x7c\x8a\x86\x6d\xed\x23\xc2\x7e\x5d\x6d\x46\x82\x72\x25\x86\x6e\xb9\xae\xe1\xd6\xba\xd5\xcc\xbf\xf7\x5b\xc1\xca\x20\xe3\x74\xd2\x54\x93\x15\x9b\x9e\x07\x17\x15\xfb\x4d\x83\x84\x16\xb9\xfb\x07\x82\x67\xda\x31\x76\x8c\x62\x7c\xd6\x38\xfb\x07\xac\x05\xba\xcd\x6a\xec\x90\x02\xd3\x80\x65\x10\xda\x7d\xe6\x50\xa6\x0f\xe5\xe3\xdf\xc3\x50\xc4\x1b\x80\x8e\x24\xcc\xdd\x3d\xb8\x6f\xd0\xe3\xba\x8f\xff\x04\x48\xe8\xe0\x91\xf6\x69\xc3\x3c\x04\xee\x7e\x41\x2f\x18\x63\x65\x54\x0c\x8a\xf8\x01\x5c\x76\x11\x80\xf7\xda\xd3\x47\xb0\x94\x23\xc9\xb5\x23\xb8\x2e\x04\x06\x8c\x99\x4c\xb6\x2a\x36\x73\x04\xe6\x77\x41\x57\x03\xbb\x41\xfd\x67\x14\x00\x7f\xcd\xbd\x1f\xcf\x67\xd8\xb9\xdb\xaa\x10\x23\xa2\xda\xd1\xc2\xec\x61\x7e\xdc\x38\xac\xc9\x69\xef\x3d\x4a\x2d\x12\x58\x93\xe8\xe7\xfd\x49\x3d\x6c\x8f\xa2\x4a\x47\xb5\x51\xfb\x02\x17\x77\x76\x9c\x7a\x30\xb2\x03\x9f\x47\x83\x97\xa3\x33\xcc\xd4\x6d\xab\x18\x98\xbd\xa0\xf8\x12\xf4\xb2\xbe\xa8\xf4\xe9\xad\x26\xd8\x63\xc4\x7f\x1e\xc2\xe0\x07\xb1\xfb\xe0\xa8\xae\x2a\xf0\xfa\xf9\xa9\x26\x94\xd5\xf7\x2e\x46\x21\x34\xef\xd8\x9e\xe4\xc4\x13\xbb\x4a\xb0\x03\xd9\x35\x13\xd9\xba\xfe\x4a\xdc\xa7\xf4\xb0\x02\x88\x91\xf6\x5c\x18\xad\x54\x4c\x03\x6e\x52\x70\x3a\x30\xcc\xef\x43\xf4\xd9\xb0\x90\xbf\x63\x87\xdf\xdb\x8a\xdd\xb1\x79\xdd\x47\x66\x81\xc7\xc9\x3d\x44\xa9\xa5\xf4\xf8\x88\xf0\xf5\x5d\xaf\xb5\x85\x2f\x9d\x0b\x16\x25\x54\x8e\x14\xb0\xee\xb3\x5e\x5e\x6b\xb8\x8d\x1b\x3d\xdb\xae\xf8\x9a\x81\xe1\xff\x78\xb5\x63\x73\x4b\xb7\x71\xdc\x5a\xf6\xd2\x8b\xff\x59\xf7\x9f\xeb\x5b\xbb\xbf\x6d\xf6\xbb\xba\xa9\xe0\xed\x2a\x75\x5c\x9d\x2d\xb0\x8b\xb0\x7c\x88\x9c\x45\xa7\xb5\xcb\xa0\x01\xf4\x14\x42\x38\xe7\x89\xe8\xbf\x4d\x71\xca\x40\x07\x46\x16\x36\x6f\x70\xa3\xe7\x72\xe1\x38\x7c\x0b\x7f\x03\xc5\x96\xe0\x74\x07\x1d\xb6\x02\xdd\xdf\x43\x91\xfb\xbc\xf2\x4c\x3b\x3b\x9b\x08\xde\x2b\xc0\x6e\x47\xae\x1f\xa1\xfd\x95\x22\xc1\x6e\x8d\x8c\x4b\x90\x6a\x25\x70\x66\x05\xd4\x45\xdd\xdd\x85\xd9\x57\x37\x7b\xdd\xef\x74\x55\xa7\x59\xeb\x99\x39\xb6\x16\x9d\x13\xea\x04\xf3\x07\x85\xaa\x63\xd1\xe6\x78\xbe\x48\xb6\xe3\x15\xcf\xdc\xa9\xa1\xeb\x10\xb7\xee\xc7\xe1\x2a\x91\xfb\x1e\x6a\x64\x38\xe1\x92\x59\xeb\xaf\x4e\xe9\xb5\x1c\xc6\x90\x26\xb9\xa9\x6b\x03\x09\x41\xd6\xa0\x59\xb6\x74\x80\x09\x82\x97\xab\x2e\x81\x0b\x99\xf4\xec\x67\x29\xa4\xe1\xc2\x5c\x8a\x2f\xb3\x22\x8e\xc2\x4f\xa7\xf4\xed\x89\xae\x3b\x45\xcc\x61\xfc\xea\xf8\xa3\x8f\x14\xd3\x9e\x18\xcc\x60\xdf\x8b\x48\xb6\x75\xf0\x29\xde\xdf\x6d\xc4\xe0\x01\x52\xa2\xed\x9c\x03\x2f\x99\xc3\x49\x9b\x89\x74\xc9\x92\x11\x7d\x88\x2f\xa9\xbd\x7b\xa1\xb3\x9d\x0c\x30\xec\xbc\x93\xff\x1d\xfe\x6d\xf2\xf3\x15\x06\xd3\x77\x92\xb6\x7a\xbb\xf8\x23\x61\xdf\xc1\xb3\x3c\xad\x4c\x78\xfa\x17\x65\x4f\xa0\x7d\xf0\x7f\xae\x3d\xf7\xac\x7e\xc9\x90\x08\x9f\xa6\x55\x2d\xe5\x34\x56\xda\xec\x8f\xa8\x32\xfc\xad\x01\x18\xf4\xc7\x0f\x65\x3d\x26\x7d\x84\x5e\xcc\xe1\x7a\xaa\x7d\x21\xba\xf0\x3b\x0a\xa5\x2f\xa1\xc3\x6f\xe6\x56\xfe\xd3\xa9\x53\xf7\xf1\xb6\x8d\x7f\x39\x30\x7d\x16\xe4\x8c\xa1\x4b\x62\x6d\xfc\xae\x04\x0e\x7f\xf6\x61\xef\x12\x61\x29\xef\x52\x84\xe5\xbd\xcb\x3e\x7a\x35\xf2\x0e\x35\x35\x53\xb9\xc8\xff\xbd\xbf\x0b\xbb\x19\xf7\xa4\x0e\xc7\x95\x6d\x4a\x79\xa9\x8d\xd1\x52\xfd\xec\x2b\x69\xbe\x7b\x34\xe9\x56\xe3\xc2\xca\x0d\xf0\x2e\x7c\xb8\xea\x1f\x45\x34\xeb\x5b\x6e\x66\xef\x39\xe6\x82\xb7\x17\x1d\xa4\x81\x79\x6e\xe0\x8f\xd8\x9c\x2f\xba\x29\xbf\x5b\xb3\xc5\xe5\xe0\xd4\x87\xc7\xa2\xfe\xce\x33\xfd\x3d\xd1\x21\x61\x27\x05\xb3\xb1\x97\xd4\xef\x74\x9f\x04\xc7\xde\x49\x3f\xb5\xfd\x30\x11\x4d\x90\xe6\xfd\x67\xe4\x37\x35\xeb\x97\x37\x18\x47\x98\x3e\x5f\xa7\x83\x30\xaf\x02\x00\xf1\xe1\x19\xff\x92\x91\xbf\x98\x14\xd8\xe2\xb5\x9c\x1e\x7f\xf5\xba\x75\x85\x01\x6b\x8f\xce\x4a\xdc\x87\xac\x5c\xfa\xfd\xa5\x35\xa2\xc8\x5e\x20\xf4\x49\x70\xbe\x47\xc3\xe5\x67\xf2\x17\xf7\x25\x7b\x8f\x47\xb4\x54\x40\xcf\xf1\xcf\x88\xf6\x4a\xfd\xfc\x43\x46\x3e\x8a\x3a\x36\x76\xcd\xd9\xd7\xe5\xaa\x77\xa0\x03\x5f\x32\x04\xaa\x0a\xc0\xbb\x9e\x7b\x34\xd9\x6e\x16\x80\xf7\xd9\x18\xff\xf6\x86\x36\x96\x7c\x08\x6f\x64\x3a\x81\xb7\xba\xc4\x0e\xf6\x73\xc5\x15\xe4\x0f\x8f\x34\xec\x25\x38\xcf\xe1\xdd\x97\xf7\xa4\xd4\x84\xfb\xa7\x69\xb7\xa9\x43\xcd\x94\x34\x8b\x1a\xdc\x11\xf0\x8f\x7e\xc2\x3b\xf9\xcf\x7c\xd5\x0f\x31\x19\x34\x51\x98\x05\x50\x83\x08\x6c\xfb\x3d\x7a\xde\xdd\x55\x84\xd6\xdb\xa6\x8c\x20\xa1\x7a\x1a\xe2\xe3\xff\x45\x02\xa2\x8f\x4a\x19\xd4\x09\xb8\x4b\x58\x66\x7b\x6f\xe4\xad\xc5\x1c\x6e\xb6\x4b\x74\x45\xd0\xe2\x6b\xd1\x89\xd9\x36\x9f\x0c\xfe\xbf\x73\x6e\xaf\x02\x1f\x0f\xa9\xdf\xed\xcc\x91\x91\xa8\x07\x22\x06\xe5\x77\xe6\x91\x02\xd2\xab\xb8\xe3\x20\x57\x1f\x9b\xa0\x6f\xa6\xce\xd8\xc8\xc1\x98\xab\x50\xf3\x79\x15\x09\x1f\x6d\x30\x4b\xc0\x68\x43\x55\xcd\x17\x53\xd1\x31\x5a\x55\x5f\x5f\x2b\x52\x8d\xa3\x8b\x62\x55\xa4\xfa\x19\x8b\x6d\x6b\x14\xaa\x38\x53\x93\x75\xfd\xfa\x23\x54\x03\xf8\xeb\x4c\x67\x51\x03\xa4\xa8\x27\x32\x13\x49\xf3\xd0\x44\xde\xe3\xea\x48\xf5\x4e\xa0\x0b\x61\x8f\x25\xe7\x18\xa1\x89\x10\x5d\x94\x68\x6c\xd8\x26\x26\xf9\xba\x64\x7b\xd9\xa7\xa2\x08\x6c\x28\x82\xed\xe5\x84\x10\x3e\x3d\x3b\xc9\xc9\x0e\xbf\x87\x89\x2f\x9c\x83\xeb\x67\x9b\x1b\x09\x9f\xae\xcc\x7d\xe0\x25\x05\xe3\xd5\x83\x07\x4f\x36\x78\x3f\x27\x22\x5a\xe8\xca\xac\xd4\xb8\x79\xe7\xa5\x7d\x3f\x60\x16\xc8\x75\xcf\x3b\x2f\x41\x7d\x9e\xd6\x1f\x95\xb9\x87\x6c\x51\xad\x1a\xef\xd4\x3c\xd8\x4e\x81\xda\x06\x43\x79\xe6\x80\xd5\x3c\x39\x0f\xda\xb6\x4e\x7e\x96\x26\xa6\x39\x7c\xda\x27\x3b\x3f\x32\x02\x3a\xeb\x3d\xb7\x0c\x92\xb3\x16\x3a\xd9\x9f\x55\xb5\xdd\x59\x07\xb1\x64\x4f\xfe\x06\xde\x34\x51\xb5\xc6\x71\x56\x83\x65\x6b\x68\x99\xbb\xe3\xaa\x99\x79\x96\xa9\xbd\xc0\xb4\x86\x55\x22\xe8\xee\x3a\x3e\x5c\xaa\x9f\xf4\x7f\x67\x65\x0c\x9c\x9a\x7c\xcf\x39\x30\x70\xbf\xf6\xfd\x5c\xe6\xff\xc8\xd7\x91\x82\x1b\x1d\xe2\x7f\x3a\x24\x72\x34\x6a\x07\x88\xb0\x38\xb2\x32\xce\xac\x66\xcc\x30\xb8\x5b\xdc\x09\x7a\x68\xf4\x54\xfc\xf9\x29\x90\xc1\xf3\xb7\x7d\x85\xc8\x5a\x1d\x20\x5b\x84\xe3\x93\xa7\x39\x6c\x00\x86\x30\x14\x86\x25\x0d\x8b\x0d\x24\xf1\x3b\x6b\xda\xf6\xa6\xcc\x83\xb0\xb5\x2e\xab\x53\x62\x27\xcb\x2a\xe6\xb5\x5d\xd6\xfc\x1f\x1c\x6b\x70\xf1\xee\xc2\x66\x4c\xf1\x74\x5a\xb6\x1f\x40\xf9\x6d\xa3\xc4\x63\x1f\xd9\x10\x70\x1c\x92\x52\xf9\x50\x7c\xf6\x81\xc6\x5e\x38\xdc\x1c\x45\xd0\x04\xb8\xdc\x9e\x7e\xb9\xfe\x3a\x30\x44\xd7\x0f\xae\xcc\x08\xb5\x14\xed\x7b\xde\x9b\xfc\xf9\xd0\xa4\x7a\xd8\x5e\x82\x1e\x02\xd3\xbc\xea\xc7\x07\x03\xdc\x93\x36\x41\x35\x95\xff\x00\x3b\x08\x87\x36\x06\x87\x78\xc2\x36\xe3\xac\x6a\xaa\x20\xe3\x82\x1d\x99\xc3\x4e\x76\x19\x6d\x00\xcc\xd8\xf8\x50\x0f\xab\xe0\x59\x18\x05\x63\x39\xc9\x6d\x2c\x64\xf8\x16\xc5\xaf\x17\x85\xe8\x95\xc3\xe7\xab\xd2\x4f\x3a\x21\x0a\xfc\xcf\x1c\xd5\xd8\x3f\xda\xda\xef\xa5\x39\x42\xed\x10\x4a\x71\xd3\xba\xcf\x2f\xb5\x4f\xfa\x30\xb1\xda\xf3\x5b\x69\x8e\x3b\x0c\x55\x33\xf9\xd9\x4c\xc9\x4c\xe1\x14\x80\xf6\x00\x5b\x21\x60\xbb\xac\x42\xc9\x91\xa2\x21\xf3\xc2\x72\x06\x1b\xdb\x8a\x81\x70\x4a\xb4\xcf\x1a\x59\x99\x56\x83\xfc\x93\x50\x31\x36\xc8\xbe\x68\x21\xda\xe6\xf3\xcb\x9e\x48\x58\x1c\xa2\x65\x7e\xa8\x3b\x87\xac\x4c\xb6\x47\x82\xa8\x3c\x47\x2e\x65\xbb\x6e\x3c\x43\x93\x0a\x7d\xe9\xca\xb6\xbc\xd6\x31\xba\x22\xb3\x6e\x6a\xde\xa2\x5b\x9e\xd8\x39\x49\x9c\x9a\xb7\x7e\xb7\x95\x5c\xbd\x91\x14\xad\x0e\x00\xd6\x62\x5e\xc3\xa4\x5e\x83\x55\xa9\x66\xe8\x64\x34\x9f\x82\xbe\xbc\xc3\x8a\x80\xf4\x32\x78\x12\x20\xb0\xb4\x7f\x44\x9f\x43\x04\xec\xef\x57\xac\x33\x1b\xf2\xf0\xe1\x37\x93\x44\xc6\xd8\xd2\x1d\x29\x8b\x5b\xba\xc3\x5c\xe0\xbc\x3f\x7c\xfe\x19\xe6\x8f\xe7\xde\xfa\x19\x6b\xcb\xe6\xac\xed\xc3\x42\x8b\xcd\xd6\x86\x7e\xeb\x2d\x4d\x6c\x9e\x3c\x9f\x91\x32\xe2\x25\x98\x0f\x38\xcb\xac\x9f\x9b\xe5\xc7\xfa\x51\xeb\x82\x9b\x34\x26\x78\x66\x79\x69\xac\xd5\xfd\xe1\xfd\x09\xe5\x97\xa6\x69\xc3\xd4\x62\x31\x6e\x71\xbd\x3b\xfa\x16\x14\x6d\x21\xd7\x99\x32\x21\x47\xb5\x3b\xe6\xdb\x7b\x1b\xc2\x07\xe8\x3b\x90\xc3\x8d\x18\x19\x7a\x47\xe6\x5f\x0e\xeb\x9a\x0f\x86\x85\xe6\xed\x9f\xb8\x4e\xa5\x7a\x92\xef\xb4\x2a\xc7\x0d\x56\x6b\x77\x50\xbb\x47\xde\xb2\x0f\x91\xf6\x69\x55\xf7\x29\x75\x06\x0c\xa3\xd8\x7f\x10\xe8\x5f\xd5\x25\xb0\xf3\xea\x4b\xdb\x83\xbc\xd3\xd8\x20\xcb\x44\xc2\x47\x3a\x06\x1b\x3c\x41\x88\xa2\x3c\xce\x9b\x6d\x96\xa5\x5c\x6a\x23\x9c\x7b\xec\x82\x96\x72\xfc\xb0\xf5\xc5\x66\x98\xde\x7d\x3a\xc5\x4d\x5a\x0a\xa3\x0b\x96\xd2\xcb\x56\x61\x4f\xd5\x69\xe7\x9b\xcc\x15\xec\x9b\xd7\xd2\xb6\x00\x84\x54\x0b\x22\x87\x4d\xc2\xfd\xdd\x22\xfc\x7b\x99\xcf\x8b\x0d\x89\x88\xf2\x98\x57\x36\xe0\x96\x19\x69\xd7\x97\x7f\xb6\xdc\xd8\x6b\x4b\xfe\xc7\x83\x72\xe2\xc1\xb9\x59\x4b\xaa\xdf\x35\xa9\x1d\x84\x14\x0a\x35\x0d\x26\xc7\x15\xfe\x0a\x09\x7f\x7f\x73\x00\xf6\x7f\x82\xe5\x61\xa6\x20\x5d\x0f\x5a\x03\xec\xe7\xfc\xa5\xf0\xf7\xfe\xb3\x2a\x0b\x34\x35\x7e\x15\x70\x57\x58\xac\x46\xc3\x90\x15\xa2\xbf\x19\x9e\xb7\xde\x2d\x99\x95\xc0\x8b\x0e\xc1\xb7\xc1\xe4\xb6\x73\x0e\x63\xca\x2c\x3f\x85\x77\x18\x2d\x54\x42\xe1\x45\x26\xf4\x13\x13\xae\xa6\x12\x5c\x50\x77\xae\x92\x13\xe5\x7a\x5f\xfd\xea\x82\xc8\x29\xa8\xa4\x8d\xa3\x2e\x4e\x7b\x9c\xc1\x36\x08\xa6\xfa\x2c\x83\xbe\x09\x41\x48\x20\x35\xfb\x78\x1c\x91\x4e\x26\x16\x8f\x55\x6c\x82\xfc\x7f\x81\x1f\x62\x73\xb9\xc9\xe5\x45\x35\x86\x53\xd3\xc9\x2b\xa7\x08\x91\xcf\x61\x32\x49\x16\x49\x79\x4a\x41\x37\xe6\x88\x03\xe2\xf8\xaf\x55\x28\x3d\x01\xc9\x29\xfd\x96\x15\x99\xa0\xd9\x34\x2f\x0d\x82\x13\xaa\x22\xeb\x24\x9d\x7f\x95\xc7\x21\x74\x12\xde\x02\x08\x07\xcc\x66\x06\xb1\x06\x6f\x76\x6a\xba\xd0\xb1\x1e\xb7\x22\x3c\xec\x57\xe1\x6a\x45\xa6\x7b\x04\x88\xe8\x64\x1d\x6d\xa3\x75\x2a\x40\xc4\xa6\x2d\x5d\xda\xe3\x49\xdd\xc7\x78\x8a\xce\x8c\xff\xbf\xd2\xf4\x01\x84\x77\xfa\x67\x16\xf5\x52\x6c\xf0\xfb\xe1\xc7\x88\xbd\x03\xfc\xef\xbc\x98\x31\xcc\x52\xc6\xb9\x59\xb0\x8d\x40\xfc\x14\x8b\x1a\x1f\x69\xcc\xe1\xb4\x3b\x46\x7c\xca\x98\xa4\x4c\x19\x45\x8c\x97\x42\x6c\x4c\x57\x2f\xae\x3b\xef\xb5\x4f\xe3\x9f\x21\xc9\x3a\x15\x79\xaa\xea\xe3\xd8\x30\xb1\xb3\xe1\x05\x17\x19\xd9\xcf\xca\x1e\x3b\xa8\xf0\xd8\xcc\x3b\x66\x8e\x2d\xb6\xa3\xfb\x27\xaf\xe9\xa7\xe6\x17\xf4\x0a\xf4\xbd\x3e\xb1\x55\xa3\x2b\x84\x7d\xaf\xea\xbc\xdb\xf9\xc5\x68\x55\x59\xa1\x3f\x23\x33\xf2\xe9\x20\xbf\x23\xf3\xab\xfb\x85\xf1\xe3\x3d\x3d\xa0\x55\x0d\x07\x32\xc6\xf9\x3a\x98\x5b\x05\xfb\xaf\x8d\x5e\xaf\x8e\x40\x58\xe6\x3f\xc3\x99\xf3\x95\x65\x09\x51\xd7\x3e\x02\x59\x5b\x0c\x89\x38\xed\x4f\xc4\xe6\xba\xa2\xd3\xff\xe8\xf3\xa6\xee\x47\xf2\xfa\x5b\x94\xb7\xd0\xe7\xe0\x94\xf7\x9b\xb1\xa5\x67\x27\x19\xe5\xb6\x53\xee\xed\xe7\x72\xc2\x19\xb3\x4b\xf8\x39\x40\x20\x12\x1f\x7f\x86\x73\x9a\x23\xe8\xad\x08\xb2\x02\x45\x0f\x1b\x04\x22\x23\xb1\x84\x3f\xf5\x50\x01\x93\xcb\xac\x13\x8e\xe0\x5e\x25\x0c\x60\x40\x25\x0e\xe0\x1d\x40\x1f\xd0\xf2\x4f\x13\xa0\xe3\x94\x36\x44\x59\x03\x1a\xd7\xcd\x9d\xce\x30\x87\xd8\x71\x98\x49\x55\x05\xdb\xfe\x55\x34\x58\x3b\x3a\x1e\xd8\xd8\xbe\x30\x1f\x34\x55\xdb\x90\xaf\x26\xac\xb1\xf1\x94\x28\x4d\xb0\xa9\x4d\x9b\x60\x74\x05\xce\x20\xeb\xc7\x73\x56\x66\x23\x7b\xd4\xab\x18\x63\x43\x0e\xf6\x0b\xae\x58\xc5\xad\x00\xa8\x4a\x8c\x7b\x75\x81\x0e\x5b\x08\x3b\x0f\x70\xfb\xe4\x20\xd1\xd8\xbe\x07\x37\xbc\xb5\xfc\x70\x37\x91\xfe\x72\x75\x33\x47\x59\x0d\x05\x47\xf8\xc5\xc7\x3f\x93\x06\x81\xd1\x97\xa5\x81\x4f\x76\x72\x28\xe9\xd5\xcf\xbf\x5f\x38\x6b\x59\x45\x2b\xef\x6d\xa5\xd0\x6b\x52\x0e\xec\x21\xb0\x0e\xb2\x3b\xe7\xfe\x9f\xf7\x33\x6d\xa4\x6c\x62\x4b\x47\x98\x7c\xf2\x75\x87\x0f\x4e\x94\x16\x00\x99\xf7\x97\x69\x71\xad\x91\xf0\x0a\xd4\x63\xd0\x98\x01\xf4\xbd\x73\x64\x57\xf1\xf0\x85\xfd\x20\x4a\x65\x8e\xf4\x95\x75\xfe\x4f\xc0\xfc\xdc\x93\xbc\xd4\x7d\x02\xe4\xea\xdc\xc7\x89\xa3\x73\x20\x1c\x7f\xf6\x0a\x2f\xea\xaa\x52\x7f\x30\x10\x2e\x9f\xc5\x6f\xeb\x6a\xaf\xc8\xd5\xda\x2f\x42\xe0\x60\x0f\x1a\x8c\xfb\x46\xb3\xaf\x9d\x98\xf2\x44\x90\x80\xb8\x2f\xd0\x4e\x11\x56\xaf\xdb\xa5\x20\xd8\x1a\x5e\x18\x60\xe1\x0b\x69\x2f\xc3\xee\x29\x43\xdd\x99\x7f\x56\x1a\x08\xa2\x26\x8c\xec\x55\x5f\xf3\x15\xdd\x25\x6b\xeb\x68\x66\x08\xe6\xbc\x50\x71\x89\x85\xc0\xa0\x57\x77\xc0\x16\x4e\xc6\xc5\xf2\x97\x74\x8f\x8b\x1c\x98\x3c\xeb\x98\x0e\x19\x2a\x84\xca\xd7\x26\xd8\x05\xe4\xbe\x3f\x02\x83\xdf\xc3\x4e\xc8\x2e\x8d\x3e\x0b\x8c\xea\xa8\xb8\xbc\xd6\xcc\xbf\xec\xe2\xf2\x7f\x85\xfd\x9f\xc2\x67\xf3\x15\x18\x91\x9d\x16\x81\x90\x75\x79\x87\xeb\x0b\x47\x20\x05\xd2\x4e\xd5\x76\x07\x5f\x19\x48\x77\xad\x4c\xee\x5a\x23\x11\x76\x59\x00\xe4\x65\x40\xfa\x11\x0f\x1f\xd3\xbf\x50\xf8\x8b\x86\xa1\xd7\x2e\xa3\x0d\xdb\x3c\xae\x82\xd9\x85\x52\x76\x89\x6c\x63\x40\xec\xe7\x9f\x72\x61\x58\x93\x76\x30\x3f\x91\x17\xa9\xef\x67\xf1\x8d\x8b\x3c\x96\xce\x6f\xf5\x03\x89\xa1\x6a\x3f\x01\xca\x58\xb9\xd7\x4f\x8d\x83\x98\xc4\x26\xc0\xa9\xea\x13\x55\xda\x60\x9d\x10\x68\x78\xe0\xdd\x87\x82\x66\xd7\xa7\x90\x74\xcd\xcb\xb6\x28\xd3\xeb\x94\x5e\xa4\x0e\x6d\xb9\xed\x28\x5d\x88\x12\xe5\x83\x70\xb5\x4a\x80\x4b\x7d\xec\x14\x55\x1b\x7d\x3f\xa3\x2c\x66\xbe\x1f\x5f\x74\xbf\x25\x2c\x42\xbf\xf2\xa2\xfe\x2a\x47\xff\x0b\x76\x22\xf9\x37\xdf\x84\x8e\xe0\x45\x52\xff\xca\x5b\x56\x40\x80\x78\xde\x27\x27\xb2\x32\xde\x9f\x20\xde\x97\xfa\x6f\x42\x0c\x77\x0b\x70\xd0\x68\xc1\xb4\x57\xcb\x85\x59\x7f\x38\xb7\x7b\x13\xbf\xdd\x8b\x3f\x28\x19\xef\xd9\xb6\x6b\x73\x83\xa7\x57\xf9\x33\x39\x8d\x9f\x40\xb1\x0f\xe3\x75\xb3\x80\xf2\x0c\x8e\xb7\x3c\x32\x82\xad\xf9\x0e\xa4\xf7\xdd\x02\xe6\x41\xf3\xc7\x55\xe5\x43\xab\x00\xdd\x90\xfc\xed\x3e\x49\x02\x93\xc2\xf9\x94\x4d\xd0\xb7\xb8\x3a\xef\xe6\x25\x0e\xbc\x3a\xd3\xa4\xfa\x25\x3c\xff\x45\x53\x3d\x41\xcf\x8f\xf0\xc0\x20\xd8\x7c\x6e\xb9\xae\xe2\xe5\x7f\x9b\x0d\x06\xad\xda\xec\xdb\x84\x59\x4f\xb0\xfb\x41\x71\x90\x13\xea\xfe\x6c\xc6\x1b\x76\x4e\xd2\x22\x51\xd0\xf3\x5a\xf2\xc8\xbf\x7a\xf1\x94\x00\x3d\x9f\xa4\x63\xd5\x0f\xda\x54\x8e\x41\xff\x5c\x54\x00\x51\x73\x25\xbc\xdb\xf2\x79\x8b\xa2\x21\x17\x3d\xf0\xfb\x15\x95\x6b\x8b\xc2\x90\xc2\x2a\x75\x8f\x7c\xdb\x13\x27\xb2\x54\x03\x05\x01\x38\xcd\x28\x55\xdb\x13\x67\xfc\xfb\x91\xb1\xab\xee\x74\xa1\xb0\x19\x46\x52\xdc\xd3\xec\xf3\xac\xbd\x24\xda\xed\x62\xfc\x9f\xaa\xac\x00\x6b\xfb\xbd\x1e\x9c\xe0\x03\x5a\xc3\x5c\x88\x63\x95\xb1\x44\xc5\x4f\xa3\xb8\xda\xba\xe9\xa3\x5c\xb4\x09\xbc\x6e\x66\xba\xd9\x89\xf0\xb5\x73\x8c\xc2\x61\x60\xd5\xd7\x3e\x37\x76\x7f\x66\x2e\x84\xfd\x77\x9c\x5a\x5b\xf0\xf5\xcb\x29\x9e\x01\x86\x42\x8c\xa1\x1c\x8a\x0c\x11\xfb\x63\xbc\x06\xae\x09\x58\x81\x08\xa5\xd8\x68\xd3\xbf\x86\x23\x04\x19\x0e\xd0\x4f\x0d\xba\xb7\x5f\xe4\x63\x0f\xe2\xff\x2d\x18\x3c\xed\x11\x59\x03\x84\x2e\x6c\x5b\xd9\xff\xbc\x8e\xd0\x24\x34\xcc\xcb\x46\xb4\xee\x88\x98\x54\x24\xfa\x16\x81\xdb\x35\x2c\xcd\xae\x88\xb9\xe9\xbc\x33\x71\x6d\x14\x92\x03\xbd\xfe\x79\xbd\xda\xbb\x96\x56\xc0\x2d\xb8\x09\x5a\x6f\xad\xf1\x76\x39\xf6\x01\xbf\x0c\x3e\xdc\x7e\x35\x92\x4e\x80\x5c\xf1\x73\x4e\xed\x5d\xd9\x59\x76\xb4\x10\x9c\x73\xf6\x2f\xf5\xc7\xd4\x87\x2a\x57\x78\xb2\xc0\x23\x1b\xa4\x27\x27\xae\x2b\x87\xbf\x46\x5e\xc9\x47\xb0\x32\x49\xed\x25\xac\x0b\xfa\x0f\x39\x49\xf1\x67\x73\x33\x1b\x16\xfd\x0c\x63\xd4\x5b\x3c\xfa\x3e\xbe\xf0\xde\x0d\xb2\x05\x2e\xef\xf3\x2f\x51\x78\xcd\xf5\xda\x7f\x68\xb4\x26\x18\xea\x00\x38\xc8\x9a\x70\x41\xed\x6f\xcc\x7e\xa2\xb7\xf0\x81\xdd\x83\xc4\x7f\xab\x2d\xee\x96\xb0\x67\xe4\xee\x0c\xe4\x63\x5d\x90\xe7\x25\x0d\x44\xd9\xb1\x61\xa8\x50\x82\x6d\x00\x52\xa4\x06\x59\x8a\x04\x7b\x4b\x74\xf5\xf0\x2b\xe0\xac\xd2\x10\x9e\xe0\xbd\x6f\x3e\x10\xec\x8c\xad\x81\x43\xca\xb5\xf9\x91\x20\x42\x56\x2c\xfc\xf2\xbe\xc5\xf3\xaf\x31\xb8\x19\xb4\x0f\xca\x3b\x23\x7e\x0a\x08\x0c\x61\x9d\x77\x96\x33\x2c\x69\xc9\xe2\x43\xd4\x31\x51\x6f\x34\x5a\xf9\xa2\x1d\x77\x60\x11\x32\x7c\x36\x97\x59\xd2\x5c\x4e\xb1\x90\xcf\x9f\x34\xf3\x6c\x64\x46\x0f\xfe\xe1\x20\xd4\x6d\x27\xfd\xad\xf8\x1a\x19\xbe\x03\xee\x40\x92\x5b\x76\x39\x70\x17\x96\xc2\x67\x56\xf7\x04\x97\xab\x5f\x46\x1c\x0f\x9a\x94\xcf\x3c\x3c\x33\xcb\x36\x00\xe1\x44\x47\xcf\xf8\x3f\x29\xfc\x6b\x9b\x46\x07\xd0\xaa\x9f\x41\x36\x70\x7a\xdd\x71\x16\xdf\xd5\xe3\xa8\x73\x9c\xc3\x30\xb9\x1d\x46\xc6\x8b\xda\x25\xfa\xe1\xa2\x73\x20\x8b\xcb\x8f\x21\x47\x3c\x5a\x6a\x0e\x54\x01\x4e\x94\x70\x16\x7d\x99\xcf\x96\x28\x34\x33\xf7\xf4\x80\xd1\x8c\x70\xe9\xff\xc4\xea\x47\x3a\x0b\x07\x32\x86\x07\x67\xec\x52\x22\x32\x4f\xd0\x83\x66\xbb\x04\xaa\x8b\x3b\xd8\x4e\xb2\xc8\xb3\x01\x17\x95\xc3\x23\x4e\xfc\x21\xb9\xfd\xdf\x9f\xab\xf0\x91\x15\xd7\x73\xe4\x2e\x14\x08\x89\x14\xff\x77\xe4\x61\x61\x38\xd3\x0e\xf7\x25\xb1\xf9\xa1\x12\x55\x6e\xd2\x07\x30\x4b\x3e\xeb\xea\x85\x2e\x62\xe8\x42\x05\xfa\xaf\x36\x8b\x93\xbc\xf0\x56\xb8\x75\x64\xde\x06\x6a\x59\xe6\x68\xe1\x97\x69\x73\xa0\xe4\x04\x47\x1a\x93\xc4\x0a\xd1\x06\xb0\xad\x31\x0f\x52\x19\x15\xa8\xe7\x5c\x71\x80\xeb\xdc\x41\xf2\x75\x56\xe9\x6a\x8b\x0e\x4d\x4e\xb8\x4f\x2a\x70\xf8\xb8\x09\x74\xe0\x54\xe6\x37\xbb\x7f\x04\x96\xec\xa4\x83\xef\x25\x20\xd5\x3d\x30\xea\xdd\x56\x2d\xc5\x40\xf3\x02\x86\xf5\xc9\xac\x54\x15\x2b\x83\xd8\x84\xdd\xb3\x56\x4d\x9a\xf6\xca\x24\xc5\x5b\x5e\x04\xd9\xd9\x7e\xdf\x43\xba\xe1\xba\x04\xd1\xcd\xdb\x66\x1c\xd0\x3a\xd5\x06\xb6\xf3\xcd\x36\x79\xf9\xb8\xdc\x04\xba\x43\x35\x6b\x55\x36\x97\x6c\x80\x99\x9d\x40\xdf\x79\xd7\x9e\xce\x15\x07\x6b\x03\xcc\x19\x54\xb6\xcd\x7f\x40\x43\x03\x30\x8f\x7c\x24\x60\xe7\x6b\x28\x0f\xa6\x97\x40\x73\x44\x1e\x3d\x88\xa7\xf3\x61\xf6\x70\xc2\x33\x4e\xb5\xa6\x3a\x61\x8a\xd8\xa2\x2c\x18\xdd\xb6\x5e\x02\xca\xdf\x32\x23\xe9\x8f\x29\x49\xd8\x81\xd4\x25\x78\x75\x73\xe8\x19\x16\x3e\x04\x3a\x44\x44\xdd\x6a\x69\x3e\x70\x9c\x77\xd1\x71\xa1\x2d\xb0\x47\xf2\x7e\x8f\x48\xe5\xcb\x3e\x59\x46\xd2\xfb\x77\x17\x20\xaf\x1d\x26\x00\x77\x31\xa6\xa4\x31\x10\x8c\xaf\x20\x45\x84\x4b\xcf\xf2\x79\x49\xe7\xcf\x1a\x45\xe1\xd9\xd8\xaf\x13\x1f\x57\x52\xd3\x1e\xe6\x9c\xf0\x3c\x39\x53\x66\x22\xf4\xc1\x98\xa4\x9d\x7b\xeb\xf5\x67\xa2\xbb\xd6\x5e\x1a\xa0\xb5\xf4\xb3\xba\xf2\x6b\xe1\xea\x42\x66\x7e\xb8\xf5\x8a\xf8\x3f\xcb\x07\x6c\x9d\x25\xd8\x07\xb2\x44\xe6\x3b\xa6\xcc\x60\xba\xc7\xa4\xb9\x02\x56\x1c\x5a\xf0\xb4\x20\xb2\x15\x4c\x43\x31\xf4\xbf\x04\xcf\xf7\x24\x40\x7d\xfe\x07\x45\x8f\xc2\xc8\x26\xd6\xdc\x55\x71\xee\xbf\x11\xaf\x14\xbc\xe2\x35\x85\x8f\xb0\x4e\x69\x06\x2a\x91\x2d\x8f\x71\x7b\x41\x7c\xd5\x1c\x48\x61\x03\xe8\x29\xc0\xf7\x63\xca\x8d\xd5\xaf\x3b\xb7\x23\x12\x9a\x20\xca\x78\x00\x6d\x77\x13\xea\xa5\xb6\xdc\x69\xdb\xa0\x6d\x51\xcd\x2e\x70\x21\x0f\x28\x9d\x77\x17\xd5\xb1\x0b\x1c\xb4\x79\x94\xab\x4a\x84\x35\x81\xc0\x42\x08\x7d\x0e\x6f\x15\xef\x72\x2f\x3b\xd2\x8f\x7f\x9a\x87\x05\x7d\x42\xbf\x03\x70\x44\x84\x58\xdf\x21\x5c\x5a\xe6\xe6\x32\x0c\x40\xbd\x85\x5c\x87\x9d\x71\x8b\x84\x5d\x66\x2d\xc0\x70\x68\x09\x13\x62\x51\x05\x90\xad\xda\xa2\xac\x27\xde\x92\xce\x20\xe5\xdb\x2e\x2f\x18\xf9\xdb\x41\xc4\x7d\x8b\x34\xec\xc4\x8d\xc1\x22\xed\xc3\x92\xec\xc5\x83\xb5\xaf\x78\xed\xc4\x4f\xfc\xa7\x44\x92\xbf\x1a\xe4\x91\xbf\xf2\xd9\x79\x0c\xe0\xf7\x2f\xd2\xd7\xfe\xb2\xd2\xdb\xe8\x78\x3c\x13\xaf\x77\x8f\x62\x3f\x7f\x6c\x96\xc8\x6c\x96\xfe\x25\x7b\x00\x6e\xb2\x69\x87\x27\x08\x4c\x48\xfd\x06\x08\x3a\x75\x16\xcf\x07\x4f\x19\xf8\x96\x29\x34\x7a\xfa\xfc\x8c\x62\xea\x26\xd6\xc5\x54\x7c\xb1\x98\x6c\xab\x21\x50\x7d\x4f\x93\x5f\x62\xee\x0b\xf3\xc3\xdc\x87\x50\xc1\x60\xdc\xec\x60\x56\x55\xb1\x30\x51\xa6\x23\xcc\x1d\x64\xc8\x69\x8e\x08\xe4\xa9\xe5\xb6\x4d\xe1\x12\x36\xcd\x71\x57\x17\x59\xdb\x2f\xf1\xf3\xf9\x0f\xb3\xdc\x76\x1c\x92\x0f\xbe\xfe\x16\x24\x78\x26\xf2\x5c\xbf\xa1\x1e\x1b\x2c\x4d\x8e\xbc\x37\x60\x1f\x4b\x74\x7e\xed\x87\xa7\x90\x06\xe8\x62\x9a\x52\x15\x65\x3e\x44\x31\x13\xe8\x72\x57\x80\xf1\x77\x1b\x5d\x53\x3b\x47\x01\xd8\x7f\x22\xc2\xea\x94\xa7\xc9\x94\x44\xe1\xdf\x24\x9e\x9e\xd2\x38\xaa\x09\x02\x97\x46\xc9\x61\xa6\x14\xb3\xc4\x94\x06\x7d\x7a\x6c\x64\x17\x2e\xae\x63\x0d\x03\x5e\x8c\x66\xec\x5c\x69\x48\x73\x4f\xad\x95\xe4\x52\xff\xdc\xd8\xfc\x22\xe4\xa3\xb9\x4a\xd0\xbe\x82\xa3\x44\xe2\xbe\x5d\x75\xc4\xef\x73\xeb\xde\x38\x9b\x1f\x47\x06\xf7\x8e\xa5\x85\x68\x8f\x56\x60\x94\xa0\xe1\x17\xa4\xc1\x73\x40\xc6\xdc\x08\xba\x90\xe6\x53\x97\x6d\xf0\x39\xf3\x7a\xa9\x10\xf0\x8c\xf0\x91\xfd\x82\x79\x5d\xf4\x1d\x8e\xb3\xe2\xc9\x67\x24\x25\x73\x8f\x0b\x7b\x67\xf6\x03\x9c\x66\xe0\x6f\x35\x5f\xd1\x0f\x38\x15\xef\x3a\x26\xc1\x6b\x28\x25\x55\x38\x8e\x58\x13\x06\x82\xfe\x6e\xe8\xcc\x07\x62\xfe\xfc\x70\xb4\xce\xea\x19\xfc\x93\xd4\x3a\xda\x05\x4c\xc3\x9b\x33\x12\x44\x9f\x60\xa2\x13\x40\xaf\xea\x49\x3c\x4f\x6f\x75\x3f\x4f\xb5\x19\x40\x00\x8f\xec\x7a\xf8\xe2\xf0\x24\x8e\x80\x98\xe7\x1a\xad\x60\x1b\x69\xf3\xf0\xa4\x3c\xfb\x39\x87\x55\xcd\xb3\x31\xc7\x9e\x12\x2b\x38\xb5\xdf\xbf\x23\x1b\xf6\x22\xf9\xd3\x2f\xa7\x29\xaf\x6d\x11\x90\x67\x74\xfa\xe6\x25\x9c\x73\xe4\x2d\x9d\xe6\x80\xf9\xf3\x9b\xb4\x7c\x4f\x8a\x21\x5c\x7f\x7b\xa9\xed\x80\xfc\xda\xb0\x04\xec\xd1\x9e\x64\xf7\xe7\x8e\xc8\xfd\x70\xf2\xed\xb8\x37\xe9\xc3\xc1\xfa\xdc\x97\xad\xf3\xa1\x0b\x8b\x91\x0f\xe8\x5e\x34\xf6\x2a\xa4\x1d\x0f\xf5\xfa\x41\xc2\x1e\x43\xce\xbd\xb7\x0d\xcb\x11\x3c\xff\xa7\x20\xff\x7d\xd4\x71\x50\xc2\xd7\x2f\xcf\x7e\xa8\x5d\x1c\x23\x6e\x4a\xae\x4b\x03\x0a\x94\x88\x37\x1b\xce\xe8\xcb\x0d\xf8\xc9\x68\xf2\x34\x94\x4b\x36\xeb\x43\x69\x5d\x85\x42\xbd\xd0\x50\x14\xe7\xe0\x44\x5b\x1a\xe2\xfc\x92\x1d\x86\xe2\x3d\x96\xa1\x65\xa9\xc1\xcc\x67\x8f\x51\xb4\x1a\xac\x88\xe1\x13\x63\x87\x3f\x80\xcf\xde\x47\x3b\x61\xd7\x40\x6d\x88\x0c\x49\x81\x77\x2e\x40\x78\x61\x7f\xa0\xa5\x8c\xe5\xdd\x4d\xf9\x87\xfc\xb3\x03\xda\x0a\x9f\xb6\x25\x35\x15\xc6\xb9\x0e\x64\x77\x23\x41\xc1\x0f\x48\xa6\xe0\x3e\x68\xd0\x36\x74\x08\x8b\x6c\xa5\x22\xf6\xf5\x06\x95\x9b\x68\x7e\xbd\x66\x05\xcf\xf5\xf5\x9f\xec\x76\x68\xb4\xd8\x37\xf8\x48\x6b\x50\xaf\xa2\x96\x82\xf2\x3e\xfa\x93\xd6\x4d\x3d\xbe\xe7\xd0\x26\xa4\x83\x1d\x85\x37\x3f\x61\x5f\xea\x41\x8d\x40\x0d\x17\x8c\xbe\xdc\x6c\x2b\xdc\x7b\xa1\x51\x35\x7e\x88\x59\x0e\xda\x87\x3a\x0b\xfb\x05\x76\x17\x5f\xcb\xde\x0a\x5f\x4b\x6a\x69\xec\x66\xce\x78\x31\xca\x16\x6c\xda\x08\xdd\x03\x82\x5b\x7d\x30\xe5\x4b\x9e\x04\x3d\xe7\xd8\x93\xc3\x41\xa0\x5f\x0f\x21\x94\xe0\xeb\xde\x76\x4d\x6b\x34\x1b\xce\x4a\x6a\x24\xc6\xf3\xda\x6e\x0e\x59\x02\x64\x01\x74\xe0\x40\x10\xd9\x18\xb4\x83\x5e\xa9\xda\x2e\x11\xe0\xec\x09\x43\xa0\x70\xd6\x56\x26\x55\x9f\x0e\xf9\xf4\xda\xe8\x8c\x9b\x8e\xf9\xe7\x09\xc4\x6d\x7f\x1f\xa6\xfc\xbd\x1b\x58\xab\xbb\x31\x5b\xa5\x22\x73\x20\x3b\xad\xe4\x19\xb4\x22\x49\x8a\x0f\x98\x41\x45\xf1\x51\x18\xed\xd4\xab\xa7\xcd\x11\xa8\xd0\xd1\xa5\x38\x47\x4d\xb8\xe8\x7e\x38\x06\x6e\x4b\x58\x5a\x99\xfa\x5e\x3d\x9e\x98\x7c\xfe\xb7\x3a\x12\x55\xd4\x7b\x78\x77\x97\xb0\x0f\xda\x18\x68\x56\x42\x46\xa0\xfd\x31\x86\x6c\xec\x33\xe0\x2a\x06\xea\x73\x60\xef\xdb\xf4\x06\x59\xc6\x68\x5d\x63\x62\xb8\x71\x90\x8c\xc2\x13\x13\xd7\xd2\xe7\xd7\xec\x18\x66\xa9\x0b\xa2\x6d\x62\x7b\x26\x75\x3b\x3e\x8e\xae\xa2\xdb\x41\x3b\xa0\x4b\x2c\x28\x74\x3b\xd8\x38\xf1\xd0\x16\xfa\x5d\x17\x84\xc9\xcb\x1d\xb9\x53\x1b\xa7\xb8\x44\x30\x9a\x26\x91\x4e\x8c\x51\x98\x12\x79\x7d\x45\x31\x02\x9d\xb3\xba\xb5\x28\x9a\xa4\x8b\xec\xf9\x55\xf1\x6e\xc8\x63\x8b\x99\xa8\xc3\xee\x4c\x2f\x22\xd3\x8d\xce\x4d\x6b\xf4\xc1\x82\x24\x8b\xb6\x49\xba\xbe\xb1\x46\xba\x27\xb8\x1f\xa3\x4b\x94\x7f\xa4\xba\x0e\x93\x9b\x1f\xcf\xe8\x71\x00\x76\xfe\x63\x2b\x45\xc8\xa6\xdb\x85\x87\x6f\x51\xa4\x29\x76\xe9\x3f\xc4\x56\x49\x93\x70\xc7\xa9\xe0\xdb\x7f\x0e\x26\x29\x4c\xd0\x21\xd9\xba\xd0\x2e\xac\x0d\x5b\x81\x78\x81\x47\xb7\x33\x89\x30\xfd\x49\x1d\x13\x76\x2f\xea\x2d\x61\x41\x1c\xe5\xe6\x1d\x53\xa5\xaf\xbe\xd4\x14\x74\x21\x3a\x06\xd2\xe6\x2d\x0f\xa7\x8a\x3c\x3c\xa5\x8d\x17\x2b\xea\x8a\xe6\x65\xf4\x9a\x07\x6e\x6a\x90\xdc\xa6\x40\x38\x58\x04\x29\x49\xff\x29\x36\x42\xf2\xd8\x3a\xbe\xf0\x12\xad\xbf\xb4\x70\xf3\xe2\xd9\xfa\xfe\x4c\xe2\xc4\xc9\xa6\x00\xb6\x09\xd9\x45\xa1\x6c\x80\xea\xac\xd4\xc9\x4a\x0e\x3b\x73\x1e\xbb\xe2\x1c\x85\xaf\x67\xe4\xe3\x65\xbe\x48\x5f\xe5\x1e\x9f\x81\x70\x0f\x6f\xad\xf8\x72\xf9\x0d\x04\xf5\x9b\xe3\xe1\x1f\xac\x43\xaa\x48\x3e\x85\x22\x0e\x44\xbe\xf9\x91\x94\x6b\x88\x0e\x76\xba\x3b\xbe\x03\xcc\x78\x57\xf7\x2b\xf5\xee\x44\xa4\x93\xd8\x60\x20\xd3\x05\xbd\x97\x87\xf7\x56\xae\x35\xcb\xa3\xfc\x67\x61\xbe\x6e\x5c\xb2\xe1\xa1\x24\xa6\xef\x7b\x0e\xb3\x73\x79\xb6\x41\x29\xf0\x9e\x65\xb5\x14\x3b\x71\xef\xc9\xa8\x11\x32\xcd\x03\x17\x86\xb7\x1b\x48\x8a\x9c\xf8\x8e\xdc\x1a\x5c\xd9\xf2\x15\x87\xff\x22\x82\x5a\x39\xde\x43\x53\x90\xd5\x44\x4a\x9f\x70\x65\x72\xc1\x7f\x9c\xf3\xf0\xd6\xe2\xfd\x6b\xec\x3e\x64\xc7\xd4\x24\x05\x34\x90\x79\xa7\x1c\xf4\xe2\xd7\xfc\x9a\x59\xd6\xbf\x04\xe4\xb4\xd0\x7f\x2a\x02\xd8\x53\x41\xd6\xec\x83\x39\x74\xce\xdb\x78\x81\x6e\x77\x69\x60\x67\x2d\xbb\x2a\x67\xcb\xfc\xf7\x7c\x29\x8d\xcb\xef\x66\x3b\x5d\x68\x6d\xe6\xe3\xa0\x14\xfb\x1f\xdc\xdf\xbd\x64\xad\x85\xa3\xd6\x04\x06\xd6\xd9\xac\xa5\x3f\x92\xaf\x18\xe1\x54\x54\xe5\x4f\x78\x57\x6f\xbd\xdd\x95\xe1\x72\x30\x5d\x5a\x65\x46\xbe\x1d\xec\xcd\x60\x37\xe8\x0f\xb5\xef\x86\xec\xa7\x1b\xab\x27\x5b\x2e\xf0\x5e\x65\x1b\x86\x26\x2b\xf7\x5f\xe2\xbb\xbe\x23\x1a\x2f\x7c\x30\xef\xa9\x9e\x9b\xc2\xea\xe8\xef\x82\xc8\x9b\xca\x46\xec\x6d\xdb\xb2\x53\x36\xe8\x76\xdd\xf8\x07\xb8\x53\x78\x83\xdd\x12\xae\x5e\x9f\x9b\x42\xb6\xeb\x23\xa3\x6f\x88\x52\xe4\x1f\x64\xe7\x4e\x56\x0c\x12\x14\x08\x02\x12\x2f\xdb\xcc\x85\x02\xe4\xaa\xdb\x2e\x18\x3e\x1c\x05\x21\x37\xb8\xee\xe8\xb7\x9c\xc5\x89\x36\xde\x91\x09\x26\xfc\x0d\x1f\x4b\xf6\x69\x10\x85\x24\xe8\x16\x1d\x99\x8d\xc7\x79\x6f\x61\xb3\xfe\x57\x96\x35\x39\x1d\x99\xa2\x6d\x03\xe9\x41\x92\xb2\xe0\x0c\x89\x41\x38\x71\x1f\xf3\xa0\x4e\x0d\x1d\xe6\xae\xf2\x0e\xd4\xe2\x2a\x57\xa3\xb7\x5d\x45\x96\x02\xd0\x20\xb0\x0b\xb3\xca\x31\xd9\x46\x5a\x59\xae\xf2\xc7\xbb\xe0\x14\x1a\x1f\x5c\x51\xda\xd7\x4f\x77\x77\x15\x36\x7a\xaf\x55\x9f\xd9\x36\xb1\x31\x6d\x5f\x00\x21\xd8\x9b\x80\xd0\x87\xb8\xd3\x45\x44\xfb\xf2\xab\x96\x1d\x9d\x3c\x2a\x08\xe0\x9a\xbc\x0d\x7b\x81\x01\xc7\xce\xc3\xb4\xc0\x4f\xd4\x47\x79\x5e\x28\x43\x70\xc2\x78\x34\x72\x64\x8e\x85\x7e\x76\xb4\x8d\xa6\xa4\x47\x66\x71\x44\xd4\xca\x91\x85\x93\xf4\x1a\xe1\x78\x95\xd9\x5a\xc9\x43\x6c\xee\x2f\xab\x05\x28\x6e\xe8\x27\xca\xf7\x30\x88\x4e\x4c\x51\x77\xc6\xd6\xdd\xcc\xd1\x9e\x35\xd8\xc2\xcb\x8d\xb2\x82\xd6\xbb\xd9\x22\x1f\x30\xb3\x63\x44\xa3\x3d\xdb\xa8\xc8\xe2\x2b\x58\xbd\x57\xb2\x5a\xe3\x92\x65\xbb\xbb\x86\xca\xaf\x69\xff\x86\xfd\xd2\x4a\x65\x11\x2c\x99\xe2\x96\x79\xa0\x0a\x61\xe6\x4f\x9b\x26\x35\x64\x5a\x67\x26\x33\xd4\x2f\xf2\xf8\x2a\x01\x9a\xb3\xdc\xd3\x93\x84\x17\x0c\xff\x81\xa0\x60\x41\xf2\x8f\x57\x53\x90\x1d\xbc\x21\x23\xce\x1d\x6c\x9b\xee\xa2\x81\x3c\xd3\xcb\x2a\xc7\x26\x49\x05\x4a\x56\xba\x25\x2e\x80\x49\x36\xea\x85\x7a\x8c\xb3\x74\x55\x4a\x03\xbe\x03\xfb\xac\x2b\xbb\x20\xe4\x2b\xca\xe2\x3d\x43\xe2\x26\x4b\xf6\xd6\x6b\xca\xf0\x0d\xe0\x6d\xbb\x1e\xb6\xc9\xfa\x69\xe3\x65\x72\x46\x5e\x9b\x0d\xbc\x1b\xd5\xb8\xe4\x36\x8a\x57\x99\xa4\xc9\xb0\xdf\x4c\xef\x38\x29\x2c\x0e\x79\xb7\x4e\x79\x80\xb8\xc0\xaf\x52\xfb\x0e\x98\x2c\xf3\xbf\x1a\x2e\x44\x90\xb5\x5e\x6a\xb9\x90\x86\x7f\xda\xaa\x2a\xe5\xe3\xa1\x8b\xfe\xf0\xf6\x94\x3c\x9c\xf6\xdb\xc9\x03\x70\x86\x67\xd3\x03\x5e\x0c\x2f\x45\x05\xda\x67\x49\x4a\x29\x4c\x37\x61\x5f\x4c\xa0\x6c\x58\x94\x61\x29\x6f\x1a\x2a\xc1\x83\x98\x2a\x04\x38\x1a\xec\xd1\xac\xe1\x76\xca\x06\xd8\x47\xc8\xcc\xe9\xbe\x37\x8d\x50\x9e\x8d\xd1\xc4\x61\x8b\x63\x86\x24\x6c\xa7\x58\xa0\xd9\x29\x49\x6b\x80\x8d\x1a\x31\xae\xa3\x69\x4f\x61\x2f\x1f\xdd\x17\xf8\xe9\xf8\xa7\xcb\x6a\xe2\xa2\x27\xa9\x3d\xbb\x0d\xd7\x2d\xf2\x28\xed\xdf\xe6\x23\xeb\xbf\xe4\x17\x5f\x11\x46\xa5\x14\x3e\x64\xcd\xf0\x47\xfa\xfa\xb6\xf2\x48\xec\x4a\xa2\x51\xd3\x22\xfe\x61\x3d\xcf\xc3\xdc\x3a\x36\x4f\x72\xae\x50\x6c\xaa\x7b\x79\xc0\xa3\xac\xe3\x93\x57\x28\xeb\x38\x1c\xd3\x50\xe9\x24\xff\x9f\xb4\x09\xf6\x7d\xc7\xec\x84\x71\xcf\x28\x12\x70\x41\xd4\xb7\xf2\x3c\x45\x3a\xd4\x5f\x6e\xf2\x53\xb0\x79\xc3\xcf\x80\x2d\x36\x57\xfd\x42\xc7\xcc\x42\xf4\x60\xff\x48\xdf\xb9\x23\x7b\xcd\xdb\x2f\x58\xfc\x95\x73\xb1\x17\x85\x82\xec\x60\xe5\x7a\xb3\x25\xab\x26\xd8\x49\x86\xd8\x73\x6d\x62\xc5\xdd\x36\x1e\xab\x9a\x34\x62\xe7\x58\x01\xdd\xcf\x4e\x22\xdf\x69\x6f\x61\x27\x3b\xbf\x1e\xf5\x64\xce\x7f\xbc\xa1\xce\x63\xf2\x2e\x25\xbc\x05\xe4\x21\xb5\xdf\x21\xbd\xc0\xb8\x3e\xe9\x17\x14\x9e\xf5\x57\xfc\x71\x9e\xb4\xf4\x81\x20\x82\xa7\xc3\x66\x0b\xc0\x29\x6d\x85\x5d\xed\xbc\x17\xf6\x16\x6a\x46\xcc\x91\xbc\x09\xaf\x5a\x12\x26\xe0\xc4\x40\x26\x3f\x69\x3e\xdb\x3c\x7c\xb8\x97\x43\x53\x87\x56\x44\xb9\x46\x12\xe3\x75\x25\xdd\xb4\x7f\x69\xba\x44\xea\x29\x0c\x19\xe6\xc8\x40\xcc\x9a\xe9\xdc\x54\xea\x92\xd9\xbd\x9a\x55\x9a\xc2\xa1\xa3\x60\x33\x2a\x43\xab\xe5\x83\x14\x42\x88\x37\xe3\xde\x1e\x6a\x06\xa9\x47\xe3\x7d\xd5\x14\xfd\x20\x3c\xe4\x60\x6f\xe7\xf8\x65\xa6\x41\x83\xa1\x4e\xf8\xd6\x6f\xa9\xb9\xe1\xbb\x19\xbe\xc6\x88\x02\x64\x57\x67\xb1\x39\x26\x5c\xa4\x10\xe1\x43\xcd\x85\x9b\x5a\xbf\xce\xc4\xc7\x00\xb4\xd3\x80\x09\x6f\xe8\x1a\xd5\x55\x83\x41\xaf\x99\x5b\x88\x64\x95\x35\x2b\x44\x1c\xbb\x7a\x41\xde\x53\x8a\x07\xc4\x93\x3d\xfb\xaa\x75\x97\xc2\x1d\x66\x4b\x5f\x1d\x3f\xa1\xb8\xf8\xe8\x2d\x7a\x3a\xff\xdc\x46\x3e\xb0\x2b\xe9\x3f\x0d\xf2\x9b\x5d\x29\x5b\xd4\xb5\x65\x88\x40\x61\xb4\xa7\x66\x3e\x3e\x9c\xc0\x12\xba\x82\x72\xad\x3a\xa3\x75\x15\xdb\x03\x0c\x65\x5a\x85\x49\xfe\x8c\x7e\xd6\xbc\xeb\xe5\x1c\x10\xa4\xcc\x44\xed\x89\x2d\xfd\xe5\xcc\x00\x80\x49\xbe\x61\x36\x21\x77\xfa\xaf\x23\xb5\x37\x89\x4e\x28\x3e\x1c\xb2\x22\x01\x40\xa6\xf0\x56\xd1\x27\x2c\xd8\xd7\xaa\xa0\xca\xea\x9a\x63\x6f\x69\xd5\xac\x6c\x04\xb4\xc5\xd8\x78\x62\x02\xbf\xb7\xa8\xca\xdb\x9b\x42\x85\xf6\x51\x36\x75\xaa\x0f\x15\xd6\x84\x68\x84\x59\x7d\xcc\xdb\xc6\xe9\xee\x93\x47\x07\x58\xb5\x7b\xb3\xfd\xb9\x06\x40\xb6\xe6\x12\xdd\xcf\x96\x06\x6a\x83\x91\xa6\x1e\x6b\x5b\x93\x7c\xab\xc0\xae\xd8\xaf\xc5\xd5\x45\xa5\x09\xd1\x64\x95\x37\x55\x0d\x31\x09\x6c\x7c\x9a\x39\xd5\x2f\xd4\x13\x7c\x4a\x1e\xa9\xa7\xc0\x72\x50\x83\x66\xb0\x26\xe7\x17\x6b\x44\xb8\x7d\x75\x7b\xc8\x9b\x4f\x92\x27\xd6\xb3\x8a\xc7\x68\xc3\xdc\xe2\xb6\xd6\xd4\x17\xde\xbc\x7c\xd4\xa9\xaa\x07\xf3\x60\x97\xba\x7f\x23\xbf\x33\x4f\xb4\x9f\x52\x8e\x01\xc2\x3a\xdd\xfc\xea\x94\x19\xd4\xd9\xec\x2a\x97\x33\xbd\xf5\xfc\x33\x31\xbf\xca\x06\xf7\x42\xfd\xc9\x7d\xcb\x30\x78\x29\x8e\xc3\x2e\xc5\x67\x83\xa5\x44\x43\x0e\x01\xcb\xd2\xb7\x64\xed\x6c\xd8\x4a\x63\x13\x0d\xa5\x73\x14\x8f\xcb\x1f\x83\x36\xdb\xe3\xc0\xeb\x56\x1f\x8c\xff\xc3\x66\x8b\x32\xd1\x6a\x4a\x89\x09\xa1\x6a\x5a\x12\x3b\x50\x4b\xda\xce\x16\x49\x6a\xe7\x9e\x4b\x43\xfe\xca\x64\x13\x28\x5e\xe9\x6f\x5e\xd5\x9e\x92\xe7\x31\x66\x4e\xe9\x4a\xe4\xce\xca\x04\xcf\x4d\x41\x06\x91\x6c\xd0\x17\x4f\xbd\x9d\xa1\x53\xf3\x6f\x17\xdc\x94\x70\xe6\x9f\xed\x67\xe2\x0a\x09\x5b\x3b\x62\xad\x53\xfd\x70\xfa\x9c\xe0\x9e\x2d\xa3\x29\x02\x1a\x90\xa2\x94\xb0\x9e\x8a\xec\xcf\x8f\x7c\x97\xca\x19\xca\x94\xd2\x1a\x07\xa0\x23\xb5\x74\xcd\x72\xce\xf2\x0b\x98\xca\x11\x39\xdf\xce\x53\xd2\x40\x5c\x5b\x6c\x7c\x5b\xcf\xa9\x88\x6c\x3c\xd9\xf4\x39\xfd\xda\x5d\xd1\x03\x5b\x7d\x56\x86\x04\x05\x41\x3a\xa2\x01\xc1\x9e\xea\xe1\x4a\x14\x36\x8c\x64\xd1\xc3\x61\x68\x52\x00\xd8\xb0\x57\x66\xeb\xb5\xa2\x0e\x64\x18\xc4\x3c\xd1\x25\xac\xab\xd8\x21\xd3\x98\xa5\xe8\xe4\xa2\xa4\xd0\x2f\xa3\x73\x16\x6e\xdd\x68\x88\xa9\x89\x16\x6e\xcb\x53\x8e\x46\x86\xdb\x59\xb1\x05\xf6\x55\x73\xeb\x03\xe3\x04\x86\x35\x58\x69\x16\x91\xa4\xe8\x8a\x65\x8d\x28\x84\x81\x0b\x86\x5a\x5d\x67\xf8\xd9\x80\x6f\x36\xab\x47\x36\xd8\x94\xfc\xd1\x50\x8e\x58\x2d\x4d\xd6\x87\x8c\x47\xa5\x89\x93\x2c\xaf\xc4\x6a\x43\x96\x69\x68\x63\xd6\x2b\xde\xe0\x2f\x9c\xcd\xdb\x6c\x0f\x76\xd1\x28\x7d\x09\xd3\x29\x68\x3c\x16\x45\x3c\x9c\xbc\x45\x40\x07\xfc\xb0\x94\xd1\x00\x33\x15\x45\x9c\x16\xce\xe7\x9e\x70\x2a\x60\xc0\xc6\x1d\x0f\x91\x2d\x7a\x4a\x93\x72\xa6\x3f\xe1\xc4\xa3\x4d\x31\x91\xe8\x70\xd3\x26\x2b\x12\x67\x50\x45\xdb\x66\xee\x66\x4f\x7f\x2c\x83\x7a\x61\xab\x9d\x6c\xdc\x4f\xd8\xd0\x0b\x2a\x48\x1b\xd5\xe7\x1f\x95\x70\x3b\xce\x27\x21\xf6\x71\x6e\x4c\x65\xd8\x64\x85\x36\xa6\xb6\xe6\x98\x6e\x40\x47\x84\x3a\x19\x59\xb4\x61\x89\x88\x8e\x1c\x41\x0b\x2b\x78\x5a\xb3\xcb\xbb\xec\x60\x2d\xb3\x77\x75\xba\x8c\x41\x72\x17\x14\x5c\x33\x87\x23\xb1\xc6\x67\xc4\x6b\xa2\xf7\x30\xf3\x28\x42\xc8\xb3\xf0\x3c\xb7\x23\x70\x54\x1a\x50\x15\x7e\xd4\xe7\xea\xe7\xfc\x53\x88\x16\x2c\xb4\x6e\x76\xb4\x6c\xea\xf5\x7b\xb8\xcd\x71\x97\xac\x9d\x83\x9e\x45\x30\x45\x32\xda\x05\x3f\xc3\xca\xed\x99\x2b\x17\x8b\x67\xa4\x08\x3e\x33\x12\x23\xbd\x8a\x78\xe6\x34\x4a\x30\x93\x42\x15\x53\xe1\xef\x1a\xa5\xad\x6d\xfe\x5a\xb0\xc9\x33\xc2\x25\x9f\xda\x2b\xd9\xae\xfa\x25\xa1\x8c\x44\x6f\x4f\x59\x91\x64\xed\x9e\x7d\x65\xa3\xf3\x95\xdc\x76\xe0\x4d\xe8\xc7\x43\x18\x5b\x06\xb9\x96\x83\xe9\x64\x15\x65\x4b\x5e\x24\x56\xa8\xb7\x93\xff\x8d\x47\x70\x1b\x73\x5d\xc2\xb9\xc1\x76\x0a\x81\xc9\x83\x08\x66\x43\x3d\x63\xa0\xc6\x3a\xe5\x34\x3e\xd8\x56\x2f\xf3\x87\xaa\xa9\x62\x08\x4f\xd0\xa1\x86\x1b\xe6\xa0\x36\xf5\x50\xaa\x42\x2d\xce\xc0\x6b\xd1\x30\x9b\x0a\x1b\x66\x5b\x6c\xf1\x07\xba\x11\xfb\x48\xed\xe4\x61\x3e\xd0\xa2\xf0\xf6\x96\x95\x70\x6c\x94\x65\x66\x4e\xcc\x60\x7a\xb6\xf6\xd8\x51\xa4\x87\xb9\x40\xd3\xe5\xf2\x0b\x08\x8d\xb1\x16\x39\xfa\xc0\x68\x85\x85\xe6\xe6\x9c\x23\x3c\x76\x2d\xee\xcf\xc5\x3b\x18\x37\xcc\x8e\x9a\xad\x68\x61\xaa\x44\x7b\xae\x5e\x96\xe3\xf6\xd7\x0f\xfc\x1f\x32\x1d\xcb\xe1\xdb\xb5\x2b\x9c\x36\xb1\x69\x69\xf3\x1b\x8f\xe7\xc8\x6f\x87\x3b\x02\xbe\x7c\x62\xc6\xc0\xa0\x68\x12\x25\x99\xf7\x27\x59\x45\x1e\x2a\xab\x2e\x99\xfd\x46\xb2\x8f\x3a\x15\x03\xde\x23\x51\x58\x1d\x33\x25\xd4\xda\xd7\x2b\x1d\x0e\xf8\xc3\x6c\xb5\x15\x39\xb6\xb9\xe7\x16\x3b\x46\x85\xe2\x99\x12\x41\xc0\x9e\x8c\x41\xf1\xba\x0d\xc3\x7b\xeb\x64\x9b\x2c\xfe\x09\x4e\x9e\xa4\x76\xd9\x76\x90\xb1\x64\xc3\x4c\xcb\xb0\xb9\xaa\xeb\x05\xa2\xb0\xbf\x77\x6f\xbd\x3f\x42\xd8\xc3\xb7\x30\x95\xc4\xe6\xda\xec\x34\x45\x34\x47\xe4\x2b\x36\xa5\x17\x7b\x41\x7d\xba\xd5\xcd\xba\xd3\xfa\x8c\x4c\x8c\xeb\xd7\x64\xee\x9d\xf8\xad\x2b\xb4\xf7\x70\x51\x35\xce\xec\x97\x4e\xea\x9c\xad\x52\xfc\xc0\x41\x34\xee\xd7\x46\xc4\xb6\xea\x6a\x82\x85\x1d\x57\x18\x8f\x81\xe5\x42\x0a\x5a\xf7\x61\xd4\xeb\x87\x8d\x9a\x7a\xb7\x3e\x18\x55\x30\xf0\x38\xd8\xd5\x94\xf3\x00\x06\x79\x6e\xb5\xce\x89\xcd\xbd\x6c\x77\x54\x36\x55\x6a\x84\xab\xd9\xa8\xf0\x59\x72\x22\xed\xe8\x98\x16\x4d\xb3\x68\x6e\xd5\xfc\xff\x8b\xbc\xf5\x3f\xe6\x3b\xfa\x64\x8a\x99\xb0\x3d\x69\x4b\xc8\x98\xe1\x55\xe2\x50\x0f\xfa\x64\x6b\xeb\x8e\x45\x2f\x2c\xfa\xd8\x36\xd4\x01\xe8\x6a\xf0\x81\xba\xf2\x65\xcf\xab\xc4\xcc\xd6\x45\x08\x75\x67\x13\x6a\x24\xcc\xfe\x10\x10\xc8\x7d\x66\x1e\xc3\x55\xeb\x97\x75\xdf\x49\xaf\x0f\xa7\x2d\x7a\x89\xb5\x4e\x1a\xfe\xa1\x37\xb4\x3c\xf8\x42\x1d\xa9\x33\x52\x33\xf6\xa4\xce\x54\x17\xf6\xb3\x1d\xbe\xeb\x52\x9e\x1c\x22\x57\xff\x6a\x21\x1a\x76\x11\xd6\x96\x82\x3b\xec\xe1\xa4\xdd\x65\x9f\x82\xfe\xed\x64\xe5\x9f\x10\x28\x3c\xbb\xe0\xff\x46\x3d\x0f\x12\x25\x69\xa3\x75\x7d\xd4\xc7\x8a\xe4\x5f\x60\xd1\x6b\x69\x2e\x5b\x77\xe3\xf7\xc1\x86\x4b\xee\xa6\x1d\x38\x6f\x52\x0d\x59\x15\xf0\x95\x5f\xd7\xc6\x97\xfa\xb9\x85\x74\xb6\x99\x08\xbd\xd1\xba\x86\x49\x97\xc2\xcb\xba\x34\xb0\xb9\xd3\x14\xbe\x20\x15\x9f\x3c\xe6\x5f\xd6\xed\x7f\xea\x4a\xfd\x97\x57\x2a\x54\xdc\x24\x90\x92\xa2\x78\x22\x52\xfa\x71\x3c\xe6\x50\xc6\xd9\x8e\x58\x5d\xb7\xb4\x2f\xc4\x95\xd1\x32\x7b\xc5\x6d\xc3\x99\x65\xcb\x09\xcb\x00\x3f\x34\xef\x05\xd8\x23\xc5\x68\x53\x5c\xc8\xea\xaa\x57\x7f\x77\x6b\x96\x29\x05\xf3\x40\x38\x71\xa4\xf1\x54\x30\x08\xcd\x90\x93\xad\x7c\x89\x86\x32\xee\x6b\xa2\x0f\x61\x27\xea\xcb\x8f\x83\x7e\x81\x84\x6a\x96\xbf\xef\xf7\xb3\xfb\xff\xfa\x56\xce\xf2\xdf\x59\x06\x5c\x37\xb5\x9b\x5f\x02\x17\x5f\xf8\x91\x29\xc8\x17\xeb\x0c\xcf\xd3\x4f\xd1\x8a\xfe\xb1\x89\x58\x5f\xfa\x07\x5a\x34\x57\x09\xd9\x22\x68\xab\x96\xf7\x92\xca\xb4\xc2\xb6\xca\x87\x79\x65\x58\xf0\x1b\xc5\x3c\x8f\xd1\xe4\xda\xbf\x31\x58\x34\x68\x6c\xa3\x37\xd0\x53\xde\x06\xc2\x97\x63\x30\x6f\x70\xd1\xbc\x4f\x06\xc5\x91\x4f\x4b\x6f\x29\xb8\xdf\x3c\x27\xdf\x79\xee\x14\xdb\x2b\x1b\x28\xd7\x17\x71\x94\xde\xa7\x7d\x7a\xb6\x1c\xde\x52\x01\xbd\x71\xfd\xee\x11\x31\xc2\xe9\xfa\x9d\xb8\x0b\x7a\xd3\xa1\x94\xef\x82\x94\x5b\x98\x67\xa9\x2f\x66\xf3\xae\x3c\xe4\x5e\x25\xec\xb1\x61\x93\xc5\xfc\xdd\x59\xd1\x24\xab\x57\xa1\x2c\x88\xac\x9e\xfa\x9c\xf2\xc6\xc2\x4c\xfd\xb2\xf7\x1e\x42\x25\xd1\x22\x5e\x10\x3f\xb1\x79\x55\xaf\xd6\xdc\xb2\x33\x70\xfd\xa7\xed\x15\xfa\xc5\x97\x4d\xba\x73\xeb\x70\xf1\x18\x61\x9c\x2f\x21\x93\xf5\xfb\xf5\xef\x03\x1b\x0b\xff\x3d\x42\x4b\x59\xa3\x13\x6e\x5b\x5a\x52\xf6\x6e\x25\x0e\xde\x1e\x28\x43\xf1\x52\x73\x89\xbd\x91\x7f\xc0\xc7\x17\xcd\xba\x77\x21\xb6\x72\xcf\xfc\x09\xec\xe8\x93\xd3\x1d\x93\xd3\x3d\xcd\x08\x65\xf1\x3d\xfd\x8d\x70\x3e\x99\x03\xde\x61\xba\x7a\x2b\xb3\x37\x6c\xe1\xd0\x72\xef\xbf\x1f\xef\x53\xbc\x21\x32\x50\x6a\x6b\xe5\xb7\x89\xdd\x77\x6b\x41\x81\x73\xf4\x60\x83\x6a\x4f\xe1\x83\x55\x23\x0d\xd7\x8a\xf6\x2d\x9e\x84\x98\xa2\x48\xbb\xcd\xf4\x39\xb3\xc1\xdf\xb5\x24\x29\x85\x22\x1f\x24\x4b\xc2\x94\xb5\x41\xb5\x51\xb3\x7c\xb2\xe1\xd2\xdc\xb1\xf6\x60\xed\x60\x2c\x3a\xcd\x75\x2a\xfa\x16\x09\xb9\x7e\xc3\x91\x95\x74\x5b\xac\xc4\x27\x0e\xeb\x4d\x27\xbd\xe2\x2e\xdf\xdd\xab\xb9\x4c\x5c\x00\x4b\x9a\x60\x28\x52\xd8\xd1\x79\x8a\xde\x12\xdf\x31\xbc\x7e\x67\x0e\xc2\xf3\x6a\x68\xc7\x3d\x46\xc3\xfc\x3f\x36\x9b\xec\x7b\x08\xdd\x10\x85\xf2\xa8\x6f\x4b\x28\x89\x86\xa1\xfe\x7f\x54\x5d\xe9\x92\xb3\x3c\xaf\xbc\x97\xf9\x7d\x6e\xca\x80\x03\x0c\x8b\x79\x01\x27\x4f\x72\xf5\x47\xad\x6e\x39\xf3\x55\x4d\x15\x0a\x01\x86\xb0\x78\x91\x7a\x91\x0c\xd5\x9b\x47\x47\xca\x64\x55\xa4\x9e\xd3\xa2\x45\x15\xa7\x80\x53\x41\xd9\x4a\xd5\xa6\xac\x46\xfd\xca\x6d\x40\x7e\x61\x18\xc5\x32\x5f\x3f\xa1\xea\x7c\xc5\x1d\x00\xa8\xe5\xbc\x3f\xdf\x8f\x9c\xcf\x51\xd5\x8a\x41\xb8\x96\x40\xdd\x4a\x60\x64\xaf\x48\xdd\x31\x6f\x47\x4d\x6a\x0e\x05\x33\x4a\x5d\x29\x4c\xb1\x27\x49\x3d\xd6\x6d\x3f\x2b\x91\x38\xc8\x33\x1f\x2c\x41\x61\xf4\xd7\xd4\xae\x46\x45\x83\x0d\x95\x48\x32\x72\x1f\x5f\x46\x1b\x0b\x54\x84\x1c\xda\xe8\xfd\xd3\x5c\x44\xde\x89\xae\x1d\x5e\xc6\xf2\xe5\x3c\xb0\x66\xc5\xe4\xde\x95\x12\x39\x44\xfb\x4c\xae\x17\x26\xa7\xdf\xf2\x13\x2d\x44\xb2\xc7\x77\xdd\x77\xd1\x85\x64\x06\xbc\xed\xf2\xfa\x9d\xc2\x3f\x58\xfa\x57\xfd\x22\x6a\x34\xa0\x3d\x1b\xeb\xce\xe7\x2c\x4a\x1b\xca\x4d\x64\x0f\x39\x8c\xe5\xc1\x32\xd2\xbf\x93\xa3\xc3\x53\x0a\xd0\x67\x56\xa1\x2c\x53\x2d\x06\x2c\xc3\x07\x4b\x45\x48\x28\x90\x55\x94\x25\x6d\x6a\x01\xa6\xe7\x1e\x85\xfd\xc7\x2b\x7c\x45\x40\x12\xee\xcf\xd4\x6c\x44\xc8\x79\x82\x3b\xb6\x2f\xf7\xc1\xaf\x27\x34\xaf\xe6\x6f\x4d\x8a\x6e\xc6\xc9\x1e\xc4\x39\x02\x5f\xca\xcd\xef\xd4\x2c\xcd\x9a\x1d\x66\xf5\x30\xc7\x13\x73\xeb\x3f\x38\x39\x06\xa1\xe9\xa8\xbf\x85\x0a\x59\x20\x58\xa8\x98\x73\xba\x3a\x2e\x23\x9b\x35\xa9\x56\x35\x4a\x21\xab\x91\xa1\x0e\xbb\x16\x2c\x4a\x9d\xb7\x26\xfe\xd0\xc1\xe2\xaa\x03\x6a\x5c\x8c\x58\xd9\xb1\xe5\xaf\x1b\xd2\x1e\x65\x3b\xbc\x8a\x72\xac\x75\x50\x89\x2a\xaa\x56\x36\xcf\xaf\xd4\xad\x9a\x3f\x5a\x13\xe6\x67\x47\x60\x7d\x51\xa7\x3a\x25\x84\x35\x89\x61\xa4\xc4\x8d\x4d\xc6\x2e\x71\x26\x8f\x89\x3e\x47\xc8\xe4\xb3\x67\x3e\xb2\x9c\x54\xe0\xad\x28\x7c\x1e\xe5\xb1\x58\x8c\x3a\x1f\x51\x38\xca\x2e\xe6\xe5\xd1\x3e\x15\x8d\xc4\xed\x2d\x95\xa2\xd6\xba\x86\xc1\xc8\x93\x82\x06\x30\x4b\x66\x19\x0a\xcc\xcb\x59\xb6\xc9\xa7\x32\x33\xc7\x17\x3f\x07\x66\xd1\x2f\xcb\x50\xed\x5f\x84\x0d\xfa\x91\x7e\xfd\x60\xe5\x55\x2f\x74\x6a\x61\xb8\x80\xdc\x1c\x2b\x4c\x8e\xf6\x42\x10\xe8\x55\x97\x27\xd6\x64\xb6\x64\xcd\x42\xfc\xc3\xf0\x92\x74\x57\x0f\x31\x08\x92\x8b\x00\xa7\x8a\x6b\xb8\x7f\x05\xe8\xf6\xba\x1e\xae\xa5\x85\x51\xa4\xdf\x62\x2f\x55\xf9\x6b\xb7\x97\xb3\xa9\x75\x0d\xde\xaa\xed\x24\x75\x51\x9e\xeb\x27\xc4\xb9\x7c\x0b\x37\x2c\xf5\x40\x6e\x28\x98\x18\xb3\xf6\x85\x49\x91\x97\xb2\x00\xca\x20\xf3\x6a\x77\x1b\xe4\x81\xc9\xf6\xad\x5e\x3e\xd1\xda\x50\x41\xe5\x32\x95\x85\xd1\xc6\xfc\xed\x56\x6d\x3c\x29\x0e\xd2\x7e\xff\x2a\x94\x08\xb6\xdb\xa4\xb0\xcc\x60\x11\x6b\x60\x60\xa6\xa9\x78\x65\x03\xfa\x21\x97\x3e\xd6\xa3\x10\x34\x9e\x51\xfd\x4a\xfb\xfb\x1b\x0e\x3a\xc8\xcc\x89\xed\x46\xfc\xd1\xe6\x15\x56\x16\xb3\x6e\x39\xa3\x68\x14\x68\xc1\xaf\x44\x97\xa1\x01\x56\xe4\xa1\xee\x7c\xa5\xaf\x4d\x33\x6a\xe9\x3c\xd1\x2c\x6a\xc2\xd6\xc4\x3c\x36\x38\x25\xb0\x52\x85\x7c\x0f\x7f\x7f\x5e\x47\x3c\x2a\x52\x04\x6b\xbc\x18\x54\xb5\x5a\xdc\x3b\x1a\x8f\xa5\x28\x7b\xfe\x55\x7c\x82\x4a\x8f\xea\x48\x76\x63\x54\x82\xeb\x47\x78\x74\xa8\x94\xd2\x8f\x73\xd7\x85\x64\x98\xb5\xd6\xb2\x52\x41\x82\x44\x3b\xda\xb4\xfa\x8c\xca\x56\x8f\x24\x67\x14\xbf\x80\x23\x53\x0d\xa7\x87\xb7\x63\xf3\x50\x01\x4c\x53\x3c\xa4\xb7\x0a\x36\xff\x82\xb2\xf4\x8a\x42\x93\xfd\x03\x55\xbd\x5c\xcf\x3a\x56\x5b\xac\x62\xcf\x7d\x55\xf9\x34\x6d\xe9\x62\xbd\xd6\xcd\xa0\xb9\x24\x31\x03\x81\xf8\x51\x71\x8e\x98\xde\x68\x9b\x7e\x66\x07\xcb\xd0\x83\xbd\x95\x3a\xad\x9b\x7a\x87\x63\x74\x78\xb3\xec\x32\x5e\xf1\xec\xb0\x6b\x39\xfe\xb0\xec\x94\x54\x0a\x5b\x51\x9c\x66\x24\x38\x38\x6a\x51\x34\xe6\xd8\x52\x0f\x35\x38\x86\xcc\x4c\xac\xe1\xc2\xbb\x72\x32\xbe\x56\xb4\x26\x3e\x38\x5d\xab\xf2\x58\xa8\x36\x51\x11\x0c\x6d\xa4\x17\xa7\x00\xf2\x94\x42\x99\x3d\xf7\xd1\xfb\x43\xa4\x4c\xd6\x23\x45\xbe\xcd\x6b\xf9\x22\xa4\x31\x16\x3a\x09\xf1\x5b\x9b\xe2\x13\x74\x26\x58\x81\x77\x7a\xa1\xd7\x76\x9c\xcd\x75\xf0\xe5\x5e\x23\xab\xb8\xce\x9a\xc3\xc3\x6b\xe5\x12\xed\x2b\x77\x41\xbb\x0a\x55\x35\x14\xb1\x52\x44\x2a\x77\xe5\xa7\x9c\xb4\x91\xd8\xe2\x32\x8a\x8d\x2b\x11\x9d\xfe\xff\x9d\x49\x2d\xd2\xd7\xe5\xb0\x0f\x3b\x8b\xf0\xbd\x16\x45\x7c\x95\x00\xaf\xbd\x91\xb4\xde\x5a\xe9\x5d\x1b\x76\x2c\x4e\xfe\xe1\x86\x8f\x1c\xbf\x27\x4b\x6c\x77\xcd\x29\x4a\x68\xd1\x9a\x59\xb4\x85\x2d\xf6\x47\x95\xad\xe7\x5c\xa2\x92\xbf\xe2\x21\x54\x0d\x2d\xc4\xd8\x6c\x12\xc0\xc2\x98\x2e\x42\x0a\x77\x98\x10\x77\x5c\xc3\x76\x6a\xa5\x26\xb4\xb7\xbd\x78\x27\x58\x23\x93\x25\x30\xea\x66\x57\x69\x15\xb4\x1f\x71\xc7\xe2\xbb\x50\x75\x4b\x23\x9d\x71\xec\x21\xaa\xbb\x20\xaf\xb0\x89\x41\xeb\x73\x33\x96\x27\x4e\xea\x08\x22\x59\x53\x5a\x3c\x31\x0e\x85\x26\x5f\x64\xc1\x5e\x60\x18\xc3\x82\xd7\xe9\xbe\x17\x0b\xec\x85\xf9\xb9\xb0\x78\xf6\xad\xac\xe5\xca\x0e\x75\x29\x4f\x82\x32\x97\x72\x7c\xcb\x57\x45\xea\x8c\xa0\xa2\x91\x40\xb9\x48\x30\x64\x89\x14\x1b\x1c\x61\xd4\x13\x2d\xf2\xe6\x5b\xbc\x4e\xf1\xe3\x22\x6d\x7d\xb0\xc7\xce\x2b\xd4\x63\x16\xc7\x55\xb0\xaa\x26\xf9\xa4\x25\xcc\x7e\x97\x1c\xf5\xb6\xed\x58\x65\x14\x83\xbe\x29\x34\x18\xed\x8d\x6e\xac\xb6\x9c\x48\x30\x8b\x0d\x31\x55\x67\x21\x6e\x23\xba\xfe\xb7\xde\xac\x03\x39\xc3\xec\x24\x55\x2c\xb4\x5e\x7e\x53\xc3\xb8\xfd\x26\x9a\x2e\xcf\xd7\xe2\xad\x38\x50\x88\x27\xa1\xdd\xf3\x42\xf1\x5a\x1b\xc7\x7a\xe5\xe4\xdd\x48\x56\x6f\x56\xa5\xa7\x7a\x25\x39\x87\x07\xcd\x02\x23\xed\x18\x8a\x4e\x35\x46\x05\x93\x84\x32\x26\xcf\x7b\x90\x0b\xf6\x26\xc9\x0c\xf9\xd2\x39\xaa\x6c\x61\x51\x8b\x2a\x9b\x2f\xc4\x38\x44\x01\xed\xe2\xb2\xa9\xac\x95\xb5\x15\xef\xd6\x21\xb7\xb0\x93\x34\x5c\xbc\x23\x10\xe3\xf5\x13\x83\x34\x65\xf3\x74\x19\x44\x00\x5b\x55\xac\xfb\x3a\xc5\x64\xa1\x8e\x5c\xc2\x36\x28\x58\x79\x18\x8f\xe0\x9c\x59\xeb\x2e\x65\xe2\x49\x32\xe3\x28\x8d\xbd\xa8\x1c\x3f\x49\x49\x74\x6a\xa4\xc4\x09\x98\x68\x1a\xb9\x5c\x61\x49\x8a\x82\x98\x0d\x62\x1f\xaa\x84\x85\x4c\xdc\x79\x8a\x21\x76\x1e\x5a\x0e\x73\xe8\xc5\xad\x34\x28\x5f\x57\x49\xbd\x01\xf1\xa0\xba\x56\x98\x48\x4d\xae\x0a\x19\x94\xb6\x14\x6c\xba\x94\x0e\x9a\x36\x8d\x55\x86\x56\xa3\x9b\x07\x8b\x77\x55\x49\xa0\x1f\x6b\x64\xcc\xc6\x3a\x48\xac\xed\x94\x71\xf3\x78\x42\xbd\x47\x91\x7e\x33\xa8\x62\x45\x72\x70\x59\xcf\xed\x78\x46\xb1\xc9\xba\x7c\x2f\x60\x95\x53\x2c\xb1\x73\xe4\x80\x75\x2c\xe5\x0a\xe6\x18\xd1\x33\xa3\xa4\x56\x00\xa6\x69\x59\x37\x74\xcd\x90\x37\xf3\x33\x03\x6a\x4b\x1d\x88\xc5\xc3\x4b\xa6\x31\xe8\x39\xfd\x90\xf3\x6a\xf7\x43\x6f\xe1\x88\x5b\x4b\xa2\x98\x3a\x07\x97\x8b\x63\x95\x4b\x39\x77\x15\xc7\xa8\x25\x77\x4b\xb4\x66\x4c\x41\x6f\x01\x77\xac\x44\xa5\x2c\x82\xf0\x92\xb1\x57\x49\xa4\xcc\x31\xb2\xd1\x16\xb8\x90\xf6\x08\x86\x46\x94\xa1\xea\x1f\xd9\xfb\x50\xed\x94\x76\x8e\x2b\xc9\xb1\x86\x75\xfe\x29\xa5\xb1\x44\xa1\x72\x05\x2b\x69\x2f\x55\xd4\xaa\xda\x91\x07\xf0\x87\xe7\x38\xab\x72\x76\xaa\x24\x6d\xed\xe4\xa0\x60\xbe\xc8\x3d\xe3\x5c\xfe\x61\x43\x16\x96\xb3\xc0\xb4\x56\x8d\x13\x5e\x34\x28\x0d\xfb\xfa\xf9\x0a\xf9\xe1\x47\xe4\xa9\x1e\x73\xd8\xf0\xa2\xb0\xe6\x17\xec\x91\xd9\x79\x3e\x9c\x30\xa9\x3c\xcb\x03\x4f\x78\x50\xc1\x1f\x3e\x34\x61\x85\x0e\x30\x97\x29\xae\xa1\x97\xc8\x9c\x28\x76\x35\x73\xb9\x46\x24\x42\x81\x5a\xba\x39\x20\x68\xfa\x0d\xcc\x0b\x7f\x54\x5e\x06\x52\x0d\x72\x48\x45\x5a\x67\x18\xdc\x30\xa6\x8a\xb9\x5d\x22\xab\x22\x27\x9a\xb4\x0d\x95\xf2\x3c\x43\xdd\x91\x32\x24\xbd\x0c\x30\x45\x96\xb9\x64\x69\x3d\x54\xde\x01\x5b\xb2\xb2\x84\xe4\x3f\x8b\x64\xa0\xab\x88\x4e\xe6\x4d\x97\x8d\x7e\xd7\xc6\x17\x13\x72\x69\x28\x9b\x37\xa3\x43\x81\xa4\x57\xd1\x14\xd1\xcf\xc9\x57\xc3\x96\x9c\x3b\x07\xbb\x78\x98\xd7\xba\xae\x51\xf8\x8a\x4a\x97\x8f\x10\x3c\xba\x38\xa0\xb7\x60\x2f\x72\x7b\x85\xff\x4c\xbd\x59\xaa\x05\x87\xac\x4a\x82\xee\xec\xde\x9e\x76\xf1\x0f\x3b\xdb\x07\x6b\xff\x74\x0e\x39\xcc\xe9\x50\x2c\x0b\x26\xda\x2a\x99\xa8\x21\x10\x61\x43\xfe\xad\x32\x83\xf7\x9c\x26\xd7\x11\x93\x32\x40\x67\x88\x5f\xc9\xc9\x67\x80\x90\x07\xbf\xfa\xaa\xe2\xf5\x75\xe6\x77\x21\xeb\x62\x33\xe0\xeb\xad\x25\x37\x96\xbb\xea\x90\x5e\xbc\x0f\x78\x5a\x06\x71\xba\x86\xc6\x0c\x19\x42\x79\x78\x80\x06\x16\x03\x96\xf0\xfc\x94\x6d\x64\x21\x06\x55\x25\xc8\xce\x96\x60\x7c\x65\x86\x49\x7a\x28\xfd\x59\xe7\xe5\x9a\xe8\xc5\xe3\x55\xb8\xf0\x9c\x39\xa3\xc5\xe9\x31\x12\x78\x33\x78\x84\x7f\xce\x4c\x51\x91\xfe\xcc\xd6\xc7\x73\x96\xda\x17\x8d\xb3\x51\x88\xe3\xa4\xd2\x46\xb9\x36\xdf\x29\x32\xa7\x07\x1f\xc5\x9d\x01\xdc\xd1\x7e\xe7\xa6\xd1\x95\x48\x49\x4f\xc7\x2f\x5d\xd7\x3c\x72\xc8\xe8\xe8\x57\x11\x41\x7a\x52\xb1\x7a\xf8\x41\xb3\x32\x87\x4e\xcc\xbf\x41\xfd\xcd\x8f\x3f\x41\x96\x99\xc5\x39\x74\x32\x2c\x15\x42\x2b\x85\x92\x78\x13\x9b\x25\xd0\xdd\x7c\x09\xa3\x68\x52\xec\x6c\x30\xae\x72\x1b\xd2\x22\xfe\x0b\xf3\x10\x5c\xb2\x77\xbe\x23\x7c\x41\x9a\x51\x45\xba\x27\xac\x6c\x64\x4b\x6f\x5d\x01\x01\xb0\x20\xbc\xad\x73\x78\xe5\x9c\x7f\xab\x73\x5f\x42\xdf\xb7\xac\x62\xe1\x18\x72\x7d\xf8\x7f\x1f\x71\xda\x82\x8d\x97\xd6\x10\xc2\xf5\xe4\x8f\xbc\x7c\x6c\x1a\x91\x46\x9d\x11\x8d\x91\xc2\x97\xaa\x7b\x4f\xad\xa0\x17\x52\x7e\x6d\x49\x8f\x3b\xf8\xe9\xcc\x61\x94\xcf\xf1\xb2\x17\xf8\xa2\xfe\xd7\x26\x95\x80\x52\xc3\x82\x04\xe1\xf9\x6e\xb5\xba\xad\x15\xf0\xec\x14\xa8\x0c\x67\x61\x54\xef\xca\x15\x06\x86\x16\xeb\xd4\x41\x87\x53\x16\x17\x8a\x63\xd1\x95\xba\x8d\x7e\x44\xfb\xf5\x35\xcc\x91\x7f\x9e\x33\xe1\x32\x83\xf1\x8f\xb4\x5f\x14\xf8\x36\x11\x91\x3a\x38\x37\x35\x1b\x9e\x02\x99\x76\x0f\xae\x28\xfa\x9d\x55\xe5\xa7\xa6\x53\x23\x01\xa0\x8b\xe1\x18\x76\x3e\x45\xa6\xc5\x9d\x30\xbf\xce\x7e\xd3\x6f\x28\xaa\x6d\x58\x20\xf9\xbf\xf2\xf6\x7f\xa8\x6a\x57\xa3\xa0\xcd\x50\x90\xfd\x61\x59\x90\xdf\xc0\xad\x59\xba\x7e\x1f\x5e\xef\x4c\x51\x99\xae\x65\x8e\x9c\xa6\xc6\xaf\xc0\x43\x5c\xf5\x6d\xaf\xf3\x09\x9d\x2d\x0b\x9a\x7b\xcf\xba\x3b\x42\xb0\x73\xd0\x03\x2b\x82\x84\xb6\x41\x11\x90\xd5\x01\xd6\x0b\x95\xc4\xef\xb2\xa6\xc1\xac\xf7\x69\x1f\x8f\x19\x9c\x5f\xa3\x9d\x2e\xab\x6a\x68\xbd\x97\xa2\xfd\x29\x43\xfd\x0e\x25\x26\xd5\xf5\x00\x3b\x0c\x91\xc0\x60\xb8\x5d\x04\xcd\x27\xcc\xc8\xfd\x19\xb5\x48\xd2\x42\x4e\x73\xdb\xed\x76\xea\x26\xda\xb1\x59\x0e\x3c\xb7\xb0\x14\x77\xf3\x2f\xb6\xc3\xee\x58\x18\x08\x13\x7d\xf0\x4a\x9e\x2b\xe2\x7b\xef\x15\x80\x06\x2f\xee\x09\x77\xee\x56\x9a\x7e\xd4\x0d\x49\x3a\xb2\x56\x41\x8f\xe3\x41\x21\x81\x8c\xe1\x35\xeb\x7a\xf2\xf9\x59\xd9\x3f\x24\x70\xc4\x3c\x6d\x9b\x5c\xca\x17\x41\xf6\x04\xb7\x4c\x7a\xfa\x5e\xd7\x28\x75\x83\xe0\x00\x89\xa5\x8f\xcf\x8b\xed\xef\xa7\x62\x1c\x86\x60\x3e\x9b\xa4\xe0\xc8\x8b\xf8\x99\xdd\x34\xc3\xa5\x08\x91\xd8\xf7\x13\xfa\x10\xc7\xfe\xc9\xec\x22\x3f\xe9\x9d\x7a\x5f\x9e\x01\xc5\x26\x2b\x8e\x02\x3c\x28\xf5\x71\x96\xf5\x92\xe9\x3c\xac\x74\x82\xf2\xc6\x5f\x83\xa1\xf5\xc9\x1a\xe0\x3a\x90\xd0\xc6\xd9\x17\x96\xe2\xa1\x79\xb3\x44\x0d\xc1\x79\x97\x1d\x8a\x45\xb1\x2a\xa0\x6f\xa2\xbb\x79\x38\xcd\x41\x51\xa5\x02\x21\xc9\x75\x6e\xce\xe1\x49\xec\xd7\x14\xf3\xf7\x97\xad\x08\xbe\xdb\xfe\x91\xec\x20\xeb\x80\xae\x28\x28\xae\x1c\x35\x9d\x5f\x8d\x75\xf3\x92\x97\x95\x93\xd9\x54\xf2\x1b\x64\x3b\x53\xf6\x53\x43\x10\xba\xe2\x78\x35\xae\x50\x64\x08\x39\x4e\x1b\xe8\xb4\x12\xdf\x2a\xcb\x1b\x0b\xfb\x59\xe4\xb6\xbb\xaa\x5f\x50\xcc\xa8\x69\x0c\xae\xac\xc0\x58\x34\x15\xc9\x99\xbb\xd3\xcd\xa7\x85\x52\x57\x64\xcd\x8f\x26\x4b\xaa\xff\x45\x96\xe3\x09\x73\xc9\xbc\x44\xd4\x75\xda\x01\xa5\xbd\x9e\xd5\xc3\x55\xcc\x3a\x62\x90\xaa\xbd\x5c\x7e\xc3\xea\x71\x4d\x5e\xae\xaa\xdb\x63\x25\xa0\xf0\xbe\xea\x2f\x59\x6e\x6f\xd2\xa0\x6e\x78\x4b\x15\x06\x4d\xb7\xe7\xb6\xbe\xca\x5f\x2c\xe8\x13\x0a\x86\x7c\x17\x15\x10\x61\xa8\x3e\xee\xe2\xc5\x9d\xb1\x4c\x92\x28\x6c\x8d\xde\x5d\x36\x19\xee\x5c\xa1\xd3\x7a\xcf\xfb\xd2\xa2\x41\x41\xbf\xec\x85\x51\x27\xdc\x12\x22\xea\x18\xbb\x0f\x5e\x7b\x55\xd1\x45\x6e\x51\x9a\xbd\xa7\x50\xf1\xf5\x88\x23\x39\x7b\x08\x2a\x59\xa1\x37\xa6\xee\xfc\xc5\x79\x94\xcd\xcb\x0d\x8c\x99\x5a\xe2\x3b\x55\x65\x93\xee\x3f\x6e\x53\x77\x6a\xbc\x3b\x4f\xb2\xf5\x5c\xd9\x15\x56\xee\xaf\xf7\xa1\x7a\xd4\x5b\xff\xfb\x7a\x69\x90\x78\xd9\x93\x1f\x25\x0a\x1b\xf1\x0c\x51\xfa\x0a\x12\xd0\x55\x4f\xa7\xcc\x50\x02\xb1\x79\xe0\x54\xca\x82\x5d\x75\x1c\xb4\x42\x35\xbe\x2a\xeb\x5c\xf0\xe3\x5b\x09\xb4\x1c\x8a\x40\x95\x09\x4d\x28\x62\x45\xc9\xbc\x73\x09\x49\xed\x96\x42\xbc\xfa\xba\x09\xe5\xf5\xd3\xbc\xed\x26\x53\x52\x0f\x51\xcf\xe0\x11\x47\xb2\x2b\x25\x01\x3d\xb2\xfb\x82\xd0\x37\xad\xe1\x1e\xe4\xd4\x3e\x11\x08\xb3\x38\x58\xfc\xe4\x16\xa8\x2a\x9d\xae\xc1\xf6\x3a\xce\x34\xba\x5e\xc8\x75\xb0\x9d\xb9\x8e\xf9\xab\xba\xc8\x3a\xdb\x91\x50\x32\xe6\x19\x1c\xaa\x71\x5b\x80\x41\x80\x7f\x5f\x9a\xd3\x8f\x18\x5b\x2e\xc1\xc8\x13\xda\xf3\x3a\x9e\x52\x5c\xdc\xb3\xc6\x2a\xd7\x46\x08\xe4\xb5\x8a\xe8\x8c\x1c\xf1\x22\x6b\xa6\xf9\xf4\x6a\xb4\xbd\x18\x71\xfd\xec\x15\xb9\x55\xb3\xd0\xeb\x82\xc7\x81\x68\x07\x9b\x8c\xbc\x36\x51\x13\xa1\x14\xc3\x65\x38\x28\xb9\x22\x0c\x9e\xbb\x6b\x3c\x45\xdb\x7b\xd0\x07\xe2\xca\x87\x26\xfb\x57\x16\xf8\x1a\x81\x7e\x5c\x4e\x8d\xba\x67\xc3\x65\xf1\x31\xad\x49\x71\x2a\x21\x4b\xa9\x3f\xdf\x2a\xaa\x7e\x3c\x3e\x09\x00\xe8\x7a\x8c\x51\x0d\x2d\x50\xcb\x0f\x99\x46\xe4\x0e\xd4\xae\x82\xc8\xd7\xd4\x22\xfb\xf6\x62\xb8\x24\xe3\xac\xa3\x20\xb5\x32\x86\x52\x62\xd5\xab\x61\x91\xf8\x06\x57\x9b\x8b\x5f\x40\xea\xdb\x88\x5a\x64\x3e\xbc\xbc\x0f\x5e\x2a\x60\x7c\x19\x70\xde\x77\x25\xe5\x30\xaf\x44\x52\xc4\x95\xbe\x44\xc5\x44\x9d\xe6\xf3\xed\xed\x96\x35\x41\x89\x54\x3f\x4d\x74\xa1\x72\x20\x22\x1f\xe6\x83\x51\x05\xd5\x15\x38\x69\x2b\x75\x16\xa9\x97\x82\xdf\xd7\x58\x7f\x5c\x6e\x7a\xed\xce\xf2\x2b\x66\x5c\xe9\x27\x6d\xdc\x79\x69\xf0\x47\xba\x8b\x34\xed\x29\xcc\x1f\x41\x30\x81\x5c\xbe\x9d\x7e\x4a\x08\x34\xed\x05\x64\x83\x15\xd8\xe8\xbb\xce\xb9\x4b\x2c\xae\x3e\xc3\x3b\xc8\xcd\xe2\x7e\x58\x5d\x95\x9c\xc3\x99\xc3\x0f\x28\x13\xb5\x0a\x87\x50\x99\x01\xdd\x4c\xfe\x41\xbe\xe3\xc3\x7a\x6a\x28\x7a\x9d\xcd\x30\xe0\x4c\xa4\xa1\x9c\x32\x65\x12\xdb\xe6\x4c\x54\x93\x4c\xfd\xc2\x01\xf9\x29\xc7\xa8\x13\xe2\xe4\xe1\xa6\x94\x3a\x07\xe1\xfd\x57\x9d\xc6\xef\x35\x3d\xe0\x3f\xbc\xca\x57\xf7\x41\x8c\xbf\x5b\x37\xf7\x80\xf2\x35\xe1\xcd\x70\x16\xaa\x77\x33\x19\x1a\x51\xf2\x65\xe9\xf4\x3d\x30\x8b\xe9\x9a\x8c\x2a\x95\xa2\xb2\x9a\x6e\x99\x08\xe9\xd9\x3c\xe0\xc1\xc1\x52\x28\xa0\x91\x94\x56\x64\x75\x1a\x96\x42\x49\x93\x37\x6b\x9c\xe7\x10\x65\x94\x1f\xbb\x3d\x95\x7d\x39\x58\x5f\x45\x77\xc2\x28\x7e\x13\x2a\xac\x89\x81\x3c\x57\xa0\xdd\xc8\xfd\xfa\x9e\xf3\x05\x94\x53\x43\xb2\xf1\xce\x8d\x11\x48\x12\xc9\x01\x2f\x32\x7e\x79\x42\x7b\x49\xc5\xd4\x18\x0c\x1d\xe8\x1a\x28\x4e\x99\x99\x03\x80\xb6\x6e\x33\x55\xca\x5f\x41\x9c\xa3\xbd\x15\x87\x3b\x47\xb3\xda\xba\x6b\x00\x77\x04\x3a\xcd\x02\x32\x20\xd9\xa2\x1e\x61\x24\x77\xa4\x41\x8f\x3b\xdc\x0b\x59\x84\xd3\xd0\xa0\x9c\xf1\xf2\xba\xda\x80\x73\xfe\xd0\x3d\x73\x29\x26\x1f\xb7\x5c\x60\xde\x8e\x60\x4a\x3e\xfd\x0f\xda\x26\x96\x34\xe6\xf0\xf2\x69\x79\x7d\x75\x19\x7d\x08\xe1\xdc\x7a\x91\xff\x9c\x6a\xba\x97\x51\x36\x47\x50\x0b\xf1\xd2\xe8\xdc\xb3\x7d\xb3\xa0\x57\xd1\xf4\xeb\x92\xb8\x43\x1e\x23\x92\xb4\xf6\x61\xcc\xd1\x78\xef\x9e\xf9\x8f\xff\x97\x45\x48\x01\x41\xf0\xd2\x92\x0b\x55\x76\x33\x67\x65\x40\xb1\x52\xb2\xb0\xba\x0d\x1d\x23\x5d\x60\x8b\x84\xc5\xdd\xc2\xa1\xd4\x02\x89\x3c\xd6\xfd\xad\x35\xd0\x47\x22\x89\xf0\x8e\x42\xab\x3d\x4a\x62\x07\xa2\x99\x6b\xd4\x43\xd7\x2d\xc2\xe5\x5f\x45\x24\x04\x16\xc1\x03\x91\xf6\xfc\x31\x4e\x7b\xab\xcd\x6e\xf5\x6c\x85\xda\x14\xdc\x43\x25\x1a\xb7\xd2\xea\xd4\xdb\x9a\xfb\x0f\x8b\x7b\xf3\x9b\xfd\xc5\x36\xdf\x91\xe5\x6f\x9a\x67\x5b\x7b\x9c\x11\x91\xd8\x88\x02\x60\xe8\x48\x4e\x59\x0c\x5a\x67\x66\x6f\x2c\xe6\x92\x51\x97\x75\x4b\x95\xc7\x72\x79\x49\x11\x02\x33\x69\xf5\x5b\xfe\x52\xd3\x32\xec\x68\x83\x8f\x98\x59\xe2\xdb\x90\xf5\xe6\x21\x42\x6e\x65\x8b\x77\x75\xcb\x83\x4d\xfe\x9d\xac\x99\x99\x1e\x01\x23\x51\x1b\x61\xf0\x10\x25\x62\x88\x51\x8a\xc3\xb7\x85\x90\x8a\x85\x59\xd5\xdb\x2d\x11\x25\xb4\xd9\x23\x24\x41\xcb\xb1\xbc\x9a\xe0\xa4\x3d\x1d\x8a\xe1\xfc\x4c\x9e\x65\x0f\xde\xa9\x8a\xc6\x48\xf4\x30\x08\xb3\xc5\xad\xef\xc4\x45\x14\x58\x6d\x4b\x6f\xbb\x69\x64\xea\xbd\x73\x15\x01\xf0\xaa\x2c\xac\x5e\x95\x95\xd3\xf6\x00\xa5\xf3\x13\x5c\xd3\xe4\xc8\xe3\xd0\xac\x54\x41\x04\xf5\x59\x6b\xe5\x1e\x3f\xdf\x0a\x6d\x23\x10\xda\x60\x18\x73\x52\x56\x50\xad\x2d\x50\x51\x96\x86\x25\x9b\x63\xc2\x3c\x08\x33\x65\x2f\x9f\xa9\xd0\x0c\xfd\x68\x56\x66\xa5\x69\x8d\x80\x2b\x6c\xa2\x16\x46\x50\xf6\xe1\x7f\x08\x97\xa9\x1f\x4a\xe3\x21\x72\x36\x03\x22\x60\xd0\xf7\xca\xf3\x29\x1a\x5c\x79\x4a\x87\x6d\x75\x70\xc1\x8f\x97\x4e\x3f\x3f\xaa\xa0\xb2\x3a\x69\x4f\xd8\xb7\xee\xea\x68\xe5\xe1\xfe\x09\x3e\x60\x29\x54\xcb\xdc\x9a\xaf\x54\xee\x58\x05\xb5\xbb\x7a\xe7\x08\xa7\xaf\x79\xe9\xea\x8a\xeb\x08\xf2\xeb\x5b\x6b\x95\x08\xbb\x47\xbe\x14\xa3\x0d\x0a\x9a\x2a\xbf\x7e\xfd\x6c\x90\x58\x3b\xf9\xed\xac\x3a\x6f\x34\x07\x00\x3d\x84\xa3\x54\x58\x01\xad\x10\xd4\xad\x1e\xa4\x8b\x75\xd8\xd4\xb4\x35\x85\xd2\x5a\x61\x4c\xab\x92\xa8\xea\xbd\x09\x4e\x75\x51\x1a\xfd\x51\x61\x94\xe2\xa0\x10\x6f\x65\x89\xd7\x27\xf6\xb4\xec\x4a\x22\x14\xad\x5f\x47\xab\x72\xaa\x20\x3b\x9f\x97\x34\x37\x67\xa9\xbe\xac\x09\x25\x60\x0f\x6c\xe6\xa2\x62\x68\x9f\x3e\xdc\xbe\xab\x03\xff\x73\x47\x9c\x03\x5c\xb1\xf8\x4a\x42\x1c\xdb\xeb\x8e\x6f\x55\x47\xdf\xa2\xfe\xd5\x06\xc1\x45\xe8\x35\xc5\x3a\x49\x4b\x63\xf1\x8a\x83\x17\x31\x6b\x37\x13\xeb\xb9\x20\xeb\x14\x58\x47\x7c\x98\x88\xc1\x43\x3d\x55\x45\xd4\x5b\x5e\x59\xe7\x2e\xdd\xc8\xa5\x9c\x92\xf7\x2c\x92\xbe\x5b\x98\x0a\x5a\x58\x2d\x5b\x8a\x88\xab\xd0\x03\x65\xcd\xf5\x51\x32\xf7\x6c\x86\x38\x8b\x50\x03\x8b\x9c\x01\x97\xb5\x1c\x98\x0d\xa8\x54\xb8\x90\xfd\xf3\x13\x6c\x46\x0f\xf8\x92\xd9\x52\x7b\xb0\x13\x58\xe4\x70\xb1\x34\xf8\x23\x68\xc9\x11\x8c\x57\x8c\x17\xe1\xbd\x55\xb8\x76\x5d\x8f\xa4\xf2\x2e\xa0\x39\x7e\xf4\xf9\xb7\x95\x88\xc9\x95\x59\x20\xb0\x73\x53\xc1\x7a\x71\x6c\x7e\x14\x69\x81\xc4\xd3\x7f\xca\xee\xe1\xc1\x7e\xc2\x3e\x04\xc1\x02\xa6\x5d\x2a\x0c\x5b\xe3\xc0\xe5\x2a\x8a\xe5\xa5\x65\x92\xf0\xff\x22\x08\xf1\x92\xa2\xe8\x4b\x54\xf5\x6f\x25\x81\xee\xb7\xee\x10\xff\x67\x28\x83\x3c\xa8\x89\x2a\x60\x8e\xee\xb7\x78\x17\xf4\x3b\xbb\xea\x24\xcb\xc2\x02\xdb\x58\x60\xcf\x8d\xf3\x33\x71\xb6\x7c\xd9\x7e\x93\x77\x68\xbf\xc9\xdf\x73\x1b\x34\xf9\xa5\x85\x86\x32\x34\xa4\x70\x15\xa0\x1e\x2a\x20\xfa\xf4\x26\x53\x67\xaa\x42\xfb\x21\x33\xe5\x55\x4e\xd8\x7a\xed\x1e\x9c\xcf\xc4\x35\xe7\x75\xb7\x5a\xee\x41\x71\x3e\x0c\x21\x16\xb1\xfb\xca\x7a\xdd\xda\x65\xca\x7f\x2a\xc3\xf9\xa1\x4d\xe5\x1c\x3b\x05\x55\x71\x76\x02\xa3\x93\x10\xb3\xac\x18\x41\x90\x54\x05\xf7\x4b\x3d\xb4\x66\x21\x48\x91\xe7\xf0\xad\x08\xc7\x76\x9d\xf6\x5c\x1b\xdb\x72\x8d\x55\x73\x3b\xb9\x3c\xbb\xef\xc4\xa5\x58\xee\x84\x13\xb8\x66\x71\x44\x58\x1d\x91\x42\x99\x9e\xa7\x38\x9a\xa9\xd9\x77\xbd\xbf\x0e\x5d\xf5\xcf\xaf\x73\x56\xbd\x78\x8a\x54\x05\x71\x87\xaf\xfd\x6b\xe2\xb5\x2f\xda\x72\xd3\x2c\x13\xaa\xa1\xfb\xa5\x80\xa5\xd9\xa6\x35\x3d\xba\xa3\x67\x04\x5e\xfc\x3c\x83\xd5\x3b\x9e\xe2\x80\x8c\x85\x88\x8b\xb1\xe8\x22\xa0\x14\xab\x1a\x6d\x70\x3e\x47\x37\x66\x3e\xc8\x37\x5c\x81\x71\x62\xe9\x95\xff\x70\x0a\xd2\x9f\xab\x72\xaa\x8c\xfa\x07\xa2\x35\x52\x6f\x5a\xf1\x90\xb5\x6d\x48\x92\xa6\x7f\xf2\x19\xb7\x29\x6b\xf3\xdb\x1e\xad\xdf\x0d\x57\x69\x8b\xfb\xa9\x29\x7b\x8e\x33\x91\x85\x08\x7f\x68\xe1\xa5\x62\xee\xa0\x67\xf6\xf1\x96\xa9\x55\xb5\xc1\x35\xb9\x87\x95\x22\x5d\x8f\x1a\xfd\xd4\xe3\x9c\x3f\x11\xc1\x92\x4f\x51\x0e\xeb\x2d\xeb\x16\x16\x07\x5e\x9c\xfa\xc4\x14\xd5\xa3\xd4\x75\x54\xb5\xf5\xdc\x78\xcc\xa2\x59\xfb\x43\xcc\xef\x47\xb8\x74\x82\xe9\xa8\x61\xc0\x03\xfd\x04\xff\x9d\x7b\x7c\xfb\xd7\x33\x2d\xc0\xfc\xb8\xe0\x21\x78\xe7\xcc\x88\x75\x57\x3a\xcd\xf9\xb1\x81\x05\x92\xc7\x57\x9e\xa4\xf1\xf9\xf9\x88\x15\x69\xfd\x40\x63\x28\x3f\xa2\xce\xfd\x40\x59\xe6\x97\x41\xfc\x68\x0c\x40\xb8\xd1\xa9\x8e\xfe\x61\xf3\x85\x68\xcf\x1e\x89\x43\xb6\x66\x7a\x67\x43\xeb\xd6\x68\xe5\x3f\x8c\xae\xa8\x57\x66\x29\xfe\xe5\xf3\x1f\xb2\xd9\xbe\xd9\xee\x5d\x7f\xde\xc2\xe0\x6b\x6d\x75\x5f\x8c\x38\x83\xcc\xb8\x3e\x50\x16\x41\xb4\x4c\x44\x20\xa3\x60\xef\xcf\x43\x53\x5d\xcf\xae\x75\xbe\xd2\x4b\x31\x8f\xcc\xd7\x21\x71\x60\xbd\x1c\xc9\x9d\x6e\x23\xe6\xcb\x60\x4e\x92\xa0\x21\xf5\x5e\x7b\xdf\x82\x03\xf9\x62\xfd\x97\x93\x25\x5b\x9e\x59\x0e\xdd\x03\xe0\xd2\xa2\xcd\x0e\x55\xb3\x07\xaf\x1e\x13\x85\x3f\x54\x61\xfd\x87\xba\xe8\xdd\x1e\xea\x43\x95\xcd\xaa\xad\x75\x28\x7b\x7c\x58\xfa\x2c\x9f\xa4\x1a\x72\x00\xed\x86\xf9\xd6\xf4\x0b\x1c\x67\x19\x95\x6d\xf5\x23\x1d\xd1\x55\xe2\x27\xc3\x0c\xe7\x31\x0e\xc6\x87\xf9\x5b\x5b\x9d\x07\x15\x1a\x87\x29\x34\xba\x6c\x3c\x48\x80\xa3\xe7\x72\xf3\x9f\x92\xb2\x07\xd4\x7a\xb5\x65\x8a\xff\x9b\x4f\x91\xc1\xa1\x03\xb1\xa9\xb2\x7b\x8a\x59\xb9\x5f\xab\x58\x97\xaa\x19\x33\xef\xc2\xb0\xd3\x57\x14\xc1\x02\xfb\x21\xea\xd6\x2b\x2b\x80\x10\xaf\x7c\x0d\x3a\xe4\x9a\xda\xba\x09\xf0\x42\x8f\x7f\x0b\xfb\xe6\xe1\x0f\x5a\x73\xc8\xc3\x2c\xfe\x26\x4a\x81\xe4\x93\xa2\x0e\x2b\x1e\x69\x66\xaa\xd8\x96\x67\x7d\xf3\xc4\x3b\xb4\x51\x1e\xc9\x35\xad\xa2\x52\x5c\x55\x67\xd6\xa8\x69\xc0\xa8\xd9\xb7\x4a\x61\xc8\x96\x24\x4e\xdb\x98\x83\x9f\xe4\x98\xe3\xfe\xdd\x31\xdb\xd8\xd7\x5b\x29\x1b\xd4\x99\xff\x48\xa4\xa2\xea\xc1\x0a\x71\xc3\x61\xf4\x78\x74\x39\x2c\xeb\x4f\x49\x15\xf4\xb0\x67\x66\x71\x39\x35\x8f\x06\x20\xd8\x55\xc7\xeb\xcb\x4b\x3b\xf3\x99\x98\x55\x1f\xae\xc8\xde\xeb\x0b\xf5\x55\x7d\xf9\x8a\xa1\xaa\x1e\x04\x7a\x68\x94\xb8\x30\x59\x71\xdc\x85\x8e\xb0\x13\x9b\x86\xba\x73\x21\x95\x34\xc4\x84\xfb\x36\x2c\xee\x5d\x32\x43\x97\xbd\x97\x13\x30\x96\xbc\x2c\x3d\x74\x15\x58\xbf\xb5\x6e\x42\xac\xd0\x9e\xf2\xca\xc0\x75\xb0\x55\x60\x84\x60\x7a\xdb\x0c\x9f\x78\xa8\x7e\x3a\x3f\x5f\x30\x19\x99\xa3\x73\x50\x47\x6d\xc8\x4e\x3e\xe9\x7c\xe8\xb2\xdb\xd3\x2b\xbd\x9f\x3e\x84\x0d\x20\xe1\x2a\xb7\x72\x97\xde\x94\x97\x6c\xef\x9a\x65\x8a\xc6\x22\xae\xea\x94\xba\x08\x91\xc3\x88\x5a\xf7\x2d\xc1\x54\x19\xc4\x55\xb2\x46\x21\x17\x96\x7f\x82\x7f\xaa\x80\x6f\x28\x44\x5d\x45\x5e\x85\x34\xd8\x8f\x0a\xdd\xb9\x15\xba\x07\x28\x44\x29\x16\x1a\x00\xf6\x5f\xfb\xce\x64\x1e\x3f\x68\x3f\x1f\x6c\xb3\x7a\x7d\x94\xcf\xa7\xe8\x78\x47\x73\xb8\xdb\xf7\x24\xd5\xd8\xed\x00\x31\x47\x52\xb2\xdb\x11\x07\xc3\xb4\x59\x41\x66\xda\xa8\x4f\x61\x57\x6c\x11\x3b\x6c\x0b\x36\x29\xce\xae\xc1\x7f\x5d\xd7\xb6\xd1\xac\x1f\xd6\xf7\x73\x89\xeb\x61\x71\xba\xa5\xf3\xe9\x89\xe7\x26\xee\x69\xbd\x5c\x54\xca\xd3\xa6\x82\xba\x04\x5b\x2b\xe7\x23\x5d\xdd\xba\x14\x3a\xd8\x5d\xd4\xda\xf3\x5f\x1b\xbc\x24\xa2\x32\x68\xb0\x5c\x16\x79\xdf\x95\x14\x12\x5f\x4e\x80\x55\xb1\x3b\x32\x97\x16\x0d\xaa\x74\xab\x0e\x6c\x13\xd1\xae\x90\x1d\x9b\xae\x28\x5a\xbf\x69\x33\x57\xfe\xb9\x4f\x1e\x13\x2b\xb6\x60\xc9\xb9\x9c\x54\x64\x47\x8b\xc0\xcd\x60\xf6\xf0\x94\xb4\x0b\x2a\xdd\xe7\x2f\x07\x88\x5d\x69\xd2\x65\xdd\x4a\xae\xa8\x4d\x25\x62\xc8\x85\x38\xc7\x84\xa5\xc3\x3c\xd6\x97\x8d\x91\xe5\xec\x59\xed\xcc\x9f\xf1\x0b\xa0\x22\x7f\xb7\x0d\x71\x30\xf7\x66\x79\x3c\xb4\x22\xba\xd9\x1a\x4f\x2a\xc8\x42\x82\x4f\x22\xaf\x6e\xe1\xf6\xc3\x1a\xb9\x96\x8d\xb3\xd6\xfd\x49\xf9\x75\xe8\xf4\xbf\x2c\x58\xd4\x79\xc9\xbc\x5d\xbf\x14\x5a\x59\xed\xd9\xe8\x48\xe7\x98\xb3\x63\x5a\x3c\x4c\x75\x38\x25\xae\x9b\xde\xbb\x2e\x78\xaa\x9c\x9c\x59\xa0\xb2\x7f\x8a\x25\x1e\x7b\x1d\x1a\x3a\x1d\x19\xe6\x59\xfc\x20\x4e\x6c\x30\x93\x3a\x57\x4c\x3a\x09\x11\xe9\xd2\x1c\x42\xb3\x76\x05\x64\xa3\xe7\x82\x85\xf6\x1f\x6e\x95\xce\x47\x0b\xbd\xe1\x4e\x8e\x5b\x65\x8d\x1a\x0a\x68\xd0\x78\xeb\x3a\xa7\xae\x9e\xbf\xaa\x6e\x9f\xb9\x23\xcf\xdb\x69\xdf\xba\x32\xae\x11\x7b\x2b\x58\x05\xa4\xc3\x24\xfa\xcd\xa5\x8d\x37\x79\xee\xe8\xe5\x64\xbf\x07\x2f\xdd\x9e\x45\x72\x55\x82\xf1\x2e\xf1\xd0\x16\xb0\x0c\xbe\xd6\xa6\x83\x08\x9f\xed\x18\x5f\xdb\x2f\x19\x45\xd9\x73\x34\x80\xbf\x09\xc9\x85\xd0\x3d\x5a\xe6\x37\xf5\x3d\xd3\xb4\x06\xcc\x35\x0d\x65\x3d\x26\x9d\xc6\x30\x28\x35\x91\x7a\x0e\x6b\x52\xbb\x73\x09\xea\xbb\x64\xc7\x02\x72\xfd\xe3\x35\x75\x20\x88\x11\x65\xb6\x1a\x1f\x8c\x9b\x7a\x4f\xe0\x7e\xd2\x6b\xbe\xc8\xa5\xf9\x40\x3c\x9a\xeb\x22\xd5\xf6\xf6\x27\x43\xbd\x14\x34\x65\xd9\xd1\xbd\xf5\xfc\xbf\x4e\xde\x0c\x3b\x84\x40\xf4\x2f\xd4\x43\xc3\x5d\xe0\x35\x13\xc5\x0d\x15\xd8\xfd\x87\xba\xb1\xa5\x36\xe1\xd8\x39\x0a\xe8\x68\x5e\x6e\x45\xa9\x85\x2c\xc2\xdb\x93\x72\x44\x7d\xdc\x21\x01\x94\x7e\x05\x4b\x30\x0c\xff\x5c\x37\x5e\xe5\x76\x96\xca\xc3\xbe\x2f\x2d\xa1\x75\x0b\xe8\x6c\x51\xa4\xc9\x06\x39\x1c\x62\xcd\x6e\x71\xb0\x10\xef\x44\xa1\x83\x65\xfd\x94\x5c\x94\xb5\x9c\x07\x6b\x26\xcf\xb2\x2e\xfa\x77\xcf\x59\xb8\x30\x7b\x16\xe6\x1b\xc3\x5a\xae\xb5\x91\x71\x8c\xc8\x9f\xa0\xb4\x85\xab\x1f\x3b\xb3\xe7\x3c\x48\x4d\x96\xbf\xf5\x89\x32\x23\x2b\xee\xe7\x40\xe6\x09\x5c\xa5\x78\x2c\x8c\x73\x1c\xed\x8e\x64\x94\xca\xed\xa7\x2a\xf8\xe4\xd5\x7e\xed\x01\xf7\xc1\x13\x41\x4f\x60\xad\x83\x79\x2b\xf8\x7b\xfd\xba\x23\x03\xba\x68\xcd\xd2\xe8\xbe\x7d\xf5\x68\xaf\xcc\xfd\xe2\x24\xe6\xae\x5b\x93\xd7\x42\x92\x97\x53\x72\x18\xfc\x69\x78\x0f\x8b\x3f\xbf\xd9\x08\xac\x0d\x8b\x66\xc4\x3e\xfe\x8a\xb2\x0b\x87\x84\x42\x5b\x3e\x1b\xa8\x70\x14\x78\x63\x64\x23\xd7\x3e\x58\x34\xa9\x37\x03\x6d\xcb\xaf\xc6\x6d\x2d\x39\x29\xb5\xc5\x7b\xf9\xbb\x84\xf1\x06\xac\x00\x7d\xa4\xe5\x15\xf3\x2b\xc4\x66\xd9\x4d\xdd\x50\xa5\xf4\x03\xe5\x7f\x2c\x64\xdf\x00\xcf\xfa\xf3\x79\x03\x04\xaa\x8a\x39\x6a\x21\x0c\x56\x49\xda\xa0\x8a\xae\x75\x1b\x92\x90\x2c\xd4\x07\x90\xf7\xb6\x17\xc3\xbf\x54\x13\x76\x27\xfd\xbf\xb4\x6a\x43\x98\x26\xfa\x70\xc6\xe5\x6a\x1b\x29\xf6\x95\x73\x68\xd6\x5d\xaf\xe0\x75\xd6\x28\x24\x7a\x71\xdc\xeb\x8c\x95\x3e\x87\x60\x04\x8f\x62\xab\xda\xa5\x3f\xe4\x2f\x58\x31\xb1\xb7\x66\x96\x6a\xb4\xf5\xeb\x46\x38\x35\x0a\xa9\x5d\xe4\x4e\x24\x5f\x2f\x8d\x47\x49\xdd\xfa\xa3\x2e\x6c\x03\x1b\x39\x05\x72\x0e\x1f\x2e\xd7\x28\x88\xdb\x46\x51\x4e\x45\xac\xde\x09\xe4\x61\x95\xf5\xed\x32\x86\x87\x1e\xae\xa8\xb5\x13\x21\x59\x7b\x47\x6d\xc0\xa6\x68\x9f\x59\x15\xe9\x42\x67\xb7\x2b\xdc\x05\xbb\x72\x7b\x1b\x73\x6d\x44\x95\x5e\x84\x95\x63\x36\x27\x00\xd7\xf5\x1b\xc6\xe9\xb0\x8d\x98\x19\x60\x48\xc4\x3a\x02\x62\x5f\x60\x94\x32\xff\x09\x13\x43\x92\xb5\x51\x4a\x0d\x9e\xb1\xcd\xb1\x5b\xfe\xf9\xb2\x47\xa4\x70\xa9\xfa\x77\x09\x6a\x31\xd2\x4a\xbe\xcc\x32\x89\xb0\x48\x96\x29\x57\xfe\x27\x08\x40\x0e\xcb\x45\xa0\xa1\x7d\xb9\xba\x68\xe6\xe5\x69\x5d\x16\xc2\xf3\xd8\x88\x7d\xd0\x63\xe5\xef\xcb\xc9\x86\x39\x2a\x80\x97\x51\x04\x70\x1b\x42\xbf\x9b\x59\xa0\xb5\x2e\x1d\xa3\xda\x48\xc4\x6b\x4b\x46\xfb\x27\x49\xde\x9e\x02\x34\x80\xaa\xaf\x25\x0f\x37\xed\x55\x15\xef\x3d\xf0\xb6\x4e\x31\x1e\xee\x45\x3b\xb4\x21\x85\x3b\x16\x46\xe1\x1a\xa3\xdf\xa5\xf9\x17\xe6\xb6\x67\xb2\xc9\xab\x88\x08\x97\x3b\x2a\x7f\x14\xe1\x61\xd0\xea\xf4\xf0\x43\xa7\x77\xe6\x33\x65\x7d\xe0\x20\x0b\x43\xd5\xcb\x4f\x49\x01\xbb\x76\xee\x57\x3c\x77\x91\x71\xe1\xd9\x87\x50\xee\x58\x39\xdc\xf7\x8a\xba\xbc\x11\x63\xea\x70\x25\x3d\x80\xe7\x9b\x4f\xcc\x59\x9f\xf2\x23\x8c\x5e\xff\xac\x4c\xe5\x9d\x35\x3c\x35\x4e\x3a\xfa\x63\xbc\xc6\x2d\xc9\x50\xb5\x65\x50\x54\xcf\xd0\x61\xb3\x80\x2c\xe3\xd0\xc7\x80\x17\x62\x57\x64\x8b\xf8\x96\xa9\xaf\x45\x81\x41\x02\x2b\x17\x93\x0a\x39\x21\x92\x46\x5c\xae\x8c\x59\x98\x17\xcb\x8b\x37\xd1\x60\x37\x47\xb1\xbf\x74\x22\x9e\x53\x73\xd6\xbf\x9e\x65\x72\x7e\x36\xfd\xdb\xb9\x39\x1a\xce\xbd\x88\x11\x67\x54\x80\xcf\xfc\x71\x08\x0b\x50\x89\x82\x02\xe4\xf9\x6e\xc6\x86\xfb\xc0\x55\x2e\x09\x06\x1b\xc3\xb9\x57\x10\x1b\x87\xa8\x6f\x4e\xaa\x9b\x5f\x2a\xc7\xdf\x93\x17\xd0\xc1\x6b\xd6\x4f\x4d\x9b\xd0\x03\x09\x63\x0c\x0f\x46\x55\xe2\xf1\x18\x40\xc6\xe3\xd6\x94\x41\xb1\x22\x76\xa5\xae\xdf\xe9\xf7\x03\x95\x78\x49\x10\x1f\x00\x8f\xa9\xa8\x5c\xcf\x81\xaa\xbc\x75\xdb\x58\x31\x3a\x6a\x54\x8c\xab\x28\xbd\x77\x08\xd1\x9e\x9f\x77\x47\xb6\xa0\xd3\xa4\xfc\xb0\x80\x82\xbe\xa4\xbf\x6b\x27\xe5\x69\x99\xa3\x54\x32\x3a\x8f\x36\x67\x3e\x7c\x76\xeb\xbb\x16\xaf\x3c\xb0\x94\xcf\x77\xc8\x35\x7a\xfd\xcc\x66\xcd\xaf\x0e\xf8\x16\x73\x14\x72\xcc\x1a\x3f\x1d\x73\xa4\x64\x8f\x39\x0c\xef\x2d\x62\x71\x9e\x08\xbb\x63\x1e\xa9\xa7\x64\xbd\x92\x18\x94\xa8\xdb\x13\x40\x2e\xd6\x73\x54\xec\x27\x78\x60\x23\x7e\xac\x55\xb6\x9d\xc7\xc3\x06\x19\x2a\xcb\xb9\xba\x6f\x27\x9a\x75\xd0\xa1\x51\xd3\x17\x42\xc0\x9e\x0f\x9d\x8c\x5b\xdb\x69\x5d\x69\x6c\x69\xe1\x37\x0e\x0e\x97\x6d\x41\x52\x22\xc8\x55\xc1\x99\xde\xf7\xf7\xab\x71\xaa\x77\xda\x32\xa2\xc5\x90\x1e\xca\xd1\x20\x02\x83\x34\x67\x9d\x53\x7d\x29\x10\x85\xe5\x48\x02\x40\x48\x78\xf4\xb0\x71\xfb\xc6\x8d\x8b\x80\xa7\x30\x65\xb4\x4e\xa2\x13\x78\x60\x67\xe5\xee\xb0\x31\xb0\xdf\xb6\xf2\x49\xde\x75\x94\xd7\x4e\xfc\xbd\x8b\xff\x12\xf5\x69\x37\x92\xcf\x75\x51\x26\xc1\x75\xaa\x1c\x21\xa0\x9e\xb4\x2c\xac\x3d\xc1\xff\xc9\x7f\x42\xc9\xd4\xee\xdf\x09\x26\xe0\xfd\x44\xfd\xdf\xbb\x04\x04\x1c\xad\xed\x25\x5a\xb5\xbd\x74\x9c\xd2\x58\x47\xf6\x2a\x6a\x6a\xdc\xa6\x91\x7c\x67\xbd\xaf\x7b\x56\xf2\x66\xcf\x71\xd4\xa4\x67\x0a\x22\x1d\xd2\x0a\x4e\x2c\x97\xd7\x4b\x15\xed\x2a\x9d\x0f\x57\xf8\x3c\x19\xec\xc1\x90\xb6\x7e\x44\x25\x7a\x87\xb5\x4f\x94\x53\x2d\x52\xef\xb0\xa0\x0b\x2a\x35\x73\x2f\x5e\xc2\xcf\xdf\x7a\x7c\x55\x8d\x3e\xbf\x8f\xf0\x32\x2c\x54\xc0\xd9\x8a\x44\xb7\xb7\xa2\x1b\xb4\xd1\xc5\x66\x43\xeb\x1b\xe9\x3e\xfb\xf0\x2d\xca\xce\x67\xab\xda\x41\x29\x58\x72\xc0\x3b\x0d\x0d\xec\xe5\xf4\xf7\x74\x03\x0a\x99\x95\xfc\x25\x26\x16\x20\x50\x8b\x77\xb6\xe1\x2e\x90\x38\x6d\x4f\xa5\x34\x8e\x6d\x60\x55\xb4\x4e\xc5\xef\xbc\xee\x6f\xd6\xee\x07\x11\xa0\xa5\xc8\xbe\xf5\x4f\x52\xc5\x31\x5b\x3d\xa9\xc3\xef\x71\x68\xfa\xd6\x3e\x45\xa1\xbd\x95\xca\x97\x39\xe8\x57\xce\xb5\xde\xc5\xa3\x76\x27\x48\x8f\xc6\xb3\x10\x3d\xd0\xbb\x5d\x43\x93\xff\x5d\x53\xc0\x0a\xfa\x71\x7e\x46\xa9\x7f\xb4\x91\x44\x28\x01\xf7\x35\x0a\x65\x1e\x2b\x38\xdf\x00\xfb\x31\x2e\x5f\x45\x5f\xeb\x31\x1b\x43\xdb\x7e\x56\xec\x96\x36\x6d\x60\x17\x4e\xf7\x04\xae\x89\x73\x96\xa3\xa6\xcd\x92\x55\x5a\xb7\x97\x97\xd3\xb0\x2d\x51\xfa\x45\x9e\x9c\xe9\x0a\x17\x49\x2f\xeb\x33\x6a\x0c\x70\x8c\xfa\x57\x56\x02\x11\x0b\xb5\xbc\x01\xa3\x24\x0d\x72\xc0\x13\x78\xad\xd2\x2c\xbc\xce\x06\xe7\x0a\x21\x0b\xb2\xd8\xdc\x83\x1a\x35\x28\xf5\xca\x41\x06\xda\x4d\xc4\xee\xa3\x80\x1f\xec\x70\x66\xda\xd7\x37\xe7\xf4\x28\xd5\x3b\x09\xcf\x63\xa7\x63\xaf\x75\x91\x69\x65\x15\x95\xd8\xda\xf2\x25\xc7\x00\x75\xad\x6e\xab\xa1\x61\xe5\x5a\x9d\x9e\x63\x0b\x15\xa4\xad\x77\x22\x95\x98\x72\xbf\xe4\x5a\xbf\x72\xd4\xfd\x43\xe0\x57\xa6\x8e\x6b\x71\xc7\x5b\x8f\x68\xe7\x0c\x14\x26\x39\xd6\x4f\x95\xb1\x67\xf9\xc2\xac\x52\xf1\x41\x02\x40\x45\x6c\xf8\x65\xbe\x7e\x1a\x3e\x40\xf0\x00\xd1\x95\x67\x9c\xa7\x28\xd4\xfe\x73\xf2\xb5\xcf\xe1\x22\x02\x99\x71\x12\xa8\xf1\xd2\x91\x04\x4d\x02\xdc\x1a\x45\xd5\x15\x9c\xa6\x9d\xc1\xb6\xd4\x89\xf4\xe9\x38\x56\x5e\xb8\x53\xe0\x84\x6d\x58\x7f\xfd\xf1\xd0\x64\x21\x1d\x52\x33\xd2\x81\xe1\xe7\x71\x8a\x82\xc6\xea\x88\x45\x95\x21\xfd\xc3\x7e\x85\x5e\xcc\xea\xd9\x47\x15\xf6\xcf\x22\x75\x65\xb4\xcd\x39\xa2\xfe\x2b\x20\x7c\xe4\xf7\x29\x92\x2f\xa4\xfa\xce\xa0\x4c\x8b\xdb\x2d\x54\x9a\x1d\x5b\x87\x79\x00\x73\x58\xe6\x20\x4a\x27\x51\xb2\x21\x2b\x48\xe8\x81\xeb\x47\x79\xb3\xb2\xbc\xa5\xff\x0b\x15\x61\x31\x8f\xc1\xf7\xf6\x5a\x73\xcd\x7c\x87\x9d\x24\xdd\x74\x80\x91\xc3\x0d\xc8\x0a\x3f\x10\x00\x20\xec\xc7\xe2\xb5\x44\xdf\x9f\x12\x70\xb6\xe8\x3a\x7e\x93\xe5\xd9\xb4\x9c\xe2\x11\x2c\x25\x30\x31\x16\xa5\xe5\x4b\xae\xbe\xe8\x9d\x59\x0e\x0e\x64\x96\xb2\x2f\x85\xd0\x80\x7c\x08\x60\xb9\x34\x89\x1e\x44\x3f\xce\xbf\x76\x1c\x07\x14\x8c\x1d\x88\xeb\x44\x6c\xdf\x1d\x19\x64\xd5\xfe\x77\x7e\x03\x39\x3e\x0f\x12\x7d\x42\xe7\x56\x43\x5c\xc8\xa1\xc0\x38\x38\x4a\xfa\xe7\x12\x35\x4d\x8b\xfb\x49\xf3\x92\x25\x06\x54\x78\x31\xf9\x8b\x71\x0d\xf4\xe2\x2f\x21\x16\x60\x81\xd0\x0d\xa8\xcd\xc8\xea\x34\x2c\x5f\x17\x48\xc8\x24\x05\x3e\xb2\x70\x88\x00\x4b\xfd\x67\xe6\xb8\x65\xc9\x8d\xf0\x1d\x2f\x06\x1a\x52\xcc\x5b\x5e\x3f\xc2\x0b\x08\x2e\xb0\x46\x4a\x76\xc9\x1a\x34\x81\x0b\x2e\x11\xe6\xca\xe1\xcd\x22\x09\x80\x25\xd8\x45\x8b\x94\x1d\x17\x66\xea\xac\x71\xf8\x94\x3f\x3a\xcd\xfd\x67\x0b\x19\x3e\x00\x07\xfc\xc6\xfd\x96\x33\xca\xa9\x36\x15\xf4\x44\xd7\xaf\x4d\x28\x73\x6c\x97\x01\x9f\x3e\x29\xdd\x7c\x4a\x4d\xee\xd7\xc6\xa6\xc3\x27\x70\x25\xb0\x06\x72\x77\x51\xf9\x7f\xd9\x3c\xd6\x7d\xa4\x9c\x5a\xbe\x39\x59\xcb\x09\xe7\x12\x39\x95\x46\xf0\xbb\x09\xfa\xbe\xd5\xd0\x4c\xef\xe0\xd8\x4f\x50\xd0\xf5\xe5\x1e\x92\xce\x91\xfa\x98\xaa\x2b\x74\x6b\x8f\x02\x00\x9f\x9c\x4b\x6f\xc1\x05\xc4\xb2\x26\xfc\x61\x2a\x02\x1e\x4c\x2b\xc1\x08\x83\xe4\x9b\x6d\x1c\xc1\x3c\xd8\x34\xff\xfb\x8a\x85\x4e\x36\xc3\x76\xd7\x16\x0b\xbc\xee\x03\x59\x37\x02\x8d\x26\xd8\x15\x84\x2d\x01\xca\x1b\x61\x62\x3a\x46\x59\x3e\x9f\x5f\xde\xf9\x99\x04\x50\x80\x6e\x80\xa6\xb3\xfc\xb0\x70\x5b\xc9\x01\xca\xb1\x54\x0e\xaa\xf9\xaf\x7b\xe9\x18\x0e\xa5\xf3\x25\x7c\xc1\xdc\x38\xf1\x74\xa9\x9d\x32\xf5\x14\x26\x9f\x5a\xfa\x9a\xf4\xb2\x19\x1b\xcd\x57\xd1\xb4\x49\x64\xb9\x86\x02\xb3\xcd\xff\xc9\x2f\x0f\x9b\xb1\x89\xb6\x8e\x13\xdf\x1d\x64\x9a\x88\x7c\xb7\x48\xe7\x94\xc8\x1b\xb7\xa5\x68\xe8\xdb\xe9\xf3\x1c\xa8\x32\x37\x68\x03\x21\xa9\x8e\x50\xe8\xaa\x58\xee\x1d\x29\x30\x76\xc7\x3f\x03\x3d\x4b\x09\x59\x1b\x6b\x02\x29\x94\xe9\xd5\xf1\x6c\x62\x65\xa3\xcd\xce\xfc\x30\x6e\x53\xaa\x4c\x9d\x13\xd1\x7d\x19\x12\xdc\x22\xa4\x4b\x9a\x39\x7d\x98\xe8\xb4\x48\xb5\x60\x8b\x82\xa2\x3c\x86\x71\x61\xe8\x2e\x0b\xf5\x60\xcd\xb5\x9f\x59\x99\xf8\xf9\xf1\xd8\x25\xcf\x2c\x3b\xac\x71\xbe\x45\x5e\x0f\xf7\x09\xe0\x22\xde\xe1\x5c\x6a\xaf\x66\x09\x5f\xd3\xc6\x91\x03\x5c\xc2\xff\xe9\x0c\x90\x2a\x4f\x6f\xce\x5d\xec\x2e\xe8\x02\x0a\xe9\xbe\x3c\xed\xb7\xfa\xf4\x1b\x79\xef\x3d\xd0\x13\x9a\xf7\x8c\x59\xed\xf5\xc8\xe2\xd5\x88\x11\x4b\x90\xd5\x6f\x4a\x6e\x00\x37\x11\x66\xa9\x1c\x60\x80\xda\xae\x23\x21\xfb\x28\xcc\x05\x06\x9b\x52\x1a\x1a\xd3\xa6\x63\x6c\x9a\x4a\x8e\x2e\x44\xe4\x01\xe4\x7b\x44\xa4\x4f\x0e\x21\xa8\x85\x4c\x75\xcf\x97\xbd\x04\xfe\x7a\xd8\x24\x80\x1c\x71\xeb\x2f\x58\x2f\x0b\xe5\xdd\x49\x00\x87\x72\x6a\x68\x4c\x5d\x0f\x79\x2e\x3e\x30\xa2\x78\x47\xe0\xcb\xcc\x09\xeb\x23\x54\x66\x1e\x71\xb1\x1f\x48\x61\x2b\x1d\xfc\x98\xed\x66\xdf\xfc\x7a\xa4\x08\xe7\x63\x6e\x10\x89\x39\xf0\x6b\x0f\x55\x5b\x1e\xe9\x25\x17\xd6\xf4\xea\x28\x19\x02\x02\xbb\xd4\xa6\xc3\x23\x0c\xa8\x88\x91\x80\x0a\xeb\x05\x9a\x07\x6c\x9a\x66\x22\x25\x3a\x39\x90\xe5\x67\x78\xe1\xe6\x7a\xf3\x2d\xcc\xd7\x14\x0f\x6c\x96\x15\x61\x3e\x94\x1f\xcf\x10\x51\x0b\x49\x62\xa4\x52\x56\xc9\x43\xe5\xed\x7a\xa9\x8c\xd2\xe0\x46\x8e\x96\xe5\x30\x36\xab\xa3\xc9\x0f\x6f\x73\x72\xf3\xd5\x42\x99\x92\xb7\x2c\xf7\x02\x67\xf4\xf0\x46\xa6\x04\x58\xee\x02\x37\x93\xd3\x39\x65\xf1\xa8\x05\x03\x1b\xde\x2a\xa8\x0c\x6f\x14\x5e\x11\x40\xb4\x91\xb5\xf9\x3a\x11\xde\x60\xef\x30\x39\xf0\xb5\x3b\x03\xe1\xc0\x11\x39\xdc\x58\x45\x98\x7f\x73\xf1\x12\xc1\xfd\xcc\xcd\x71\xf5\x99\x08\x7e\x38\x75\x01\xa1\x21\x4d\x85\xe5\xb2\xf3\xfd\x71\x2e\xbd\x52\x89\x43\xa1\x34\x74\xc9\x37\x9b\xe8\xa1\x10\x84\x66\xdd\x4f\x27\x29\xe8\x66\x8f\x0f\x54\x6b\x42\xf3\xff\xfe\xfb\xc1\x63\xb1\xe6\x75\x16\x73\x8e\x52\x00\x1e\xf2\x31\x8b\x7b\x2f\x2c\xfe\x80\xe7\x32\x09\x72\xe1\x3a\xd3\x24\xcf\xef\x41\x78\xdf\xde\xe2\xb4\x37\xe6\x3c\xdc\x6d\x08\x65\x58\xe7\x60\xf2\xdb\x10\xb2\x12\x19\x31\x33\xdf\x3b\x64\xb9\x62\x0e\xd9\xa5\x76\x15\x52\x90\xf6\xc7\xf1\x0a\xa8\xf5\x1d\x6c\x02\x07\x3c\x77\x42\x2e\xc8\x00\xd7\x1a\x5a\xc9\xe2\xc3\xe3\x95\x6c\x34\x9b\x01\x84\xed\xbc\xbd\x64\xd0\xd6\x66\xd4\xb0\x0d\x60\x28\xb0\x7e\x5c\x9d\xb0\xce\x70\x3b\xae\xaf\xcd\x2b\x89\xf3\xa2\xc1\xf6\x67\xfd\x48\xa3\xda\x46\x5d\xf2\x7a\xe9\xcf\x39\xee\x88\x85\x1b\x97\x59\x48\x25\x8b\xb4\x4c\xef\x90\xe5\x23\xd0\x41\x06\xad\x6f\xca\x53\xd7\xd3\x0d\x59\x33\x3f\x3c\x12\xbf\x3c\x9d\x45\x52\x18\x1f\x1c\xd2\xd8\xbc\x2d\xa0\x31\x7d\xa1\x58\x6c\xcf\xd9\x03\x64\xab\xfd\x39\xe8\x51\x09\xdb\x03\xb2\xf0\x54\xd9\xc6\xc2\xf0\xcb\x06\x6c\x01\xb9\xaa\x3d\x90\x0b\x30\xc5\xfd\x83\x43\xe0\xa4\x15\x67\x44\x06\x73\x3f\x85\x8d\x54\xaf\x17\xd0\xf1\xde\x3b\x8b\xd1\xee\xfe\xba\x33\x4b\xe3\x40\x01\xe1\x03\xce\xca\x9a\x50\xef\x77\x4b\x65\xfe\xa3\xa9\x59\x7b\x96\x86\xe5\x79\xdb\x99\xb5\xf8\xbd\xd7\x76\x4c\x41\x73\xc3\x35\x76\x66\xb9\xda\x86\x3f\xe1\x5d\x5a\xcf\x4e\x33\x8a\xae\xae\x0f\x55\xd7\xe9\x81\x5a\x87\xef\x7c\xc7\xc5\xa6\x59\x23\x57\x51\xde\xc5\xc6\x55\x51\x2f\x83\x35\xde\x8d\x94\xde\x2f\x4d\xa1\x7a\x1e\x9b\x9b\xab\x3c\x4a\xec\xa5\x6e\x52\xd5\x7c\x12\xbb\xb3\xd9\xb1\xd6\x7b\x1e\x49\xb9\x3f\xa3\x44\x7c\xd2\x03\xb1\x49\x22\x43\xec\xdf\x8f\x5d\x84\xa0\xeb\x6c\x28\x29\x8e\x7d\xa1\x88\x76\xd1\xe0\xae\x53\xeb\x8e\x1c\x6e\x24\xdc\x1c\x45\x11\x37\xdf\x3e\xf0\xbf\x95\x66\x9e\xaa\x79\x4d\x57\x68\xfb\xd4\xc1\x62\x5c\xff\xb9\xf8\x58\xca\x23\x6b\x3f\x68\xdd\x0a\x49\x2f\xd6\xec\xa3\xd3\xb7\x48\x06\x37\xac\xd5\x33\x61\x05\xa9\xeb\xa8\xda\xfb\xb5\x9d\x9b\x02\x34\x87\xa0\xd7\x4a\x7a\x7b\x1a\xe7\x22\x02\xba\x06\x8f\x18\x59\xaa\xf6\xec\x0a\xd8\xca\xab\x39\xc9\x5d\xb5\x7c\x49\x65\x50\x04\xfb\x87\x25\xfd\x28\xce\xef\x03\xc6\x92\x1e\xae\xb7\x0d\x70\x78\x9c\x20\x2b\x76\x5f\xdb\xd8\x3f\x30\xc9\x2e\x8f\x84\x06\xa4\x37\xeb\xe3\x9d\x75\xf0\xce\x86\x0f\x30\x0b\x04\xaf\xf5\x4e\xa8\x81\x11\xe3\xbe\xb5\x36\x5e\xcf\x2f\x52\x2f\x4f\xe7\x92\x54\xe4\x97\x79\x6d\x0a\xae\xbe\x8c\x50\x3b\x97\x69\xf0\x6b\xea\xb8\x92\x60\xd4\x87\xce\x36\x2d\x9e\xba\x06\x8c\x00\x83\x86\x47\xb4\x3e\x9e\x5d\x75\x87\x2e\xf2\x74\xd3\xd6\x37\x2d\x50\x43\xf2\x0e\xda\xd7\x58\xbc\x44\x8b\x87\x0c\xf2\x8f\x83\x05\x1a\x99\x25\xb9\x17\x9f\x98\xe9\x55\x7a\x30\x90\x5c\xf1\x05\xc6\x11\xaa\xa3\x87\xef\xa9\x5d\x00\x8e\x85\x5d\x48\x3e\xe6\x0d\x18\x43\xfa\x7f\x3e\x77\xb9\xe9\x41\x67\x77\x24\x32\x25\xf1\x71\x44\xb9\x83\xdb\xf4\x60\xf1\x72\x76\x9e\x1c\x3d\x4d\xfa\x7d\x58\x42\x03\x6a\xc0\xa3\x6d\xef\x7f\xbe\x98\x03\x6f\xc0\xd7\x19\xe8\x08\x19\xd6\x1e\x0d\x36\xc0\xe5\x4c\xea\x69\x9a\xf5\x6c\xa4\xf1\xb6\x3e\xe4\xf0\xc8\x6e\x2b\x87\x12\xc8\xef\xf8\x12\x8e\x89\x7e\x60\xf8\x5a\xc9\xa2\x56\x4b\x20\x72\xfc\xda\x27\x3e\x5b\x42\x6e\x42\x64\x3b\x88\xf8\x23\xd9\xfd\x7a\x01\x3e\xae\xd2\xb4\x2a\x22\x70\x60\xfb\xf8\x73\xf0\x61\xf2\xf5\x5d\x4f\xa7\x0d\xd9\x92\xd7\xd9\x9e\xb2\x85\x3d\xe8\x3b\xab\x9c\xfd\xce\x29\x40\x05\xe7\x17\x5d\xe0\x8b\x89\x0b\x76\x5a\xb6\x74\x5b\x09\xf4\x51\x4d\xfd\xd0\x55\x71\x14\x7c\xeb\x67\xaf\xf2\x7b\xf7\xd4\x5a\x7f\xed\x2e\xcf\x46\xe6\xfe\x2c\xed\xee\x5d\xb4\x65\x8b\xe4\x1b\x3b\x87\xbe\xb6\x17\x5f\x9c\x45\xef\x0f\x1b\x01\x0a\x28\x93\xf9\x95\x79\x21\x23\x41\x2c\x02\x26\x66\x12\xe7\xde\x6f\x3d\x01\x2f\xa7\x65\xff\xd0\xb0\x96\xae\x2d\xfc\x3f\x6d\x68\xfd\xca\xb1\x26\xf9\x4c\xec\xe5\xaf\x19\xc5\xbc\x1b\xd2\xe3\x95\x54\xa7\x7a\xa5\xc6\x14\x02\x0a\xc1\x2b\xfa\xd6\x2a\x90\xa8\xbf\xb2\x5a\x42\x79\xee\x70\xa7\x85\xcf\x79\xd8\xd6\xf2\x3f\x41\x2f\x50\xd6\xb4\x73\x62\xfe\xea\x89\x5f\xb1\x08\x80\x00\xa2\xf3\xc8\x90\xc0\x83\x73\x2a\xd2\x16\x7c\xa2\xf0\xa4\xa3\x39\x0c\xc1\x37\x88\xa2\xe2\x13\x5a\x52\x00\x3a\x30\xeb\x0b\xe3\x5b\x5f\xd8\xcc\x4d\x4f\xa2\xc5\xcf\x52\xce\x49\xfa\xde\xfb\x24\xfc\xba\x6b\x04\xbc\x03\xb2\x60\x73\x91\x52\xa4\xf7\xed\x48\x1b\xc9\x41\x3d\xc3\x54\x13\x58\x53\x29\x8b\x43\xb1\xc4\x96\x35\x14\x8d\xea\x79\x39\xda\xa9\xa2\x46\xe6\xc1\xa1\x9c\xca\x5d\x05\x7f\xbd\x83\x5a\x67\xc1\xde\x69\xa8\x68\xb1\xdf\xf7\x1b\xf2\x35\x8e\x1d\xe0\xb4\xf1\x46\xd5\x90\xdd\xa5\x8d\x81\x8f\x4c\x91\x80\x12\x39\x68\xd8\xe8\x36\xf3\xdc\x46\xa0\x77\xbc\x19\x64\x46\x7f\xa4\x3b\xee\x4f\x08\x64\xc7\x6b\xfe\x09\xfd\x71\x04\xe5\x22\xac\x21\x39\xac\x20\x6a\x67\xb7\x8b\x1f\x13\xe6\xb0\x95\xdb\x1b\xd7\x7b\x16\x0d\xc7\x66\x5b\xfc\x6a\x0a\x87\xe6\xdb\x39\x06\x42\x12\xdf\x53\x16\x80\x21\xd2\x5f\x77\x5e\xea\xea\x1d\xda\x9d\x7f\x39\x0a\xb9\x95\x36\x93\x40\x80\xaf\x4a\xe7\xc1\x7f\xee\xe3\x3b\xbe\x4b\x30\xe8\x95\x5e\xc6\xf5\x71\x50\xdd\xf5\xb6\x43\x5d\x54\x02\x40\x02\x55\x86\xbc\x39\xb5\xfe\xe3\x72\xd6\xf6\xa2\x28\x56\x59\x13\xaa\xca\x79\xf5\x9f\x7c\x55\xaf\xf7\x7b\xe1\xb7\x52\xfd\x84\x58\x88\x61\xc8\x12\x21\xaf\x40\x34\x29\x54\x5e\x18\xf8\x06\x91\xf9\xad\x71\xfc\xf2\xfd\x0b\x07\xfe\x16\x08\xd0\x60\x8f\xc9\x24\x9c\xc4\x1c\x76\xb2\xb7\x3a\xfe\x0b\x4a\xee\xea\x05\xae\xdb\x26\x7b\x55\xd0\x07\x29\x86\xc3\x96\x42\x58\x87\x3e\xc6\xb7\x97\x74\x8b\xae\x5b\x19\x06\x0b\x94\xbb\xbd\x5c\xe7\x9d\x05\x7d\xf4\x5c\xf6\x12\xb0\xc4\xfd\x9f\x1b\x1c\xd0\x43\xf8\x38\x9f\xd2\x53\x87\x09\x69\x44\x3e\xf2\xb9\x8e\xa2\x5a\xfa\xc1\x79\xe8\x75\xb8\x42\xa8\x90\x14\xb9\xa9\x07\x90\x49\x86\x25\x53\x77\xd0\x11\x18\xb9\x1c\xf7\x1a\xda\x01\xd7\xd7\x4e\xf8\xe4\x8d\x2b\x9a\xd4\x21\x2b\xec\xb8\xa5\x0b\x0d\x23\x61\x07\x85\x33\xe6\x6b\xd7\xc1\xb7\x33\x2f\x64\xb5\x6f\x85\xed\x81\x8d\x4d\x42\x53\x00\x1c\x3c\x26\xe5\xed\x85\x24\xc5\x1f\x72\x9e\x0b\x83\x00\x16\x2c\xb3\x04\xe0\x97\xec\xa9\x1d\x94\xb4\x88\xcd\xb0\xe6\xf1\x62\x10\x2c\xfd\x39\x7e\xa7\x84\x62\xaf\x79\x13\x26\x66\xce\xe3\x1f\x11\x78\x39\x0d\xdb\x00\xbe\x51\xa5\xe0\xf2\x71\x84\x00\x7c\x49\x42\x73\xa0\x04\x1e\x70\x8e\x8d\xf8\xe8\x4b\xe2\xe2\xd7\x17\xe4\x30\xe5\x2d\xbc\x91\xa7\xac\xde\xef\xca\x1a\xa1\x5f\x98\x79\xf1\x44\x51\xe6\x22\x8c\xc3\xde\x20\x5d\x55\x81\xa4\xae\xdc\xf2\x2c\x2e\x60\x70\x46\xa0\x2c\x81\xc3\x38\x7e\x84\xbf\xc8\x57\xd3\x7b\x5f\x9b\x0a\x7c\x13\x44\x02\xe6\xa2\xfb\xca\x16\xa4\x80\x5b\x1c\x94\xe8\x00\x8e\x42\xcb\xd8\x21\x55\x21\x40\xfc\xa2\xd3\xbe\xd9\x3a\xf8\x59\x9a\xed\xc8\x37\x49\xd1\xfd\xf0\xd6\x9c\xd7\x21\xed\x5b\x58\x71\x59\xbc\xd6\x39\xa4\x0d\x6e\x2d\xc3\x84\x00\xee\x66\x5c\x47\x5d\xfd\xb4\x72\xf5\xc2\x6c\x3f\x54\x33\xfd\x12\xa4\xbe\x51\xf0\x60\x7c\x58\x37\x05\xb3\x96\x9e\x3b\x38\x4b\x50\x82\x4e\x6a\x72\xc1\x47\x40\x6f\x3e\x30\x14\x4d\xc0\x20\xf4\xeb\xe5\x62\xdc\xcb\xc5\x38\xe9\x71\xf6\x70\x6e\x2b\xb9\x6a\x0e\x3f\x64\xd9\x18\xd3\xea\x00\xca\x58\x7f\xcd\x92\xc1\x07\xf8\xa1\x34\x82\x30\xf1\xee\x32\xf4\x62\x20\x17\x74\x69\xc2\xa1\xc2\x10\x81\x6c\x98\x21\xbb\x42\x14\x46\x97\x2a\x2d\x90\x69\x64\x04\x55\x2d\xbb\x25\x0c\x25\xa5\x7b\x5a\x37\xaf\x94\x2c\x42\xb9\x1f\x4b\x79\xc5\xda\x2c\xf9\x20\xa7\x4b\x82\x08\x3b\xaf\x9a\x80\x64\x2e\xc5\x25\xf4\x85\xf6\xf8\x8d\x49\x18\x10\xfd\x42\xd5\x9d\x54\x5c\x75\xf3\x63\xff\x07\x89\xf2\xb9\x48\x86\xef\x9e\x31\x3a\x44\xb6\x3c\xea\xad\xde\xef\x60\x42\xe3\xc0\x45\xf2\x7a\xbf\xfd\x9c\x37\x83\xdc\xf4\x0f\xee\x00\x56\x74\x04\x49\xbc\x85\xa0\x78\x45\xc1\xd7\xc1\x14\x34\x5f\x3a\x50\x5a\xba\x25\x77\x20\x3e\xff\x51\x34\x25\x3d\xa0\xa1\xec\x4b\x02\xf1\xc1\x50\x65\x95\xe3\x98\x05\xa9\xd8\x35\xd0\x3a\xe0\x2c\x2d\x0c\xc5\x4a\xdc\xfd\xa1\x96\xda\x96\x49\xfa\xf3\x23\xd5\xb1\x80\xae\x68\xe5\x03\x48\xcf\x6f\x21\x53\x07\xb4\x85\xee\x2e\xf4\x11\x84\xe0\xb0\x77\xde\x2d\x53\x8f\x4c\x2d\x9f\xe3\xef\xee\x70\x49\xc6\x50\x85\x40\x0b\x81\x18\x60\x02\x16\x50\x8a\x43\x46\x66\x88\x74\xc0\xbc\x3f\xc2\x8a\xd9\xc6\x09\xf7\xac\xef\x63\x22\x75\x64\x2f\x7f\xfd\x10\x3b\xd1\xac\x8f\x6b\x08\xce\x23\x0b\x4a\x08\xc4\x45\x29\x87\x44\x3d\x2f\x17\x51\x60\x4d\x0e\x32\x2a\x0e\x44\xb1\x9e\x86\x57\x21\xf5\xed\x40\xb0\x73\x70\xcc\x83\x20\xfa\x58\xf2\xce\x94\xaa\xb6\xb4\x5c\x5f\x91\xf9\x2f\x92\x13\x4a\xb5\xbb\x38\x84\x65\x62\x6e\xbe\x50\x1d\x1a\xd1\x50\x5d\xea\x05\xf2\x09\xd2\x4a\x78\xb1\xb8\x08\xd4\xc4\x5a\xa5\xa8\xd0\x69\xfa\x63\x91\x57\x6a\xf6\x39\x66\x4d\x3b\xf2\x9e\x7a\x46\xf6\xb9\x13\xab\x62\xcf\xaf\x2e\x52\x71\x7b\xde\x88\x36\xdc\x33\x4a\xff\x81\x99\x78\x12\x7e\x81\x0c\x88\xb7\x1b\x16\xc5\xbf\x73\x38\x89\xf7\x88\x7b\x5a\x88\x7f\xb2\x20\x39\x3c\xc3\xe3\x66\x7e\x6c\xd3\xb7\x93\xa9\xd5\xad\x52\x43\xa0\x2a\xe7\xb1\x41\x32\xbf\xb1\x62\x70\x38\xd1\xe4\x8b\xf4\x9b\xb6\xa2\x0a\x52\xb3\x58\x26\x86\x62\xbf\xac\x35\x9d\x85\xb7\x50\xfb\x62\xd1\x6f\xe6\x52\x84\xed\xcd\xde\x2d\x61\x2e\x24\xcb\xb7\x15\x8e\xac\x80\xaf\xf0\xd9\xc6\x26\x19\x52\x2c\x57\x29\xd3\x53\xe0\x70\x0b\xc8\xd1\x36\xaf\xc2\x2b\x00\x4c\x44\xa1\x7d\xbf\x9e\x3c\x31\x4c\x3a\xbe\x2e\xbf\xf9\x82\x8c\x3f\x41\x15\x6e\x6e\x46\xa5\x83\xb0\xea\x71\x18\x06\x71\x15\x02\x98\x84\xb1\x2d\x3c\x9b\x2f\x2d\xfd\x57\xe4\x6d\x2b\x01\xca\xa0\xfe\xe4\x96\x03\x20\xb1\xff\x91\x3a\x40\x16\x4d\x18\x8c\x2f\xc4\x02\x05\x6f\x1a\x1f\xaf\xca\x66\x4a\xed\xfe\xad\x50\xba\xf4\x0b\xb8\x02\xda\x7d\xbe\x92\xa3\xd7\x2c\xe2\x0e\x63\x9d\x25\x7f\xe0\xa2\x00\x84\x6c\x3c\x52\xd3\x6b\xa5\x82\x42\x88\x32\xe4\xf5\x4c\x4f\x1e\x1e\x59\x5c\x3a\xcc\xcb\x83\x99\x91\xf8\x49\xef\xff\xf9\x14\x18\x8d\xaf\xb5\xdc\xd6\x77\xb9\x69\x2b\x10\x1c\x71\xbf\x09\x2e\xb1\x0e\x75\x9a\x73\x68\x26\xdc\x57\x65\x82\x7f\x83\xe8\x4b\x40\x35\xa6\xb7\x36\xb5\x07\x94\x2e\x2c\x5b\x12\x1b\xd1\x02\x69\x75\x24\x79\x20\x79\x97\x2b\x80\x06\x40\xcd\xfc\xd2\x22\x65\x75\x80\xdb\xc8\x94\xe7\xdd\xe0\x1a\x3d\x72\x27\x4c\x47\x19\xb4\x23\xef\xa5\x8c\xf2\x67\x08\x6b\x2a\xf4\x83\xb1\xc3\x1c\x9b\x49\xe9\x65\xb3\x01\x6e\xc0\x3b\x56\xaa\x01\x6c\x89\xe9\xe3\x0d\x09\x95\x4f\x6e\xb2\x0f\x33\x94\x51\x18\x82\xef\xfd\xeb\xd1\x28\x5c\xfd\x26\x99\xa3\x0d\xa0\x4c\x21\x50\xfa\xad\xa9\x55\x58\x2b\xd1\x84\x1c\x9a\x10\xc3\x3b\xa4\xe1\x2b\x51\xd5\x6b\x60\xb9\x56\xd0\x64\x7c\xb9\x7f\x88\xdb\x40\xf3\x24\x48\xf3\x5a\x1e\x77\x08\x8e\xaf\x25\x6b\xfa\xb4\x12\x47\xb9\x12\xff\x81\x68\xfe\x70\x5c\xb2\xba\xde\x88\xb0\x1c\x57\xbc\x20\xf0\x09\x6f\x01\x4f\xd8\x22\x8e\x80\x21\x19\x21\x34\x48\x08\x8a\xaf\xd0\xc9\x15\x52\x65\x26\x85\x7c\x9d\x25\xcd\xdf\x54\x1c\x6c\x28\xc0\x46\x7f\x9d\x9b\x19\xb3\xb3\xc5\x42\x14\x22\x4b\x46\xff\xaa\x9c\x4c\x00\xcf\x2d\x60\x87\x2c\xc0\xd6\x2c\x21\xeb\x95\xc6\x90\x74\x4d\x58\xf3\x10\xd2\xfa\x36\x13\xeb\xa1\xba\xea\x71\x55\x39\x91\x51\x13\x54\xb0\x2e\x73\x94\x72\xfd\x4e\x68\xba\x63\x36\x44\x49\x75\x2f\xe9\x5d\xb9\xe7\x35\x35\xfb\x69\x64\x5c\xf5\x3d\x99\x4e\xae\x84\x1f\xb8\x10\xbb\x73\xed\xdf\x86\x6b\x80\xdd\x72\x5a\x1a\xa4\xbe\x09\x43\xc8\x6e\x61\x79\x7b\xf6\xd0\x6b\xfc\x6f\xfe\xb4\xa5\xba\xe2\x8c\x47\x42\xe7\x2f\x62\x72\x2d\xb5\xff\x6a\x3d\x00\xae\xe2\x91\x0d\x41\x24\xbe\x80\x53\xc7\xb2\x7c\xc8\xe7\x86\x1c\x7e\x3f\x6b\x1d\xb4\x6e\x67\x45\x5c\x10\x0d\x02\xa6\xc2\xca\xa1\xa0\xc5\xd6\x7f\xf3\xa8\x7b\x61\x27\xbb\xec\x89\xf8\x8f\x0d\xb0\x13\x22\x32\xac\x09\x11\x14\x04\x9a\xb7\xc8\xf5\x71\x53\x18\x1a\xc4\x17\x59\xab\xd2\xdc\x09\x52\x71\xdf\x81\xda\x68\x06\xc8\xcb\x97\x5a\xbe\x34\x24\xd1\x02\x97\xfe\x29\xa0\x1d\xc2\x93\x83\xc2\xcd\xd3\x8f\xc7\xc8\xda\xc4\x99\x2b\xe6\x93\x9f\xb3\x4c\x00\x52\x75\x9c\x48\x88\x3c\xc3\xe3\x9a\xeb\x4f\x79\x96\x2c\xe9\xa8\x5c\x13\x53\xee\x25\xc9\xf7\x79\x49\x13\x87\x09\xbf\xf5\x0a\x75\x25\x10\x9b\x02\x40\x31\xed\xd7\x59\x07\x0f\x9b\x21\xcd\x2f\x44\xc2\xf0\xca\xfd\x3a\x9d\x5a\x3b\x65\x26\x48\x7f\xc9\xfd\xf6\x68\x08\x4a\xd0\x6f\x5a\x0a\x6e\xff\x7c\x69\x60\x0a\x79\x24\x02\x5e\xdd\xc8\x7b\xa6\x6c\x3f\xea\xe8\xec\x76\xa6\x37\xd1\x04\xf5\x9f\x4f\x8f\x3d\x7c\x71\x71\x4a\xe6\x72\xaa\x9b\x8d\x75\x3c\x18\xa7\xe6\x94\x1d\xb5\x09\x8b\xc6\x90\xf0\x67\x0b\x34\x35\xa7\x05\x1b\x63\x0d\xef\xe8\xf1\xe0\x95\x00\x00\x3b\xc1\x15\xd6\x7c\x34\x40\x07\x9e\x0c\x22\x30\xd6\xab\x11\xea\xdd\x11\x9b\x08\x8c\x06\x99\x01\x18\x43\x5f\xe6\x47\x44\xc3\x35\x08\xd2\xd1\xec\xb2\x7f\x8b\x84\xfd\x01\x49\x6d\x91\x2f\xc3\x60\xdd\x49\xd2\x52\x87\x08\xcd\xfd\xfc\xd6\xa2\x7d\x96\x5b\xf6\x18\x06\xd7\x3b\x50\x18\x01\xc9\x00\xf2\xa8\x79\x67\x0b\x1d\x92\xd7\x51\xf6\xd8\xae\x59\xe4\xca\x10\xd2\x88\x00\x1e\x24\x50\x1e\xb2\xca\x9a\x98\x24\x99\x32\x4d\xcc\x27\x32\xa0\x1a\x69\x0b\x73\x4c\xff\x3e\x52\xe4\x5e\x9d\xb2\x3b\xd0\x37\x98\xc6\x4a\x84\xc5\x1d\x86\xda\x17\xec\x96\x76\x85\x3f\x94\x8b\xf8\x08\xc5\x37\x25\x0d\x39\x26\x64\x26\x14\x8c\x9c\x6e\xa0\x3f\xe1\x9a\xc0\xcd\x00\xa4\xc1\x63\x6e\x49\xa9\xa5\x29\x32\xd8\x13\x14\x01\x7c\xd9\xe3\x65\x28\x42\x90\x74\x70\x80\xf4\x88\x42\x53\x70\x11\x28\x0a\x16\x59\x6a\xaf\xec\xc0\x31\xa2\x20\x72\xa2\xce\x6b\xc7\xe1\x95\x85\x52\x97\xa8\xa8\xc9\x7b\x55\xd5\xad\x06\xb8\x27\xaa\x12\x9e\xb5\x1b\x1d\xc6\xbf\x47\xa4\x89\xa9\xc5\x8e\x44\xb1\x25\x9d\xe0\x47\xa0\xf7\x7d\x49\xa4\x8c\x30\x1e\x39\xbc\x34\xe0\x45\xf0\xb5\x13\x40\xa6\xaf\x89\x6c\x00\xfe\x71\x12\xfe\x61\x57\x5b\xc2\xe9\x16\x0b\x31\x52\x30\x6f\xa5\xb2\x3f\xfa\xc7\x30\xef\x5e\xe7\x41\xe6\xdd\x51\x15\xb2\x48\x28\x12\x21\x7c\xc7\xf5\xbd\xb9\x6d\xd4\xb8\x6a\x44\xed\xde\x05\xfc\x59\x6b\x1a\x1e\x41\xf0\x19\x21\xe2\x23\x20\xc9\xad\x97\x66\x9c\xcf\x71\x66\x20\xf2\x93\x0b\x6d\x08\xee\xf2\xbd\x8c\xa8\xef\x72\xcf\xaf\xec\xca\x68\x6f\x51\x22\x54\xc4\xf1\x23\x8c\x54\x4e\x1f\xdd\xa0\xd5\x2f\x77\x3e\x02\x85\x60\x8d\x05\x4f\x8b\x73\xf5\x11\x2c\x05\x02\x3f\x28\x05\x92\x7c\xfe\xa5\x48\xf3\xcb\x31\x1d\x73\x13\xe7\xd8\x03\x88\xa2\x2e\x16\xd6\x08\xfa\x66\xcc\x1b\x23\x54\xd5\x08\x49\x59\x07\xae\x99\x75\x35\x53\x28\x90\x8f\x69\x68\x77\xc0\x99\xcb\xde\x85\x3f\xbc\x2f\xa3\x6f\xee\xa3\x9e\xf7\x1c\x6a\x1e\x0f\xb9\x92\xd7\x28\x7e\x3f\xa0\x63\x79\x31\x00\xa4\xd5\x61\x22\xa0\xf6\xf8\x61\xce\xfc\xbe\x13\xd5\x3c\x32\xd0\x99\xd6\xb2\x4b\xe6\x83\x8e\x26\x72\x30\x8f\x70\x91\x3f\x03\x68\xee\xff\x8b\x60\xf9\x71\xfc\x8a\x8f\x38\x21\x85\xcf\x93\x28\xab\x2a\x26\x8f\xb5\xfa\x3f\x59\x67\x65\xdf\x1e\x0e\x49\x25\x12\x45\xfa\x69\x8f\xf9\x74\x8d\xc1\x87\x8d\x0b\x29\xfa\x00\xf5\x0f\x65\x8b\x81\x5c\xf9\x21\x6c\x45\x9d\xd9\xc3\x65\x84\x28\x95\xf7\x70\x82\x81\x44\x47\xf2\x4c\x1d\x0f\x72\xe7\x1f\x9a\x7b\x3d\x92\xee\x5f\xe6\x50\x38\x7f\xe4\x00\x68\x8d\x1e\xf1\x21\x92\x3d\x03\x5e\x45\x80\x93\xca\x86\x1b\xde\xd8\x4f\x16\x9a\x32\x95\xe0\x33\x9a\x41\xc1\x5b\xac\x49\xb4\xf7\x15\x43\xee\xbc\x1d\x5a\x07\xee\x45\x68\x82\xb8\x27\x79\xa4\x8d\xf3\x3c\x7c\x65\x3b\xda\xcb\x67\x4f\x58\xb8\x96\x0f\x73\x98\x36\x58\xd3\xf6\x92\x94\x48\xea\xcf\x4c\xf1\x8d\x8f\xd4\x35\xfe\x28\x25\x0d\xb5\x17\x63\x72\xa8\x1d\x47\x27\xc3\x59\xf8\x72\x0d\xa7\xb0\xb6\x83\xa8\x58\xd6\x53\x30\xdd\xec\xf0\x12\x5f\xb6\x99\xf7\x50\x34\x79\x1d\x4a\x3e\x64\xde\x10\xa3\xbe\xa1\x60\x00\x2b\x48\x89\x4f\x81\x29\xca\xc1\x6c\x9c\x87\xbb\xd7\x5e\x87\x39\x1e\xf3\x61\x1e\xe6\x50\xe1\xf8\x48\x7e\x60\xc8\x77\xa8\x6a\x5c\x93\xbe\x6c\x26\x07\x4d\xe8\x1c\x90\x92\x2a\x81\x8c\x4d\x70\x2e\x44\x82\xe6\x03\x68\xf2\x2e\x0a\xce\x25\x02\x21\x49\x56\x25\xf1\x2c\x12\x16\x61\x70\x25\xda\xeb\x62\xfc\xdb\x00\x7c\x43\x76\x63\x66\xa1\x66\xdc\x6a\x94\x58\x92\x6b\xda\x3d\x23\x08\x9e\x32\xd7\x50\x6a\x0e\xcb\x00\x9e\x28\xe9\x3b\xa0\x74\x19\xd2\x28\xe9\xe1\xaf\xcc\xc0\x31\x69\x5f\x79\xd3\x7a\x87\x5d\x36\xdd\x84\xba\x2e\x61\xb5\xf0\x12\x72\xe3\x74\x39\x0a\x8f\xd2\x4b\x06\xdc\x16\x56\x6e\x96\xf6\xef\x2a\x19\x07\xd8\xd5\x61\x93\xd2\xfb\x10\x93\x12\x0a\xd0\x14\xd3\x80\xa2\x47\x26\x5d\xb0\x93\x82\x71\x93\xea\xbe\x36\xd3\xfc\x58\xcb\x23\x0b\x87\x70\x17\xf5\x48\x02\x19\x30\xa2\xd6\xba\x21\x14\x1b\xca\x16\xfe\x0c\x53\x91\xa0\x06\xdb\xf9\xde\x5e\xea\x00\xd0\xac\xf8\x35\xc2\xa6\x44\x0e\x0a\x30\x15\xb7\xdb\xf9\x7e\xa4\x38\xc3\xda\xd2\x50\x36\x29\x3f\xf8\x40\xf6\xce\x57\xe3\x11\x52\xd4\xba\x30\xc4\x7e\x73\x89\xd4\x9b\xff\xf8\xa9\x4a\x30\xe3\x56\xa3\x07\x35\x5d\xca\x7a\x00\x83\x1a\x22\x1a\x10\x23\x0a\x45\x8c\x0c\x44\x81\xef\x8c\xa7\x4d\x7a\x21\x39\xf8\x7c\xbd\x44\x32\x92\x10\x44\x7d\x7a\x6a\x5c\x09\xbb\xf6\x1d\x3c\x08\xc2\x6a\xd2\x95\x04\x83\x39\x25\x54\x64\x91\x27\x40\x92\x3e\xc4\xca\x81\xea\xb1\x7d\x78\x4f\xf5\x6e\x59\xc8\x80\x08\x1e\x1b\x5d\xf0\xc2\xa1\x0b\xd0\x1c\xd5\xe3\x31\x84\x2c\xf4\x98\x24\x8c\xd3\xaa\xbc\xd8\x3d\x43\xed\x90\x03\x3a\xed\x76\xd5\x8b\x45\x92\xa9\x20\xcc\xce\x2b\xb7\x52\x2b\xa8\x3e\x22\xe8\x6a\x08\x23\xa8\x48\xdb\x01\xdd\xce\x6d\xa1\x8d\x19\xe0\x99\x0a\xee\x2d\x0f\xcb\x9c\x40\xe7\x04\xc4\x70\x5f\x70\x85\x4e\x57\x01\x08\x54\xce\xc9\x81\x38\xc1\x34\x22\x4e\x74\x67\xb0\x62\x5d\xd6\x22\xab\xbd\xa1\xf3\x03\xe1\x11\xc8\x9a\x6c\x52\xc5\x68\x7b\xe5\x41\xb8\x9b\xb4\x7c\x6d\x21\xec\x83\xe0\x3c\xf6\x36\x04\xb2\x26\xe6\x96\x04\xdd\xbc\xe6\xac\x98\xea\x98\x5d\x34\x79\x1d\xc4\xbb\x08\x89\x79\x06\x06\x07\x49\x66\x3f\xf3\x12\x83\x48\x8b\x84\x96\xb9\xc2\x8e\xde\x75\x49\x09\xab\xb1\xd7\xe9\x25\xc5\x0a\x78\x80\xc4\x06\xa7\x8e\x7b\x52\xc2\x02\xe3\xad\x13\x25\x1d\xa1\x75\xa8\xae\x81\xe1\x23\x67\x1b\x36\x27\x8f\x3d\x91\x65\x26\xc0\xc8\xae\x45\x60\x78\x26\xb2\xc1\xba\x42\xcf\x12\xc0\xe2\x26\x2d\x69\xc4\xbe\xda\x65\xb8\x9a\xd6\x46\xbf\x68\xe0\xce\x58\x5e\x14\xf1\x36\x00\xb3\x23\xec\x0e\x15\xca\x3a\xa0\xf5\x79\xc2\x10\xe8\xa3\x10\x87\x36\xa5\x99\xbd\xe7\x07\x02\xb9\xd3\x70\x3b\x77\x58\x4c\x84\x77\x07\x73\xb1\x1d\x20\x54\x76\x24\x81\x7e\x46\x54\x3a\xaf\x2b\x00\x3d\x82\xeb\x40\xa2\x86\x84\x97\x2e\x4b\x93\xc0\x81\x3d\x01\xe6\x21\xb7\xd9\xad\xee\x4f\xa6\xb5\x3b\xeb\xb5\x79\x15\x6c\x4a\x10\x9e\xf6\x7a\x1a\x73\x8a\x43\x48\x48\x12\x79\x98\x40\xe8\xbc\xf5\x24\x7d\xfd\xef\xed\x95\x18\xe4\x42\xcf\x76\xa1\x13\xf8\x5f\x42\x1e\x8c\x4a\x98\x61\x14\x3d\xeb\xde\x2f\x30\xb0\x96\x8a\x4a\x21\x5f\x17\xc8\x2e\xc1\xd2\xe6\xe3\xb9\x0c\xc7\xfe\x7c\x84\xf8\x59\x7a\xfd\x0f\xa5\x4f\x81\xf9\xe1\x23\x99\x88\xaf\x4a\xe3\x58\x04\x22\xa2\xbe\x1f\x0a\x6f\x7a\x98\x53\xd7\xba\xf1\x2e\xb1\x8a\x93\x2e\x4e\x3b\xbc\x8d\x71\x6c\x8b\x4d\x5a\x46\xca\x7f\x00\x29\x60\x0d\x73\xd1\x87\x14\xab\x51\x8c\xa1\x0c\xc7\xd9\x4a\x1d\xf8\x85\x92\xd7\x50\xb1\x1f\x09\xbc\xfd\x96\x7f\x4d\x42\xe5\x7f\x6d\x08\x1f\xa5\x8d\x6c\xf6\xce\xd1\x91\x0d\x5e\x05\x42\x41\x9f\xb7\x53\x4a\x64\xd4\x88\xc9\x23\x3e\x1d\x48\x59\xef\x5f\xb8\x8f\x2f\x12\x8a\x15\x44\x04\xad\x77\x08\x85\xdc\x84\x94\xfc\xc8\x82\xbf\xa7\xaa\x08\x93\xd8\x76\x39\xaf\xaf\xba\x48\xfe\x57\x8e\x22\x12\x67\x5a\x59\x9a\x75\x79\x11\xca\x94\x38\x85\x81\x90\xa6\x25\x1e\xcd\xa4\xde\x38\xe4\xdf\x21\x31\xe2\x65\x82\xd4\x17\xc7\xf6\x24\xef\x0c\xfc\xdc\xbb\xc3\x3a\x1a\x9b\xc7\xfd\x50\x77\x44\x86\x1e\x7c\x29\x3f\xaf\xd2\x24\x3f\x3f\x30\x29\xea\x8b\x98\xe7\x1f\xa2\xa6\x3f\x14\xa3\xff\x04\x0a\xf6\x13\xa5\xd1\x4f\x5e\x55\x25\xb2\x08\xf5\x0b\x8f\x04\x1f\xfe\xa4\x4a\xec\x97\x05\x2c\x31\x7f\x40\x37\xf5\xfb\xf0\x49\x63\x39\x9b\xcf\xbf\x90\xd2\xef\xc4\xd1\x0a\x60\xf3\x99\xcb\xe8\x11\xad\x8f\x5a\x65\x4c\x81\xee\x0a\x82\xfa\xeb\x4f\x78\xff\xaf\xf4\xfe\xa7\x16\xe3\x2b\xc8\x13\xf0\x00\x79\x09\x33\x74\x02\xbf\xc9\x95\x7b\x7c\x8b\xe1\x9f\xb4\x4c\x96\x60\x13\x59\x6c\x53\x77\xbf\x86\xf0\xff\xff\x74\x32\x31\x01\x43\x6a\x0a\x85\x92\xb7\xf2\x91\x2f\x17\xf1\x14\x9e\xa8\xad\xdb\xe3\x50\x99\xee\x75\x2f\x09\x42\x32\x94\xb4\x49\x16\x36\x19\xad\xa2\x36\xc7\x8b\xe6\x4b\x01\x86\x5f\x7f\x74\x64\x9e\x04\xfa\x3d\x9d\x40\xeb\x7a\x26\xf3\x2d\x24\xd1\x7e\x71\xc2\xec\x02\x26\xbb\xe4\x4b\x38\xe5\x7b\xce\xda\xb6\x27\xe0\xee\x89\xb4\x9a\x14\x4e\x90\xf3\xf2\xa5\xee\xe8\x33\x03\x22\x89\x20\xbd\xbd\xb3\x7f\x26\x0d\xbf\x9e\xe9\x94\x77\xc8\x19\x5e\x8a\x72\x09\xa1\x45\x37\x2c\x40\xd0\x11\xb2\xc7\x7f\x42\xfc\x3d\xbc\x3a\x2a\xd8\x3f\x14\x27\xae\x24\x8c\xc2\x08\xc4\x2f\x45\x65\x6e\xaa\x86\x61\x4c\xdd\x48\x78\xb7\x2e\x9b\x60\x9f\x3b\xe0\xef\x8e\x01\x4a\x81\x01\xda\x28\x58\x4d\xfc\x0f\xc7\x27\x77\x0d\x2d\x85\xfb\xb4\xf7\x87\x40\x9a\xb3\x4c\x04\x02\xcd\x72\xc3\xb1\xe8\x1a\xa8\x79\x41\x48\xd0\x4d\xc4\xd0\xdc\x75\x11\xe6\x83\x35\x67\x00\x82\x64\x1e\xe2\x06\xe3\x21\xe0\x0a\xc5\x8e\x5b\x56\x08\x1e\x6b\xf2\x72\xf3\xb7\xd8\x42\x48\xb1\xbb\x89\x61\x20\x89\xe0\xd5\x46\x0b\xf8\x0c\x58\x90\xae\x2a\x15\x15\x0b\x75\x76\x45\x2a\x2a\x03\x1e\x0c\x1d\x04\x50\xd9\x1f\xd9\x95\x08\x6c\x74\x1e\xde\x38\x59\xd0\x57\x37\x1a\xb7\xde\x8a\xd3\xb8\x7b\x16\x4f\xfc\xd6\x68\xf3\x9e\x37\x42\x88\x22\xcd\x75\xcf\x1c\x6b\xdc\x93\x5d\xc5\x1f\x0a\xb3\x8c\x10\x16\x0e\x6d\x96\xd3\x06\x6b\x4b\x8e\xd8\x61\xc8\xfa\x20\x7f\x93\x12\x3f\x78\xca\x61\xea\x69\x9d\x43\xe5\xc2\xfa\xfd\x27\xc7\x45\x77\x0e\xd2\x2f\x30\x4e\xb3\x54\xc6\x2c\x16\x94\xf8\xce\xe1\xa2\x6f\x17\x56\x25\xe1\xdb\xd5\xa7\xb8\x52\xa2\x7d\xf6\xca\x32\x51\x0c\x4d\x7f\xef\x38\x81\xed\xa9\xf2\x83\x49\xba\xf9\x09\x6c\x85\x9f\xff\xa3\x84\x0b\x01\x4c\x5f\x4d\x0c\x77\xab\xb0\xb7\x22\x1c\x4b\x5e\x01\xab\xbf\x9a\x2b\xe9\x55\x9b\xf2\xd9\x55\x69\x22\x7f\xd9\xcc\x85\x10\x96\xca\x61\xf8\x65\x8f\x63\x83\x25\xdb\x07\x02\x32\xc0\xb8\x10\xc0\xe8\x64\xe6\x09\x63\x82\x5d\x80\xa7\x3d\xd3\x06\x85\x9f\x62\xbc\x72\xdd\x2c\x1c\x7a\xa8\x1a\x25\x46\xc1\xa8\x99\x52\x58\x26\x47\x3a\x38\x0c\x4f\xf4\xcf\xec\x83\xe8\xa4\x17\xaf\x9f\xff\x54\x98\xc6\xe8\xac\x92\xea\x99\x16\x9d\xb4\xc1\x02\x26\x6a\x14\x28\xca\xfd\x31\x02\x0e\xe5\x14\x50\x6e\x7c\x38\x75\x53\x17\xee\x38\x93\x58\x4c\x08\x71\xce\x8c\x0b\x28\x8e\x01\x78\x42\x6b\xa9\x08\x3e\x36\xcd\x3a\x05\x50\xaa\x37\xc3\x59\x18\xa1\xc3\xda\x14\x22\x41\x2c\x0c\xe9\x99\x14\xca\x95\x57\x61\x59\xed\x2a\x07\x7f\x7b\x51\x89\xf1\x6a\xb8\x50\xee\xe2\xf0\x49\xee\xb1\xc2\x84\xd5\xa3\x05\x28\x52\xff\x7f\x4a\xe9\x5c\xdb\x5b\xff\x76\x9b\xa5\x16\x75\xad\x85\xf6\x20\x3e\x21\x23\xe6\x89\x36\x5c\xd6\xf3\x10\x90\xb4\xb0\x07\xbc\x80\x89\x1a\x14\xac\x04\x41\xb1\xd0\x6b\x33\xfe\x73\x90\x76\x0d\x0a\x35\x02\x0a\xcd\x5b\xe0\xa1\xb8\xbb\x64\xa1\xaf\x70\x02\x03\x3e\x2a\x80\x52\x1a\x64\x5c\x53\x5d\x08\xb4\x9a\x6c\x10\x42\x00\xd3\x54\x7c\xb6\x6b\x4b\x31\x83\x90\x1e\x58\xa2\xe9\x03\x6e\x8a\x27\x03\xb0\x94\xa0\x51\x73\x5b\xfa\x33\x0b\x59\x62\x1b\x1b\x49\x0f\x67\x8f\x6b\x3b\x09\x53\x84\x54\x72\x89\x88\x4b\x42\x51\x60\x88\x38\xc9\x60\xd5\xe2\xc7\x19\xdf\x0a\xa8\x95\x42\x2a\x12\x4e\x32\x04\x54\xbd\xd8\xe7\x3a\x10\x8b\x9a\x3a\xf7\xc4\x6f\xa8\x47\x7d\xe5\xff\xaa\x10\x5a\x47\x5d\x9f\xb4\x4f\xbc\xe4\x5d\x71\x35\x1b\x30\xc7\xe4\xfc\x32\xb2\x5f\x45\x61\xa5\x3c\xfb\x94\xed\x6a\xa8\xb2\x9c\xc7\xd0\xeb\x19\x34\x17\xb1\x48\x00\xbc\xc6\xcb\xbe\xb2\x8f\x7b\x75\xcd\x7b\x09\x59\x5f\x7d\xd8\x2e\xc0\xbf\x23\x74\x73\x5e\x74\x8a\x93\x89\x4d\x03\x7c\xd5\xaf\xe0\x8e\xe4\x36\x5d\xaf\xe7\x52\xb0\x36\x83\x9b\x3d\x0c\x0f\x42\xbe\x87\xe1\x56\x43\x75\x87\xea\xf4\x01\x13\x0b\xd6\x16\x90\x62\xdb\x15\x81\xff\xc8\x3e\x89\x0a\x70\xf5\x49\x78\x9c\xcb\x65\x1a\x67\x46\x8f\xc7\x3c\x10\xc0\xf5\x8f\x62\x49\xe9\x45\x70\xfa\x95\xea\xd3\x46\xd3\x84\x25\xa6\x70\x66\x4a\x4d\x99\x29\xb1\x6a\x8b\x21\xc1\xdc\x22\x0d\xf6\x10\x36\x01\xa8\xf0\x0c\xf0\x80\x42\x3e\x9a\x98\x5f\xb0\xcf\xe1\x9d\x4b\xab\x40\x6c\x23\x1f\xd2\xf4\xe0\x49\xc5\x31\x7a\xcf\xc4\x72\x9d\x14\x10\xaf\x94\xbc\x8f\x81\xf0\xd8\x2c\x89\x1f\x95\x00\x4e\x71\x8d\xce\x2a\x7b\x41\x0b\x3c\xb7\x09\xf5\x78\xe9\x02\xd9\xf5\x23\x36\xad\xe3\x63\x01\xaa\xa7\x30\x67\x9f\x77\x2f\x98\x59\x3d\x08\x4d\xab\x0f\xdf\x04\x35\x01\xa2\xd7\xae\x4d\x5e\xe4\x98\x5b\x9d\x01\x55\x6b\xf6\x37\x65\xa7\x2d\x8d\x4d\xc2\xb8\xe3\x2a\xd4\x59\x00\xbd\x11\x49\xec\xe2\x2c\x01\x89\xcb\x13\x15\x86\xec\xb7\xaa\xbd\x46\xec\x8b\x0e\x15\x50\xff\x16\x3c\x93\xe8\x2f\xcf\x59\x8f\x9c\x9b\xf9\x72\xca\xec\xc6\xe2\x7e\x66\x33\x8d\x7a\x26\x0a\x2b\xd8\x5d\xdd\xc3\xb1\x47\x8f\xe1\x89\x8a\xdf\x25\xc8\xda\x41\x7a\x8e\x45\x74\x03\xb2\xde\x65\xa6\x52\x92\xbd\xde\x8b\xce\xda\x7b\x03\xcf\xc4\x59\x7f\x43\x38\x1b\x34\x7a\x89\x63\x43\xe3\xb3\xf2\x7e\xda\x88\x85\x58\xb4\x3b\xfd\x6a\x92\x73\x26\xf1\x10\xa1\xbd\x11\x4e\x3d\x4c\x19\x9d\x89\x59\xc7\xd3\x26\x17\x9c\x4f\x9d\xf2\x16\x05\x7f\x9f\xdf\xfd\x57\x13\x95\x84\x38\x04\x3d\xea\x05\xd5\x15\x07\x42\x55\x80\xa1\x5b\x13\x7e\x58\x8f\x7e\x4b\x1c\xc8\x2e\x15\x67\x9e\x16\xf3\xe6\x1e\x18\xa4\x85\x04\xd0\x19\x29\xe3\x03\x1d\xf4\x8b\x3e\x8f\x36\x31\xba\x02\xdf\x16\x90\xae\x72\xea\x2b\x6b\x39\x99\x17\x38\x94\x06\x74\x0c\x1c\xf5\x71\x10\x11\x00\x77\xaa\x88\x7e\x94\x10\xe3\x3c\xbe\x93\x1e\x0b\x1f\x81\x8f\x4b\xdf\x75\x90\xb4\xf2\x2d\xd7\xca\xb3\x5f\xe5\x5e\x6d\x73\xa9\xca\xb4\xcb\x31\x2b\x2d\x0f\xd8\xdc\xbd\x7c\x91\x6f\xee\xd0\xff\x43\x0c\x5c\xe0\xd5\x38\x1f\x3d\xe6\x14\x23\xf5\x03\x0c\x58\x3a\x7f\xc2\xc5\x04\x8d\xc3\xf1\x20\x1d\xe5\x20\xf6\x4b\xf0\x35\xd8\xfe\xfd\x08\x11\x47\x41\x25\x29\xf5\x00\x7b\x2f\xe0\xdc\x79\x25\x22\xdc\xce\x35\xea\x59\x16\x2f\xda\x8c\x18\xba\x5d\x22\x68\x87\x2b\x69\x7b\xc0\x73\x0a\x12\xec\xc1\x1c\x0c\xb0\xcc\x1c\x6d\x40\x34\x68\xe0\x37\x74\x8f\x07\xa8\x19\xbe\x95\x21\x19\x34\xd8\xb5\xe3\x21\x84\xfd\x3f\x20\x46\x7b\xde\xd4\x55\x3b\xe4\x12\x05\x47\x95\xb7\x96\x78\x65\x0a\x06\x4d\xbc\x56\x7f\xcc\xdd\xcb\xb9\x49\x19\x03\x62\x42\x4c\x1f\xe0\xb5\xf5\xe7\xae\xac\x3e\x30\xf7\xe7\xab\x84\x56\xb0\x0c\xd8\x8a\x30\x67\x85\x32\x16\x65\x28\x82\xba\x14\x22\x91\x7e\xdc\x87\xc8\x27\x97\xb6\x9c\x59\xcd\x68\x12\xf6\x7b\x55\x26\x67\x2f\xcf\xc2\x85\xe6\x7d\xfb\xd7\x32\x07\xbe\x0c\xec\x74\xf6\x79\x61\x93\xb6\x4b\x39\x1f\xd8\x9e\x46\x64\xd9\x95\xc5\xb3\xe5\xf0\xc1\xbc\x51\x07\x02\xed\x53\x81\x76\x8e\x39\xd3\x9e\xdf\xca\x2c\xee\xf9\x75\xc9\xdf\xe8\x29\x97\x86\xdd\xda\xfb\xc2\x49\x9b\x85\xee\x37\xa5\x1e\x67\x83\xc5\x71\x52\x20\x61\xec\xcd\xfd\xdb\x57\xaf\x67\x6f\x75\x3b\xc4\xab\xdb\xd0\xd4\x3a\xd4\x28\xda\x5a\x0b\x26\x01\x50\xb6\x52\x57\xcc\x05\x0e\x8f\x6f\xc9\x1b\x2d\x61\x47\x14\xba\x88\x80\x99\x09\xe9\x65\xb7\x89\x89\x30\x57\x56\x65\x8d\x18\xe1\x42\x5f\xb9\xcd\x3d\xdd\x19\x80\xf6\x4a\x79\xa4\x1d\x36\x8d\x8a\xb8\x90\x59\x50\xdc\x2a\xf8\x14\x5d\x84\x93\x2a\xcb\x65\x73\xbd\x4b\x42\x45\x9a\xcc\x6c\xf3\x1a\xa0\xbb\xa6\x45\xba\xcd\x13\xe5\x8f\x06\xc0\x16\xc9\xe0\xdb\x34\x24\xd8\xf2\x25\xf9\x21\xf7\x81\xfa\x21\xba\xce\x1e\x2e\x21\xef\xa8\xf9\x93\xd7\x50\xa8\xdc\x5a\xb7\xbd\x65\xbc\xfd\x7e\xe0\xfe\x9e\x47\xa2\xbd\xfa\x3d\x07\x0a\x0e\xf6\x4f\x67\x0e\x30\x9d\x5a\x27\x87\xd8\xfd\x11\x3c\x5a\x9f\x02\xd2\xfd\xd6\x3d\x14\x7c\xfa\xb1\x29\x1e\xcd\x8e\xe9\xb7\x20\x2b\xb5\xb1\xf5\x0d\x09\xd9\xe7\x75\xc2\x94\x4e\xe0\xb8\x56\xfa\x06\x6e\x4e\x5d\x35\x04\x8c\x02\xef\x97\xd0\x3f\x7a\xf0\x92\xdc\x53\xaa\x72\xed\xb9\xab\xdc\x86\x1c\x39\xf7\x43\xec\xdb\xc4\x79\x27\x64\x8b\x02\xf2\x86\xc4\x27\x37\xf4\x0a\xaf\xc2\x6d\xd6\x3f\x38\x97\x10\x33\xf5\x6e\x36\x7d\xe1\x71\xe5\x8f\xc4\x51\x0e\x21\x22\x4a\x04\x63\x29\x93\x21\x6b\x4f\x56\x41\xe6\xde\xa8\x8b\x73\x8f\xbd\xa1\xe7\xb8\xf9\x2e\xc4\xf4\x46\x5e\x91\x0e\xc6\x61\xaa\x2d\xb7\xc8\x88\x58\x9c\xfa\x24\xec\xdf\x6f\x33\x54\x1a\x03\xc0\x07\x52\x15\x6d\xe8\x60\x73\xb4\x2b\x88\x1d\x7a\x4a\xd9\x6e\x3c\x07\xba\x49\x31\xc4\x80\xcc\xdf\xc0\xf5\x4d\x85\x9e\x37\x6b\x3e\xd6\x03\x04\x0a\xad\x3a\x8b\x71\x85\x7d\x1d\xbf\x81\x44\x37\xa9\x80\x6b\x9d\xce\x58\xfe\xb8\x34\x12\xde\x0f\xc2\xbc\xca\x4b\x50\x74\x74\x22\xaa\xb1\x43\x47\x80\xa2\x3f\x90\x40\x70\x8c\x57\xd9\x3d\xb5\x4c\x1d\xa2\x42\xdc\x58\x79\xc4\xcf\x5e\x4b\x7e\x7d\xe1\x0a\xab\x0d\x41\x02\x71\xc7\x72\x1e\xc4\xe3\x5b\xaf\xbb\xda\xff\x5e\xb9\x76\xfd\xcd\x7b\x3b\xc6\x3c\xd6\x42\xdf\x24\x34\x4a\xbe\xec\xd8\xaf\xad\xb9\x2e\x31\xe5\x5c\xb3\x8d\x21\x89\x3b\xcb\x8d\xb3\xb2\xc2\xa9\x91\x8a\x4e\x79\xff\x30\x17\xba\x7a\xa9\x57\x6d\x83\x7d\x38\x04\xc5\x13\xeb\xdf\x3b\x42\xc2\xfc\xe0\x49\x48\x1c\x1e\xaa\x5f\xc2\xbc\x7d\x84\x93\xfb\x30\xad\x0b\x9c\x1d\x31\x6e\xc2\xbf\x61\x94\x6b\x6f\xbb\x84\x94\x24\xa8\x64\x13\x0e\x0e\xc0\xd7\x14\x32\xcf\x70\x47\x8d\x48\xe0\x45\x98\xe2\xf0\x58\x68\x15\x2f\x46\x23\xdd\xc2\xd1\xaa\x29\xf7\x80\x0a\x1c\xdb\x26\x47\xe8\x29\xf8\x6a\xc6\xac\xd1\xb3\xb9\xfb\x92\x56\x35\x33\xd2\x35\x8d\x67\x96\xbb\x53\xcf\x27\x0d\x66\x4b\x51\x97\x81\xcb\xd2\x4d\xa8\x1d\x50\x38\x4a\x7f\x2d\x75\x3e\x78\x46\x4b\xf5\xc9\x8c\x47\x3e\x3e\x86\x98\x12\x67\xb6\xcb\x99\x84\x89\x5a\x5a\x6a\x69\x09\x21\xc5\x05\x0c\xeb\x39\x24\x93\x3e\x14\x72\x2a\xb0\x9e\x22\xee\xee\x0e\x57\xa5\x5b\x3d\x90\xa0\x78\x6f\x86\x42\xf3\x39\x66\x6c\x81\x8b\x66\x83\x01\x96\xf9\x53\x37\x46\x53\x38\x14\x95\x86\xc2\x83\xbf\xbe\x2f\xf9\x54\x2f\x3b\xe7\x8b\x8e\xe5\xfb\x71\x74\x9e\xe7\x96\x96\xc6\x90\x5a\xe6\x06\xc2\x43\x01\xc5\xff\xfd\x7c\x04\x2c\x6f\x68\xea\x48\x8d\xfa\xb2\x7c\x4d\x64\xac\x6d\x88\x92\xc1\xd2\x04\x35\x97\x3c\xf8\x78\x64\xf1\xaa\x48\x56\x18\xc3\x20\x87\xe4\x49\x10\xc9\xde\x76\xb6\xd6\x0b\x58\xf9\x0a\x64\x7a\xb6\x34\x91\x04\x44\x3e\x1e\xb5\x60\x26\x60\x8f\x73\x80\x5f\xb8\xc7\x87\x04\xdf\x2f\x34\xa2\xd2\x52\x3d\x5c\x55\x57\xfc\xcd\xd5\x9f\x0b\xe0\xdc\x89\xa3\xf9\x45\x51\xc1\x93\x88\xbf\x36\xa2\x76\x89\x23\xa9\xb4\x23\x85\xe1\xcb\x2b\xc7\x93\x63\x4d\x70\x1f\x83\x61\x8b\x5d\xf1\x68\x9b\x0a\xae\x27\x3c\x17\xbc\x81\x06\x4c\x8f\x58\x3c\xa7\x39\x8f\xdf\xd0\xa3\x35\xf4\x83\x2c\x9a\x39\x3b\x9d\x6c\x7e\x15\x58\x3d\xf4\x88\x82\xad\x9d\x54\xce\xb0\x93\xf3\xc7\xdf\xe1\x76\x0a\xf6\x2f\x52\x4f\xbd\xe5\x44\xdf\x47\x46\x0b\x37\x3b\x59\xe7\x9b\x4a\x69\x5f\xd9\xd5\x7f\xc5\x9e\x16\x83\x72\xe9\x03\x00\x1a\x34\x31\x98\x03\xcb\xe7\x95\x0e\x62\x00\xed\x69\x52\xfd\x73\x2a\x1c\x41\x41\xe5\x97\x9e\x46\xf6\x86\xf5\x53\x00\xd7\x3c\x75\xe9\xf5\x4e\xff\x34\xea\xb7\x80\x36\x4d\x25\xa5\x2e\x60\x7e\x9e\xc5\xf5\xa3\xe7\xd7\x2a\x4b\xa5\x2b\x5c\x96\xac\x3f\x5b\x85\xe8\xdb\x04\xb0\x3b\xa4\x43\xd4\x6c\x67\x80\xd8\x5b\xbf\x90\xbd\x86\xd8\x9b\x87\xbb\x93\x1f\xcd\x04\x2c\x03\x61\x70\x6c\xa3\x26\xc0\xf6\x42\xf4\xc8\x5a\x0b\xa4\x4d\x05\xbe\xe3\x14\x70\x4a\x2a\x06\x4c\x3e\xcf\xde\x42\x0f\x29\x39\x26\x3f\x3e\x10\xa3\x67\xef\xe0\xc7\x83\x79\x8c\x53\x02\xc6\x5b\xfe\x4d\xfd\xa2\x74\xfc\xa8\x4a\x95\xcd\xc9\x07\xe6\xcf\x02\x49\xb7\x12\x37\x67\x3d\x5f\x65\xfa\xdd\x63\xfb\xaf\x0e\xa1\x42\x33\x2a\x4d\x9f\xb3\x36\x61\xa4\x2a\x38\x9b\x05\xe2\x2f\x5b\x18\x10\xbb\xfb\xb3\x08\x4f\x77\x5d\x8d\x6f\x40\x98\xdd\xc5\x68\xd0\x1a\x3c\xf3\x82\x6a\x9d\x45\xe2\x4b\x04\xb1\xd9\xf2\xf1\x23\xf8\x9d\xf2\x47\x1e\x57\x42\xf6\xac\x21\xe7\x2a\x40\xa7\x2f\x45\x43\x0c\x82\xc6\xa0\x5d\x01\xa5\x17\xc7\x67\x4e\x78\xb4\x41\xeb\xd0\xb8\x86\xa3\x24\xbc\x80\xd0\x0b\x41\x24\x80\xf5\x4e\x90\x73\x7f\x08\xd7\x4b\x42\xe6\xad\xb9\x9b\xdb\xd9\xda\x73\x21\x91\x24\xdb\x91\xa5\x83\x71\xfd\x56\x3f\xc7\x18\x6e\x8e\x9e\xf5\xd4\xa6\x36\xda\x69\x1a\x4f\x90\x60\x5c\x7d\xd2\x30\xe2\x9d\xdd\xd8\x25\x7a\x4c\x0a\xce\x38\x85\x66\x13\xab\xa0\xa8\x45\x7e\xb8\x0c\x49\x2a\x1b\x7e\x9e\x1b\xc7\x63\x16\x4b\x93\x2a\xcf\x4d\xe3\x69\xde\x84\xa3\xab\x36\x4c\x97\xaf\xf8\x88\xfb\x2d\x24\x65\x3a\x39\xcc\x44\xef\x4a\x24\x60\x42\x99\xc5\xff\x4b\x12\x10\xd3\xfa\xbd\x57\xa0\xf1\x06\x56\x2a\xfd\xc3\xfa\xe6\x59\x91\x6d\x0b\x60\x5e\x3c\x5f\x29\xd8\xe3\xa3\x80\x05\x23\x90\x64\x3c\x98\xce\xd1\x96\x6a\xca\xc6\x94\xce\x90\x7b\xba\x66\x51\xbf\xe1\xb1\xc5\xe9\x1a\x3c\xb6\x68\x29\x55\xc7\x4a\xfc\x1c\xa5\xd4\x1e\xd0\x46\x17\x5c\x6f\x26\xe5\xce\x02\x92\xcc\x2c\x18\xe2\xbb\x7c\x51\x5c\xf4\x11\x5a\x42\x8f\x53\xb2\xa6\x0e\xd4\x63\x23\xe2\x40\x3d\x9f\x87\xf9\x43\xf1\x10\x83\xe8\x21\xf1\x67\xc0\xf3\xd4\x5c\x5a\xd8\x31\xc9\xf2\x58\x59\x7f\x7d\xc0\x18\x98\x2b\x72\x00\xf5\xb2\xbe\x08\xd5\x29\x9b\x94\x74\x95\x6f\x38\xf4\xa6\x92\x6a\xc1\x8f\xb9\xc1\xfe\x1f\xb1\x66\x9d\x0f\x26\xd8\x21\x41\x95\x67\x89\x50\x09\x1d\x28\xdb\xc4\xc7\x9c\xae\x96\x41\x03\x92\xcf\xef\x84\xcb\x52\xb1\xd6\xfd\x08\x60\xba\x05\x63\x24\x40\x1e\xd6\xe7\x51\xe6\x2a\xcf\x01\x08\xf4\x96\xf3\x01\xe1\x5f\xff\x05\x18\x08\x31\xa0\xea\x3d\x7c\xbc\x1c\x4f\xf7\x92\xfa\x17\x66\x1b\x6a\x1c\x11\x4a\x2e\x38\xdf\xa1\x33\xa5\xa9\x86\x0b\xfa\x79\xb0\x37\x79\xa9\xdd\x2d\xb6\x54\x89\xce\x33\xd5\x0a\x91\x81\xfa\x03\xea\x13\x8a\xf0\x6b\xdf\x35\x7c\xa1\xcd\x79\xd8\x4a\x30\xcd\x73\xc0\x61\x32\x07\xc6\xd9\xf1\x62\x04\xf0\xbd\x66\xcd\x0a\x87\x7a\x64\x82\xfc\xe0\xd4\xaf\x68\x0c\x2b\xae\x44\x05\xdf\xa1\x62\x12\xab\x70\x24\x1a\x7d\xb0\x76\xcc\x73\x9c\x43\x1d\x3e\x5e\x83\x1b\x00\xf4\x04\x82\x9c\xa9\x8f\xa1\xf6\x52\xaa\x2a\x4e\x04\xf7\xb1\x20\xc4\xaa\x3a\x80\xb7\x2f\x7e\x08\x18\x61\x8e\x47\x67\x70\xd9\x7e\x62\xf8\x80\xfd\x62\x80\xf7\xd7\x8f\x55\x36\x89\xd8\x0d\x01\x7e\x19\x4a\x90\x87\x07\x1b\x14\x01\x4d\xa2\x0f\x6a\xd0\x1d\x4c\x48\x94\xe0\xfc\x75\xd6\x9a\x03\xaf\x38\xab\x65\x18\x9a\xc4\xf5\x30\x07\xfa\x94\xeb\x7b\xd5\x43\x87\xe8\x0d\x01\x32\x14\x74\x64\x80\xd4\xa4\x10\x82\xc8\x8a\xb3\x7d\xb0\x37\xb5\xbe\x03\x5f\xa8\x81\xfb\x90\x43\xab\x75\x50\x72\x6a\xc8\x9b\x4c\xb6\xc0\xba\x2a\x11\x9e\x17\xd3\x58\xd6\x9f\x55\x19\x6e\x2d\x85\x68\xc4\x4e\xc0\x1f\x98\x71\xf1\x02\xe6\xe6\xae\xf5\x5e\x65\xc0\xf5\x0a\x27\xae\x4a\x4b\x80\x21\x69\x98\x0d\x31\x01\x7e\x63\x0d\xad\x70\x88\x67\xa2\x4c\x18\x98\x57\x17\xf4\xe6\xfc\x54\x31\xf6\x7f\x72\x5f\x6b\x2e\xfd\xd6\x5a\xdb\xf4\xf3\x7f\xb4\xea\x22\xa6\x8c\x6e\x17\x7d\x0d\x34\x5f\x4d\x83\xec\x93\xce\x2a\x55\x2b\x6c\x2c\xdc\x1c\x68\xc6\xd2\xa1\xb2\xd0\xde\x5e\x45\x54\x9f\x3a\xf3\x53\x46\x5c\xf6\x1c\x2c\x5b\x65\x28\x9d\xf9\x5e\x7e\x2a\x7d\x00\xb0\xfa\xf2\x21\xd6\xad\x50\x29\xac\x2f\xff\x04\x1f\x7c\xb2\x95\xed\xff\x3c\x6f\x40\x32\x06\xcc\x10\x98\xb6\x42\x05\x2c\x9b\xdf\xcc\xf4\xba\x2a\xe7\xb3\x09\x64\xfd\x91\xb4\x82\x56\xf6\xa9\xa8\x29\xab\x20\xd6\xbf\x2c\x3c\x13\xe5\xde\x7b\x08\x16\xf3\x9f\x40\x66\x88\x08\x3b\xd0\x2b\x0e\xad\x1c\x63\x55\xd6\x52\xde\xc6\x7d\x99\xf5\x5f\xc0\x6d\xf6\xa0\x9f\x38\xec\xf0\x0e\x4e\x66\x62\xa5\x99\x89\x61\x26\xe9\x87\x70\xf6\xfc\x2e\x90\xa4\x24\xe9\x10\x64\x3e\xeb\xbd\xcd\xe5\xbc\xdc\x01\xa5\x2e\xa9\x74\x11\x8e\x38\x41\x29\x8c\xaf\x8e\x7b\x82\xd5\xf0\x04\x93\x01\x1f\x40\x6a\xca\xbb\x03\x81\x78\x0b\x02\x09\xd1\xb8\x50\xf5\xb2\x96\xf9\xc1\x79\x9c\xbd\x25\x7e\xd0\x6c\x93\x75\xa2\x53\xe0\x09\xa6\x47\xc2\x1d\x2d\xb4\xae\x0b\x4c\x64\x1f\xaa\x84\x08\xd3\xd9\xc4\xbc\x5e\x41\x77\x80\x95\x58\x13\xec\xba\xd4\x49\x23\xd2\xb5\x43\x3d\x2a\xbc\xc5\xec\xe5\x8d\x0d\xad\x8d\x70\x02\x00\xcc\xc4\x24\xa7\xef\x61\x03\x54\x6a\x43\xc0\x82\x75\x48\x15\x0b\x90\xe6\x78\x36\xc3\xb0\xe3\xd0\xca\x43\xff\x6e\xbf\x65\xf8\xd5\x04\xca\xec\xb5\x55\x70\xd8\x24\x24\xf4\xc6\xba\x53\x48\xcc\xf5\x93\xb4\xa1\xbd\x46\xbf\x8a\xe6\x71\xae\x52\x23\x7b\xc4\x2e\x83\xb2\x40\x7d\xea\x09\xed\xed\xde\x62\x67\x74\x55\xf2\xe7\x76\xb7\xa5\x83\x85\x82\xfa\xc5\xa0\x19\x24\xa2\x24\x22\xcd\xfc\xae\x86\x1a\x72\x57\x77\x61\x38\xc9\x31\xeb\xaa\x90\x66\x95\xa2\xdb\x5d\x1d\x56\xe1\x2b\x6d\xb6\x3f\x25\x11\x23\xec\x83\xf3\xec\x6e\x01\x34\x25\x81\xd0\x85\xd7\x17\x6a\x46\x12\x2c\x2b\x55\x4b\xb2\x5e\xa0\x85\xb6\x10\x4d\x59\x02\x4c\x89\x77\x9c\xdf\xcd\x9b\x60\x9a\xeb\xda\xe0\x9d\xf6\x3a\x35\xf4\xe6\x10\xf2\x67\x40\xca\x50\x0b\x07\x96\x21\x02\x6f\x86\x0e\xa3\xe3\x38\x2f\xfd\x3b\xb7\x61\x7e\x47\xc8\xd4\x52\x47\x6d\x85\xae\xbc\xa9\xdd\x55\x5e\x64\xe2\x22\x10\xa4\xaf\x54\x69\x8f\x76\xf0\x01\x14\xd4\xb2\x92\x30\xd4\x15\xd5\x1b\x3a\xdc\x93\xc6\x97\x06\x9e\x73\x0e\xf4\xe6\xa5\x2d\x35\x36\x25\x9e\x93\xbf\xa8\x9c\x25\x1c\xd1\xd4\x1e\x76\x45\xec\x0c\x0b\xbe\x47\x93\xee\xda\x3a\x54\x06\x23\x47\x91\x5d\x91\x29\x64\xb7\x5a\x5b\xe6\xe7\xbf\x52\x74\xe9\xe6\xf4\xbf\x5b\x9d\xea\x2c\x00\xea\x9a\x21\xa2\x4e\xd3\x34\x16\x9b\x51\x1d\xc4\x50\xe7\x47\xe0\xcd\x90\x84\x03\x44\x53\x67\x3b\x07\x6e\xaa\xfb\xe3\x78\xde\xcd\xcc\xfc\x75\x18\x12\xfa\xab\x6a\x11\x94\x84\x89\xfd\x1c\x05\x94\x14\xb6\xcf\x96\xcc\xa4\x74\xb0\xc6\xe6\xc3\x00\x6d\x73\x62\x28\x5d\xc6\x3f\x22\xe2\x62\xf9\x16\x3b\x1a\xbe\x27\xac\x04\xba\x6d\x60\xce\xf1\xee\xc3\x16\x73\x9a\x85\xde\xdc\xad\x05\xa9\xc2\x76\xee\x57\x40\x35\x85\x35\xec\x30\x8f\x87\x8d\x22\x35\xdf\xe2\xdb\x55\x0a\x6b\x8e\xfb\x26\xe6\x74\x7d\xac\x21\x76\x97\x57\x8a\xe8\xe5\x25\xce\xf1\x37\x71\x39\x33\x3f\xd3\x61\x60\x15\xea\x71\x54\x10\xb4\x89\x1e\x7f\x44\xda\x3b\x48\x38\x08\x84\xf9\x22\x22\x97\xda\xaf\x9d\xdb\xab\x79\x60\x83\xcb\xac\xc0\x4d\x0c\xe4\xc6\x76\x37\x5b\xb7\x8b\x34\x53\x0b\x94\x0c\x73\x8d\x38\xc2\x59\xd1\x16\x85\x0c\xdc\x42\xac\x28\x85\x03\xd3\xd6\x36\x5e\x01\xa6\x62\xa4\x23\x42\xf8\xe9\xa5\x88\x97\x31\xd9\xf3\xe4\xa8\xc4\xb7\x46\x30\x68\xce\xd8\xe8\xa7\x6b\xd2\x5c\xd4\x22\xbd\x4b\xf0\xea\x14\xf1\x1e\xad\xe2\x5b\x60\x4d\x24\xee\x81\x2c\xf3\x0f\xe4\x72\xba\xa9\x16\xb5\xdb\xdc\x8b\xe7\xd6\xda\xde\xbb\x99\x1f\x87\x73\x96\xc8\x54\x83\xb2\x4d\xa9\xb4\x9d\x0e\x01\x49\x6e\xc7\xe9\xeb\x03\x95\x36\x41\xd2\x93\x35\xdc\xbe\xd3\x26\x25\x33\xf7\x5c\x74\x79\x4d\x78\x74\xa8\x0a\x65\xa1\x10\x51\x0e\xf4\xb4\xe1\x2e\x01\x9a\xa1\xde\x63\x01\x9f\x50\x5c\x0a\xe6\x09\xac\xeb\xf0\xdf\xbd\xf6\x52\xe4\x40\xc4\xda\x68\x5a\xa6\x9b\x10\xd8\xa9\xd2\xf7\x0e\xf3\x5f\x19\x07\x83\xe4\xed\x17\x67\xf8\xa2\x3f\xa1\x0b\xe7\xeb\x3a\xcf\xfd\x26\x60\x71\x7f\x20\xfe\xe6\xfd\xd4\x07\x25\x6c\xc1\x35\x67\xa7\x8b\x7c\x98\xca\xff\xa8\xaf\xf9\x40\xea\xce\x97\x2c\xcc\x7f\x92\x70\x3b\x1f\x89\xca\x7f\xec\x3f\x78\x23\xf5\x2e\x8e\x48\x82\xdc\x20\x0e\xf0\xde\x83\xf9\xf3\xce\xcc\xab\xbd\x73\x90\x2a\xdf\x6e\xe5\xfb\x43\xe3\xb9\x9b\xdf\x35\x89\x80\xb7\x0d\xf5\xa8\x2d\xe7\x75\x0b\xfc\xae\x97\x9c\xbb\x90\xf2\xf8\x23\x10\xf7\xe0\x74\xc3\xa2\x14\xa0\x4f\x98\x5b\xec\x1e\xfd\xee\x89\xab\x7e\x7b\x4e\xb2\x80\xf4\x0c\x33\x39\x07\x84\xd3\xad\xee\x7a\x85\x40\x9c\xca\x7b\x2f\x17\x6d\x87\x7a\x1a\x37\xdd\xa3\xf9\x46\x39\x40\x8f\xf4\xcb\x7a\x42\x51\x21\x2d\x8c\xa6\xf1\xd5\xb8\xe6\x2f\x2a\x9d\xbd\xe6\x24\x91\xb7\x69\xbe\xf9\xb6\x22\x02\x74\x5f\xf2\x73\x02\x4c\xbd\x90\x97\x52\xbe\xfe\xd5\x08\xbe\x2f\x8d\xb1\x5f\x4a\x7b\x41\x85\x8e\x9f\xd7\xc0\x8c\x36\x7d\x3a\x1b\x0f\xf8\xb0\xf1\x85\xd6\x20\x30\xa8\x43\x73\x6c\x78\xb9\x7b\x10\x82\xf4\xd6\x63\x6f\xd1\x1f\x11\x3a\x18\xae\x27\x8f\xee\x4f\x04\xfa\x81\xcd\xfd\xd9\x23\xf6\x6e\x2f\x10\x82\x88\x65\x8d\x39\xfd\x4b\x22\x74\x40\x52\x3c\xcb\xa8\xff\xb6\x7e\x6f\x58\x9a\xf8\x35\xf2\x55\xda\x63\x18\x38\xc8\x79\x92\xf7\xf9\x04\x8e\x97\x50\x56\xbe\xa5\xcf\x22\xc6\xdf\x73\x3e\x47\x0a\xe1\x09\x89\x8a\xdc\x0b\x47\x3b\xae\x93\x17\xa6\xa8\xfe\x41\x82\xac\x40\xb6\x72\x1d\x1c\x7c\xde\x8c\x22\x95\xfa\x04\x75\xca\xbf\xf5\xc2\x01\xad\x42\x41\x99\xf5\x3e\xd9\x02\x01\xb2\x01\xd5\xf7\xc4\x02\x63\xee\x2a\x38\x06\x82\x76\xb8\x35\xfd\xc7\xc7\xfd\x99\x7d\x26\x2c\x78\xac\x27\x8b\x9f\xc8\x3e\x64\x06\x2f\x01\x68\x77\x0d\x00\x9f\x42\xe6\x26\xb8\x44\x14\xd6\xe7\xdc\x85\x54\x5a\x79\x2e\xf7\x12\x36\x80\x4a\x0a\x84\x9e\x1e\x1d\x52\xf9\xe9\x28\x79\x6d\x1f\x60\x86\xc1\xdd\x5d\x61\xcf\x2f\x61\x0d\x05\xa7\x6a\x4b\x57\xf0\xa8\x67\x62\x5f\x54\x0f\xe9\x0d\xd4\x63\x78\xfb\xfd\xad\x1c\x5c\x55\x40\xe2\xbd\xd0\xe3\xf5\x2b\xee\xde\x8c\x2f\x11\x69\x3e\x5f\xd7\x37\xf3\x27\x64\x56\xee\x8c\x92\x50\xba\x0b\x91\xb8\xa7\xfd\x9d\x0a\x77\xb9\x62\x23\x94\x5c\x9e\x0d\xe9\x59\xae\xbf\x61\xb6\x2e\x69\xe0\x1b\x27\xc9\x7d\xfe\x82\x7a\x61\xbe\x1d\x46\x86\xc5\xe1\xa2\x67\xbd\x62\xf7\x33\x28\x3d\xb0\x31\xd4\xd8\x1b\x76\x2c\xfe\xff\xdc\x7b\x39\xe0\xb9\x59\x80\x39\x8b\x06\x36\xbd\x16\x91\xc2\x6a\x77\xf0\xad\xe9\xb5\x85\x8e\xf8\x2d\x74\x68\xbe\x0b\xc5\x23\x6c\x69\x53\x7f\x97\xbc\xe2\x27\x9f\xe0\x5a\xbb\xaf\x22\x2e\x7a\x00\x01\x77\xe5\xa6\x72\xcf\x67\x28\x03\x86\xaa\xdf\xcc\x57\xda\x2e\xb3\x75\x0b\x81\x69\xd5\x35\xbf\xe7\xa1\x4b\x02\xd0\xbe\x00\x65\xf5\xa3\x4e\xca\x61\xb8\x65\x62\xd8\xcd\x3b\xfe\x56\x9b\x96\x53\xd3\x2b\x94\x72\x1b\x18\x77\xce\x4d\x66\x50\x3a\x66\x9a\x1f\x41\x2f\x87\xf9\x77\x9b\x1c\x3d\xd8\x3b\xdc\xe9\xdd\x11\x11\x78\x27\xa5\x94\x6e\xc1\xee\x6f\x75\x0c\x8e\x95\x97\xcb\xea\x6d\x2f\x32\xe5\x0d\x53\xc7\xf9\x8f\x05\xb4\xe6\xbe\x3e\x79\x21\x7f\xee\xfa\xa4\x2f\xf4\xc5\x05\x08\xb1\x44\xfb\xaa\x46\x95\x40\xdc\x47\xfa\x23\x40\x28\xa8\x2e\x56\xdd\xc4\xda\x22\x01\x46\x04\x69\xd5\x83\xee\xf1\xf6\x0d\x39\x5e\x83\xee\xe0\x2c\xd9\xc1\x2e\x94\xca\xdc\x86\x51\x01\xc5\x81\xdd\x80\x31\x0b\x61\x7b\xbe\x03\x12\x6c\x8f\x90\xbe\x86\x02\x9a\x02\xa6\x6a\x91\xe4\x0a\xe3\x45\x28\x9f\x35\x9f\xc5\x33\x4d\x02\xd9\xb6\x87\xce\xc2\xb2\x5c\x61\x19\x88\x11\x53\x7b\x61\xec\xd3\x22\xb0\x6f\xd0\x28\x6c\x94\x1e\xf8\x4d\x3c\x0e\xbe\x04\xe3\x9a\x28\x43\xf7\xb4\xe4\x66\xa0\x81\xef\x47\x99\x56\x7d\xd2\x7c\xc7\x3b\x10\x9d\x42\xe3\x09\x59\xf8\x78\x84\xc4\x61\x0e\xd9\xc5\x66\x0c\x6f\x63\x73\x41\x1f\xed\x7e\x22\x53\xfe\x56\x9c\xc2\xe8\xd2\x15\x12\xb5\x76\xd4\x44\x51\xe8\x60\xdd\xca\xff\xea\xdc\xb9\xe7\xe1\x71\xd6\x10\x80\x74\x7d\xc4\xcc\x28\x4f\x11\x08\x29\x7c\x36\x1b\xca\xa3\x08\xcb\x71\x1d\x73\xe0\x45\xed\xea\x09\xd1\x7b\x68\xab\x02\x48\x2d\xaa\x3d\x7e\x9b\xda\xe5\xda\xcb\xeb\x0b\xff\xdd\x13\x6f\xec\xf6\x26\xc1\xc8\x02\x7e\xb1\xa6\x37\x07\x67\x2e\x6e\x18\x11\xbb\x19\x1b\x67\x3c\x67\x41\x7d\xb3\xae\xf3\x6f\x91\x72\x95\x45\x44\x25\x5d\xb6\x89\x0d\x21\x89\xee\x05\xbb\xe7\x0e\x14\x2f\x81\xc8\xc0\xea\xec\x29\xc0\xb8\xb5\xe9\xbb\x5d\x13\x25\x06\x30\x3b\x10\xca\x73\x9a\xb7\xd4\xd5\x45\x52\x80\x93\x4d\x5c\x08\xdc\x75\xd5\xe7\x9b\xa1\x80\xf8\x00\xe7\x4a\xdb\x70\xd0\xb0\xc9\x71\xba\xfc\x2e\xd5\x8e\x4b\xe4\x24\x78\xb0\x40\xe9\x01\xb3\x3b\xf0\xb0\x69\xd2\x25\x07\x60\x57\x8f\x24\x18\xfe\x36\xac\x70\x5c\xa7\xaa\x0c\x97\x2a\xa4\x97\xb4\xaa\xae\x3c\x7f\x4d\x65\xe9\x89\xe9\xc1\xc4\x05\xd1\xe2\x79\x0c\xa0\xaf\x83\x6b\xf9\x7f\xfa\x79\x63\x95\x9b\x48\xda\x10\x49\x84\x6a\xae\xc0\xad\x2f\x92\x92\xe5\x94\x99\x19\xd6\xaf\x3d\x25\x00\x98\x5a\x7b\x26\x21\x63\xf1\x44\xec\x0a\x65\x44\xda\x83\x66\xd0\x76\x0a\xdd\x4b\x57\x69\x14\x7c\x77\x4b\x4d\x97\xd1\x21\xb7\x0a\xe3\x98\x71\x8f\x00\xf8\x13\x2e\x78\x52\x93\x80\x87\xb3\x0b\xcd\x52\xd8\x67\x86\xac\x35\x3f\x04\x12\xf7\x3c\x42\x9e\x11\xb9\x37\x5f\x09\xc4\x81\xbe\x4f\x47\x51\x9e\xf3\xfa\x56\x8a\x2e\x0a\x43\xcf\x0a\x13\xc5\x7d\xaf\xb4\x7e\xa2\x15\x49\x01\x95\xc7\xb0\x5e\xf0\xef\x06\xbb\x4e\xbd\x48\xb9\x30\xac\x77\x40\x26\x20\x69\x04\x60\x56\xd1\x8a\x4f\xef\x1a\xf9\x25\xd0\x95\x04\xc8\xe2\x75\xfd\x71\x80\x6c\xde\x08\x67\xfd\x47\x88\x29\x58\x55\x44\xe0\x96\x7a\x52\x96\x51\x43\x30\x6b\xdb\x2a\xa5\x77\x91\x22\x39\x37\xbe\x14\x8e\x9f\xe5\xf6\xda\xbc\x50\x02\x51\xae\x65\x67\x11\x12\x36\x50\x01\x27\x9b\x29\x48\xed\x6a\xc3\xe0\x5d\x38\x15\x56\xcb\x3d\xbc\x32\x69\x64\x39\x93\x2a\x79\xce\xcc\xf6\x9d\xf3\x78\x71\x8a\x74\xba\x1b\xa5\x9f\xf9\x1c\xda\xbd\xa7\x6c\x0e\x4e\x70\x4c\x03\x97\xe2\x98\xd9\x4a\x58\xec\x5b\xdd\xe1\x99\x5f\x33\xe1\xae\x4e\x6c\xda\xb9\xae\x86\x63\x27\x75\xed\x4e\xe9\xaa\xb9\xee\x70\x78\x73\x4a\x01\xde\xbd\x39\x39\x69\x73\x3c\x6d\xfb\x5f\xd3\x49\xe5\xca\xb0\x0d\xb3\x06\x2e\x0b\x3b\x0d\x47\x2b\x62\x67\x2b\xcf\x92\xb9\x0e\x20\x01\xe8\x07\x71\xa6\xab\x63\x53\x7b\xda\x33\xc3\xdf\x2d\x2a\xfb\x99\xe4\x47\xe2\x12\x91\x52\x92\xec\x39\x3c\x07\xc2\x23\xeb\x88\xf1\xfb\x52\x77\xca\xf4\xb3\x2b\x7e\x37\x6c\x44\x7a\x69\xec\xee\x16\x7c\xb7\xb2\xd1\x07\x64\xcb\x82\x7d\x84\x56\x5b\x58\x5a\xc9\x76\x1d\x70\xa9\x8c\x48\xad\xed\x81\xfa\x6d\xe2\xff\xb6\xb8\x13\xfb\xf6\x40\xd6\x5b\xea\x91\xa7\x84\x96\x1c\x46\x2b\xa0\xec\x51\x7a\xe2\x69\x37\x8e\xc0\x2d\x10\xbe\x36\x1c\x3c\x57\x50\x07\x9e\x3c\xc2\x3a\x0b\xbb\x7f\xd8\x3c\x2f\x51\x52\x71\x7d\x6f\x2c\xca\x5a\xf3\x26\x67\x18\x8b\xa8\xad\xe8\x72\xb5\x08\xe4\xfb\x0c\xd7\xcf\x49\xc2\x94\xbd\x34\x28\x9b\x28\x88\x85\xc9\x8b\x96\xee\xe3\xa9\xf6\xd6\xba\x98\x8e\x3a\x98\x0f\x3e\xa8\x47\x8e\x5f\x91\x39\xde\xb1\x65\x48\x3a\x5a\xd3\x39\x13\x17\x0b\x90\xa3\xa2\x06\xac\x5d\x22\xb0\x06\xd3\xcf\x32\xef\x49\xfb\xad\xb2\xdf\xf4\xe9\xde\x2c\x4c\x2e\xba\x65\xee\x01\x87\x57\x69\x5e\x66\x25\xb8\x8f\xac\x1f\x9d\xde\xa1\xce\x99\xfe\x6d\x42\xd3\xbe\xd6\xf9\x8b\x21\xa6\x98\xde\x91\x08\x58\xb2\x25\xb3\xe8\x16\x78\xf7\x71\x68\x06\x6a\xcb\x44\xa4\xae\xf5\xd7\xd4\xaa\xbc\x04\x4e\x46\x45\x85\xf7\xd5\x7a\x77\xa1\x78\xcf\x90\x96\x38\x84\x30\x3d\x84\x1d\x3b\x12\x48\x4b\x97\x54\x2f\x0b\xcb\xc0\xc8\x20\x6f\x59\x5e\xa1\x91\x61\x39\x92\x73\xcf\xa0\x3e\xfa\x9c\x59\xbb\x6b\x5e\x6e\xc5\x7b\x42\x04\xe7\xbd\xd2\x89\xa9\x9c\x74\x74\x2b\x9a\x0e\xd8\xc4\xd6\x1e\x19\x3a\x84\xb2\x85\x2e\x13\x69\x39\x25\xae\x5c\x71\xf6\x54\xd0\xc4\x00\xe2\x95\x30\x5d\x19\x38\xb4\x2d\x43\x56\x46\x44\x0e\x64\x05\xf9\xed\x5d\x91\x04\xd7\x5c\xc3\x8f\x80\xde\x97\x26\xde\x16\x0d\x12\xd0\x7c\xea\x2d\xd9\x09\xb8\xde\xed\x34\x55\xe5\x84\xa6\xa6\xbc\xb4\xf6\x28\x6d\xec\x65\x0d\xf4\xef\xf5\xc7\x88\x74\x11\xaf\x74\xb7\x6e\x72\xa2\x62\x2f\x42\x55\xc8\xf7\x5c\xc1\x3d\xa5\xbc\x66\x8d\x19\xfb\x9e\x39\x03\xa4\xfa\xa1\xaf\x49\x73\xe8\x6d\x8e\x69\x93\x5c\x63\xa8\xa1\x6f\x15\xa3\xf8\x3b\xa0\xbe\x83\xa6\x68\xd6\x6c\x53\xf7\xaf\x4e\x6b\xa7\xe9\x85\xbd\x8a\x7f\x84\x0d\x36\xa8\x70\xf9\xd2\xad\x68\x36\xb4\x01\x44\xf7\xda\xe4\x8f\x15\x0b\xff\x64\xef\xbb\x70\xf6\x1e\xff\x10\xeb\xab\x65\xbe\x78\x28\xd9\x1f\x6d\xc5\x5e\x73\x1e\xcd\x66\xcf\xe5\xad\x88\x45\x09\x44\x72\xe1\x72\x13\x54\x8d\x29\x01\xf5\xd5\xb5\xde\x9c\xe3\x25\x70\xf0\x1a\x83\x77\x0b\x07\xdd\xdf\xad\x4c\xfc\x55\xf2\xe4\xf3\xaf\xe7\x6b\x22\x70\xd3\xc1\x53\x81\x87\x70\x74\x70\x12\x74\x18\xcf\xeb\xcc\xc8\xae\x7f\x43\xd1\xc2\xcb\x97\xca\x99\x5e\x3b\xd3\xe3\x60\x1f\xac\x07\xf0\xa0\x09\x61\xe2\xde\x04\xf2\x57\x6a\x09\x5b\xf3\x31\xcd\xca\xa9\x83\xff\xf5\xa2\x58\x97\x7f\xda\xaf\xd8\x65\xbf\x12\xa1\xc4\x3b\x71\xd6\x70\xf6\xe8\x84\xc9\xb6\x46\x82\xef\xe3\x16\xb2\x78\xa8\xfa\xf0\x8a\x79\x11\x9f\xff\x6c\x3a\x55\x2f\xdf\xf2\xa0\x2f\x81\xb9\xf1\xff\xd4\xdf\x32\x78\xdc\x7a\x1b\x4f\x9f\xfe\xfa\x59\x38\x35\x47\xd6\xf2\xda\x15\x85\xb5\x39\x84\x3f\xcf\xc0\x0f\x2f\x73\x8b\xf2\x77\xed\x58\xdf\x01\x3b\x4e\x01\x8f\xb6\x70\x78\x0b\x69\x4c\xa3\xa1\x08\xf9\xec\xf4\x7d\x0d\xc1\x4c\xa0\x92\x43\x3a\x14\x56\x3e\x82\x2a\xaf\x55\x72\xa3\x3d\xdf\x47\xc2\x94\x53\x44\xc3\x1a\xc2\xa4\x69\x2d\xc2\xf7\xbe\x75\x1b\x95\xec\xdb\x92\x0e\x61\x3d\xaa\xd4\x3d\xaf\x2a\x2b\x62\x8b\x25\x8a\x8a\xdb\x40\x69\xcb\x3b\xcb\x11\xf5\x2a\x61\xa6\x7a\x7d\xf1\xcd\x35\x44\x35\x4f\x82\x88\xcf\xab\xac\x59\xe0\x64\x58\xd9\xca\xa9\xd5\xa1\x18\x82\x2a\x07\x84\x64\x83\xe9\x52\x18\xbc\x42\xf2\x93\x67\xc0\x4a\x22\xa4\x3c\x4f\xe9\x76\xee\x63\x60\x9b\x99\x1d\x03\x7c\x59\x50\x76\xe4\x91\xe2\x6e\x43\x13\x90\xbf\x78\x0d\x4c\xf2\xda\xfe\xeb\x2a\xa0\xe6\x96\x7e\x97\x2a\x65\x4f\xe1\xaa\xbd\x35\xf4\xa8\xb7\x59\xe3\xcc\xff\xc0\x37\x35\xf5\xd6\x9c\xe8\xea\xc1\x40\x88\xd8\x65\x71\x41\x57\x6a\x41\xad\x55\x3a\x72\x2b\xd2\x41\x04\x31\x03\xef\x75\x32\xb4\xa1\x48\xc7\x43\x40\xfe\x93\x57\x6b\x85\x66\x88\xa4\x40\xa1\x5b\xe8\xbd\xf2\x2a\xee\xd5\x2a\x42\xcb\x5a\xdc\xe3\x9b\xdb\xef\x41\xaf\x76\x08\x73\x94\x00\xd7\x32\xc9\xf1\xb5\x8c\x4c\x26\x5b\x10\xa9\x8b\xb5\xa8\xd6\xb8\x16\x59\xf1\xd9\x9b\xe2\xfe\xba\x08\x81\x9c\x1c\x09\x6f\xfe\xce\x59\x20\xa4\xc5\x75\xca\x23\xa2\x5d\xe7\x3d\x84\xcc\x4e\x38\xae\xda\x68\x6e\x42\x7b\xee\x31\x7f\x1a\x21\xa5\xab\xb3\x2e\x6e\x1d\xab\x6b\x0a\xa2\xc0\xc6\x04\xc4\x19\x89\xb6\xa6\x56\x6a\xad\x8d\x30\xbb\x6b\x70\x66\x2c\x18\x40\x0c\x64\x48\xd7\xda\xb0\xf9\xf2\xc0\xff\x91\xbd\xcf\x8b\x82\x7d\xa2\x39\xe9\xca\x09\x16\x94\x2c\xf9\x8d\x0c\x68\x07\xae\xd5\x7f\xe9\x56\xb2\xbe\x6c\x28\x34\x09\x0a\xfd\xf9\xb0\xe0\xb0\xa6\x57\xc0\x0e\x56\x8c\x15\x08\x69\x7e\x05\xee\xd0\x42\x5e\x6b\x9b\xb7\x8c\x7b\xa0\xa9\x25\x5f\x5a\xe5\x00\xe3\xbe\xb5\x0a\xe2\x3e\xd8\xfb\x35\x71\x73\x90\x34\xd4\x2a\xe3\x83\x0e\x22\xa4\x99\x3d\xc5\x0b\x57\x08\xc4\x62\x41\x53\x31\xd5\xaf\x05\x52\x43\x27\x78\xc4\x3f\x74\x2d\x21\xfe\xa3\x6d\xd3\x91\x36\x6d\xbe\x81\x4a\x40\x50\x37\x44\x6b\xeb\xd5\x42\xed\xdc\xe7\xa6\xc0\xda\x71\x32\xb8\xa6\x44\x4f\xd9\x7a\x0b\x4c\x2d\x3c\x31\xcb\x26\x4b\x25\x7a\x67\x39\x21\xfa\x24\xab\xda\xda\x04\xea\x16\xf0\xea\xf8\x7d\xfe\x82\xaa\xf7\x08\xc2\xb8\x15\x7d\x24\xdd\x67\xa9\xf4\xbb\x14\x60\x3a\xfd\xf8\x28\xff\x30\x58\x65\x61\xb2\xa8\x45\x59\x8a\x4c\x85\x97\x12\xfa\x2f\x88\x2e\x09\xa6\x42\x1a\xcb\x37\xdb\x39\xb5\x5a\x6c\x04\x40\xf8\xb4\xf5\xfb\x34\xd0\xb5\x91\x03\x16\x6b\x65\x4b\xb8\x48\xfd\x7c\x11\x8e\x76\x59\x93\x4f\xd5\xe1\x53\x3b\x92\x6d\xe3\xe2\xa7\x42\x51\x37\x2f\x81\x25\x64\x01\x10\x34\xaf\x58\x8b\xe5\xe7\xb8\xb8\xf9\x82\xff\xc7\x79\x1d\x89\x95\xb0\xa8\x2f\x6f\xb9\xde\x46\xd7\x67\x91\x4f\xfb\x16\xd7\xba\x50\x0f\x09\x77\xda\xeb\x96\x3d\x2d\x80\x9b\xf2\x94\xcd\x7e\x7c\x02\xc3\xf3\x1f\x8b\xda\x75\xf8\x4a\xac\xce\x61\x70\xfb\x48\xf1\x1b\x13\x38\xfa\x2d\xdf\xb3\x10\x49\xbd\xa4\x4b\x0b\x61\xd5\x53\x5c\x75\x9b\x48\x07\x8a\x3e\xcd\x21\xd0\x3a\xbf\x66\x2e\x77\x47\x6b\xd7\xb3\x27\x07\xfe\xb7\xda\x0f\x8e\x49\xfa\x6f\x05\x67\x08\x01\x78\x7c\xcc\x8b\x43\x80\x75\xa0\x16\xe6\x2f\x7a\xb3\x3d\x14\x58\x11\x37\xb9\xd6\xc7\xe3\x9c\xc3\xf0\xd6\x7f\xf7\xaf\xaa\x12\xbf\x48\xb4\xf0\xfe\xfe\x42\x34\x77\xe7\x97\x52\x87\xfb\xf5\x69\x41\x80\xc5\x31\xdf\xf2\xf4\xcd\x6f\xaa\x7e\x91\x7e\x13\x38\x19\xbe\xaf\x3d\x80\xcc\x52\xff\x72\x9c\x35\xbf\xd2\x95\xc2\x2b\x57\x8a\xae\x17\xe7\x4d\xf3\xce\x7b\x38\xef\xac\x2e\xdb\xcc\x88\x7d\x37\xd0\xd2\x0f\x30\x99\x10\x67\x8e\x87\x20\x05\xc9\x25\xc8\xd1\xd4\x4d\x9c\xde\xab\x8c\xf6\xa7\xfa\x4f\x65\xa6\x29\xd4\x57\xeb\x86\xdc\xdc\x9b\x98\xf3\x48\x8f\x4c\x04\x17\x4f\x6e\x04\x33\x68\xc3\x15\xe0\x0f\x8f\xfa\xc5\x5e\x4d\xa2\xc4\x5f\x59\xd2\xae\x3e\x11\x97\xbf\xee\x53\x18\xf0\xda\x90\xe3\xf5\x14\x62\x72\x2a\x97\x70\xe9\xc7\x28\xd4\x73\xd9\x04\x8c\x75\x18\x79\xa0\xce\xed\x25\x5a\xe9\xaf\x5b\x16\xca\x4b\x63\xb4\x74\xa4\xea\x59\xed\xa9\x44\x16\x0c\x6a\xb0\xf1\x16\x30\x0e\xe3\x13\x7c\x12\x47\x6f\xb2\x1b\xe3\xae\xb6\x40\x78\xb9\x02\xeb\x1c\x9e\x6c\x53\x53\x9e\x46\xb4\xea\xdf\xcf\x7b\x48\xc6\x76\xce\x85\x9e\xbc\xbf\xf0\xe0\xfc\x04\x6a\xfc\xbc\x3f\x71\x7c\x17\x79\x6f\xa7\x01\xa0\x51\x62\xf0\x47\xe3\x75\x3f\xa5\x05\xbb\x07\xd6\x1c\xd4\x1f\x0f\x34\x4c\x80\x14\xcd\xc2\x6d\xd6\x31\x9e\x23\xa0\xd3\xaf\x22\x37\x5f\x1b\xd5\xfa\x72\x54\x1e\x03\x0a\xb3\xda\x75\x94\xc4\xec\xc3\xbb\x6a\x97\x98\xed\x43\x40\xf6\xbd\x86\x97\x6f\x0d\xa1\x5c\x6b\x89\x42\x4b\xf6\xa6\x58\x0f\xbc\x7f\x67\x7a\xfc\xba\x7e\xd4\xa5\xd0\x25\xf6\xa7\x90\x4d\x07\xd6\xbd\x84\xcc\xec\x76\x85\xbc\xac\xde\x50\xc8\xca\x6a\xd5\x57\xb9\x71\x8a\x61\x10\xcc\x44\x43\x04\x0e\x23\xf9\x98\x7f\xb9\xa2\xec\xc5\x89\x1e\xe2\x51\x00\xe4\x1a\x93\x4c\x80\xdf\x1d\xfa\x5c\x5d\x57\x33\xd3\x2c\xf8\x2b\xfd\x0c\x48\xfc\xa3\xbc\x03\xb0\x5e\x57\x87\x4c\x9f\xf3\x25\x24\x35\x52\x4c\x3a\x43\x1b\xc2\xbd\xb8\x59\xa0\xd3\xe5\xa1\xef\x08\x73\x45\xa7\x44\x8e\x46\xf2\xa6\xec\x49\x95\x46\xab\xe3\xca\x1d\x16\x60\x21\x07\xd3\x6e\x16\xcc\x60\x3d\x26\x6d\xa6\x31\xf9\x58\x1a\x0c\xdc\xc1\x1b\x8a\xfc\xab\x55\x4c\xd9\x71\x3e\x87\xaf\x83\xb0\xab\x5d\x78\x90\xa4\x05\x8b\xb1\xe4\x41\x1c\x36\x66\x37\xcd\x56\x78\x10\x38\xdd\x3a\xfe\xde\x83\x66\x24\xdc\x75\xb3\xf6\xc5\x4c\x7f\x17\x58\x7d\xa3\x55\x07\x3e\xe4\x5b\x2f\xe6\xf8\x47\x4f\x14\x31\x99\xb3\x23\x2a\x30\x82\xaa\xc3\xbd\xd1\xab\x72\x0c\x3d\x00\x5a\x25\xf6\x57\x5b\x05\xbc\xb9\x5f\xcd\x24\x03\x59\x97\x7c\xd5\x57\x42\x08\x20\x48\x9c\xe2\x5a\x98\x89\x47\xb7\xd3\xf3\x7f\xce\x6e\x0e\xb8\x71\x59\xf2\x86\xfd\xe5\xa3\x36\xd1\xd0\xc7\xd9\x54\x55\xcf\x79\x26\x3c\x7c\xce\xc3\x4a\xf0\xb7\xcb\xba\xb6\x5e\xc5\x3e\x0b\x84\xf8\x38\x13\x47\x19\xc8\xbd\xfa\xd2\x6e\x34\x91\xe7\x01\x9d\x7a\x14\xe8\x89\x31\xc2\x34\xd6\x83\x55\xc3\x90\x47\x89\xd2\xfe\xa3\xb0\xfc\xfd\x50\x9f\xe0\x3e\xc5\xc4\x8c\x0b\x80\xbd\x66\xd9\x2b\xc3\xba\xd8\xbb\x31\xa8\xbe\x8a\x4f\xff\x10\xdc\xe2\x31\x9f\x34\x42\x7a\x40\x4a\x4d\x0d\xde\x63\xde\x1f\xf2\xd8\x79\x60\x5c\xcb\x76\xe5\x31\xb7\xc3\x38\x79\xd8\xd7\xb9\x44\x78\x03\x8a\xef\x89\xd9\xc9\x47\x30\x09\x1e\x36\x82\xd5\x3b\xf6\x80\xa2\x1c\x45\x62\x9f\x74\x54\x46\x2e\xc1\x77\xb4\x6b\x42\xd3\x65\x9f\x43\xfd\x48\x3f\x96\x5f\xb5\x25\x9f\x9d\x07\xb0\x30\xef\x1f\xe1\xca\x83\xf6\x6c\x1f\x62\x65\x40\xda\x13\xfb\x82\x07\x6c\x88\x42\x51\xd6\xe7\x0f\xf9\x5a\x08\x73\xce\x51\xd8\xcd\xf4\x22\xca\xa7\x8f\xcc\x90\x71\x3b\x7d\x49\x14\xea\x17\xf0\x96\xb7\x47\x3c\x9f\x79\x53\xf5\x0d\xee\x6d\x92\xfe\x41\xcb\x5d\x09\x0d\xc8\xab\x3c\x0e\xa0\x22\x90\x62\x9f\x15\x43\x70\xef\x66\x90\x5c\x6a\x87\x62\x5b\x89\x6b\x2b\x5b\xe5\x41\xd2\xe6\x39\xfc\x04\x81\xe1\xf6\xff\x60\xc3\x12\x99\xa6\x0e\x35\xe0\xd4\xf0\x9e\xd7\x2a\xbf\xac\x43\xdd\x57\x26\xef\x1c\xab\xce\x55\xe1\xc8\x39\xd4\x31\xfc\x92\x65\x67\x6a\x11\x21\xd1\x57\xa9\xde\xc3\x0f\x27\x79\x8e\xc3\x29\x96\xe3\x50\xaa\x8c\x8f\x85\x15\x1a\x90\x88\xd5\x92\x1b\x48\x82\x77\x28\x2b\xc7\xea\x83\x3d\x3c\x82\x78\x37\xe2\xfa\x00\xdd\x2b\x07\xd5\xe3\xc7\x73\x38\x05\xfc\xf8\xd9\x11\xb5\x0d\xc3\x38\x02\xc8\x5f\x84\xae\xe7\x60\xd8\x0d\xe0\xa3\x8f\xd4\x89\x85\x50\xb0\x12\x73\x03\xa4\x82\x7d\x79\x07\x9c\xfc\xe2\x36\xe7\xb7\xa7\xb3\x0f\xc5\xc9\x94\x8c\xb9\xea\x28\x01\x32\xdf\x6d\x3e\xa8\xff\xf6\x15\xa5\x15\x0c\xc3\xf1\xe6\xef\x08\xe4\x14\x9d\xd7\xda\xeb\x4c\x56\x0a\xcf\x66\xa8\xef\x34\x54\x3a\x65\x54\x10\x68\x05\x94\x82\x3d\x9a\x27\x9e\xec\x14\x62\xbc\xae\x23\xcb\x68\x62\x0b\xef\x36\xcd\x95\xdf\x76\x76\x1b\xf8\xad\x14\x7c\x86\xf0\xce\x1c\x32\xf9\xcb\x43\x92\xc5\x34\x06\x72\xe1\x0f\x34\x00\x6b\x4b\xdf\xc0\x21\x85\xb6\xae\xc8\x09\x69\x0a\x67\xe6\x89\xbe\xfa\x43\x92\x6b\xe0\xe0\x34\x64\xc7\x02\xd7\x5b\xaf\x4b\x5f\x65\xb9\x85\x9c\x8b\x80\xc6\x5e\x26\xbf\x18\x91\xbc\xd5\xd7\x50\x33\xeb\x21\x8f\x76\x31\x5b\x0d\xd7\x15\xbe\x00\x16\x59\xef\x8b\x33\xeb\x4f\x72\xc2\x9d\x4d\x1e\x6a\xbc\xc7\x25\x08\x7c\x91\x56\x2c\x0a\x03\xcc\x59\x3b\x02\x5e\xc6\x75\x88\x13\xd4\xb5\x1d\x24\x7c\x72\x26\x0b\x3c\xfc\x20\xc8\xf8\xb3\xe9\xe6\x3e\x85\x39\x3f\x29\x5c\x0b\x2c\x05\xad\x95\xed\xa8\xfa\x15\xd0\x54\x52\x74\x04\xe6\xfc\xd0\xb8\xab\x47\x16\x91\x10\x6c\xb7\xfc\x21\xde\x19\x9c\x7d\x12\xad\xa0\xd1\xcb\x69\x53\x5f\x36\x15\x92\x01\x66\x97\xad\x5d\x2f\x49\x88\xbe\x4c\xa1\x05\x6c\x23\x2b\xc1\xc1\xcb\x1f\x04\x3d\x19\x03\xf6\x9a\x48\x31\xbb\x27\xf1\x1b\x92\xbe\xc4\x2b\x22\x81\xc6\x84\x3f\x45\x7a\x19\x58\xf7\x2c\x15\x60\xe1\xfe\xe7\x9b\x0d\xa4\x05\x81\x64\xb7\x6e\x48\x17\x03\x45\x8a\x2f\x8a\x7c\x3a\x21\xc0\xfa\xfa\xeb\x44\x1d\xc2\xbd\x8d\x6c\x10\xae\x75\x54\xf5\x3d\x19\xd9\xdc\x81\x5f\x4a\x88\x1b\xc1\xdc\xc7\xaa\x59\x68\xf9\x3c\xf3\x86\xdb\x60\x6e\xd2\x2a\x7b\x16\x25\xc5\x2b\xbb\xfb\x1e\x7a\x4c\x84\xbf\xaf\x6b\x20\xdd\x91\x82\xe0\x46\xbf\x04\xc9\xa7\x67\x43\x04\xf4\x98\xa3\xea\xce\x40\x17\x58\x72\xc4\x48\xd3\x48\x82\xd7\x63\x37\x2d\xe6\x87\x4b\xf6\x04\x3d\x6c\x32\xb2\x20\xec\x72\x8b\x81\x14\x21\xf7\x77\x6e\x07\x7f\x1f\xe8\x92\x4d\xa1\x13\xda\xc2\x65\x7f\x2b\x8a\x0d\x56\xe5\x77\x01\x86\x1f\x02\x5f\x7f\x1c\x25\x50\xf1\xb9\xd7\x2a\x09\xca\x23\xf7\x18\xff\x7b\x97\xf2\x71\x72\x55\x0d\x7d\x9b\x05\x6d\x5f\x7b\x94\x51\x78\x69\xd2\xd0\x64\x88\x3b\xbd\xe9\xdd\x9b\xea\xaf\xef\x3f\x72\xc1\x77\x3f\x11\x0e\x5b\x03\x6a\x5d\xc5\xe5\xe9\xaa\x97\xa7\x89\x92\xad\x9c\x55\x76\xc4\xd5\x63\x26\x25\x58\x70\x85\x9c\x5a\xd3\x0d\xae\x0d\xf8\xcc\x91\x8d\x47\x83\x06\x9c\x80\xc0\x87\x86\x31\xc0\xf0\x9a\xd5\xc3\xef\xfb\x97\x70\xfb\xb3\x6e\xab\xdc\xb0\xd1\x6b\xe8\x00\x36\xe6\x9d\x9a\xfd\x77\x6d\x68\xf6\x12\x23\x6c\x0b\x63\xcc\xe0\xe2\x8d\x3c\x94\x32\xf3\xe0\xbb\xea\x94\x2c\x1a\xd8\x9e\x42\xe3\x40\xbd\xac\x85\xb1\x9c\x83\x33\x06\x2c\xfc\xa0\xb5\x78\x02\xc8\x52\x04\x75\x37\xc5\xbf\x49\xa1\x7d\x9c\xa8\x92\x21\x5f\x73\xb1\x64\xba\xf2\x4f\x92\xbe\xa5\x86\x6a\x30\x72\xd9\x9c\x76\x03\xf6\xae\x7f\xa4\xdc\x23\x00\xef\x01\xd8\x2f\xa7\xd3\x49\x5d\xab\xf8\x64\x00\xd9\x97\x33\x80\xee\x36\x26\x2e\x52\x1f\x46\x2b\x42\x4d\xe4\xe0\x15\x94\x5f\xde\x4c\xa4\x6e\xb8\x0c\x98\x5b\x57\x46\xfd\xa4\x22\x0c\xbf\xb5\x75\x40\x0a\x10\x93\x6e\x97\x4d\x33\xdb\xae\x74\xba\xd7\x48\xdd\x91\x58\x80\x21\xa0\x4c\xb4\xe1\x57\xc4\x75\x48\x4b\xcf\x8c\x9c\xa9\x28\x4f\xed\xdf\x72\xc6\x8d\x43\x8b\x20\x41\x65\x3f\x80\x07\xf6\x6b\xfc\xe8\x33\x44\x70\xd7\x10\xbe\x6e\x96\xf6\x9d\xd0\x90\xdd\x3c\x0c\x6e\xa6\xe7\x41\xa0\xf1\x67\x40\xef\x43\xd3\xf8\x29\x86\x01\x5e\x04\xfa\x8a\xa3\x70\xec\x6d\x23\x60\xf0\x36\x2e\x8b\x9e\xdc\x89\x6a\xb7\x02\x00\x41\x3f\x8c\xd7\xb9\xd9\x99\x37\x6f\xf2\x73\x69\x45\x99\x0e\x4a\x38\xdc\x6d\x97\x47\xbc\x0d\x21\x22\x5a\x55\xde\xed\x32\xce\xaf\xf1\x0e\xb2\x3d\x80\xf1\x60\x22\x09\xae\x20\xa8\x01\x50\x62\x51\x98\x02\xe9\xd8\x25\x2f\x54\x3a\x5a\x1d\x40\x34\xc6\xfa\x3f\x29\xc4\x1d\x21\x6e\x2c\x49\x64\x0b\x3a\xed\x11\xe9\x78\x0b\x3b\xf1\x2c\x00\xea\x1e\xd8\x31\x74\x54\xef\x3d\xb9\x71\x53\x41\x9e\xf9\xab\xd4\xbc\x60\xd9\x04\xa2\x3d\x66\x4e\x02\xb1\xb5\x97\x8c\xfa\x44\x59\x06\x0b\xbd\xc7\xe8\x92\x6c\xda\x67\x32\xd1\xd2\xc7\x7f\xa9\x7b\xbb\x24\x06\x5f\x88\x6b\xaa\x97\x8a\xff\x09\x43\x0b\x5f\x02\xed\xee\xe8\x71\x88\xa3\x3a\x84\xdd\x26\xe1\x2c\x32\x41\x2d\xb9\x95\x2d\x92\x46\x06\xf8\xd1\x75\x50\xa0\x1d\xf2\x4e\x04\xfd\x50\xa5\x64\x0c\x61\x2c\x1e\xff\x4c\x12\xf0\x49\xf0\x55\x14\x22\x5e\x4a\xee\x8e\xd8\x0b\xed\xe3\x8b\x94\x23\xaf\x7a\xf0\x4b\x71\xeb\xd2\xf6\x72\x63\x6a\xe0\xe8\x29\x52\x94\x02\x2a\x0f\xd0\x0e\x91\xef\x92\x08\x4b\x6b\xe1\x62\x0d\x4b\x56\xcd\x20\xa0\xf6\xa9\x67\xdc\xae\x94\xde\x71\x9b\x0f\x66\x0e\x4e\x5d\x09\x43\x28\x7d\xd8\x3b\x10\x2a\x3f\x70\xa0\x05\xb4\x22\x3b\x1f\x46\x4d\x16\xd9\xb3\x44\x10\x3e\x26\xc2\xbe\xeb\xbe\xc8\xfa\x2e\xf9\x2d\xfd\x28\x39\xfb\xa9\x92\xc4\xfb\x40\xbb\xd6\xef\xea\xa7\x66\xce\x10\x3f\x1c\x97\x7f\x8a\xf7\xfc\x1f\x96\xd4\x3f\xd9\xc7\x82\x1f\xe6\xef\x3f\x99\xb2\x33\x1f\xa7\x89\xdd\x0c\x3d\x6d\xfd\x2e\xf5\x72\x32\xfc\xbb\x10\x34\x5f\x98\xe2\x7c\x67\x80\x42\x1c\x67\x9f\xf6\x58\xfa\x33\xf0\x4e\x32\x2d\x04\x4a\xde\x11\xd6\x6f\x19\xa7\x07\xb9\x14\x91\x98\x84\x40\xd0\xd3\xf0\xbc\x08\xdd\xf6\xf2\x4c\x04\xbd\xcf\xcb\xa6\x6a\xe4\xcb\x86\x73\xd7\xe7\xcd\xef\xc5\xd0\x78\xed\x39\x60\xf4\x3e\x04\x74\xe7\x75\x06\x91\x71\x79\xcd\xca\xc7\x00\x43\x4f\xbf\x74\x1b\xec\x2c\xde\x72\xbc\xa8\xde\x41\xd0\xfd\xba\x4e\x25\x3c\xdb\x57\x0d\xf7\x5e\xb3\x7e\x06\xf4\xb2\xb8\x42\x08\x7c\x41\xce\xe7\x74\xf3\xe2\x03\x43\x9f\x55\xd4\x7d\x4d\x76\x61\x35\x1d\x76\x3b\x77\x1f\x94\x41\x7e\x39\x55\xc9\x29\xbf\x39\xc2\x7d\x79\xb6\xfa\x0b\xad\x1f\x70\xbb\xfc\x1f\x64\x31\x20\x5c\x84\xd9\xc1\x08\x0e\xad\x8f\xd6\xca\x3e\xac\x78\xf8\xe2\x83\x67\xfa\x5f\x01\x8b\x6b\x3a\xb2\x2f\x81\xfa\xc3\x6e\xc9\x82\xa5\xe9\x48\x27\x25\x95\x2c\xf8\xca\x85\xd8\x87\x59\x10\x7a\xbb\xb6\x99\x11\xaf\xbf\xcf\x45\x79\x7f\x30\x38\xe3\x77\x71\xbe\x02\xbe\xbd\xdc\x5a\xd4\x6f\x9c\x4d\x14\x04\x45\x40\x18\x66\xf9\xa1\xfc\xfd\x02\xfc\x0b\x3f\xeb\x09\xcf\x76\xe2\xe9\xc1\xec\x42\xc6\x0c\xfb\xc0\xdb\x65\xa6\xaa\xf1\x93\x22\x16\x0e\xa3\x3f\xcf\x2a\x69\xe8\xd5\x5f\xb6\x16\x4a\x37\x7a\x85\xe4\xcd\x93\x1e\xf1\x20\xe1\x73\x6d\x7f\x87\xc1\xcd\xd3\x26\xf2\x42\xd5\x43\xe7\xed\x62\x68\x0f\xcb\xbc\x09\x32\xaf\x84\x12\x3d\xf3\xe4\x09\x9f\x89\xe6\x7a\x7a\x66\x21\x33\xa2\x0a\x75\xda\x9f\x39\x80\xf0\x37\x00\xef\x45\x80\xf7\x1c\xa0\xf9\xa1\xc1\xe7\x7b\x4e\x9a\x2d\xb2\x26\x92\x65\xfc\xa7\x2b\x9b\x4f\x3a\x82\xb5\xd0\xcf\x39\x3b\x7a\x25\x7c\xe4\x2b\xc1\xd9\xf5\x18\x72\x40\x92\xea\x7e\x7a\x41\xbd\x42\x6d\x86\x10\xee\x77\xcb\x1f\x5a\xfb\x4a\x91\x99\xbb\xee\x81\x37\xaf\x19\x18\x4d\xa2\xd0\x35\x66\xb9\x25\x18\x0a\x14\x39\xd5\x02\x6e\x98\x00\x4b\xd1\x58\x23\xd6\x1b\xa2\xee\x44\x5f\xdd\x85\xed\xf7\xad\x69\x27\xae\xe7\xc7\x97\xac\x07\xb5\x26\xf6\x2e\x84\x11\xdc\xa5\xa1\x9f\x6f\x7b\xe5\x67\xae\xa3\x28\x32\xe6\xf2\xfe\x85\x9d\x03\xa1\xe8\x32\x0d\xb9\x27\x02\x9b\xef\xe9\x14\x2c\x9c\x6a\xce\xfc\x4e\x58\xf9\x29\xd7\x7d\x16\xcf\x1f\x7c\xb8\x4d\x22\xd0\x59\xa8\xf4\xfc\xef\xf6\x44\xdc\x0d\xb0\x90\x1f\x2d\x53\x98\x5b\x9a\x69\x77\x5e\x12\x5b\x78\x7b\x5f\x4f\x8a\xfc\xde\xd9\xad\x75\x6e\xb9\x97\xc1\xbb\x5e\xea\xe2\xb7\x5d\x38\x97\xe4\xe2\x3f\x0f\x89\xc5\x3b\x51\xf4\x03\x3a\xc5\xf4\x85\xbd\xdd\x23\x8a\xa7\xad\xc6\xf0\x8e\x6c\xb1\x05\x60\x99\xce\x2d\x0c\xca\x40\x5a\x2f\xed\xbc\x12\x21\x0c\x9d\xe8\x81\x6b\x88\x01\xbe\xd3\x94\xb5\xa3\x35\xe9\x3c\xaa\xf5\x0f\x5c\x03\xdf\x4c\x0b\xac\x51\xdc\x24\x8b\x79\x7d\xfa\x4f\x3e\x00\x7e\xe0\x27\x87\x69\x0a\x12\xfd\x7a\xcb\x14\xee\x7a\xd1\x3d\xdd\xa1\xed\x6b\x53\x56\xad\xa1\x3d\x8c\xcc\x3a\xfd\x74\x1c\xcf\x2e\xb1\xe9\xd5\xb5\x8c\x7d\xff\xda\xaa\x62\x16\x06\x92\xbc\xaa\x99\x00\x8c\x5d\x1a\xb1\x18\x19\x35\x79\xe9\x50\xd3\xb5\x50\x62\xd0\xd6\xac\xf1\x4b\x58\xea\xeb\x41\xb3\x0f\x94\x2c\xbe\x0b\x91\xbd\x36\xba\x19\xc3\x66\x1d\x54\x85\xe6\xae\x1f\x66\xed\xf7\x57\xe3\x01\x31\x0f\x02\xcd\xe9\x2f\xa2\xfb\x96\xf3\xf9\x0d\x75\x51\x9e\x63\xda\x8f\x76\x54\xdc\xcb\xe6\x59\xea\x38\xf3\xb3\xa1\xcc\xa7\xca\xff\x46\xe5\x69\x6f\x21\xaf\x13\x46\xfc\xf6\x8c\xf8\x79\x1e\x45\x4e\xf9\x21\xa9\x0d\x04\x2e\x71\xd9\xc7\x1c\x12\xb5\x87\xfc\xdf\xcb\x4b\x87\xa6\xf1\xdb\x55\x4a\xc0\xca\x77\x76\x64\x57\x09\x88\x7b\x41\xa5\x4f\xf0\xe8\x22\x6d\xd7\xab\xb8\x1f\x89\x4e\x74\xa7\xe2\x9f\xff\x9e\x8d\xd3\x49\x6b\xd0\x6f\xe1\x77\x37\x5a\xdc\x40\x59\xd6\x77\x5d\x09\x72\xbc\xe0\x57\xe3\x2b\x16\x10\x85\x42\x96\x78\x49\xa1\x49\x3d\x8b\x99\x79\xcd\x67\xe8\x44\xcb\xe3\x7f\x46\x5e\x32\xb8\xe4\xd0\x8d\xe6\x13\x30\x2f\x0b\xdb\x67\x4e\x56\x28\xaf\x78\x59\x2b\x24\x7d\xe4\xa9\x6e\x3a\xf4\x14\x96\xee\x10\x8f\x5e\x69\xf8\x0e\xd1\x68\x2e\x1b\x74\xda\x9d\x0f\xb9\xc3\xbc\xd1\xbf\xc7\x8d\xf6\xed\xb7\x06\xe6\x79\x9a\x01\xb7\x23\x36\x7d\x96\xea\xf5\x94\x8f\x49\xbe\x45\x16\xab\xa3\x02\x50\xbd\x41\xd7\x81\x49\x12\x06\x1d\xb8\xb4\x90\x8b\x3e\xbf\x18\x75\x24\x19\x89\x6f\xc7\x2b\xfc\x20\x7b\x0d\xc3\x07\x59\xb0\x5b\x98\x05\xf4\x9f\xec\x35\x0c\x04\x3c\x25\x1c\xc0\x43\xf5\x24\xa8\xcb\x4c\x0b\xc2\x6c\x13\xa1\x4f\x08\x3e\x1f\x6c\xad\x2f\x99\xae\x5c\xc0\x62\x86\x2c\xb4\xab\x0b\x08\x85\x9d\x57\x16\x54\x2d\x28\x4f\xed\x1b\xd2\xaf\x57\x86\xc8\x92\x70\xe0\xf9\x21\xd4\x7f\x06\xa4\xd0\x7f\x5a\x86\xd4\x04\xd7\xa5\x90\xcd\xb3\x30\xc0\xfa\x19\x70\xdc\xfc\xf1\xff\xd9\x9f\xca\x3b\x5d\xbd\xf4\x33\x80\x7a\xd7\x53\x0c\x56\xea\xc2\xcd\xa6\xf3\x1d\xdb\x4d\xa7\xe6\x50\x8e\x84\xdf\xb2\x50\xf3\x45\x8a\xd5\xa8\xe9\x3c\xbe\x20\xf6\x3f\x82\x7e\xc0\xc3\xcf\x79\xf8\xc6\x7f\x70\xf0\x4d\x84\x3a\xd0\x69\xc0\xbf\x9f\x7f\xc0\xfe\x78\x8d\x03\xe1\x3e\x85\xeb\x2d\xc2\xef\xc9\xe4\xb9\x0b\x55\x6b\x32\x89\x11\x2c\xa1\x9f\x9d\x7c\x10\x74\xa5\x7f\xbe\x09\x26\x2b\x6f\x06\x4c\xd1\x5e\x5e\x5c\xa2\xde\x3a\x10\xf0\x91\xf4\xba\x9c\xfe\x96\x46\x3d\x4a\xd6\x64\x64\x16\xc7\xa1\x3d\xad\x07\x02\xd1\x18\xeb\x34\xdc\xb9\xa8\x59\x2f\x02\x11\x46\xc4\x64\xc5\xa4\xf5\x03\xfa\x63\xc4\x7c\x0d\xd3\xfa\x0c\xc8\xfe\xfa\x4c\x6d\xfe\x06\xd0\xbd\x84\xb6\x2c\x8c\x8e\xf2\x4a\x31\x8e\xba\xd2\xd4\xc4\xad\x33\xd5\x65\x2e\xf9\xd1\x9c\xef\x1d\xaa\x72\x04\xaf\xcb\x48\xf7\xac\x47\x33\xf3\x3d\x6b\x13\x54\x3c\xeb\x76\xb2\x15\x3c\xeb\xb4\x0b\x0b\x2f\xf6\x89\x2b\x69\x46\x8d\xc4\x26\x49\x92\x52\x2e\x17\xf3\x4f\x08\x9a\x03\x3b\x8c\x2c\x99\x6c\x3d\x61\x5f\xe6\xcb\x4d\x60\x7e\x01\xff\xad\x39\x17\xc4\x09\xe8\x7b\x09\x60\x8f\xcd\x89\xef\x2c\x92\xc2\x1e\xb0\x6a\xe6\x2a\x64\xf3\xa5\x80\x1d\xfb\xce\x14\x5d\x14\xbd\xdb\xed\x30\xfc\xdf\xcd\xfa\xf7\xf2\x2f\xd3\x63\x07\x68\xfe\xe5\x30\x27\x68\x53\x48\xda\x5a\x1c\x80\xd9\x75\x0f\xb8\x4e\x52\x09\xa7\x46\xf5\x8e\xda\xef\x88\x93\x3a\xa7\x10\x28\x83\xff\x8e\x9f\x43\x0e\xc6\x2d\xb0\xf7\xe1\xd4\x76\x8a\xe3\xea\xc7\xce\x23\x6b\x52\x67\x1e\x9a\x59\x1f\xa8\x7b\x85\x4b\x24\xaa\xa9\x50\x4d\xa9\xeb\x44\xd7\x2f\xd4\x8c\xe2\x08\x30\x47\x92\xed\xc1\x29\x33\x24\x87\xe2\x53\xe8\x7a\x17\x5e\x7f\xd7\x11\x09\x54\xb3\x37\x72\x4f\x54\xa7\x3a\xed\xf1\xf0\x9f\x86\x19\xa4\x6f\xfc\x5f\x05\xba\xbf\x48\x2d\x00\xc2\xd7\xb8\xaf\x47\x95\x73\x81\x05\x69\x17\x7a\x9e\xfa\xa1\x07\x20\x92\x97\xb0\xf5\x73\xc8\xd2\x1e\x1c\xf7\x01\x62\x4f\xb4\x0b\x1f\x2b\x42\xec\xe5\x21\x7a\x40\xbe\x82\x40\x79\xe0\xef\x2f\x06\x0d\x1c\x5e\x30\x47\xbf\xa5\x89\xbd\x87\x1b\x1a\x80\xf6\x92\xc5\xb6\x80\x1b\x4a\x87\x7a\x2d\x84\x2d\x1e\x40\x71\x31\x33\x65\x61\xcf\xdc\x09\x60\xf6\x55\x22\xd5\x00\x9b\xf9\xb1\x66\x58\xa4\x0b\xf1\xed\xa3\x4d\x3f\x87\x39\x94\x6c\x2d\x92\x8c\xd8\xc1\x51\xab\x2d\xc6\x70\xfb\x00\xf6\x8b\xf2\x4a\xc0\xe9\x17\x6d\xe6\x88\xfd\x39\x42\x5d\x0b\xeb\x95\xbc\xea\xe7\x81\x96\xf1\x85\x10\xef\xc0\x5d\x50\xd0\xfa\xb1\x86\xb1\xc2\x01\x7b\x45\xfd\xea\x0c\x32\x5f\x44\x99\x28\xfb\x7b\x96\xea\x36\xab\x90\x47\x86\xc0\xc0\x92\xb8\x2a\x0c\xb1\x21\xc2\x29\x55\x6e\x8f\x42\x8e\xcb\x4d\x97\x43\x24\xd7\x49\x01\xc1\x09\xf0\xb9\xd4\x11\xd9\x77\x0b\x46\xfd\xb8\x3f\x40\xa8\x23\xa3\x02\xe4\x2f\x01\xba\x42\x81\xfb\x33\xbc\x26\xfc\x62\xe7\x90\x11\x3d\x72\x8a\xab\x94\x45\x33\x3b\xd2\x73\x15\x17\xf8\x48\x97\x60\xac\x84\xf6\xc7\x80\xf7\x80\x0d\xa5\xef\x0e\xa7\x8f\x5e\x7a\xdd\x9f\x39\x78\x05\xe4\x53\x1f\xc8\x85\xcf\x11\x0d\x69\xe1\x4f\x48\x71\xc4\x9e\x37\xad\x10\xec\x0b\x29\x2b\xc7\xf1\xbf\x6c\x0c\x7c\x72\x18\x5c\x62\x2c\x5b\x50\x53\x65\xf5\x12\xc6\x0a\x9c\x35\xb4\x8c\xac\x4d\x66\x5e\xce\xbc\xf5\x58\x14\xf4\xe6\xb7\x6d\xa3\x38\x0a\x50\x15\x5d\x3b\x1b\xdc\x40\xbc\xc8\x0f\x71\xe6\x07\xa1\xf0\xf0\x79\xe6\x33\x2e\xc7\x67\x5b\x4c\x2c\xd4\x4a\x4d\xbf\xac\x07\x25\xc2\xbd\xce\xe3\xbf\xab\x2c\x7e\x15\xec\x42\x9f\x22\xf6\x95\x25\x09\x26\x5c\xa6\x5b\x84\x82\xe8\xf5\xf6\x37\x41\xf7\xf5\xe6\x14\x67\x47\xff\x4f\xf9\xef\x72\x92\x7d\xb2\x53\x36\xc9\xfa\x58\x21\xb1\xd9\xdb\x4e\x21\xc3\x8a\xa4\x7c\x11\x01\xd9\x66\x2c\xbe\x6f\x7e\xb3\xee\x01\xe9\xee\xa0\x0f\xb8\x57\x8c\x07\xfe\x2e\xee\xc4\xce\x95\x81\x12\xdf\x94\x34\xdc\x31\xd3\xf2\x23\xa4\xca\x5b\x60\x7d\x27\x48\x76\x1c\x44\x78\xca\x95\x6f\xd7\x2e\x08\xd7\xf6\x66\xc7\xb8\x41\x20\x29\xd2\x0f\x5b\xd8\x05\x81\xc5\xc5\x8e\xdd\x3f\xfc\x4a\xce\x9f\x82\xdf\x01\xd4\xaf\xa4\x77\x6c\x45\x1e\x9d\x5b\x91\x66\xdc\x56\x6e\xb9\x18\x6d\x21\xfd\x8c\xb2\xdd\x8f\x70\xfe\xb9\x12\x73\x5c\xc4\xdb\xf5\xdc\xd9\x2a\xab\x13\xfb\xb0\x47\xf3\x6c\xf1\x54\x84\xef\x70\xd8\x7f\x6c\x0e\x60\xc3\xa6\xe3\x61\x0e\xce\xc8\xfa\x8e\x59\xbb\xf5\x2a\x19\x68\x0c\xbe\x95\x91\x8b\x70\xe6\xda\x4a\xcf\x9b\x84\x0a\x67\xd1\x32\x73\xc9\xe2\x8b\xf5\xf4\x37\x47\x6d\x90\x70\x09\xd8\xf6\xdc\xc4\xf0\x37\xb5\x56\x10\x13\x26\x25\xa0\x9f\x44\x02\x98\x72\x80\x16\xf0\x81\x69\x0a\x48\x87\xfb\xe6\x4d\x86\x5a\xa5\x48\xbb\x45\xf3\xc3\xfb\xcb\x0d\x39\xa9\xf2\x23\x3c\x3f\x97\x21\x37\x1e\x2c\xb9\xcd\x61\x7f\x44\xf8\x0f\x14\x01\xda\x72\xef\x95\xc6\x2d\x6b\xb0\x6e\x01\xcf\xc4\x5a\xe3\xc4\xe0\x45\xc5\x16\x8f\xa1\x29\xe7\x9b\xf5\x28\x73\x0b\x69\xde\x2f\x4a\x51\x6c\x3d\x34\x33\x0b\x37\x18\x73\x0a\x71\x71\x5e\x93\x1e\x6e\xf7\x5c\xe3\x30\x4c\xc5\x43\x38\x61\x02\xcf\x6f\xcd\xd6\x1c\x82\xe2\x67\xd5\x48\x5f\x9a\xe3\xb3\xe2\x22\xcc\x3e\xb4\xc2\x02\xf2\xdf\x80\xfc\x10\xfb\x4a\x8d\x09\xc0\x9c\x22\xb0\xfe\xe7\x1d\xf8\xff\x48\xc8\x6f\x7d\x97\x04\xa7\x7f\x6b\xca\x8b\x48\xa0\xf8\x00\x5c\x59\xd4\x73\xbe\xbe\x25\x2a\x0c\x50\xbc\x5c\x41\x26\xfd\x00\x6e\xfc\xdc\xe6\xaa\x21\x46\x6e\x27\x4c\x1e\x06\xea\x02\x92\x17\x40\x4c\x25\x40\x6a\x0c\xdb\x7b\xd5\xd3\x88\x65\xf3\x8a\x01\x9f\xa2\x84\x21\x9b\xa4\xc7\xff\xe8\xfe\x36\xad\x73\x1d\x69\xca\x0f\x81\xff\xcf\x9e\x3a\x68\x5b\x90\xd9\x31\xe8\x08\x8c\x8c\xc5\x92\x13\x05\x25\x60\x0a\x96\x80\xa8\x75\x5b\x5a\x41\x59\x63\xb4\xa2\xd0\xc2\x2d\xd7\x50\x7e\xb6\x70\x2a\xb7\xc4\xca\x75\x95\x93\x44\x81\xa0\x3c\x10\x80\xd6\x2d\x61\x12\x26\x16\xc4\x38\x93\xc9\x90\x4f\xa9\xa5\x0f\xdc\x1f\x52\x6b\xe3\x24\xd9\xfc\x90\xa8\xb6\x80\xf2\xa8\x24\x1a\xfc\xb5\x63\x25\x8f\x60\x1f\x07\x0e\x6e\xb6\x24\x7c\xf6\x7b\xe7\x62\x70\x31\xc5\xb5\xbe\x25\x53\xb9\xd6\x9b\x58\x6e\x60\xac\x25\xb6\x63\xed\x31\x45\xd2\xad\x51\x22\x00\x70\xb5\x26\x69\xe7\xe6\x13\x3f\x4b\x6f\xc4\x02\xd2\xef\xd7\x3a\x00\x31\xe7\x51\x14\x32\xd7\xe0\x0f\x7b\xd0\x68\x0a\xfc\x20\x58\x7e\xed\x67\x9e\x47\x58\xf1\xae\x41\x67\x02\x9d\x61\x24\x0c\x04\xa2\xeb\x5a\x2e\x5c\x0c\x6f\x2d\x73\x0c\xa9\xd7\x12\x12\xef\x70\x3c\x0b\x75\x73\xc4\xec\xf1\x3c\xf4\xdf\x5e\xb6\x7a\xf5\x3a\x2e\xdc\xeb\xd9\x89\x61\x7a\xb8\x07\x8d\x61\x91\x3a\x38\xf4\xf2\x54\xea\xb4\x11\x99\x5e\x78\x70\xa0\x5e\x5c\x75\xd8\x6d\x3e\x3c\x82\x1c\x11\xd7\x41\x20\x9a\x40\xfe\xd9\x45\xca\x23\xcc\xfb\xc6\x81\xa9\x7d\x80\x62\x39\xe9\x0d\x0e\xb2\x06\xd5\xae\xfd\x6c\x94\xf9\x04\x73\x5a\x81\xb5\x7a\xba\x46\xe2\xaa\x32\xdc\x9a\x8b\x74\xdb\x77\xe5\x68\xd6\x3c\xea\xbc\xa1\x90\x11\x01\x17\x43\x93\xc3\x82\x44\xbb\x2c\x1b\xd7\xf4\x56\x86\x65\x85\x8c\x23\x19\x20\xf6\xfa\x56\x2e\xc7\x29\xe8\x01\x16\xea\x46\x92\xeb\x46\xec\x3f\xdd\xd8\x00\xfe\xb3\xc6\x5e\x24\x06\xa0\x06\xc4\x24\x90\x5a\x0f\xd2\xd4\x3e\x62\x58\x93\xf0\xb3\x6b\x3a\x84\xd2\x05\xd6\x86\xc2\x53\xab\xeb\x3a\x05\xd1\x60\x6c\x5c\x01\xf7\xea\x8c\xd5\x43\x5c\x77\xe4\x20\xb8\x14\xc7\xa2\xe1\x23\x10\xcd\xfc\xff\x1a\xdf\xda\xa9\x61\x8c\xed\x91\x4d\xb1\x38\x13\x5b\x3d\x17\xd8\x17\x9d\xf5\xe3\x31\x07\x59\x42\x3e\x01\xf6\x28\xf1\x6a\xf4\x4c\x6d\xad\xc9\x2b\xb0\x24\x26\xc8\x77\x7f\xa9\xec\xba\x96\x2a\xf2\xd7\x52\x3b\x1f\x0b\x2c\xd5\x4e\x0c\xbb\x2f\x2e\x70\xe7\xb8\xf7\x93\xf9\xee\xc5\x9e\x3d\x92\x07\xce\xf0\x57\x73\x7d\xf8\x0f\x03\x4e\x31\x2c\x68\x38\x85\x05\x3e\xc0\x7e\x84\xf2\x91\x26\xfc\x87\x5c\x85\x86\x40\x71\x49\x78\x87\xe8\x17\x19\x52\x2d\xe5\x97\xec\xcd\xa5\x68\x84\x0c\x46\xc2\x2f\x01\x26\xcb\x5a\x95\xe5\xb4\xc8\x67\xac\xc0\x20\x2e\x53\xe3\x4c\xe0\x59\x54\x94\x83\xbf\xa0\x2c\xe6\xb2\x8a\xcc\x64\x41\x22\xef\xe0\xf3\x21\x18\x7f\x21\xd5\xcf\x23\x24\xab\xe8\x27\xb2\xb8\x10\x78\x60\xa3\xe3\x93\x54\x49\xc0\x64\xe0\xab\x8a\x88\x0b\xd1\x15\xf6\x81\x24\x8d\x39\x48\xde\x16\xf5\x49\x7a\xf2\xb3\x06\x6f\x8b\x27\xc2\x78\x1a\xe3\x74\xb7\xd9\xa5\xb5\xfb\xfb\x87\x62\xfc\xec\x47\x96\x69\x26\xfb\xc1\x75\x45\xaf\x26\x4b\x4f\x0a\x83\x1d\x8d\x9f\x65\x89\xb7\xe4\xe0\x23\x64\x1f\xd6\xa0\x9c\xea\x6d\x9e\xea\xaa\xcb\x57\xb1\x3e\x5d\x87\x66\x03\x4b\x3a\x5a\x83\xb5\xe0\xb1\xfe\xfb\x81\x0b\x0e\x46\x97\x38\x16\x3a\x0a\xb2\x1d\x56\x6e\xa0\x3a\xa3\x05\x8d\x18\x81\xb7\x51\xdb\xa4\xf8\x92\xd7\x3d\xcd\xaa\x1d\x2d\x49\x97\xfd\xb7\x72\xcc\xfd\x5b\x5d\xec\xe3\xb7\x28\x39\xe4\x81\x2f\x31\xe6\xe6\x73\x6e\x31\xf9\x0f\x74\xd6\xfb\x9d\x41\x00\xf6\x9d\x6d\x9c\x53\x49\x7e\xb0\xf3\x26\x93\xe1\x7c\xce\x5c\x12\x46\xf1\x0b\xb9\x04\x1e\xd9\x7e\x0a\x47\x71\x8c\xb8\xd9\xdf\x04\xb2\x7f\x0a\x66\x84\xeb\xe8\xbf\x22\x05\x3f\xd7\xc0\x70\xcd\xa7\xdf\x2b\xbb\x7b\x92\x1c\x9a\x35\x52\x9a\x7f\x25\x1c\x3e\xcb\xe4\x63\x16\x8f\x1f\xb8\x47\xdd\x8c\xe9\xbd\xfb\xb3\x34\x85\x4c\x00\x9c\xe0\x48\x7b\x90\xec\xb1\x05\x3e\x0f\x9a\x6c\x54\x39\x48\x51\x7f\xbf\x5b\x91\x88\x8a\x73\xd9\xa3\xc0\x80\x4d\x75\xac\x79\xd7\xde\x23\xa9\x13\x04\x80\x4e\x15\x70\x0d\x8e\x3b\xa6\x2a\x7e\xc3\x4b\xc4\x08\xaf\x74\x79\x14\xd2\xfd\xa8\x10\x85\x85\x02\x98\x6c\x8f\x24\x9d\x7d\xf0\xb8\x79\x1d\x6c\xa0\xfd\x99\x44\xfc\xc5\xa0\x7b\x96\xb6\x7d\xf9\x43\xd2\xb0\x51\xf4\x29\x42\x86\x0d\xf8\x1a\xe8\x68\x9a\xdd\x12\x92\xd1\x95\x45\x85\xe0\x55\x98\xcf\xf4\x16\xc1\xc2\x5e\x2a\x70\xeb\x44\xac\x90\xf0\x94\x5b\xcc\xc3\x29\xfa\xc1\x4f\xeb\xfd\x15\xe8\x5f\xbf\x17\x67\xfe\x03\xe7\x9f\x83\x5a\xe1\xdd\x36\xa6\x90\x9b\x3e\x12\xe2\x3f\x77\xa1\xd4\xff\x0e\x2e\xc5\x2b\xc8\x0e\x61\x3f\x84\xd7\x8f\x57\x0d\x93\xf0\x60\x5c\x0c\xa4\x55\xec\xba\x83\xb9\x31\x82\xa1\xa0\xa0\x23\xac\x0f\x31\x22\xe6\x18\x32\x58\xb8\x2c\x04\x3d\x80\x27\x41\x1e\x07\x86\xe9\xda\xa3\x63\xb7\x28\xce\x04\x6f\x31\x54\xec\xb8\xec\xa2\x24\x37\x29\x4d\x34\xb9\x77\xe9\x2c\x12\x84\xf7\x7e\x6f\x86\xe2\x40\xd8\x0f\xf6\xd1\x2c\x18\x15\xfa\xea\xbc\x0f\xf1\xe4\x30\x82\xa3\x0b\x24\x7a\xfd\x38\xeb\x04\x06\x3a\x47\x90\x93\x4f\x05\x3d\xd8\xaf\x96\x2c\x74\x29\x98\xa9\x64\x85\x2b\x0f\x6b\xf3\x91\x85\xdc\x8d\x35\xd6\x84\xa9\x41\x5a\x1f\xaa\xd5\x20\x94\xea\xd2\x94\xac\x55\x89\x7f\xc9\x6c\xa6\x2d\xcf\xef\xbf\x56\x4f\x3e\x11\xeb\x38\xa5\x07\xa1\x46\x53\x0a\x15\xa1\xb1\x02\x34\x10\x14\x8c\x7b\xd9\x95\x1f\x1d\x2b\x46\x17\xa2\x38\xd4\x5d\xa9\xf3\x11\xdd\x1a\x84\x28\x43\xd3\x1e\x52\x62\x7c\x89\xc0\xe5\x10\xa7\x63\x0d\x9b\xe2\xb1\xfa\xbc\x08\xef\x54\x5b\xf3\xe5\x30\xd8\xfc\x64\xe2\x93\x30\x86\xe2\xc8\x78\xd2\x47\x72\x74\x6c\xe2\x1d\x91\xf3\x14\x6c\x16\x1b\x34\x06\x28\x82\x34\x9e\x83\xac\x09\x06\x6e\x2d\xab\x75\xb7\x26\x08\x47\x84\x14\x09\x5c\x0b\x85\x60\x40\xf4\x78\x44\xc0\x65\x27\x2f\x85\xd4\x51\x85\xbf\xdc\x2c\xc8\x8e\xe5\x7a\x05\x7f\xc4\xe7\xdf\x23\xe0\xaf\x3b\x45\x64\x2d\xee\x3f\xef\x9e\xab\xcb\x10\xcf\xd1\x58\x56\xb2\x4a\xec\xe4\x27\x2f\x54\xc3\xab\xe0\xc5\x66\x0e\x61\xd0\x57\x40\x4d\x23\x81\x74\xc4\xc8\x49\x98\x21\x8b\xe3\x44\xf1\xf3\x89\x88\x1d\x81\x6e\xe4\x55\x9c\xa9\x90\x37\x46\x32\xcd\xe6\x0e\x36\x27\x75\xe7\x86\x19\xe8\x00\x0a\x64\x8c\x60\x8f\x29\x8d\x3f\x66\xe5\x25\xad\x1b\xaf\x42\x41\x8d\x39\xa6\x4f\x76\x94\x97\x37\xb0\x23\x44\x88\x2e\xae\xfa\xb2\xe6\xdc\x80\x1d\x42\x97\x59\x1f\x58\xa2\x18\x95\x0b\xb1\x65\xd7\xf0\x1b\xee\xb6\xce\xb5\xb3\x9c\x12\xb2\xd4\x7a\xc7\x3c\xc8\xf2\x20\x87\xe2\x81\x4d\x73\xf9\xd6\x8e\xe9\x39\x93\x42\x52\x9b\x2f\x42\x15\x2b\x6a\x04\x46\x83\x1b\x9d\x54\x46\x85\xaf\x06\x4f\x3c\xa8\x01\x23\x4a\x08\xfc\x6a\x6d\xe3\x01\x8f\x7b\x39\x38\xa4\x35\xb8\xda\x63\xa2\x93\xf2\x98\x06\x9d\x58\xea\xf8\x1f\x3b\x20\x7f\x2f\xfd\xaf\xce\xde\x7a\x65\xbd\x1f\x55\xfc\x7a\x0b\x1a\x93\xeb\x51\x7f\xe7\xe2\xaf\xeb\xa3\x8a\x6f\xf0\xa8\x21\x34\x63\x97\x6e\x97\x0b\xc2\x28\xde\x8a\x17\xc4\x3c\x4a\x3e\x92\x9c\x19\x2f\xda\x3e\x0d\x7a\x47\x48\x68\x21\xb5\xe5\xbc\x94\x1a\x7b\x80\xc4\xf4\x43\x46\x4b\x7b\x9b\x1e\x65\xd7\x76\xfe\xb4\xd9\x82\xaf\xa5\x05\x6b\x38\x25\xac\x9a\x8a\x3d\x56\x2f\xa5\x3a\xc7\x03\x59\x8e\x46\x6c\x01\x93\x74\x14\xdd\x05\x56\xd5\x49\x53\xb6\x47\x2b\x8a\x5b\xa4\xb4\xa0\x0d\x97\xa7\x59\x56\x09\x4d\x8b\x58\xe1\xac\x30\x3d\xa5\x87\xff\x98\xb3\x08\x30\x9c\x29\x3e\x66\x90\xd3\x2f\x46\xbd\xcf\xa4\x1f\x59\x3c\x9d\xbf\x84\x03\xb0\x60\x26\xfd\x22\xa5\x0a\xdd\x41\x21\x2e\x7b\xe6\xcb\xf8\xc8\x82\x44\x3d\xd2\x73\x16\xf9\xc5\x2e\x5c\x9b\xef\x3c\x92\xe8\x2b\xe7\xae\xcf\x82\x8c\x3e\xd2\xe2\x0c\x46\x0f\xe7\xd3\x86\x07\xde\x70\x3e\xa8\x82\x99\x05\x86\xf6\x50\x7e\x3a\xd9\x25\xd2\x3c\xd0\xc4\x03\x9a\x49\x6a\xeb\xed\x25\xaa\xfc\x0e\x50\x64\xa7\xc9\x9c\xb9\xf3\xd3\xce\x47\x93\xa1\xc9\x87\x6c\x15\xf6\x37\x67\x96\x50\x9a\x58\xa5\x75\x93\xbf\x66\x69\x79\xf3\x76\x21\xbb\xcc\x86\xb7\x0b\xad\xd0\x92\x75\x27\xf5\xfb\xff\x94\x5a\x20\x73\xc4\xdd\x26\xd1\x5c\x06\xd4\xd8\x75\xc4\x41\x67\xd0\x20\x04\x2a\xbf\x81\x0b\x43\xe3\x06\x67\x6b\x37\x83\x1f\xc7\xb3\x69\xdf\x34\x8a\x36\x43\xab\x00\x52\xf2\x06\xeb\x27\x5a\x86\x65\x40\x47\xc1\x9c\x92\x85\xbd\x27\x1a\x87\x1a\x5e\x07\x36\x0f\x1a\x0b\x75\xa9\x07\xa0\x86\x9c\x0c\x72\xe6\x37\xc7\x9a\xc0\xff\xc9\x64\xe1\x45\xef\x80\xd2\xa8\x29\xf6\xbc\xeb\xab\x33\x8c\x0c\x4a\x89\xad\xf7\xe4\xaa\x59\x1e\x88\x2e\xb3\x75\x6d\xea\x34\x14\x09\xc1\x0d\x12\xc4\x1f\x4a\x27\x75\xa7\x01\xfe\xd0\xdc\x03\x33\x3f\xb1\x9d\x87\x59\x33\xbb\x61\x96\xa0\x32\x44\xbd\x39\x1e\x1b\xe6\xf8\x0a\xd9\x05\xb1\x74\xe6\xc3\x0b\x34\x7e\x0e\xf3\x16\x32\x35\xc3\xbc\xca\x6f\xc2\x35\x23\x9b\x65\xf7\xf0\xb5\x85\x70\x0c\x31\xb7\xed\xc2\xf7\x21\x3f\xc5\x9f\xb9\xef\x20\xb6\x5c\xa1\x1b\x6d\xa1\x4d\x6b\x77\x71\x6f\x2a\x69\xfe\x36\x62\xd7\x1c\x77\x00\x29\xae\xb3\x9e\x91\x07\xd8\x50\xef\xfd\x11\xc7\x86\x0d\x8c\x85\xf6\xec\x8a\x25\xb3\x16\x92\x71\x56\x2f\x2d\x0e\x41\x8f\xb5\xc0\x73\x18\x43\x9e\x83\x06\x34\xcb\x89\x6f\xc8\xf4\xc5\xe1\x89\x5a\xc3\x79\x73\xe8\x3e\xe4\x47\x95\x81\x45\xee\x4a\xb0\x7d\xec\xa9\x27\x23\x2a\xa7\x48\x71\x59\x38\x84\x48\xf0\x80\xa6\xc1\x81\x5d\x2e\x82\x73\x37\xdb\x08\x7d\x2b\x49\xf3\x01\x78\x54\x3d\x70\xca\x51\x0d\x50\x5a\xd5\x97\xeb\x87\x16\xda\x16\xf1\xe6\x26\x11\x70\xa8\xb0\x82\x8a\x58\x4c\x35\xfa\x7a\xbf\xce\x99\xaa\x69\x16\xaf\x34\x0d\xef\x2b\xe7\x1d\x7d\x95\x48\x52\x4f\x0c\x3f\xcf\xc7\x3f\xa8\x09\xe9\x6b\xb4\x8d\x3d\x2a\x77\xda\xe0\x9c\xd5\x95\xba\xed\x84\xa8\x3e\x00\xdf\xdb\x06\x9b\x68\x35\x3e\x33\xc6\xd2\x9f\x9d\xfe\x4c\xb3\xce\x0e\xee\xbb\x24\xc4\x88\x10\x51\x68\xf6\xd4\x17\xaf\xcb\xf7\xf6\x6f\xb2\x9c\x23\x9e\x8d\x85\x22\x58\x90\x2d\xc5\x88\xb9\xef\xa0\xdf\x5c\x04\x66\xad\x22\xe8\xfc\x3f\x55\x5f\x96\xe0\x2c\xcf\xf4\xba\x97\x77\x67\x06\x9c\xe0\x66\x30\xbf\x81\xe4\x4b\x56\x7f\x4a\x25\x95\xf3\x9c\x9b\xb6\xa0\x99\xc2\xe0\xa1\x5c\x92\x82\xa8\x73\x44\xdc\xdd\xf0\x46\xed\x72\x43\x62\x01\x1b\x5a\x98\x5f\xe8\x0c\x1d\x1a\x45\xec\xe2\x1d\x21\x03\x9e\x6c\x24\xfb\xb8\x2e\xae\x5a\xab\xf7\x2d\xc0\xd2\xb9\x75\x06\xb8\x12\xcb\xb4\x42\x43\x71\x0f\x2d\x5f\x5a\xa5\xfa\x03\x48\xde\x11\xd0\x86\x62\x97\x73\x8c\xa9\x80\x11\xfe\x89\xb3\xba\xb2\xe3\x1a\x42\x11\xe3\x9a\xc3\x6f\xdf\x20\x12\x15\xb4\x1f\x74\x2b\xc8\xca\xb1\xb7\xcb\x4f\x19\x0c\x96\xf2\x08\x8a\x4e\xb1\xce\x86\x87\x08\x49\xcf\x11\x25\x02\x79\x4b\x71\x43\x5c\xb4\xd0\x7b\x78\x80\x5a\x67\xbd\x36\xd1\x4d\xe6\x7f\x9b\x22\xc4\x2c\xd4\xd6\xc2\xb7\xe2\x15\x9b\xa4\xce\xd4\x89\xfc\x97\x11\xc9\x09\x7c\xd8\x39\x1c\x31\x92\x24\x3b\x5c\xcc\x79\xfd\x4f\xe4\x9a\x35\xd2\xbc\x9d\x5f\x43\x03\x8b\x24\x33\x4a\xf7\x8f\x10\xe3\x66\x63\xfc\x00\x3e\x12\xf1\x1e\x24\xb8\x86\x74\x4b\x8b\xd6\xed\x25\x50\xff\x68\x8b\xa3\xe8\x0b\x1d\x99\xf2\x2d\x94\x7c\x3c\x30\x86\x28\x32\x02\xe8\x9d\xfd\x83\xf1\x26\x8f\x84\x19\x06\xad\x4b\x9b\xec\x26\x98\x49\x3c\x6a\x7e\x00\xe5\x1a\x1c\x9b\x14\x13\xc8\xc0\x64\xdb\xbc\x25\x6a\x36\x7c\xd8\x33\x19\x3e\xf8\xc9\x38\xc2\x80\xa0\x59\x23\x98\xbd\xbb\x65\x20\x2c\x25\x44\x46\x47\x7e\x20\x5f\x65\xb0\x6f\x62\x73\xeb\xf8\x24\xfd\x57\xc3\x10\x43\xa2\xc4\xdc\xf4\x29\x85\x09\x05\x77\x13\x1d\x6f\xb8\x73\xa7\xe5\xa8\xd3\x39\xd8\x70\x2e\x34\xe3\x1d\x07\x83\xa4\x51\x0f\xd5\x4a\x45\x56\xac\x25\xfc\x5f\x50\x69\x38\xb4\x03\xf5\xc6\xa9\x09\x48\x92\x95\x37\x44\x61\x4e\x05\x38\x36\x4c\x3d\x71\x9f\xb9\xce\x0b\x6a\x65\x5b\x63\xcb\x50\xa9\x1a\x64\x0c\x3a\x84\x31\xd1\xa0\xec\x5b\x0c\xc1\x69\x7a\xa1\xee\x20\xfc\x26\x7c\x45\x7d\x73\x86\x6f\x80\xeb\xc0\xa9\x9f\x6f\xf5\x41\xe7\xd8\x9c\xb3\x7c\x23\xc4\x6a\x69\x93\x3e\xa3\xa1\xfe\x63\xc4\x80\xcc\xd4\x2c\xf0\x20\x9b\xc1\x27\xf5\x72\x16\x9b\x46\xb4\x97\x3a\x77\x02\x39\x98\x34\xd1\x03\x1c\xba\x36\xe4\x50\x47\x3a\x6e\x01\xe8\x6a\x06\xc9\x11\x0c\xdd\x52\x66\x60\x78\x09\x2d\x83\x2e\x74\xd5\x78\xc6\x1a\xc0\x6f\xfe\x8b\x30\xd1\x00\x1b\x19\xcd\xef\x39\xe6\x1d\x43\x16\x06\x9a\x05\xe2\xf2\x15\xe8\x5c\x2a\x40\xa9\xe0\x39\x16\x19\x46\x2d\xb5\xdb\x52\xe8\x3a\xf4\x82\x0e\xd0\xd6\xf0\xcd\x4b\x18\x38\xa1\x59\x85\x25\x04\x61\xb7\x12\xb7\x26\x4c\xec\x92\x02\x8d\x47\xd2\x6e\x3e\xa2\x6d\xe5\x8f\xdf\x2d\xb7\xf6\xe6\x7f\xc2\xaf\x68\x70\xd3\x2d\x12\x67\x90\x4d\x97\x88\xc4\x9b\x69\x41\xb4\xe9\xd2\x49\x8e\x45\xb2\xca\x9a\x4e\x1f\x82\xdc\xb3\xe7\x09\xc9\xda\xc4\x0a\x83\x5a\x6f\x41\x31\x2a\x47\x32\xb8\x58\xd7\x68\x67\x87\x1c\xbf\x3e\x2b\x7e\x31\xe4\x7f\x28\x38\xe3\x42\xdf\x12\x68\xb5\x34\x02\xde\x5e\x28\xc4\x4e\xa4\xbe\x38\xe1\x49\x2b\xf5\xea\x3a\x3d\x67\x0e\xb4\xfe\x8c\x25\x12\xeb\x6e\x2e\x05\xd9\x0d\x1a\x42\xe1\x37\x61\x5d\x2f\x31\x78\xfa\xfb\xe4\x55\x97\x38\x3c\x83\x6c\x4f\xa0\x34\x41\x3e\x58\xff\x34\xc3\x0b\x1b\x5c\x1c\x11\x7a\xd2\x79\x83\x7f\xc6\x34\xe5\x21\xf9\x48\x75\x48\x33\x37\xb7\x5e\x70\x0e\x1a\x90\x55\x37\xbc\x12\x11\x84\x98\x0f\x98\x3e\x9c\xe6\x85\x1c\x2c\xaf\xa5\x1b\xf2\x80\xa6\x13\xfd\x5e\x39\x2e\x5b\xd7\x44\xf5\x6d\xba\x16\xb5\x63\x40\x61\xdb\x80\xc1\xaf\x88\x29\x92\xd8\x82\xb8\xac\xd3\x74\xce\x3c\x70\x2c\xef\xd5\x38\x37\x97\x65\xa5\x95\x91\x14\x88\xf9\x49\xae\x72\x7e\xa7\xac\x32\x50\x5b\x67\xe5\x21\xd9\xa0\x56\x34\x39\xe8\xf1\x50\x42\x28\xc9\x9b\x10\x6e\x0f\xe4\x15\x6d\xac\xe8\xd3\x7a\x87\xaf\xc6\x6a\x2d\x30\x6f\x45\xfa\x31\xe5\xd5\x4d\x02\xb3\xc9\xc3\x82\x60\xc0\xa2\x98\x25\x7e\x97\x62\x14\x61\x1d\x28\x3a\x0b\xa5\x27\x7c\x69\xf6\x7f\xa0\xda\x9c\x14\x75\x4b\x9a\x4e\xd7\xb0\xc3\x14\x45\x7c\xbf\x69\x64\x25\x9e\xc6\x48\xd4\x43\x80\xda\x2f\x9d\x5d\x1e\x2b\xd8\xb3\xf8\xba\x6c\x38\x2b\x86\xef\x9d\x43\x93\xf4\x5b\x98\xc9\xf5\xed\x91\xd3\x2f\x63\x34\xce\xc5\xf9\x92\x8a\xc3\xa8\xec\xd7\x33\x67\xfc\x83\xfd\xa6\xe3\x50\xed\xff\xb5\x1b\xc2\xdb\x06\xeb\x0b\x1d\x3f\xe8\x21\x9f\x9b\xfc\xa3\xcf\xc9\xef\xfb\x63\x35\xbb\x78\x3c\x4c\x24\xfb\x60\xd4\xc3\x96\xe6\x23\x49\x5c\x78\x5f\xd0\x5a\xeb\x83\xb7\xc2\x0f\x83\xdb\x8e\xff\xfd\x8f\xd3\xab\xd6\xb7\x25\xaf\xa6\xa1\x1a\x64\x1d\xf2\xb6\xc1\xc6\x38\x87\x21\x05\x3c\x2d\xc9\xc6\xa9\x2b\xeb\x37\x18\x64\x20\x98\xa9\xfc\xbc\x77\xc5\xa8\x4d\x29\x9b\xef\xee\xbc\x0b\x94\x77\x89\x65\xdb\xc2\xe2\x0e\xef\xef\xae\x27\x04\x26\xcf\x97\xe5\x92\xd7\xee\x9f\xb1\x4f\x3a\xce\xae\xf7\xe4\x5d\x36\xae\x58\x5d\x74\x9f\x70\xd5\xd4\xb1\x1b\x69\x9f\xe1\x97\x11\x9d\x35\x43\x9e\x41\xeb\x57\x5d\xf2\xf4\x21\xbd\x68\xea\x27\xb1\xfe\x59\x38\x6f\x8c\x0c\x55\xbc\x4b\xb8\x15\xc9\x51\x83\x14\x20\x28\x3e\x6a\xcb\xb9\x4c\xde\x60\xbe\x99\x55\x03\xd2\xcf\xcf\x03\x03\xb9\x3c\x3e\x55\xf3\xf6\xfa\x99\x7e\x19\xec\xa6\xbf\xc9\x4f\x14\xf3\x28\xab\xa5\x72\xe1\xea\xdc\x7f\x63\xee\x32\x72\x80\xf2\x9f\x7d\x4b\x31\x00\x1e\x1c\xf3\x15\xd6\x1b\x45\xd3\x26\x6f\x28\x36\xc6\x49\x9f\x4d\x9c\xaa\xfc\x8c\x1f\x99\x4e\x36\xc1\x6f\x6b\x9a\xbd\xf2\x44\xd2\xfd\x4c\x22\xfa\xdb\x3b\x0f\x9a\xb5\xb0\x05\x05\xaa\xdc\x54\x43\x64\x9f\x18\xdb\x1b\x4a\xef\x08\xe8\x83\x03\xc4\x78\x0e\x50\x6c\x30\x8b\xe9\xff\xe6\x68\xe1\x65\xc3\xe8\x60\x0a\xbf\x60\x4c\xe5\x44\x53\xff\x0f\xf3\xc4\x5f\x1e\xde\x69\x8e\x20\x9a\xe3\x95\xee\x6b\xb5\x31\x31\x19\x3f\x90\xc0\xf6\x00\xdf\xab\x34\x79\x74\x1c\x5d\x63\xe4\x85\xc1\x02\xc3\x88\xaf\x32\x05\x1d\xe8\x94\xb9\xc6\x49\x7e\xc2\x4b\xb1\x74\x2b\x9f\x24\x00\xc2\x77\x43\x6c\x9e\x8c\x3c\x9d\x22\xc3\x8d\x15\x7d\xdb\xe7\xcd\x4d\x9e\x6c\x93\x5f\xea\x9a\xc2\x53\x83\xc7\x4d\xfb\x8b\xe6\x9e\x5a\xa0\xf2\xc8\xcd\x8d\xa1\xdc\x3a\x31\xf9\x0d\x0b\x5e\xd3\x00\x8c\xf3\xd5\xdd\x35\x74\xdc\x3d\x4b\x8b\xfe\x95\xc2\xa2\x63\x52\x72\x97\x9c\x37\xae\x4e\x44\x12\x67\x03\x28\x09\x29\xa6\xec\x60\x17\xa0\x33\x08\xc0\xca\x03\x43\xbd\xc2\x2b\xb2\x9b\xca\x71\x38\xbe\xb3\x8f\xe4\xc8\xb1\x2a\x56\x80\xe4\x45\xb7\x58\xf8\x6c\xd1\x79\xb8\xde\x55\x95\xae\xdd\x21\xa7\x5d\xc3\x24\x43\x44\x24\x0d\x8e\xae\x76\xff\x4f\x5d\x6f\xd8\x61\xb0\x0f\x65\x5f\xe6\x8b\x7a\x93\x86\x8a\x5c\x2e\x8a\xcf\x75\xbb\x2d\xc6\x49\x60\x55\xff\xaa\x75\x62\x16\x5e\x56\xf3\xc7\xf6\xf9\x41\x8e\x90\xd4\xfc\xc1\x2c\x41\xd0\x56\x27\xb0\xc6\x2f\xd3\x26\xc2\x2d\xc8\x7b\x52\xf3\x55\x6f\x86\x50\x0c\x50\x21\x04\x2e\x1a\x35\xda\x6a\x43\x9b\xfe\x1d\x23\x0f\x43\xf6\xd9\x71\x5f\x51\x94\x2a\xb3\xe0\xe1\xab\x71\xf2\x77\xd7\x9f\x72\x9a\x61\xce\x31\x82\xa3\xeb\xc5\xc0\xf5\x50\xf1\x8a\xc1\xdd\x55\x2e\x46\x79\x2e\x68\x74\xf1\x87\x94\x4c\xb1\xaa\x6b\x0e\x12\x88\x21\xbf\xe5\x73\x63\x82\x35\xb9\x51\x31\xa7\x72\xcd\x65\x80\xdf\xbc\x37\xa8\x17\x03\x99\xbc\xfb\xf6\xcb\x69\x8d\x81\xc1\xdd\x25\xc4\xea\xff\xca\xa2\x8f\xe5\x51\x97\x9b\x35\x86\x31\x80\x3a\x45\xe4\x25\x3d\xf5\x0b\xae\xe4\xe2\x2d\x1d\x4a\x39\xbe\xfa\x04\xc3\x45\xfb\x74\x78\x68\x90\x62\x63\x5f\xbe\xa7\x76\x19\x98\xc2\xbd\xe0\xbe\x1e\x32\xc4\x60\x92\xbb\x1a\x26\x94\xe1\x99\xd1\x93\xd6\x0c\xc3\xf6\xe7\x76\xe7\xf2\xd3\xde\xbd\x1c\x9d\x1d\x5b\x28\x2f\xd1\x8f\xc2\xa1\x1f\x16\x1b\xdd\xf5\xc2\xed\xcf\x85\x9e\x59\x5e\x19\x90\x87\x23\xc8\x94\x26\x83\x7d\xc6\x18\x4e\xaf\x98\xf1\x13\x01\x09\x79\xe7\x8d\xc8\xad\xa3\xf7\x8e\x09\x72\x19\x02\xb0\x84\xc3\x62\xec\x91\x2e\x11\x8c\x5a\x9a\x49\x49\xaa\x4c\x6a\x3a\xdd\x99\xa5\x09\x29\xe5\xff\xaa\x73\xd8\x60\x84\x73\x46\xd5\xeb\x8d\xbe\xc7\xde\x2d\x42\xc4\xaa\xb9\x4a\xa7\x56\x61\xd6\xcf\x5a\xce\xa7\x2e\x2f\x3f\xac\xda\x08\x82\xd2\x95\x95\xc4\x70\xfa\x83\x0c\x9a\xd3\x75\xf3\x8a\xba\x29\xc3\x15\x53\xd5\x3e\xa7\x5a\x82\xb1\x80\x05\x1d\xd6\x3a\x61\xe2\x4b\xcd\x6b\xee\x46\x24\x69\x52\x43\x7d\x1e\x2d\x05\x6b\xec\x88\x01\x1c\x0c\x34\x4a\x18\x68\xc4\x08\xc5\x6a\x57\xca\x23\x1b\x20\x09\x07\x19\xc4\x72\xa0\x38\x42\x85\xd6\xd0\xaa\xae\xf6\x59\xef\x35\xc8\x52\x22\x4f\x1d\x24\x24\xb1\x9a\x71\xca\x94\x5f\x64\xe5\x84\x21\xb4\x71\xa5\xc8\x6f\x50\x94\xf8\xb3\x52\xa0\xc8\x4a\xc9\x2a\x9e\x36\xc4\xc8\xa2\x40\x19\x94\x0d\xc7\x56\xfb\x30\xc8\xb1\x6f\x69\x55\x26\x29\x53\xe9\xa5\x87\xbf\x40\xaf\x41\x9b\x2d\x55\x92\xc8\xb6\x0c\xa7\x53\x47\x59\x64\x24\xc8\x39\x0a\xb0\xa3\x6c\x80\xe7\x2c\xd6\xab\x18\x1d\xbc\xc4\x70\x3e\x83\x86\x53\xc8\x2f\x38\xe9\x79\x76\x86\x99\xd7\x29\x65\x31\x2b\x47\xd1\x93\x60\x9b\xde\x15\x33\xcf\x92\x7b\x35\x8c\x3c\x8f\x3e\x07\x74\x5a\xe5\x21\xde\xcc\xec\x73\x9a\x9e\x18\xe2\xbe\x80\xfc\x77\x99\xc2\x20\xa4\x3b\xd5\xcc\x1e\xb8\xd7\x17\x38\x63\xcc\xa6\x03\xdb\xd3\xe3\xeb\x83\x19\x60\x4d\x9b\x83\x31\x15\x8c\xab\xb4\xa7\x7f\xf9\x52\x2c\x83\xee\xe5\x6c\xf0\xe0\x2a\xc9\x03\xc5\xda\xd9\x85\x6c\x29\x29\x1d\xc0\xef\x57\x16\x28\x59\x09\x90\xd6\xcd\x79\x42\xf8\xd7\xe1\xfa\x8f\xfb\x87\xf8\x4f\xfd\x07\xe4\x0c\x19\x48\x1e\x3f\xbb\x96\x1a\x20\xa5\x7d\x88\xda\x37\x58\x3d\x63\x45\xa3\x2a\x92\x10\x7a\x8d\x81\xa2\x6d\xd0\x72\x50\xc8\xdc\x35\x24\xb8\x50\x6f\xfc\xa6\xd8\xe4\x0e\xfd\x52\xe0\x10\x5f\x74\x12\x95\xb4\x09\x9d\x46\xe5\x69\x9f\x3a\x5d\xab\xba\x1e\x43\xf9\x78\xc4\xce\xad\x4a\x8c\xc8\x29\x56\xdb\xf1\x20\x64\xb8\xc1\x41\xac\xf9\xc7\xf6\xa3\xe6\xbd\xfb\xcf\xf8\x52\x1c\x4d\xc9\xe0\xee\x3c\x12\x6e\x27\x6b\x56\x00\x06\xb3\x6f\xe8\x20\xe8\xf7\x94\x7e\x00\x43\x7d\x0a\x1c\x53\x11\x61\xfb\x03\x1d\xb1\x47\x6f\x33\x4f\x8f\x24\xd5\x40\x3a\x4a\x8a\x53\x93\x68\x35\x3a\x39\xc0\x51\x9f\xf3\x3e\xd3\x9b\x8f\x3b\x75\xbd\xe2\x33\xbd\xe8\xc4\x00\x4a\x96\x98\x58\xb7\xdc\x67\x52\x3b\x44\xcd\x2a\x5a\x76\x63\x69\xc2\xf4\x08\x46\xd6\x22\x12\xd5\xfe\x77\xb7\xbf\xa0\x61\xc5\xe4\x83\x61\x78\xe4\x5c\xda\x78\xbb\xa7\xc2\x4d\x36\xa6\xd3\x6a\x41\xc4\x2f\x9f\x75\x03\xed\x2a\x48\x57\x8b\x88\x6c\x69\x95\xfe\xcb\x99\x16\x6b\xb7\x78\xe5\x0b\x1b\xf4\x33\x49\xf6\xff\x14\x51\xd1\x3a\x18\xde\x8c\x80\x44\xb3\x7b\x19\xcc\x25\xcc\x4c\xbf\x05\xe4\x85\xf2\x0f\x25\x6b\x63\xbe\x1e\xfd\x51\x9c\xe4\x03\xef\x6f\xdd\x28\xc3\x24\x2a\x45\x8a\x33\x92\x1c\x1a\xe9\x56\x60\x3a\x30\x1c\x0d\xa7\x8c\x53\x86\x27\x37\x8d\xcf\xdc\x3c\xa3\x11\x3c\xc5\x71\xb2\xca\x79\x24\xbf\x6b\x13\x33\x0b\xd1\x05\x8d\xfb\xed\xfd\x0c\x6a\x56\xf0\xbd\x9e\xb4\xff\x00\x31\xeb\xff\x6e\xf1\xb2\x5a\xfe\xbf\xa0\x6d\x4d\x3a\xe3\x28\xe7\x90\x2a\x0a\x15\x98\xec\x4d\x48\xcd\x58\xf8\xe4\x37\x17\xc3\xaf\xe2\x36\x42\xa8\x47\xf3\xaf\x5c\xb2\x7e\x0c\xa9\x5c\x1b\xeb\xee\x56\xfc\xb9\xa3\x72\xf0\x9b\x51\x94\xd6\x63\x40\x73\x6d\x4d\x99\x5c\x8d\xf9\x06\x2d\x7f\xea\x26\x60\x9d\x6a\x4d\x06\xb6\x7c\xeb\x14\x5d\xfc\xbe\x85\xd2\x8b\x5b\xe4\xd2\xb8\xc4\xc7\x2b\x95\xb0\x74\x76\x40\x73\xae\xa1\xd6\x8a\x49\x16\x62\x6c\x2d\x3f\x8b\x00\x6f\x59\xd6\xdc\x7a\x73\x09\x01\xf2\xc0\xd2\xad\x2b\x4a\x4f\x12\xd8\xa8\xdd\x09\xcb\x15\x29\x37\x45\x26\xa4\x95\x73\xa6\xf5\xca\x7e\x71\xc5\x2e\xb6\xd8\x3e\x29\xdc\xd8\xd2\x56\x78\xff\x53\x24\xf0\xb7\xa4\x08\x4a\x4b\x7f\x3a\x5e\x39\x35\x6e\x31\xb8\x69\x4a\xd5\xe0\x10\x3e\x2e\x61\xec\x02\x41\x46\xe6\x44\xfd\xdf\x1d\x9e\xd6\x44\x4f\x47\x7c\xd5\x60\xd6\xe2\x1b\x1d\x94\xf2\x38\xee\x06\xc3\x7a\x86\xae\x0e\x74\xfa\x1f\x8c\x22\x19\x0e\x96\xd6\xad\xfc\xb9\xe3\xe6\xec\xb7\x7b\xbc\x90\x51\x86\xcc\x31\xfa\xbe\xb4\x30\xaa\x38\x1a\xf3\xe3\xe1\xce\xe5\x7b\x35\x26\x00\x1e\x60\xc0\x2d\x04\x7a\x1e\x07\xb4\xb4\x88\xbc\xcb\x2e\x20\xf3\x92\xda\xe4\xfe\x72\x70\xbe\xcc\x00\xa6\xaa\x1d\x6d\x69\x15\x23\x6d\xad\x6f\x6e\xbd\xea\xae\x92\x79\x76\x06\x62\xa9\x23\xaa\x9f\xe6\x9c\x34\xd2\xd5\x26\x1b\x4c\xfa\x45\x55\xb7\x6f\x82\x27\x0c\x4f\xb6\xd6\xe0\x79\xad\xca\x27\x3c\xec\xc5\x67\x8f\xf7\x28\xa1\x20\xe1\x88\xa5\x8c\x58\x22\x85\xfe\x70\x3d\x3e\x07\xe8\x71\x71\xe2\x9a\x5c\xb4\xba\x05\x5f\x6d\xe4\x54\xfa\x51\x40\xbd\xf1\xcb\x98\xd9\xfb\x75\x46\xd9\x37\x1a\x3b\x5b\x62\xe2\x0e\x1a\xf5\x60\x6e\xc1\x3c\xfc\xd2\xca\x9f\x67\x4b\x8e\x74\x23\x43\x63\x89\x88\x1d\x98\xeb\x4c\x04\x39\xb2\x24\x18\x8f\xac\x5c\x45\x78\xc8\x5c\xe1\x26\x13\xee\x3a\xb9\xfc\xaf\xca\x4c\x46\xde\x35\x09\x5d\x6b\x92\xd0\x52\xeb\x31\xb3\x23\x47\x78\xea\x48\xaa\x2b\x0d\x90\xf4\xf5\xce\xab\x68\x64\x9c\x1b\x3a\xac\x4a\xe0\x7f\xae\x59\x86\x31\x2d\x24\xdc\x0e\xe8\x94\xf0\xf0\x76\x74\xef\xfe\x1d\x89\x63\xc5\x03\x39\x40\x83\x7a\xa5\xd6\xb3\xac\x8c\x1c\x00\xb1\xd8\xd4\xa8\x1d\x98\x8b\x8f\x3b\x96\x1e\x0f\x89\x77\x1e\xc9\xbd\x3d\xb8\xf1\x14\xd7\xe8\xce\x60\x4e\xd4\x7a\x69\x8a\x96\x86\x7b\x00\x67\xdc\xcd\xd0\x63\xb5\xca\xd6\x3f\x6a\x1b\xe7\x2b\xbf\xc9\xc9\x64\x7c\xd0\xb5\x49\x13\x15\x1f\x80\xdf\xe3\xaa\x2e\x41\x0d\xcb\xcb\x2a\xa7\x24\xe4\xb1\xfa\x17\x54\x97\x7b\xe3\xab\x54\x17\x0e\xec\x2a\x87\xae\x14\x6b\x5f\x93\xde\x3d\x8d\x61\xac\x7d\x65\xe7\x0a\x26\x33\xe4\x9c\x49\x8a\xbe\x52\xea\x62\xff\xcc\x3e\xf6\xdc\x3f\x3f\x17\x98\xdb\x53\xa7\x48\x30\xbb\xa1\x82\xc6\x3b\xb8\x83\xbb\xe0\x95\xe4\x4e\x0f\x1c\x78\xd3\x90\xa0\x66\xb7\x62\x09\x12\xca\x5e\xaf\x3c\xd4\x70\xa3\x79\xf1\x0b\xdc\x35\x0a\xda\x31\xa6\xde\x65\x5a\xa3\xf1\xef\x4e\xa2\x2d\xc2\x1f\x7e\x45\x45\x33\x50\x7b\xb9\xfc\xde\xed\x2e\x13\xff\x21\x9a\x8b\x52\x3c\xf7\x12\xbb\x23\x1f\xc3\x9e\xd4\xc6\x3b\x6f\x8b\x31\x4e\x44\xab\x16\xdb\x8c\x8b\x8e\x30\x42\x90\x9b\xac\xb5\x7c\x3f\x75\x2d\x99\xcc\x35\x7c\x19\xfc\x4f\x59\xd8\x09\xdf\x11\x3f\xf3\x52\x4a\xeb\x7b\xe6\x7c\xe2\x9e\xbe\x89\x31\xb0\x1d\x34\xf2\x2a\x40\x55\x03\xbb\xe5\xce\xd1\x27\x49\x8e\xd2\x49\xbb\xd5\x3b\x07\xff\xb9\xa4\xaa\xd2\x2f\x38\x41\xf9\xd4\x89\x30\x1f\x24\x9d\xd3\x17\x7a\xbb\xa5\x1e\x6f\x4f\x9b\x07\xc2\x63\x17\x45\xd5\xe1\x7f\x64\xce\x91\x5b\x74\x43\x9b\x41\x39\x2e\xdb\x6d\xa3\xc5\x50\x68\xdb\xee\xac\x24\x61\xeb\xfe\x90\x96\x73\x87\x44\xec\xd6\x6a\xef\x62\x80\x58\x47\xda\x9a\x93\x23\xfd\xfe\x6d\x35\xf8\x63\xb5\x49\x80\x1d\x68\x97\xb9\x4f\x70\x21\xb7\x8a\xf8\x08\x6f\xb4\x61\x71\xbf\xea\x7e\x45\x29\x3e\x9b\xa3\x49\xfc\x39\xcc\xe2\x0b\x16\xfd\x97\x3f\x09\xea\x77\xf4\x0e\xa9\x72\x3f\xf1\xfa\x99\x20\x91\x5e\xba\xd5\x85\x04\xac\xda\x15\x95\xe1\xbe\x33\x88\x91\xf7\x4c\xaf\x38\xb8\x8e\x14\x9c\xac\xf2\x01\xbb\xd3\xd1\xf5\x95\xe1\x4a\x39\xe5\xd0\xd3\xb8\xa8\x21\x31\xd2\x1f\x32\xcb\xee\x65\x53\x56\xd1\x11\x83\xc4\x54\x22\xee\xbd\xe1\x6d\x94\xe1\x50\x11\xc9\x6f\xf6\xde\xbb\x95\x89\xe3\x49\x6b\xb2\xff\xb5\x38\xca\xae\x36\x29\xb8\xe8\xd1\x41\xb6\xdf\x27\x53\x7d\x41\x1a\x40\x1b\x66\xcd\xff\x35\xef\x69\x0b\x37\x56\xd6\xc8\x16\x62\x35\x9b\x38\x94\x59\xe3\x77\x03\x36\x40\xf3\x56\xd6\xda\xa6\x1e\xd7\xde\xf2\x42\x67\x21\xab\x89\xbf\xda\x31\x18\x7b\x57\x09\xb7\x9e\xff\x83\x42\x39\x89\x76\x90\x2a\x15\xcd\x0e\x36\x4e\x7c\x60\x48\x50\x10\x27\x0f\x6c\x12\xe5\x32\xb8\x61\xcf\x37\xd0\x30\x88\x85\x67\x1d\x82\x60\xd9\xc1\xc9\x9a\x07\x78\xde\x8d\xcc\x3a\x34\x05\x4d\xff\x9e\xea\x5b\x96\x3a\x4e\xf3\x2a\x41\xc4\xbb\x39\xf7\x05\x72\x9f\x0c\xe5\x9d\xdb\xb7\x04\x17\xd0\x3a\x18\x4b\x40\x3b\x85\xc8\x8c\x20\xf8\x51\xf6\xd3\x1d\x7c\x94\x05\xb2\xa5\xef\xf7\x1e\x45\x68\xfb\x7e\x6b\x87\xf7\xff\xc7\x9f\x83\xf7\x07\xd5\x62\xb7\xf4\x91\xee\xc9\x96\xfe\x37\x92\xb4\xf6\x62\xd2\xef\x96\xee\xaf\x68\x6c\x37\x02\xf4\x24\x9e\x5d\xf7\x8f\x10\xb0\xc1\x4e\x5c\x1f\x92\x41\x91\xf6\xae\xf3\x0e\xa2\xb1\x2f\x88\x7c\x27\x9b\xf1\xcd\x75\xba\x08\x66\x0f\x16\xd3\x57\x44\xcc\xcc\x14\x0a\x8d\x40\xec\x09\x10\x89\x4b\x38\x93\x76\x9b\xdc\xfd\x4e\xa4\x3f\x51\x70\x53\x7b\xd6\xee\x16\xc4\x46\x02\x8c\x40\x06\xfc\x21\x55\xac\xad\xac\x7f\x95\x48\x64\x4d\xfb\xfb\xb7\x77\x70\x76\x93\xd3\x68\x79\x16\xfa\x36\x80\x2e\xd8\x0d\x87\x3c\xb3\x77\x2f\x22\x0a\x06\x37\xd2\x5e\xc1\xec\x12\x83\x1b\x32\x29\x74\xf4\x25\x75\xb6\xa0\xee\x51\x39\x83\xfe\xc8\x5c\x13\x2b\xd7\xb9\x54\x19\x0b\xe9\x37\x4e\x7a\x23\x51\x7b\xf2\xa4\xe3\x12\x5e\x4c\xa3\x54\x76\xc1\x07\x6c\xe1\x00\xf3\xa1\x01\xe9\x0a\x65\xe2\xec\x20\xc4\x61\xdd\x31\x88\xe5\x73\xde\xc2\x85\x8a\x19\x3a\xde\x13\xb7\x6e\xce\x79\x28\x58\x2a\x86\x9d\x23\x6b\xe5\x09\x58\x55\xa0\x74\xe1\x2f\xed\xbf\x67\x11\xf7\xe6\x98\xed\xb1\xae\xa1\x4f\xe6\xad\xb0\x7e\x63\x3f\xc8\x60\x30\xef\x64\x24\x54\x42\xd3\x1e\xac\x3b\xb9\xa7\xac\x85\x1e\xa3\x78\xb5\xc9\xa9\xeb\x89\x04\x10\xf4\xe1\xaa\xac\x79\x17\xa2\x70\xc8\x81\x55\x10\x27\x9a\xd7\xfc\x1d\xc5\x64\xcc\x2f\x3b\x10\x25\x22\xf0\x4d\x78\x07\x1a\x73\x80\xf9\x26\x0a\x65\xd7\x35\xcb\x16\x6a\xcd\xdb\x21\x53\x20\x0f\xee\x40\x65\x91\x9b\x5a\x4d\xaa\x7f\x94\xfd\x1d\x66\x48\x20\x4a\xf3\x2e\xd3\xdd\x77\x95\xf6\xcb\x9a\xde\x68\x8b\xc9\x64\xd3\x5d\x4f\x9e\x67\xe2\x34\xbb\x24\x9a\xdd\xd9\xc9\x72\xe7\xfc\x16\x3b\xad\x61\x20\x99\x09\x19\xf5\x5c\x93\x68\x77\x7b\xbd\xbb\xf3\x0f\x83\x13\x78\xbd\x54\x49\x3b\xa1\x8e\x9b\x87\x70\xe2\x9a\x82\x39\xa7\xc1\x90\x73\xe3\xe4\xca\x94\x1e\x1a\x3e\x58\x6b\x73\xe7\x53\x2b\x47\x5d\xfe\x10\xa6\x41\x43\x55\xc9\x61\xf5\xf2\x4e\x27\x7a\x22\xa2\xa7\x51\x28\x97\x04\xb0\x9b\xbe\x37\x77\xa4\x24\x2c\x36\x6e\xd2\xbf\x1a\xe9\xa0\xec\x85\x2e\xad\x2a\x45\xc1\x50\x16\x31\xad\x91\xda\x60\xe5\x33\x18\x64\x8d\xb2\x7c\xce\xa6\x8b\xe3\xe4\x50\x5c\x36\xf8\xe0\x0e\xe9\xa4\x94\xe6\xc2\x19\xa9\x85\xce\xb5\x4b\xbd\x3f\x9c\x8d\x59\x34\x75\xb0\x54\xb9\x05\x21\x5a\x4e\x02\x9d\xa6\x1c\x00\x06\x4a\x4b\x2f\x9e\xeb\x1f\x3e\x44\xd6\x5f\xe5\x86\x87\x82\xaa\x4b\xdd\x79\x8c\xed\xa7\xf3\xb1\x04\x9b\x7e\xa9\x3d\x99\x66\xa9\xf9\x08\xfa\x5b\xcd\x94\xad\x05\x5f\x8f\xae\x47\xca\x22\x5b\x76\x9f\xb3\xe3\xaa\x94\x29\x6a\xb3\xac\xa4\x47\x80\xb7\x07\x09\x56\xde\x95\xb5\x6c\x71\x05\xa2\x4c\x5a\x53\xad\x0e\xe6\xb2\xa6\x03\x1a\x40\xff\x39\x3b\x2f\x7c\x86\xec\xd3\xe5\x1a\xce\x5f\x38\xeb\x8e\xbc\xb6\xa2\x10\x0c\x0c\x86\x58\xe8\xcc\x25\x38\x72\x98\x1a\xf6\x46\x00\x0d\x1b\x77\x12\x8b\xc3\x59\x76\x3c\x30\x24\xe9\xe9\x1d\x64\x8d\xf2\xcf\x52\x08\x46\x08\xfc\xdd\xc0\xe2\xb8\x00\x4f\x02\x7d\xd3\x6d\x17\x89\x2e\x6f\xba\x68\xbc\x0b\xdc\x6a\xdd\xe7\xfa\xd0\xca\x1f\x4b\x69\x89\xe4\x09\x00\xb2\xc6\x96\xc8\x67\x05\x9f\x0f\xb3\x00\x93\xe3\xbc\xf3\x38\xf2\x54\x36\xf0\xf3\x32\xca\xda\x13\xe2\x78\x7a\xad\x38\x2f\xbf\xd8\x28\x5c\x9d\xee\x25\x8c\xd7\x01\xc8\x2f\x74\x3a\xa0\x58\x96\x4c\x81\xb5\x0a\xfd\x2d\x66\xdc\x92\x0e\xd0\x8d\xe3\xbd\x01\x21\x4e\x44\xc0\x4e\x9a\x00\x29\x70\x12\xcd\x6f\x09\xba\x9f\x5f\x90\xb5\x0c\xa3\x78\x86\xe3\xd7\xdb\x28\xf9\x22\x35\x06\xb0\xfe\x94\xc5\x40\xa1\x34\xaf\xfa\xff\x40\x3a\x61\x28\x03\xee\x48\x8c\xb3\xfd\x95\x9d\x3d\xdf\x3f\x68\x54\xb8\xc9\x52\x50\x02\x7d\xd2\x37\x4c\x8e\x1a\xc9\xd8\x7f\x79\x6f\xfd\xff\x3b\x05\xa6\xff\xa8\x90\xfa\x97\x3e\xcd\x3f\x7b\x03\xa4\x00\x4a\x95\xf8\x2f\x59\xb3\x7d\x39\x60\xec\x08\xfe\x48\x99\x2b\x30\x2d\xe3\x8d\xeb\x9f\x8f\xcd\xf8\x5f\x4d\xf2\x94\xef\xbd\x39\x31\xd0\x3b\xd0\x00\xfb\xf7\xa6\x74\x4e\xb0\x49\x0b\x15\xf4\x40\x7d\x94\xa0\x6c\xf1\x19\xf2\x2c\x94\x64\xbf\x3c\xdf\x4a\x35\x46\x54\x3a\x31\x4c\x30\xf7\xb4\x41\xa0\xe1\xa6\x73\xce\x7d\x84\x4b\x11\xa6\xc4\xfc\xcd\x9a\xef\xf5\xec\x1f\xa9\xf3\xfd\x64\xec\x83\xc0\xa3\x48\x56\x06\xf9\x38\x66\xaa\x4b\xcc\x2d\x7b\x5c\x6e\xae\xc1\xa8\x9e\xeb\x9b\x86\x48\xd6\xb3\xa9\x6b\xf0\xf8\xee\x73\x0a\x13\x25\x6f\x94\xe7\x2a\x57\x5a\xfb\x76\x64\xa4\xc4\x9f\x08\x63\xba\x6e\x43\x84\x49\x9d\x88\x41\x38\x45\x90\xc9\xc8\xa4\x08\x0e\x32\x12\xb5\x1e\x76\xb8\x34\xcf\xf5\x69\x35\x1f\x0f\xf3\xec\xd7\x43\xf2\x59\x9d\x9e\x4b\x77\x55\xea\xc9\x8f\xf3\x9f\x4c\x3a\x67\x18\xf3\xf1\x20\x6e\xa5\xdc\x3d\x94\x20\x4e\x16\x5c\x41\x5e\x61\x59\x83\x85\xb8\x0e\xe4\x05\x0e\x91\x93\x32\xe7\x8f\x47\xd2\xe7\xc8\xe5\x35\x10\x64\xbc\xeb\xf6\xa2\x33\x17\x61\xca\xe9\x6c\x4a\xcc\xc9\x4e\x72\x3b\x52\xa5\x0b\x90\xc4\x57\xf4\x6b\xa1\x7e\x35\xf1\xa8\xd5\x72\x75\x98\x73\x18\x32\x5d\x61\xa4\x67\xb8\xc4\x4a\x1f\x66\xce\x98\x1c\x22\xe7\x70\xdd\x82\xc5\x69\x57\xd8\xfd\x9e\x70\x01\x6d\x09\xa2\xa1\x32\x44\x66\x06\x6f\x66\x7b\x63\x99\x54\x03\xf5\xbc\xf4\xcf\x59\xc2\x63\x65\x4e\x1f\xb6\x54\x06\x94\x1e\x39\xff\x74\x80\x90\xd9\xb3\x26\x3d\x7f\xab\x1d\x74\xab\x12\xd4\xf1\xb4\xad\x8d\x71\xc8\xcf\x6b\x74\xa5\x4a\x3a\x43\x8a\x0e\x0c\xb8\x85\x2c\x31\xdc\x21\x53\x71\x57\x30\x16\x33\x10\xf1\x9b\xd2\xd6\xc8\x1f\xdc\x82\xa9\xb8\xe5\x60\x3b\xba\xcf\x8a\x23\xab\xd6\xc9\x67\x7c\x8a\x0d\xf8\xd4\x26\x0c\x39\x5a\x29\xa3\x29\x0c\xfa\xe2\x72\x13\x63\xda\x10\xf5\xda\xbd\x2c\x2d\x28\x84\x12\xb1\x7e\xde\xcf\x67\xe6\x5c\xa9\x8d\x9f\xa0\x2e\x48\xbb\x25\x60\xab\x81\xab\x30\x7d\xe8\x9f\xf7\xc4\xa8\xc8\xf3\xee\x46\xd0\xcf\x3b\x4c\x8f\xda\x4d\x52\x9f\x63\xf1\xc8\x5a\xe9\xe4\xbd\x2c\xcf\xa7\xcc\x2c\x99\xa7\xe7\xd3\x8a\xb7\xa5\x2f\xe0\xd9\x72\x90\x05\x39\xb2\x71\x6e\xa0\x58\x88\xcd\x95\x46\x88\xc0\x35\xda\x04\x75\x78\xcc\x03\x13\xcc\x41\x21\xec\x8e\x92\xc0\x22\xa8\xc1\xf2\xfb\x43\x5e\xe0\x1d\x22\x06\x18\x57\x60\x0a\x88\x66\x54\xb5\xc5\x5d\x83\xc8\xa5\xc0\xb4\xec\x9a\xe2\x7b\xba\xd4\x33\x57\xc3\x89\x8a\x26\x4a\xee\x9a\x21\xee\x62\x45\xc4\x84\x4c\x42\x6f\x90\x9f\x35\x1e\x08\x48\x84\x97\x1d\x75\x16\x3e\x15\x61\x00\xe6\xe5\xc9\x48\xe3\x59\xe5\x82\x95\x7f\x2e\x56\xbc\xb8\x1c\xd7\x36\x65\xfe\x0a\x6e\x2f\xf1\x8f\xe7\xca\x00\x97\x95\xbf\x1f\xdf\x27\x88\x9f\xab\x7c\xb7\xec\xb9\x4e\x2c\xd5\x87\x78\x16\xdd\xbd\xd2\x2b\xac\x67\x97\x92\x7e\x96\x20\x2c\xe6\xb3\xfb\x3c\x63\xe6\x80\x57\xa2\x7b\x58\x06\x51\x85\x9e\x05\xfa\x8d\x94\x54\x72\x36\x63\xb2\xee\x16\x04\x79\xb9\x4c\xb9\xe2\x67\x37\x06\x06\x4a\x9a\x3a\x7f\x66\xc5\x8e\xec\x84\x90\x49\x22\xf2\x20\x9b\x95\xb2\xcd\x33\x94\x98\x5f\xfd\x8c\x3a\xf4\x89\x29\xc4\xec\x99\xb9\xc8\x03\x4d\x17\x0d\xba\x62\xc2\xe3\x19\x96\xf2\x4f\x70\xad\xbc\x84\x95\x20\x0f\x21\x36\xd3\x13\xb1\xdb\xff\xc8\x69\xdc\x45\x6a\x3c\xc9\x4d\xbc\xde\x9c\xb8\x7f\xa6\xab\x5b\x6d\x49\xb7\x05\xe2\x95\xe2\x34\xb6\x46\x59\xb9\x27\x2c\xd9\x58\x96\xa0\x3d\x2a\xa4\xf5\x84\x6a\x03\x5f\x32\xfb\xb0\x99\x3d\xe5\xc8\x4b\x90\xc9\x49\xd6\x4c\x13\x87\x0e\x06\x2a\xd3\x6a\x1e\xb7\x52\x30\x1e\x91\xc5\x85\x29\x0b\xd6\xd2\x8f\x7b\xb9\x49\x4b\xfc\xb8\x4b\x18\x26\x91\xc3\x02\xcb\xbd\xb9\x4a\x47\x01\xc2\x3f\xaa\x61\x74\x27\x7d\x13\x5b\x90\x25\x16\xd2\xd7\x68\xbb\xd5\x92\xa7\x71\x3f\x7a\x1e\xd8\x83\xef\xee\xa3\x8a\xca\xd8\x94\x54\x0d\xa6\xa3\x7f\x08\x0f\xa7\xae\xd0\x91\xab\xca\x52\xca\xc0\xb3\x93\x1f\x45\xc9\xac\xa1\x7c\xf3\xa8\x24\xae\xf9\xf5\xac\xf2\xfc\x7b\x90\x57\xc2\x53\xda\xe3\x0c\x50\x68\xc8\x75\xf1\x15\x70\x7c\x86\x71\x3f\x2c\xbd\xc4\x72\xdc\x95\xda\xf7\x88\x2c\x4b\xe2\x7e\x4a\x3e\xe0\x87\xdb\x2e\x28\x8b\xc6\xc9\x8c\xe1\xd8\x45\x9f\xa7\x07\xfa\xbb\xe7\xe9\xb7\x3f\xaf\xf2\x2f\x33\x40\xfe\xa2\x8d\x19\x75\x60\xf0\x40\x58\xf2\x51\xe1\x4d\xe0\xed\x4b\x1c\xb9\x3c\x5c\x32\x33\x85\x91\x17\x7f\x61\x8f\x23\x88\xd9\xc8\x5d\x0b\x18\x7d\x8a\x96\x3d\x42\xa2\xde\xc0\x93\x49\x19\x8f\x34\x8a\x06\x23\xd1\x8f\xfc\x1e\x48\x42\xc8\x2f\xb9\x7b\xbd\x34\x9b\x9e\x31\x7d\x2c\x6e\xe4\x3b\x18\x91\xa2\x3a\x52\x91\x2c\xbb\xe0\x6f\x78\x82\xdd\x57\x11\xea\x04\x45\x98\xaf\x2a\x2e\x04\x9f\x8a\xae\x4d\xd9\x7b\xc0\x99\xc9\xac\x3e\xd2\x9e\x83\x21\x39\x50\xa1\x3f\x6b\x06\x3f\xff\xf4\x09\x5c\xf5\x57\xdf\x92\x14\x80\x49\x54\x04\xe1\x57\x9e\x64\xe0\x82\xd2\x2a\xec\xb7\x1b\x26\x5d\x91\x2a\xff\xe5\xc2\x48\xd1\xf1\xa0\xb3\x83\xf6\x26\x60\x7d\x24\x19\x10\xe7\x99\x99\x52\x19\x2f\x97\x7c\xca\x9e\xe1\x2f\x66\xdf\x50\x18\x8e\x85\x20\x6d\x8e\x09\x82\xcc\xe1\x51\xfe\x71\xa3\x9d\x59\x29\xda\xdb\xbb\xc4\x93\x98\xde\x6c\x6e\x27\xd2\xd0\x4e\xc1\x24\xa1\xe9\xe9\xd6\x10\x68\x92\xb1\xca\x74\x33\x3a\x39\x59\x5b\xba\xf0\x67\x4f\xe8\x97\xd2\x72\xcc\x7e\x95\xb8\xe5\xd6\xdf\xa7\x81\x3c\x40\xf4\x16\x0d\x8b\xf4\x67\x2f\xd4\xb3\x92\x45\xf9\x26\x6b\x4f\xce\x4f\x53\xfd\x91\xf3\xea\x3d\x91\x7a\x89\x04\x7c\x17\xc4\x81\x85\x19\x8b\x33\xee\x10\xb8\x9a\xac\xb9\xa7\xda\x19\x97\x7e\xfd\x8e\x10\x4d\x5e\x02\x3d\xbd\x35\x9b\xa2\x67\x3c\xc9\x99\xab\x0e\x54\xbf\x9f\x8a\xc4\x3b\xa6\x88\x7f\x4d\x45\x29\x78\x53\x81\xf2\x27\x57\xc5\xbc\xe1\x64\xf5\x1c\x7f\x77\x59\xc5\xef\x5c\x11\x95\xd0\x6f\x2d\x41\xf5\x5c\x74\xf0\xe7\x33\x40\x06\xd1\x88\xb4\xc6\xd2\x3d\xd5\xf4\xd9\x41\x0f\x8a\x7d\x86\xa9\x88\xf8\xb0\x65\x2e\x26\xb1\xb2\x60\xb6\x46\xea\xa8\x7d\x2d\x22\x51\x5a\x7b\xa3\xa8\x97\xfd\xb6\x3e\x7f\x80\x89\x74\x9f\xc6\x10\x1d\xb2\x91\xa0\x79\x24\x37\xf5\x07\x10\x0b\x14\x2e\xd3\xba\x29\x39\x42\x65\x40\x34\x79\x84\x95\x85\xec\x95\xad\x46\xa5\x0b\xc0\x7f\xe2\x74\x66\x81\xb3\x95\xaa\x0d\xd0\xeb\xe1\x6e\x1e\x28\x12\x52\x18\x6b\xca\x7f\x56\x49\xfa\x1d\xca\x9d\xf9\x9a\x9f\xc5\xcd\x21\x85\x27\x21\x18\x2f\x8a\xd3\xf9\x90\x5b\xdb\x08\x83\x34\xf2\x50\x9d\xab\xa2\x59\x11\x30\x3d\xb3\x12\x04\x27\x5a\xdd\x4e\xe9\xfe\xfa\x84\x86\xf3\x3d\x7f\x43\x16\x79\xab\x4f\x89\x6e\x73\x36\x54\xe6\x74\xc3\x64\x37\xf7\xae\x7c\xec\x21\xcb\x36\xb9\xe7\x34\xef\x06\x3c\x47\x78\xdc\x95\xcf\x83\xb2\x16\x53\x1a\xe5\x99\x46\x97\xba\xf1\x26\xe1\x11\x53\x78\x74\xad\xe2\xcc\x50\xd0\x28\xef\xd1\x19\x0d\xce\x5c\xbb\x07\x9f\xe3\x86\x18\xdc\xc6\x72\x22\x85\xb3\xbe\xbb\x8b\x1a\xb3\xe6\x47\xd7\x02\x26\x71\x10\x73\xb9\x31\x30\x1b\x9b\xe4\xff\x47\x06\x22\x46\xf5\x57\x41\x09\xbd\xc2\xce\x0a\xf7\x45\x4d\xb2\x61\xcd\x08\x8c\xd6\x4c\x66\x71\xef\x5a\xb8\x98\x41\xac\x96\x36\x25\x63\x45\x54\xa2\x33\x3d\xaf\x8b\x9c\x54\xa8\xfa\x91\x15\x2a\xe9\x38\xb8\xb1\x05\x3a\xe4\xe2\x55\x8f\x24\xaa\x27\xdf\x4e\x2b\x27\xd1\x3b\x2f\x8a\x5f\xc1\x91\x4d\xac\xd1\xdf\x4c\x27\x30\x7b\x02\x86\x7a\x5d\x05\x4e\x68\x13\x13\xf4\xd2\x76\xd0\x33\x13\x63\xb2\xae\xa1\x37\x62\xf0\xa1\xab\x05\x67\xa7\xf1\x56\xba\x14\x15\x79\xab\xf1\xc3\xd7\x5f\x87\x19\x73\x16\x27\x4b\x0d\x85\xc7\xb5\x7c\x5d\x61\x0c\xba\x84\xec\xe0\x8f\xab\xeb\x0d\x76\x58\x3b\xbe\xcf\x20\x8d\x26\xf2\xf1\xe0\xeb\x26\x3b\x3d\x28\x4d\x86\x59\x5b\x01\xab\x33\xc6\x19\xf6\xfc\x49\xf3\x1e\x3b\xb5\x65\x2c\x1b\x88\xb4\x7e\x43\x4a\x0a\xa3\x02\x91\x48\x49\x3c\xe2\x42\x30\x5b\x67\x0c\xe9\x48\x34\x2d\x5f\x86\x81\x91\x54\xb6\x97\x91\xdb\x96\x4e\x77\xb2\x9f\xff\x92\xd3\x04\x60\xa7\x99\xca\xfe\x0f\xe3\x57\x92\x50\x23\x3b\x70\x74\xb7\x5d\x82\x8d\xc5\x5a\x9e\xf5\x0f\x30\xaf\x39\xb8\x39\x63\xfa\xc8\x35\x2d\xc8\xa3\xaf\x14\x49\x0d\x23\xbe\x34\xf9\xda\xa5\x6b\x13\x6f\x38\x79\xce\x32\xf7\x95\xea\xe6\x98\xda\xdd\xd9\xa5\x37\x74\x0b\x09\xe1\x34\x21\xf4\x23\x9c\xb6\x7b\x10\x5d\xb5\x31\xad\xc9\x50\xa5\xaf\xcb\xe8\x59\x0d\xfa\x02\x12\x74\xbf\xb5\xe5\x8f\xbb\x3a\x24\xd1\x5e\x8f\x10\x5e\x1a\xa9\x4f\xf2\x9f\x98\xa9\x41\x26\xdd\x82\x54\xed\x39\x6a\x55\x3f\x68\x2b\x3a\xd0\x96\xff\x04\x92\x72\x63\xc6\x54\x4e\xd9\xd2\xd9\x23\x3e\x0e\xfe\x7b\x18\xa0\x59\x66\x9f\xe0\xc2\xc5\xe4\x11\x08\xe7\xad\x92\x1e\x26\x57\x9e\xe1\xfe\x9f\xa2\xca\xc3\x1d\x72\x45\xfe\x02\x04\x0b\x18\x6f\xde\x99\xb5\x7a\xef\x02\x13\xe0\xa3\xfe\xbb\xf0\x24\xcb\xb4\x5c\x8d\x1e\xe0\xc3\x9d\x49\x6d\x83\x28\x48\x27\xa3\x26\x71\x51\x17\xfd\x72\x50\x51\x87\x12\x3c\xcb\x7b\x14\x67\xf4\x3e\x3b\x3b\x75\x3f\xaf\x4e\x46\x2d\x9a\x06\x76\x87\xca\x7a\x93\x3b\x5a\xeb\x26\x16\xa9\x12\xd1\x00\x26\x1e\xa7\x8e\xdd\x48\x2e\xaa\x7a\xa0\xa0\x2d\xe2\xbd\x0c\x9a\x6a\xfe\xb2\x33\x6b\xe8\x0c\xcf\xb8\x1f\x27\xd0\x30\xc5\xe6\x86\x16\x33\xab\x30\x90\xd3\x61\x32\xb7\x8f\x38\x08\x4c\xe4\xee\xe0\xbc\x42\x40\x9e\x04\x72\x60\x5d\x60\x8a\x90\xb3\xc1\x60\x29\x3a\x31\x41\x80\xd3\x14\xe2\xc6\x0e\xe2\x7d\xca\xde\x7e\xa8\xff\x0b\x8a\xeb\x9b\x41\xe1\xa1\x86\x21\x1a\xc8\xdd\x62\x44\xd6\x2e\xf0\x45\xfb\x39\x12\x61\x2f\x49\x27\x0c\xd2\x41\xb6\x92\xd9\x58\x00\xa1\xff\x09\xe9\x17\xde\x2b\xa8\x4f\x88\x6a\x6b\xd5\xd9\x47\x20\xac\xee\xd0\x35\xe1\xf3\xa8\x0a\x75\x0e\x35\xec\xf8\xea\x1a\x6e\x76\x85\x3d\x7f\x03\x6b\x5c\xe5\xbc\xeb\xe4\x73\xf8\xd9\x75\xbe\x72\xb0\xe3\x01\x82\x30\x49\xcf\x98\x61\xfd\x90\x3e\x5c\x5e\x52\x50\x03\xa1\x8e\x25\xc7\xba\x70\x8a\xbe\x44\xcb\x55\x70\x1f\x14\x58\x8d\x46\x86\x22\x1d\x78\x03\xb3\xec\x3d\xc1\x7d\x4d\xc1\xc6\xfd\x35\x52\xe4\xb8\x0a\x90\x9c\xc6\x0b\xce\x8a\x7d\x1b\x08\x2f\x38\x4d\xd0\x83\xd6\x5e\xc9\x7b\x6d\xfb\x15\x5b\x85\x81\x1b\xec\x85\xd4\xa0\x0e\x68\x8a\xdf\x04\x4f\x5a\xbf\x58\x3f\xe2\x23\xbe\xeb\x27\x9c\xed\x38\x4b\x35\x60\x16\x4e\xc7\xda\xe9\xf4\x97\xe5\xd2\x01\xfa\x6b\x8a\x04\x3a\x58\x83\x51\x90\xc2\x4d\xc2\xc8\x1c\xed\xa9\xd1\xc3\xef\x0b\xcc\x4f\x99\xaa\x19\xe2\xa9\x1f\xec\xd1\x0e\xb4\x00\x02\x83\x53\xb7\x60\x9a\xe2\x5a\x7e\x5f\x2b\xcc\x35\x4e\xf1\xbd\x81\x83\x9d\xab\xa1\xff\x90\x3e\x2b\x99\xb3\xb4\x02\x1e\xe4\xb2\x63\x65\x50\xb6\x53\xf4\xe7\x07\x6a\x04\xcb\x84\x0e\xb7\xb9\x3b\xea\x59\xe3\x1d\x37\x2b\xb1\x66\x1b\x10\x38\xd4\x85\x59\x45\x1d\x46\x79\x56\x4d\xaf\xb4\xab\x0b\xa2\x75\x6a\x32\xab\x83\x8e\x15\x59\xb0\xa8\xa3\xf8\x13\x13\x85\x74\x87\xb4\x9e\xac\xb5\x9c\x6c\xab\xb7\x03\x7e\xde\xa2\xf4\xae\x52\x35\xb0\x1a\x54\x84\xac\xc1\xdd\x3e\x89\x46\xd6\x3b\x70\x83\x61\x39\xfa\xc1\x92\x52\x96\x90\x78\x12\xb6\x6f\x9c\x56\x01\xc9\x5b\x8e\x77\x77\x37\xb9\x43\x2e\x84\xd3\x42\xaf\x51\x39\x16\x98\x62\x41\x61\x75\x76\x63\x52\x00\x1e\xe9\xca\xfe\x27\x6c\x7a\x78\x30\x1b\x13\x87\xdf\x80\x4f\x82\x0e\x91\x31\x8f\x9c\x99\x91\xf4\xdb\xb4\x7b\x1b\xe1\x4e\x78\x7a\xa3\xe0\x6b\x02\xa1\x39\xde\xfc\x84\x04\x43\xb2\x5d\x3d\x37\x47\x74\xdb\x5d\x1c\xd6\x9d\xaf\x2d\x14\x49\xe5\x9f\x37\x35\xfd\x67\x6a\x1c\xaa\x00\x65\xa9\x78\x28\x07\x0e\x71\x43\xfd\xcb\xda\xc7\x27\xad\xf4\x3e\x3e\x27\x02\xfa\x6e\x7d\x39\xc8\x2b\x55\x27\x3c\x34\xeb\xbb\x6d\x49\x77\xce\x3a\xf6\x34\xb8\x73\x0d\xc0\xda\x1e\x8e\xed\x3c\x8c\x8f\xdb\x80\xbf\xbc\xb4\x01\xd3\x04\xad\x3c\x3c\x81\x2a\x95\x5f\x7b\x95\x58\x8f\xa7\x42\x6b\xfa\x34\x33\xaa\x0c\xa2\xaf\xf7\x46\xd3\xb3\x69\x4a\x17\x6e\x57\x9a\x09\x48\xd9\x7d\x48\x82\x0b\xac\x18\x27\xba\xf4\x8a\x95\x25\xeb\x66\x7b\xda\x50\x1a\x17\xa6\xf2\xcb\x69\x3f\x0d\x13\xc6\xec\x9b\xeb\x17\xdb\x4b\xe7\x47\xe3\x2c\xd8\xb7\x36\xb5\xea\xdf\x48\x94\xfa\x76\x6d\xaa\x2f\x67\x3a\xbf\xe5\x78\xd0\xb0\x0f\xb3\x3c\xe4\x7c\x7e\x0b\xfd\xfa\x38\x34\xfb\xb2\x8f\x6c\xcf\x8e\x93\x64\xdf\x14\xdc\x5e\xa9\xe4\x7c\xed\x49\x36\xfe\x67\x24\xc1\xe6\x8b\x39\xea\xe8\xfc\xd9\x42\x84\x2d\x3f\xdf\xff\xbb\xad\xcd\xf2\xa7\xe5\x69\x50\x5f\xaa\x49\x7e\xa8\xf0\xf7\x29\x3d\x4c\xf1\x89\x7a\xed\xc3\x59\x00\xe7\x02\x53\x6a\xc6\xe0\x12\x8e\x7f\x5b\x22\x81\xe3\xa3\x58\xfa\x27\xc1\x44\x54\x3c\xe0\x0f\x93\x3f\xde\x6c\xb6\xde\x61\x77\xd7\xbe\xf9\x8c\x0b\x7a\x37\x1f\xbe\xbd\x5b\x67\xe1\xda\x10\xfa\x26\x63\x37\x06\xd3\x4e\x21\xe6\x07\x49\x36\xb1\x03\xe5\x3d\xc1\x1a\xb0\x5b\xe0\xd9\xbd\xf5\xfc\xc7\x67\x5f\xd4\x01\x56\x65\xe8\xbf\xa3\x87\xfe\x56\x8f\xe9\x5d\x82\xab\x5b\x9a\x12\xc2\xdf\x1e\xf4\xda\xb5\x83\x2d\x74\x04\x41\xaf\x22\x18\x5a\xc2\x6f\xa5\x88\xbd\xd1\xde\x64\x91\x8a\x83\x7c\x09\x16\xb2\xbe\x77\x30\x8d\xf5\x25\x02\xe6\xed\x94\x87\xe0\xba\xd4\x93\x3c\x66\xe8\x90\x2c\xdc\x76\x91\x47\x61\x90\xa8\x8b\xc8\x27\x00\x39\xd0\xef\xdd\x7c\x97\xf0\xf8\x7e\x43\xcd\x99\x74\x65\x64\x15\x74\xed\x7f\xb0\x92\x65\xc8\x0f\x56\xf2\x1e\x2b\x25\xaf\xfe\xee\xa4\x7e\x43\x13\x09\x54\x86\x12\x33\xb7\xdf\xca\xc9\x78\x5b\xeb\xd7\x6d\x0a\x7d\x4c\xef\xcf\x29\xff\x04\xf4\xc1\xf4\x6d\x0c\x6c\x3a\xe9\xd7\xcb\x6e\xf1\x98\x8b\xc6\xc7\x20\x29\x2f\x34\x1a\x05\x0d\x39\xa8\xc9\x59\xbe\x88\x9e\xe4\x26\x1a\x17\x2c\x08\xc7\xb0\x20\x9c\x28\x9a\xec\x8c\x63\xf6\xb5\xe1\x3d\x18\xef\xb9\xe1\x91\xd3\x9b\xef\xa4\x2a\xf1\x9d\x94\x65\x61\x40\xc3\xa2\x77\x9a\x74\x57\x5f\xf5\xbd\xca\x73\xb0\x6d\x9a\x6d\x79\x61\xac\x47\xa2\x70\x9d\xc9\x1d\xf6\xbd\x5e\x48\xc3\x71\xca\xaf\x98\xd8\x2f\x99\x05\xb9\x00\x85\xd7\x37\x1e\x94\xd8\xf3\xfd\xea\x0b\xae\xb5\xfc\x5b\x62\x75\x04\xb1\x36\xff\x8c\x5e\xc5\x46\xae\xce\xb9\x2d\x49\x07\x90\xe9\x60\x0b\xf5\xaa\x97\x8c\x80\x5e\x56\x73\xfb\x3d\xc0\x54\xb3\xc0\x2a\xca\x32\x59\x81\xaf\xac\xe4\x9a\x57\xd2\x06\x68\x3b\x76\xb1\x7b\xe1\x7d\x2f\xc6\x6f\x1b\x82\x69\xfc\x66\xa2\x10\xc2\x6c\xe1\x57\x68\xbb\xd4\xe0\x30\xef\x08\xbd\x68\xd3\x2d\xa5\x3d\x78\xc5\x73\x37\x30\xb4\xe7\xa4\x83\xee\xa4\xc8\xbf\xd8\x3a\x04\xed\xb8\xb6\x43\x28\x87\x2e\x0e\x59\xca\xaf\xac\x6c\xb0\x4e\x5a\x5e\xaf\xbe\x34\x57\x17\xa4\xe4\xc2\xd0\x1d\x14\x07\xa4\x5b\xe8\x10\x78\xfc\x25\x08\xd0\x49\xba\x8c\x70\x4e\x64\x1c\xd6\x17\x8a\x38\xcf\x9a\x9b\x73\x25\x75\xf5\x8b\x40\x53\xf0\xde\xf0\x2d\x61\xee\x1b\x59\x45\x2c\x33\xf3\xa8\x7c\x52\x9c\x79\x82\x12\xe7\xbf\xc3\x4c\xf7\x92\x1a\x0a\x5c\x43\xfc\x82\x2e\x7b\xe7\xb8\x06\x13\xe5\xce\xf0\xbd\xd3\x97\x6b\xc0\x66\x16\x63\xd9\x0d\x6f\x2e\x62\xf2\x8c\xbd\xb9\xd6\xaa\x3e\xe9\x7a\x49\x0e\xf3\x6a\x91\x66\x77\xd5\xaf\xca\xff\x05\x13\x19\xe4\xd1\x51\x5c\x64\x0e\xa3\xaf\x7a\x54\xf9\x29\x1b\x2c\xe4\x19\x33\x55\xdf\x4a\x38\xa9\xf8\xf5\x54\xba\x8e\x21\x07\x97\x26\x87\x55\x2c\xe7\xcc\xc4\x2e\x6b\xfe\x55\x75\x5d\x4e\xa3\xcf\xb4\x66\x74\x9a\x71\x95\x9e\xb9\x2d\x6d\x4a\xd3\xbb\x66\x48\xbe\xf9\x8f\x99\xb3\x4c\x39\xf0\xed\x16\x19\x33\x26\x89\x12\x80\x8c\xcc\x2a\x1a\xce\x8c\x02\xed\x4b\x22\xf2\x0e\xef\x19\xd2\x94\x6d\xe4\xcb\x86\xf9\xca\x59\xee\x8c\xc9\xe7\x14\xae\xae\x58\x72\x61\x2e\xa9\x90\x6c\x1c\xf7\x3d\x29\xb3\xe7\xf2\x14\x45\xef\x0f\x5f\x49\x29\xaa\x20\x2c\xeb\x61\xa4\xee\x33\x74\x61\xe0\xfd\x21\x90\xa8\xce\x15\x19\x62\x34\x67\xe4\x56\x83\x68\xa8\x5f\xfb\x66\x9f\x1f\x27\x7d\x7d\x90\x07\x4b\x6e\x33\xe2\x5b\x0b\x11\x7c\x1e\xc2\x92\x0f\x72\x0b\xe1\xb1\x98\x3e\x7c\x76\x86\x68\xf6\xf7\xb2\xd6\x94\xac\xe7\x4b\x8e\x9f\x27\x0c\xd9\xbd\xa4\x61\xe0\x4d\x53\x51\x2b\xc9\x22\x75\xd1\xf2\x08\x01\xfa\x92\x76\x23\x3d\xe2\x44\xa0\xc3\x83\x39\x27\x0c\x08\x50\x5e\x37\xa7\xcd\x0c\x1c\xf2\x3c\x14\xe9\xb7\x1b\x13\xa0\xfa\x14\x9b\xb8\xd5\xb9\xaf\x63\xa6\x23\x4d\x19\x83\xe9\x8c\xfb\xcd\x73\x5f\x6e\x8d\xce\x53\x1c\xe9\x16\x55\x99\x31\x47\x67\x36\xb3\xdc\x36\x59\x40\x6e\x72\x56\xbb\xfe\x6e\x65\x30\xda\x67\x4b\xfe\xdf\x85\x50\x34\x6f\xe3\xd5\x2d\x18\x73\x30\x6c\xfb\xfc\xaf\xa1\x43\x53\x60\x06\xb7\xa0\x49\xc7\x44\x14\x51\xec\x83\x26\x85\x9c\x53\x77\x7e\x94\xd9\xdd\x35\xda\x37\xf8\x3f\xa2\x19\xe4\x10\x51\x99\xef\x6e\x31\xee\x8d\xbd\xa8\xd0\xd6\xa2\x75\x63\x3d\x2c\x91\xd6\xa7\x86\xf3\x3c\x10\xda\xe4\x3e\x07\x19\x53\x7e\x15\x56\xe7\xdc\xec\x07\x1b\x0c\xab\xcc\x23\x7f\x44\x11\x3d\x7a\x35\x66\xd0\x86\xfd\x8c\x15\x1a\xee\x0f\x03\x9e\x47\x37\xb7\xf5\xb7\x30\x68\x96\xd6\xb5\x25\xcb\xf9\xcd\x67\x55\x6f\x25\xb8\x9d\xd5\xd5\x88\xe8\x39\x07\x57\x7c\xfe\xbb\x89\xe6\xbc\xc7\x56\x5b\xd5\x5b\x0b\x5f\x4a\xf2\xa7\x29\x2a\x74\x56\x76\x1e\xfc\xb5\xd8\xad\xd2\x3f\x05\x16\x01\x52\x5d\xf7\xda\x0d\xa9\x4f\xba\x7c\xf8\xc8\x43\xa3\x9b\x13\x69\xb2\xe4\xd8\x6f\xf4\x2a\xdc\x52\x74\x6e\xad\x9f\xf0\xa3\x78\xae\x9a\xdd\x32\x40\x93\xc4\xe8\xa1\x9d\x4b\x15\x77\x7d\xf1\x04\x90\x13\x44\xf1\x44\x00\x91\x56\x32\xa3\xdf\x7c\x01\xca\x6f\xb8\x78\x22\x2a\xc9\x52\x2f\xa4\x55\xfb\x07\x47\x6a\x67\xb1\xcb\x0a\xd2\xf4\x46\x65\xd4\x13\x49\x5f\xb1\xab\x3b\x58\x2a\x73\xc0\x96\xc8\x6d\xef\xb3\x51\x27\xdc\xe8\xfd\xda\xca\x40\x8b\x8a\xb3\x68\xd8\x08\x2a\x75\xb8\x44\xde\x9c\x7f\x30\x90\xc7\x96\x1e\xa4\x3c\xb7\x90\xc8\x3b\x95\xa2\xd4\x9d\x0f\xe7\x2a\xff\x49\x90\x57\xf8\x04\xe0\x70\x79\x0a\x68\x27\xeb\x52\xc8\x79\x32\xb7\x6e\xa1\x38\x33\xd1\xc0\xfd\x2a\xd9\x80\x38\xfc\x51\xae\xe3\x2d\xb2\xe6\x8a\x9f\xb9\x35\xb0\xe2\x1a\x7b\x53\xbb\x92\x44\xdd\xe8\xf2\x71\x4a\x75\xfc\xec\x9f\x13\x72\x25\x65\x59\x29\xc3\xb2\x33\x26\x8c\x4f\xf5\x32\x40\xb2\x16\xb3\x58\xc2\x07\x79\x7e\x26\xbf\xd4\x9c\x43\xb5\xff\xcc\x53\x79\x71\xeb\x41\x1e\x88\xd6\x2b\xf5\x22\x6e\x60\x4e\x1e\x2a\x3f\x03\x6b\xab\x34\x30\x54\x4b\xc2\xf5\xd5\x39\xcc\x6f\x51\xa3\x9c\x72\xdd\xbe\xb1\xba\xdd\xbb\x08\xcd\x30\xf0\xec\x6b\x7f\xce\x92\x52\x93\x03\x21\x9a\xb5\x2e\x6c\x28\x1f\x3f\x4b\xca\x6c\x7d\x9f\xeb\x8a\xad\xe3\xa6\x03\xfd\x93\x89\xab\x65\xa2\xed\xee\x0e\x9e\x20\x54\xff\xd8\xdf\x36\xea\x7b\xf6\xfd\xd7\x5b\x67\x5b\x23\x75\x97\xde\x96\xc1\xa6\xee\xe2\x14\xc0\x0f\xb1\xb9\x73\xbc\x29\x5c\x4c\xc1\x37\x4f\x79\xea\x67\x94\xa9\xa3\xb5\xc8\x0a\x8e\x9d\xc9\x87\x4d\x67\xba\x29\x7d\x75\xba\xcc\xe0\x4e\xb4\xeb\x35\x01\xbf\x99\xa5\xdc\x24\xe5\x92\x01\x7f\xcb\xfa\x11\x80\xf5\xbf\x38\xd3\x56\xbf\x8c\x5a\x3d\x05\x8d\x5a\xf5\x25\x44\x64\x5c\x82\x43\x09\x56\x60\x4c\x8b\x88\xbd\x96\x6e\x62\xe9\x61\x10\xe4\x1d\x4a\x50\xc1\x9a\x7f\x35\x1d\x29\x5f\x59\x46\x95\xd3\x2d\x27\xd8\xd4\xeb\x3f\xc4\xa6\xb5\x1d\xfd\x22\xef\x6b\xa6\x8e\x79\xbb\xcf\x1f\x5b\xa6\x81\xbb\x9b\xff\x23\x53\xda\x49\xb6\xf7\xcc\xfd\x0c\xe4\xa8\xfd\xdb\xfd\x70\x8e\xeb\x2d\x42\xf4\x3d\x71\xc4\xd8\x50\x8b\x0a\x30\xc8\xdd\x7e\xb3\x30\x4e\x8d\xf6\x40\x45\x83\x71\xd1\x26\x1f\xca\x8b\x24\xda\x2a\x13\x20\x04\x9d\x83\x22\x5d\xa5\x69\x61\x68\xe2\x51\xf7\xa7\x72\x25\xc0\xef\x2f\x5c\x27\x8b\xd3\x56\x99\x42\xd8\xaa\x3d\x1a\x91\x89\xab\x06\x6a\x08\x51\x8b\x46\x6d\x0f\xda\x2f\xa1\xbc\x38\x09\x0c\x8f\x61\x44\x58\xe5\xc5\x19\x43\x64\x88\x30\x92\x1c\x8d\xae\x41\xe7\xeb\xb7\x42\xea\xaf\xdb\x5d\xca\x10\x33\xcb\xf9\xb3\x64\x0e\xcf\x91\xb1\x42\x3a\xb5\xab\x1e\x64\xc1\x4d\xc7\xb5\xb7\x8b\x36\x8a\x80\xea\x2d\x23\xd1\x36\xb4\x94\xdb\xec\x6e\x3d\x2d\xbf\x82\xec\xbc\x9d\x61\x0e\x9a\xb7\x7f\xfc\x2f\x6c\x49\x03\xd2\x98\x05\x02\x79\x9a\x89\x2f\x86\x34\xcb\xd0\x60\x55\x4f\x1a\xb5\xcf\x3e\xfb\xaf\xc8\xb3\x0c\x36\x95\xb9\x63\x60\xa7\xea\x94\xa1\x22\x37\xcc\x3c\x49\x4e\x88\xfa\x50\x9a\x57\xb5\x05\xcd\x92\x59\xbf\x7e\x92\xad\xe6\x67\xb8\xc5\x7f\xbe\x67\x26\x9f\x36\x31\x49\x9b\x44\x00\xc1\xf4\xfc\x23\x38\xa4\x8a\x82\xf8\x3c\x77\xdf\x42\xab\xc2\xe1\x1d\x68\x4a\x22\x50\x6f\x24\x54\xc3\x68\x8b\x5c\xec\x22\x5b\xce\xe0\xb2\xc3\xb1\x50\x1c\xeb\x99\x7b\xdb\x57\xc1\xd3\x3f\x92\xba\xec\xcd\xae\x76\xa7\x41\x67\x16\x1b\xcb\xd0\x5f\x62\x99\x45\xaf\xfe\xf8\x17\x74\x58\x55\x24\xd6\x33\xdc\x12\xc8\xa8\xfe\x67\xb6\xe6\xa0\xb4\xf7\x71\x93\x3e\x7c\x6b\xa6\xfc\x68\x9c\xfd\x3d\x14\x08\x86\x9d\x27\x23\xd8\xb0\xf1\xd4\x44\x81\xc1\x3b\x87\xa3\x27\xa4\x75\x7d\x25\x8c\xa9\xc8\x3f\x36\x94\x84\xae\x4b\xe9\x3e\x07\x3e\x18\x99\x76\x92\x31\xab\x21\xe4\x61\x9f\xcd\x4c\x5f\xf4\x43\x93\x0d\x47\x6d\x32\x6d\x3d\xea\xc1\x77\xfc\xa8\x55\x12\x81\x68\xbf\x27\xd2\x59\x0d\x8e\x1f\xae\x5b\x18\xd9\x3a\x2a\x8f\xb9\xde\xaf\x42\x8d\x9e\x43\x21\x21\x7b\x62\x3e\xe2\x3e\x56\xe5\x1a\x1e\x45\xcc\xdf\xf2\x9b\xc2\x3d\x90\xc8\x2b\x11\x06\x78\x7b\x86\x4f\x26\x08\xd5\x62\x62\xff\xd3\x85\x77\x57\x70\x92\x8e\xe7\x42\xf1\xbe\x63\x4e\x5c\x56\xa0\xfb\x78\x50\xcd\xe8\xd0\xdb\x71\x78\x83\xa2\x5f\x19\x8d\x8b\xd3\xb0\xc7\x1f\x0b\xbb\x31\x79\xef\xd4\x52\x12\xf0\xee\xe9\x11\x71\x68\xa7\x58\xb7\x30\xdd\x0c\xa3\x20\x43\x0c\xd7\x3a\xdf\x9a\xa5\x4c\x3d\xa5\x1a\x62\xfd\xc9\x59\xdc\xee\xe4\x8f\x28\x7d\xb7\x30\xcb\x04\x31\xc1\xff\x95\xac\x7b\xd3\x86\xff\x48\x9e\xe6\x29\x52\x84\x28\xa1\xe2\x42\xa2\x75\x1b\x15\xda\x39\x92\xbf\xad\x42\x93\x88\xd5\x87\x8e\xc5\xf9\x08\x74\x59\x6d\x88\x55\x02\x23\xdf\x56\x47\xde\x27\x71\xb9\xf7\x51\xc1\xf3\x43\x73\x8f\xe0\x5d\x6b\x56\x06\x6a\x3f\x62\x7b\x62\x9c\xba\x2f\xb1\x81\xd8\xdf\x3e\x6e\xe7\xc1\xc7\x85\x93\x8d\x70\xff\xe4\x03\xac\xfa\x14\x20\x23\x11\xb5\x80\x55\x16\x41\xbc\xbe\xcb\xf6\x33\xfe\xd4\xcc\xb5\xf5\x75\x6f\xd2\xb1\x35\xc7\x5b\x4f\x37\x9f\x24\x6e\xf5\xeb\xc5\x93\x83\x12\xce\x70\x51\xa8\xb4\x36\xf2\x1f\xac\x4f\xe1\xc4\xed\x43\xea\x79\xd5\x86\x90\xce\xdb\x5e\x41\xd9\xf2\x4e\x64\x0d\x45\x3c\xeb\xa5\x3f\x74\x64\x58\xe7\xeb\x62\xd7\xfc\x67\x8f\x55\x2e\xa5\x4b\x30\xb9\x6f\x0f\x02\xd5\xd9\xab\xc1\x3a\xab\xd5\xae\x70\x0f\x21\xc3\x5c\xe9\xa1\x61\x0a\xea\x47\x0d\x62\x6f\xb5\xa7\x7f\xd2\xc3\x74\xaa\xa1\x29\x6d\xbd\x77\xbf\x49\x48\xcb\x11\x39\x1d\x81\xa5\x0a\xeb\x11\x6f\x41\xea\xd0\x3e\x22\x84\xa3\x2a\x27\x77\xfa\x23\x01\xb5\xfd\x23\xc5\x2e\x03\x5a\xa1\x11\xc3\x7e\x93\x9b\x7d\x4b\x00\x6c\xc7\x67\xed\xaf\x29\xbc\xdf\xb5\x46\x03\x21\x43\xd2\x33\xdb\x91\x8b\xd1\x1c\x88\xbd\xbe\x73\x0c\xba\x87\x40\xda\x6e\x37\x2b\x46\x65\x7b\x1d\xa9\x1f\x05\x13\x53\x68\xa0\x12\xa2\xb5\x91\x01\x6a\xf1\x2c\x0c\xbf\xe4\x2c\x41\xec\x3d\xdf\xc3\xad\x3e\x37\x9c\x4a\xad\xdd\x65\x67\x03\x0b\xcc\x46\x07\x67\x5b\x61\x0d\x7b\x15\xaf\x56\x04\xbc\x78\x56\x45\x75\x61\x56\x8a\x02\x22\x0a\xe4\x5d\x5f\x67\x50\xb7\x90\xe4\x29\x60\x1d\xee\x4c\xeb\x46\x78\x50\x25\x5a\x2b\xde\x68\x14\x48\x94\x36\x38\xa9\xa4\x37\xe3\xed\xaf\x87\x15\xe4\x36\xde\xfb\x88\x2e\xac\x43\xfb\x88\xc8\x35\x0e\x67\xc1\x4d\x71\x9f\xad\x7e\x44\x7d\x56\xb8\xd2\x3d\x4e\x49\x44\xad\x9a\x55\x33\x30\x52\xed\x7a\x83\xae\x18\x77\x67\xe2\xd3\x06\x4b\x0a\x57\x9b\x02\x22\x3f\x7b\xd7\x71\xf6\x91\xb4\x52\xe7\x5b\x3b\xdf\xb5\xae\x5f\x0a\xcb\xda\xd0\x91\xe9\x20\xe0\x4f\xf3\xe2\x99\x42\x63\x45\x09\xe2\x69\xb9\x54\x3d\x61\x54\x28\x5d\xaa\xad\x78\x6d\xc3\x4b\xb7\x2e\x0b\xe9\xc1\x88\x9a\xca\x05\x60\xb3\xee\xcc\x50\xc4\x9d\xde\x5d\xe5\x5d\x98\x94\xe9\xbd\x33\xad\xf7\xae\x40\x01\x0c\x72\x95\xd8\xe0\x3d\xc0\xbe\x21\x0a\xcb\xd8\x16\x46\x7d\x59\x3b\xae\xeb\x9b\xf4\x62\xb7\x71\xfa\xf9\xa7\x32\x0a\xb1\x95\xa5\xdd\xbc\xfe\x39\xad\xbc\xbc\x18\xfe\xb9\x81\xaa\x77\xec\xb6\xec\xf1\x29\xab\x40\x82\x24\x9e\x4f\xd0\xa1\xfd\x27\x20\xc5\xd5\xc6\x10\x3f\x2e\x36\x0b\x8d\x31\x36\x88\x67\x68\x95\x9b\x51\xd2\x92\x16\x86\x85\x2c\x27\xeb\x33\x53\x32\x7c\x0b\x69\x4c\x37\x63\x25\x79\x39\xaf\x61\xcd\xee\xba\x2e\x64\xcb\x6b\x54\x8a\x72\x67\xbe\xf5\x96\x17\xca\x57\x6f\xb9\xd0\x05\x6a\xcb\xfe\x33\xc4\x17\x17\xf9\x19\xa1\x7d\xf1\x75\xc7\xb7\xb2\xac\xb6\x11\x31\x07\xd1\x79\x47\x06\x41\xb7\x71\xa7\x74\x0d\x40\x12\x5d\x7a\xf3\x9e\x85\xc3\x25\x27\x72\xaf\x67\xe4\xb2\xf9\xe9\xc6\xe7\x5d\xa4\xbb\x61\x38\x46\xdd\xb0\x6a\x6d\x99\xea\x19\xc0\xb3\x08\xc1\x80\x59\x71\x37\xb7\x73\x0d\xc3\x4b\x10\xbb\xdb\x95\xc2\xab\xf5\xe6\xa7\x47\x62\x77\x13\x6c\x41\xf6\x6e\x9b\xfb\x77\x92\xe1\xad\x0d\x57\xe9\x31\xb8\x7b\x2b\x72\x3b\xb4\x71\x6a\xfd\x04\xe0\x8d\x38\x4a\x61\xef\x9b\xbe\x5f\x59\xb2\x7e\x45\xb2\xfe\xca\xc6\x6c\xb3\xc1\x95\x5c\x84\x35\x7d\xbd\x91\x9e\x0a\xe6\x36\x3d\x74\x9d\x90\xdd\xb9\xd9\x20\x66\x10\xbb\xe9\x92\x60\xf0\xb0\x8b\x76\xc1\x5c\x6e\x15\x0a\xbb\x5e\x83\xe9\x19\x3c\xed\x2f\xe7\xb2\x0d\xc9\x06\x0b\xdc\x6d\xdd\x96\xd4\xce\xaf\x9a\x44\xe4\x04\xc5\x86\x9b\x8e\xdd\x38\xb7\x00\xef\x57\x65\x05\xbb\xf3\xab\x14\x10\x92\xd2\xaf\x00\xc2\x23\x76\xac\x9b\x40\x89\xf7\x13\x82\xcc\xc1\x2d\x6f\xb2\x0d\xda\x90\xb7\xa4\x7d\xf6\x6f\xa7\x76\x5f\x62\xbb\x63\xe6\x47\xfc\x70\x7c\x36\x64\x67\xef\xa9\xca\xe2\x76\xdd\x9e\xc1\x19\x77\x49\xbf\x2c\x58\x62\x9d\xc4\x03\xd2\xda\x6f\xf8\xd2\x5f\xe0\x30\xb2\x74\x76\xf8\x8f\x90\x5f\xc0\x44\x0f\x8a\x7d\x61\x52\x2e\x18\xe1\xbc\xda\x67\xbd\x3f\xfc\x1a\x23\x0d\x6e\x4b\x39\x18\xee\xd3\x47\x8f\x71\xba\xb3\x2e\x3b\x58\xe9\x93\x06\x59\x08\x27\xc6\x69\xc5\xcf\x73\xd3\x59\xd5\x98\x49\x26\xce\x69\x7c\x62\x14\xf9\x1f\x28\xe5\xcc\x6e\x01\x29\x6c\x25\x48\xec\x3c\xad\xb7\xba\x81\xeb\xad\xb7\x7e\xbd\x17\xef\xf9\xaf\xf7\x94\xbb\x41\x6c\xf1\x36\x7a\xd5\x34\xc3\x5a\xdf\x93\xdc\x5a\xd5\x5b\x70\x0a\x7a\xf7\x60\xad\x67\x10\xd0\x79\x97\xc8\x44\x17\xa1\xbb\xb6\xd8\x57\x23\xfd\xb5\x1e\x1a\xc5\x81\xa7\x1e\xc7\xab\x9b\x80\x8d\x58\x35\xc9\x0e\x8c\x6c\x3b\x8f\x48\xd9\xc2\x48\x5e\x77\x0d\x16\xfb\x53\x6f\xd5\x5a\x21\x39\xb9\xca\x9e\x08\x3d\xf0\x1f\x55\xbe\xbc\x2a\x19\xe6\x65\xd7\x04\x1b\xbe\xd0\x5f\x10\x0c\x29\x93\x2b\xc7\x0c\x74\x83\x55\xd6\x19\xc8\x1a\x4f\xf9\xc5\x8a\xf1\x8d\xd9\x3b\x85\x85\x1d\x77\xd5\x0a\xab\xc1\x4f\x11\xcd\xc9\xa1\xcf\x3e\xd1\x24\x12\x7c\xe6\x48\x6f\xcd\x07\xd3\xf3\x60\x15\xab\x61\xe5\x2a\xaa\x14\xfc\x9e\xb8\xa3\xc2\x5f\x2b\xd3\xe3\x89\x30\x52\xe3\x56\x33\x26\x98\x04\xf9\xa4\x72\xbe\xe4\x3f\x1b\x64\xba\xd5\xc6\xd2\xe1\x40\x3b\xbd\x99\x91\xb1\xe6\x7f\x1c\x67\xf3\xb8\xc6\x85\xe8\xc2\x82\x9c\x9f\x93\x52\x4a\xd7\xe4\x32\x4d\x8e\x3e\x24\xad\x7b\x64\x67\x4d\xff\x13\x5f\x3d\x74\x45\x41\x38\x6a\xca\xf6\x59\xd3\xab\x72\x6f\xc4\x32\xef\x40\x13\xff\x77\xd5\x9b\x71\x12\x83\xe1\x64\x7b\xcd\x3a\x9c\xf2\xcb\x41\xaa\x8f\x0e\x33\x32\x87\xd8\xc1\x72\xcf\x5a\xa6\x86\xae\x29\xdc\x84\xad\xe7\x5f\xf8\x4f\x1b\x7d\x6d\xfc\xdf\xfe\x2d\x6b\x0d\xae\xbc\x75\x66\x68\xb0\x8b\xd9\xbf\xa7\xfc\x72\xf7\x89\x8a\x3e\xce\x28\xf5\x26\x62\x4d\x5b\xb7\xa6\x5d\x75\xba\x95\x67\x58\xe2\x73\xb0\x4f\xfd\xaa\xdc\xc4\xe3\x8c\x6b\x9a\xc5\xfc\x77\xfa\x1a\x51\x6e\xd1\x3e\x82\xa7\xcf\x7f\x3f\xec\x16\xeb\x37\x87\xc8\xc0\xd0\xc4\x29\x86\xd8\x66\xa7\x1f\xdf\xba\x25\x60\xe7\x2b\xf8\xb3\xdc\xeb\x3f\xbe\xb3\xf7\x9f\xf7\xcb\x97\x3b\xcf\x3b\xb9\xe0\xf7\x60\xaf\x08\x57\xb6\xef\x4f\xed\x18\x14\x7e\xa7\xaa\x37\x56\x77\x8b\x0d\x6d\xcb\x52\x05\x69\xde\x8a\x99\x30\x9e\xa3\x85\x27\xe4\x02\xf7\x3e\xa7\x86\xb4\x58\x62\x79\x86\x51\x6e\xb0\xb6\x1b\x19\x1a\xc2\x22\xa2\x37\x66\x0d\x59\x19\xdc\xe9\x96\x90\x5a\x4e\xab\xc1\xa5\xb2\x87\xb9\x54\x65\xa0\x2d\x55\x8a\x83\x4b\x3d\x10\x4e\x72\xb4\x33\xbd\x60\x89\xdc\x17\x03\x64\xe3\xcb\x60\x70\xa9\x73\x90\xff\x31\x18\xe5\x71\xf2\x5e\x9e\x3c\xb4\xa8\xfb\x48\xd3\x0d\x96\xff\x40\x92\x38\xc4\xa0\x74\x55\xbb\x98\xbe\x06\xb2\x42\xb7\xe4\xf4\x93\xc8\x5f\x69\xfb\xe0\x3f\x7d\x75\x5d\x3d\xd1\xf5\xd5\x42\xb9\xcf\x2e\x5b\xd5\xa5\x9c\x29\x88\xf1\x45\xd4\xfb\xc6\x7e\xdb\xa2\x18\x7a\x6f\x34\xe0\xa7\x9b\xc3\x73\x37\x22\x22\x0b\x3b\x0a\x20\xf3\x6b\x76\x7a\x91\x2c\xc4\x52\x86\x3a\x69\x78\x87\xb1\xe5\x0b\x55\xa2\xdf\xa3\xfc\x61\x26\xf9\x12\x4e\xc0\xe2\x5e\x2e\xb2\x27\x5f\x5c\xb6\xff\x95\xfc\x68\x48\x7a\xf0\x41\x3c\x10\x0f\x9c\xb7\xe3\x52\xa9\x15\x99\x44\x74\xeb\x46\x49\xa1\x6e\xc1\x00\x3d\xb7\xa0\xc5\x7f\x45\x80\xff\xfe\x98\xf4\xef\x04\x43\x61\xae\x0e\xef\xe5\x74\xde\xfc\xe7\xa9\x24\x0e\xa0\x1c\x2c\xfc\xdf\xe1\xfa\x40\xca\xa0\x6c\xb1\x16\x37\xe8\x74\xb0\x6b\xe2\x77\x61\xe6\x01\xf8\xf7\xdc\x6d\x8d\xb0\xce\xa2\x6f\x14\x4c\xfc\x9d\xff\x9b\x29\xc7\x90\x66\x4d\xc9\x2d\x31\xa9\x0b\x07\x5e\x8a\xf3\xfd\xdd\x08\x00\x9c\x8e\x48\x3a\xf9\xbb\x33\xd5\x24\xff\x6e\xf9\x8c\xff\x31\xfa\xf6\x57\x31\x77\xe3\x51\x9e\xbf\xba\x2b\xad\xd2\x10\x69\xf2\x55\x9c\xfa\x3a\x04\x33\xff\x49\xd3\x42\xf8\xf3\xfe\xa5\xd1\x2a\x29\xff\x7f\x7a\xff\xf2\x9c\xfe\x78\x03\x1c\xed\x32\x3d\xff\x4b\x92\x45\xfa\x43\xb8\xa2\x93\xf0\x77\x15\xb1\x3c\x2e\xbf\x83\xc4\xbc\xde\x5f\x1a\x06\x06\x1e\x0b\x63\x3c\xe5\xa5\x10\x42\xe4\xcf\xd8\xa0\x44\x12\x98\x05\xd6\xdd\x6a\x92\x0d\xcb\xc6\xd7\xde\xb7\xfa\xa4\xd5\x2f\xdf\xb7\xb2\x64\x99\xa3\xfc\x63\x4d\x39\x7f\x82\x5c\xff\x3f\xb5\x9b\x90\xb1\xa5\x35\xeb\x2d\x42\x74\x58\x17\xfa\x0c\x14\xd7\x74\xb2\xd4\x7c\x6f\xdd\x4b\x61\x16\x3b\x19\x2a\x6e\x85\xa4\x38\xef\xae\x8b\xf4\xff\x64\x2b\x30\xdf\x53\xc8\x04\x0c\xbc\x03\x30\xd0\xf3\x68\xce\x8c\x48\x8a\xc2\xdd\x33\xc6\x99\x24\xcf\x9f\x1c\xdb\x22\x6b\x56\xde\xbf\x9d\x99\x6d\x97\x4c\xf2\x7a\xdd\xd5\x92\xfd\x04\x6a\xc1\xe6\xd7\xa1\xd6\xa0\xf7\x5b\x9f\x44\xde\x35\xa4\xf4\xf7\x09\x57\x5f\xfc\xb1\xfa\x3b\x39\xbd\xce\xfd\x54\xf6\x52\x28\xf1\x63\xae\x53\x9c\x6c\x92\xaf\xaf\x0e\x5a\x1a\x7f\x48\xd9\xbf\xb1\x5f\xd9\x51\xab\xf0\x85\x98\x7f\x16\xbf\xd2\x75\xb0\x8e\xc6\x97\x85\x94\x3d\x66\xeb\x72\x84\xe5\xef\x33\x51\x2b\xcc\x9a\x0a\x72\x52\xe9\x02\x0c\x90\x43\xbb\x79\xce\xdd\xda\x57\x16\x97\x48\x11\x98\x97\x70\xc2\x06\xc3\x3f\x33\xda\xa7\x39\x20\xc1\x27\xf9\xe8\xd9\x2e\xef\x79\x8b\xe1\x2f\xc6\xc7\x1c\x9a\x3b\x60\xec\x77\xd1\x63\x2c\x14\xf1\xf8\xa7\x90\x1c\x90\x69\x37\x0c\x82\xe3\x7c\xe5\x11\x3a\x02\x88\xa8\x72\xb3\xa7\x78\xf0\xd6\x81\xd3\xc3\xcf\x43\x6c\xd5\xd9\xb8\x06\xcf\xb5\x90\x4a\xff\x0d\xf0\xe1\x84\xbe\x01\x0e\x0b\xe7\xf4\x66\xa5\x38\xa3\xd3\xb1\x25\x91\xe8\x5f\xfc\x85\x9e\xe2\xea\xe0\xa4\xfb\x38\x38\xff\x7b\x18\x3d\x83\xe1\xb9\x12\x5c\x7b\x37\x13\x8e\x55\xf4\xf7\x33\x70\x94\x10\x00\x58\x9a\xe6\x50\xe6\xf0\x8d\x81\x16\x80\x56\xa0\x7f\xc5\xe9\x17\xab\x93\xbe\x59\x9e\xc1\x3b\x75\x2f\x52\x37\x66\x9c\x9d\x52\x41\xb0\xb9\x11\xf3\x56\xa8\xd3\x90\xd8\x0a\x23\x0b\x9d\x49\x87\x73\x8c\x4e\x30\x11\xb7\xc6\x55\x14\x2a\x0e\x3c\x9f\xec\x4c\xc2\x47\x98\xdb\xe8\x42\xa6\x22\x86\xb2\xc1\xc4\x6d\xc7\x25\x3e\xe6\x34\xe4\xec\xd6\xb4\xf7\x87\x81\xee\xa7\x0f\x0c\x9c\x95\x7c\xef\x9a\xac\x7b\x92\xda\x10\x56\xc2\x61\x11\x0e\x38\xa8\x81\x32\x2c\xdf\xd9\x1b\xf6\x84\x8d\xda\x03\x4a\x2f\x7c\xde\xb4\x74\xbd\x47\xd1\xaa\x6f\x5c\x94\x23\xeb\xb3\x0c\x3f\xf6\x3e\xb2\x48\x9d\xed\xee\x12\xc4\x91\x64\x6b\x4b\x9b\xbf\x8c\xae\x3c\x10\x8a\xf2\xcf\x7f\xf5\x87\x3d\x68\xa8\x2f\xca\x30\xf7\xd2\x4c\x14\x80\x5c\x4f\x0d\x3e\x1e\x85\x56\xe4\x2e\x59\xa0\x5e\xfe\x33\x26\x82\x20\x56\xa0\x89\x2c\xef\xd3\xe9\x26\xbb\xea\x80\x22\x20\x54\x20\x88\xa4\x64\x5b\x12\xf7\x5f\xa6\x6a\x36\xf4\x92\xd7\x6e\xbd\x99\xe4\xf3\x8c\x38\xd8\x93\xb9\xec\x88\xe3\xc5\x71\x6b\x8b\x59\x16\xc8\x0d\x44\x34\x08\x98\x32\x2e\x40\x6b\x5f\x07\x51\x8b\x90\x26\x98\x03\xe2\xd5\x92\x0a\xc1\xfe\x13\x3a\x58\xa7\x9f\xc0\x23\x96\x68\xd9\xf8\xc4\x14\x5f\x08\x0c\xb4\x55\xda\x0d\xd4\xf9\xe6\xd1\xb2\x3a\x57\xcf\x3a\x48\x99\x60\xc8\x6a\x1f\xec\x1b\xf5\xa6\xfc\xb9\x4a\x68\xcc\x4d\x91\x79\xaf\x3c\xbf\x9f\x1b\x75\x1f\xa2\x67\xb9\x4f\x89\x03\xb4\xae\x30\x70\xb0\xc7\xf1\x8c\x81\x19\xb4\x06\x74\xbf\x8a\xdd\xc9\x4a\x4a\x3e\x6a\x70\x09\x16\x64\x4d\xc0\x3c\x73\x37\xab\x7a\xa2\x72\x12\xf3\x1f\x63\x49\x5d\x4d\x3e\x74\x12\xb6\xce\x56\xe8\x66\x64\xaa\xb7\x3c\xff\xa1\x28\x43\x32\x40\x0a\x01\xc3\x20\x6f\xe3\x8f\x76\x4f\xca\xaa\x7c\x26\x37\x9b\xfd\x8f\x32\x00\x65\xe7\x84\xd4\x13\xb3\x14\xf1\xc2\xe2\x57\x17\xca\x4f\x43\x18\xa0\xb2\x94\x6d\xf1\x2e\xff\x6c\xf1\xbf\x9f\x69\x3d\xf4\x9f\x75\x95\x51\xf2\x5a\xbe\x3a\xf9\xdf\xc4\xd2\x2d\x19\x9e\xf1\x8a\x27\x7b\x5b\x9f\xe1\x6d\x2c\x39\x80\xc6\xbc\x65\x98\x1d\x2b\x6f\xf2\xd1\x6c\x4c\xcc\x80\xfd\xa3\x75\x0b\x22\x97\x07\x38\x05\xda\xc4\x9b\xe4\x8c\x51\x89\x51\x3c\x42\xbe\xd9\x69\xff\x21\x8e\x0a\x5b\x63\x16\x2d\x77\x80\xfb\x82\x0c\x51\x66\x87\x3c\x38\xb9\xf3\x08\x0d\x95\x87\x3c\x0a\xad\x64\xde\xc5\xa3\x87\x49\x9d\x99\xbf\x77\x0a\x95\x2d\xe6\x87\x12\x96\x1e\x65\x75\x2e\x98\x95\xe4\x90\x3c\x4a\xee\xcc\xfe\xde\x82\x80\xaf\x9f\x3f\x8d\x3c\x7e\xeb\x67\x48\x6c\x06\x9e\xc3\x39\x2c\x87\xf5\x5f\xf9\xdb\x3e\xa4\xbd\xff\xc8\x4a\xb3\x7d\x64\xa7\xbe\x96\x80\xbc\x12\xcc\x4b\x4b\x3c\x21\xf8\x21\x8f\x74\x9f\xbb\x9a\xf8\x87\xb7\x14\xbe\x3b\x69\x6c\x8f\x20\x71\x3c\x3c\x76\xb5\xca\xd4\xd8\xee\xa0\xd2\xab\x0c\xb3\xf7\x84\x89\x53\x49\x00\x40\xbf\xd0\xdf\x9a\x47\x82\x67\x2b\x37\x1b\xfc\x3d\xc9\xff\x53\x48\x3a\xbf\xc5\x5b\x27\x51\x10\x0d\x77\x66\x0d\x65\x3d\x78\xe6\xaf\x79\x2c\xb7\x8f\x18\xdc\x04\x59\x29\x53\xf9\x47\xfe\x4f\x3f\x8f\x60\xe5\x20\xe6\xf3\x60\xdd\x01\x11\x29\xe8\x88\xd3\x74\xc0\x6e\xe3\x97\xcc\xfa\x83\xb9\x3d\x56\xb2\xc2\xce\xfb\xf5\x2e\x9c\xa8\xc9\x91\x45\x49\xb3\x63\x07\xe8\x06\x28\x32\x9c\x43\xd2\x1d\x09\x36\xe2\xeb\xcb\x43\x59\x4a\xe7\xa8\x23\x82\xa4\xdf\xed\xa7\x34\xd1\x9f\x9f\x32\x73\x44\x48\x38\x54\x08\x28\x8c\x92\x7f\xd3\x41\x18\x33\xaf\x3f\x31\x02\x4e\x75\x66\xe8\x20\x00\x58\xdd\x4f\x3b\xdd\x0f\x87\xd6\x13\xf9\x96\x93\x24\xd4\xa7\x5b\x92\xce\x53\xa4\x45\x4d\x90\xa4\xe5\x26\xbf\x6e\xdd\x74\x53\x3f\x60\x52\xc2\xe2\xc4\x91\xea\x04\xd7\x96\xdd\xc1\x43\x2d\xe5\x74\xf7\x33\xde\x63\xcb\x87\xfe\x3d\xd0\x7b\xda\x01\xcb\xa2\xd2\x3b\x1c\x93\xa7\x67\x38\x28\xd4\xcd\x9c\x6c\xac\xad\x9e\xfd\x54\xff\x77\x25\x4a\x83\xc3\x63\x99\x47\xac\xef\xdd\x9b\x24\xb0\xfa\x33\x09\xfc\x72\xb4\x9d\x22\x48\x36\x49\x22\x76\xfa\x51\xfc\xcf\x1c\x5c\xff\x21\x6e\x00\x1a\x06\x96\x14\x23\x9b\x6a\xb7\xca\x00\x7c\x32\xa8\x32\xd5\x59\xfa\x02\x21\xef\x04\xa4\x4e\xd8\x54\x07\x9d\x79\x08\x4f\xe3\x42\xf7\x83\xa9\x58\xed\xbe\x8a\xf0\xff\x8f\xf3\x70\x89\x29\xbf\xa9\x28\xb3\x65\x0a\x37\x24\xfb\x70\x93\xf7\xf6\xc0\xca\xff\xa8\xe4\x23\xca\x2f\xcd\xf2\x4e\xfe\xf6\x3b\xb8\x38\x58\x9a\xf2\x09\x9f\x2b\xb6\xad\x13\xec\x1b\xb9\xeb\xc9\x18\xa9\x2b\xe1\xf3\x5f\x47\x9e\x44\xc6\x0f\x52\xc4\xe4\xa4\x2c\xde\xa2\xee\x26\x0d\xc0\x3d\xb7\xd2\xfe\x8a\x8c\x94\x31\x17\x32\x87\x7a\x00\x22\xe9\xd4\x79\x77\x9c\xc5\xd5\x7f\x2a\x5a\x69\xf0\x11\xfa\xbd\xc8\xa9\xbe\x5d\x70\xf8\xd4\xd2\x16\xd4\xff\x34\xf2\x1a\xca\xa5\x06\xca\xe0\x29\xff\xec\x0c\x79\x22\xb2\xe5\x01\xd3\xe3\x3f\xd2\xf9\xa5\xb3\x90\x51\x27\x1e\x87\x8e\x39\x62\xce\x58\x3f\x68\x68\x37\x5f\x13\xb7\x73\x2e\x44\x3a\x63\xd8\x21\x19\xf2\xc6\x71\x82\x24\xac\x0f\x97\x27\x68\xdd\x90\x93\x2f\x1f\x98\xc9\x4d\x10\x9d\x64\x6c\x70\xf8\xb8\xe5\x8a\x2f\x40\xd2\x87\x9b\x1e\x8d\xf3\x60\x53\xda\xc5\xff\x4f\x33\x8f\xbb\x7a\x92\x16\x21\x58\x7e\x92\x4f\x48\x52\x30\xb0\x6e\x26\xc5\x1b\x74\x0b\xd2\x78\xd3\x18\x63\xb2\xda\x83\x7d\xa2\xf1\xfb\x71\x1a\xfe\x7d\xf5\x26\x79\x8c\x61\xe4\x78\x23\xc7\x20\xb8\xc7\xf7\x1e\x12\x67\xa3\x0d\x25\xf9\x7f\x0c\xd3\x04\x30\x9d\xcf\x7f\xca\x10\x74\xbc\xa7\xe0\xf2\x73\x28\x3f\xde\xe3\x2d\x1b\xe7\x5b\x86\xcf\x71\xa0\x6e\x3e\xe1\xb6\xd1\xe4\x54\x3b\xff\x56\x84\xfb\x96\xd5\x21\x01\x0a\xd7\x68\x79\xed\x36\x69\x0b\x8f\x4d\xd4\x46\x03\x72\x9b\xb6\xa1\xb9\x9f\x1f\x0e\xd6\xab\xe8\xe0\x91\x0b\x30\x56\x75\x33\x20\x20\xe0\x93\x7e\x5a\xf8\xe9\x4a\xc1\x49\xfa\x9a\x83\xe9\x7f\x83\xb4\xe0\x8c\x79\xab\x07\xc8\xe0\xae\x4c\x4e\xb7\x72\xbf\xe5\x06\xdd\x96\xa6\x7d\x99\x40\x39\x22\xbd\x9e\x34\xf5\xce\xdc\xaf\xfb\x29\x23\xe2\xba\x33\x59\x1e\x20\xfe\xb7\x07\xa5\x0a\x6e\xd3\x3f\x63\x6e\xcf\xc5\xe7\xea\x6d\xa5\xba\x80\xb5\x0c\x8b\x74\x06\xc8\x3d\x0f\xf9\x6b\xd0\x01\xc3\x14\x7b\x55\x56\x31\xa6\x55\xdd\x58\xc4\x71\x89\xdf\x1e\xf4\x77\x64\xfa\xf2\x5e\x0d\x72\x9d\xe6\x04\xdb\xb8\xba\xd7\xb6\x23\xbc\x20\xfb\xc1\xd9\x44\x57\x1d\x08\xf7\xe9\x7d\x72\x5b\x10\x2e\xf4\x1c\x5a\xe8\x29\xeb\x18\x39\x74\xb1\x5d\x97\x40\x2d\x3b\xc4\x08\xb8\x61\xe9\xec\xfa\x02\x0b\x01\xa2\xca\x86\xc0\xbe\xce\xed\xf8\x09\x0b\x54\x4f\xac\xf7\xa3\xce\x50\xd5\xf7\xa9\x38\x64\x70\x92\x49\x3f\x7b\x6e\x3b\x1a\x58\x4a\x02\x58\xa5\x13\x8f\x66\xce\xbf\x8c\x71\x0a\x0b\xd0\xe7\xdc\x07\xdb\x94\x28\xc8\xeb\xcf\xc6\x1a\x3a\xd4\xd4\xc9\xf0\x81\x66\x12\xaa\x2a\x9f\xd2\x87\xc0\xa0\x31\x8e\x49\x3e\x22\x7f\xe7\x0c\xe3\x19\xdf\xc2\xfa\x4d\xb7\x7f\xa3\xd6\xcd\xa0\x42\x80\x35\xfa\xe1\x34\x6d\x9f\xac\x7a\x2d\x23\x34\x6e\xa5\x26\x70\x53\x85\x22\x75\x09\x83\xee\x56\x0d\xe1\xe6\x1f\x8a\x7f\xb7\x16\xff\x6f\x61\x94\x9e\xf4\x62\x25\xcc\x84\x32\x90\x0b\xf1\x81\x4f\xe8\x15\xac\x59\xff\x9e\x58\x7f\x8f\xe9\x60\x4e\xdf\x18\x96\x5f\x06\xa0\xc2\xec\x68\x3f\x29\x94\x32\xd2\x30\x30\x04\x08\xf4\x9e\x1a\xaa\x67\x5c\x01\x86\x13\x1e\xdd\x76\xf8\x97\x02\xc9\x21\x71\x44\xc6\xb6\x56\x62\x7a\x51\x48\x76\xde\xbf\xef\x30\xd1\x9f\x65\x4c\x2e\xf9\xe2\xa3\x65\xc7\x72\xf3\x1e\xd8\xeb\x1a\x6e\x7a\xd3\x0f\x1a\xe0\x58\x19\x83\xcf\x01\x5c\x6c\x78\xec\x3a\x6e\x5d\x91\x76\xf0\xbc\x9f\x8f\x50\xa8\x0b\x90\x50\x69\xe5\x42\xcd\x94\x81\xc6\x24\x5a\x29\x01\x3b\xf8\x67\xcb\x31\xf9\x2e\x98\x8c\x70\xe4\x0f\x73\x97\x20\xae\x2d\x3e\xb9\x53\x16\x53\x67\xb0\x7a\x43\x1c\xf0\x7b\x9a\x65\x49\x0c\x61\x03\x22\x12\x1b\xa1\x64\x30\x6b\xf2\x6c\x40\xad\x98\x42\x45\xe0\x0e\xdf\x0c\x6f\x70\x42\x6a\x01\x2e\x3f\xec\x3e\xd3\xd6\x2f\x60\x77\xcf\x35\xac\x0b\x69\x3e\x5a\xd5\x3a\xbc\x09\x61\xc8\x5d\xd5\x02\x0c\xad\x7c\x6f\x32\x92\x06\x89\xb2\x0c\x6e\xbb\x23\xd1\xbd\x21\x32\xbf\xc0\x20\x7e\x06\xcf\x1f\x43\x99\xb8\x18\xcc\x3a\x06\x11\xdb\xc6\x08\x2e\x30\x46\xfc\xa2\x09\x71\xcb\x77\xe7\xfe\x0d\x31\x85\x01\xf0\x93\x4d\x58\xcf\xdf\x11\xca\xa5\xc9\x64\x48\x25\x74\xfd\x03\x66\x19\x85\x50\x82\xa0\x86\xb3\x83\x2c\xf4\xa0\x82\x50\xb5\xfd\x30\x48\xe0\xe0\x1b\xd2\x04\x1f\xc9\x1c\x84\xeb\x7a\xfd\x2c\xd2\x17\xe8\x66\xe0\xef\x30\x0c\xbf\xa4\x53\xc0\x74\x48\xaa\x24\x04\xf0\xf2\xea\xea\x10\xf5\x54\x78\x17\xdc\xa7\x38\x50\x93\x3a\x81\x54\xef\x0c\x74\x89\x89\xba\x87\x50\xc3\x1e\x3a\x0a\xa2\xff\x5b\x69\x5f\x2b\x57\x45\x6e\x18\x90\xce\x23\xe9\xde\x21\x26\x60\x06\xb1\xda\xc3\x03\xbe\x5a\x37\x81\x6f\x5a\x9d\xd3\xe8\xe5\x53\x06\x24\x43\xd5\x14\xfb\x10\x8e\x33\x43\xb5\x6e\x74\xdd\x29\xb9\x40\x21\x80\xda\x15\x1b\x94\x03\xe9\x52\x0a\xdc\x7a\x05\xb5\x94\x28\x85\x02\xc6\xca\x40\x9f\x95\x5b\xfc\x0b\xef\x35\xef\x00\x30\x9c\x84\x80\xf5\x56\x89\x13\x39\xfc\xac\x57\x6d\x3c\xca\xff\x28\x29\x04\x32\x0c\xf1\xbe\x3b\x19\xf2\xce\x32\x38\x2f\xcf\x78\x3f\x3c\x49\x99\xc7\x11\xd7\x6f\x98\x91\x78\x4e\xda\x3d\x12\x2d\x63\xba\x7a\xc8\xaf\x50\xb9\x70\x7d\x86\xbe\x1a\x75\xa7\x34\x16\x2e\x25\x8b\x43\x83\x41\x65\x8f\xa3\xba\x1c\x83\xbc\xc9\x35\x99\x01\xc1\x85\x10\x6d\x30\x24\xb5\x87\x5d\xd3\xa5\x86\xf8\xf6\x59\xc9\xa9\x47\x43\xfa\xf1\x19\x93\xe7\x7c\x29\x40\xa0\x90\x78\x02\x75\x8c\x07\x28\xa3\xb3\xb6\x88\x69\x3d\x07\x5c\x23\x62\x3a\xda\x71\x6e\x0c\x56\x92\xae\x81\x5d\x1f\x94\x3c\x5e\x92\xc6\x49\x86\xbc\xd7\x25\xc4\x03\xa6\xaf\x12\x00\x06\x3c\x40\x59\x90\x5b\x97\x4c\x8e\xe7\x4d\x9a\x07\x67\x7c\x0b\xe9\xe4\x1c\xeb\x90\xba\x30\x09\x94\x14\xa8\xd7\xd0\xe2\xed\xa4\xbb\x4e\x98\xb4\x93\x7c\x52\x03\x52\x1f\xc5\x9a\xa2\x5d\x7b\x2d\xf3\xcd\x91\x92\xbb\xa0\xb3\x9c\x52\x38\x99\x87\xb5\x00\x90\x76\x48\xf2\x55\xdf\x1f\x45\x57\x85\x04\x11\x6e\xb4\x6e\xe1\x80\x4e\xc5\x0b\x1c\xe7\x0a\x39\x55\xa8\x33\xe8\xeb\x02\xe3\x73\x95\x3c\x83\x3e\xf8\x54\xa4\x3b\xa1\x20\xdb\x90\x74\xcc\x89\x53\x39\x06\xc2\xdb\x7d\xe2\x33\xe3\xdb\x4c\xa4\xaf\x0f\x8a\x0e\xff\xc1\x37\xfd\x1c\xbd\xad\x4a\xaa\x57\xd2\x7d\x46\x0a\x5a\xba\x7b\xac\x2c\x85\xfe\x6b\x02\x13\x4c\xc6\x15\xe9\x5c\xde\xa1\xd1\x00\x73\x2f\x07\xad\xae\x01\xa9\x48\xa0\x4e\x0b\xa5\x92\x74\x0e\x1b\xb6\xb0\xe1\x4e\xfb\xa5\x14\x7d\xc8\x82\x69\x15\x38\x3a\x54\x5c\x60\x7a\x82\x12\x6e\x6b\x87\x04\x48\x11\xe2\x0e\x53\x4b\x7e\x08\xa4\xed\x51\x6c\x21\xcb\x0f\x3d\x0e\x0e\x3e\x14\xff\xb5\x52\x6b\xcd\xca\x3a\xc4\xef\x84\xe5\xaa\x87\xd2\x12\xb2\xd2\x46\x66\xc9\xd8\x6f\x3c\x98\x51\x8c\x0e\xc0\xc6\x6c\x7e\x0c\x54\x5c\x07\x03\x66\x02\x3c\xe0\x72\xf0\xf7\xf5\x80\x43\x2a\x7c\x63\xd2\xf3\xa3\xf6\x06\x2c\x20\xf9\x74\x62\x50\xe3\x69\x73\x00\x7a\x63\xd2\x48\x52\x9b\xdd\x94\x97\xf4\x2a\xac\x1d\x51\x99\xe6\x24\x1a\x3d\x12\x0a\x71\x0d\x5f\xa7\xbd\x37\x47\xd9\x9b\xa8\xef\xad\xa8\xdb\xf7\xde\x24\xfe\xf4\xbd\xd7\x9b\xb6\x16\xdf\x7b\xf0\xd7\xe3\x5b\xe5\x86\xfb\xb5\x16\x4e\xdd\x8c\x6f\xe9\x33\xfd\x5f\x97\x81\x97\xe8\x02\x66\x3f\xa5\xca\xe0\x71\x85\x6f\xfe\x79\xad\xdf\xa1\xc7\xb0\x85\x34\xf2\x17\xf1\x45\x3f\xeb\xe7\x3e\x9d\xf0\xfe\xb9\xee\xc4\xaa\xef\xc3\x2e\xc7\x07\x06\x5c\xba\xc8\x4f\x96\x30\xe0\x27\x9d\x1c\x5b\x7d\x48\x1c\xfd\x28\x53\xe9\xe3\x9a\xc4\xd4\x5e\x18\xbb\x5e\xcf\xfb\xc3\xdc\x94\x37\xd3\x56\xdf\x61\x33\xe8\x31\x18\x11\xf6\xc1\x71\x67\x3f\x04\x30\x49\x4e\x21\xd2\x74\xdf\x1e\x0f\xf7\xa8\xfe\xdb\x55\x79\x9f\x5d\x8e\x61\x9a\x53\xe8\x31\x4c\x7d\xeb\x55\xea\x3e\xef\xfa\xf7\xcb\x9b\xb7\x85\x51\xc6\x0e\xef\xca\x80\xdf\x7b\xad\x53\x57\x6d\x7f\x97\xff\x5d\x99\x2a\x05\x7e\x59\xe1\xbb\x6e\x4d\x91\x73\xf9\x23\xc0\xf5\xee\x3a\x01\xf0\x89\x69\x5d\xad\xbb\x33\x0a\xdf\x65\x97\x39\xfb\x9e\x7b\x02\xd2\xdb\x93\xbd\x1d\xac\xd7\xa3\x4a\xcb\x01\x73\x8a\x2d\xcc\xda\xd7\x55\x66\xed\x2b\xf3\x34\xdc\xe8\x9d\xd7\xb0\x30\x4a\xf4\xee\xc4\x54\x20\x2f\x7e\x96\xe8\x85\x26\x79\x0e\x35\x3b\x09\x5d\x85\x30\xac\x9f\xdd\xb1\x5e\x3f\xca\x16\x42\x2a\x01\x50\xb1\x3c\x60\x0c\x73\x8e\xda\xb7\xd2\xd9\x80\x7c\xfc\xd9\xd7\x0f\x85\xaa\x09\x73\x0e\xf5\x05\x8f\x51\xf2\x01\x64\xa7\xd7\x2e\x82\x49\xce\xf2\xed\xfa\x27\xdf\xea\x6d\xd7\x12\x36\xf5\x98\x38\x95\x60\x42\x34\xf7\x5d\x15\xf6\x2d\x15\xab\x37\x9a\xdf\xa2\x88\xed\x3b\x4f\x59\xfa\xa1\x6f\x24\x1e\xf9\x35\x06\xfd\xf7\x6d\x15\x96\xd4\xd0\xdf\x64\xf0\x4b\xaa\x61\xbd\x64\xa0\xef\x4f\xec\xc4\xf4\x23\x97\x86\x48\x60\x7b\x5b\x5d\xe0\x83\x5c\x00\xa6\x49\xbd\x15\x99\x7f\xa7\x42\xc7\x71\x03\x30\xb0\xe5\x1b\x1d\xea\x58\x06\x7e\x6f\x4c\x7a\x8a\x2c\x01\x27\x56\xe7\xf9\xdf\x9f\xf8\x84\x5e\x37\x87\xe0\xaf\x7b\x8d\x15\xfd\xf3\x7a\x61\x1a\xba\x11\xac\x32\x78\x03\xec\x52\xcc\xaf\x6a\x75\xe8\x33\xdb\x98\xe7\xe9\x4b\x21\x97\xf3\x5a\xe5\x4d\x2f\xfd\x99\x57\xb9\x34\xb0\x85\x30\x04\xe9\x93\xaf\xa2\x7c\x55\x03\x89\xcd\xd2\xab\x50\x8d\xe8\x55\xc2\x4b\xe5\xe5\xd2\x21\xae\x34\x81\x6e\xd0\x21\xaa\x9d\x2f\x84\x41\xbd\x0e\xa2\x13\xc9\xbc\x1d\xb3\xf2\x0d\x34\x3a\x2e\xd8\x5b\xef\xdc\x0a\x64\x7d\x51\x84\x21\xef\x2c\x34\xe3\xfe\x12\x3f\x04\xde\x75\xaf\x10\x5b\xa8\x2d\x44\x22\xf6\xd5\x5b\x36\xe8\x39\xe4\x2e\xd8\x90\xdb\xbb\x72\x1e\x51\x52\x0c\x88\x34\xc7\x92\x6d\x78\xbf\x7e\x9b\xee\x43\x3d\x03\xeb\x5b\xa0\xd5\x3c\xc1\xb0\x46\x8a\x29\x24\x1a\xba\xf3\x7d\x52\xed\x8c\x80\x96\xd4\x2e\xd2\x1a\x52\x0e\x2b\x3d\x3b\x5e\x29\x56\x48\xda\x22\x69\x2c\x80\x69\x53\x5a\xcf\x43\xe8\xd3\xef\xc4\xdd\xac\x07\xe1\x6d\xc6\xbd\xeb\x79\x42\x3a\x56\x0e\xf5\x4e\x8f\xab\x8a\xb4\xde\x91\x7a\x71\x89\x98\x7d\x41\x52\x31\x8c\xeb\x93\x62\xa9\x36\xda\xdb\x95\x62\x60\x6d\xae\xdf\x41\x7f\xd2\x61\x53\xef\x95\x31\x64\x1d\xe4\x60\x1f\xa2\x72\x86\x24\xa5\x60\x63\x29\xfd\x6b\x70\x0d\x69\x00\xd6\xd8\x17\xdc\x77\xf3\x3b\xb0\x07\x55\x31\xff\xc5\xdd\x72\xa8\xde\xc3\xc9\x3e\x2b\x5f\xef\xf2\x71\x52\x23\xfa\x1f\x8b\x9b\x8a\x11\x6a\x86\xa0\xb6\x17\x1b\xa8\x9a\xbd\xac\x3e\x5e\x43\x2a\xc2\xde\x6c\xbc\x5b\x27\x97\xf6\x70\x8f\xb3\x82\x9b\xc2\xa3\xb5\x0a\xa9\xcd\xbf\x20\xbc\xc3\x1d\x38\xad\x07\xb2\xb9\xa7\x45\x5d\x52\xe4\xb9\x68\xd9\x7b\x39\x25\xbb\x7f\x96\x57\x39\x10\xf5\x77\xc1\x07\x9f\x9e\xea\xb6\xf0\x98\xc0\xfb\x10\x70\x96\xe2\x9a\x3f\xcf\xee\x8f\x3f\x93\xb3\x27\x8f\xab\xcb\xe7\x34\xd2\xf4\x5f\xe8\x4e\xe8\x18\x33\x02\xcd\xd2\x95\x80\xcf\xbe\xce\x39\xc7\x25\x79\x62\x86\x03\x48\xa2\xf0\x48\x79\x08\x33\x7c\xf5\x63\x61\x1d\xc9\xff\xe5\x37\x27\x8b\xae\x7c\x53\x7e\xc9\xc6\x85\xba\x69\x98\x0f\x1b\x42\x29\x23\x47\x08\xe6\x82\x88\xb3\xbe\xe2\x4b\x0f\x8d\x5d\x8c\xeb\x37\xfb\x72\xd9\x18\x2c\x32\xa8\xae\x4c\x83\xe5\x2b\x5d\xfe\x29\x5f\xd6\xe5\x55\x34\xfc\x52\x0f\xe0\x0a\x95\x57\x98\xb0\x8b\x34\x72\x59\x27\xc8\xbb\x78\x97\x5c\x89\xaf\xa4\xae\xc7\x95\xfc\xeb\x3a\xbf\x9f\x69\xed\x6a\x13\xdf\xda\x55\x28\xaa\x34\x22\xac\xba\x9e\x18\x65\x30\x18\x9e\xd2\x56\xa1\x3b\x5f\xf7\x9d\x64\x63\xfd\x0e\xab\x8f\xf3\x96\xb1\xcb\x79\x37\xa5\x1d\x9c\xe4\x10\x42\xc2\x94\x9c\x5e\xb8\x14\xef\x0c\xde\xbb\x04\x05\xc1\xd6\xdd\xe9\x4e\xda\x83\x42\x94\xa2\x88\xd4\x7b\x3f\x1e\x51\xe9\x9f\xf7\x40\x7d\x85\xcf\x28\xf7\xfd\x89\x26\x34\x70\xdf\x27\x43\xdb\x6d\xf8\xbb\x0e\x05\x39\x31\xee\xb7\x1f\x4d\x98\xcf\xc8\x8d\xe4\x1c\xe3\x63\xa1\x64\x44\x50\x75\x4f\x11\x9a\x2f\x1b\x1b\xd9\xfd\xa3\x1e\xc2\x05\x36\xd7\xbd\x08\x4e\x29\xcc\xf5\x8f\x30\xea\xaf\x21\xf0\x60\xe8\x51\x08\x72\x88\x42\x54\xb0\xcd\xc2\x4f\xdc\x25\x2c\x74\x75\x05\x42\x39\x55\x38\xec\xd9\x2f\x10\x0c\x3b\x67\xff\x2a\xcf\xd0\xaa\xc0\xa0\xb6\xc8\xfc\x1f\x33\xed\xaa\xdc\xac\xfa\xba\xb5\x45\xbe\xbb\x9d\xff\x2d\x61\x85\x2b\x1f\x57\xac\x3b\xf6\xfe\xac\x5d\x0d\x23\x2e\x23\x44\xbb\x69\xfb\x1f\xbe\xe6\x57\x24\xf5\xc0\xef\x47\x02\x1b\x99\x29\xa3\xf6\x9e\x7c\xe2\x7f\xe9\xa6\x12\xad\x21\x5d\x5b\x3a\xe9\x63\x7f\x71\x06\x09\x65\x1c\x1f\xc9\x65\xbc\x75\xc8\xfb\x95\x24\xca\xf5\xcf\x84\xb6\x2d\x6c\x1c\x5e\x19\xa2\x3e\xc0\x85\x86\x39\x9e\xa7\x1a\x69\x03\xe3\xcc\x68\xda\xf9\x7f\x77\x9a\x1a\x09\x5e\xa7\x53\x52\xc3\x9f\x08\xca\x1a\x4f\xaa\x5f\xc0\x72\x60\xd3\x3b\x7d\x74\x59\x86\x23\xf1\x4c\xf5\x55\xc7\x4a\xc1\x93\x7a\x23\x4a\x90\x08\xc9\x5a\x3a\x91\x7e\xda\xf4\xc6\x56\x19\x91\xd7\x9d\xa3\xf9\xd3\xfa\xb4\x94\xc5\x60\x24\xe9\xdc\x31\xff\xe1\xff\xd9\x14\x17\x82\xce\x05\xe7\x04\x5d\xf1\x42\xda\x17\x59\x9c\x6d\x48\x81\xfe\xd4\x2d\xea\x4b\x1e\x45\xa7\x7b\xf3\x6a\xb5\xf5\x8a\x9b\x46\xb4\x86\x17\xde\x8a\x45\xa3\x3c\xb7\xfb\xbf\x42\x91\x22\x44\x1f\x4f\xb0\x1f\x59\xc6\x0a\x58\x63\xee\x1d\x25\xc1\xcd\x9e\x02\x0f\xb3\x4a\x41\xe8\x2c\x91\x2f\x67\x43\xd4\x07\xdb\xdb\xb3\x4c\x22\xe2\xcf\x37\x7e\xcc\x4f\xda\x64\x8e\xc7\x6f\x40\xd2\x24\x33\x0d\x4a\x50\x26\x99\xfd\x17\x59\x32\xbb\x30\x05\x4b\x79\xfb\x43\x9f\xec\x24\x9a\xe2\xb9\xcc\xd1\xf5\x35\xb4\xbe\x24\x93\x81\xd7\x92\x0f\x79\x06\x6b\x80\xf1\x7d\x48\x5a\x8c\xad\x4a\x34\x23\x5d\xda\xc0\x9d\x48\x42\x5f\x65\x86\x00\xaa\x84\x02\xe6\xf0\xdd\x3d\xb3\xf4\x55\x0d\x3c\x92\x7e\x8b\x55\xdb\x92\x67\x41\x55\xcd\xc8\x06\xa0\x17\x87\x0d\xf5\x54\xf1\x59\xfd\x45\x71\x8a\xf0\xb4\xc7\x00\x94\x1b\xaf\x8c\x66\x9e\x90\xcc\x6f\x8b\x10\x8b\xf2\x3c\x43\x12\x83\xda\xb2\x67\x2e\xcc\xaf\x39\xd1\x6d\x56\xf5\x90\xbb\x0b\xf9\xe9\x93\xf3\xe7\x15\xc3\xd0\xae\x89\x7e\xe2\x73\x94\xca\x45\xe5\x2c\x27\x08\x41\x92\x46\x33\xf8\xe4\x80\xc9\x10\xc9\xfb\x90\x65\x95\x67\x15\xe0\x3a\xd5\x30\xda\x7f\xbb\x50\x60\xe0\xa8\xb0\x20\x97\xd1\x11\x33\xab\x0d\xdd\x76\x43\xbb\x5f\x18\x96\x31\x7b\x4c\xd8\x6a\xb8\xfe\x5b\x7d\xfb\x8a\x0d\x5a\x19\x3a\xa4\xcb\x9f\x23\xe8\x61\xd7\x33\xb6\x4f\x3f\xad\x8d\xfa\x8f\x76\x45\xa5\x08\xbd\xa3\x55\x67\x41\x3a\xd4\x0f\x7b\x72\xf6\xfe\x5b\x22\x82\xc9\x6f\x1c\x6f\x63\x7a\x80\xe7\xe8\xf1\x01\x43\x4e\x03\xfd\x8c\x78\x53\x31\x77\x88\xac\xf4\x90\x1d\xc1\xb2\x0e\x14\x13\xe1\x80\x43\x21\xc8\x21\xa8\xa1\xce\xac\xa3\xe1\x87\x08\xd2\xbd\xfd\xa3\xc1\x61\xdd\xe4\x2e\xc3\x81\xd6\xd7\xa1\x55\x26\x12\xfc\x71\x98\x45\x6b\x3d\xd1\x43\xf3\xd2\x6a\x0e\xe9\x66\xdc\xd2\x07\xf1\xe4\x2d\xfe\xb3\x61\x3a\x9a\x8d\x2b\x72\xdc\xbd\xe4\x43\x42\x82\x8b\xe6\xa1\x1c\x6b\x23\xa0\xe8\x91\x9d\xae\x61\x4a\x30\xbd\x58\x51\xbb\xc0\x5a\x5a\x03\x0e\x1d\x82\x68\x39\x6a\x13\xef\x5f\x14\x1e\xc2\xde\x72\x2a\x47\x1b\x3c\x43\x96\xf0\x84\xa6\xfc\x49\x90\xf4\xed\xc1\x14\x9e\x25\x7c\x23\x75\xfd\x6a\x02\x92\x64\x5f\x30\x12\x61\x43\x91\xb2\xc6\xda\x67\x9a\xca\xff\x79\x39\x50\x4d\x12\xba\x1e\x2b\xe9\xee\xed\xf3\xe4\x34\x22\xa6\x43\xd8\x37\x69\xf7\x3e\x52\xa8\x83\x4d\x17\x4a\x3f\x7f\xb3\x9a\x7b\x64\xd6\x6a\xbb\xd9\x4b\xb6\x72\xb8\x3d\x60\xd8\xee\x69\xe5\xe9\xda\xcd\x0f\xd2\x85\x3e\xe8\xca\x6f\xdd\x8a\x93\xe3\x63\x9f\x46\x61\xf3\xd3\x14\x28\x6f\x77\x27\x81\xb4\x5b\x8d\x64\x43\x3d\x28\x69\x0b\xa4\x42\xef\xd4\xf6\xf8\xf6\x26\xd7\x70\x64\x74\x20\xcd\x9c\x5b\x56\x1a\x86\x34\x70\x2d\xd2\x4b\xa9\x7b\xb6\x34\xa5\xb8\xc8\x6a\x63\x07\x8a\x67\xc0\x81\x64\x95\x98\x88\x75\x10\xaa\x34\x43\x4e\x85\x0c\x0d\x49\xee\xa2\x9e\x4a\x77\x04\xda\x31\xd7\x4c\x4d\x90\xa6\x73\xad\xeb\x27\x4e\x2f\xc1\xc8\x56\xff\x32\x77\x2d\xf2\x0a\x6d\x95\x29\xfa\xad\x3e\x25\x60\x42\xa3\x28\xfb\xd2\x6d\x54\xa2\x13\x4e\x55\x35\x92\xc1\xde\x07\x37\x9c\xa2\x94\x28\x09\x69\x40\x10\x25\x11\xdb\xab\xd5\x01\xfd\x5c\xef\x50\x37\x97\xb2\x8f\x7d\x93\x34\x45\xec\x17\x2a\xc6\xef\x72\x77\x11\x20\xc5\x42\xbe\x2a\xd7\xbb\x4a\x0a\x65\x38\xca\x3f\x5a\x57\x2d\x9a\xbc\x16\x5d\x27\x9f\x1f\x57\x57\xae\x05\xc3\x12\x8a\x26\x5e\x4c\xfa\x39\x76\x45\x7a\x94\x86\xfa\xb1\x34\xcb\x61\xdd\x59\xbf\x0d\xb3\xfa\x3d\x36\xa0\xe5\x5e\x9a\xa8\x6a\x99\x3c\xec\xe6\xb4\x0d\xdd\x43\xb9\xa3\x34\xf7\x4a\x51\xda\x32\xc4\x4b\x7e\x59\xc3\x58\x9a\xc9\x6e\x02\xd4\x75\xe7\xf2\x38\xf7\x8f\xf4\x5e\xf2\x2c\x2a\xb0\xfc\xf1\x60\xd0\xa5\x90\x85\x8d\xee\x1e\xcc\x7e\x6c\xa1\xf0\x03\x61\x13\xd2\xda\x9a\x4b\x2d\x37\xa1\x50\x44\xc1\x04\x51\xa5\xe4\x8b\xe3\xc4\x0d\x30\xc9\x5e\x5f\x39\x16\xf6\x8e\x02\xe8\xc7\x51\xd5\x18\xfe\x25\x7e\x37\x5c\x76\x59\x3f\x36\x5d\x4a\x7e\x6c\x52\xe0\x69\xe9\x74\x11\x1d\xf4\x53\x78\xaf\x9c\xc9\x45\xd9\x94\xad\xf0\x00\xdb\x44\x99\x9e\x14\x75\x66\x4b\xe0\x52\xe4\x8d\x5a\x26\x4f\xda\x68\x34\xd5\x19\x90\x90\xe0\x97\xca\x0c\x59\xd0\xb2\xf4\x06\x52\xae\x9e\x7b\x0d\x10\x08\x66\x7f\x12\x81\x66\xce\x6c\xff\x9f\x4f\x13\xb5\x8d\x52\xef\xb6\xe4\x3f\xe1\xff\xd0\x4f\x16\x61\xd2\xb0\xc6\x31\x86\x28\x4c\xa1\x68\x3d\x84\x52\xfc\x02\x0e\x5a\x4c\x5b\x5f\xa0\x70\x46\xfe\xb8\x5d\x54\x82\x5b\x59\x8d\xe4\xaf\xbc\x01\xf1\x12\x0e\x17\xfe\xa9\x44\x24\x18\x41\x2d\x45\xea\x21\x4d\xfe\xb8\x47\x88\x08\x1f\x78\x55\x62\xcf\xf4\x5e\x59\x6a\x30\x79\x54\xce\x63\x1f\x4e\xde\xf7\x43\xd5\x97\xfe\x63\x1d\x9f\x26\x05\x95\xfc\x1f\xf5\x52\x62\xa7\x26\x3d\x8d\x1a\x59\xf2\x47\xa5\xdf\xf0\x01\x03\x8b\x26\xdf\x74\x5f\x50\xc9\x62\x84\xdf\x54\xee\x72\x2a\x5b\xde\xb9\x13\xf4\x89\x6f\x9e\x9d\x04\x91\xc3\xda\x65\x3e\x84\x03\x41\x2e\xcd\x65\x1d\x56\x25\x44\x4c\xe4\x40\xab\xeb\xbb\xac\x32\xc0\x3e\xdc\x9e\x97\x3b\xad\xe0\x00\xc7\xc7\x6b\x4b\x45\x6b\x23\x56\x7a\xe0\x56\x8b\x64\x74\x94\x9f\x9d\xbc\x61\xe4\x46\x50\x58\x06\xf4\xb6\x90\x6c\xb1\xc3\x51\x9c\x65\xe7\x68\xd9\x00\x95\x2d\x01\x3c\xe0\x6f\x40\xb7\xa7\x88\x1b\x71\x78\x96\x28\xff\x07\xc3\x57\x9e\x2c\xfa\x54\x47\xd1\x0f\x2c\x5d\x6b\xa5\x30\x6d\xc5\xf5\x5d\xf8\x5c\x91\x50\xcb\xad\x1e\x1c\x1f\x1e\xf9\xfb\x65\xbe\x04\xd5\x5b\xfe\x95\x6f\x89\x93\x65\xc8\x53\x3a\xb0\xae\x80\x02\x2a\xd6\x55\x56\xbe\x07\x10\xeb\x17\x43\x22\x49\x02\xed\x02\x4c\xa2\x02\x45\x75\x0d\x95\x97\x36\x96\xc7\xcd\xb3\x1f\x52\x57\x81\xf2\xcb\xff\x02\xf0\x65\xb4\xea\x48\x71\x98\x23\x6f\x1c\xb9\x1c\xd9\xab\x66\x2b\xd4\x71\x36\x04\xe5\xd2\xcf\x7f\x52\x8a\xd1\x46\x34\xf0\x05\xc8\x50\x00\xe1\x31\xd6\xb2\xe8\xfc\x7a\xfa\x79\x88\x11\xc2\xa1\x98\xf3\x61\xef\xb3\x22\xfa\x87\xe7\xea\xfb\xf7\x79\x84\x67\x9b\x01\x7c\x8b\x39\x04\x64\xe4\xc4\x6e\x40\xdf\x48\x3a\x95\x2c\x71\x58\xef\x97\xed\x3e\x84\x07\x02\xf4\x35\xca\xbe\x70\xc4\x1d\x1b\x5f\x39\x65\x92\x1c\xe9\x40\x8e\x83\x24\x64\x90\x1a\x7a\x49\x6f\x06\x59\x7a\xbb\xb6\xd9\xa5\x5f\xb3\x4f\xba\x8c\x0d\x4f\x3a\x13\xda\x2e\xb7\x74\x69\x36\x9d\x63\xbd\x4f\xee\xc8\xd4\x90\x43\xd5\xd2\x11\xd4\xf1\x23\xfd\xe3\xd5\x5f\xbf\xd2\x96\xb2\x5a\x2a\x22\x5e\xa8\x7d\x43\x9a\xb3\xc2\xf0\xc1\x5f\x0b\xc4\x26\x9b\xb4\x53\xe0\x0e\xee\x5b\x9e\x19\x5c\x0d\x57\x74\x39\x39\xc0\x82\x9e\xaa\x57\x29\xb5\x6d\x12\xec\xaa\xcd\x9e\x49\x3f\x61\xb3\xaa\xb9\xb0\x8e\xb1\x77\x8c\xf5\xb4\x81\xae\x73\x63\x75\xa6\x78\xec\x15\xc9\xc7\x34\x34\xb1\x0f\x09\x63\x4b\xca\xd8\x48\x38\x66\xab\xf3\xbd\x33\x75\x13\x2d\xc9\xf6\xdf\x4f\x8e\xc6\xdf\x5d\xab\x29\x5e\xc8\xed\xf6\x43\xf1\x1b\xb3\x2f\x37\x12\x91\xeb\xc2\xf7\x0f\xba\x33\xbf\xd9\x85\xea\x33\x10\x14\xa1\x51\x87\xa2\x32\x4d\xb2\xda\x6d\x3c\x25\x10\xf3\xbd\xa9\x17\xc3\xf3\xec\xbf\x51\xb3\xd5\xf5\x95\x93\x09\x7b\xed\x74\x5e\xc4\xa7\xa9\x9c\xb6\xd7\xda\x18\x9f\xdb\xab\x33\x3a\x95\x92\xb1\x87\x71\xd6\xfe\x57\x17\x74\x44\xf6\xf2\x65\xfc\x77\x2f\x6f\x4a\xc4\x78\x25\xbb\xff\x78\xa0\x7b\xd9\xfc\xed\x46\xfb\xa4\x00\xe9\x5e\x34\x7e\x71\x0d\x99\x4a\x30\xb3\xa7\xba\x17\x4f\x70\x00\x42\xda\xf8\x7b\x27\x62\xb7\xd2\x00\x83\xda\x3b\x06\x4c\xfa\x91\xf9\x16\x51\xc4\x90\xe7\x80\xbf\x65\xdd\x6a\xcd\x90\xa6\x86\x76\x75\x34\xf6\xfc\xa7\x8b\xca\x88\x38\xf0\x5f\x1c\x3b\x6a\x41\xa2\x2b\xfb\x8f\x06\xba\xa7\x97\xcf\x4c\xed\xfc\x22\x91\x01\xff\xd1\x3f\x76\xa6\xe3\x40\x78\x66\xe3\x5e\xcc\x6a\xb0\x92\x52\x37\x53\x68\x02\x5b\xe5\x3f\xa6\xd0\xa4\x89\x0a\xc2\xa0\xe2\x19\x86\x64\x5d\x0d\xa9\x9a\x4b\xd4\x4f\xc8\xd4\x50\xc8\xc1\xde\x9e\x77\x4c\xb3\x41\xb4\x46\xbb\x93\x8c\x0e\x77\x9d\x3e\x1a\xb3\x05\xcc\x57\xed\x84\x63\x92\x16\xc7\xed\xcc\x2b\x6a\xe1\x8c\x74\xbf\xd8\x90\x90\xa9\x0e\xf1\x86\x1c\x4c\x8a\xcb\x30\x85\x7b\xab\xed\x95\xb8\x02\xd2\x42\xfe\x1e\x6e\x54\x98\x85\xbb\xf8\xc9\x32\xb4\x36\xaa\xbc\xe0\x91\x7c\x21\xe7\x86\x2d\xb4\x10\x00\x42\xab\x9d\x52\x38\xfa\xb7\x4c\x4e\x37\xbc\x69\xa2\x4a\xb9\xe7\xca\x5f\x0d\xf4\xa4\x48\x4c\xdd\xaf\xf8\x6f\x24\xe5\x1a\xec\x57\xbe\xd3\x0e\x62\x43\x1e\x6a\x12\xd2\x39\x66\x6e\x91\x67\x26\xa1\x39\x92\x72\x45\x9d\xc0\x29\x8a\xcb\x9a\x12\xde\x06\x62\x26\x8d\x6f\x95\xae\xe5\x5b\xf9\xa4\x59\xd2\x14\x98\x69\xf2\x6d\x4a\xd4\xaa\x6e\x28\x77\x12\xa8\x12\xde\xca\xa6\x35\x9a\xec\x34\x30\xb4\xd0\xeb\x89\x2c\x83\xad\xc0\x90\xfd\x4f\xdf\x83\x2d\x25\xef\xbb\x6d\x59\xbd\xaa\x2d\x5f\xa1\x37\x13\x52\x8c\x86\xa8\x27\x64\xdd\x18\x65\xb9\x00\xfe\x4b\xa7\xb3\x65\x0c\x12\x78\xb7\xb2\xab\x8f\x52\xd0\xa6\x9d\xec\xb8\x6d\x9a\x33\xdf\xa4\xc6\xb0\x41\x5c\x8b\x2b\x56\xc6\xb1\xb6\xb0\xe2\x32\xf0\xe0\x95\x94\xd0\x70\xd8\xf2\x13\x55\x1b\x77\x7c\x86\xc2\x4c\x8e\x8e\xf5\x96\xbb\x46\x8e\x2a\x4b\x7b\xe3\x18\x8a\xdf\xa2\xa7\xbd\xe5\x98\x3e\xdf\xfa\xfe\x4a\xc6\xd8\x6c\xc4\xc3\x29\xdf\x6d\x3c\x22\xe2\xb4\x45\xb6\x2c\xf4\x6f\xac\xca\x3c\x4e\xe1\xa2\x09\x9a\x6d\x7c\xba\xb8\x82\xf4\x69\x9e\x5d\x29\x64\x7c\x32\x8b\x79\x1b\x11\xb8\xf1\x1f\x3f\x7a\x5a\xf5\x46\xd8\x34\x29\xe6\x70\x5c\x42\xfc\xc6\x7a\x09\x64\x94\x41\xcb\xa6\x66\x01\x77\xb3\x8a\xb5\xe9\xb1\xc6\xd6\x3f\x0d\x9f\x91\x86\x9e\xdb\x98\xee\x95\x1f\xce\x88\x77\xca\x0f\x90\xac\x47\x33\x52\xb6\xe4\x73\xdd\xc3\x40\xc9\x15\x8d\x89\x0c\xf0\xd1\xdb\xb0\xa0\xeb\x2b\x19\x9e\x25\xe1\x72\x5d\x1a\x34\x39\x4c\xda\xd4\xba\x10\xa1\xd2\x82\x89\x65\xeb\xf0\xbf\xba\xee\xcd\x15\x93\xa6\x1b\x4c\xb6\x46\x49\xd6\xc4\x8b\x05\x3f\xc1\x96\xf6\x90\xb7\xb1\xce\xd0\x57\x50\xfb\xb8\xe1\x56\x0a\xe1\x9a\x7f\x8f\xd6\x9a\xae\x09\xea\xb7\x3a\x40\x0d\xf1\x1c\x10\xf0\x84\xe8\x5d\x08\xb1\x9b\x8b\x97\x64\x3d\x75\xa9\xde\x64\x0e\x55\xa5\x6f\x23\x35\x9b\x36\xf0\x43\x87\x6d\x4a\xc8\xdf\x24\xf2\xb6\xb7\xc4\xfe\xbf\xd5\x34\x76\x76\x65\x03\xba\xec\xcd\x19\x80\xe5\xb3\xeb\xe0\x3c\x7b\x30\xde\xbd\xba\x75\xa1\x9b\xee\xd6\x5a\x25\xa6\x63\x77\x9a\xdd\xc5\x2d\xf5\x1f\xf8\x37\xce\x8d\x69\x2f\x1b\x06\x54\xbc\x80\xdf\x97\x9d\x9c\xd2\xea\xc8\x67\xfa\x79\x09\x93\x8e\x3c\x7a\x04\x8b\xb0\x54\xd6\xcc\x88\xb7\x3f\x93\x50\xa8\xee\x20\x9d\x99\xeb\x68\x63\xb8\x7e\x86\x90\x25\xb9\x5f\x01\xd8\xf5\x47\xd9\x68\x9e\xb6\xde\x87\xff\xf8\xf5\x5e\xc2\x83\x1e\x32\x36\x6f\x7f\xed\x56\xab\xd4\x3b\xcb\x00\x02\xd7\xa3\xe4\x83\xd6\x6a\x4d\x3b\x14\x61\xaf\xff\xa4\x64\x23\x25\x9c\xea\xc2\xe3\x8e\x34\x85\x04\x5e\xb8\x54\x40\xa0\x5a\xc3\xbd\x77\x89\xd7\x6c\x4a\x0b\x5e\xad\x33\x92\x39\x52\x58\x6b\x59\xf8\xcf\xb9\xd1\xd1\xdf\x90\xf6\x7f\x5c\xa4\x79\x20\x32\xbc\x4a\xca\xc6\x86\xd3\x03\x4f\xdd\x7b\x8c\x48\xba\xf2\x12\xcc\x7e\x29\xcf\x5c\xaa\x4d\x56\x8d\xc8\xdd\xf1\x99\xff\xda\x25\x41\xb3\x4f\x0a\x45\x5a\x77\xf8\x56\x2e\xad\x55\x2a\xb7\x5f\x20\xa4\x51\xff\xa3\xf4\x8c\x5e\x03\x6b\x1c\x7d\x08\x88\x92\xff\xda\x79\x73\xad\x12\x49\xfc\x47\x99\x22\x4c\x6c\x58\xc2\xa9\x2b\x78\xa2\x5e\x4a\x52\x25\x3f\xa4\x80\x92\xb3\xd7\x10\x6b\x9e\xa8\xd4\x92\x9d\xdb\x40\x94\x79\x11\x91\xe5\x06\x79\x19\x7e\x2b\x86\x46\xfd\x5a\xeb\x5b\xac\x92\x8a\x79\x15\x16\x50\x68\x4c\x01\xbd\x94\xaa\x0c\x9d\x89\x56\xf6\x1d\x56\xcf\x47\x67\xea\xd4\x9a\x8e\x42\x89\x55\x43\x1a\x7b\xc1\x61\xb3\x2b\x15\x21\x1d\xed\xc5\x20\x48\x77\xde\x74\x59\x18\x75\x6f\x81\x95\xba\x0a\xe8\x66\xca\x8e\xbd\x26\xda\x79\xbc\xc8\x1a\xc7\x00\x53\x8d\x0e\x24\x61\x78\x8b\xed\x42\x78\x63\x53\x88\xce\xd0\xa2\x13\x35\xe4\xad\xdd\x1e\x48\x61\x25\xf2\x2e\x9b\xc3\x89\x07\x1f\xab\x74\x69\xc6\x78\x2b\x91\x5b\x26\xd1\x1b\x4f\x09\xe1\x9e\x83\x57\xa8\xcb\x3b\x9d\xec\x6a\x2e\x37\x9b\xcd\xe5\x0e\x69\xb8\xe5\x3e\xe7\xbd\x08\x51\x1b\xe3\x6e\x97\xd2\x93\x97\x3b\x04\x3d\xac\x6f\x14\xd2\x19\xf7\xb2\xfe\x24\x69\x38\x19\xba\xdc\x63\xcf\x65\x87\xe6\x8c\x74\x61\xee\x18\x24\x2f\x8d\x51\x10\x2b\x45\x67\x5f\x5a\x6c\x54\x42\x66\xc4\x23\x65\x0e\x42\x48\xd6\x65\x64\xbc\x4c\xd7\x57\x07\x22\xa1\x67\x91\xe2\xa0\x95\xa1\x2e\x53\xbf\xf7\xc0\x92\xb2\x23\x95\x13\xc1\x0b\xd2\x42\x98\xd1\xba\xd4\x48\x8f\x36\xe4\xfd\x9d\xa5\x62\xba\x83\x80\xea\x31\x27\xa5\x6d\xea\xe1\x1f\x28\x4a\xee\xe9\x73\xb4\x4b\x85\x90\x8c\x22\x07\x0b\x94\x07\x43\x44\x46\xb9\x39\x4b\x9d\xd7\x18\x54\x2d\x95\x44\x9f\xc5\x06\x04\x07\xcb\x68\xca\x0d\x72\xc2\xdf\x65\x65\xd6\x8e\x7a\x54\x62\x81\x36\x61\xcb\x9e\x3e\xbe\xec\x59\x16\x71\xcb\x4a\x2f\xf2\x05\xbe\x9b\x7a\x7a\x6b\x58\x30\x59\x65\xf1\x0e\xf5\x1d\xe4\x40\xfb\x53\xf3\x89\x40\xdf\x05\x55\x19\xc5\x6f\x4a\x8b\x79\x69\x83\x6e\xa3\xac\xbe\xa8\x2d\x8e\x8b\xa7\xd1\x2d\xe5\x50\x3d\x09\x62\x9f\xba\x53\x06\x8b\x34\x69\xd6\x10\xa7\x09\xc9\x7c\xab\xd9\xa8\xe1\xc3\xd9\xef\x85\x7d\x36\x1b\x4b\x85\xa4\x8e\xa4\xaf\x16\x17\xe8\xf0\xca\x7c\xc9\xf1\xcb\xa1\x12\xed\x33\xe9\x50\x9c\x91\x16\x4e\x8e\xd7\x44\xf7\x20\x2b\x95\x6a\xc9\x99\x9c\x24\x03\x13\x35\x69\xd4\x00\x2c\x99\x4a\x98\x56\xb6\x41\x22\x35\xef\xf4\xbc\xe9\x46\xb3\xa4\xfb\xb8\x59\x32\xfa\xb0\x24\xcc\x2e\xa9\xe7\xbf\xa4\xfe\x62\xa0\x0d\x3f\x09\x8e\x2a\xe1\x36\x60\xea\xca\x20\x65\xc7\xc1\x2e\x49\x75\x88\xd0\x34\x29\xca\x6c\x87\x56\xe9\x9e\x80\xe8\xfb\x26\x48\x0f\x6f\xa6\x97\x14\x52\x3c\xc9\x35\x78\x04\x2b\x0b\xb9\x57\xfd\xdd\x5d\x31\xee\xef\x5e\x43\x5b\xe6\x2b\xf7\xee\xbf\x10\xe8\xfe\xab\xf6\xd9\xb2\xf2\x30\xe8\xed\xdc\x9f\x35\xd0\x3e\x68\xfd\xcb\x6f\x29\xd8\xa0\x83\x29\xe0\x2f\xf2\x5f\x6e\x2e\xe8\xf0\x17\xea\xeb\x7f\xa9\xc9\x19\xca\x5a\x6d\x3a\xfa\xa1\xf9\xe6\x8c\xfa\x5f\xf7\x4e\xfb\x4b\x9b\x84\x65\x5c\x08\xfa\xcf\x2a\x20\xfc\x20\x8c\xbd\xf1\xef\x72\x85\xba\x0c\x66\xec\x38\xc7\x50\xaa\x68\x85\xe8\xac\x9c\x23\xee\xbe\xfd\xc0\xe6\x17\x58\x42\x6a\xa7\x6c\xcd\x7f\x4d\xd9\xd8\xf5\x2b\xf6\x9c\x43\xee\xbe\xcc\x5e\xd3\x97\xa7\xe7\x22\x15\x3d\xab\xf9\xfe\x84\x24\x8c\x7d\x30\x5e\xae\x57\xe8\xad\x60\x3e\x26\x74\x62\x9e\xae\xa4\x71\x67\x8f\x93\xa0\x94\x4c\xc8\x59\xbc\xe5\x9a\x63\x86\x7b\xae\x2f\xca\x70\x60\xfa\xbc\x53\xdb\x6c\x09\xb5\xf5\x4e\x28\x55\xb4\xd9\xd5\xc9\xb8\x2e\x3e\x8b\xb9\x9e\x21\x09\xa3\xd4\x3b\x64\xfe\x94\x45\x80\xf2\x23\x95\x59\xca\x73\xdd\x3f\xf7\x76\x20\x81\x87\x4b\xf9\xa3\x8b\x92\xbc\xec\x8c\xac\xa5\xa6\x17\x61\xae\xeb\xff\x27\x30\x53\xff\x11\x98\x41\x0d\x2c\x06\x0d\x96\x24\xf9\x4d\x48\x20\xcd\x58\xb8\x6c\x31\x54\x3b\xd7\x45\x17\x13\x1a\x16\x73\xb5\x0f\xd4\x75\x47\xea\xd4\x65\xa8\x0c\x3f\xe3\xa2\x26\x89\x25\xcc\xf6\x62\xd9\xaf\x0c\xe5\x1d\xcc\xab\x84\x39\xd7\x8c\xd9\x14\xde\x3e\xa6\xfb\xcf\x7b\xa2\xd6\x8c\x02\x6a\xb3\x57\x32\x44\xbb\x77\x9d\x3c\xe3\xd0\x16\x16\x16\xfe\x53\x51\x93\xf0\x78\x25\xb2\xeb\x5c\xc8\x5a\xc1\x7e\x1b\xe0\x5f\xec\xf9\x41\xc2\xc2\x3b\x58\xb3\x67\xb4\x6a\x6f\x0c\x42\x9e\x43\x50\x20\x6d\xe0\xee\x57\x02\x45\xdd\x90\xb7\x41\xfa\x27\xbd\x18\xfc\x9e\x41\x04\xb5\x4a\xee\x26\x54\x6b\x9a\x0d\x05\xd3\x7f\x21\x74\xe3\xbf\x1b\xdd\x1d\x8d\x57\x67\x5a\x85\x9d\x21\x71\x23\x2f\x33\x88\xf7\xb3\xf8\x47\xe8\xe6\x52\x0e\x9b\x0b\xe0\x64\x81\x22\x5e\x37\x30\x1f\x44\x8e\x4c\x64\x20\x48\xf3\x12\xea\xb8\xe5\x8a\x96\xc4\xb0\xae\xba\xec\x3a\x1c\x34\x65\x63\xbb\x3d\x49\xf6\x00\xa2\xce\x67\xd5\x61\xca\xa0\xcb\xa6\x8d\x8a\x95\x12\x94\xc9\x0f\xfd\xc3\x6a\xd2\x95\x19\x9a\x73\x9e\x7e\xa9\x70\xf6\x5a\x8d\x15\xe1\x5b\xc8\xe8\xe4\xf0\x87\xb6\x85\xac\x48\x27\x54\x75\xd8\x9f\x81\x88\xce\x2e\xb1\x43\x7b\x23\xe2\x11\xb9\x26\x9f\x64\x71\xd8\xa5\x44\x6b\xa2\xbc\x68\xc0\x78\x6e\xa9\x75\x39\x1c\x49\x43\xb9\x2b\x64\x4b\x21\x9b\x83\x97\xfc\x4d\x14\x02\x39\x8b\xce\xb1\x4b\xa4\x7e\x46\x87\x98\x97\xbb\x85\x68\x12\x26\x77\xd4\x46\xd9\x80\x21\x04\xa9\xd0\x23\x3b\xa5\xdb\xb3\x4a\xd6\x10\x48\xda\x3f\x25\x1e\x9a\xf5\xd7\x78\xf6\x12\x2a\x3f\x22\xa6\x1a\x58\xc3\xa3\x75\xf6\x71\x8c\xcb\x7f\xdc\x5f\xff\xd2\x9e\x51\x31\x3d\xc3\x00\xd8\x80\xb2\xc2\x9f\x77\x93\xa0\x92\x21\xaf\x88\x9f\x37\xf8\xb6\x14\xfa\xb8\x83\xa6\x6c\x88\x63\xf7\x27\x66\x79\xaa\x34\x64\xee\x4c\x56\x36\x80\x94\xb5\x3d\x1e\x2b\x15\x9d\x29\x15\xf2\xcb\xa1\x9b\x93\x6d\xa0\xe2\xb5\xe2\xd3\x13\x2c\xbc\x99\xb7\x3a\x97\xab\x9c\xc3\x47\x35\x14\x48\xe5\x50\x90\x06\x48\xd5\xe7\x93\x69\xd6\x56\x4c\x5d\x37\x47\xd7\xd3\xca\x97\x13\x52\xcf\xe6\x99\xe2\x44\xa7\x9c\xe7\x00\x67\x51\x7a\x9e\x98\x0e\x7d\xf2\x7c\x25\xd2\xf6\x01\x79\xb6\xf2\x78\x48\x3f\x07\x5a\x3b\xba\x04\x70\xa6\xb8\x12\x2e\x7d\x54\x76\x69\xb1\xc6\xf3\xbf\xb3\x14\x7e\x72\x5a\x19\x27\x74\xfd\x1d\xde\x6e\xa4\x4a\x7d\x05\x22\x8d\x0d\x38\x44\x6d\x42\x70\x06\x72\x82\x14\xe3\x69\xd2\xea\xa9\x2d\xc4\x78\xea\xc4\x19\x1b\x20\x74\xe7\x79\xe3\xe0\x8f\xb1\x71\x22\xe2\x59\xad\xfe\x65\xb9\x4a\x38\x1a\x30\xd1\x14\x1a\x1a\x3a\x6f\xd7\x83\x73\x6d\x9d\x81\x56\x00\x8e\x55\xb6\xd8\x67\xee\xe7\x9c\xb9\x3d\x18\xbd\x7c\x28\x15\x02\x7d\xd2\xd5\xe1\xe4\xc8\x13\x74\x86\x99\xc7\x62\x95\xf4\x5c\xef\xcd\x69\x74\x48\x78\x57\x27\xd0\x20\xf7\x5a\xbb\xb2\xde\x13\x3a\x97\x81\x38\xd6\x7a\xfe\xe5\x35\xc1\x88\xfc\x59\x5e\x6c\xd8\x9e\x85\x5a\xeb\x56\x32\x9e\x60\xe0\x99\xa5\x85\x54\x20\x24\xaf\x20\xc1\xb3\xac\x47\xba\x98\xfa\x01\x6d\x9e\x12\xfb\x6b\xd6\xc0\x00\xe3\xe7\x90\x79\xbf\x2f\x81\xd0\x20\x2a\xea\xa1\xe1\x70\xf1\x4e\xbb\x86\xdc\x25\xfd\x1f\xfb\x5c\x35\xaa\x85\xdb\xad\x6e\x4f\xbe\xa9\x6e\x82\xf9\x8c\x12\x80\xaf\x20\x45\x1b\x3c\x23\x91\x97\x87\x26\x93\x9b\x34\x8d\x3d\x9e\xee\x44\xc0\xcd\xba\xda\x9c\x4b\xfd\xf8\x65\x22\x6d\x6a\x27\x58\x63\x33\xf5\x30\x9f\x79\x9a\xfa\xf6\xa9\x49\x5d\x48\x9f\x8d\x0d\x3f\x43\xee\x28\x7d\xba\xde\x52\xba\xf9\xce\xa5\x9b\x29\x3c\x4f\xe7\xc2\x39\x08\x0a\xcb\x13\xb3\x4d\xdc\xcf\x7a\xc0\xac\x01\x92\xb8\x07\xd0\x06\xea\xca\x43\x76\xc6\x87\xf4\xb3\x52\x28\x06\xed\xac\xb5\x40\x56\x0e\xe5\x1f\x48\x1f\x9f\x44\x03\x8f\xb1\xd7\x3b\x04\x85\xfa\x47\x60\xdf\x00\x8d\x48\x9e\x98\x37\xe2\xd1\x56\x09\x34\x3f\xe1\x44\xa8\x73\xae\x6b\x4c\x52\x40\x74\x28\x44\xb3\x0c\x6e\x01\x16\x96\x39\x31\xf0\xf3\x4c\xf4\xe2\x42\x29\x76\x1f\x14\x43\xa2\x64\x88\xe9\x89\x24\x1c\x6e\x95\xe1\xc5\xc5\x7b\x35\xd9\x90\x1b\x57\xfc\xb8\xe3\x5d\x7d\xdc\xed\x5e\xe8\xe5\xfa\xb8\xdd\xb8\xb2\x33\x2c\x01\xce\xdf\x64\xed\xa3\x7d\x1a\x83\xae\x8f\x56\x39\x58\x7c\xf4\x5b\xe7\xfa\x18\x52\x3c\xf2\x9c\x8b\x99\x6a\xf0\x58\x5a\xfb\x16\x13\x77\xb2\x8e\x17\xdb\x5b\x87\x52\x44\xca\xc8\xed\xed\xa7\xca\x7d\xb5\x7f\xbc\x1c\x51\x3d\x5a\x96\x52\x92\x12\xf5\x3d\x51\xd3\xfb\xb4\xae\x93\x54\x76\x21\x0f\x5a\x3e\x64\x27\xff\x68\xdd\x8c\xf9\x51\x6f\xd9\x8d\x3f\xaa\x44\x42\x1f\x10\x0b\xbf\xb8\x4a\x2a\x2b\x0f\x18\x8b\xf8\x74\x29\x50\x11\x8f\xfd\x21\x05\x9f\x07\x33\x28\x1f\x21\x1f\xf1\x50\x00\xfa\xb1\x4a\xcd\x0f\x92\x4b\x3c\x0e\x34\x83\xb5\xf5\x8a\xf0\x07\xaf\x6f\x4d\x5b\xec\x99\xc4\x80\x7b\xb8\x3d\x1c\xab\xf3\x07\xd4\x8e\xf9\xde\x3e\xca\x4f\x15\xeb\xe1\x36\xb0\x6f\xa1\xdf\x5a\xf0\x4f\x08\x35\x27\xf7\x08\x62\x07\x3a\xf2\xb2\x36\x7a\xe0\xcd\xf1\x53\xa6\x17\x15\xaa\xec\xab\x19\xd5\xed\x7d\xa0\x63\xbb\x87\xca\x12\x3b\x2e\x8f\x14\x8d\xa7\x21\xee\xd8\x38\xf7\xf3\xf0\x20\x6a\x26\xda\xa3\x87\x6c\x58\xc3\xda\x07\x1a\x70\xaf\xcd\x1f\xf1\xb5\x3e\x52\xf8\x4a\x50\x6a\x89\xca\x4d\xc3\x2d\x99\xa6\x61\xf0\x50\x41\xfe\xac\x65\xf4\x8b\xc4\xb0\xc9\xbb\x3d\xc8\x93\x58\x29\xa5\x84\xe9\xef\xd1\x1e\x1d\x97\xc6\xf4\xc7\xe4\xcc\xfc\x7f\xb7\xff\x9e\xfc\x4f\x94\x35\xef\x55\x19\xf1\x36\xb8\xa6\x3c\xd2\xfe\x8c\xf4\x41\xaf\x84\x24\x9a\xa4\x7c\xce\x10\x74\xce\xc1\xaf\xce\x70\x01\xa0\x38\x13\x2a\xa8\xae\xb5\xc4\xe7\x6c\x20\x04\x66\xf3\xda\xc5\x93\x30\xf6\x1a\x18\x2f\x89\x80\x41\x2e\xf4\x04\xf3\xf8\x3b\x32\xfd\x95\x0e\x65\x83\x6a\x9e\xef\x97\x45\x85\x88\x91\x4b\x82\x02\x0f\xe1\xa8\xab\xf4\xeb\xe9\x5b\x6e\xaa\x29\x2d\xb3\x92\x8c\x27\xbb\xef\xd2\x3b\xf2\x6b\x9a\xee\x83\x92\x46\x37\x1b\x63\xc8\x28\xcd\x12\x3f\xda\x11\x61\xe7\x46\x7b\xd4\x48\x93\x67\xe0\xeb\x23\x9c\xee\xb8\x8c\xe9\xb6\x81\xa5\x04\x99\xe4\x09\x03\x90\x4f\xe9\xab\x4d\x8a\xc5\x4f\xf7\x10\xc2\x4b\xf1\xfb\x20\xaa\x44\x25\x1d\xeb\xe7\x80\xe4\xed\x97\x13\x92\x03\x93\x58\xd3\x53\xcb\xff\xa3\x0e\x4d\xd3\xc7\x02\xd0\xf7\xcc\x92\x5c\x9d\x1a\x4d\x49\x1c\x5b\x0f\xc2\x2f\xa4\x4a\x14\x7d\xaa\xa7\x02\x53\x86\xb4\xa6\x69\x64\x31\xd5\x26\xa5\x26\x1f\x74\x4d\x75\xcb\x21\xcb\xb4\xf6\x92\x35\x8b\xa1\xc1\x5f\x53\x00\xed\x34\x34\x9a\x29\x01\x25\x45\x6f\x27\x04\x92\x7a\xdc\x64\xb2\x1e\x1e\x85\x76\x4a\x3d\x27\xf2\x4a\xd1\x60\xe9\xed\x9a\x22\xc1\xd6\x40\x50\x2c\x09\x5d\x62\xc7\x1d\x7f\xa5\x70\x6a\x0b\x89\x29\xed\x13\xcc\xb6\xb8\x37\x99\x03\x0e\xa1\x55\x10\x48\xff\x4d\x9b\x04\xf7\x11\x3d\x67\x20\x16\x06\xb9\xfa\xe9\xf9\x15\x52\x46\xaf\xd0\x61\x31\x48\xf6\xca\x94\x7f\x89\x34\x93\xcf\xb5\x65\xb6\xef\x93\x93\xed\x36\x21\xed\x2f\x0f\x79\x57\x66\x93\xc9\xe9\x84\xcc\x09\xae\xd4\x68\xda\x00\xa2\xdf\x45\x82\x4d\x11\x92\x31\x74\xb9\x34\x0f\xe5\x9a\xf6\x50\xa9\xca\xdb\x39\x4b\x0b\x49\x12\x00\x10\x79\x0a\x51\x27\xf7\xb0\xd5\x76\x12\xa4\x5a\xbf\x3a\xde\xca\xec\x33\x74\xae\xd9\xda\x06\x75\xdb\xca\xce\x0e\x84\xa6\xd3\x2e\xe5\x2a\x43\x63\xa0\xb9\x7e\x78\x7d\x8b\x0e\x5f\x62\x24\x34\x85\x8a\xd4\x2c\x09\x69\x57\x7b\xd2\xed\x7d\x84\x5e\xfa\x24\x3b\x59\x2b\xfd\xa1\xe5\x31\x02\x0e\x06\x43\xe6\x0a\x84\x07\xfe\x12\x4f\x73\xba\x28\xac\xc4\x0f\x13\x39\x2b\x8c\x1b\x4c\xd1\x27\xa4\x32\x4e\xa4\xac\x4d\x50\xaf\x14\xcf\x74\x42\xcb\xa5\x2f\x9c\xa6\xd1\x56\x78\x57\x93\x5b\xc6\x20\xc9\x5e\x3c\x69\x2b\x1b\x9a\x98\x1f\x04\xc4\x07\x93\x46\xd1\x95\xc7\xcf\xa1\x00\xf2\x78\x87\x81\xed\x78\x37\x8a\x3b\x49\x6c\x6a\x24\x3f\xbc\xcf\x01\xf5\x99\xc6\xf1\x9e\xa2\x72\x1f\x25\x98\x36\xb6\x8f\x3e\x4a\x43\x3d\x4d\x16\x92\x4d\x9b\x34\x99\xec\x28\xab\xd4\x9b\xac\xb1\x9c\x25\x07\x37\xa2\xbb\xe0\xa5\x8d\x1a\x35\x79\x36\x36\x58\x2e\x0b\x8c\x02\x29\x14\x9f\x52\xc8\x1d\xbd\xa5\x93\xf4\x9e\xd8\xfa\x8c\xf5\x8e\x60\xe1\x58\xaf\x7f\x64\x99\x10\x61\xe8\xd8\x87\x37\x0e\xc3\x13\xd2\x90\xac\x9b\x0d\x1d\xb5\x0b\x32\x85\x46\x11\x90\x34\x91\xda\x44\x8d\x9f\xda\x49\x5b\x50\x60\x8a\xff\xee\x98\xde\x21\xca\x21\xb1\xb4\x91\xa9\x30\x86\x66\x31\x45\x97\xfc\x1b\x32\x38\x89\xf9\x69\x10\xf2\x46\xd2\x50\x42\x36\xdd\x75\x57\x09\x50\xad\x49\x09\x86\xc8\xe6\x87\x90\x1a\xd5\xaa\x6a\x30\x9b\x80\xa2\x5f\x39\x56\x37\x35\x10\x62\x61\x6f\x19\xb2\x90\xfd\xba\xad\x97\x40\x75\x23\xc8\x22\x7c\x04\x28\xae\xb5\x6a\x8a\xdf\xd5\x97\x74\x63\xd6\x2c\xf9\x20\xc8\x30\x85\x5b\xc2\x88\x09\x9e\x9d\x20\x3e\x31\xcc\x1f\x3f\x78\xc0\x42\xa7\xc4\xd1\x87\x40\x44\x47\x75\x9f\x0e\xc7\x08\x3c\x53\xa7\x29\xff\x79\x6f\x17\xf2\x08\x4a\xc2\x32\x38\xce\x4a\x58\x06\x4f\xe1\x11\x7b\xcd\x98\xaf\xd0\xd3\x70\x59\x27\x25\xee\xba\x6b\x26\x58\x33\x92\x75\x2a\x21\x71\xe4\xb1\x2a\xff\x35\xd6\xb0\xde\xdc\x34\x53\x4a\xd8\x80\x0d\x88\x1d\xa0\xbf\xa3\xed\xd3\x4b\xf5\xb0\x41\x09\x55\x23\x63\xdf\x09\x7b\x94\x83\x0a\xef\x7e\x97\x70\xaa\x5e\x73\x3a\xd4\x4e\x6b\x79\x68\xa5\x74\x0f\xc6\x6c\xad\x92\xd7\x4e\x23\x3b\xa6\x63\x0c\x8b\x01\xf6\x89\xdf\x2d\xf2\x67\x98\x8d\x3c\xfa\x9c\x37\x32\x98\xb4\x80\xfc\x3a\x36\xa9\x5a\x92\x42\x13\x48\x52\x7c\x3c\x49\xf2\x5c\xce\xa0\x3e\x85\xf4\x80\x5d\xf0\x89\x20\x64\xa2\x10\xe8\x91\x3a\x18\x6a\x9e\x53\x00\xbc\x62\xef\x1b\xf9\xc2\x53\x80\x19\x2b\x30\xbb\x29\x91\xac\xe8\xce\x37\x3a\x7a\x5b\x69\xd8\x6e\x48\x83\x49\x77\x76\x7c\x25\x21\x89\xc0\xf9\x8c\x38\x81\x87\x69\x47\xc8\xd4\x49\x93\x49\x3c\x20\x03\xf1\x7e\xa7\xa8\x9b\x30\x04\x95\xa6\x15\xcc\xbb\x79\xa2\x35\x5c\x67\x47\xb7\x7d\x11\x90\x6a\x96\xcf\xe9\x75\x24\xc3\x7e\x88\x47\xfd\x4f\xa5\xb6\xd7\xb7\x8f\xa9\xca\x16\xd2\x58\x6b\xd8\xb4\x8c\x29\x8c\xe6\x0d\x31\xb3\x15\x80\x5f\x19\x84\x11\x36\xfe\xe8\xc1\xa5\x96\x43\x94\xe5\xbe\x12\xe5\xa1\x40\x58\xcb\xbb\x44\xa0\x4e\xca\x3b\x59\xed\xaf\x36\x01\x12\x51\x92\x91\xb9\xdb\xcc\xde\x1b\x6d\xc5\xa8\x10\xa5\x83\x35\xf2\x0f\xa0\x1d\x25\x1d\xa2\x7b\xd5\x9a\xbc\xee\xd2\x8c\x0a\x19\x92\x3b\x36\xa6\x08\xd0\x8d\x2e\xc2\x2e\x95\xa5\x0f\x89\x7a\xd6\x6d\xb9\x42\x49\xe9\xd6\x8a\x8d\x99\xe2\x03\x23\xfe\x56\xc4\xff\x95\xcd\x35\xb4\xfa\x51\xec\x10\x90\xc5\x1b\x7a\xe2\x94\x67\xaa\x78\xb7\x78\x84\x8a\x3c\xbe\x27\x8f\xab\x88\x94\x74\xa3\xba\x74\x4b\xf3\x4c\x3e\xc2\x22\xdd\xad\x16\x31\xe8\xa1\x95\x3d\xe4\x9f\xf8\x00\x5d\xf0\x29\x54\xa3\xd2\xfe\xe9\x68\xe2\x7f\xd3\x26\x41\x1d\x08\x38\x4b\x7b\xa6\xf5\x29\xdd\xa1\x7e\x43\xec\xe8\xc3\x9e\xb6\x75\xe4\xc0\xf2\xf5\x38\xdb\xe0\xec\x39\x02\xde\xb9\x8a\xc6\x2f\x76\x95\x8b\x22\x80\xa4\x6d\x07\xb4\xcf\x7a\x7e\x08\x90\x40\x4a\x99\x7a\x31\xd5\x6a\x55\xff\xfa\x5c\xc5\x09\xaa\xa3\x3c\x81\xc4\x77\x6a\x5b\xe4\x1f\x63\x10\xce\x56\xfa\x2f\x42\x66\x59\xa7\x6e\x12\x8f\xaa\x57\xe8\x3b\x39\x61\x5f\xff\xdd\xd9\x24\x0d\x35\xb2\x91\x91\xa3\xcf\x63\x97\x6b\xe7\x70\xc3\x20\x65\x71\x60\xad\x71\x05\x08\xcf\x5a\x5b\x90\xd0\x52\xcd\x21\x21\x95\x15\x1c\x87\x43\x05\xb5\x9b\x90\x54\x21\x59\xa9\xa1\x9b\x1e\x0c\x60\x65\xa0\x5c\xef\xdc\x2f\x18\x1e\x3f\xf6\xb4\x26\x4a\xb3\xdb\x22\x5f\x87\xd5\x3a\x9c\xbc\x9a\xd5\x27\x2c\x89\x24\x08\x95\x4e\x69\xf4\xac\xc9\x05\x85\xb3\x52\xf0\x87\x55\x1a\x05\x00\x3f\x8e\xab\x2f\xe9\x25\x5c\xd3\x1a\xb2\x52\xc8\x6a\x02\x73\x90\x0b\xa3\xc6\xe4\x43\x81\x34\x8e\x5f\x43\x69\x6a\xb2\x06\xcc\x94\x86\x80\x59\x7f\xb5\x42\x03\x7a\x70\xc1\x38\x7f\x2b\x40\x1e\xf7\x29\xdb\x41\xaf\x5d\xd8\x2f\x0f\xb3\x12\x15\x5d\x1b\x6a\xd5\x6f\xcf\x57\x96\xb4\x93\x7a\x39\xd6\x23\xfa\x16\x09\x2d\x35\x8c\x44\xb9\x59\xfb\xa9\x3c\x31\xd7\xd8\xad\x05\x29\xe5\x30\x64\x65\xf8\x0c\xd1\x07\x1f\x5c\x36\x43\xc2\x4f\x7f\xa8\x3d\x08\x8b\xdd\x84\x53\xbb\x3c\xab\x52\xab\x87\xb0\x01\x19\x5c\x40\x51\xab\x46\xf1\xc2\x0d\xfa\xd7\xe8\x70\x3d\xd9\xeb\x00\x62\x02\xef\x90\x7b\xca\xc9\x20\xad\x76\x1b\x91\x46\xe5\x83\x6c\xd1\x50\x6a\xcb\xb3\xae\xe2\xc1\xea\x22\x4b\x56\x0a\x7a\xb4\x3c\xbb\xf5\xfb\x2f\x75\x4a\x07\xcf\x30\xd1\x55\xe9\xb9\x59\x3f\x57\x04\x2b\x9f\x15\xe3\x51\x41\x79\xe1\x66\x49\x41\x43\x03\x2a\x43\xd7\x7a\x40\x3b\xc6\xd6\x7f\x40\xab\xe5\xb7\x59\x8a\x55\xa0\x66\x84\x90\x53\x83\x60\x40\x6c\xc7\x29\x27\x2b\xf7\x28\xcb\xa8\x13\xb5\x95\xd1\x6e\x88\x47\xf1\xb7\x18\x98\x6e\x09\x43\xb9\x1d\xa9\x14\xab\xda\x10\x03\x32\x68\x48\x85\xf2\x1f\x20\xbb\x76\xd0\x2e\xd6\xad\xa2\xeb\x28\x37\x85\xf3\x8b\xfe\x1f\x9c\x15\x47\x5d\x71\xea\x9a\x9b\x27\x18\x40\x7c\x2a\x8d\x8c\x4a\x0c\xdd\xcd\x7e\x40\xc4\xfc\x5f\x05\xaa\xae\x9b\x05\xfd\x18\xad\x1b\x58\x3e\x43\x78\xea\xc9\xd1\xc4\x90\xa6\xc4\xae\xf1\xa0\x09\x5f\x0c\x94\xf9\x6b\x87\x12\xf7\x53\x1f\x31\xe2\xff\xfc\xa1\xd4\x62\x86\x50\x7a\x98\x25\x26\xe5\xaf\xa0\x4f\xe2\x1a\x4a\x2f\x8d\x6e\x6c\xac\xc1\x0e\x0f\x62\xa7\xcd\x4b\x12\x74\xd2\xcd\xcc\x36\x24\x28\x32\x27\xd7\xe7\xe8\x59\xc3\xe0\x61\xea\x56\xa6\xf3\x50\xba\x7a\x3a\xd7\x60\x98\x27\x98\xf1\xbb\x9c\xd4\x69\x95\x53\xe2\x7f\x3d\x83\xca\x5e\x78\x5f\x8f\x94\x3d\x91\x20\x61\x54\xb7\xb2\x23\x92\xda\xff\x29\xc0\xe3\x88\x8a\x52\xae\xd1\xfc\xbc\xb9\x9b\x74\x67\x31\xde\xa2\x5e\x55\x53\x96\x3b\x8c\x39\x39\x6b\x25\x9d\x30\x3c\x6e\xe9\x50\x1d\x74\x29\x74\x87\xe6\x3d\xc0\x53\x24\xe0\xa4\xfc\x0d\xa7\x3b\x86\x72\x15\x3c\x6e\xa8\x51\xb5\x5f\xdd\xfa\x05\x99\x7a\xa7\xca\x2a\x71\xad\x67\x57\xa7\x72\x05\xad\x55\x22\x5a\xd3\xcd\xdf\xb3\xc7\xbc\x83\x13\x8d\xf4\xf6\x58\x07\x83\x2c\x49\x1b\xcd\xaf\x8f\x22\xbe\x10\x38\x96\xa7\x80\x77\xd4\xec\xc5\xa2\xe9\x0d\x04\x71\xfc\xbc\xeb\x26\xab\x4d\xfb\x61\x6c\x4d\x60\x17\xd7\xd1\x53\xd3\x95\x2e\xac\x19\x36\xc5\xf6\xf6\x31\xe9\xca\x86\x91\x9c\x0b\x4a\xc1\xf6\x4e\x98\x34\xd0\xf1\xe0\x92\x3a\xe9\x21\x2c\xde\x49\x49\xe5\x62\x34\x15\x2a\x3a\x27\xcb\xd8\xf1\xd9\x6f\x14\xe4\xd4\x98\x6c\xeb\x0a\x5c\xbe\x1d\xda\x6c\xff\x36\xd2\x40\xa6\x9b\xbd\x85\x17\x89\x97\x5f\x1b\xe7\xaa\xf1\xf9\xde\x0f\x8e\x71\xbe\xf7\xe0\x8d\xd5\xb7\x90\xee\xf4\x75\xee\xb8\xff\x92\x6f\x51\x38\xc8\x80\x7f\x56\xdf\xc8\x24\xff\xb2\xe3\xf2\x85\x8d\x12\xbf\xef\x6f\xb6\x4e\xb1\x1f\x38\x4b\x40\xdd\xfe\x6a\xec\x07\x73\x99\x90\xe6\xfa\x55\x91\xdf\x41\x24\xd8\x2f\x98\x22\xfe\x40\xbf\x90\x37\xf5\xe9\x1d\xe4\xb9\xb1\xfa\xfd\x26\xce\xdb\x7f\x45\xf1\x80\xc9\xa9\x44\x0b\xbf\x1e\xb6\xe7\x21\x06\x46\xd0\x01\xf6\xec\x7a\x5c\x36\x94\xf2\x00\x9c\x01\xb6\x08\x9f\xca\x18\xe8\xa7\xf2\xe3\xfb\xf0\x0d\x87\x88\x17\x65\xb9\xd8\x9e\x7e\xec\x83\xe3\x5c\xf1\x27\x51\x13\xf9\x03\x3f\x14\x55\x58\x1f\xab\x7b\xb0\xd7\xdb\x3e\xc0\x9d\xa5\x75\x5e\xd4\x97\x7a\x47\x46\x24\x00\x3f\x6c\x43\xa1\xe4\x54\xeb\x1a\x03\x7a\xe0\x47\xd3\x06\x5d\x0c\xf4\x6d\xcf\xeb\xcf\x7f\x99\xa1\x07\x3e\x28\x1e\x6b\xed\x00\x55\xc0\xc2\xbd\xfe\xa4\xb3\x65\xdd\x0e\x4d\x24\xbc\x5d\xd3\xe5\x24\x0a\x65\xcb\x77\x39\xbb\x34\xd7\xb9\x97\x1c\x2a\x5c\xe7\xbf\x82\x5c\xec\xe0\x18\xfa\xe9\x81\xc1\x9a\x60\xe5\xb1\xc0\xf5\xec\x2a\x5e\x6a\xc1\x80\x20\xf9\x1d\x67\x5e\xbb\x4a\x54\x59\x15\x7b\x7a\x33\x95\xe1\xec\x50\x82\x6f\xb6\x30\x93\xcf\x0d\x94\xd7\x7f\x56\x4b\x21\x0f\xb1\xb5\x2e\x23\x16\x3f\x3e\x9c\xe7\xdf\xe2\x86\x41\xe4\xeb\x1f\x61\x04\x1b\x9e\x46\xb6\xc3\x1b\xe2\x09\x62\xfc\xbe\x4b\xd2\xc5\x48\xe8\x81\x52\x5f\x97\x50\x96\x00\x81\x63\x7f\x49\xde\xb3\x9c\x0c\x21\xce\x65\x0d\x4b\x16\x0c\x92\x19\xb0\x7f\x97\xef\xde\x83\x06\x8a\xd8\x9e\xe1\x08\x74\xbf\xa5\xea\x0a\x6d\xaf\x39\x24\x3f\xde\x9e\xf6\x45\x44\x35\x17\x2b\x9f\x7d\xcd\x24\xb0\x1e\x5e\x94\xc8\x52\x34\x78\x46\xe2\xdd\x9b\xa1\x6e\xd2\xac\x6d\x41\x13\x7d\xef\x90\x6f\x31\x30\xf5\x4b\x98\x1b\xdd\x0e\x80\xfa\xe4\xce\x3b\x67\x86\x21\x00\xb8\x4f\xe4\x94\xbf\x43\x9d\xc7\x80\x0c\x2c\xde\x49\xda\xae\x6f\x69\x79\xbf\x21\x7e\xc8\x9b\x6e\xb5\x7c\x17\x07\x87\x72\x58\x1c\x04\x61\xd6\xe8\xd2\x62\x92\xbc\x4a\x11\xcc\x3e\x6a\xaa\x90\xad\x92\x0d\xe3\x7b\x90\x7e\x3c\x1a\xc3\x12\xad\x7b\x85\x4c\x57\xad\x90\xb3\xf2\x55\x75\x77\xbf\xac\xdd\xb1\xb2\x47\xa0\x02\x86\xec\x9c\x4b\x58\x5a\x5c\x4c\xc5\x85\x2a\xd8\x7f\x2e\xf5\x75\x29\x6c\xfa\x2a\x55\x89\x1c\x2f\x25\x38\x58\x39\x16\xb7\xe3\xa1\x16\xd8\xee\xd7\xe8\xc3\x84\x2b\x05\x6a\x72\x3f\x7a\xe1\x3d\xe4\x10\xfc\x85\xee\x6d\xa2\x7c\x0e\xbc\x90\x37\xaa\x7a\x7d\x76\x96\x88\x17\xac\x12\xfa\xb2\xeb\xcb\x1e\x83\x74\xab\x47\x59\x7c\xbe\xc2\x83\xc5\x23\x15\x6c\x2f\x5e\x39\xcc\x19\x5f\xf9\x2f\x49\xbf\xe8\xd5\x99\x7f\x44\x00\x29\xec\xb4\x0c\xc9\x81\xea\xd5\xe9\x7c\xd6\xbd\xf0\xb6\x1d\x99\xfd\x69\x26\x98\x3f\xa1\x63\x66\x98\x89\x94\x40\xec\xd8\x3a\x52\xbc\x07\x5a\x60\xe5\x45\x37\x1e\xd7\x08\x7b\xc5\x7b\x49\x69\x31\x7a\x4b\x11\x2f\xb5\x96\x58\xc0\x28\x73\xe1\x82\x94\x4d\x5c\x2a\x4c\xc7\x54\x9e\x89\x83\xfd\x67\xb4\x09\x0d\x31\x74\x3a\x28\x8e\x86\x39\xd4\xcc\x63\x90\x7d\xf4\x4a\x4f\x1e\xea\x86\xe8\xe4\x75\x62\x7c\x41\xe1\x30\x07\xfe\xa4\x7b\x56\xc7\x45\x21\xed\xeb\xe3\x0f\xe2\x7a\x7f\x44\xf4\xb9\xde\x75\x0b\x1d\xaf\x77\x9d\x29\xfc\xe4\xd1\x05\x4e\x93\x41\x38\x8c\xa2\x59\x77\xfb\x59\x0f\x5e\xb7\xc2\x2a\xd6\x27\x5e\xf8\x5f\x06\x59\x2f\x9c\xd0\xdb\xf4\xeb\x46\x7a\x28\x95\xc9\xe0\x4c\x1f\x32\x50\xa7\x07\xd8\xfc\x96\x5d\x4e\x28\xa5\xda\xd7\x3d\x48\x3f\xac\xba\xb6\x3d\xcf\xd2\x98\xb0\x74\x79\x37\x8b\xdb\xe9\x1f\x52\x94\xb9\x64\x0a\x6e\x65\x6a\x2e\xde\x0a\x31\x32\x3f\x4f\x93\xc7\xb1\x0b\x89\x9d\x6c\x13\xaf\x5a\x25\x39\x65\x4d\x8c\x54\xba\xea\x2e\xc2\xc2\x55\xb7\xa5\x44\x76\xe5\x05\x29\x2e\xef\xf2\x44\x6f\xeb\xf2\x46\xc9\x4f\x56\x25\xd2\x6b\xc3\x07\x1f\x22\x5c\xa5\x51\x05\x6c\x3f\xa5\x58\x70\xf9\x4c\x8b\x2a\x1a\x88\xa6\xf0\x6b\xbc\x0a\xb4\xb9\xa9\x4b\x36\xdf\x3f\x09\xb0\x56\xf7\x2e\xfb\x85\x34\xd7\xed\x3f\xe9\x7d\x79\x29\x73\xeb\x8b\x46\x5d\xfe\xd0\x30\x3d\xa5\x43\x76\xcf\x8a\x0b\xf3\xba\x04\xf1\x9d\x5f\xdd\x67\xdb\x50\x76\x89\xb7\xac\x34\x81\x2b\xcb\x3f\xc4\x80\x77\x57\xae\xf4\x71\x23\xec\xcb\xfa\xe6\xfe\x44\x9d\x4f\x7f\xc6\x3f\xa1\xf8\x41\xf5\xae\x76\xce\xda\x40\x9c\x5e\x00\xbf\xc0\xd4\x2f\x25\x29\x6e\x6a\x20\xde\xb3\x54\xd4\x4e\x5e\xc9\x53\xf2\xaf\x9e\x7f\x0b\xf9\x24\xa6\x8a\xdb\x98\x80\x9a\x5f\xdf\x4f\x70\x1a\xcf\xef\x3b\xb9\x26\xfb\xf9\xad\x47\x17\x21\xfa\xb8\xcc\x90\x14\xc0\x10\x94\x6e\x8e\x4a\x44\xdf\x0d\x52\xd4\xc5\x5a\xbe\x36\x32\x07\x0b\x98\xca\x2a\x48\x97\x95\x3e\x8d\x35\x7d\x97\xfe\x9b\x69\x89\x6f\x40\x89\xc6\x50\x19\xfb\x72\x55\xa2\xa8\x03\x71\xd8\xaf\x19\x94\xdc\xc5\xf9\x66\x3e\xd1\xf9\xca\x1e\xd0\x3a\x5f\x4a\x2c\xe1\x2e\xb4\xa9\x3f\x6f\x30\x91\x1c\x1c\xd4\x28\xb9\x69\xef\x44\xc1\x31\x85\xbb\xb0\x20\x81\xab\x7b\x2d\x54\xcd\xfa\xf8\xa2\x7d\x95\x91\xa7\x6a\xf8\xe0\x8d\xb2\xef\xcd\xad\x90\xce\x2b\x64\x46\x0c\x65\xeb\x04\xfc\xdd\x99\x3e\xf9\xb6\x1c\xe1\x0a\xc2\x55\x68\x5e\xa5\x8c\x75\xeb\x5e\xd8\x47\x78\x85\xec\x17\x47\x8d\x2e\xae\x19\x22\x5d\xad\x2a\x9b\x9e\x3a\x65\x14\x62\xc3\x67\x46\xf1\xa3\x4b\xf5\xb1\x83\x90\x1f\x93\x84\xcc\x85\x94\x05\x82\x83\x8e\x4c\x86\xea\xc5\x9f\x55\xd9\x01\x85\x58\xd9\xd5\xe7\x1f\x6d\x29\x04\x7b\xae\x9a\x55\x4b\x58\xad\x1e\x3a\x4a\x57\x91\x80\x59\x89\x04\x03\xab\x21\xf8\x1d\x1b\x78\xe7\xae\x37\x16\x37\xc5\x9a\xdb\xa5\x71\xf6\x12\x43\xb6\xae\xd7\x63\x6d\xcf\xa1\x87\x68\xf0\x77\x7a\x90\xee\xf8\x23\x22\x80\x04\xb4\xf0\x57\xd8\x28\x3e\x94\xd2\xd2\xae\xe4\x6b\x57\x0e\xcb\x02\x45\xc2\x44\x57\x30\x44\x20\x20\x86\xe2\xff\xee\xc2\x5e\xa8\xeb\x81\x49\x77\x07\x90\x91\x1c\xc0\x2e\x61\x03\x05\x03\xd5\xa0\xe7\x51\xa8\xe6\x60\x80\x3e\x90\xe7\xa1\xf4\x05\x03\x92\x21\x3b\x72\x88\x8a\x65\xf1\xc7\xdc\xbc\xc9\xef\xc4\x91\xe8\xef\x0a\x10\x67\x4d\xae\x53\x41\xa8\xf7\xea\x48\xa5\xe7\x68\x9f\xf5\xd6\xa5\x7a\x66\x33\x15\xc7\x44\xe8\x3e\xd9\xc1\xb2\xa2\x48\x82\xac\x79\xc7\xff\xac\xff\xe7\x83\x61\xd8\x85\x70\x03\x29\xda\xc1\xad\x43\x69\x7b\x67\x65\x52\xf0\xb9\xdd\xa1\x21\xb5\x9d\xd2\x44\xda\x44\xd3\x76\x10\x3a\x59\xc2\x45\x58\x12\x4d\x9b\xcb\xc6\xfa\xf5\xad\x37\x67\x1a\xc0\xc4\xe7\xee\x6b\xed\x2a\x66\x3d\xc9\xe5\xb4\x1e\x8b\x74\xd2\x0c\x65\xad\xd2\xab\xba\xa6\xa7\x5e\xa3\x35\x51\x61\xfc\x84\xa5\x32\xbf\x10\xd8\x23\x1f\x52\x3c\x2b\x24\x6e\x9c\x7f\x35\x94\x67\x0d\x06\xd1\xfb\x2c\xaf\xc6\x1b\x65\x03\x54\xbf\x1f\x50\x8e\xf7\x32\x0c\x11\x4f\x44\x02\xf9\x63\x5d\xfa\x8c\x80\x97\x6f\x25\x77\xb2\x51\xf6\x49\xcd\x6a\xe8\xfe\xa8\x1b\x6a\x90\x5a\x49\x65\x55\x72\x24\xc5\xd1\x66\x3d\x0b\xeb\x7b\x71\xb2\xc6\x3a\xb5\x2d\xae\x27\xff\xc3\xf4\xe7\x12\x15\xcf\x18\xec\xb7\xd2\x73\x3e\xac\x44\xae\xa7\x23\x19\x4f\x9e\x73\x7d\xe9\x45\xb1\x13\x5c\x0c\x6d\x60\x22\x47\x07\x28\x1f\xcf\xbc\x77\x5d\xb5\x42\x53\x29\xc4\x47\xd5\x7b\x3c\xe7\xcc\xff\xe6\x50\xdb\x9b\xb3\x06\x2d\xc8\xfc\xf0\x2e\x03\x26\x60\xf9\x4e\xce\x69\x29\xdc\xc8\x7a\x36\xce\x96\x82\x36\x5a\xe5\xaf\x86\x0b\xa5\x56\x75\xef\x49\x24\x94\x7a\xc8\xe9\xcc\xb7\xe4\xc9\x6e\xf9\x10\x22\x7e\xf7\x51\xa9\xd7\x23\x37\xb6\x68\x50\x4f\xcb\x1d\xf0\x07\xe5\xc6\xd4\x14\xab\xa9\x4f\x38\x41\x13\x52\xc2\x0d\xc6\x30\xac\xb9\xf3\xa6\x8d\xb6\xc4\x8b\x82\x12\x1c\x3f\x4c\xb4\xb5\xf1\xdd\x61\xd0\xe7\x65\xc8\x8e\x59\x85\xc2\xd7\x2b\x43\x71\x2d\xd6\xc1\x66\x53\x30\xb4\xbe\xb2\xb2\x28\xce\x9c\x94\x2b\x72\x4a\xa9\x02\xe5\xaa\x92\x6a\x93\x98\x03\x96\xe2\xd6\x58\x63\x36\xe0\x74\xb7\x1c\xae\x84\x78\x9a\xd2\x2a\x99\xd5\xde\xa5\xd1\xde\x9a\xb7\x83\x60\xda\x1d\xe0\xf8\x09\x8e\x21\x7d\xb4\x2b\x96\xf1\x2b\xb0\x72\x0a\xed\xb1\x7b\x08\x7d\x31\x68\x23\xc5\x76\x5d\xab\xd2\xe5\xd1\xfa\xcd\x70\x21\xb4\x59\x82\x75\x58\x08\x7f\x56\x5f\xe8\x7b\x43\x43\x41\xa8\x76\x14\x23\x2f\x60\xf2\xc5\x1d\x95\x21\x14\xd7\x36\xd5\xe4\xa1\xa1\x46\x5c\xf6\xd8\x16\x52\x82\xfb\x33\x70\x96\xbe\x5a\x59\xaa\x74\xe7\xec\xf5\x64\xb8\xcd\x8d\xc8\x8f\xbe\x6d\x7f\x5d\x01\x25\xa1\x96\xb7\xae\x1c\x67\x0f\x7b\xa6\x85\x04\x16\xa6\xfe\x7b\xac\x53\xaf\x53\xa4\xc7\xa3\xd3\x1f\xb8\xd8\x1f\x44\xea\xdb\x87\x8a\x3d\xd0\xa3\x06\x78\x10\xec\x91\x01\x7f\x8e\xd4\x93\x3a\xd3\x27\xde\x09\x38\xd5\x7a\xf9\xbf\x2e\xd2\xf6\x92\x7e\xd9\xcb\x67\x65\xfd\x60\x1a\x75\x9d\xb0\x48\xf0\x12\xd3\x7e\x0e\x76\xef\x10\xee\xc4\x53\x64\x1f\x9d\xf0\x2b\x62\x35\x85\xf8\x9e\x3a\x2d\x08\xf1\xf1\x64\x36\xd2\xe4\xbb\xe0\x93\x9d\x94\x44\x5b\x59\xed\xdb\x98\xe4\x0a\xf5\x37\x0d\x08\x01\x36\x5e\x9b\x73\x22\x05\xd7\x38\xd7\x80\xb0\x3b\xeb\x3d\xeb\xed\x5d\x21\xf0\x99\x42\xe8\x0d\x96\x06\x38\x6f\xfb\x4c\xdf\x70\xcb\x6c\x9f\xc1\xab\x1d\x2b\xd5\x2d\xc4\x74\x3c\x6b\xcf\x66\xbd\x29\x4d\x2a\xb7\x5b\x9a\xf4\x90\x5a\x63\x86\x0a\xd4\xd4\xa4\xd6\x05\xc4\xd2\x0f\x75\x0f\x1f\xef\xff\xb6\xfa\xf1\x08\x6c\xab\xff\x8b\x96\xb7\xd5\x9b\xdd\x0c\x03\x9b\x67\xd6\xf9\x9d\xf8\xc7\x28\xb6\x49\xcf\xc1\x45\xcd\x72\x80\x61\x65\xca\x1a\x16\x14\x90\x31\xa8\xc0\x40\x0b\xc7\x21\x00\xaa\x98\x59\x5b\x2f\xd6\x8e\xb5\x24\x85\x87\xd9\xf8\x15\xb7\x6e\xa7\x02\x89\x34\x0a\xcb\x21\x3d\x7c\xe4\xd6\xcf\x99\xca\x44\x86\x18\x2d\xb0\xce\xd9\xc5\x6b\xa4\x9e\x58\xb5\x66\x2f\x36\x96\x51\xb9\x81\x10\x48\xb3\x57\x57\xa5\xf4\xd4\xa6\x3c\xe7\x24\xc9\x2d\xa8\xe1\xef\xbf\x5b\x81\xb9\x16\x5d\x88\x86\xd7\xd0\x42\x68\x13\x0f\xa9\x7a\xcb\x00\x26\x03\x6a\x48\xbd\x0d\x89\xf9\x58\xa0\x06\x54\xa6\x72\x03\x52\x3f\xab\xf7\xd2\x61\xb3\x2b\xc1\xae\x72\x4a\xd0\xb7\x95\x83\x3b\x52\x83\xcd\x06\x0d\x90\xb7\xde\x28\xc4\xb6\xbb\x3c\x3b\x77\xdd\x25\x85\xa6\x57\x12\x56\x67\x67\x90\xc1\x99\xe3\xdb\x65\xd3\xdc\xe1\x0b\xd5\x4a\xa1\x12\x5b\x7f\x38\xee\x79\xdd\x9f\x81\x96\x78\xd7\xe6\x4a\xf1\x37\x77\x64\xf1\xdf\x9a\xef\x2b\x94\xce\xce\x43\x32\xd7\x56\xb0\x8f\xd0\x22\x5d\xb3\xfd\xc3\xcd\x01\xee\xe2\x6b\xb1\x6f\xe9\xb1\x1f\xe0\xaa\x72\xc9\xff\xec\xf4\xd0\xc5\xc6\x72\x57\xb3\x43\x9a\x26\x55\xf9\x90\xa5\x59\xf4\xff\x99\xe7\xcd\x7c\x24\xcc\x62\x6e\x79\x94\x9a\xda\x90\xa9\x80\xda\x94\x40\xe3\xf0\x4d\x01\xb3\xfb\x92\xa2\xd9\x0d\x5e\x0a\x11\x1e\xbe\xe4\xfe\x30\xdf\x22\x3d\x3f\x1b\x0c\x4a\x4f\xed\xb8\xf5\x1a\xa7\xa3\x1e\x0c\x84\xb8\x1b\x2c\x7d\x3b\x30\x77\xd5\xb9\x56\x4d\xcd\x8d\x3d\x3f\x70\x4c\xe9\x0d\x00\x75\xb5\x2a\x36\xb1\x75\x1d\x78\xa8\x12\xba\x23\x2e\xa2\x16\xc9\x67\xe8\x0b\xef\x61\x05\x6a\x7d\x2c\x4d\x14\xa1\xb7\xe5\x03\x4e\x37\x1c\xcc\x5a\xb5\x96\xd0\x4d\xbb\x2e\x51\x16\x80\xf5\x6f\x4d\x29\x19\xa0\x6e\xd2\xdd\xc2\x36\xc6\xe0\xc1\x66\xe1\xb0\x36\x21\x80\xde\xd0\xc3\x13\x1a\x58\xff\xdb\xa0\x4d\xe5\xcd\x01\xb9\x01\x1f\xa0\x1d\x50\x65\xdc\xd9\x95\x3e\x30\x81\xcd\x32\x78\xd2\x87\x8b\x25\x36\xfd\xd7\x53\x85\x03\x26\x8a\xaa\x95\x17\xe3\x38\x07\x3f\x0d\x41\xcf\x7b\x3c\xe4\x42\x79\xa8\xc3\x62\xa5\x2e\x22\xf3\x12\xf2\x44\x71\xa8\xc6\xb9\xbd\x03\x72\x78\x92\x6f\x43\xb0\xd0\x2f\xa0\x5e\xa1\x31\x05\x4a\x33\xf7\x47\x44\xc5\x43\x41\x70\x42\xe3\xb4\x9a\xdd\x06\x6b\xeb\xb8\xce\x1a\x04\x0a\x38\x42\x83\x8d\xbb\x6e\x4d\x41\xd9\x03\x95\x14\x5d\x9f\x3c\xaf\x8a\x9b\xad\x88\x0e\xa9\x2f\x7a\x44\xf6\xf9\xc1\x08\xf2\xb1\x4a\x86\x4f\x4a\x6a\x40\x45\x72\xd5\xd6\xf8\x7e\xf9\xb8\x0e\x17\x57\xe7\x08\xf4\xf8\xd9\x86\x3b\xf4\x07\x6f\x28\x1d\x85\x0a\x69\xcf\x3d\x76\x7a\xee\xbd\x15\x39\xfc\x53\xe1\x06\xf9\x70\x6e\x8c\xfd\x90\x38\x22\x58\xd3\xfc\x5f\xc4\xff\x8f\xa2\x2a\xed\x88\x30\xc0\x21\xc7\xbc\x03\x9d\x53\xa4\xb2\xdc\x2f\xee\xcd\x14\x55\x8e\xd1\xb9\xc0\xc9\x66\xe8\xa7\xd9\xfb\x4a\x45\x39\x1b\x92\x30\x4e\x75\x64\xf9\x44\x50\x9e\x0c\x21\x13\xaf\xa5\x0e\xf4\x3c\xbf\x02\x89\xe5\x93\x89\x49\x98\x57\x92\x5c\x59\x93\x2e\x9d\xf3\x80\x79\xe0\xbd\x2b\xc2\x11\x72\xdf\x9d\xea\x42\x50\x50\x93\x5c\x9a\x18\x50\x47\x46\x47\x82\xff\x63\x3a\xfc\x91\x3e\x67\x95\x78\xd9\xab\xa7\x77\x1a\x66\xaf\xdc\x55\xd0\xbc\x49\x3b\xac\xfb\x72\x15\x29\x8a\x85\xfa\x9a\xdd\x1d\x3e\x0b\x7b\xb7\xe8\x2f\x64\xdd\xe6\xef\x2f\x5c\x76\xb0\x57\x04\x5d\x34\xc9\x9e\x02\x7a\x93\xf0\x9f\xa4\xd1\xf4\x30\xad\x32\xff\xe3\x1d\x4d\x52\xc3\x38\xdc\x2d\x82\xd3\xa0\x47\xd2\x53\x45\x8d\x12\x82\x7f\x29\x4c\x26\xa0\x12\x3e\x8e\x3a\xfd\x9e\xba\x6e\x1d\x8c\x95\x42\xb8\x4d\xfd\x9b\xc3\x1d\x94\xa9\x96\xd6\xab\xca\x23\x4d\x4f\x7e\x5d\x52\xee\xb6\x26\xbf\x2a\xce\x59\x5f\x9a\x3f\xae\xf7\xf5\xd6\xdb\x8a\x60\x33\x33\xd2\xeb\xc5\x6e\xa8\xa7\xd7\x76\x65\xb4\x73\x53\x19\x71\x29\xd8\xec\x8e\x12\x39\xab\x89\x1a\x68\xbb\xb4\x7a\xa0\x86\xe6\x05\xc7\xa0\xe8\xc4\xeb\xd8\x07\xb5\xca\x6d\x94\x2a\xde\x35\x22\x22\xfe\x5a\xd6\x18\x35\xd4\xe5\xf6\xf1\x75\x5d\xaa\xd3\x57\x21\x25\x20\x91\xb2\x70\x19\x36\xc0\xda\x16\x7a\x66\xa1\x0a\x5f\x3d\xf7\xcb\xab\xbc\xaa\x94\xf6\x3a\x21\xa3\xd0\xff\x39\x65\xae\xc8\x48\x5f\xd2\x2f\xe0\xd8\x1c\x19\xd8\x71\xd7\x80\xbb\x62\x3c\xbc\xdd\xcf\x99\x19\x42\xd5\x93\x3f\x88\xf7\xdb\x1f\xef\x6e\x5d\x4f\x57\xf3\xaa\xed\x47\x1a\xdd\xab\x42\x0e\x7b\x95\x5c\x5a\x0b\x0a\x09\xa0\xa2\xec\xdd\xc4\x03\x20\x69\xf3\xe4\x4d\xef\x8e\x5e\x4e\x26\x1a\x2a\xe5\xd0\xc2\x06\x6d\x2f\x3d\xce\x6a\x70\x57\x82\x3a\x94\xd0\x9a\xc7\xd1\xfb\xe2\x10\x3f\xd1\xc5\xd1\xf4\x09\x39\xa6\x97\xe3\xee\xda\x9c\xd1\xef\x41\xce\x61\x77\x12\xd8\xf3\x3b\xd2\x83\xf6\x7c\xa3\x1f\x46\x14\x77\x68\xf7\xb1\x66\x28\xe6\xee\x90\x85\x3a\x25\x72\x46\x59\xa7\x5d\x19\x99\x56\xfa\x18\x0e\xa5\x8c\x18\x76\x89\x14\xee\xff\x88\xa5\xec\x39\x85\x06\x9b\xf7\xbc\xf6\xf4\x82\xa2\xe9\x4a\xc8\x1b\x81\xee\xbe\x7f\x73\x86\xbc\x2b\x08\x77\x10\x8a\xa5\x29\x26\x0e\x10\xd3\x02\x12\x73\x95\xc8\x9a\x64\xd6\x0e\x8f\x1c\xee\x69\x73\xe5\x37\x4f\xf9\xe0\x7e\x8b\x01\xeb\x81\x50\x96\x2d\x12\x5c\xb6\x8f\x94\xac\xac\x8f\x1b\x8a\x69\x10\x5f\x0b\x6d\x25\x1b\xc7\x31\xb1\x69\xbb\xc9\x72\xd8\xee\x5a\xf8\x9f\x7d\xd2\x3f\xf6\xf4\xe0\x9a\xc5\xea\xfe\x3f\xaa\x38\xc1\x26\x7b\x15\xdd\x6f\xbb\xc3\x80\xdc\x63\x43\x94\x58\x53\x53\xbc\xb5\x9b\xea\x63\x1f\xaa\x8f\xa9\xf9\x36\xc0\x7c\xd3\xcd\x3e\xdc\x26\x6d\x35\x55\x5b\x5b\x64\xc3\x53\x49\x4d\xb3\x09\x58\xa0\x14\x19\x24\xe1\x3e\x84\xfb\x25\x37\x68\x57\x48\xfb\xde\x5b\xac\xc6\x3c\xc8\xb7\x2f\x6c\x31\xeb\xe4\x4b\xfa\xe5\x06\x07\x64\xb2\x4b\x37\xed\x4a\x6c\x32\x1c\x92\x34\x83\x40\xcf\x93\x73\x6e\x94\x58\xbb\xb8\x76\x55\x3c\x1f\x11\xae\xd0\x4c\x83\xe0\x10\x01\x1f\xfe\x56\xe3\xdd\xdb\x6a\x26\xc5\x60\x8b\xf1\xf3\x86\xcc\xac\xef\xcd\x3d\xcb\x27\x7d\x53\x87\x67\x40\x66\x00\xc3\x79\x97\xc7\x2d\x2e\x2c\xee\x7b\x63\x72\x5b\x3a\x65\x45\xa9\xd2\x5b\x59\x6d\xf0\xf2\xf2\xac\x9d\xcd\xa7\x97\x95\xed\x8d\x34\x67\x56\x20\x5b\x09\x11\x31\xe4\x4d\xab\xe6\x03\x16\x87\x1d\x30\xec\x63\x48\x9d\xd0\xb0\x80\x0b\x3f\xf4\x08\x53\x30\x2c\xea\xf6\x59\x3d\x4e\xe2\xb3\x55\xad\x0b\xc5\xd1\x9a\xf2\xf4\x88\xfc\x51\x64\x06\x8e\x10\x9f\x09\xd5\xb3\x5d\x19\x10\x5b\xd8\xc6\x6d\x88\xb3\x3c\xf8\x4f\x76\x91\xad\xe4\x45\x65\x1b\x44\xbe\x29\xd8\x36\xbe\x23\x46\xb3\xfd\x84\xa6\x46\xeb\x4c\x89\x06\xb2\x8d\x7b\xd6\xca\x5d\xfa\x63\x5b\x61\x02\xa1\xa1\xae\x75\xb6\xba\x6f\x5e\x0e\xfc\x0c\x25\xb3\x88\x2f\x6e\xe3\x72\xeb\xdf\x8b\xdf\xf5\x93\x38\x3d\xf9\x7e\x8c\x73\xd2\xe4\xc0\x36\x5a\x7f\xe0\xe0\x8b\x3a\x3e\xd7\xfa\xd3\x63\x93\xae\xdb\xf8\x08\x7b\x8f\x6d\x9c\xd2\xae\xa4\x23\x88\xb0\x31\x81\x03\x62\x6b\x94\x95\x1b\xc7\xf5\x13\x5c\x27\x2c\x14\x89\x75\x41\x6b\x6d\xd3\xa6\x3d\x3f\xce\x55\xd7\xae\x0e\xa3\xec\x7a\x71\x10\x09\xd5\x05\x02\x4a\x78\x6f\xf4\x2c\x5f\x47\x98\x4d\x5d\x57\x49\xb4\xad\xf9\xd5\x11\x33\x4f\xa1\xd1\x86\xe4\x53\x2a\x74\x7d\x64\x61\x61\x48\x63\x31\x43\xf2\xb2\xd9\x6c\x58\xc2\x5b\xee\x22\x6d\xef\x10\x64\xbb\xe6\xe2\x7c\x7f\xf8\xaa\xb7\x3d\x00\x8f\x27\x0d\xd6\xcd\x93\xf6\x78\xba\xf8\x00\x20\xd1\x56\x09\x70\x01\xbc\x5b\xc8\xf1\xda\x25\x7a\xd6\x1a\x13\xa2\x28\xc4\xa6\x93\x35\xe6\xec\xc3\x8b\x8c\xad\x34\x10\xf5\x19\x01\xa8\xbe\x67\x68\x0b\x61\xb5\x2e\x31\xd7\x86\xa6\xed\x07\xfd\xef\x08\xcd\xb9\xfd\x26\x8d\x68\x73\xbf\x43\x02\xca\xaa\x71\x57\xf4\x82\x74\x7d\xf6\xca\x7f\x25\xbc\xa6\x2a\x02\xd3\x4e\xdc\x6c\xbd\x06\xfe\x0b\x79\xe6\x8b\x90\xe4\xd5\x64\x3a\x05\xd0\xe3\xbe\x5b\xfa\x93\xd8\x1f\x94\xd8\x74\x6b\x8b\x9e\x0a\xbf\x0c\xb8\xf9\x5d\x02\x99\x67\x99\xee\x2c\xa5\x36\x64\x66\x12\x80\xa1\x10\xba\x6b\xaf\xa4\x33\x85\x53\xb6\x21\x37\x03\xd7\x2f\x50\xcf\x7a\x73\x3b\x3f\xb6\x2c\xeb\xc7\x1b\x7d\x2b\xa2\x03\xbe\xde\xd1\xb7\x33\xc4\x0c\x59\x64\xec\x51\x3d\xcb\xbe\x47\x4a\x7c\xf9\x87\x49\x65\x36\xca\x35\xac\xf7\xcf\xc9\x6f\xb5\x96\x82\x73\x9c\x20\x2b\xcc\x0c\x2d\xad\x48\x24\x67\x8d\xb6\xde\x49\x86\x70\x6b\xfd\xea\x14\x22\xed\x41\xd1\x4d\xf2\x6b\xaf\x48\x76\x59\xeb\xad\x12\x62\x80\xdc\xaa\x49\xf3\xad\x29\xf8\xb0\x56\x4e\xad\x59\xa9\x86\x0b\xda\xfd\xf6\xa1\x36\x0a\xb1\x51\x2f\x13\x06\x04\x71\xbe\xb9\x85\x04\x9c\x04\xc3\x30\x20\xf3\x43\xd8\xbd\xe3\x47\x01\xdd\xda\xfe\x9b\x8a\x34\x97\xad\x3b\xaf\x94\x4c\xb8\xfa\x67\xb6\x74\x6b\xf1\xd0\xfb\xea\x02\x92\x13\xd7\xa0\x89\x75\x79\x26\x97\x71\xf3\x4b\xb2\x8b\x0d\x42\xa6\x61\x26\xa2\xae\xe2\x59\x59\x29\xd5\x5f\xeb\x61\x3e\x39\x3f\xb2\x96\xa9\x6b\xc4\x4d\x12\x50\x95\x30\x32\xfc\x12\x9a\xb4\xd2\xf2\xe7\x64\x4d\xb4\x66\x34\xc1\x7a\x7a\x20\x61\x52\xbc\x8d\xb1\x4f\xb0\x8d\x25\xcb\x06\xc5\x38\x76\xfe\x57\x4a\xa6\x10\x15\x8a\xac\x61\x7a\x46\x65\x1c\x6a\xa3\x7a\xc9\x9a\x9f\xcf\xbe\x23\xb8\xa8\x94\x57\xcb\x6a\x33\xd7\x88\xb2\x1b\xd0\x46\xe4\x22\x40\x37\x6e\xd3\x9a\xb1\x8e\xff\xe7\x40\x79\x72\x06\xfc\x66\x42\x86\xd6\xa5\xf5\xd2\xa7\x4a\xec\xed\xdd\xa4\x95\xf6\xe6\x2c\xba\x55\xe3\x94\xb5\x53\x1e\x81\x8b\x55\xfa\x10\x57\xf7\x34\x5d\xb7\x3f\x14\xe2\x4b\x87\xb9\x68\x26\xe4\xb8\xdf\x82\xf0\x1c\x02\x5d\x89\x9b\x85\xc2\x93\x0d\x68\x5b\xd1\xf1\x38\x9b\x0e\xf3\xbc\x50\x9a\xe3\xce\x98\x47\xe6\x1d\x4f\xbb\x46\xcf\x40\xaa\x38\x5d\xdf\x47\x53\x51\x8e\x15\xf6\x72\xec\x99\xd7\xab\xfb\xad\xf0\xff\x50\x8e\xd6\x89\x37\xf8\x0b\xaf\x94\x8c\xf3\x0f\x8c\xbf\x1a\x04\x0e\xea\xd8\xfd\x85\xc2\xde\x93\x43\xa4\x3e\x76\x47\x3a\xa6\x04\x12\x53\x27\xda\xad\xd1\x56\xac\x69\xe4\x5c\x92\x01\xe8\xdb\x09\xce\x9e\xb2\x4b\x51\x3a\x5c\x00\x7c\x64\x51\xbc\x12\xcd\xd8\x00\xfe\x73\xf1\xb9\x33\xd4\xaf\x6e\x8e\x82\x96\x5b\x29\x87\xd6\x86\xf2\xf5\x59\xdc\x02\xcf\x77\xbf\xd7\x3f\xd7\xee\xba\x17\x06\x62\x97\xdb\xeb\x82\x45\x4e\x40\x56\x52\xb2\x0b\x54\x60\x09\xb2\xb5\xcf\x79\x59\xa7\xca\x6b\xcc\x05\x46\x5d\x89\x80\xd2\x73\x77\xaf\x37\x0d\xe7\xa7\x04\xe9\xec\x1d\xee\xda\x6d\x92\xb7\x5e\x9c\x4b\xe2\x27\xc1\xc8\x5d\xff\xa3\x5d\xe1\xd2\xa4\x8b\x60\xe0\xe1\xb3\x49\x0b\x9c\x00\x56\x89\xd1\x15\x89\xe9\xb9\xce\x36\x7f\x5a\x7d\x25\x7a\x9d\x02\x35\xee\x5b\xaf\xee\x87\x66\x6d\xcf\xc6\x48\x2f\x58\x1d\xd4\x9b\x63\xbf\x7f\xa1\x16\xc0\x52\xdb\xc1\x0d\x5b\x8f\x43\x2f\x15\xb2\x71\x0e\xe0\xee\xdc\xb8\xdd\xbc\xce\x99\x92\x6a\x55\x69\x7b\x8b\x0c\x6c\x08\x43\x32\x6f\xfc\xde\x3c\xfe\xc0\xfe\xfc\x82\x18\xef\x5c\x9e\xcc\x25\xc5\x12\x0a\x0c\xfc\xa4\xcb\xb6\xb3\x59\x5c\x82\x55\x4b\xd9\xba\x46\x64\x23\xa0\x2e\x58\xc7\xee\x0b\x14\xeb\x74\x52\xab\x0e\xbd\xb0\xa1\x90\x34\xe1\x56\xa4\x5b\x0a\x40\x94\x28\xc4\xeb\xec\x29\x48\x4e\x6c\x01\x31\xe2\xc8\x5d\xd5\x4e\x93\x2e\x0b\x3e\xc1\x4c\xc0\xf9\x66\x07\xff\x49\xe6\xce\xaf\xa1\xb4\xa5\x4b\xd8\xd9\x87\x18\xc3\x38\xeb\x99\x7d\x23\xd3\x0e\x1e\xa1\xd2\xb8\x73\xb6\x2e\x4a\x5e\x75\xf8\xd9\x2d\xd4\x39\x88\x14\x4b\x5b\x1c\x6f\x35\x34\x8b\xd7\xae\xdc\x3a\x77\xb9\x44\x1b\x9d\xf2\xb6\x60\x6c\xda\x9f\x6b\x99\x24\x5a\x08\x67\x28\x96\x56\x39\xfb\xbf\x7c\x54\xd9\x45\xf2\x10\x19\xa4\xdc\x1d\xe8\xfd\xac\x97\x17\xe6\xd1\xfd\x47\xc5\x3c\x2f\x76\x69\xe4\x45\xbb\x0a\x94\xa4\x86\xb7\xc3\x40\xdd\x7f\x5d\xde\x0e\x4c\xf5\xf3\x6a\xb3\xb4\xb4\xb8\x50\xc8\x1f\x5a\xe0\x36\xa8\x35\x92\xf4\x5e\x32\x05\x97\x96\x9c\x57\xe9\xec\x25\xf7\x61\x59\x22\x97\xc8\xc0\xca\x53\xe9\x94\xd6\x52\x84\xe0\x5d\x97\x0a\x24\x7d\xf0\x24\x3c\xbd\x3e\x86\x88\x1e\xdf\x31\xab\x72\x6e\x95\x08\xbf\xd9\xd8\x96\x1b\x1e\x2a\xd6\x9b\x9b\x1d\x49\x00\x7e\xd1\x21\x8c\x68\x15\x97\x57\xc7\x4b\x0c\xdc\x1d\xfc\x3f\xaa\xde\x2e\xd9\x59\x9e\x07\x16\xbd\x3f\xc3\x78\xe7\x75\x2e\x0c\x18\x70\x02\x98\x8f\x9f\xe4\x49\xaa\xf6\xdc\xb7\x5a\xdd\x72\xd6\xae\x5a\x55\x6e\x58\x04\x0c\x18\x5b\x96\xa5\xee\x85\x80\x9c\x8e\x9a\xfc\x3e\xd3\x4a\xce\xc1\xe4\x31\x27\xc1\xf4\xb7\x2c\x7f\x98\xe0\x9f\x21\xfc\xfc\x4c\xa3\xbe\x73\x2d\xdc\x3e\x53\x17\xf7\x92\xca\xec\x7d\xdd\xe3\x66\x7b\x79\x54\x17\x26\xe5\xeb\x79\xd4\x07\x3b\x58\xf0\xf1\x69\x15\xe5\x51\x07\xb1\xf6\xa5\x9e\x52\xd3\x8f\xb2\xc5\x02\xd6\x03\xd3\x5f\x52\xf9\x79\x08\x87\xb7\x88\x47\xa6\xa7\xe0\x61\x13\x30\x72\xf0\x65\xbb\x6b\xf9\xd3\x80\xa7\xa0\xc4\x7e\xa4\x77\xd0\x17\x3d\x40\x95\xe1\x4d\xdc\x7a\xf1\xe3\xa3\x52\xc3\xa9\x43\x7f\xce\x60\xf8\xbb\x78\xd4\x56\x79\x8a\x4d\xaa\xed\x86\xa4\x55\xfd\x48\x4b\x65\x4d\xcc\x02\x1d\xf8\xbf\x89\xf7\x95\x7a\x0f\x68\x71\xc8\xc9\x53\x79\xd3\xfd\x0c\x35\x41\xf6\x07\x66\x53\xfb\xc1\x88\x4b\x67\x63\x28\x27\x5d\x2e\x56\x9a\xf5\xe8\x68\x73\xde\x79\x47\x63\x7c\x83\xa5\xa3\xcf\x69\xfe\x88\x4e\xee\x23\x02\xbb\x8f\xc7\xb9\xfa\xae\xb7\x3b\x11\x66\x4f\xbb\x0e\x92\x3a\x6c\x84\x0e\xdb\xac\xd0\x90\xf9\x3e\x16\x28\x0c\x9c\x8e\x23\x4e\x6d\x76\xcb\x32\x7e\xb6\x9c\xfc\xc5\xa2\xed\x39\x38\xcb\x6e\xf9\x7d\x0d\xc0\x04\xe0\x39\xc6\x71\x0d\xb9\x88\x19\xce\x0a\xef\x0e\x67\xeb\xe5\xeb\x8b\xaf\x60\xae\xef\x41\x7c\x80\x8d\x54\xdf\x8c\x07\xf7\x14\xc3\x88\xb0\xcf\x88\xbd\x23\x36\x48\xdd\xa7\xbc\x5f\x9b\xc3\x50\xd8\xc3\x40\x4c\xd6\xe7\xba\x93\xd3\xad\x56\x95\x9b\xa8\xf5\x16\xeb\x10\x0b\xd1\x59\x57\x49\x04\xd9\x46\xe5\xc4\xc5\xd0\x1a\x22\x84\x33\x86\x81\xa2\x9a\xcc\x6d\x21\xca\x70\xb0\x82\xcc\x75\x22\x03\x8d\x01\xa6\xae\x19\x68\x4f\xd6\x5e\xa8\xfd\xe6\x0a\x4e\xc3\x58\xd1\x87\x0e\x9b\x17\x79\x0c\xf6\xb6\xaa\x99\xed\x5c\x38\x30\x92\xe9\x2f\x3c\x19\x10\xe5\x03\xbb\x3f\xa1\xf8\x82\x90\x04\x78\xf1\x37\x5b\x63\x21\x2c\x5b\x5a\x1b\xe3\x1f\x6f\xd8\x5b\xbb\x5c\xeb\x33\x5c\x14\x3f\x1e\x40\xf4\x2c\x24\xc3\x8b\x26\x93\x3d\x76\x0e\xb3\x48\x2f\x8e\x20\x66\x74\xf9\xd3\x60\xc6\x13\x57\x64\x0e\x02\x3d\xe4\x09\xfe\xe4\x06\xc1\x7d\x12\xf4\x78\x7f\xe8\xf4\x22\x0a\x90\xf1\x01\x41\xef\xa7\xaa\xd8\xa7\xaa\x1d\x8b\x96\x61\xe7\xfc\xa3\xc5\x81\xef\x23\x18\xef\xe0\x03\xd9\x42\xc9\x1b\x84\x7d\x75\xd3\x55\xcb\x26\x1a\x3a\x30\xb5\xb0\xfa\x25\x18\x73\xe6\x3c\x91\xff\x79\xce\xe3\x78\xe8\x07\xea\x95\x67\x30\xb7\x74\xe2\xb5\xcb\x9e\xa3\xbf\x09\xc6\xb3\x84\xb4\x3b\x6b\x02\xe6\xbe\xc8\x93\x9d\xd3\x5b\x77\x8c\xa5\xe0\xb8\x12\xd6\x93\x38\x7d\x83\x33\x55\xc2\x51\x73\x0a\x82\xbd\xe3\xfd\xa3\xee\x3b\x79\xd4\x11\x4a\x62\x4e\xdd\xc7\xd2\xd9\xe2\xb4\x6f\x50\xc3\x4c\x4e\x66\xd9\xf6\xe6\x55\xa4\x7c\xa1\x88\x37\xd3\x47\x60\x03\xa3\x08\x05\x23\xc5\x0d\x2e\xa9\x68\xe7\xa9\xc4\x47\x43\x02\x3e\xd5\x74\x26\xc5\xe0\x14\xe4\x7c\x41\x5b\x69\xa6\x75\x63\x4e\x4c\xb9\x71\xf0\x21\xb6\x48\x0e\xc5\x99\x74\xda\x73\xb2\x7e\xcc\x03\x4f\xa7\x17\x16\x6d\xc8\x90\x75\xdb\x15\xd4\xb9\x03\x93\xb8\x7a\xba\x49\x60\x6b\x25\x59\x6d\x9a\xd6\xd0\xd4\x3c\x25\xd3\x2d\x6e\x3e\x0a\x2d\x80\xe1\x2f\x18\x21\xc0\xe7\xe7\x95\x98\xee\x01\xbe\x52\x7e\x6b\x13\xa6\xb8\x24\xcd\xba\x91\x5a\x76\x90\x73\xcf\x3a\x2c\xce\xf0\x0d\x92\x48\x0b\x0b\x8d\x2c\xcf\xd3\x0c\xbe\x51\x58\xe7\x36\xd4\xb1\x83\x06\xf7\xde\x15\x68\x09\x22\xbd\x90\x59\x9c\x8e\xfc\x4e\xe4\xf0\xcb\x8d\x98\xb0\x51\x5e\x4c\x8a\x9c\xb4\xb2\x9d\xf8\xf7\xaf\x6d\x8b\x5d\x1b\x67\x86\x58\xd1\x8a\x7f\x76\x4a\x42\x9e\x2a\x17\x4d\x27\x08\x46\xf9\xff\x6c\x04\x0b\x8a\x40\x0c\x66\x71\x62\x28\xc7\x89\x80\x8f\x87\xf9\xf2\x1a\x09\xef\x18\xbe\x35\x55\x67\xc7\x12\x1c\x74\x7b\xc8\x14\x22\x8b\x5a\xdd\x5c\x83\x42\x30\x31\x05\x6b\xaa\x6d\xdd\x0c\x74\x7d\xab\xf8\xfa\x1a\x5b\x9f\x7d\xc5\x25\xc2\x4d\xa6\xca\x14\x65\x1b\xed\xbe\x64\x37\xab\x64\xb0\x03\xb7\x32\xaf\xb6\x78\x02\x92\x6c\x2c\x6d\xc5\x46\x52\x07\x39\x89\xf4\x8c\x32\x51\x01\xf9\xaf\x42\x2f\xef\xc4\xf9\xbd\x5f\xac\xac\x8b\xf6\x41\x5c\x54\x04\x7d\x25\x7c\x3c\x13\x13\x86\x06\x42\xaf\x7d\x28\xca\x4d\xe1\x90\x05\x9b\x9e\x0f\xeb\x93\xf3\xf3\xfc\x47\x2e\xbd\x5b\xf3\x51\xe7\xd5\xc3\xfc\xf4\xe4\xa6\x73\x54\xea\xa1\xe7\x83\xb3\x08\x00\xbe\x92\x1c\x99\x59\x86\x0a\x49\xf7\x40\x06\x9c\xff\x13\x93\x1e\x69\xe8\x48\x50\x6f\x05\x96\xcf\x48\xb7\xc7\x34\x70\x9b\x37\x1d\x37\x7f\x5e\xae\x89\x8d\x0d\x0a\x74\xc1\xa3\x37\x47\x5e\xb3\x4d\x27\x0e\xef\xa3\xa7\xf4\x6a\x32\x1e\xce\x9a\x17\x6c\x76\xd7\x0c\x05\xfd\xcc\x8d\xb5\x0a\x4c\xa2\x91\xe3\x67\x95\x22\xbc\x12\x7c\x75\x65\x6a\x7c\x75\xcb\x0f\xfc\xf6\x89\xba\x77\x6a\xb1\xe9\x13\xc9\xe0\x26\x65\x41\x4d\x49\xa6\xd3\x18\x64\x9d\x60\xa1\xfb\x90\x83\x8e\x52\xaf\xe3\xfd\x28\x92\x5d\x1f\xef\xf9\x28\x41\x07\x77\x67\xf2\xbe\x49\x60\x7c\x64\x1c\x0e\xd9\xd2\xc0\x38\x40\x27\x09\xb8\xe6\xc8\x31\x6e\x7d\x77\x09\xfe\xb9\x0c\xd6\x1d\xfe\x2a\x77\xb1\x4f\x84\x76\xa0\x36\x0d\x90\x1b\x87\xdf\x18\x91\xd6\x4e\x08\xe4\xef\x66\xac\xff\x7c\x46\xe2\x7b\x2b\x32\x51\x17\x31\xc5\x35\x4e\xb6\x7a\x70\x68\x1e\xf1\x45\x9c\xea\x6b\x47\xa4\xfd\x91\x97\x8e\x94\xc1\x8e\x06\xba\xc7\x46\x86\x84\x8e\xf0\x77\x71\x91\xc9\x06\xfe\xfb\x60\x1e\x30\x88\xe5\xe6\xc6\x28\xb7\x51\x4c\x65\x04\x2b\x10\x98\x80\xb5\xa2\x65\xdb\xea\x68\x0c\x69\x7a\x3f\xd2\xba\xb6\xc2\x87\xf2\xb1\xbc\x72\x5f\x9d\x1f\x78\x2c\x3f\x35\xa8\xb1\xd4\x48\x17\x35\xc3\xf0\xee\x39\x5b\x1a\xa3\x07\x1b\x8b\xf5\xac\xbe\x24\x38\x7a\x96\xd2\x40\x38\x0c\xa2\xca\x1d\x41\x15\x49\xf7\xe0\xc8\xf9\x94\xff\x2a\x22\xca\xc7\xbc\x92\x70\xce\x5e\x83\xdf\x72\x9e\x83\xdc\x2e\x4b\x2c\x6b\x04\x3f\xa1\x97\x8d\xca\x2e\xbd\x5f\x02\x60\xbe\xd7\xbb\xf2\x14\x64\xfe\x02\x4c\x9b\x66\xdd\x0b\x33\xfd\xdd\x80\xa8\xeb\x8e\xc3\xec\xc9\x24\x28\x5e\xbb\x43\x54\x00\x63\x23\x33\x19\x29\x7d\x34\xa6\x45\xe3\x92\x21\x27\x66\xb1\xf2\xf9\xcb\x1f\x1b\x45\x2c\x02\x36\xbb\xca\x7a\x14\x11\xf9\x99\x05\xc6\x85\x93\x51\xb6\x18\xe9\xed\x08\x90\x75\x45\x9f\xd1\x98\xf8\xa5\xe5\x8f\xdd\x80\xfc\xdf\xf9\xc3\xfe\x13\x1e\x36\x3a\xa3\xf2\x8b\x49\xc4\x6e\x28\x20\x38\x99\x04\x74\x88\xec\x77\x87\x70\x3e\xf7\xca\xc5\x19\x10\x27\x85\x63\x29\x87\x2b\x27\x6b\xb5\x16\xcd\xe7\x40\x9c\xac\xf0\xc6\xc9\x10\x14\x75\x58\x8a\xde\x3a\xef\xbc\xad\x4c\xb1\x38\x64\x01\x32\xc3\x22\x83\xfd\xc1\x07\xf7\xcc\x00\x30\xc4\x5d\x71\x56\xe3\x76\xd8\x27\x40\xd0\xe2\x5d\x5f\x2d\xfb\x99\x49\x96\x3e\x59\x04\x7a\x5a\x87\xcd\x9e\x8a\xe7\x40\x0e\x69\xac\x4a\x1d\xdc\x63\xa6\x11\x33\xbb\xb3\x66\x2e\x7e\x42\x7c\xae\xf2\x40\x80\x46\xd9\xcb\xf9\x88\x5f\xcf\x47\x8c\x63\x79\xa2\xba\x64\x36\x13\xe4\xed\xa5\x42\xfc\xf3\xc8\x1c\x26\xc4\xc3\xf2\x3b\xcb\xc3\xea\x41\x61\xfe\xa0\x20\x00\x7a\x89\x75\xef\x19\xef\x28\x23\x0a\x89\x57\x68\x31\xd0\x19\xe1\xb6\x7c\x4b\x9a\x27\x65\x17\xec\x59\xc8\xcd\x67\xd3\x6d\x0e\x1c\xc8\x90\x0f\x36\x52\x70\xf4\xdd\x85\x19\xc8\xc3\x47\x9c\x7c\x36\x0c\x47\x27\x64\x1b\x6e\x94\x0f\x58\xed\x97\x0b\x83\x38\x0b\x93\xc4\x71\xc0\x62\xd0\x22\xc0\xe6\x69\xa8\xe8\x5f\xec\x5e\x49\x1b\x56\x1d\x21\x9a\xe9\x14\xc9\xdf\x09\x65\x2a\xc1\x5c\x44\xf1\xb7\x6d\x1e\x61\x6a\x40\xf4\x77\xf7\xa6\x25\xa4\x81\x4b\xb1\xc3\x0d\x55\x16\x02\xa6\x6b\x0f\x77\x51\x73\x1e\x6e\xc6\x5d\x0f\xf7\x98\xc9\x3a\xd8\x57\xde\x9a\x47\x27\x64\xc1\xff\xc8\x0c\xe8\xa4\x7a\x20\x93\xc9\x04\xfe\xdd\x0d\x47\xfd\x99\xe7\xb6\xf1\xe4\x3f\x0b\x12\xae\xf8\xff\xf4\x56\x6c\x93\x41\xf1\x01\xda\x97\xef\x97\x93\x65\x33\xd4\xfb\xc9\x47\x5a\x11\x0b\x40\x20\x0e\xbf\x43\x56\x90\xa1\x8d\xcc\x88\x55\x2e\x61\x46\x63\x88\xc6\xce\xe6\x74\x2f\xd1\xff\xc1\x83\xe1\x0f\x0f\xa2\x18\x5e\x32\xba\x60\xa8\x72\x65\x0f\xc5\x17\x88\x86\xf2\x2a\x36\x18\x92\x4c\x75\x28\x52\x6d\x1c\x8a\x12\xe6\x0c\x60\xd9\x4f\xfb\x3a\x9e\xb2\xec\x12\xda\x1c\x1a\x69\xf9\x50\x96\xfb\xab\x73\x60\xb0\x24\x0f\x63\x21\xd3\x2f\x77\x8f\xb1\x10\x32\xc0\xa9\xa5\x06\xc3\xa8\x4b\x21\x45\x9a\xc0\x22\x63\xe3\x07\x7a\xea\x40\x50\xd3\x25\x2a\xc6\xd8\x46\x3e\xe9\x94\x1b\xf2\xbf\x96\xfe\x3b\x38\x8d\x4b\x16\xe2\x4b\xce\xaf\x7a\x91\x4d\x0f\x89\xa8\xe0\x1f\x3e\xb9\xc5\xe8\xf8\x21\xbb\xbb\x58\x8d\x06\x92\xdc\xf4\x39\x18\x2c\x72\x9b\x0c\x98\x15\x9e\x22\x05\x64\x23\xcc\xc8\x7d\x21\xc9\x1f\xd2\x48\x08\xc2\x6f\x68\xd0\xd9\x57\x79\x1d\x39\xe7\x07\xac\xd2\xb0\xee\x36\x5b\x14\x0d\x64\xde\x29\xb2\x07\x1e\xc1\x8f\x76\x6d\x55\x84\x84\x14\xc6\x1b\x5a\x25\xb6\x70\x16\x03\x3e\xb5\x4f\x17\x59\x83\x06\x70\x0d\xf2\x3f\x03\x3d\x7f\x6f\xf5\x3b\xb8\xde\x33\x60\x72\x19\x74\x82\x2f\xfe\x20\x56\xa2\x86\x90\x17\x1b\xd0\x47\xeb\x66\x97\xb9\x7e\x84\xa6\x43\xda\x7d\xc0\x52\xa6\x37\xd8\x33\x22\x0c\x54\x84\x85\xa0\xfc\xa1\x1b\xbc\x3f\x02\x9c\xe6\x18\xb2\x31\x42\xf7\xa9\x40\x6b\x03\xe3\x2f\x82\x76\xc8\x39\x1e\x4d\x4f\x22\x98\xc1\xe3\xd0\x1c\x74\x95\x27\x71\x82\x1d\x47\xa1\x25\xeb\x14\x85\x24\xf0\x31\x28\x26\x44\x1b\xb3\x0a\xbf\x6a\xc9\x02\x0e\xa2\x9e\x74\xc7\x96\x5e\x38\x03\xa7\x86\x24\x4e\x42\x36\x09\xeb\xea\xc4\x6d\x58\x29\xfe\x33\x90\xef\x63\x48\x4d\xfe\x1a\x4c\x86\xfc\x3c\xa8\x0f\x37\xa4\xc6\xc1\x60\x90\x62\xaa\x03\x88\x27\xbc\x7c\xea\x62\x6a\x0a\x29\x42\x8e\x07\x19\x92\x43\x8c\xab\x06\x26\xd6\x91\xae\x81\xfe\x8b\xb5\x62\x5d\xd3\x36\xf6\xc6\x9f\x0c\x7a\x30\x52\xbc\x99\x79\xc2\x14\xaa\xde\x0d\xaa\xaa\x9d\x9d\x93\x5e\xf5\x9c\x35\x7a\x4c\x5d\xfc\x0b\x29\x3f\xe2\x3d\xf4\xc4\x67\x1d\xd1\x75\x1a\xbb\xfb\x13\x09\x6b\x78\x72\xfd\xf1\xb9\x82\xb2\x30\x42\x62\x7a\x74\x78\xc1\xdb\xef\x1b\x6d\x37\xed\x94\x3e\x74\xc6\xfa\xa3\xb4\xdf\x20\x08\x5a\x64\x83\x98\x1e\x92\x43\x31\xbb\x4f\xd6\x4a\xd1\xa3\x21\x44\xa9\x27\x28\x53\x0d\xc0\xbb\x34\xd4\xb1\x74\x05\xad\x45\xff\xe6\x24\xa5\xaf\x1f\xf8\xa6\x83\x55\xf0\x1d\x64\x86\x11\x50\xd5\x23\x1c\x9f\x24\x6b\xce\xaf\x48\x70\xb6\x5d\x67\x12\x0d\xe3\x9f\x49\xb5\x6d\x78\x12\x04\x69\x18\xc5\x05\xc7\x00\x26\x2b\x98\x5e\x0d\xd6\xc5\x74\x73\x17\x82\x97\x44\x7d\x78\x40\x6c\xf1\x20\x14\xf5\x5e\x3d\x9e\xb7\x7e\x91\xc9\x1d\x67\x63\x30\x17\xe8\x7b\xd0\x7e\xea\xa0\x14\x19\x69\x7d\xdd\xa4\xac\xd9\x23\xb2\x28\x7e\xb3\x9d\x37\xbe\x26\xe1\x4b\xa4\x4c\x86\x2b\x03\x27\x40\xf4\x41\xd2\x39\xd0\x5c\xf1\x37\x2b\x13\xee\xa0\xe7\x79\x16\x01\x56\x65\x41\xd0\x0b\x67\xc4\xa0\x74\x0c\xdd\x05\xa7\x77\x0c\x06\xc9\x85\x61\xf8\x08\x72\x7b\xab\xbc\x8e\x5b\xd4\xdb\x64\x79\x3c\x7e\x50\x92\xfa\x3d\x42\x8f\xbc\x9c\xe2\x26\x86\xe0\xa9\x1c\x86\x20\x9d\xec\x9f\x22\xd4\xab\x58\xe5\x0c\x01\xe5\xbe\xca\x3f\xd1\x2f\x11\xc1\x05\x24\xee\xc7\xaa\x44\x16\x43\x4f\x1e\x04\x6d\x80\x95\x68\xc3\xca\xd3\x42\x3c\x8e\xfc\xb7\xcf\xab\xd9\x84\xac\x79\xc7\x97\x54\x8e\xe0\x03\x2c\x47\x52\x63\x2a\xd6\x6c\xbd\xd2\x90\xd0\xe5\x33\x36\x9b\x83\x2d\xb9\x74\x41\x34\x3a\xdf\xd4\x6c\x82\x7e\x9c\xdf\x86\x73\x39\xea\xd3\x37\x83\x6a\xe5\x3f\x11\x69\xae\xef\x8d\x8c\x8e\x27\xa1\xaa\x32\xbb\x2a\x73\x11\xe4\x4f\xf2\xfd\x3a\x48\xed\x81\x98\xdd\x45\x3b\x4f\x3d\x15\xd0\xaf\x71\xf0\x85\x41\xcc\x93\xd8\x8c\x94\xc4\xf8\x10\x9f\x27\x4d\xb8\x53\x3f\xea\xf9\xcd\x69\x0f\x5a\x4f\x83\xca\x38\x07\xdf\xa3\xb2\xf5\xfb\x7c\xf4\x2c\x17\x2e\xa5\xf7\x79\x09\xf2\x42\x66\xb4\xf4\x08\xee\x0d\xf6\xc3\xeb\x0a\x42\x44\x6b\x77\x49\x74\x90\x57\xb2\x8e\x48\xe4\x82\x8d\xee\xb1\xfe\x36\xb9\x12\x0c\x26\xc7\x70\x9a\xf5\x64\xc8\x4a\x82\x94\x1c\x33\xb4\xeb\xc0\x39\x5a\xa1\xf5\xc9\x72\x3c\x81\x48\x6c\x13\xe3\xe2\xc1\x58\xf8\xd8\x30\x13\x66\x09\xf8\xa2\xeb\xc2\x99\x1f\x15\xba\x01\x9c\x24\x44\x87\x20\x92\xe0\x8c\x70\x4e\xc8\xd8\xbb\x54\x55\xf2\x78\xc2\x29\x4f\x38\xe8\x63\x01\x62\x69\xcf\x61\x08\x1e\xc8\x1f\x8d\xe3\x11\xdf\x60\xf2\xd8\x32\x36\x6d\x7c\x14\xea\x8c\xd2\xb6\x8b\xa5\x92\xf4\xbd\x88\x72\x2a\x90\x9e\xe3\xcf\x25\x7a\x05\xa0\x07\xb1\xa9\x39\x63\xa4\x5e\x4b\x20\x96\xce\x62\xa9\x5e\x26\xc2\x7a\x7a\x9b\xe6\x1d\xfa\x2d\x72\x0a\xf5\x6e\x13\x02\x45\x82\x1c\x12\x5f\x81\x98\x34\xa5\xfa\x06\x9a\x48\xcd\x7a\xfa\x14\x6c\x60\xce\x0f\xf9\xe2\xf8\xd9\x43\xe7\x2d\x08\x36\xbb\x23\x0e\xe8\x24\x30\xd9\xc7\x02\x56\x77\xab\x8f\x77\x42\x49\x96\xc1\x28\x16\x92\x2d\xa0\x95\x2c\xa4\x29\xbb\x35\x5c\x18\x20\xaf\xd7\x7d\xca\x2a\x06\xd2\xbf\x8e\xb6\x2e\x02\xc2\x49\xcd\x71\x3a\x67\x8f\x38\x85\x1a\xe3\xe4\xa4\x20\x23\xc0\x83\xe9\x6e\xe0\xa1\x5c\x58\xaa\x1e\x9c\xab\x75\xf7\xaa\x99\x4f\x77\x2b\x56\xa7\xbb\x1f\x6d\x48\xef\xec\x83\x26\x3b\x5c\x48\x17\x76\x68\xcc\x22\x4a\xbb\xd5\x16\xbb\xe3\x5b\x29\x71\xd0\x1d\x9f\x61\x12\xdd\xe3\xbd\x32\x7c\xcc\x79\x25\xc5\xd3\x47\x8a\x60\xfd\xa8\x3e\x49\x59\xd8\x52\xa8\x9c\xd8\x85\xbc\x7c\xe8\x40\x82\x3e\x92\xdf\x5f\x0b\x06\x75\x7d\xda\xc8\xe5\xe1\xf6\xb9\x89\x4d\x12\xa1\x30\x35\xe0\x46\x06\x97\xae\xf1\x84\xd9\x8b\xfa\xea\xa4\xf6\x95\x15\x51\x4c\x9e\x2d\x40\xc8\x09\xc0\x35\x39\x04\x6e\x3b\xa3\x7a\x56\x01\x91\xc4\x3b\xd6\x3d\x25\x59\x89\x86\x4a\x43\x74\x0e\x74\x07\x27\xd8\x9d\xd8\x30\x6c\xa2\x24\xbe\xcb\xfa\x0e\x0e\xc7\xa0\x02\xe9\x68\x36\x76\x9e\x17\x4e\x0e\x47\x9a\x94\x56\x4a\x4e\xc1\xe3\xea\xc5\x7e\xc9\x4c\x87\xae\x4d\x82\xc0\x37\x39\x1f\x8c\xe3\x35\xcc\x77\x5a\xc9\x85\xd0\x55\xe5\x55\x00\x60\x6e\xc4\x9d\x4b\x7e\x88\x89\xb1\x2e\xa2\x43\xed\xaa\x88\xae\xba\x3a\x71\x8a\x62\x20\xf5\xba\x02\x02\xac\xf9\x74\x6a\x9e\xb7\xe0\x50\x44\x36\x3a\x6f\x72\x48\xa4\xe8\xec\xc8\x10\x5a\x45\x11\x79\x8b\xe0\xbb\x43\x0b\xe3\x7a\x44\xb7\x14\xda\x1c\x06\xb6\xde\x8d\x58\xfb\x78\xd4\x9c\x96\xf4\x19\xf8\x48\x16\x7b\x3b\xa4\xf8\x2b\x92\x22\xb1\x81\xf0\x94\x5a\x59\x57\xb4\x0e\xdd\x95\x08\x86\x75\x22\x48\x71\x68\xba\x92\xb1\x37\xc0\xe2\x8a\x76\x68\xac\x67\xb0\x49\x5a\xaf\xce\x83\x7e\x41\x03\x5d\x89\x98\x3b\xb0\x2a\xfb\x9e\x99\x0e\x97\x6e\xe6\xc1\x59\x46\x54\x97\x25\x1a\x63\xe0\x0a\x16\xaa\x2e\xa8\x0b\x63\xee\xe6\x94\x92\x24\x66\x3c\x83\x5a\x30\x8b\xfd\x11\x54\x87\x3c\xb8\xb1\xcc\x23\x46\xbe\xe4\x1f\x12\x10\x13\x2a\x12\x07\x04\xf2\x36\x89\xd8\x35\x44\x1b\x91\x3d\x20\xc2\x4c\x1b\xd7\x07\x77\xee\x74\x79\xe5\x15\x97\x22\x1a\xc7\xb2\x34\x26\xc8\x7b\xd3\x25\xe7\xf0\xc0\x74\xf6\x33\x31\x10\x66\xfa\xd8\xe0\xf4\x0e\x02\xc8\x1b\x89\x24\x34\xfd\x3a\x10\x9b\x68\xf7\xa4\xfb\x4b\x9f\x9b\xc4\x88\x1f\x31\x16\x7e\xc4\xc7\x8b\x29\x4c\x50\x46\x82\x1e\xf2\x0a\xfa\xc3\x4b\x14\xb5\xa9\x25\x79\x18\x9c\x52\x50\x38\x5e\x30\xc7\xb2\xc8\x1a\xc5\x17\x00\x14\xff\xf6\x20\x16\x00\x2c\xc8\xae\x29\x98\x24\x45\x9f\x01\x38\x89\x83\x12\x6f\xfc\x0c\x18\xf4\x8f\x91\x03\x05\x76\xc8\x60\xdb\x6e\x24\x4f\x5d\x92\x94\x06\xa8\x24\xdb\x7d\x1c\xdd\xcd\xd2\xe6\x2d\x97\x50\x9f\xb6\xe0\x93\xec\x74\x8e\x4d\xc4\x93\x9b\x6a\x18\x3c\x41\x5d\x62\x42\x17\xca\xe9\xe6\xb1\xb4\x4e\xad\x1c\x4a\x90\x42\x8a\x74\x72\xe9\xf9\x5a\xc1\x4d\xc4\x5f\x17\x3e\x2d\x79\x23\xbb\xc4\x06\x9d\xc8\xae\xdf\xa5\x29\xd8\x40\x13\x48\x5b\x74\xde\x81\x6d\xc8\x8c\x09\x3e\xb6\xfe\x79\xf3\xa3\x4a\x5a\x67\xc0\x57\x26\x1d\x93\xf4\xee\x18\xa8\xe7\xb4\x91\xa2\x27\x7c\x25\x34\x2b\x87\x37\x79\x8e\xd2\xad\xf5\xcb\x74\x3f\xfc\xcb\xc0\xfb\x6d\x5e\x53\x84\xa0\xd0\xd0\x01\x45\xa4\x76\xb1\xdf\x49\x71\xce\xe3\x2e\xdf\xfb\xbf\xa0\x80\x74\x10\x7c\x89\xd6\x0d\x86\x13\x9b\x64\x8f\x1b\x11\xfa\xf7\x2b\x76\x43\x86\xd5\x2b\x7c\x3c\x83\x17\x32\x66\xd2\x66\xb5\x9b\xe5\x43\xe6\x43\xf9\x10\xcc\x0e\xb9\x69\xcb\x03\x25\x8a\x3e\x9b\x21\xf2\x26\x67\xa3\xf3\xe3\x6f\x84\xd2\x1a\xf7\x65\x37\xe7\x4c\x44\x88\xbe\x5f\x69\x9b\x38\xaf\x73\x01\xfd\x55\x84\x8b\xee\x3a\xe5\xd9\x26\x0d\x50\xee\xca\x65\x03\xc7\xd8\xf0\xe1\x7f\x7b\xb6\x74\xc4\x19\xb3\x71\xa4\x75\x2d\x07\x79\x0b\xa1\xe3\xd3\xbb\x10\x30\x28\x47\xab\xba\xba\xd4\xe8\x02\x80\xe6\x40\xc1\xeb\xb9\xbc\x8a\xbb\x4c\xdc\xb0\x61\x86\x9a\x41\x5a\x20\x56\xe3\xda\xc9\x8a\x0f\x4c\xd8\xd2\xe7\x11\x9a\x13\x04\x96\x0b\x58\x89\x68\xfc\xa5\xe5\x74\x8e\x2d\x24\x7d\x7d\x78\x63\x2d\xfd\x2b\x2d\x71\x3c\x72\x15\x98\xee\xeb\x51\x3c\xda\x5b\x44\x1f\x96\x3c\xa0\x55\x1c\x94\x20\xdb\x1a\x08\xbb\xd2\x18\x2b\xbb\xe6\x8b\x46\x26\x59\xe1\x0d\xe9\xf1\x95\x20\x9d\x3c\x79\xde\xd9\x49\x95\x2b\x53\xf8\x93\x02\x36\x92\xdd\xb3\x9f\xb5\x0f\x1b\xc8\x1e\x11\xdf\x5c\x2f\xf6\xd0\x3e\x7b\xa4\x6e\xea\x4e\x05\x65\x9a\x81\x76\x93\x68\xd2\x90\x0f\x5f\xa9\x13\x31\x66\xc7\xa9\x28\x32\x62\xb9\x9d\x7d\x02\x03\x79\x1a\xfb\x09\xa7\xe0\x29\x69\x81\xfc\xfb\x71\x15\x80\xef\x2d\xa3\xff\x7b\xaf\xd1\xf4\xbf\x37\x03\x6e\xbf\xf7\xcc\x15\x92\xef\x6d\x83\xe2\x39\xa8\xf6\x5f\x3a\x4a\xad\x50\x7a\xfd\xb7\x1e\xe2\xb4\xfa\x52\x94\x0c\x21\x72\x22\xa4\x34\x34\xa9\xe4\x27\xf2\xe5\x6c\xe8\x8b\x0e\xda\x7d\xa3\x86\xfc\x88\x7c\x90\xfa\xfe\x1b\x91\x12\x5f\x4a\x23\x7e\xf3\xc2\xa0\xdd\x2f\x38\xfc\x58\x0e\x9c\x1f\x7c\xad\x9f\x0f\x52\xcb\x97\x4d\x40\x9d\x15\xd3\x1a\xcf\xd7\x9b\xe1\x17\xd9\x4b\x41\x8b\xb9\xd3\x50\x05\x41\x26\x05\x9b\xbf\xd6\xdf\x89\xc0\xf6\x0b\xba\x5c\x82\x75\x47\x52\x98\xc3\x60\xea\x4c\x36\x89\x7d\x30\x18\x13\x1f\x24\xf7\xd9\x40\xfb\xd5\xe5\xdc\x0e\x28\x82\xb8\xda\x87\x79\xd2\x9f\xdb\xab\x0f\xf6\xcc\x89\x79\x35\x9f\x08\xde\xf9\x38\xd9\xf8\x49\x34\x7b\x77\xe8\x24\x9a\x2c\x19\xeb\xfd\x51\xf7\xfb\xfe\xfc\xb8\x11\x83\x63\xf0\x88\xf8\xc8\xb7\xd5\xa2\xf0\xea\x58\xd2\xfb\xb2\x54\xbc\xdf\xdb\x6c\x28\xd1\x59\x56\x91\x6a\xd6\xa5\x17\x5f\xa3\x35\x19\xb2\x27\xc2\x7e\x92\xd7\xe3\x5d\x17\x8e\x4e\xf0\xb1\x86\x50\xe1\x9b\x4b\xd3\x44\xee\x3d\xb3\x32\x56\x17\xc1\xa6\x65\x36\x39\x09\x22\x1b\xf3\x01\x20\xa9\xec\x0c\x85\x62\xfa\x1b\xcb\xd8\xb7\xb8\x24\x0f\x45\xb0\xbc\x8b\x07\x23\xbc\x0b\x93\xa8\xde\x3c\xe7\xa6\x65\x35\xe8\x0f\x8a\x84\x32\x94\x08\x88\xfa\x80\x24\x61\x2c\xc8\x76\xd0\xf5\xe0\xa4\x0b\x42\xcb\xa0\xed\xb4\x96\xdf\xa0\x59\x86\xa5\xe1\x9f\xbd\xe2\x5b\xdb\x9c\x75\x2b\x39\x88\x1e\xed\xe1\xbe\xe9\x85\x06\x7c\xca\x9c\x04\xd6\x33\x06\x1b\xa6\xe6\xb3\xc0\xa2\xd6\x04\x1b\xe6\xc4\x85\x4a\xe0\xf6\x8c\x7c\xf1\x4c\x84\x9a\x86\x49\x6f\x39\x9b\x8d\x15\x67\xcb\xba\x61\x2c\x9f\x05\x89\xa6\x56\x3c\xdf\xe8\x2c\x82\x1a\x34\x37\x0a\x10\x90\x5e\xa2\xf3\xd0\xee\x9e\x1c\x9b\xe5\x74\x65\xb7\x83\x1b\xdb\x8f\x5d\x53\x89\x49\x06\x94\x6c\x06\xa4\xdf\xf4\x33\xe8\xf1\x79\xa2\xf9\xf0\x7e\xd7\x00\x0f\xa7\x0a\xd2\x5b\x99\xc2\xef\x14\x1a\xd0\xef\xf4\x7b\xed\xe9\xf8\x66\xba\x53\xdf\x18\x08\xff\x09\xe8\xde\x6c\x48\xa4\x7d\xfe\x4e\x62\xd3\x7a\x83\xc8\x24\x4e\xd3\xe8\x2b\x91\xe1\x52\x88\x78\xdf\x50\xb2\x60\xa5\x13\xe8\x5d\x37\x21\x57\xfb\x61\xff\x6d\x9b\x76\x3b\x07\xaf\xbc\xa8\x4f\x76\xa4\x9f\x89\x11\xe4\x9d\x34\xc1\x44\xb4\x40\x10\x77\x16\x5e\xb6\xd0\xb1\xf5\x4e\xf3\x6e\x13\x38\x2e\x45\xda\xc6\x12\x87\xc9\x3c\x7c\x83\xdb\xfa\xb9\xc9\xac\x04\xf1\x26\x0f\x1c\x86\x7a\xef\xa7\xa0\x78\x22\x25\x8e\xf2\xba\x9d\xa0\xc9\xad\xc9\xd7\x3d\x41\x19\x4c\x04\x9c\x27\xe5\x1b\x5e\x9e\xf0\xfb\x24\x62\xde\xd7\xab\x22\x1e\xdf\x01\x95\x1c\x5f\xb0\x9e\x9c\x2a\xb2\x44\x26\x3b\xf8\xb1\x05\xce\x3e\x35\xf2\xcd\x4c\x3a\x4d\xb5\x14\x77\x90\x4e\xe9\xbf\x60\xe1\x74\x4e\x4f\x64\xc6\x93\xe7\xb2\x64\xa9\xbe\xbf\xca\xa0\x3c\x95\x57\xe9\xdd\x8f\xf1\x6a\x81\xc3\x2f\x38\xc9\x5e\x64\xd7\x94\x24\x07\x46\xeb\xe0\xde\xb4\xf7\x3a\x2d\x62\xd7\x3c\xb8\xb0\xfc\x72\x05\xb7\x2c\xd4\x0e\xc4\xa4\x9f\xe4\x5f\x4e\xce\xf9\x9f\x93\x6f\xd2\x12\x78\x71\x92\xf2\x42\x2b\x19\xf8\x3d\xbd\xe0\xf5\xf0\x51\xf0\x05\x17\xcc\x76\x05\xbb\xe6\x79\xaf\xf9\x68\x1b\xfd\x7c\x7f\xb8\xd6\xfe\x82\xfa\x49\xbe\xdf\xf1\x2f\xb0\x94\x05\xaa\xdf\x38\x24\x07\x75\x27\x94\xa7\x96\x67\xec\xc6\x32\x12\xd2\x8b\xdb\x56\xfe\xfd\xe7\xf8\xbe\x53\x9a\xda\xd6\x5b\x73\x75\x6e\xcd\x9f\xdf\x86\x82\xbb\x0d\x9b\x0d\x44\x9a\x38\x60\x46\x8d\x3a\x9b\x27\xff\xbd\x90\xa3\x13\xb1\x10\x34\x97\x0d\xf7\x4e\xf6\xfe\x9f\x58\x3c\xfb\x2a\x34\x24\x22\xd9\x4e\xf7\x61\x0f\xd0\x73\xd1\x6e\xef\x33\xb3\xb4\x65\xef\x0d\x51\xc1\x01\x55\x32\x50\xda\x13\x21\xfa\x16\x89\x79\x8f\x63\x78\xc0\x6d\x2a\xcb\xd5\x83\x9b\xcc\x10\xd7\xe7\xfc\xba\xad\x6f\x80\xdc\x99\x9f\x55\x94\xa0\xbe\xfe\x70\x7d\x12\x43\x48\xcc\xe6\xdc\xdc\x89\x75\xdd\x0c\x52\xb9\xee\x53\x93\xb6\xeb\xd6\xe4\x0e\x64\xa0\x31\x1b\x05\x8e\x9d\x1e\x02\xe1\x27\xbf\x77\x1a\xcb\xd7\xfd\x14\x7d\xe8\xe8\x33\x99\x8b\xe2\x3c\xd7\x2d\xba\x50\xb6\x42\x27\x26\x94\xb1\x77\x9d\xb7\xfd\xb9\xf3\xcc\x4a\x1b\x42\xdd\x3e\xf5\xfc\xdc\xe0\x32\x3d\xca\x8b\xeb\x45\x86\xf6\xbd\x04\x00\x87\x57\xe6\xc6\xfa\x3b\x94\xbe\x3e\x07\xfe\x8c\x0c\x71\x2c\x07\xe8\x48\x3a\x9a\x5f\x85\xb6\xdc\x15\xca\x6f\xd7\x91\x3c\xc7\x97\xd0\x6d\x23\x2b\x9d\xc9\x12\x6b\x0f\xfe\xb3\x7a\xb1\x09\x5f\x2e\xc0\xa1\x10\x2a\x6c\x68\xe9\xe8\x92\x5f\x1f\xd9\x26\x0b\x4b\x4e\xc4\xcc\xde\x6d\x2a\x7d\x57\xa9\x93\x75\x90\xde\x26\xc4\xa5\x74\x81\x2d\xee\x24\x98\xc2\xcd\x73\x05\x03\xe5\xe5\xe1\x15\x0e\x98\x5a\x82\x92\xf7\x5d\xbc\x7f\xb8\x20\x68\xce\x43\x21\x5b\x14\xcc\xa2\x47\x8d\xd8\x42\xa8\x91\x6c\xa7\xd6\xf7\xaf\xa6\x44\x8e\x04\x4b\xed\x2a\xd1\x8a\x00\xff\x13\x19\xa9\x4e\x49\x82\x19\xb3\xd3\x2f\x95\xc1\x4e\xba\xc4\x6c\xc0\xf0\x20\x92\xd1\x3b\x22\x40\xd0\x9e\x6d\xce\xe5\xe6\x4f\x5b\x91\x41\xfe\x26\x1b\x67\xde\x47\x1d\x86\x5b\x67\x2d\xf3\xaa\x80\x3f\x43\x34\xb2\x2e\x0f\xdd\x28\xfc\x85\x72\xab\xc1\x5f\xaa\x9f\x26\xb9\xa3\x6c\xb2\x90\x9e\x74\x5b\x5c\x50\xb1\x3b\x09\xa2\x26\x98\xd1\x4d\xca\x12\xb6\x8d\x9d\x3f\xd9\x82\x3d\x55\xaf\x88\x3c\xcb\x56\x88\xfe\x35\x31\x4c\xef\x4a\xd2\x75\x82\x77\x34\x14\xef\x2e\x9b\x6b\x7f\x18\xb0\x03\xc8\xcf\x02\x74\x65\x5e\x72\x31\xe3\xb2\x67\x72\x9e\x81\xbc\xe8\x62\x55\x0d\xbc\xa7\xce\xab\xf5\xe5\xba\x88\x95\xce\x3b\xf7\xa5\x61\x6b\xa5\x2f\x0b\x9d\x1f\x91\x40\x7e\x16\x11\xcc\x7d\x44\x29\x66\x96\x5e\xe3\x40\x9d\x64\x61\x9d\xd6\x57\x9e\x8d\xc9\x94\x5c\x5e\x36\xd6\x1f\x01\xfc\xb5\x19\x48\xdb\x27\x40\x0e\xb6\xd3\xeb\x5d\x6f\x9e\x43\x5c\x5e\x6f\x11\x30\x9c\x91\xb3\x73\xde\x47\x80\x6d\xe8\x16\xff\x32\x48\x64\x7a\x92\x01\x91\xa4\xa6\x89\xdc\xa5\xe8\xd4\x93\xf8\x4d\xc9\xe1\x76\x4f\x91\x48\x73\xde\x20\xe5\x0f\x79\x86\xd3\x7b\x11\x82\x9d\x1c\xa4\x66\x6b\x07\x43\xe9\xbd\x6a\x9f\xcd\xce\x9f\xcc\x86\x20\x11\xf9\x29\xa4\x59\xaf\xc3\xc6\xca\x78\x89\x14\x09\x29\x50\xdf\xaf\x7e\x94\x6e\x27\x57\xbb\xa0\xad\xc6\x39\x38\xf0\xa3\xce\x41\x0c\x5a\x19\x93\xe2\xae\x20\x9d\x14\xbc\x08\x1f\xf1\xd6\xf8\x56\x8b\xfc\x06\x7b\x29\x23\xb2\x0d\x3d\xc5\x03\x5a\x9f\xba\xa5\x0a\x37\xdc\x22\xd8\x28\x58\x6b\xd0\x02\x3b\x0c\x33\xce\x37\x82\xbf\xd4\xe0\x20\x5e\xd8\xab\x8a\x7d\xcf\x49\x50\x83\x0e\x35\x2f\x24\x29\x2d\xc7\x24\x6e\x53\x30\x86\x10\x59\x33\x88\xf3\x23\x32\x22\x60\xf0\x7f\x42\xe5\x82\xf1\x9b\xa0\x02\xe2\x63\xc5\x12\xd0\x25\x12\xd5\xb2\x35\x2e\xbf\xeb\x8f\x99\xe9\x1b\x0a\x03\x3f\x9d\x4e\xf8\x78\xd3\xff\x80\x2d\xf1\xfa\xd9\x17\x78\x90\x1f\xd2\xbe\xbb\xf1\x4f\x52\x0d\x62\x31\x4e\x5e\xc0\xac\x7a\x55\xb9\x49\x11\x43\xbf\x6a\x8d\xe3\x9e\x99\x8f\x3f\x89\x60\xee\x32\x83\x6d\x0b\x8a\x0c\xdb\x9a\xb6\xc2\xb1\xc6\x70\x56\x1c\x97\xc1\xe4\x8f\xe6\x10\x8b\x1d\xc8\x97\x48\x80\x2a\xed\x28\x50\x77\x6d\x4f\x31\xa7\x3a\xa3\xd1\x22\xd8\xb8\x65\xf7\x43\x5d\x0b\xd0\x16\xe4\xaa\x62\xd9\xdc\xcb\xab\x11\xb1\x26\x96\x66\x6a\x68\x0f\x83\xee\x01\xa4\x54\xed\x54\xac\x6f\x02\xfe\x2b\xfb\x9b\x26\x14\x95\xe0\xce\xe4\x0c\x04\xa5\xe8\x21\x81\xe8\x26\x10\xdf\xfe\x8f\x93\xf5\x9a\x35\xa3\x3b\xeb\xe9\xbd\xe9\x29\x19\xa7\xb3\x56\x2d\xc9\x9e\x1e\x3d\xe4\xcf\xa3\x32\x31\xfc\x24\x67\x89\x15\x3c\x9b\x07\x92\xfa\x53\xad\x43\xcb\x31\x3b\xab\x1c\x14\x67\xed\xd8\x6d\xac\x4c\x7d\xb5\x32\x24\x07\xce\xb5\x5c\xf3\x83\xc0\x2b\xdd\x42\xa2\xa1\xaa\x27\x90\xb7\x86\x74\x43\x0b\x83\xea\xcf\x67\x15\x8f\xcc\xa9\xf4\x39\xc2\xae\x11\x3b\x3f\x33\x3f\xe5\x27\x47\x15\x2b\xc7\x42\x76\xaa\xb3\x90\x95\xe2\x2c\x7f\xb8\x9f\x83\x12\xec\x2c\xe2\xc9\xa5\xea\xd0\x69\xef\xa6\xa7\x00\x1a\x74\x15\x7b\xd1\x9f\xae\x7b\x1c\xbd\x8a\x66\xd6\xec\x04\x9a\xc8\xa4\x52\xd5\xcc\xf0\x2c\x41\xe0\x59\xf2\xf4\xd6\x94\xf3\x2c\x43\xf0\xb0\x0e\x9c\x18\x9c\xe0\x82\x15\xdd\xe9\xbd\xaa\x8b\x9a\x6f\x2e\x1d\x39\x96\xb6\x26\x16\xc9\x3a\x96\xfb\xe5\xee\xcf\x13\x69\x3b\x1f\x02\xe4\xd4\xe8\x2d\xfb\xc2\x73\xa3\x81\x01\x69\x54\xfb\xea\xb0\xd0\x2c\x4a\x03\xc3\xe3\x21\x6a\xd6\xd2\x58\x35\xe7\x88\x1b\x3c\x83\x74\x73\xce\x22\x79\xcd\x20\x81\x62\xed\xf2\xd2\x7a\xc5\x39\xc7\x2f\xd5\x15\xce\xae\x9d\x2c\xb4\x6b\x42\x87\xf5\x79\xdc\x31\xa7\x35\xe7\x6f\xfd\xd9\x65\x20\xff\x7e\xd9\x3f\x82\xcb\x59\x5e\xe6\x73\x14\xcb\xd5\xc9\x34\x9c\x33\xff\x8b\x8e\xc3\x1e\xf0\x47\x25\x59\x4b\xf3\xa5\x96\x4a\x8d\x9d\x33\x8b\x6b\x39\xc7\x97\x8c\x53\x29\xba\xcd\xf0\x40\x79\x66\xb0\x2f\x42\xfa\xd0\xe1\x32\xd4\x35\xd6\x38\xce\x0c\xb6\x5c\xf5\x25\x39\xe8\x98\xa1\x32\xc5\x5c\x82\xb3\x09\xab\x9e\x66\x1e\xfb\x47\x83\x05\x7a\x5e\x49\x7c\x9f\x99\xf1\x7d\x67\x0e\x85\x22\x27\xb7\x4a\x07\xa9\x3e\x8f\xaa\xfb\x66\xa0\x8a\xa3\x02\xc6\xab\x24\x78\x04\xd7\x68\x1b\x74\x9d\x8c\x35\xb8\x58\xef\xb5\x51\x8d\xde\x12\xd1\x01\xec\x23\xa7\xbf\x6d\x10\x1f\x25\x37\x1a\xd2\x83\xce\x33\x47\x76\x6b\x8b\x7e\x5b\x39\x73\xd6\x86\x9d\xf4\x2b\xf8\xe3\x5d\x1d\xa3\xa6\x22\x5d\x72\x02\x56\x09\xda\xf8\x42\x65\x1b\x27\x20\x6c\x79\x05\x9d\xea\x5a\xe8\x22\x70\xbe\x55\x32\x83\x3b\xd5\x62\x3c\x01\xa8\xf0\x9c\x8d\xb2\x75\x09\xba\x7d\x60\x9b\x52\xff\xf8\x59\x39\x3d\x73\x34\xb6\x9d\xa0\xcb\x21\x85\xad\x35\xd8\x6f\xec\xce\xe2\xba\x04\xb4\xf9\x78\x3b\x79\x70\x90\xe3\xd1\xec\x6d\x6f\x6a\x07\xa7\xc4\xea\xc1\x2b\x78\x15\x11\x22\xf7\xd6\x34\xe9\xf1\x3a\xed\x6a\xa1\x17\x71\x42\x45\x94\xe4\xa3\xf1\x82\xcd\x70\x9c\xb8\x00\x7c\xa6\xfb\xc5\xd0\xe7\x33\x18\xce\xd1\x76\xb5\xa8\x7a\x8a\x9c\x37\x41\xda\x59\x88\x5c\x52\x8e\x37\xe5\x21\x9d\x14\x6b\x12\x4a\xcb\xad\xd6\x81\x8d\xfe\xb8\xc5\xa1\xba\x81\x60\xbb\x08\x8b\x5b\xe4\x54\x26\xc4\xe9\x32\x4d\x02\x31\x43\x3a\x13\x38\xe2\x1b\xdd\x2b\x34\x65\x64\xe7\xc1\x15\xae\x3a\xc0\x80\xe7\x19\xac\xcd\x7e\x09\x44\xe8\xfa\x64\x4c\xad\x81\x46\x0d\x9d\x1e\x03\x3f\x3f\x2e\xd8\x9c\x69\x42\x14\x94\x23\xeb\x6b\x48\x27\xab\x78\x9e\x13\xf2\x5e\x2a\xc9\x04\xf9\x91\x96\x52\x38\xaf\x0f\x1b\xa4\x62\xda\x62\x38\x79\x71\x32\xe3\x05\x20\x89\xc1\x95\x14\xaa\xb7\x98\x89\x0c\x04\x7b\xda\xd1\xa6\x0d\xc7\xbd\x93\xc7\xf2\xfe\x65\xd9\x1d\xb7\x48\xde\x0c\x58\xff\x27\x6e\xcc\x3b\xdc\x39\x07\x0c\x0e\x85\xdf\x1f\xb7\x02\x67\xc0\xfe\x2a\x8f\x07\xa0\x17\x6c\x1c\xc7\x6d\x1d\x1a\x0f\xf1\xd5\x4e\x21\xb2\x8b\xda\xb0\xeb\x1d\x3c\xac\x88\x1f\x9d\xd8\x21\xbd\x44\x04\xb3\x4c\xb9\x0b\xa4\x4c\x00\x86\xb8\x34\xf6\xd5\x93\x9e\x70\x4c\x5f\xd9\xda\xb0\x0c\x1e\xe1\x9a\x58\x4a\x21\x7d\x29\x03\x56\x10\xe3\xa2\x78\x7f\x64\x6e\x89\xc0\x54\xc4\x99\x95\x6b\xa1\xf6\x5c\xf3\x29\x07\x04\xf0\xa2\x3a\xb5\x53\xfe\x54\xe1\x1d\x8f\x0d\xd3\x3f\x76\x54\x19\x4b\x47\x15\xad\xed\xcc\x0c\x1f\x80\x2e\x7c\x11\xb6\xd1\x28\x6c\x67\x71\xbc\x86\x60\xa1\x04\x93\xad\x38\xa2\xf6\x79\x96\x81\x00\x95\x00\xef\x36\x8e\x3a\xd8\xa4\xd8\x93\x25\x0d\xfe\x61\xba\x75\x03\x88\x61\x32\x47\x8d\x67\x5f\x3b\x31\xd1\xa6\xa1\xf7\x2f\xd8\x99\x63\x49\xe1\x6b\x03\x7f\x56\xc3\x2a\x2f\x86\xf0\x02\x1c\x62\x88\x3d\x45\x2f\x1b\x69\x6b\xf4\x04\x48\xc1\xc0\x36\xc8\x1c\x4c\x41\x2a\xd4\x37\x04\x55\x98\x11\x13\xec\xb1\x9b\x7c\x5a\x87\x2f\xd5\xfb\xed\x95\xac\xc4\xf7\xc3\x5d\xcb\x9b\x10\x8f\x52\x2e\x14\xba\x65\xb2\xf3\xba\x55\xd0\x12\x93\x8f\xb9\x7a\xa4\x0e\x78\x64\xfd\x21\xda\x74\x59\x59\xa4\xc7\xcc\x20\x9e\x03\xd6\xb5\x5f\x08\x71\xcf\x22\x1c\x86\x66\x18\x9f\x48\x6e\xbb\x7e\xe2\xe8\xee\x9c\xe0\x75\xf3\xff\x7c\x1d\xe4\x50\x0e\xf1\x91\xeb\xae\x76\x83\xb5\xf6\xf8\x14\x14\x7e\x7c\x84\x45\xa6\x91\xe3\x00\x81\x40\xdb\x33\x88\xab\x37\xcb\xd6\x3d\xf2\x4a\xd5\x3c\x92\xda\xf2\x04\xab\x8d\x6d\x5f\xa2\xf4\x54\x93\x03\xf4\xb2\x5c\x9c\x8b\x91\xfc\x36\x78\x69\xcb\x49\x92\x10\xa0\x59\xbf\x28\xca\x92\x3b\x98\xbf\x6b\xc5\xf0\xbb\x39\xb5\x20\x38\xab\x79\xd1\x89\x5d\xd8\x81\x17\xc1\xef\xd0\xcc\x43\xb2\x36\xe7\x4c\x02\x1d\xeb\xa6\x76\x66\x1d\x82\x0a\xb5\xe8\x28\xfb\xfa\xbf\x65\xd2\xdd\xa8\x2b\x80\x0d\x24\x8e\xda\xcf\x56\x3d\xd9\xfc\x48\xff\x44\xcb\x9b\xae\xd6\x17\x1e\xc9\xe6\xa8\xfc\xef\x09\x27\xee\xa9\x1f\x29\x65\x28\x12\x1f\x0f\x57\xea\x73\x36\xc6\x43\x02\x28\x98\x2d\x58\x87\x25\x14\xbc\xfd\x4d\x2f\xf6\xc0\x0a\x94\x7f\xa2\x69\xf8\x36\xea\x4c\xb3\xc7\x8e\x44\x42\x38\xf0\xd9\x5e\x1f\x51\xd7\x16\xcd\x13\x49\x68\xcb\xae\xc3\xf0\xb3\xd1\xf3\xda\x06\xdd\xab\xfb\x47\xa4\xa3\xb7\x16\xd7\x77\x69\x7d\x81\xe5\x96\x81\x06\xfb\xcd\xe8\xf5\xfd\x16\xa7\xc1\x7e\x4f\x2b\xa9\x59\xf6\x3b\x68\x34\x6d\xf0\x7d\xfa\x47\xb3\x1f\x94\x40\x02\xc1\x6d\x16\x33\x6d\x7d\xf1\x44\xf6\x59\xcd\xe2\x02\xb5\x4f\x19\x8a\x03\x1b\xe9\x6c\x69\x57\xed\x70\xb3\xa5\x20\xbe\xd5\x80\x6f\x93\xab\x4b\xf5\xc0\x0a\x39\x09\x3c\x0f\x08\x89\x0b\xf4\xbe\xc6\x09\x29\x44\x91\xdd\x3a\x59\x18\x11\xec\x4a\xa2\xa0\x94\x65\x80\xd2\x8e\xc8\x5e\x35\x1d\xc3\x8c\x3f\x00\x93\x2f\x79\x70\x2b\xde\x4e\x50\xfc\x56\xdd\x7d\x55\x06\xec\x5e\xd7\x35\x78\x70\x23\xdb\x0d\x9c\xb5\x43\x25\x37\xaf\x8d\xe3\xcc\xe1\xdf\x39\xa2\xef\xb5\x50\x0c\x68\x97\x54\xf6\x1e\xd4\x29\x7b\x1d\xea\x12\xc7\x4a\x73\x7a\x5f\x6e\xcd\x7b\xf6\x85\x5e\x6a\x2b\xf9\x74\xac\xe4\x2a\x9c\x21\xbe\x22\x08\xb6\xfb\x25\x96\x26\x55\xb7\x2f\x8c\x4a\x06\x6b\xee\x37\xf6\x90\x79\x17\x1c\xda\x7c\x0a\xc5\xba\x63\x2f\x9b\x40\x14\x18\x75\xf9\xaf\xca\xef\x67\x47\x28\xec\x49\x20\x8f\xc2\xae\x25\x84\xbd\xc0\x39\xde\xa8\x76\x59\x95\xb2\x90\x14\x89\x94\xba\x22\x67\x75\x7a\x4d\xbb\x00\x37\xfa\x78\xf8\x2d\x02\x09\xa8\x55\x20\xc8\x0a\xf6\xb9\x20\x80\x91\x54\xae\xb3\x08\x68\x67\x86\x57\xee\xa3\x0f\x24\x7e\xd8\xe8\xb4\xd8\xc4\xde\xcd\x05\x8f\x6f\xbe\x0e\x31\x60\x89\x5f\xb7\x17\x54\xe8\x92\xf3\xbe\x34\x5a\xd7\x1c\x79\xdf\xbb\xc7\x5f\xc4\x02\xe6\x9e\x65\x73\xec\xf2\xe9\x62\xfa\xc7\x57\x65\x93\x89\x9b\x9e\x20\x40\xb1\x2f\x23\x98\xa9\xa1\x76\x21\xe4\x7e\xeb\xc0\xaa\xf4\xa8\xa6\xaf\xb2\x6b\x10\x72\xee\x5e\x96\x83\x07\x72\x19\x48\x1c\xb2\x76\xb1\x0b\xec\x0c\x74\xdc\x7d\xc6\xc4\xfc\x4c\xd0\xf6\x4e\x7c\x41\xca\x57\x46\xa9\x9a\x96\x5d\xf7\x26\x6a\x90\xdd\x07\x23\x7d\x58\xe8\xe9\x78\x52\x50\x96\xef\x1a\x5a\x6d\x96\xe7\xff\x4d\x9f\xcc\xf2\xb5\x28\xe2\x0e\x90\x0c\xff\x76\xac\x16\x2a\x76\xbc\xd5\x53\x0c\xbb\xe7\x0f\xe4\x8f\x00\xfc\xb9\x1c\x64\x6c\x0b\x5d\x13\xcf\x74\xb2\x5b\x82\xa0\x8c\x28\x84\xed\xb1\xe9\x09\x72\x41\x30\x09\x92\x93\xd8\x23\x64\x78\xce\x83\xf1\x20\x3b\xc2\x99\x83\x61\x18\xcc\xc1\xc7\xc4\x53\x5b\x73\x7d\x7c\x03\xb1\x0c\x9a\xe2\x4d\xb3\xbc\x3d\x2d\x3e\x95\xdc\x53\x08\xfa\xef\xa9\x65\x55\xec\x49\xd4\xc3\x8b\x18\x2c\xc1\xa4\xb5\xf0\xf0\x1e\x79\xa4\x64\x3a\xee\xf9\x99\xa4\xbe\xd5\xd5\x4d\xcc\xfa\xed\x3c\xde\x09\x6c\x1d\x6f\x0f\x5b\x00\x02\xab\x86\xbf\x89\x8a\x25\x1e\x7f\x4b\x48\x42\xa0\xc7\xcb\x93\x0b\x3a\x4e\x09\x14\x5a\xe2\x94\xa3\x52\xba\xa9\x0a\x20\x35\x4b\x8e\xd4\xc2\xbe\x86\xea\x40\xf1\x79\xc8\x3b\x70\xcf\x7f\x75\x27\xa6\x9f\xe0\xa0\xfc\x60\x3d\x9a\x0e\x5a\x05\x13\xae\x37\x47\x24\x8b\xf9\x9e\x95\xd3\x8e\x1a\x0b\xa2\xf5\x19\x4c\x9c\xb5\x31\x14\x99\x05\xa7\x49\x54\x9d\x13\xc3\xa2\xea\x74\xb3\xb2\x5a\xf1\xac\xe3\x95\x83\x2a\x18\x99\x3c\x5e\x86\xb8\x7d\xcd\xb1\x24\x5b\x39\x45\x66\x4c\xe4\x40\x54\x28\xf8\x46\xa6\x60\x11\x22\x23\x68\xa6\x1e\xce\x76\xdc\x25\xc9\xa3\xd6\x4e\x61\x78\x95\x73\xd9\x9a\x9e\x1c\x86\xb7\x0f\xd3\x67\xb6\x0f\xcf\xbe\xdd\xab\x68\x7f\x79\xb6\xa0\xb8\xb1\x72\x8e\xa5\x7c\x30\x84\x44\x84\xbc\x8d\xe1\x3a\xce\x67\xe4\x1b\x94\x81\x50\x82\x3b\x59\xb9\xd9\xc1\xa3\x6c\x7d\x2e\x52\xfd\x1d\x29\x64\x61\xb3\x91\xed\xde\x83\x11\x58\xeb\x25\x06\x66\x11\x06\x0f\xc1\x7a\x84\x69\x9d\x04\xf0\x39\xc3\xfb\xc4\xb1\xd6\x05\xfa\xa0\xe6\x48\xa5\xbe\xa8\xad\xc9\x52\x01\x55\x1f\x16\xb6\xe9\xe3\xed\x6b\xcb\x6f\x25\x3d\x18\x0a\xea\xe2\xfc\xca\x4e\x7e\xb9\xe5\xfb\x4b\xa2\xdf\x7c\x83\x12\xd3\x4f\x91\x63\x25\x7d\xcb\xb2\x46\xb6\xc6\x80\x12\x5d\xe6\xa6\x84\xe7\x0d\x9c\x77\xcc\xdf\xd8\xc0\x72\xe7\xff\xb3\x49\x2f\x49\x7c\x0d\x49\x56\x17\xc8\xcf\x14\x6c\x05\x1b\xc9\x05\xb7\x14\x9b\xd4\x2e\xde\xd2\xf1\x4a\x85\xbf\x38\x86\xb8\x58\x72\x37\x3c\x28\x5c\xe2\x49\xa7\x42\xa6\xe3\xe4\x5e\xd6\x2d\x4d\x3a\xcb\xc4\x59\xea\x96\xc6\x6f\x89\x7d\xe3\x1f\x3c\x44\xf2\xe3\x8a\x0e\xff\x0f\x97\xb0\x4a\x91\x00\x1f\x4c\x99\x5e\x21\x9f\x47\x40\x72\xca\x5b\x8e\xd2\xf5\x5e\x6c\x20\x24\x57\xa9\xf7\x70\xc5\x5d\x70\x86\x15\x15\x60\xc8\x07\xde\xf5\x9e\xb9\x09\xc7\x19\xd9\x82\x3f\x9b\x12\xb9\x56\x84\xf3\xf0\x74\xf5\xba\xe2\xdf\x24\x5e\x5e\xeb\x29\x7b\x0e\xa8\xe3\xbf\xfe\xcc\xa0\xd7\x26\x92\xb4\xe2\xa3\x3e\x0f\x8f\x14\x06\x16\xb1\xae\x7d\xd7\x22\xa6\x6d\xa2\xb7\x4e\x4b\x7c\x04\x00\xdf\xfc\x12\x9b\xbc\x13\xe7\x2b\xd5\x79\xd2\xef\x42\x62\x7a\x06\xf2\x8f\xdf\x01\x4f\x58\xb9\x0d\x71\xe1\x8f\x90\x38\x52\x81\xb2\x80\xa8\x3b\x81\xa6\x80\x27\x8b\x1a\x8f\x22\x18\x15\x0c\x3d\x83\xf3\xd0\x70\x2f\x2a\xd1\xba\xee\x73\x23\x2f\xfe\x6c\xc1\xdd\x5a\xd5\x47\x3a\xd8\xc4\x47\xb2\xd6\x88\x63\x05\xbd\x31\x8b\x35\x6a\xac\x30\xb4\xf5\x27\xd5\x0b\x9e\x63\x1e\xd5\x73\x85\xc0\x00\xa3\x35\xb1\x16\x27\xbe\xe2\xef\x37\x1e\x4d\x09\x9f\x95\x21\x36\x1b\x04\x6c\xdf\x1a\xd2\x7c\x43\x74\xc5\xf0\x49\x5c\x42\xf1\x93\xe0\x29\x06\x79\x35\x1b\x9f\x19\x4b\x62\x4a\x6e\xde\x57\xa7\x47\x2e\x3a\x72\x8b\xa8\xa7\xb5\xfc\x5c\x32\x8e\x05\xa2\x35\x95\x60\x02\x5d\x23\x7a\x13\x60\x6e\x16\xe7\xea\x4c\x46\xed\x1f\xee\x7e\x6e\xff\xa0\xef\xc9\x10\x24\x44\xae\xc0\xd2\xca\x33\x38\xd7\xb8\xc8\xf0\xc7\x09\xbb\x36\xe6\xb9\x15\x5d\x5e\x7a\x88\xc2\x0b\x9c\xc5\x64\xaf\x2d\xcf\x27\x6d\xda\xf5\x8f\x40\xeb\x5a\xc6\xf3\xe6\x95\x33\x89\x2c\x0d\xc4\xea\x23\x98\x9f\xc3\x87\xbe\x96\x81\x27\x07\xf3\xb3\x40\xa9\xcf\x24\x48\xd7\x99\xd3\x39\x37\xa2\x67\x8e\xc9\xae\xd6\xc6\x52\xca\xe7\x6b\xe3\x99\x59\x65\x9e\xad\x5a\x2b\x41\xa9\xe6\x9b\xff\xdf\xef\x22\x73\x3d\x78\xcd\xdb\x1d\xb4\xcf\x21\x25\xb2\x36\x36\x96\x95\x14\x8c\x56\x4c\x62\x83\x05\xd3\x25\x7b\x8d\x2c\xa7\xeb\x8a\x70\x62\x96\x88\xd3\x20\x11\x9b\x93\x65\x88\x86\xba\x81\xf2\x4f\x8d\xd2\x85\x85\x5b\xae\xf2\x8a\xd8\x0c\x36\xdc\x5c\x62\xb5\x65\x75\x1d\x61\xa1\x85\x3c\xe6\x59\xc9\x76\x6b\x1e\xce\x60\xa8\x56\x6a\xb7\x03\x66\xd6\xac\x39\x75\x22\x67\x7e\x07\x19\xdc\xda\xff\x41\x39\xd8\x9f\x0f\x0e\xfc\x2b\x88\xd7\x0e\xf1\x24\xf7\xd0\xa3\x6f\xbb\xe3\x80\x7d\x16\x5f\xf3\x06\xee\x33\x9e\x7c\xcb\x8d\x3b\x7a\xcb\xfa\x6f\x2a\xfa\x01\x28\x86\xd7\x80\x41\x3b\xfd\x14\x57\x2e\x88\xab\x5f\xba\x9c\x7d\x1f\x8b\xc8\xb0\x9f\x39\x89\xed\xbd\x2f\xc7\x2b\xd0\x76\x1d\x1f\x9e\x1d\xea\x2d\x42\xe0\x18\x26\x9c\x0e\xb3\x05\x44\x56\x3d\x89\x4b\xb9\x9f\x70\x7a\xfe\x3e\x6f\x51\xa5\xbc\xcc\x25\x18\xb4\xed\x15\x1e\x5c\x74\x02\xd9\x35\x1c\xf1\xa7\x70\xd7\xa9\x8f\xef\xed\x91\x35\x92\x6b\x58\x6f\x41\x88\x1d\x1a\x80\xe0\xbe\x66\xf2\x8a\xf3\x5d\xcb\x67\xe5\x38\x07\x23\xf6\x12\x0f\xab\x53\x96\xc3\x0a\x66\xec\x99\xa4\xce\x9f\x2a\xd6\xe3\x0f\xf9\x45\xd7\xf4\x2f\x91\x1c\xf9\x3e\x92\x68\x9e\xcd\x1a\xe7\xbf\x2e\x0a\x8f\x62\xfe\xc4\xff\x5c\xfa\xcd\x35\x8b\x8f\xf9\xa2\x27\x1a\x4c\xd6\x59\xff\x4a\x2f\xee\xe1\x84\x13\x25\x7b\x3c\x00\x4e\xde\x56\x4f\x04\x4a\xa2\x92\x76\x39\x31\x47\xc7\xef\x43\x81\x43\x81\x97\x3c\x74\x9a\xe3\x9c\x1b\x57\x75\x78\x82\x57\x27\x20\xd1\xff\xe9\xc2\x75\x40\xbe\xe9\x48\xd8\x32\x34\xdd\xed\x07\x43\x81\xab\x32\xce\x04\x4f\x7a\x9c\x40\x82\x31\x4e\x91\x2f\xfe\x0f\xc7\x04\xdb\xad\x0a\xa9\x33\x43\xa4\x57\x50\xcd\x62\x43\xe5\xa6\x33\x37\xa1\x0f\xe4\xbc\x07\xa7\xb5\x22\x34\x30\x74\x14\x71\x61\x7b\x52\x9d\xa3\x95\x3b\x96\x70\x3c\x1b\xac\x37\x69\xba\xed\x85\x8e\xc1\x37\x8e\xee\x92\x7c\x30\x6b\x72\x62\x5c\x44\x3a\x2f\xb1\x2d\x12\x6d\xac\x5f\xa9\x22\x4f\x0d\xda\xc9\xa3\x3b\x5f\xac\x48\xd9\xaa\x48\xb9\xdb\x7f\x1b\x4d\x77\x8b\xc4\xb3\x6f\x68\xbd\x05\x06\xde\xde\x6c\xd3\x9d\x4b\x94\xe5\x78\x57\x1f\x21\xf1\xd4\xdb\x6c\xd0\x3e\x6a\xd6\x01\xfc\x6e\x1c\x3c\xcc\x84\xba\x54\x7a\x61\x9f\x11\xc1\x60\x33\xac\x1a\x28\xb8\xba\xe9\x86\x61\x60\xfe\x15\x48\xa1\x09\xc2\x44\xb3\xfe\xdb\x47\x13\xec\xff\x34\xf3\xe4\xc3\xf4\xf2\xa1\x78\xc0\x72\x33\xa1\x1c\x25\x17\xf8\x97\x5b\x33\x83\x25\x2c\x26\x03\xa4\x01\xe6\xda\xc2\x72\xab\xf5\x2c\xf7\x2c\x1b\x77\x91\x9c\xe8\x72\x0f\xaf\x22\x69\x5c\xc3\xf4\x47\x81\xdd\xa3\x1d\xf7\x87\xc5\x3b\xb3\xb9\x2c\x77\xa7\x5b\x5c\x44\xe1\xb1\xdc\x9d\xae\x2b\x5f\xbd\xd9\xe2\x22\x90\xae\x2f\xb1\x7b\xbb\x2b\xce\x0a\x91\x75\x33\xee\x6e\x31\x43\xed\x64\x29\x1b\x04\xb4\x46\xdb\x57\x13\x7e\xb0\x8b\x28\xcf\x10\x50\x94\xc6\x86\xac\x02\xa4\xa5\xae\x4f\xbb\xa3\xab\xbe\xfe\x23\x9d\xb7\x17\x39\x2e\x19\xf4\xd7\x95\x6c\xb1\x56\x36\x71\x22\x1b\xc9\x7d\xa0\x04\x89\x8e\xca\xba\x31\xbb\x7b\x71\xd1\xfa\x80\xc1\x1a\x5d\x0e\xf1\x65\x40\x05\x9c\x9e\xa9\xa5\xec\xb2\x61\x60\x0b\x44\x95\xed\x49\x37\x96\xf0\xad\xa9\x67\x2d\x6e\xbf\x04\xa1\xb8\xbd\x26\xd0\xe8\x12\x6b\xa1\x16\x88\x34\xce\x25\xd2\xef\x91\xe3\xe6\x96\x33\x2c\x2d\x25\x23\x3a\xf4\x32\xe2\x1e\x81\x8e\x60\x08\x8f\x50\x3b\x30\xce\xf3\x97\x36\x6a\xcd\x71\xba\x78\x96\xe0\x0c\xe1\xf3\xc3\x42\xe6\x7f\x41\x32\xce\xf0\xe7\xc5\xdd\x49\x1f\xa2\x39\x48\xc8\xd3\x4e\xb2\xec\xcc\x87\x00\x3d\x16\x2f\x45\x07\x67\x20\x9f\x4c\x5e\x04\xd4\x92\xc7\x92\x5f\xad\xde\xf9\xfe\x65\x93\x98\x05\xda\x05\x73\xa5\x59\x5d\x77\x80\xb5\x49\xb3\xd9\x86\xfb\x29\x16\x79\xa4\x96\xbc\xef\x52\x35\x33\x18\x3e\x86\xa5\x89\x5a\x82\x32\x2e\x1e\x02\xd2\x69\x32\x51\xf0\x11\x2e\xca\x68\x40\xee\x61\x94\x53\x12\xc5\x79\xf9\x99\x6c\xbe\xa1\x27\x98\xcb\x93\x5f\x03\xdc\xe2\x3c\x72\xbe\x6a\xd4\x21\x56\xac\x17\xf1\xf0\x2e\x79\x12\x97\x77\x1e\x21\x6e\xe9\xa8\xe7\x2d\xf4\x8a\x5d\x6c\x6c\x5b\x4b\xee\xc2\x13\xbe\xe4\x44\xe7\xd2\x92\xde\x57\x80\x83\xa1\x40\x4b\x7a\x91\x06\xfc\xe6\xfe\x1b\x82\xfc\xf2\x2f\xf9\xd6\x26\x20\x36\xf8\x14\x09\x04\x86\xb8\x9e\xb7\x84\xbc\xe3\x02\x67\x92\xd8\xbf\x0d\x15\xce\x34\x16\xe4\x8a\x93\xf0\x3e\x9d\x3c\xfe\x24\xb1\x27\x7c\xae\xf5\xad\x77\x9b\x48\xa9\x08\xc9\xfb\xad\x63\x8d\xce\x3e\xd8\xca\x61\x34\x09\xf5\x8c\xa5\x5b\xd2\x2e\x12\xf8\xe4\x7e\x3a\x31\xaa\x6f\xf7\x97\xc7\x6d\xad\x96\x6d\xca\x63\xf0\x1c\x38\x88\x1a\xfc\xd1\xa2\x83\x62\xbd\x88\x58\x7d\x92\x87\xc8\x79\xe9\x74\xa4\x8d\x18\xfe\x3a\xd3\xba\x33\x5c\xda\x99\xd4\x09\xca\xf7\xd6\x0d\x97\x4b\x64\x01\x06\x27\x5d\x64\x26\x05\xbb\x35\x59\x9f\x2b\x19\x0a\x65\x01\x43\x18\x96\x8b\x08\xdf\x27\x4d\xf0\x80\xf4\xa8\x46\x46\x7c\x1b\x90\x96\x41\x1a\x31\xa9\x17\x92\x1c\x41\x1a\xee\x5e\x77\x31\x6c\x71\x3f\xe0\xb8\xe1\x39\xfa\xea\x7e\x5d\xe2\x67\xa3\x8f\xef\xf3\xa1\x47\xd7\x31\x7f\xde\x40\x3d\xc4\x45\x2f\x36\x07\x8c\x88\xb7\x0f\x7e\x4f\xd1\x04\x3d\xef\xe6\xba\x35\x18\x44\xde\x37\xd7\x48\x9e\x77\xf0\xb4\x1f\x8c\x20\x32\x30\x7c\x48\x5f\x2e\x06\x86\xe7\xbd\x89\x43\x08\xac\xee\xf1\x73\x6f\x38\x90\x4a\xf9\xb0\x74\x5a\xf0\x5b\xa2\x66\x00\x13\x7f\xbb\x24\x81\x22\x26\xea\x9b\x16\x95\x95\xd4\xa8\x7b\xde\x6e\xea\x2f\xc2\x4f\x5d\x69\x50\x1d\x40\x0f\x47\xd4\x42\x8f\x00\xfb\x40\x89\xac\xef\xdf\xcf\xf7\x47\x1a\x03\xaa\xf8\x42\x6e\x64\x83\xeb\x5b\x4b\x81\xc0\x24\xb0\x3f\xea\x5e\x86\x1f\x63\xfb\x51\xd9\x1f\x3e\x91\x08\xcd\xf3\x95\x46\x13\x5f\x3a\xfe\x2b\x17\xad\x8c\x3c\x7d\x95\x4c\xff\x4d\x9f\x4d\xec\xf4\xe9\xe4\x71\xa9\x3d\x2d\xe8\x27\xa2\xac\xdf\x8f\x08\xdd\xbf\x51\x6f\xb8\x28\xc5\x1c\x8f\x98\xf3\xb9\xe1\x5e\xfe\xd0\x67\xbd\x6e\x91\xc8\x5f\x47\x27\x20\xdf\xb3\x55\xf6\x0f\xd9\xfc\x33\x07\xd9\x7c\xd1\x71\x67\xdf\x9e\x54\xd5\xdb\x85\x80\xa9\x97\x58\x6b\x11\x60\x25\x01\x96\x60\x94\x07\x76\xb0\xbd\x7f\xa7\x58\x1a\x8d\x7d\x38\xa9\x9f\xbe\x40\x1d\x3b\xff\x1c\xa9\x01\x1e\xf3\x56\x51\xdd\x67\x77\x2b\x3c\x49\x46\xfd\x84\xbf\xeb\x95\x8e\x80\x24\x76\xaf\x7c\xc0\x1b\xf3\xb5\xac\xcc\x51\x0d\x32\x39\x90\x92\x9e\x8c\xea\xfa\x56\x9e\x3e\x3b\x22\xc2\x8a\x1e\x4f\xa4\x80\x21\x10\xd1\x5f\x8d\xec\x1d\xe3\xec\x8f\x77\x7c\x91\x18\xa9\x53\xd2\x23\x3b\x99\xd7\x5c\xb2\xc7\x06\x58\xa9\xb5\xd6\xe7\xc3\x2e\x10\x3f\xc2\x9a\x69\x84\xa4\x3f\x0b\x57\x35\xad\xa4\x86\xd6\x93\x5c\x43\xcf\x42\x59\x75\x30\xd3\x8b\x3b\x7e\x9b\x4e\x0d\xa9\xc0\x22\x99\x5f\x77\x11\x94\x97\x55\x3f\x5f\x96\x55\x7b\x82\x40\xd4\xd0\x14\x9e\x5d\x90\xd5\xab\xad\x95\x99\x3b\x82\x9e\xee\x59\x5a\x6d\x75\x04\x0c\x55\x9e\x35\x7f\x4b\x22\xed\x7c\xb0\x89\x90\x96\xde\xcf\x90\xcf\x19\xde\x56\x11\xc3\x1f\xe7\x15\xfc\xf3\x87\x5a\x0b\xd6\xda\x4f\x82\xb8\x78\xde\xf2\xa8\xda\xe5\x75\x9f\x55\xfa\x4b\xcd\xcb\xd9\x26\xdb\x30\x5a\x37\x95\x7f\x09\xda\xf3\x33\xcd\xf7\xc6\xc3\xcb\xd9\x98\xf2\xcb\x21\x92\x77\xfb\x7d\xe1\x2e\xde\x64\xe6\x67\x9d\x18\x58\x6c\xe5\x38\x73\xb2\x03\x38\x06\x03\x3e\xa6\x6d\x3f\x4a\x79\x7b\xb0\x7e\x81\x74\x7e\x3f\xd1\x24\x0d\xdf\x9d\xf6\x9e\x60\xaa\x24\x4b\x3c\x1b\x27\x66\xb6\x59\xa0\x69\x5d\x24\x24\xa3\xf1\xee\x9d\xea\x5e\xcd\xbc\xad\x8d\x3c\xd3\x21\x9e\x7a\x2c\x2f\xfb\x03\x49\xfb\xa1\xea\xea\x9b\x82\x50\x10\x3b\x14\x1b\x14\x66\xae\xcb\x23\xc9\xb9\xd5\x7b\x15\xf9\xfd\xc2\xbb\x5b\xb8\x4a\xef\xac\xf6\x2f\x3e\x87\x98\xdb\x3e\x31\x01\x6c\xea\xca\x4f\x28\x2d\xce\x34\x3a\x9f\xe8\x37\xda\x3c\xf2\xe9\x31\xee\x02\xd6\x9d\xf0\x68\xc9\x13\xd8\xbc\xe5\x9d\x88\x48\xf0\xfa\x00\x51\x88\xf7\x57\x8f\x3f\xe9\x21\x86\x91\x79\x1d\x6b\x04\x0f\xeb\xb2\x5d\x8e\xf8\x51\x77\xbd\xb1\x07\x98\x23\x7d\x0d\xe2\x51\xb9\xf6\xf1\xa8\xe4\xc4\x62\x34\x76\x38\xbd\x1f\x2d\x76\xfa\x91\x5b\xe5\x01\x49\x98\x7f\x8a\x4d\xf8\x01\x36\x49\xaf\x8f\x7d\xf2\xfa\x25\x9c\x43\x64\xfb\x70\x36\x7d\x52\xde\x43\x7a\x46\x68\x64\x95\xcc\xea\x51\x0e\xd3\xc3\x66\xa0\x6c\xb7\x40\xa4\xe4\x17\x3d\xac\x95\xc9\x6c\x00\x3c\xad\xf2\x4e\xe1\x19\xfb\xb3\xea\x50\xce\x3f\x8d\xb4\x9c\x5d\x18\x98\x05\x7a\x22\x3e\xa7\x2b\xa2\x43\x28\xdb\x87\xae\x44\xb7\xe0\x7d\x04\x2b\xdb\x56\x7b\xb1\x0b\xd9\xe3\xd1\xd0\x57\x7c\x02\x1b\xaa\xaa\x08\x56\x79\xd1\x88\x2a\x10\xe8\x43\x89\x85\x19\xff\xcd\x6a\x1d\x90\x0f\x81\x25\x54\x93\x42\x1e\xa0\x80\x11\xcd\x63\x9e\xc0\x04\xac\xf0\xa7\xf9\xa6\x57\x67\xbe\xaf\xe0\xc4\x57\xf4\xde\x7c\x47\xf2\xdf\x7c\x7b\x7f\x6b\xdf\xda\x75\xfe\xb8\xce\x6f\x7b\x90\xc1\x99\x7d\x5b\x63\x73\x3e\x76\x2a\xe2\x5a\x41\x46\x7b\x33\x1c\x83\x5d\x5f\x74\xfc\x4e\x20\x2f\xd2\xed\x3b\xc7\x95\x06\xb1\x48\xce\xf5\x15\x9c\xf9\x0a\x14\xf6\x18\xda\xab\xd1\xca\x9f\x67\xf0\xdb\x2b\xd6\x01\x0e\x26\x75\x88\xa0\xcd\x27\xe3\xfd\xb1\xb5\x38\xa6\xd9\x35\x50\xec\xa2\x1e\x54\x09\x16\xfd\xd2\xd8\xec\xc9\xfd\x03\xd6\x27\xde\x66\x5d\xbe\xbf\xe9\x80\x6d\x7d\x7a\xd1\x43\x1a\xfe\x43\xe1\xbf\x5c\xdf\x25\xe6\x18\xb6\x25\x26\x13\xf0\xec\x2f\x8c\x9b\x41\xaf\x92\x83\xd2\x95\x1b\x8d\xf9\xbe\x2e\xaa\xff\x63\x13\x59\xc9\x5c\xe7\x65\x8c\xff\xce\x7f\x9a\xce\x8c\xc4\xa0\xb8\xa8\xc1\x5e\x8c\xec\x88\x18\x26\x21\x7c\xcd\x4a\x63\x98\x6b\x3c\xbf\x2c\xc1\xf9\xb9\x0e\x7c\x23\xc1\xbb\x5e\x5d\xdd\xfa\xd6\x13\xa2\x7b\xd9\x7a\xec\x33\x1c\xdb\x33\x7a\x50\x3f\x3f\x32\x78\xfd\xf4\x45\x8f\x8e\xca\x00\x45\x62\x32\x90\xd9\xff\xd1\xf3\x33\x4d\xd7\x40\x3f\x07\x07\x05\xd4\xf7\xf5\x13\x1f\xee\x78\xc9\xb2\x0c\x0a\xb6\x72\xa2\x7e\x56\xaa\xe4\x91\x0e\xfd\x19\xb1\xd4\x7c\x8b\x45\x9a\xe2\x73\xfe\x84\xfc\x29\x20\x0b\x11\xe1\xbf\xdc\x67\x31\x3b\xa9\x89\x48\xf2\x79\xd7\x90\xda\xe5\xbf\x30\x08\x0c\xa4\xea\x57\x7e\xda\x9c\x95\x35\x3b\xbb\x1c\x38\xd3\x4b\x67\x4f\x38\xfa\x10\x2d\x2a\x73\xe3\xfb\xcf\x54\x73\x9b\xa1\x74\xea\xe5\x2a\xf5\x2b\x43\x2b\x8b\x50\x09\x68\x3c\xfb\x8b\xf2\x33\x40\xf9\xef\x04\xeb\xdc\x78\x6c\x3c\x53\xd9\x16\x95\x14\x72\xf8\x13\x02\x35\xdb\xc1\x41\xd1\x8f\xe5\xc7\xc6\xe7\xcf\xf5\xc7\x39\x77\x4c\x21\x06\x9f\x6b\xc8\x04\x24\x89\x17\xa4\x89\xa7\x4f\x83\xc8\xc6\x01\xfd\x0e\xc1\xf1\xdf\x49\x1e\x71\xf6\x48\x00\x32\xe7\xc3\x48\xb7\xb7\x72\x71\x83\xf7\xe9\x59\x69\xa3\x82\x79\x66\x9f\x7d\x05\x19\xbf\x99\xf6\x5a\x79\x75\xae\xff\xd0\x8e\x30\xac\x9f\x1e\x57\x7c\xc5\x18\xee\x82\xcc\x7f\xaf\x55\xfb\x56\xf1\xf4\x1f\x43\xfb\xc6\xb0\xa4\xf8\x09\xe0\xde\x21\xd0\xff\xd3\x15\x09\xd4\xbe\x55\xeb\x59\x43\x35\x80\xb9\x19\x36\x30\xb4\xee\x29\x29\x29\x72\x4e\x5b\xc8\x12\x6c\x67\x6b\x78\x49\x39\x1e\x70\x36\xea\xbd\x62\x28\x8d\x5b\xe1\xa8\x09\xf5\x1d\x36\x7a\xcf\x40\xf9\x09\x09\xb4\x59\xc4\x2c\x9d\xaa\xd9\x83\x6f\xb5\xc2\x8f\x50\xbe\x25\x6e\xf5\x8f\x0e\x44\x6a\xc1\xfa\x36\x94\xee\x87\x9e\xd4\x12\x22\x04\x66\x93\xcd\x01\xa5\xff\x33\xa7\xa2\x05\x49\x68\x14\xb0\x26\x13\xb2\x65\x79\xd8\xf0\xd6\x39\xba\xc2\x49\xbc\xf3\x4e\xaf\x14\xb6\x9c\x44\xd7\x3c\xdd\x21\x36\x64\x28\x63\x5e\x75\xfd\x27\xa1\x82\x10\x15\x60\x78\x69\xfe\x8f\xda\x04\x0c\xf6\x70\x95\x02\xee\xda\x1a\xe5\xc6\x74\xaf\x1c\x61\x26\x2c\xa7\x72\x8c\x30\xe8\x6c\x52\x71\xb2\x82\x19\xa0\x13\xc0\xdf\x30\xee\x2a\x11\x35\xa9\xa7\xbb\x7f\xf3\xe7\x9e\xe9\x7b\xd0\x8e\xb0\x2d\xa4\x13\xeb\xd0\x04\xe6\x4c\x87\xc7\xcd\x55\xc0\xe9\xa8\xd4\x00\x01\xf0\xa5\xa6\x49\x42\x2e\x56\x66\x8c\x37\x13\x31\xa2\xdd\x1d\x49\x81\xcd\x40\x53\x39\x81\xaa\x01\x23\x40\x79\x70\xb6\x16\xcd\xfe\xd5\xb1\x1a\xd2\x74\xd0\x0f\x35\x1d\xc9\x66\xb4\x24\xaf\x3f\x12\x4f\x9a\x34\xba\x4e\xce\xbe\xa5\xa3\xb6\xaf\x2e\x69\x4f\xe0\x91\x9b\xe4\x41\xc7\x93\x81\x01\xc5\x51\xfd\x9a\xf1\x44\xb9\x02\x5a\x3c\x53\x65\xa0\xcc\x54\x4f\x71\xda\xdb\x4b\xe5\xa1\x87\x12\xb9\x21\x5e\x30\x31\xd6\x63\xaa\x9b\xe7\xbb\xba\x5e\x41\xbc\x0b\x70\x00\x1f\x3c\x50\x06\x01\xc0\xd4\xa4\x15\x9c\x13\x8b\x47\x16\x29\x17\x20\x7c\xd4\xc1\xa0\xa5\xd9\x09\xa2\x77\x2c\x15\xc9\x08\xe4\xc9\x8f\x53\x1b\xce\xa6\x82\x44\x16\x6a\x5d\x94\x9f\x3c\x00\x3c\x95\x6e\x5d\x18\x5a\x1b\x3c\x5e\xfa\xef\x71\x49\x7e\xe0\x10\x07\xb8\xdd\x0b\xe8\x7a\x79\x1a\x7d\x7e\x13\xe4\x39\x74\x11\x76\xb8\x53\x69\x37\x08\x5f\x20\x05\x1d\x8a\xab\x82\xf0\x02\xf6\xc1\xb2\x79\x30\x9e\x61\xca\x52\x16\x56\x82\xe3\x14\x52\x60\xd3\x4f\xa0\x23\x1f\x8a\x50\xc1\xba\x21\xaf\x92\xc9\x09\x32\xd1\xf0\xcb\x84\xcc\x13\x02\x38\x59\x0e\xa1\x4c\xc0\xb4\x89\x49\xde\x3b\x28\x15\x48\xd0\x60\xfa\xb3\xfc\x37\x79\xf7\xcc\xfd\x59\x33\x9d\x49\xa9\x09\x53\x7a\xc5\x75\x0c\xe9\x81\xd8\x1c\x41\xf5\x4a\xf7\x50\x18\x7d\x3a\x25\xb9\x44\x01\x78\xd4\x75\x9d\xf2\x9c\x4e\x89\xdd\xca\xe4\xbc\xf2\xdc\x83\x6c\xb2\x42\xf4\xe4\xf1\x67\xa9\x8d\x15\x6c\xc2\x7a\x56\x3c\x11\x60\x66\x04\x4e\x29\xb2\xf9\x1d\x51\x4c\x82\x0f\x39\xf6\x62\x49\x44\x87\xb2\x0d\x43\x7d\x8b\x15\xc3\x4a\xce\xc8\xb3\xfb\x78\x37\xa5\x55\x95\x59\xe3\x6e\x63\xaa\xe9\x2a\x0b\xa2\xcb\x70\x99\x85\x8b\xbf\x2b\x5b\x55\x45\x8a\x4b\x1f\x7b\xf3\x4d\xb3\x8c\x81\x09\xe9\xb1\xbc\x68\xee\x42\xae\x61\xf8\xc6\xf4\xdf\xb0\x6c\x96\x29\x75\xba\x79\x37\x78\xc7\x0f\xf9\xfd\x41\xef\xff\x26\xe0\x4d\x18\xe8\x19\x95\x37\xde\x9b\x0a\x4a\x1c\xdc\xcb\x9b\x64\x3a\x86\x5e\xee\xc4\x32\xb0\xa8\xc6\xe3\xfd\xbc\x15\x37\x35\xde\x0c\x32\xb7\xd2\xaf\x3c\x1e\x1f\xc5\xca\x8e\x07\x43\x6f\x47\x44\xc7\xd3\x6c\x82\xc4\x03\x53\x8e\x0c\x05\xa0\x8e\x9d\xdf\x8c\x0b\xfd\x08\xc1\xd4\x72\xe7\x3a\x64\x1f\x36\x95\x14\x72\x00\x3d\x3c\xd7\xf1\xc6\x43\xfc\xcc\xc8\xd1\xf3\x10\x48\x57\x77\xb0\xd9\xc8\xcd\x9f\xda\xdc\x0d\xdf\xf3\x58\xdf\x4c\x63\x1f\x3d\xdf\xa0\xc5\xd4\x8f\x15\xfe\xd4\x8d\x88\x4b\xc0\x23\x39\x7c\xb8\xef\x60\xa7\x6f\x40\xd9\xa7\xa3\x59\xc8\xea\x92\x47\xc6\x86\x30\x92\x6d\x44\x30\x48\xa6\x0a\x41\x95\xd4\xc8\x58\x23\xee\x73\x5c\x6e\x5f\xc1\xb5\x52\xdc\xfe\x86\xfc\x5e\x16\x2e\x55\xc0\x51\x59\xf9\xfc\x16\x8f\x98\x10\xcc\x7c\x02\x4b\xfa\x27\xd1\x0c\xef\x72\xfc\x2a\xf6\xd8\x18\x3c\xe3\x1b\x36\x65\xeb\x6f\x2a\x43\x6c\xcf\x50\x7b\xd8\x64\x14\x21\x91\x29\x94\x12\x6c\x3e\xea\x1c\x00\x63\x79\x24\x57\x4a\x80\xad\xcd\xef\x60\x2c\x41\x9e\x31\xba\xcd\xa9\x4b\xc2\x34\x68\x50\x4f\xc1\xc6\x6e\x8d\x92\x63\xa4\xa7\x8f\xe8\x32\x0e\xee\x52\xe0\x00\x06\x92\x88\x3b\x1d\xb3\xe6\x2f\x23\x46\x15\x1e\x36\x64\x19\xa4\x06\x13\xcb\xce\x5d\x38\x63\x86\x19\xe6\x67\x45\x64\x28\x55\x2c\x12\x75\x1a\x47\x2c\x52\x5c\x04\x07\xc7\x3f\x48\x4b\xa8\xd9\xa4\xbb\xe3\xd0\x30\xa6\x3f\xcd\x2a\x49\x28\xce\xe6\x85\x93\x13\x75\x8f\xce\xcc\x25\xd1\x8c\xb4\xf0\x29\x73\x5a\x3d\xa6\x54\xfc\x95\xe6\x7f\x7c\x79\xf9\x2d\xd9\x03\xe4\x41\xfb\x62\x68\xd6\xaa\x05\x4a\x01\x9b\x08\xbf\x7c\x20\xcb\xd6\xef\x3c\x78\xd0\x5a\xdc\x98\xf3\x75\x17\x3e\x57\x71\xec\x66\x12\x14\x99\xe5\xb4\x2b\xeb\xce\x1e\xdc\xc9\x45\x68\x90\xa8\x4b\x14\xa1\x09\x25\x1c\x1a\x95\xf2\xd1\x27\xc8\x5f\x51\xaa\xe0\xa0\x58\x67\x96\x3f\x11\x5d\xf8\x1a\x77\x8c\x01\xbd\xd0\xd6\xb6\xca\xd3\x69\xda\xe6\xf2\x79\x9b\x22\xaf\x11\x5a\x11\x59\x33\xdf\xbc\xfd\x86\x36\xc4\x8a\x6b\x66\xeb\x61\xe3\xfa\xbf\xec\xed\x4c\x96\x56\xf0\x97\x4b\xdc\x61\x55\x8a\x5c\x5e\xf9\x9f\x45\xdd\x3c\x7c\x51\x3c\x4b\x38\xa3\x7e\x58\x5f\x7a\x66\xc8\x87\x6b\x49\xf8\x65\x16\xb3\x39\xfc\x1f\x50\x74\x90\xe8\x43\x48\x6d\xf8\x88\x7a\x11\x49\x09\x2c\xb6\x54\x35\x38\x22\xf4\xbe\xe6\x63\xa2\xcb\x22\x2b\x80\x33\xc7\x9d\x20\xfb\x64\x0d\xdd\x88\x76\x13\x0e\x75\x64\xff\x8c\xca\xc2\x5f\x2a\xeb\xd8\x9f\x94\x9f\x1a\x8b\xbf\xba\x20\x14\x23\xf8\x6d\x61\x76\xc1\x5d\x3d\x03\x23\x87\x8f\x34\x0e\x6e\xb7\x98\x5c\x08\x42\x72\x0c\x66\xe6\x6d\x0e\x36\x79\x71\x0c\x85\xb8\x91\xcd\x45\x59\xc8\x01\xe5\x20\x11\x50\x6a\xe0\x8e\x14\x8f\xe1\xee\xf8\xe3\x4e\x1c\xfd\x87\xa8\xe4\x41\x99\x2a\xe1\x85\x99\xfa\x0e\x47\x12\x13\xd9\x50\xdf\xcc\x8d\x02\x60\x37\x68\x88\x52\x01\xf5\x3d\x2b\x79\x7a\x08\xfa\xe9\xc1\x1d\xe5\x6e\xe1\x0d\x75\xe7\x22\xfa\x10\x39\x74\x4e\x3a\x4a\xb0\xc6\x28\x34\x78\x72\xff\x4c\x66\x98\xa1\x46\x14\x9a\x21\x25\xac\x0d\xf0\x52\xf3\x9f\xcc\x94\x1c\x22\x76\x6d\xa8\xdd\x53\x55\x03\xe7\x07\x40\x79\x31\x20\x14\xd2\x0d\x5c\xe9\x18\x42\x17\x6a\x08\xea\xa2\xc1\x69\xb6\xa4\x47\xe1\x9f\x8f\x3f\xe4\x72\x70\xb9\x7c\x00\x43\x08\x9f\x24\x8d\x25\x4c\xfa\xde\x49\xa7\x75\x5d\xea\x4a\xb8\x86\x20\x44\x4b\xcb\x00\xad\x5a\xa0\xd2\x24\x1d\xa6\x59\xf2\x04\x25\x02\x23\x87\x92\x6f\x57\xa7\x20\x0e\x3d\x89\x7c\xfc\xea\x65\x5f\xef\x93\xb7\x94\xa3\xc5\xc0\xfb\x74\xa4\x76\xc0\x08\x91\xe1\x83\x5a\x10\xcc\x98\xb2\x32\xad\x0a\xf4\x1c\xc0\xcc\xad\x9a\x76\x74\xb4\x0e\xf9\x0b\x9a\x1f\x47\xef\x50\xa6\x73\xf5\x87\x33\x80\x44\x03\xee\xfd\xe0\x23\x47\x68\x99\x64\x6a\x06\x57\x9f\xa9\x44\xab\xd4\x45\xf2\xf9\x48\xf6\xdc\xa4\x1c\x11\x62\x45\x83\xf2\x4f\xac\xb4\xe1\x35\x74\x25\x8e\x23\x84\x27\xb0\x8a\x18\xda\x0f\xd5\xd9\x02\x75\x04\x92\xa1\x79\x02\x1b\xb5\x79\x29\x25\x16\x0d\x19\x4b\x82\xbb\xb4\x35\xb0\x31\x4a\x8a\xc1\x46\x58\x9d\xd6\xf3\x0d\x1c\x6d\x17\xef\x63\xab\x1b\x74\x18\x78\x9f\x1b\x16\xe6\xa4\xf6\x20\x89\x8d\xbc\x42\xa4\x56\x22\x08\xd9\x23\xee\xf8\x2a\xf2\xca\x88\x71\x00\x89\x69\xac\x49\x5c\xb8\x43\x46\x64\x86\x40\x68\x58\xa0\x31\xa4\x45\x30\x9d\x97\x2a\x02\x4c\x80\xf5\xb5\x4b\x7a\x1b\x92\x1b\xb1\xbe\xeb\xec\x7e\x32\x11\xc7\x1a\x7b\x8f\xe9\x23\x84\x59\x50\xa8\x50\xf8\x42\x65\x88\xae\xe4\xa2\xb7\x47\x5b\x7a\x40\x2e\x83\x6e\x63\x0e\x9d\x0e\x9f\x7e\xf1\x2e\xa6\x90\xf1\xf8\xa3\xbf\x31\x22\x80\x56\x67\xa1\xe5\x00\x6d\x09\x1f\x3a\xa0\x2d\x81\xa4\x46\xee\xec\xee\x99\x75\x54\x27\x37\x20\x17\xef\x08\xc0\x5b\x82\x7c\xd8\x26\x94\x55\x5a\xbf\xc5\x9a\xa4\x8f\x68\x2c\x06\x85\x5d\x0f\x58\x60\xe5\x7b\x4d\xce\xaa\x15\x90\xef\xc7\xc6\xee\x7c\x53\xe6\x05\x10\x19\x89\xc4\xdc\x75\x6c\xfa\x8a\x40\xc4\xfa\x20\xda\xe9\xd5\x1e\xe0\x7d\x95\x28\xdb\x00\x3f\xb3\xce\xbc\x45\x08\xea\x00\x52\x70\xfd\x7b\x51\xee\xd2\x10\xbc\x33\x58\xb3\xe6\xe2\x38\x50\x0c\x40\x03\x63\xb4\xad\xe0\x77\x82\x57\x40\x30\x69\xe9\x7a\x20\x87\x8c\x15\xa4\x18\xff\x7e\x9a\x0f\x1d\xd2\x14\x54\x3c\x80\x46\xc5\x9f\xbd\x0f\x92\xe5\x7f\x26\xd4\x4d\xf9\x6a\x90\xae\xe0\x27\x66\xe8\xe0\x47\xdb\x7b\x76\xef\x49\x94\x22\x24\xbd\xbf\xad\xb1\x93\x9a\xfe\xde\xa8\x6b\x70\xaf\xe5\x94\x2a\xc0\x1d\x12\x07\x77\xf9\x4a\xda\x42\x91\x4d\x00\x59\x25\x5f\x1d\xa4\x2e\xc4\xb9\x0e\x26\x6f\x94\xc7\x87\x5f\x61\x0f\x57\xbc\xff\xfc\x70\xfd\x07\xa2\x55\x3a\x0a\x47\x53\xad\xd0\xc1\x66\xa0\xdd\x42\x7e\xa9\x0a\x7e\x4b\x02\x31\xca\xd7\xb7\x04\x17\xde\x03\xcd\x7f\xd7\x9a\x38\x08\x8e\x8b\xce\x03\xc0\x16\x5c\xd3\xd7\x2b\x44\x27\x4e\xad\xe6\x02\x85\xe8\x44\x28\x09\x40\x6d\x42\x62\x0b\xae\x36\x51\x02\x4a\xee\x82\x5c\xf7\xda\x1b\x3f\xc9\x2a\x3b\xed\xa7\xb5\xd6\xd7\x9d\xcf\xd5\x9d\xdb\x93\x6a\x57\xed\x71\x6b\x86\x63\x1b\x9b\x1b\x64\x00\x94\x17\x71\x21\x8a\x10\x9f\xd8\x24\xd4\x0c\xc5\x09\x55\x73\xbd\x98\x0e\xdc\xbb\xb3\x81\x3f\x59\x7f\x32\x14\xab\xbc\x8a\x06\xf3\xf4\x21\x5a\x3e\xa4\xa5\x97\x04\x03\x24\x94\x34\xc5\x77\xac\xfb\xb2\x8e\x44\xb4\xfd\x22\x22\xb0\xb2\xa3\x5f\xab\xaf\x73\x28\x55\x4c\x5d\x68\x4d\x28\x0f\xa5\xaf\xbd\xd2\xc9\x7b\xc4\x97\xfb\x15\x97\x1a\xe7\x87\xf2\x3e\x4b\x84\x07\x4e\xd1\xd7\xf7\x10\x08\xd7\x0d\x9b\x61\xa1\xd7\xb2\x44\x7e\x53\xbf\x48\x88\x42\xe1\x9e\xfd\x22\xf6\xf3\xbe\x68\xcd\xbf\x47\x0c\x39\x5b\xb7\x99\xcc\x91\xcd\xd4\x3b\xa9\xa5\x03\xa7\x1d\xe5\xbb\x2b\x48\xcd\xa7\x92\x02\x95\x9a\xfb\x42\x5e\x59\x62\xb8\xa8\x42\xb0\xc2\x03\x4c\x25\x3a\x80\x90\x68\x3f\xe9\x2c\x75\x97\xf9\xee\xba\x5b\x4a\x0f\x87\x22\xbc\x29\x4c\x81\x58\x29\xdf\x28\x5c\xe4\xea\xc1\x48\x19\xce\x73\xdb\x30\x9b\x97\x17\xa3\x22\x85\xe0\x32\x70\x60\xf4\xe0\x4c\x89\xb3\x98\xc5\xd7\x14\x03\xe6\x4c\x59\x8c\xd9\x95\xb8\x29\x83\x81\x18\x4f\xab\xd6\xc8\x8d\x7d\x95\xf8\x05\xa4\x10\x3e\x44\xcc\xbf\x42\x18\x6f\x66\xcb\xca\x52\x99\xb1\x6f\x1c\x41\x9d\x27\x71\xf0\xad\xf5\x39\x62\x4b\x7b\xd0\x10\xe6\x21\x0e\xa0\xe2\x4e\x8f\xd8\xa5\x45\x8f\x27\x79\x6a\x95\x34\x0a\x98\x05\xe8\x0f\x06\x21\xaf\x21\x35\x41\x0f\x78\x1f\xf4\xcc\x00\x11\xba\x88\xe5\x38\xbe\x7d\xf8\xa2\x9b\x2e\x82\xbc\x52\xe8\x38\x7e\x1a\x12\xdb\x41\x07\x19\x60\x68\x3c\x20\x57\x5f\xaa\x09\xc7\x22\x35\x0c\x03\x5c\x1f\x33\xc8\x17\x62\x25\x83\x4e\x7a\x77\x9e\xe4\x40\xca\xea\x00\x0e\xb9\x8c\x03\xb6\x8c\x84\x16\xf6\x5b\xe5\x1e\x3a\x15\x88\x43\x68\x4a\x1d\x48\x58\xd5\xb5\x37\x2e\x4b\xbb\xfc\x44\x5e\x84\xd4\xec\xf0\x80\x8f\xf0\x68\x4b\x84\xa2\x0a\xaa\xc6\x58\x1d\x16\x60\xf3\x40\x94\x6c\xa8\x58\x0c\x6c\x10\x69\xdd\x3b\x9d\xda\x53\x1a\xf8\x83\x55\x32\x3c\x69\xa1\xc8\x25\x42\xa0\x4b\x88\xe5\x90\xce\xb0\x4f\x6a\x68\x11\xc4\xdd\x8b\xe1\xcd\x4a\x1b\x11\xa9\x64\x41\x39\x12\xcc\x14\x54\x56\xbd\xc6\xee\xc8\x0f\x21\x51\x27\x1b\x0a\xe9\x10\x58\xa5\x38\x75\xf7\x61\x57\xd0\x31\x53\xad\xbb\x3f\xd2\x78\x88\xe0\x22\x20\x29\x3c\x84\x0d\xd7\xdd\xb1\xd0\xd0\x61\x22\x72\x06\x0c\xa6\xf4\x1b\x42\xff\x9a\xb9\x77\xe2\xd7\xb6\xd2\x4d\x3f\x67\x21\xbf\xd7\x9d\x11\x36\xdd\xfd\xd3\x7f\x03\xe6\x62\x84\xa1\x89\x2e\xc7\xee\x9e\x48\xde\x7e\x73\x5a\x6f\x1f\x6c\x8b\x07\xc0\xc7\xdb\xcc\x5c\xa9\x4e\x70\x7f\x47\x62\x85\xee\xf8\x6c\x91\x6b\xd9\x1d\xb7\x07\xda\xa1\x0c\x47\x02\xf0\x53\x0a\x14\xf7\x26\xaa\x4e\x87\x1c\x48\xa1\x50\xa1\x95\x56\x83\x93\xec\x24\x83\x52\x3b\x40\x0c\xf3\xbd\xe8\xa2\x87\x0d\x69\x8a\x00\x35\xac\x98\x58\x43\x57\xfc\xaa\xf6\x21\x12\x51\xd3\x00\x6e\x34\x77\x3d\x74\xe4\x74\xed\x9a\x0b\xd1\x10\xfd\x66\x06\xd6\x95\xe6\x35\x22\xe2\xa9\x00\x68\x68\xc0\xda\xa0\xa4\x36\x8e\x0c\x85\x26\xd5\x06\x16\x3c\xc1\x8b\x7c\xf8\x87\x18\x6d\x75\x59\x6c\x49\x7c\x02\x84\x61\x11\xfd\xd8\x1d\xb1\xbc\xef\x91\x8a\x5e\xa6\x6f\x93\xc1\xb8\x63\x86\x02\x1c\xff\x6e\x22\x1c\xd0\xb5\x6d\x72\x17\x73\x0a\x14\x8a\x21\x10\x4a\x3d\x04\x9a\xc2\x06\xd9\xe7\x8f\x84\x15\xba\x10\x17\x80\xa8\x9f\x2b\x9b\xd4\xcf\xc5\x22\x74\x27\xde\x1c\x8b\x3b\x7b\xb8\xd2\x9f\xb8\x65\xcd\xba\xfa\x85\x80\x2e\x53\xcf\xff\x89\xc2\x1e\x39\x9f\x89\x80\x0f\x4e\x63\x3b\x46\x40\xac\x5d\xf3\x2a\x47\xa3\x79\xec\x6a\x0c\x3a\x1d\x42\x38\xd7\xbd\x12\x6e\x25\x5a\x40\xdd\x42\x85\x63\x53\x5f\x8b\xee\x86\xdf\x90\x8d\xb0\xac\xed\x5c\x79\xec\x9c\x7c\x96\xd1\xd9\xa8\xca\x73\x7a\xc0\x0e\xeb\xa8\xa4\x47\x03\xf2\xb7\x50\x1f\x43\xff\x6c\x34\x54\x1d\xc2\x2e\xbc\x6d\x54\x77\xfc\x77\x35\xf9\xb9\x17\x33\x35\xce\x88\x88\xf2\xad\x89\xc6\x47\xb7\x90\xfb\xc2\xc9\xb3\x39\xa9\xef\x96\xf2\x8f\x25\x32\x79\x63\x9f\x3d\xda\x98\xe1\xf9\x06\x49\xc2\xba\x07\xd6\xef\x69\xd6\x76\x11\x31\xe7\xaa\x1a\x5b\xd7\xf4\x51\xca\x15\x02\x18\xc8\x3b\xe0\x83\x71\x8f\xa1\xea\x0c\x6a\x72\xa6\x20\xc1\xae\xc8\x4d\x67\x43\x5d\x68\x57\x26\x29\x30\x94\x50\x21\xb0\xe1\xa8\x13\x98\x42\xc0\xe2\xeb\xe6\x42\xa7\x00\x49\x94\x58\xb0\x5a\x42\x10\xe3\x20\xdf\x1b\xd2\xb6\x34\xfb\x45\xb5\xa9\x17\x91\xff\x28\xbc\xd8\xfc\xf0\xc3\xd2\x86\xbd\xcc\x7e\xc4\x3f\x02\x01\x9b\x3a\x4c\x14\x3a\xf1\x64\x27\xfe\x1e\x11\x21\x92\xd1\xc9\x1b\x95\x73\xf2\xb6\x85\xac\xc7\xf6\xf0\x1e\x9c\x38\x7f\x03\xf0\x3e\xb3\x52\x93\xf0\xb8\x18\x90\x0a\x24\xb1\x8d\x6d\x68\xe7\x48\x77\x91\x7a\x49\x6e\x8a\x1b\x8a\x1a\x02\x90\x3a\x09\x66\x82\xae\xf7\xab\x0d\x3d\x93\xe5\x11\xbf\x98\xe8\x55\xe9\xa4\xe6\x89\x7c\x68\x39\xc7\x3b\x74\x70\xba\xcd\x99\x6d\x22\x67\x71\x2d\x19\xfa\x49\x7a\x64\x84\xfc\x53\x16\x64\x78\xc7\xe9\x86\x96\x69\x62\x58\x1f\x96\x35\x4b\xbd\xe1\xac\x65\x11\x03\x34\x6b\xa1\xfe\x81\x4e\x93\xf0\x18\xe4\xf9\x80\x0c\xc8\x9a\x25\x3f\xf1\x65\x1f\x91\xd4\xa8\xd2\xbd\x22\x86\x42\x70\x4a\xf2\x05\xdb\x46\x63\x81\x86\x1c\x88\x5e\x23\x7a\x1b\xce\x45\x3b\x50\x84\xb0\x97\x6e\x5a\x47\xa9\x7d\xf2\xe9\x54\x84\x3f\x50\x28\x3e\x75\xa2\x78\xee\xc0\x00\xf6\x11\x60\xc1\x8c\x3b\x07\xd4\x30\x03\xcc\x52\x12\xd1\xc2\x96\xa3\xf8\xe7\x56\x9b\x40\x08\x9d\x85\x06\x9e\x4d\x51\x24\x44\xc0\x0d\xfe\xd4\x43\x54\xb3\xc3\x49\x89\x63\x5f\x04\x06\x41\x34\x44\x95\x84\x91\xa1\x53\x77\x48\x9e\x4f\xba\x91\x43\xaa\x1d\xb1\x38\x01\xf4\xab\xc6\x7e\xd1\xc5\x00\xa6\xf6\x78\x58\xdb\x53\xb7\x19\xec\x9d\x86\x24\x8f\x82\x00\x1a\xfd\x53\xfe\xc0\x0e\x64\xcd\xda\x23\x19\x1d\x64\xea\xb4\xd1\x3d\x3d\x19\xb7\x6a\x20\x2d\x7a\x97\xe3\x78\xab\x2a\x99\x1a\xc4\x1d\x04\x83\x58\xa1\xfe\x59\x75\x16\xa4\x13\x2c\x42\x47\x48\x9c\xc0\x1c\xe7\x81\x5d\x3c\x0d\x28\xf3\x6c\x85\xa7\xf1\x0b\xa4\xaf\x66\x24\xe9\xeb\xab\xca\xe9\xd3\xd7\x7f\x5e\x26\x09\x51\xbc\x2a\xfd\xbc\xe9\x3e\xff\x58\x67\x3e\x50\x09\x8d\xa0\x90\x16\xa1\xb4\x06\x2d\x0c\x54\x9b\xf4\x48\x93\x7d\xec\x24\x98\x4e\xd1\x2b\xfb\xda\x2c\x35\x2a\xce\x10\x26\xa1\xcb\xcf\xda\x8f\x26\x77\x86\x0e\xb7\xd4\x0d\xb4\x38\xa7\x74\x76\xc1\x7d\x87\xd0\x03\x4e\x2d\xac\x89\x49\x66\xc4\xec\x72\x2e\xff\xa2\x1d\x7d\x55\xfe\xef\x96\x72\x89\xbd\x4b\x77\x02\xc3\x14\xe6\x28\xed\xd1\x1a\x97\x24\xc4\x5c\xda\xa4\x34\x69\x13\x0f\xf3\xc7\x84\x61\x25\x45\x18\x20\x69\xab\x21\x48\xa3\x18\xb5\xa4\x44\x6d\x04\x71\x50\xd1\xe2\x48\x2f\x1e\xc4\x78\x46\xd0\x7e\x2f\xfc\xfd\x76\xdd\x2c\xcc\x38\x67\x8d\xdc\xf0\xbd\x7c\xe8\xf2\xd8\xfd\x7a\xe8\xc0\xf9\xa7\x82\xa2\x00\x36\x08\x61\x71\xdd\xdf\x43\x05\xfd\x01\x6c\xcf\xd0\x32\x81\x1c\xd0\xa9\xdf\x0c\x9a\x3d\x43\xf3\xc4\x79\x16\x1d\xdb\x07\xcc\x9b\xdc\x24\xf1\x90\xd6\x73\xaf\x21\x6b\x72\xb0\x7d\x18\x90\x72\xcc\xaa\xd0\x78\xad\x83\x4a\x0e\x85\x4a\x1f\xcb\xd9\xc9\x59\x9d\x96\xed\xa6\x5c\x0d\x9c\x6b\xfc\x27\x08\x5e\xf8\xda\xb1\x36\x9a\xb3\xbf\x41\x7b\x02\x94\x52\x41\x6b\x27\x4f\x3c\x42\x42\xfc\x0d\x99\x15\xeb\x97\xd0\xf7\x93\x24\x01\x0a\x31\x7c\xff\x89\x07\x0d\x72\xc1\x27\x15\x7e\x3e\x2e\x45\xe2\xb2\x5d\x60\xb7\x47\xe1\x51\x16\x0e\xc8\xa5\x94\x86\x66\xec\xa4\x01\x8c\xc4\x5e\xa3\x41\x41\x11\x09\xae\xa7\x42\x57\x27\xc2\xd3\xf4\xe8\xba\x5b\x9a\x23\xf6\x0c\xa9\xa6\x9d\xba\xc1\x07\x04\x2b\x19\xdf\x63\x76\x3c\xe5\x05\xbe\x9f\x77\x71\x13\xea\xfb\x86\xfb\x77\x99\x2b\x79\x14\xbe\x20\xdc\xf7\x8f\xfd\x7b\x6b\x5d\xdf\xa5\x47\x50\xae\xb7\xd7\xf1\xbb\xca\x7e\xf9\x16\x92\xb3\x7c\x45\x8e\x83\xe5\x60\x9e\x04\xc9\xd9\x59\xe6\x6d\x5b\x0c\x73\x01\x92\xd0\x84\xfc\x16\x24\xf5\x70\x37\xd6\xec\x47\x72\x19\x7d\x41\xd4\xe5\x17\x73\x8e\xc3\x55\xc1\x19\xdf\x2c\xb5\x2e\x48\x94\x78\x3b\x80\x32\x49\xf6\x72\xed\xb4\x70\xf0\x75\x5a\x96\x98\xcd\x7f\xb3\x67\xaa\xfc\x47\xd1\x12\x1e\xca\x5a\x33\xde\xfb\x0b\xd9\x26\xaa\x99\x19\x94\xb6\x08\xc5\x07\xbf\x69\xde\xbc\x9b\x06\xe0\x55\x40\xa0\xe0\x8f\xfb\x9b\x7a\x2e\xba\x7f\x93\xdb\xe8\x3c\xde\xcc\xc1\x84\x87\xf9\xb9\x23\xbf\xf2\x73\x63\x55\x8b\xa3\x25\xf4\x47\x7c\x4a\xf4\x21\x73\xc1\x49\x48\x43\xf1\xc3\xf1\xfb\x83\x55\x60\x7f\xdc\x9f\x7a\x3c\x79\x04\xed\x11\xe8\x93\x64\xe9\x93\x90\x85\xe4\x93\xa5\x28\xf5\xc9\x52\xc3\xf8\xd8\xc8\xc9\x16\x0a\x44\xcb\xe1\x13\x4c\xd1\x9f\x4e\xb1\x22\x1f\x1b\x0f\x2f\xa6\xc7\x7d\x12\x39\x77\x3e\x69\xd3\xf6\xc6\x88\x95\x8f\xba\x7f\xf0\x64\x7f\x19\x1b\x05\xe8\x55\x84\xd7\xda\xca\x7f\xf0\x62\x78\xef\xf4\xfe\x7c\xd9\xe8\xdf\x1f\x59\x7c\xef\x8f\x9b\x69\xef\x8f\x34\x2e\x6e\xc5\x4e\xbc\x95\x19\xf7\xbe\xb5\x04\x69\xa0\x93\x52\x87\xe7\x4f\x33\xd6\xc5\xec\x54\x51\xcc\x19\x62\xbe\x91\x01\x4d\x0f\xde\xa2\x86\x81\x86\xca\x19\x6a\x2a\xc3\x41\x2b\x16\x90\x97\x06\x90\xfc\x44\xdd\xc8\x4f\xf5\x0e\x29\x87\x77\x5d\xcc\x58\x67\x68\xa0\xe1\x85\x2d\xf0\xfd\xcb\x63\x30\xa8\xd5\xc0\x77\x7d\x5c\x7a\x16\x0e\x09\xe6\x65\x0c\x6d\x93\x0a\x0f\x8f\x83\xce\x7a\xa4\x4b\x2a\x29\xbc\x39\x28\x92\x28\x92\xfa\xed\xcc\x06\x5e\x33\xfb\x4e\xf1\x38\x84\xb7\xf0\xe0\xbe\x63\xdd\xf5\x5d\x0e\xc9\xaa\x44\x5a\xc3\xbb\x6c\x3f\x1d\x94\x75\xf7\x09\xdb\xbb\x98\xed\xc7\xab\x2c\xd7\xa9\xb3\x2d\xcc\x63\x77\x90\x0e\x21\x29\xcf\x60\x4d\x69\x38\x25\xf6\xb2\x0c\xb3\x08\x10\x81\x13\x7f\xad\x98\x04\xeb\x09\xde\x7c\xf8\x25\x37\xc1\x99\x7c\x79\x3b\xff\x2f\x54\x5c\x02\xcc\xaa\x32\x98\x5f\x3d\xfa\xe0\x5d\x62\x95\xf3\x5d\x86\x4d\xf5\x1a\x56\x12\xb1\x82\x48\x47\xef\xac\x38\xb3\x20\x6b\x16\x32\xab\xef\xf9\xe2\xcb\x86\xe7\xac\xa1\x36\x19\xc5\x86\x38\x51\x5d\xd7\xc5\xcc\x20\x1f\x4a\x20\xe0\xb2\x37\xdd\x16\x69\x35\x1b\xca\x12\x0a\x71\x74\x36\xc4\xff\xda\x20\x2e\xad\x9d\xfc\x09\xe9\x13\x91\x9f\xba\xe6\x8b\xa7\xa3\x02\xed\x88\xaf\xdf\xb4\xc1\xb6\x05\x10\x3f\x09\x5e\x04\x43\x55\x5e\xd4\x77\xfe\xed\x93\x7c\x89\xcc\x8d\x37\xed\x43\x08\xc8\x88\x92\xd0\xe0\x73\x56\x0e\x2c\xe6\x8c\xe0\x97\x7e\x0a\xc7\xf3\xc9\x4b\x34\xfd\xdc\x16\xc8\xc1\x11\x7f\x4e\xf9\xa7\x2c\x83\x04\x0c\xde\x8e\x84\x55\xb2\x9e\x94\xe7\xf2\xf1\xa0\x26\xcb\xe7\xaa\x32\x7c\x38\x30\xf5\xa5\xc3\x13\xca\x32\x6a\x30\x8d\x49\xf7\x9d\xae\x23\x94\x5c\xce\xd3\xc7\x6a\x89\xcd\x08\xf9\xc2\xca\x3b\x39\x95\x30\x87\x38\xdb\x90\xa9\x13\x8c\xcc\x6f\x0f\x10\x95\x13\xfe\x8d\xf8\x68\x2f\xd7\x35\xa4\x68\x56\xa8\x45\xfa\x1d\xfc\xd1\x12\x83\x2e\xc8\x9f\x5f\x99\xdd\xd9\xe6\xe1\xef\x1f\x95\xd4\x3b\x3d\x9b\x26\x0c\xab\x29\x72\xb7\xd7\xdd\xb7\x0c\xdb\x57\xad\x93\x6b\xae\x54\xe5\xf1\xbc\xea\x53\x0a\x2f\xcc\xf9\xb3\x32\x2f\x41\xe3\xf9\xaa\x83\xd2\xc7\x5e\x0c\xbb\xa6\x90\x4c\xd9\x19\x18\x86\x80\xb9\x42\xb5\x16\xfb\xac\x16\x2e\xac\xbc\xca\x4f\x17\xe3\x15\x43\x95\x01\x2e\xef\xbe\x10\x99\xd1\xfe\x2b\x59\x91\xec\xd3\x88\x42\x78\xba\xd9\xfe\xca\x4c\xf6\x7a\x79\x0c\xc5\x49\x94\x7b\xc9\xba\x80\xf5\x51\x48\x01\x47\xaf\x6c\x1f\xf3\x5d\xa8\x1c\xf9\xb2\x17\xeb\x3f\xc1\x7b\x90\x02\x8a\xbd\x9e\xba\xd7\x9b\xe9\x28\x2f\x64\x66\xf6\xb7\xa3\xe3\x25\x95\x93\x83\xea\x38\xf0\xa3\x9e\x01\x78\x9b\x5a\xd9\x02\x0f\xd1\x49\x65\xae\x57\xda\xde\x1f\x6f\xd4\x40\xf6\x3d\x0d\x3f\xfd\x97\xd2\xd4\x5f\x36\x2d\x5f\x43\x08\xe6\x7e\xc5\x11\x4b\xad\x02\x08\x16\x54\x77\xf3\x02\x8d\xee\xfa\x53\x8a\x71\x36\xbd\x97\x6b\xf3\xee\x4b\x9c\x6f\xaa\xc7\xde\x50\xbb\xa2\x7c\x2f\x2f\xb7\x1c\x4f\xc9\xd8\x40\x96\x4a\x20\x7f\x94\x39\x4f\x8d\x19\x84\x96\xc7\x31\xf9\x75\xc6\x59\x06\xe7\xc4\x5f\xda\x86\xd4\xf0\xb9\x11\xcd\x21\x31\xd2\x9f\x3f\x59\x9e\xbc\x8f\x05\x71\x37\x3e\x04\x02\x87\xa2\xec\x2b\x85\xf6\x0c\xc8\xa2\x93\x10\xca\x9b\xbe\xb6\xbb\x09\x9f\xdf\x10\x55\x3e\x08\x2a\x77\x30\x9c\xfe\xde\xaf\x39\x87\xf2\x3b\x96\x1f\xff\x28\xca\x78\x55\x6f\x39\x17\xee\xb5\x05\xc7\x63\x8d\xce\x0b\x04\xbf\xfa\xc1\x74\x38\xdd\x8b\xb2\x5e\xee\x79\x71\x89\xa5\x7b\xa0\x8c\xdb\xf5\x91\x5f\xe6\xfa\xac\x21\xe3\xf1\x61\x57\x7b\xd9\x68\x34\xd0\xd7\x7d\xbd\xb3\xbe\x26\x20\x92\xa9\x5f\xc1\xf5\x74\xc9\x4f\x8b\x52\xda\x30\x9e\x11\x76\xdd\x92\x7c\x41\xe2\x7f\x48\xc3\xdb\x44\x8b\x3d\x11\x64\x3a\x77\x99\x6b\xc0\x1d\x27\xff\x88\x01\x96\x6e\xc9\x51\x25\xe2\x52\x9b\xc2\x4b\x79\xc1\xc0\xa5\x0e\x08\xa8\xff\x1a\xd0\x2f\xca\x15\x3a\x31\xc8\x04\xff\x10\x82\x79\xa3\x38\x44\xdc\x01\xcd\x66\xc3\xbc\xd7\x23\x3f\xfc\x9b\xb8\x10\x1a\xa0\xc8\x98\xeb\x68\xc1\xa2\xd7\x61\xb3\x48\x84\xf6\x13\xbf\xe2\x4c\x8a\x03\x03\x80\xf6\x12\x5b\x18\x22\x85\x4e\x17\x51\x00\xca\x2a\xfd\x51\xd8\x4b\xf4\xab\x54\xfa\x19\x2e\x36\x65\x48\x59\x44\x14\xd4\xd5\x44\x5d\x2a\x48\x3a\xfc\xce\xaa\xbf\xc2\x4b\xec\xf4\xd6\x01\xaa\x5c\xa1\x6c\xab\x97\x55\x57\x2e\x4e\x41\xce\xa2\x48\x39\xef\x0a\x52\xa7\xab\x3e\xd9\xf1\x5d\x55\x62\x3e\x55\xbc\xb8\xae\x49\xe1\xe5\x2a\x59\xbe\xcb\x75\xb1\xfc\x54\x05\x16\x35\x8f\xea\x16\x0e\x0c\xd7\xfc\xd1\x67\x70\xc1\x03\x48\x15\x9e\xf9\x0e\x3d\x31\x40\xd7\xbc\x99\x8f\x3b\x74\x68\xd0\x47\xe7\x41\x90\x7d\xf3\x05\x92\x5d\x9e\xae\x4a\x9c\xa6\x84\xaa\x4e\x0b\xd5\xc5\x1c\x9b\x7b\xd2\xb6\xa7\xcc\x57\xe2\x41\xfc\xaf\x6a\xa3\x61\xe2\x66\xc8\xdd\xe4\x7f\x85\xde\x24\xa0\x81\x0f\x2c\xbf\x7e\x39\xf0\x36\xf5\xa2\x78\x92\xbd\x27\x7d\x0c\x57\xde\x45\xae\x68\xc8\x6f\x9d\x54\x8f\x17\x06\x96\x85\x63\xeb\xe5\xac\xad\x7c\x76\x08\xf2\xe2\x4c\xcf\x2c\x46\xde\x79\x7e\xe4\xb8\x56\xb9\x9a\x4f\xf5\x02\x11\xae\x86\xd7\x4b\x66\xd1\x95\xa7\x66\x00\x5e\x59\xea\x38\x6e\xc4\x5f\x94\x5a\xb9\xd2\xad\xe0\x37\x43\xf2\xfb\x5c\xe9\x0c\x66\x4e\x17\xbf\x59\xd5\xcb\xd9\x86\xf3\x3a\x56\x62\x68\x80\xb3\x15\x60\x8d\x2a\x16\x34\x6c\xa3\x3c\x78\xf4\xc6\x61\x19\x5a\x39\x69\xa6\x2d\x70\x21\x6f\xc2\xe6\x0c\x54\xb1\x59\xd2\xfc\xb9\xf2\x9b\x47\x3f\xd3\x29\x75\xfc\x2b\x85\x2f\xf9\xf2\x09\x0d\x81\x64\x75\x3a\x55\xf7\xfc\x7e\xd6\x1f\x1f\xf9\x17\x6b\xb7\x6d\x0b\x1a\x60\x92\x01\xf8\x1c\x92\x5c\xf8\x6c\x9b\x74\x30\x3e\x83\xb8\xd2\xcd\x92\x75\xf2\xf2\x77\x0e\x25\x1b\x04\x7a\x4c\xa1\x74\x63\xb7\x2e\xe1\x94\xf7\x4f\x3d\xfb\x7c\x65\x76\x5d\xe7\x7d\x7c\x24\x68\xb3\xe3\x85\x66\xc2\x4d\x6a\x36\xb5\x63\xb6\xb1\xcb\xdd\xf8\xc9\xc1\xcf\x97\x04\xba\xc4\xa3\x16\x8e\x99\xe7\x8d\xac\x6b\x0a\x3c\xdc\x4f\x5f\x0f\x3b\xef\xa9\xd1\xb7\xdf\xd6\x85\xe8\xce\xee\xe1\xad\xb8\x16\x83\xa1\x45\xe1\xbc\xff\x3a\xe0\xba\x2f\x99\x61\x50\xbf\x19\xab\xc4\x60\x9c\xbe\xce\xd1\x71\xbb\xfc\x1d\x00\x09\xff\xbd\x2b\xa4\xb6\xcd\x51\xdf\xcd\x2b\xe4\xe4\x67\x8a\xf0\x03\x66\x3a\x12\xd0\xec\xfd\x7d\xec\x1f\xc7\x70\xe1\x9c\x2e\x90\x15\x97\xc9\x2f\x89\xce\x1c\x9a\x20\x03\x79\x58\x80\xf0\x1c\x47\x26\x26\xaf\x03\xad\x2a\xfb\x50\xc4\xb1\x89\xbe\x62\xa9\xa1\xb6\xc3\x1b\xbf\xaa\x44\x7d\x20\xa8\x63\x06\x78\x28\xbc\x54\xa9\xca\x54\x7e\x5d\x06\xc6\xf8\x4f\xff\x9c\x75\x6e\x83\xa3\x32\x35\xcf\x0b\x19\xa8\x3c\x77\x09\x21\x72\x83\x71\xcf\xe4\xd3\x3c\x03\xa7\x98\xde\xdb\x96\xbc\xd4\xae\x8e\x93\xfa\x80\xbc\x0b\x64\x91\x12\x6c\x3f\x45\xa1\xbc\x35\x69\x9d\x65\x89\x0b\x64\x05\xdd\x38\x8a\x1e\x43\x1b\x7d\xa8\x06\x99\x11\x1d\xcf\x0c\x9e\x41\x3e\xd3\x2c\x05\x2f\x08\xe7\x14\x70\xf0\x09\xeb\x37\xe9\xbc\xf4\xb6\xa0\x32\xce\x6a\x35\xf6\x2a\xc0\x45\x74\xb1\xc4\xac\x8d\x19\x44\x32\xf2\x81\xe3\xdf\xb0\x6b\x02\x85\x08\x03\x70\xfa\x61\x09\x2a\xba\x2a\x49\x04\x56\x9c\xd7\x2f\x71\x07\x7a\x3b\xf1\xb2\x5b\xd0\xbe\xc1\x41\x55\x1c\xae\x96\xd8\x6e\xc6\xcc\x87\x7d\xd0\xb9\xc3\x10\x61\x85\xf7\x83\xf2\xa9\xae\xaf\x13\x92\x37\xd5\x2c\x5e\xb9\xec\x4f\x50\x29\xfb\x4d\xec\x85\xa4\x9e\x66\xe7\x32\x5e\xca\xa3\xeb\x4e\x01\x18\x66\xda\xd9\x6b\x90\xc3\x64\x47\xda\x28\xbb\xe2\xb8\x5c\x43\x87\xd1\x9e\x06\xed\x46\xd5\xba\xcd\x8a\xf7\x53\x83\x01\x81\xfa\x4f\x08\xd5\x39\x04\xe2\x20\x5d\xcd\x4a\xea\x2a\xd4\xa3\x6b\x87\x47\x1b\x40\xd6\x8b\xdf\xbb\x02\x5f\x6d\xda\x56\x25\x68\x54\xa5\x4b\x54\x5b\xd8\xb0\x2b\xee\x60\x89\xcc\x31\x7b\xc1\x73\x2b\x4a\x63\xb6\xc9\xbb\x04\x25\x56\x3a\x3c\xa0\xc1\xb3\x85\xf6\x4e\xad\xee\xa6\x35\xc0\x79\x0d\xde\xce\x57\xa5\x3d\x66\xf6\x18\x6b\x38\xd5\x0d\x71\x79\xe7\x04\x39\x53\x48\xf2\xdc\x3e\x7e\x21\x80\x7a\x63\xf9\xd2\xd9\x97\x2a\x12\xa1\xf3\xa7\xec\xb1\x14\x8f\xc4\xb2\xc9\x67\xa8\x78\x2c\x29\xc4\x7d\x9e\xf7\xc8\xef\x12\xcc\x19\x7e\x99\x67\xf8\xad\xce\xa7\xd3\x23\x9d\xcf\x47\xe6\x66\x51\x92\x9c\x0d\x9e\x94\xc2\x35\x40\x06\x0e\x00\x76\x17\x4f\xaa\xec\x9d\xe5\xdf\xb3\x35\x1f\x99\x15\x67\xd1\xd5\x8b\x54\x61\x4a\x74\xa5\xe5\xa0\xfa\x49\x09\xb6\x58\x20\xfe\x67\x93\x1c\x2e\x50\x6e\x5f\xa3\x0d\x11\x75\xe5\x4f\x40\xa8\x28\x19\xa1\xe5\xc5\x55\x87\xb3\x55\x14\x4b\xab\x7a\x87\xe5\xf9\xa4\x25\x73\xc2\x36\x08\x31\xa1\x2c\x01\xa5\xa2\xb0\x6b\x00\x55\x32\x8f\xcf\x40\x3f\x45\xa1\x4e\x2d\x41\xf4\x47\x67\xe9\xef\x58\xe9\x3d\x9b\x72\x88\xf3\x20\x01\xcc\xf7\xaa\xda\x1b\xb2\xd9\x16\x1f\xcd\x7c\xff\x15\x0b\xba\xc1\xbf\xcf\x0b\xcd\x37\xd7\x1f\xcf\xf9\x88\x43\x0f\xac\xb4\x39\x82\x95\xc8\x53\x55\xd1\xc2\x01\xf1\x77\xe5\x15\x6a\x3e\x65\xb3\xa3\x6e\x41\x4a\x7f\xd8\xf0\x5d\x25\x22\x69\xb8\xb8\x8f\x0e\x1c\x25\x54\xb4\x42\x3a\xed\x4d\x51\xac\x39\xfa\xc8\xd9\x19\x1d\x98\x6c\x07\x81\xa1\x97\x64\x8a\x6c\x16\x7c\xa5\xd8\xb9\xb3\x2c\x71\x94\x26\x76\xd0\x21\x92\x42\xc9\xec\xeb\x5e\x42\x7b\xec\x92\xca\xdb\x6c\xd6\xc9\x47\x40\xe2\x41\x20\x2f\xd0\xe1\x0c\x34\x3c\xf3\x27\x9a\x50\x16\xad\xe0\x09\x5f\x37\x85\x7e\x14\x11\x7f\x62\x1e\xa1\x1e\xc4\x03\x7f\x09\xb8\x2d\x46\x0d\x00\x9d\xa7\xd9\x1b\x19\xa2\x8c\x7a\x3b\x79\xe3\xe3\xce\x5a\x7a\x38\xf3\xba\x8b\xac\xff\x44\xc3\xd0\x3e\x04\x28\x38\x5a\x9c\xdd\xef\x8c\x17\x9f\x97\xce\xdd\x6b\x67\x48\x7d\x42\xab\x88\x05\x3f\x70\x9b\x7c\xb3\x8c\xf4\x62\x43\xf6\x1b\xb9\x6c\xce\x3c\x30\x7c\xfe\x8c\x8c\x87\x33\x27\x24\xa2\x13\xf5\xea\xfe\x73\x12\x6f\xd7\xd9\xdf\x1b\xe3\x83\x5d\xbf\x68\x62\x07\xd8\x1f\xf0\x24\xb6\xd7\x06\x0e\xc5\x5d\x54\x34\xb6\x91\xa2\xd7\xb6\xb3\xf1\x7b\xef\x6b\xc7\xe7\x67\xb3\xf3\x44\x85\x4b\x48\x1b\xdd\x54\x42\x05\xa4\xd8\x86\x23\xcd\x02\x5d\x06\xe9\x88\x43\xc5\x89\x4e\x41\x24\xa7\xdb\xb8\x79\x35\xb3\xfb\x25\x5a\x74\xd3\x94\xc3\x7c\xd7\xff\x3d\x69\x2b\x64\x8b\x6e\xa7\xe6\xd6\xc1\x87\x7a\x7a\x2c\xf1\x35\x4d\xa2\x2a\xe2\x11\xc0\xed\x8f\xaa\x52\x65\x3a\x68\x3b\x2c\x6e\xcf\x50\x47\xb0\x95\xeb\xdb\x64\x90\xa2\xf3\x35\x94\xee\x90\x54\x22\xaf\x08\x40\xfe\x49\x2e\xad\x2e\x5c\xb1\x70\xc3\xba\xdc\xfc\x93\x47\x6a\x5a\x2e\xbe\xd1\xd5\x59\x37\xb7\x48\x80\x0f\x28\x78\xd4\x7c\xa3\xfc\x95\x53\x0a\xd1\x0c\x6e\xc4\x13\x58\x9a\xda\x1e\x16\xcf\x55\xc7\x12\x8f\xe4\x27\x0c\xe6\x12\x4b\x85\x28\xdf\xb1\x0f\x8d\x53\x52\x55\x73\xfe\xa9\x2b\x2d\x7a\x04\x0c\x63\x76\x60\x0f\xcb\x1d\x15\xda\x6e\x62\x51\xbf\x27\x9a\x8e\x5f\xd5\x53\x17\x2a\xa0\x67\x4f\x93\xa6\xc7\x44\x4b\x48\x52\x6a\x06\xc6\xb6\x6f\xd1\x97\x93\x3e\xd2\x4c\xfa\xf8\x34\x0f\xea\x4c\x7c\xdc\xce\x50\x2d\x6a\x05\x6c\x24\xac\x9e\x10\xb3\x27\x42\x28\x3b\x7f\xca\x5e\x2d\x1d\xc8\xcf\xbd\x08\x25\xa7\xe4\xdc\xd5\x7e\xbf\x58\x5c\xfc\x34\x24\x01\x28\x04\xad\x13\xfc\xd1\x44\xda\x46\x9e\xc3\xba\xc3\x77\x80\x2c\x20\x29\xa0\xf3\x8f\x19\x15\xf2\x1e\x0e\x24\xda\x84\x5c\x71\xf7\xcb\x19\x94\xf6\xd3\xca\x81\xde\x7a\x3d\x1d\x9c\x24\xea\x64\x7d\x83\xd4\x91\x0d\x5f\xa2\x8f\x30\x78\x4e\xf2\x82\x9d\xa1\x5b\x0f\x6e\x7e\x49\x3a\x85\x08\x94\x0d\xa3\x2a\xbd\xb0\xde\x7c\xa9\xb7\xf4\x9e\x28\x13\x72\x5a\xcf\x40\x6d\xb5\x34\x4d\xf1\xcc\xa7\x84\x69\x05\x71\x08\x4d\x85\x12\x94\x35\x07\x5e\x24\x2d\xae\x17\x28\xcc\x62\x70\x3d\xc3\xe3\x43\x59\x9d\x8f\xb4\x87\x3e\x54\x8b\xf9\xb8\xcf\xf4\xc0\xfa\x90\x8c\xc9\xe3\xfe\x4a\x10\xe9\xfe\x48\x72\xe5\x7e\x55\x2f\x48\xcb\x74\xdc\x9c\x05\x98\x69\x38\x28\x5e\x07\x30\xab\x4c\x92\x6e\x62\x48\xda\x61\x46\x8c\x52\xb4\x11\x0f\x27\xbb\xf4\xb8\x3d\x53\xf5\xb8\x7d\x69\xf5\xf0\xe8\x3b\xa9\x40\x31\x07\x0f\xd3\x21\xc4\x6a\x51\x7a\x48\xb1\x5a\x2d\x32\x0e\xd3\x23\xb8\xb8\x63\xef\x6c\x83\xd1\x4f\x73\x0a\x29\x09\x1e\x56\x41\xb4\x09\x25\x96\x3c\xbb\x8d\xed\x92\x7a\x62\x60\x2a\xd4\x9c\x36\x70\x77\x9d\xb1\x11\xe7\xca\x5b\x8f\x35\xf7\xef\xdf\xad\x38\x88\xd6\xe5\x51\x15\x4e\xe2\x6a\x82\x17\x17\x59\x91\x5f\xcd\x7f\x82\x5f\x80\x79\xcd\xc0\x52\x5e\x7a\x4a\x09\x6a\x86\x7f\x8d\x57\xca\xd7\x1c\x37\x64\xf3\xdc\xb8\x97\xa1\x69\x4c\x0d\x91\x26\x7c\xd4\xa1\x71\x3d\x00\x8f\x71\x68\x92\xe4\x33\x6c\xbb\x78\x50\x36\xfd\x92\xe2\x57\x24\xe2\x03\xa8\xba\xdd\x22\x99\xaa\x6e\x91\xfa\x13\xe7\x90\x9e\x45\xc3\x43\x7c\x30\x3c\xb4\xc8\x6b\xa5\x77\x4f\x56\xfa\xc5\xcb\x3f\x0a\xfb\x58\xa3\x2f\x3e\x18\x1f\xb4\xcd\x10\x99\x18\x82\x78\x86\x0f\xcc\xb0\xf9\x6f\x4a\x67\x61\xbd\xc2\x4b\x84\xda\x3a\xa0\x83\x0b\x2e\x3b\x35\x4f\x8f\x0a\x8b\xd8\x32\xcf\x63\x2a\x52\xf7\xc1\x24\x91\x8f\xb6\x84\x8e\x56\xa1\x2b\xef\x28\xf9\x19\xa5\x8e\xcd\xfd\x1c\x72\x50\xf0\x5e\xf2\x68\x0d\xb6\x98\x94\xfd\xc4\xae\x4a\xdf\xd6\x42\x80\xb3\x34\xd0\xf2\xc7\x0c\x78\x3f\x69\xfe\xc7\x9e\x13\xc1\x18\x59\x32\x4c\xfb\x1e\xd2\x64\x79\x27\xd1\x21\xc8\x19\x6f\x2e\x6f\x1f\x59\x1a\x36\x47\xf6\x4c\x7c\x4a\x8a\x21\xf4\x4a\x7b\xed\x69\x48\x60\x69\xb4\x69\xc5\x10\x7b\xc7\x00\xdd\x29\x65\xaa\x5c\x64\x33\xd8\xd4\x5d\x9a\x4a\xe1\x6d\x32\xdb\x71\x90\x60\xd3\xa0\x50\xd9\x23\xf7\x9c\xa1\x18\xb8\x65\x77\x19\xd4\x0f\x7b\xc5\x28\x1c\x41\x37\x69\xd3\xf8\xa5\x63\x7c\xce\xa1\x68\xab\x23\xe2\xf1\xe1\x04\x3d\x92\xf7\xad\x06\x7d\x7d\xe0\x48\x6f\xb6\x91\x04\xbd\xfb\xc2\x5e\xf9\xf0\x44\xfa\x2a\xb4\x85\x92\x9b\x9c\xa5\x56\x52\x69\xe9\xba\xc4\x3b\xe3\x50\x02\x4b\xd7\x3c\x4a\x73\xe9\x4a\x0f\x2f\xed\x61\xf4\x0e\x28\xdb\x94\x88\x11\x80\xcd\x8a\x6c\x41\x23\x74\xe8\x19\x78\x2f\x7e\x26\xee\x5a\x29\x95\x96\xc0\x63\x7d\xe8\x2e\xca\x36\x27\x81\xc8\x6b\x3f\x22\xcc\x02\x40\x72\x6b\x50\x30\xe5\xed\x20\xc5\x91\xd5\x1b\xee\x5e\xbf\x1d\x48\x05\x76\x84\x78\x26\xf4\x8b\xd8\x2f\xa4\xfe\xfb\x47\x93\xca\xa6\x0f\xe4\x2a\xfb\x9f\x13\x4d\xbb\x63\x16\xce\x3b\x85\x2f\x82\x01\x9c\x0b\x3a\x20\x00\x6f\xde\xad\x3d\xc8\x9c\xf6\x7b\xf7\x48\xd2\x3d\xb4\xf3\x76\xd9\xda\xfb\x3d\x49\x3c\x8a\xfa\x30\x07\x09\xd5\x76\xeb\x2b\x39\x84\x42\xfa\x49\x7e\x0d\x83\x3e\x0a\xc0\xc2\x7d\xc6\xca\x34\x36\xd4\x3d\xef\xf8\x8c\x78\xa0\x07\x61\xd0\x2a\xdb\xdd\x03\x25\x19\x29\x10\xe5\x52\xdb\xe5\xc8\x14\xd8\x39\x22\x2b\x17\x68\x8b\x13\x21\xb3\x9a\x2a\x36\x58\x86\x39\x03\x78\x19\x52\x30\x1e\xfe\x7b\x0a\x95\x10\xb1\x12\x37\x82\x01\xaf\xaa\xd2\x40\x77\x4f\xe7\xa1\x0e\x0d\xb2\x74\xf2\x3b\xb9\x53\x8d\x1b\x04\xbd\x14\xa4\xa0\x5a\x4e\x24\x09\x9b\xba\x37\x21\xa9\x9d\xd3\x2b\x03\x08\x02\xf1\x1b\x80\x1d\x75\x85\xd0\x4e\x0d\x57\x03\x10\xcf\xbb\xc8\x55\xba\xbb\x0a\x82\x8e\x6a\x3f\x7e\xc2\x51\xcf\x6a\xd9\x98\x3d\xe4\x7f\xa1\x50\x85\x90\x17\xe9\x2a\x99\xf9\xf8\xf5\x56\xbc\x2f\x12\x28\x5a\xb2\xf4\xa4\xf2\xa5\x6a\x23\xf1\x65\x21\xb0\xc9\x32\xff\x99\x3e\x6a\xd2\x06\xff\xb9\x15\x02\x49\x29\xaa\xe0\x2c\x29\xa4\x6f\x77\x68\x0d\x78\x53\x35\xd4\x17\xef\x05\xf7\x72\x86\x07\x72\x2f\xdb\x9d\xb9\x8a\xb7\x97\x46\xa1\xb1\x17\xd9\xc5\x7b\x51\x06\xd1\x8e\xf5\xcb\x10\x8d\xda\xf8\x86\x68\x8d\x5a\x71\xa9\x94\xa0\x0d\xe4\xa7\x20\x4e\x45\xfc\xbc\x79\x30\x48\x5b\x64\xe9\xdb\x86\x6c\x5e\x43\x21\x2a\x55\x32\x52\x7f\x99\xc9\xbe\xa3\x13\x96\xb7\x01\xac\x9c\xad\x12\x08\x21\x3f\xe5\xfa\xdf\xa5\x1e\x04\x12\x80\xc8\xad\xdb\xcd\xcc\x77\x0f\x1a\x34\xaa\x96\xb2\x4b\xf8\x68\xf6\xd8\x60\x7f\xb6\x20\x53\x98\x78\xa8\x58\x42\x77\xcc\x21\xa5\x7f\x94\xaf\x43\x52\x63\x40\x2b\x17\xb4\x1c\xc3\x3f\xe6\xd8\xa7\x39\xbb\xe7\x60\x73\xe4\xda\x99\x56\x7a\x85\x56\xd4\xa1\x06\x91\x0f\xc9\x3b\xa3\x3f\xbd\x58\x86\xc2\x93\x9d\xaf\x48\xd3\x6a\x8b\xd0\x00\x83\xdb\xa7\xe7\x14\x68\xa7\xde\x01\xef\xd3\x70\x92\x03\x0c\x8e\xfb\xd6\x88\x6c\x44\x91\x52\xbc\x19\x59\xf4\x7d\xef\x31\x61\x31\x40\x49\x36\xe6\x8d\xec\x59\xca\x5b\x45\xf4\xe8\x7b\xd6\xd0\xb6\x5b\x87\xcf\x8a\x88\xa2\x6e\x87\xe4\x2e\x4f\x91\x8a\x8f\xe8\x7b\x52\x86\x96\x01\xda\x62\x7b\xb2\x4f\x86\x72\x4b\x2f\x49\xaf\x52\x84\x8a\x72\x4e\xaf\x06\xa4\xc9\x74\x6b\xdd\x10\xfa\x54\x14\x48\x4b\x97\xbc\x81\xbb\x33\x68\x27\x21\xed\x09\xc3\x17\xe9\x1b\x4d\x99\xea\xa4\xd5\x4d\x8d\x2a\xbf\x59\xa7\x41\x91\xd2\x94\x3d\x5a\x5e\xc1\xf5\xff\x1c\xed\x2d\x6a\x0c\x92\x53\xe4\xf4\xdb\xc5\x50\xef\xe2\x53\xda\x31\xdc\x87\x50\x08\x76\x91\xce\x68\x87\xf6\x2a\xcb\x45\xfa\x4f\x2e\x47\x35\x11\x24\xe5\x06\xed\x52\x6f\x4b\x8f\x8b\xdf\x91\x59\xe4\x58\xc5\xa2\x30\x58\x8a\xf6\x8d\x6c\x76\x96\xe8\x43\xde\x29\x36\xa4\xc8\x35\x51\x62\x2c\xe9\xd3\x4f\xda\x8c\xb7\x94\xfa\xc5\xe7\xaf\xd0\xb7\xd2\x2b\x45\x0a\x53\x88\x64\x71\xca\x5e\x15\x78\x5b\xbf\x85\xd3\x90\xfa\x4d\xbe\x5c\x53\xdf\xec\x85\xea\x2d\xaf\xbd\x4d\x1e\x96\x50\x6d\xa9\xb7\x47\x5d\xfb\xf1\x18\x59\x38\x64\x79\x2e\x5e\xf3\xf4\x56\xd1\x6b\x6c\x81\x97\x3a\x07\x14\xfb\x52\x75\x6e\x31\x8e\xb7\x66\x32\x1f\xfe\xb9\x40\x23\xcb\xdf\x55\x0d\xfe\x63\x9f\xb7\x67\x27\xfc\x74\x32\x10\x49\x67\x55\x3a\x0e\x99\x1e\xa1\x03\xf3\xe3\x66\xec\x82\x75\x73\x95\xd3\xc7\xba\x9f\xd2\xb3\xda\xf5\xd5\xd4\xad\x8e\xde\x90\xea\xc6\x60\x58\x33\x98\xe7\xea\xfe\xf4\xba\x9c\xdf\xfa\xf6\x6f\xdc\x20\x57\xd8\xaa\x22\x9e\xaa\xac\x8a\x2a\x27\xa1\xf5\xde\xff\xf8\x9b\x21\x96\x54\x0c\x8e\x49\x86\x97\x75\xe9\x74\x55\x9b\x15\xbe\xb1\x08\x19\xae\x27\x1c\xf9\xbd\x23\x8a\x6f\x31\x14\xbe\x62\xce\x1f\xeb\x02\x20\xba\xcc\x8a\x76\xaf\xc3\x46\xa6\x52\xf0\xc9\xf8\xf7\x05\x97\xf1\x93\xca\x00\x75\xa0\x6b\xbc\xf6\xcc\x77\xa9\x1d\xa2\x5a\xf5\x3d\xd5\xc4\x20\xb0\xed\x96\x8e\x9b\xe7\x19\xd3\x4c\x36\x58\xbf\x2c\x37\x9b\x95\x90\x4b\xd0\x36\xa8\xac\xb3\xc1\x1b\xce\x1e\x72\x73\xc2\x60\x4a\x6a\x41\x79\x2b\xd4\xb6\xcc\xc2\xf1\x40\x9d\xad\x6a\x2d\x6e\xa3\x90\x91\xd7\x1f\x22\x5c\x54\xce\xaa\xc7\x94\x68\x0c\x6e\x48\x5f\x4d\x02\xdc\xd1\x41\xd3\x13\xa8\x7c\x8b\x62\x3d\x37\x0c\x2a\x21\x83\x55\xf2\xcb\xbf\x10\x70\x13\x41\x92\x93\xd0\xbf\xa7\x0d\x7c\xcb\x4d\x6a\x4c\x5b\xa9\x68\x0b\x69\xa6\xfe\xc3\xfc\x6e\xda\x5a\x3d\x0d\x5d\x43\x6d\x1a\xb7\x65\x44\x0e\xf0\xc0\x17\x07\xbd\x4d\x0b\x5b\x10\xdc\x8a\xc6\x1c\xcc\xfa\x5b\x8b\xc5\x42\xce\xa7\x57\xdc\x86\xd9\xcb\x4b\x32\xe9\x62\xdc\x69\x40\x47\x96\xd0\xe8\x2a\x74\x8e\x6d\x61\x7d\x6f\x8c\xaa\x40\x82\x1e\xfb\x08\x43\x21\xad\xb4\x31\x20\xd8\x8a\x21\xce\x83\x5a\x73\x7c\x40\x7b\x70\x33\x66\x03\x8f\x94\x37\x4b\x43\x63\x0b\x80\xdd\x12\xe3\x9d\xb7\x14\x32\x5f\x20\x5c\x63\xf7\x89\x4c\x44\xbd\xc2\x44\x2f\xed\x96\x1a\xa9\xe3\x06\xc3\x96\xcb\x75\x1e\x5f\xe3\x5f\x05\x8c\xb0\xc2\x1f\x3c\xb9\xce\xb3\x29\xfd\x6f\x6b\x91\xf3\x5b\xea\xd0\xd9\xac\x9f\x23\x31\x77\x72\x85\x9a\x9b\xab\x5d\xbc\xd3\xb3\x5c\x6f\xfa\x1c\x20\xea\xf5\xf1\x12\xec\xed\x12\xcb\xb8\x19\xa9\x84\x52\xf2\x0e\x80\x14\xb9\x00\xa0\x40\xc6\xfd\x4b\xf0\x5c\x29\xe5\xef\xb2\x60\x3e\xf6\x1a\x1a\x29\xa5\x62\xc6\x30\xcf\xbf\xe1\x05\x08\x4a\x58\xe3\xde\x44\x60\x03\x39\x5b\x69\x88\xdc\x41\x35\x6b\x28\x49\x64\x0c\xcb\x25\x5b\xfe\xd7\xb0\x9c\x30\xd0\x0e\x9b\x75\x26\x68\x29\xe8\x80\xd0\xfa\xb9\x75\x1a\x30\x43\x52\xb6\xe8\x6e\x6b\x3c\xeb\x3d\xb0\xb7\x76\xc0\x3d\xc8\x11\x54\x2c\xb2\x6d\xcc\xa1\xf4\xf5\xe5\x27\xb2\x56\xad\x40\xac\xf5\x5e\xb8\x20\x8d\xee\x83\x2a\x2a\x35\x46\xb6\x55\x1e\x87\xd5\xdd\x04\x5e\x49\x52\x2c\xad\xf8\x26\xff\xa8\x8f\xcd\x44\xa1\xc5\x75\x14\x1d\x3b\x29\x59\x1e\x6d\x43\x6f\xa1\x1e\xd4\xc0\x01\x0b\x14\xff\x55\xcf\x10\x3a\xb3\x31\xb1\xea\xc2\xb0\xd6\x6a\xa0\x09\x71\x17\x1f\x6d\x51\x19\xc6\x85\xc6\x4a\x6d\x90\x00\x4e\x2d\x5e\x7a\xfb\xfb\x9b\x29\xe9\xff\x43\x88\x6e\xd5\x0d\xce\xe4\x38\x55\x08\x8b\xb9\x7c\x9c\x23\x8a\xd3\xb8\xa8\xd8\x9c\x6e\x9d\x1e\x89\xce\xab\x50\x0d\x55\x97\xaa\xd1\x61\xad\xcf\x78\xc6\xe5\x94\xfa\x4b\x05\x5d\xbc\xa4\xd5\xe6\x50\xee\xaa\x60\x6b\xe4\xf5\x42\x8d\x8d\x53\xa2\x35\xf2\x86\x1d\xa8\xec\x59\xfa\xec\x6d\x45\x62\x3a\xe5\xb5\xdc\xa1\x08\x29\x32\x32\xd4\x03\x49\x9f\xcb\xe9\xdb\x2e\x66\x64\xdb\xc7\x86\xb1\xf0\x22\x94\x3b\xc8\xe9\x3d\xb0\x02\x4b\x2d\x9c\x72\x84\xce\xe4\x5a\x2a\x15\xf8\x0d\x70\xc8\x35\x7b\xe2\xca\x02\x3c\x62\x83\xfd\x13\x0a\x64\x92\x46\x5b\x43\x23\xac\x49\x8b\xd5\x8f\x40\x69\x72\x63\xfc\xa0\x0d\x68\x40\x86\x72\x98\x8d\x24\x84\x60\xda\x97\xda\xd9\x33\x64\xc3\x16\x49\x99\xd9\xdd\xf4\x7c\x0a\x05\xd2\x56\xf2\xbe\xc4\x86\xc3\xd0\xf3\x2a\x03\x17\x8f\x3c\xbf\x5a\x02\x70\xee\x22\xd7\x4e\x49\x18\xe5\xaf\xc4\xbc\xde\x27\x0b\x89\x7c\xc1\xed\xeb\xf5\xc9\x4d\x39\xeb\x54\xb5\x6c\x7a\xa8\x81\x73\x85\x9a\x2a\x9b\xb7\x7d\x98\x7a\xa5\x88\x16\x39\x24\x46\xe6\xaa\xae\x14\xcc\x70\xcc\x45\x9c\xb5\x31\xbd\x80\x3b\x85\x24\x7d\xab\x13\x93\xeb\x04\xc8\xe7\xae\x84\x24\xb2\x43\x3e\x0c\x4d\x68\x20\x3e\x62\x74\x5f\xda\x53\xaf\x38\x8a\xbf\xda\x26\xdd\x1c\x18\xf4\x24\x3e\x16\x9c\x08\xae\x3a\xa6\x6a\xe0\x41\xf3\xbd\x21\x55\x82\x02\x58\x88\x28\x1e\x42\xea\x0c\x3c\xfe\xca\x1d\x5d\x73\x5b\x98\x58\xf3\x7c\xa9\xc1\x60\x89\x28\x54\xc7\x42\xfe\xc7\x06\xc7\x22\xf9\x20\x84\xde\x38\xe8\x2f\x26\x86\x3b\xf0\x72\x6f\x51\x99\x6b\xef\xe4\x23\x44\x39\x94\x89\x5c\x11\xec\x2d\xa5\xaf\x25\x4b\x58\x2b\xa4\xbf\x96\xf4\x0a\xe9\xaf\xa7\x7d\xe5\x4d\x25\x6c\xd3\xeb\xec\x9f\xb1\x2b\xc7\x45\x9e\x7a\xe3\x7d\x59\xde\x36\x2a\x49\xd2\xac\x80\x42\xd9\xd1\x74\xd0\xf0\x81\x2c\xd8\xad\x4f\xbf\x87\xef\xa0\xb4\x8d\x26\xd4\x35\xfa\x92\x34\xef\xcc\x1e\x1d\xe3\xf3\xd6\x7e\x50\x3a\x85\xab\x7e\xfd\x50\xa7\x5b\xef\xb9\x38\xe6\x60\x69\xaa\x61\x55\x9a\xb8\x84\x29\x8e\xa0\x6b\xce\x35\xc3\x42\x49\x0c\x43\x45\x08\x8c\xb9\xe9\x17\xd8\x5a\x61\x53\x10\x13\xfb\x16\x25\xc6\xd8\x40\x00\xd5\xeb\xf5\xbd\x8b\x83\xeb\xd2\x18\x80\x75\x15\xad\xa5\x01\x51\xfc\xaf\x47\x34\x4c\x08\xa5\xa1\xe3\x0a\xf4\xd3\x28\x43\x36\x5c\x08\xa4\x21\x84\x83\x07\x4b\x7b\xd8\x4a\x6d\xde\x8d\x25\xd2\x36\x0a\x19\x74\x21\x66\x16\x12\x53\x1f\x89\x17\xa6\x7f\x91\xc6\xb6\xa6\x7b\x09\x31\x31\x9b\x19\x95\xd4\x94\xcc\x42\xa8\x2c\x6e\xd8\xec\xb4\x10\x0a\x83\x9c\x59\xfb\x3f\xf5\xfe\x92\xbc\x29\x50\x36\xe3\x6c\x7a\x45\xf2\xa4\x14\xb7\x6c\x38\xe3\x39\xce\x10\x0f\xc3\xc2\xa4\xbb\x06\xa1\x61\x56\x34\x2c\x3b\x97\x83\x1e\x2a\x74\x52\x34\xd5\x06\xd6\xd4\x10\xba\x65\xf7\xa0\xbb\x39\x14\x0b\xb0\x46\x42\x27\x72\x05\x42\x0f\x4d\x12\x6a\x47\x0e\xdd\xb2\xdc\xc4\xcc\x3c\xb9\x48\x34\x37\x2e\x68\xc6\x77\x07\x4e\xfe\x68\x80\x69\xfb\xde\xf9\x4a\x82\x09\x19\xd8\xda\x40\x44\xa0\x1a\x4c\xda\xa2\x6f\x49\x1b\x1c\x73\xbc\xd0\x56\x43\xec\x2c\xe4\xcc\x7e\xe2\xa1\x69\x7b\xa0\xa9\xb0\x8a\xdb\xa4\x47\xb8\x85\xf2\xd7\xf6\x1b\xde\x52\x48\x19\x82\x13\x52\xf7\x1b\x7e\xfb\x35\xad\x0c\x57\x59\x11\xef\xce\xbb\x58\xe2\x51\x35\x0d\xb0\xa8\xb1\x9a\x50\xfa\x29\xf2\x00\x4b\xbb\xd2\xd0\xa4\x9e\x1d\x3a\xd0\xf3\xaf\xa6\x5e\x69\xbe\xb4\xa7\x34\x6e\x10\x86\xb0\x67\xc6\x4d\xad\xe9\xf1\xe7\xb6\x1e\xd4\xeb\x4b\x0f\x78\x27\x79\x68\x39\xd5\x6c\x8a\x88\x0b\x5d\x32\xad\x34\xf9\xb4\x29\x94\xd7\xe6\x25\x04\xeb\x38\xd8\xa6\x09\x6b\x67\xdc\x33\xed\x66\x12\xf2\x79\x4c\x5b\x68\x9f\x4d\x21\xa8\x36\x65\x1b\x4c\x79\xfb\xbf\xbc\x30\x60\x44\x29\xf3\xd8\x88\xdf\x5a\xa1\x94\xa3\x87\x37\x0c\xea\x5b\x10\x24\x24\xe6\x21\x9b\xa0\x6d\x3f\xea\x01\xdb\x5a\x83\xc2\x0e\xab\x2e\x71\x2b\xfd\x73\x0b\xa9\x46\xc5\x87\x58\x69\x56\x87\xa7\x6e\x01\xe6\x87\xd6\xc1\xb0\x91\xd8\x34\x30\xd6\xe8\x53\xeb\x67\x91\x26\x1a\x9c\xee\x22\x71\xc0\x9e\x94\x50\xc4\x3d\xe4\xca\x54\x51\xeb\x20\x3a\x1e\xd2\x75\x1a\xce\x68\x8e\x9b\x3d\xc2\xed\xe5\xd3\x4b\x8d\xed\x22\x71\x34\x58\x3a\xc5\xc5\xb7\xc8\xfe\xb6\x12\xfc\x25\x8e\x38\xb9\x59\xee\xe0\xfe\xc4\x6a\x6b\xf8\xc3\xa1\xe8\x76\x7a\xc9\x06\xb1\xdc\x90\xd8\xa2\xf4\xd1\xed\x02\xe4\x22\xf3\x5a\xcc\xd8\x4d\x92\x6b\x1b\xf8\xcb\x7e\x0e\xc7\xd9\x72\x77\xce\xeb\xb7\xd4\x2f\x5b\x32\x74\x18\xa5\x9b\x04\xe2\xa6\xe8\x77\x20\xd7\x36\x1f\xb9\xc1\xa4\xbd\x0a\x4d\x5d\xea\x19\x0a\x6b\x48\x7e\x95\x30\x95\x99\xc3\xd2\x66\xc3\x7a\x32\xe5\xc2\x2a\xd3\xc1\x16\xb0\x22\xd1\xc6\x5e\x14\x3e\x65\xe5\x49\x49\xa6\x5a\xd9\xc4\xa0\xef\x76\x5e\x8c\x3f\x02\xae\x5d\x3c\x19\x08\xbf\xc5\x92\xe1\x52\xb9\x64\x8b\xf2\xdc\x54\xc5\x96\x00\x63\xb0\xcd\x1f\x97\x6a\x13\xb7\x8e\xd5\xc8\xaa\x06\x42\xfc\x16\x47\x83\xc4\xbf\x17\xae\xbe\xb1\x26\xfd\x93\xb6\x2c\xce\xe0\x95\x05\x47\x11\xab\x6d\xb6\x24\x47\x11\xa0\xb8\x5a\x89\xe7\x80\xd8\x74\x96\x9b\x76\xfc\xe6\xd3\x70\x45\x85\xbe\x5b\x5e\xb9\x6e\xe2\x98\x1a\x52\x91\xdc\xb5\x94\x10\xeb\x2b\xf9\x06\xd9\x6c\x26\x3e\xdb\x69\xb2\x2c\x2b\xf8\x42\xf8\xf6\x4a\x08\x0c\xc2\x80\x59\x4a\x48\xa8\x7d\x38\x7f\x37\x10\x22\x6a\x6f\x7f\x4e\xf9\xee\x54\x3d\x4c\xa9\xa9\xf7\x95\xcf\x2d\xe4\xd3\x90\xb1\x59\xc8\xf9\x66\xf7\x4f\x19\x2c\xa4\x27\x53\x4d\x0b\xa4\x79\x89\x80\xdd\xc4\x02\xb2\x11\xfe\x6b\xa3\x99\xb7\xe4\x95\xba\x52\x0b\x98\x5a\x37\x01\x16\x12\x21\xcb\x25\x58\x1a\x16\x04\x6a\x44\x75\x4a\x13\x48\x2b\x9d\x6e\x32\xcf\xab\xd6\x08\x97\x1c\xba\x38\xe0\x14\x1d\x78\x01\x2c\x46\x89\xea\xc2\x36\x34\x59\x01\xbb\xb6\x62\xaf\x16\x1c\x70\x85\x12\xd8\x2b\x49\xb9\xeb\x0e\x9d\x39\x9b\xc3\xfb\xf2\x13\x18\x92\xdd\xd1\x0c\x25\x34\xe9\x72\x9d\x73\xfc\xee\x14\xb5\x24\x84\xcf\xb0\xe4\xe3\x35\xc3\x98\xa8\x16\x83\x01\x8f\xa9\x60\x4b\x62\x38\x8d\x95\x76\x6e\x5d\x6d\x57\x1c\x2b\x44\xd0\xa8\x3b\xb6\x9d\x4a\xba\x70\xb9\x33\x55\x65\xab\xd2\x5e\x8b\x2c\x7d\xe4\xd1\xe8\x03\x45\x66\x8c\x7a\x72\x60\x59\xa7\x80\x11\x2b\xe4\x58\x13\x9a\x45\xc4\xa5\x74\x09\xe9\x49\x7a\xaa\x35\x09\x36\x21\x98\x16\xa5\xb4\xdd\xd6\x90\xa1\xd3\xcc\xd0\xd7\x24\x04\x10\x8d\xc0\x4b\x78\x1e\x81\xb4\xca\xca\xd9\x04\xd6\xf4\xe4\x26\x29\xf9\xa5\xe9\x77\xd1\x20\x75\x5d\xbc\xfb\xf7\xb7\x97\xfa\x7a\x4a\xc1\x0d\xfc\x56\xbb\xa6\xcf\x2e\x75\xb6\x09\x70\x5c\x86\xc0\x59\xf2\xd2\x7b\x52\x2b\x3c\xe8\xfd\x79\x1f\x1f\x37\x5a\x9e\x3f\x5b\xca\xa0\x96\xd4\x9f\xf7\x6e\x63\xa4\x83\x45\x12\x5f\xf7\xc2\xf5\x2a\x07\x5e\xce\x2a\x78\x99\x50\x46\x23\x43\x1e\xc4\xc5\x24\x2d\x56\x9b\xf8\xd0\x51\xd7\xd8\xc7\x78\x8d\xe7\x21\x22\x30\x03\x48\x56\x12\xdc\x38\x5f\x75\x09\x31\x9e\x2c\x5d\x75\x64\xb5\x0f\x4a\xb5\x5b\xd9\x06\xee\x67\xc4\x63\x3f\xeb\x57\xe2\x63\x55\xda\x39\xcf\xca\xe5\x02\x17\x10\xcb\xa1\xc0\x75\x99\x71\xc6\x06\xfa\xac\xe2\x09\x86\x44\x98\x46\x7f\x68\x84\x29\x19\xf7\x59\x19\x6e\x63\x65\x27\x41\x2e\xc4\xd2\xf3\xa8\x06\x28\x62\x54\xb7\x0f\x37\x37\x69\x54\x3f\xab\xbb\x24\xad\xf0\x07\x09\x46\x55\x9e\x62\xe1\x82\x0b\xc0\xf3\x27\x51\xe6\x21\x54\xcf\x3a\xa9\x0e\xf9\x54\x3c\x87\x41\x91\x55\x43\x1f\x8c\xea\x45\xb5\x97\x14\x5a\x3f\xcf\x91\xd9\xfc\xac\x5d\x1c\xd6\xd1\xe5\xf4\x04\x91\x8a\x3c\xa9\x4f\x38\xed\xfc\x01\x6e\xc9\x5e\x2d\xe9\xd9\x9e\xf2\x7a\x3d\x97\x5b\x1c\x4c\x50\xd5\xd6\x65\x97\xf6\x1a\x96\x62\xf3\x53\xc9\x84\xf9\x37\xa8\x54\xc2\xe7\xa2\xb8\x37\x03\xeb\x53\xa0\x6c\xa1\xdf\xc4\x0e\x8a\x22\x51\xa1\x10\x49\x3c\x8e\x71\x8d\xdc\xb7\x73\x25\x29\x84\x9d\x3e\x91\x7f\x82\x2f\x56\x3a\x5f\xa0\x90\xd0\x3a\xda\xb3\xc0\x99\xae\xba\x16\xc6\xdb\xa3\xd4\xf9\x0c\xf1\x6c\x70\x41\xc4\x51\x5b\x24\x57\x19\xdc\x6e\xbd\x63\x48\xba\x7c\x02\x48\x56\xaf\x80\x38\x8c\x3b\x97\x2b\x4a\x5e\x01\x09\xd0\x1f\x5d\xc3\x06\x19\x72\xfd\x02\x26\x1e\x47\x1a\x95\x27\x08\x64\x79\xaa\x1c\x72\x6b\xa5\xe9\xc6\xcd\x69\xf1\x1e\xe0\x99\xad\x71\x7a\x79\x86\x06\x5e\x16\x9f\xdf\x33\x1c\x02\xcf\xc6\x7c\x88\x75\x0a\xc5\xe1\x3c\x3d\x11\x96\x0d\x32\x4b\x48\x0d\x41\xe3\xd2\x2b\xab\xeb\x6d\xdd\x17\xe3\xbe\x9e\x11\x55\xf1\xcc\x5b\xd3\xc8\x7e\x86\x0e\x35\xd8\xbd\xbe\xc8\x47\x66\xd3\xb3\xa1\x46\xcf\x0f\xf9\x0f\x27\x41\x3e\x9a\xfe\xd8\xc2\x49\xcd\x13\x53\xf7\x38\x90\x6a\x7a\x08\xd3\xa0\xde\x57\x2e\x6c\x09\x79\xe2\x6f\x74\x58\xe2\x9c\xea\x99\x3e\x71\x3b\x89\x92\x37\x4f\x9b\x87\x4b\x5e\xea\x69\xf3\xa7\xae\x36\x29\xb2\x0b\x8c\x3e\x52\xc8\xf3\xc5\x30\x82\xfd\xa0\xc1\xf9\x84\x2b\x58\x82\x6e\xc8\xca\x1c\xe3\x87\xea\x2d\x9f\x29\xd4\xd4\xa4\x22\xf9\x6c\xac\x87\x4f\x10\xd9\x35\x8d\xb0\x7d\x9f\x19\x76\xf7\xc4\x04\xc6\x5f\x88\x4d\x37\x98\xf1\xfe\x24\x9d\x1c\x51\x6a\xea\x66\xcb\xcd\xd3\x70\xf9\xd7\xca\xdd\x3e\x60\xbe\x0f\x9b\x0b\x82\x08\x2c\x7e\xe4\x81\xc7\xcf\x54\xfc\xeb\x4a\xb1\xe2\xfb\x4c\xad\xb9\x2b\xb5\x1c\x09\x1e\xd5\x4b\xce\xf2\x51\x52\xa5\x8b\x2a\x63\xde\x2a\x0c\xfb\xe4\xe7\x71\x33\x2a\xf8\x71\xcb\x8c\x7e\x20\x7c\x4c\xe7\x99\x78\x1a\x2d\xfa\x3e\xaa\x56\xf8\x1f\x15\xb6\x2d\xd5\x12\x1f\x35\x7a\xbb\x87\x75\x52\x6e\xd7\x3c\xaa\x77\x28\x8f\x3a\x6f\xbe\x58\x48\x81\x32\xfe\x67\xa8\x85\xc7\x3a\xe9\xb6\x23\x7e\xcd\x8f\xb2\x35\x51\xf7\x07\x3a\x4d\xd6\xae\x44\x86\xe4\xc3\x99\xa4\x2e\x22\x2d\xc5\x3f\x82\x53\xd8\x41\xfe\x8f\x6a\x66\xc1\xeb\xfd\x80\x7f\x88\x15\x32\x03\xc4\xf5\x01\x48\xde\xf9\x48\x5f\x5f\xce\x7b\x24\x90\xe5\x39\x90\xd5\x61\xf3\xcb\x2f\x26\x00\x54\x30\xb3\x47\xcf\x75\x9f\x87\xdd\x2d\x43\x51\x1e\xe9\xe9\x6a\x8e\x8f\x04\x0d\x4b\x52\x78\x3c\x6c\xd8\xec\x28\x1f\xfa\xe0\xdc\xb6\x7c\x13\xcc\x32\x4a\x95\xbd\x13\xa5\xff\x6d\x2c\x62\xd0\x45\xb9\x90\xe4\x01\x70\x1e\x29\x8b\x4b\xa1\x9c\x92\x1f\x43\x44\x21\xbd\x03\x98\x1a\xa1\x22\x25\xfc\x4f\x2e\x88\xa6\x10\x0e\xe4\x22\x4e\x12\x37\x9b\xf2\x24\xb6\x4d\xcf\xbb\x3c\x79\x72\xd4\xdd\xbf\xb5\x02\x07\x31\xe5\xd7\x7a\x9b\xcf\xd3\xe5\x36\x7f\xf8\x30\xad\xa4\xa2\x90\x98\x04\xe7\x9b\x2e\x3a\x94\x14\xef\xb9\x2f\x2e\x7d\x40\xf2\x8c\x2a\x54\xf7\x21\xb1\x9f\x3b\xb8\x21\xe6\x9b\x44\x31\xf3\x2d\x6d\xcb\xf9\xde\xb8\x8c\x07\x90\x75\xb4\xa4\x9c\xee\x26\x98\x36\x5f\xc9\xee\xf1\xe0\xf5\xa4\x00\x75\x8f\xd2\x40\x0b\x49\xa8\xc3\x1e\xae\x7f\x2a\xb3\xd4\x84\xaa\x84\x7c\xe6\xfa\x3a\xf3\x4e\xbf\xae\xa7\xf2\xbb\x53\x79\x46\xc4\x5b\x88\x93\x61\x49\xd6\x01\x33\x24\xa0\x8c\x26\x55\x35\x43\x4d\x4e\x0c\xba\xbb\x3e\xfd\xf2\xd0\xff\x4d\x80\x05\x0f\x56\x06\xf2\x5c\xa3\x0a\x75\x2f\xfc\x81\x84\xc7\xea\xa4\x77\x34\x8b\x52\x76\x46\xca\xac\xce\xbf\x66\xf5\x53\x73\x5d\xa4\xcf\x54\x97\x6b\x3a\xf2\x3b\x0b\xeb\x1e\x9a\x2c\xbb\x43\xd2\x02\x18\xfc\xfd\xc8\xa9\x09\xe6\xac\x73\x2d\xce\x0a\xf8\xd4\x46\x92\xbc\x9b\x87\x68\xa8\x5a\x0a\x49\x9a\xe1\xab\x8f\xfa\x8d\x4a\x32\x98\x6d\xd2\x15\x12\x6a\xba\xab\x34\x85\x36\x5b\x39\x68\xca\x20\xe1\x01\xeb\x89\x4d\x8b\x0a\xf3\xa6\x8d\x20\xb4\xa8\x1c\xc5\x7f\xcd\xd8\xf6\x5a\x43\x63\x73\xb4\xae\x91\x58\x8a\x62\x45\x66\x9f\x07\x95\x48\xe5\x2c\x78\x32\x1c\x51\xf8\x0f\xe4\xac\x4d\xec\xab\x4c\xe1\x35\x30\xa8\xe1\x17\x32\xc4\x88\x6b\xe7\x11\x99\xec\x50\x60\xa0\x90\x48\x1b\x5c\xe1\xd2\x1f\x3b\xbe\xf1\x9a\x0d\xea\xf8\x03\x19\x18\x92\xcc\xc2\x86\x6c\x08\xa9\xa1\x55\x42\x90\xac\x4c\x65\x89\xcd\x76\x3e\x29\x3a\x00\x0d\x02\x9d\x74\xc7\x0e\x26\x33\x02\xf0\x5d\xe4\x9d\x47\xb8\x90\xda\x42\x88\xae\x58\xa2\x7d\x59\x1c\x85\x0e\x7e\xb2\x58\x1e\xd4\x23\xd3\x04\x1b\x2a\x87\x43\x35\xde\x86\x26\x91\x32\xe7\x95\xa4\x84\x00\x2a\x9d\x83\x38\xd4\xd6\xd4\xda\x91\x63\xc2\x7f\x2f\xab\xe4\xdb\x96\xb5\x49\x5d\xcf\x39\xde\x46\x0e\x09\xb5\x65\xa4\x77\x01\xb1\xee\xba\x80\xcd\x26\x0e\xa2\xf2\x0d\xf9\xb5\x98\x5f\x23\x33\xf2\xa3\x32\xfc\x0d\x4e\xe9\xd5\xe4\xde\x1c\x13\xfd\xb9\xd3\x50\x7d\xcb\x8c\x92\x37\xc0\x6a\x64\xd9\x72\x73\xfe\x31\x3b\x38\x8e\x7c\xdb\x39\xa7\x97\xaa\x9a\x86\x10\x0c\x43\x78\x4d\xa4\x05\xdb\x96\x22\x6a\x0c\xa5\x27\xe3\x37\xe6\xf4\x7e\x9e\xa1\x1f\xf6\x72\xf9\xd5\x50\x79\xbb\x58\xe8\xc1\xa5\x9b\x5d\x55\xba\x3b\x7d\xc4\x49\x4b\x55\x0e\xda\x2d\x9a\x29\x11\x9a\x89\x66\x7e\xbb\x6b\xc2\x25\xe0\x82\x2b\x03\x29\x3a\x25\xd0\x1e\x00\x61\xad\xa1\xf2\xb6\x96\xa6\xdd\xa6\xfc\x29\xa7\x3a\x8a\x7d\x85\x9d\x63\x3a\xa8\x6b\xe3\x60\x15\xc0\xbf\x59\xfb\xed\x1b\xda\x6d\x2f\xdd\x9c\x3a\x21\x97\x7a\xcb\x42\x7f\x84\xd7\x36\xb5\xaa\xa4\x9c\xf3\x39\xb5\xdc\x0f\x83\x23\x0b\xad\x20\x52\xb2\x6d\x09\x75\x36\x11\x0f\x1a\x3a\x93\x74\xec\x16\x56\x6d\x59\x22\xf3\x73\x6e\x72\x47\x33\x99\x71\xad\x50\xf2\x83\xa1\xc4\x43\x1e\x74\x44\xcf\x88\x00\xfd\xbd\x35\xdd\xd1\xcc\x9b\x9c\xa2\xc2\x13\x97\x05\xe6\x24\x9d\xc6\x34\xe8\x8e\x87\x21\x5e\xa1\x07\x5e\xf3\x9a\x29\x04\xee\x9c\x00\x6e\xba\xbf\x5f\x79\xec\x0c\x7e\xbc\xb8\xfe\x48\xb8\x85\xb7\xc8\x50\x9b\x39\x41\x0e\x8e\xcb\x9a\xd3\x7d\x70\xf8\x71\x01\xb8\xc3\x81\x75\x1e\xb2\x7e\xa7\xbb\x89\x8e\xdd\xb4\x07\xa7\xbb\x2c\x2b\x1d\x11\x80\x85\xeb\x4f\x06\xf5\x5b\xf6\x76\x28\x25\xc6\x75\x87\xe7\xcd\x90\xe6\x58\xa0\x23\x2b\x49\xe2\x6a\x77\xa8\x8e\x21\xda\x9e\x86\xa1\xc1\x53\xfd\x39\xe0\xcc\xd2\x67\x8c\x13\x32\x95\x55\xc6\x7d\x1d\x35\x6b\x58\x9e\x0e\xb2\x93\x4e\x1e\x56\x3e\x8e\xc2\x3f\x15\x0d\x97\x8a\xd3\x5e\xe6\x15\x18\x50\xda\xed\xe4\x5c\x0e\x3c\x2a\x6f\xbf\x5f\x64\x7a\x19\x26\xb0\x39\xc8\xfa\x07\x8e\xff\x4e\xbc\x8d\xfc\x47\xb3\x13\x72\x06\xdc\x1b\x9f\x95\x6b\xc8\xf1\x22\xd2\xbd\x83\x82\xf7\x87\x60\xd0\xfa\xc1\x54\xf9\xcd\x4f\x88\xbf\xca\x2b\x19\x4b\x6c\x83\x8b\xae\x93\x8d\x58\xfe\x83\x1a\x22\xc7\x56\x1d\xbe\x24\x33\x52\xf4\xea\x6a\x15\xf5\x01\x5c\x53\xef\x24\xa9\x35\x68\x9c\xb2\x9a\x36\xdf\xae\x2c\x25\x1e\x86\x65\xf8\x85\x44\x12\x53\x5d\x5b\x6c\xa6\xe1\x8e\xcf\xbb\x2e\x75\xd3\xa1\x91\xe3\x0c\xa9\xb9\xeb\x48\xbb\x60\x70\x2b\x4f\x35\x2a\xba\xb8\x0d\x39\x55\xdd\xd5\xa4\x5f\xb9\xba\xb2\x23\x4a\x61\xe8\x57\xc3\x53\x77\x3d\x84\x62\xda\x22\xfd\xb0\x85\xa9\xa8\x13\x1c\x5a\x3c\xd8\x65\xeb\x3e\x42\xda\x57\x5e\x45\x92\x7a\xc5\x8c\xab\xa3\x48\x7c\xee\x64\x80\x30\x54\xe8\x9a\x18\xc1\x54\xb6\xca\x37\x53\x36\x29\xcd\xf9\x2a\xdc\xde\xde\x5c\x41\x52\x0f\x1b\xbc\x73\x57\x10\xc4\x3f\x27\x6a\x1c\x4f\x25\x77\x71\xf1\xae\x93\xd8\x5a\x31\x33\xd9\x9d\x16\x8e\x16\x86\xdc\x01\xf7\x7f\xe0\xdc\xb4\xec\x78\x87\x1c\x4b\x25\x75\xa7\x0d\xc0\x31\x02\x89\xb0\xee\xe9\x15\xb5\xb9\x6d\x91\x28\xdd\xa1\x66\x82\x0e\x9e\x2a\x8e\x59\x91\x30\x06\x32\x33\x8c\x26\x2c\x5e\xbb\xca\x9b\x02\x0c\xac\xec\xdb\x32\x08\x04\xed\x24\x9a\xd7\x5c\xd7\x54\xb3\xe3\xb5\xe8\x89\x9b\x72\x34\xa0\xf4\x66\x3c\xa6\xeb\xd6\xf1\x0e\xb0\x02\x97\x08\x0e\xad\x17\x39\x04\xb9\xf2\xc5\x8d\x3a\x52\x13\xc0\x60\xf9\x09\x3e\xa6\x83\x52\x5e\xc4\x79\xf9\x89\xd1\x29\x92\x17\xc2\x73\xa3\xda\x4e\xa2\x5f\xdb\x5a\x90\x1c\x3b\x40\x73\xa0\xc9\x89\x05\xbd\xc7\x80\x58\x06\xfb\x96\x14\x59\xa6\x93\x96\x52\x51\xaa\xf6\xcb\x12\x72\x77\x8b\x19\x6d\x3a\x9c\xd7\x44\xcb\x22\x2a\x13\xeb\x36\x90\x91\x64\x4a\x1d\x0d\x20\x68\xce\xb9\xd8\xd6\x87\x03\x03\xc4\xe6\x28\x48\x76\x73\x32\x07\x6d\x39\xe5\x5a\x18\x94\x8c\xd8\xfd\xbc\x15\x71\x38\xde\x8f\xa2\x81\x7a\x04\x0f\x44\xfe\x8f\xea\x72\xcc\xc6\x1d\xc9\x7e\x38\x1e\x1f\xfd\x10\x04\x0e\x5e\x5a\xb7\xf8\xd3\x75\x3b\x82\x50\x06\xa8\xd7\x64\x89\x4a\x74\xb1\x5b\xe6\xde\x88\x0c\x1b\x3f\xb3\x67\x76\x4a\xe9\xec\x28\x21\xd4\x76\x20\x92\xba\x19\x6b\xbe\x19\xf2\x70\xae\x6e\xc3\x7b\x3c\x42\x9a\xee\x94\xd0\x5d\x0b\x80\x18\xb5\x78\x6a\x25\xfd\x87\xd0\xb1\xd3\xf2\x82\x4b\xda\xc5\x51\x22\x2d\x01\xf2\x07\xea\x80\x39\xc3\x06\x21\x30\x24\x64\x66\xdf\x33\x6a\x93\xb5\x3c\x31\x1e\x4d\x31\xed\x48\x1f\x29\xad\x1d\xa1\x99\x38\x92\xfc\xbb\xfc\x27\xa1\x3c\xed\xdb\x42\x95\x0f\xab\x18\x67\xaf\xe7\xa9\xd5\x35\x03\x53\x3c\x0c\xce\x2e\xc6\xfa\xcf\x7f\x58\xdf\x8b\xa8\x66\xc7\x96\xaa\x89\xc0\x18\x1f\xa8\x0c\x6c\xe9\x92\x3a\x5f\x70\x45\x8d\x5a\x4c\x1a\xa5\x53\x3a\xd6\xe9\x62\xc1\x05\xd7\x11\xc1\x44\x97\xfe\x13\x53\xe1\x71\xf9\x4c\x94\x9e\x19\xed\xc1\xb1\x2c\x72\x82\x8c\xec\x72\xc6\x85\x2e\x15\x94\xda\x9f\x60\xd1\xf1\xe7\xde\xba\xc7\x07\xed\xfe\xb1\x20\x04\x84\x29\xfe\x23\xd4\x22\x78\x7c\xf9\x2d\x8c\x8d\xee\xfe\x53\xf3\x28\xb2\xa5\x46\x84\xee\x27\x21\x1a\x1f\x63\x59\x98\x68\x04\x2d\xbd\x5e\xc1\x8f\x86\xf9\xd2\xe0\xf9\xba\x04\x24\xd4\x07\xbf\xcc\x46\xc4\x4f\x12\xfd\x47\x13\xd2\x43\x22\x1e\x1b\x08\x30\x73\x99\x46\xda\x04\x23\x9c\x87\x0c\xb7\x31\xf8\xd4\x2e\xef\xcf\x38\x3f\x1c\x95\x6a\x3a\x4a\x1f\x09\x25\x8b\xad\x84\x54\x63\xe6\x4a\xc3\x98\x49\x1f\x69\x3d\xa6\x0b\x02\x8d\xe1\x3a\xc4\xbc\x48\xf9\x99\x23\xe6\x77\xb3\xc8\x5a\x6d\xe3\x51\x79\xc9\xe2\x5c\xde\x0e\xe7\xa6\x0a\x48\xb1\xbc\x9c\xa3\xd9\x59\x63\x4d\x21\xe6\xa7\x00\x00\x43\xfa\xcc\x73\x38\xf7\x46\x31\x36\x8c\x29\xbe\x5f\x18\xe8\xfe\x1f\xd7\x08\xfa\x47\x74\x46\x6b\x4d\x5c\xc2\xb0\xb2\xd7\x36\xe7\x90\x23\x1a\xb4\x57\xc9\xfa\xb3\x5b\x3a\x4e\xc0\xf4\x08\x19\x4a\xfa\xc1\xd6\x4e\xb5\x91\xff\xde\x00\x9f\x77\xf2\xa4\x00\x1e\x2e\xa7\xd7\x88\x05\xff\x37\x41\x28\x0a\x3a\xe9\x5d\xe2\xcc\x7f\x4c\x0f\x95\x73\x48\x21\xa6\x4e\xbf\x6c\xb4\x25\xf9\x83\x30\x36\x89\xca\x7d\x34\x63\xce\xff\xe4\x23\xc9\xff\xfc\xf8\xfc\xd2\x88\xe5\xa1\xb5\xec\x89\xb3\x73\xb1\x01\x80\xd6\xcb\xdb\x55\xd6\xfd\xe6\xab\x2f\xa4\xf8\xcd\xd1\x76\xf3\xa9\x46\x94\x7f\x76\x9b\x0d\xd1\x0b\x8d\x4e\x0c\xd6\xdb\x09\x03\x99\x1b\x88\x1b\xf0\x06\x90\x91\xb3\xde\x71\x90\xc9\x9e\xa7\xee\x9f\xe0\xdf\xac\x8b\xe6\x62\x73\xa9\x58\xfe\x77\x09\xf2\x11\x98\xa9\xf2\x23\x1a\x14\x9d\x64\x10\x21\x3a\x63\x76\x48\x10\x36\x73\x3e\x07\x6b\x5a\xe6\x93\xcf\x72\x1e\x90\x9b\x95\x40\x24\x1f\x40\x4d\x90\xcf\x3a\xee\x8d\x61\x1b\x79\xe3\xe2\x84\xf2\x76\xf2\xf2\xf5\x79\x2c\xf8\x02\x19\x2c\x18\xad\x19\xf6\x00\x14\x12\x7d\x42\x8b\x8c\x14\xee\x1c\xe3\x8b\x01\xd1\x8d\xce\xbe\x64\xe5\xda\x01\xf1\x7f\x58\x62\xe6\xd9\x44\x87\x01\x32\xc7\x3d\xb9\x58\x56\xa6\x16\x8a\x75\xd8\x48\xa8\xf7\x33\x94\x48\xf2\x64\x2e\x7b\x0e\x84\x72\xa6\x46\x73\x9e\x6e\xf2\x82\xf9\xda\xa8\x9f\x72\xa8\xb7\x74\x1d\x07\x33\x2b\x98\xdd\x12\x71\x67\x59\xf9\xa0\xb9\xfb\x49\x0d\xbe\xc2\x49\x61\x9f\x0e\x2d\x1a\x10\xb6\x4b\xa7\x50\x69\x10\x59\x13\xa2\xe1\x7b\x73\xf0\x1d\x3e\xb4\x95\x87\x4f\xd4\x71\x78\x73\xde\x3e\x40\x88\xea\x4d\xc0\xb8\xe3\xe1\x3e\xdd\xd8\xb3\x32\x04\xf5\xee\xb3\x09\x15\x7e\xa8\x1b\x77\x1f\xf7\xae\xff\x1d\x97\xb8\x08\x05\xf5\x7f\xbe\xe2\xe1\x66\x5c\x34\x4a\x29\xc3\x0f\xb7\xa6\x97\x03\x79\x0a\x20\x63\xe8\x75\xbc\xf9\x89\xa1\x5c\x54\x25\x05\x58\x1a\x28\x8b\xaf\x11\xba\xd6\x21\xaf\x10\x92\x87\xf4\xdf\x0f\xf7\x4f\xf8\x76\x40\x34\x53\xe1\xde\xfe\x19\xd2\x7e\x58\xf1\x25\x27\xdf\x70\x77\x71\xcf\x64\x5f\x41\x29\x31\xc2\xdb\xed\x9b\xe1\xb8\x29\x9c\x06\x9d\x10\x3d\x84\x23\x9c\x5c\x03\x5c\x74\xbc\xf8\x21\x6e\xd6\xe1\xf8\x85\x17\x0e\x48\xe9\x8c\xdf\x24\xa6\x0e\x0e\x9e\xc0\xa8\x5d\x1d\x4d\xbd\xa1\x7e\xb8\xa7\xbe\x07\x3d\xde\x7a\x77\x5e\x1c\x21\xa7\x88\x21\x48\x92\x7b\xf5\xcf\x17\x39\x44\xe2\xdb\x50\x5b\x1c\xff\xa0\xf5\x43\x2b\x7b\xfe\x6b\xa3\x16\xfa\x50\x23\xbc\xdb\x91\x97\x88\x8f\xf2\xa5\xf0\xa1\x2e\x3c\xc6\xda\x07\x48\x5c\x89\xa5\x7a\x56\xe9\xe7\x1a\x6a\x91\x1e\x5b\x0b\xfc\x35\xa4\x82\x81\x75\x66\x84\x32\x25\x71\xa8\x14\xfd\x47\xf9\x53\x80\xec\x24\x8a\x08\x9e\xce\x2c\x4d\xb6\xc2\xd1\x95\x75\x2f\xf6\xbc\x4f\xee\x3e\x6a\xdf\x13\x85\xb2\xee\x50\xea\xee\xc5\x26\x9e\x41\x84\x16\x37\xc9\xc4\x35\x98\x11\x5d\x4e\x88\x3d\x91\x41\x24\x39\xf9\xe4\xde\xa7\x89\x2f\xe7\x02\x34\x18\x2a\x71\x65\x54\x24\x0f\x34\x1b\x55\x3b\xbc\xa1\x01\x19\x37\x47\x6c\xf2\xb4\x63\xd6\x5a\xa4\xc1\xd4\x49\xf3\x31\x87\x5c\xbc\xcb\x3b\x36\x88\x34\x3c\x31\xf3\xfa\xca\x92\x6c\x43\x17\x6e\xdc\xdd\x66\x1e\x4a\x68\xea\x95\xf4\x35\x6b\x2f\x4b\x3a\x32\xa9\x66\x59\x13\x16\x00\x69\x15\x86\xe6\x25\x00\x4b\x7f\x8e\x97\x30\xeb\x8b\x81\x23\xe4\x22\xf3\x8b\x0e\x96\x21\xe8\x77\x87\x3f\x49\x76\xd0\x7c\xac\x21\x5b\x78\x85\xab\x70\x08\x96\x5c\x17\xf8\x31\xa3\x2d\x24\x1f\x53\x68\x2d\xb6\x17\x03\x2f\x28\x8f\x3c\xa4\x2a\x18\x42\x94\xd0\xa8\x5d\xdb\x3f\x53\xa8\x4d\xfe\xef\xb6\xe1\x39\x84\x1d\x93\xf4\x0c\xf7\x34\xdc\xac\xce\xf6\x91\x60\xe1\x26\xf1\x40\x1f\x36\x78\xf8\xd6\xf8\x94\x86\xac\xcc\x9e\x21\x2b\x70\x1f\xa0\x31\xa9\x62\xc3\x7e\x36\x6d\x9f\xb6\xc1\xdb\x5a\x33\x7b\x33\xd8\x91\xfc\xf9\x02\xf2\x01\x9e\x7e\xd9\xcb\x25\x90\x76\x1d\x56\x7f\x9a\x8f\x52\x48\xcd\x7a\x33\x0b\x52\x20\x02\x4a\x1b\x14\xeb\x7d\x7b\xaa\x8a\x3c\xb2\x4d\x4e\x29\x1d\x34\xb9\x4a\xbc\x64\xcc\x51\x4f\x6d\x29\x76\xc7\x20\xd4\xb2\x6a\x40\x06\x79\x08\x12\xa5\x77\x3c\x13\x04\xad\xf4\xba\x46\x5a\xee\xaf\xd0\x7c\xab\x1d\x20\x9c\x03\xd7\xe0\x21\xcf\x2c\xab\xdf\x20\x45\x62\xf3\x23\xe5\x78\x92\x0f\x88\x3c\x48\x8d\x72\xd6\xbf\xe7\x78\x31\x13\xfb\x2a\xcc\x6c\xb8\xfd\xd3\x27\x8d\x1e\xdc\x85\x48\x08\x86\x23\xee\x05\xd9\xa3\x90\x02\xe1\xc6\x5c\xd4\x58\xfa\x1c\xcd\x06\xba\x63\xbc\x44\xfb\x44\x72\x53\x2e\x85\xf0\x86\xc4\x7c\x29\x3f\xa9\xb7\x6a\x66\x14\x0f\x80\x00\x65\x28\x4f\x62\x0a\x4b\x85\x58\x17\x28\xa1\xef\x62\x48\x5a\x4f\x19\xd2\x4b\x2d\xcf\xe6\xdd\x7e\x42\x30\x26\x7b\x79\x4e\xf7\xce\x5e\x21\x35\xb5\x52\xcc\x80\x45\x3e\x3d\x84\x47\x75\x48\xf5\xe6\xa9\xb6\x53\x1a\xea\x83\x2f\xdd\xf2\x9f\x5b\xd3\x5f\x33\x9c\x67\xfd\xbb\xd7\x45\x57\x49\x7e\x42\xdf\x80\xd7\x5a\xfa\xd8\x35\x2f\x8d\x5c\x73\x48\x43\x30\xd5\x0c\xa9\xbf\x99\xda\x6d\x28\x49\xd2\x7b\x60\xa0\x62\xff\x39\x94\xd6\xd9\x7f\x10\x7a\x84\x7a\xf6\x6f\xee\xb8\xe5\xb6\xea\x6f\xa5\xab\x18\xf0\x06\x6d\xa5\xcf\x3f\x50\x56\x2f\x29\xf0\x8e\xd2\x8d\x0d\x00\xa9\x9f\xd9\x84\x59\x2a\x8b\xb7\x35\x3c\x9f\xcd\xf7\x66\x5e\x6f\x4a\xca\x84\x7e\xa4\x9f\xe2\x94\x2d\xd1\x43\x31\xae\xf0\x2c\x3f\x71\x2d\xc0\x95\x19\xd6\x80\xa1\x21\x59\xef\x36\x83\x80\xb2\x3c\xd5\x05\x1b\xed\x86\x99\x9e\x67\x72\x77\x23\x88\x93\xa8\x52\x07\x53\xb7\x0a\xc4\x60\xd1\x3b\x61\x83\xe4\xf8\x40\xb0\x20\xd5\x4a\x48\xa6\x90\x62\xa1\xaf\xdf\x6f\x96\xde\xe2\xcb\xbb\x09\x2a\x4e\xc6\xda\x31\xb6\x7a\x05\x2e\x19\x8e\xfc\xc6\x1e\x22\x00\xb3\x64\x14\xef\x58\x2d\xb3\xd6\x70\x84\xb4\xe3\x39\x81\x40\xc1\xa1\x8d\xb9\x14\x2d\xe9\xab\xd2\x84\xc0\x5b\x51\x29\x52\x07\x99\x49\x5e\xc8\x97\x9a\x43\x53\xb1\xd6\x2d\x02\xbe\x6c\x42\x1d\xd1\x21\x14\x94\xd4\x15\xa0\xc7\xc1\x3b\xae\x5b\x88\x65\x6e\x87\xa4\x28\xb1\x5c\xa8\x5f\x04\xff\x30\x1c\x63\x12\xd7\xc4\x4a\x36\x91\x52\x95\x0d\x34\x3d\xcd\xc5\x66\xc5\xaa\xe5\x22\x82\x0d\x50\xa5\xbd\xa4\x46\x57\x17\x09\x50\x16\x5d\x60\x9a\xf4\xc3\xbc\x49\x44\x32\x28\xfb\x7b\xd2\x77\xc2\x08\x56\x80\xb9\x43\xbe\x55\x5f\xb2\x0f\xfd\x49\x6a\xf0\x80\xe4\x4a\x34\xb3\xfd\x82\xd5\xd6\x8d\xc8\x5f\xcf\xa2\x47\xb7\x80\x62\x44\x69\x2c\xfd\xd2\x84\x19\x97\x18\x40\x30\xc1\x49\x43\xd3\x93\x0c\x41\x44\xb3\x5a\xd9\x44\x8b\x34\x5d\x9b\x40\x24\xf7\x42\x23\xac\x49\x47\xaa\x73\x05\x18\x14\x37\x0f\x71\x48\xc5\xc3\xf6\x33\x69\x73\xac\xaf\x3a\xa4\xea\x58\xec\x49\xf9\xb4\x08\xa2\x8f\x89\xa9\x5f\x98\xbc\xd1\x42\x75\x62\x7c\x21\x3e\xf7\xd9\x17\x95\x1f\x92\x8c\x4c\x1a\x6d\x81\xd2\xb4\x71\x60\x76\xa9\xc8\xa2\xdd\xfb\x7e\x4b\xa2\x12\xbd\x89\x4e\xb1\xc6\x24\x0d\xe4\x0c\xf7\xce\x75\x05\xe0\x31\xf6\x8e\x63\x9c\x6a\x90\x96\x25\xf4\x47\x42\x1c\x35\x9f\x21\x75\xe8\x4f\xb1\x0a\x49\xfe\x35\xab\x2b\xed\x7d\xf1\x92\xff\xdc\x94\x1d\xd7\x43\x27\x4a\x2a\x89\xd0\xbe\x08\xf9\xc7\x97\x74\x11\x41\xb2\x1c\x4a\x87\x27\x73\x2d\x7b\x10\x46\x95\x3e\x7e\x05\x26\xd2\x1c\xaa\x92\x21\x1a\x09\x22\xcc\x90\x28\x3c\x29\xfb\xa5\x8d\xf3\x8a\xd4\x51\x17\xa8\x44\xba\x2c\xf1\xae\xda\x26\x91\xa7\x01\x24\xa9\x28\xd2\x50\xf3\xd1\xe3\xd4\xe1\x89\xaa\x89\x8d\xcb\x1a\x39\x24\xf1\x49\x23\xe1\x61\xe2\xda\x09\xd2\x49\xf8\x94\x93\xf2\x6e\x7b\xef\xf7\x6b\x20\xc9\x3e\x1e\xbb\x27\x87\xe9\x4e\x8f\x75\x89\x1f\x85\x67\xcb\xe1\x19\xb0\x0c\x43\x11\xea\xeb\xa8\xeb\x4b\x1b\x92\xf2\x20\x28\xef\x26\x82\xd9\x69\x97\x8f\x5b\xbc\xc6\xee\xc9\x54\x25\x70\x12\x10\xc1\xbb\xc1\xa6\x48\x79\xf3\xbc\xdb\x25\x31\xcc\x2d\x64\x72\x95\x71\x6a\xe5\x64\xc6\x63\xe5\x57\x61\xc3\xd1\xae\xe3\x86\xf6\x40\xcc\xae\xd0\xd9\xd6\x9d\x47\x21\xe7\x91\x20\x1e\xc6\xda\xba\x29\x74\xd7\xda\x97\x8e\xa6\x73\x99\xf2\x4c\xb4\xbc\x42\x7f\x93\x92\xb5\x84\xc3\x4f\xef\xd5\x46\xbb\x3b\xf4\x2f\xfb\x38\xb6\x48\x7f\xb2\x17\xc7\x5c\x8f\x40\x7c\x0a\xbf\xa6\xae\x5e\x4c\xda\x31\xc8\x65\xe5\xee\x13\x22\x94\x5f\xea\xca\xfd\x59\x83\x83\x94\xa5\xf4\xeb\xee\x93\x46\x06\x44\x2d\xeb\xab\xf0\xc3\xb1\x8d\x4e\xb2\x93\xa7\xc4\xb3\x6e\x70\x7d\xf5\x9c\xa4\xda\x68\x7e\x35\x85\x4b\xc9\xb3\x00\x29\x2d\x1d\x50\x27\x67\x28\x75\x77\x87\x88\xe5\x31\x85\x24\xd8\xed\x4e\x77\xa1\x12\x87\x83\x57\x57\xd7\xdb\xf8\x25\x18\x08\xe5\xcb\x6d\x90\x0a\xe4\xbd\xea\x8e\x5c\xf3\x84\xa8\x34\x31\xcc\x45\x35\xc3\xa9\xb8\x07\x9c\x38\xfa\xa7\x99\xdb\x7c\x3a\xb7\xce\x4e\xa7\x5b\x67\x33\xdf\xbf\x72\x9a\x12\xc1\x3b\x3c\x84\xcd\x8a\x21\xb4\x33\x3f\x52\x53\x3b\xee\xed\x7c\x71\x01\x1b\x38\x94\xef\x40\x2c\xcb\x7b\x31\x14\xad\x01\xf2\x99\x7a\x27\xc7\xcd\x02\x6a\xcf\x89\xa8\xc9\x8b\x82\x7b\xeb\x43\x50\x9f\xfc\xc0\x0d\x7a\x52\x21\x61\x98\x89\x6e\xf9\xfd\xb4\x3b\x9d\x0d\x8b\x1d\x0b\x54\xb2\xf8\x02\x9d\x21\x27\x50\x9f\x7f\x55\x29\x10\x51\xf0\x8f\xa6\x73\x6a\x8a\x4b\xbf\x63\x07\x04\x30\x68\x8f\x2b\x63\xd2\x8f\xdb\xe1\xca\x71\x8b\x52\xff\x46\xf8\x9c\x6a\x80\x14\xe4\x9f\xa2\xe6\x65\xa3\x1a\x63\x8b\x7d\xab\x93\x32\xe1\xd1\x22\x5d\x00\xb7\xd0\x05\x85\x26\x7b\x3b\x8f\x3c\xf7\x1d\x18\xa1\x36\x01\x4e\x8e\x3d\x13\x6d\x10\x78\x86\x16\x69\xfa\x96\x40\x9f\x96\xfc\x00\x7d\xce\x55\x25\x8b\x50\x5b\x75\x42\x7b\xfd\x6b\x6b\x4a\x61\xd8\xe8\xd3\x15\x50\x29\xbf\xdd\xc1\x74\x8c\xce\x55\xb1\x59\xd7\xd4\x94\x4b\x81\x36\x19\xb5\xee\x1b\x8b\xfd\x5a\x1f\xef\x10\x49\xb5\x11\x78\x27\x0e\x21\xcf\x2d\x54\x3a\xdf\xd2\x38\x84\xd3\xe2\xd2\xf1\xf7\xe5\x0c\x2c\x00\xf3\x8f\xf9\x02\xca\xf7\x67\xf9\xdf\x1d\xff\x3b\x1e\x95\x6e\x08\xe0\xac\x9d\xd0\x69\xe8\x75\x34\xeb\x81\xc8\xfc\x22\x62\x00\x6e\xf0\xdf\x21\x57\x5a\xc1\x02\xed\x7d\x11\x02\x39\x55\x86\xd0\xe8\xf1\x61\xe5\x0e\x15\x12\x03\xb5\x4b\xf3\xb7\xc7\xc4\x4e\xa0\x1e\x89\x55\xaf\xfa\x52\xab\x04\x0f\xeb\xe6\x33\xab\x08\x68\xef\x6a\x48\x43\x75\x10\x55\xe3\xd9\xb6\xa4\x29\xba\x6b\x87\x52\x35\x4f\x64\xfa\x5d\x0d\x51\xbe\x16\x7a\xe5\x88\x65\x61\x6d\x4b\xd0\xe1\x19\x94\x1a\xa9\xe2\x01\xa0\x3d\x7a\x48\xc3\xa2\xab\x13\x62\xd0\x42\x30\x35\x9f\xfb\xb8\xdc\x93\xb0\x2e\xa6\x0e\xa0\x86\xea\xe6\xef\x33\xf3\xe5\x61\x9e\xdb\xb5\x66\xb3\x1e\xde\x10\x42\xa8\x7d\x84\xab\x1b\xec\x79\x6d\x26\x19\x41\xa2\x54\xe5\xcc\xdf\xa4\x81\x91\x66\x1d\xb2\x99\x58\x86\x0a\x29\x65\x11\xe0\xac\x55\xeb\x5a\x62\x7c\x87\xfa\x12\x13\x82\x0d\x35\x39\xd4\x05\xd1\x38\x3c\x57\xd2\xa7\x88\x60\x6c\x8e\x84\x2e\x70\x4a\x85\x4c\x28\x9a\xea\xcb\x7a\xd4\xe3\x19\x11\x24\xdd\x83\x4c\x2a\x5d\xf9\xba\xa7\xac\x43\x48\x4c\x25\xa0\xb3\xcb\x40\x6a\xad\xa7\x78\x9c\x9e\x15\x14\xfa\xea\x8a\xa4\x1c\x6d\xf2\x72\x25\x0f\xf1\x07\x94\x8a\xa1\x3a\x35\xfc\x98\x8f\xb0\xfc\x51\x35\x8e\x6c\x1f\x0a\xa2\x3a\x98\x34\xdb\x34\x44\x67\x0b\x54\x50\xe5\x45\xec\x4a\x04\xa0\x74\x66\x9d\xf2\x8b\x2e\x69\x54\x1b\x9b\x13\x73\x13\x3b\x7a\x26\xba\xfc\x61\x63\x0c\x57\x4e\x07\x56\x0d\xaf\x9d\xf5\x45\xfe\x8b\x1c\x4a\xae\xf6\xa4\x3c\x1c\x49\x1b\xb3\xf4\x50\xaf\x18\x79\x9a\x38\x33\x32\xbb\x6d\x06\x20\xc8\x79\x2b\xd2\xc4\x62\x98\x43\xa2\xd0\x25\x90\x9a\x12\xab\xcd\x38\x0b\xe1\xb3\xc9\xaf\x42\xb1\x87\xad\x1d\x3c\x2a\x92\x26\x85\xe6\x6e\xd6\x01\x64\x6b\x80\x68\xeb\x97\xdd\x5d\x3e\x98\xf2\xdf\x65\x24\xa1\xa9\xae\x1b\x96\x63\x89\xe6\x54\x24\xd3\x6a\x56\x1a\xdf\xbc\xc1\x90\x44\x5d\x99\x87\xd1\x99\x11\x92\x74\xf7\xcb\x22\x5b\x4a\xca\xaa\x01\x43\xf6\xd4\x90\xbb\x65\x5c\x61\xb5\x1c\xf1\x23\x9b\x59\x86\x8c\x69\x7c\x0c\x59\x51\xa7\x5d\xe6\x2c\xa4\xcb\xb3\x9c\xd1\x90\x54\x65\xef\x94\x07\x9d\x0c\xc3\x46\x00\x2f\x43\x1c\x34\x43\x8f\x32\x85\x84\xac\x6d\x68\x6c\xcf\x69\x68\x75\x6a\xfd\x6a\xfa\x4a\x73\xf3\x73\xba\x03\xe3\xff\xff\x3f\xff\xdf\xff\x0d\x00\x00\xff\xff\x9b\xc6\xef\xe7\x7d\x0c\x06\x00") + +func dataSurnamesJsonBytes() ([]byte, error) { + return bindataRead( + _dataSurnamesJson, + "data/Surnames.json", + ) +} + +func dataSurnamesJson() (*asset, error) { + bytes, err := dataSurnamesJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "data/Surnames.json", size: 396413, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "data/Dvorak.json": dataDvorakJson, + "data/English.json": dataEnglishJson, + "data/FemaleNames.json": dataFemalenamesJson, + "data/Keypad.json": dataKeypadJson, + "data/L33t.json": dataL33tJson, + "data/MacKeypad.json": dataMackeypadJson, + "data/MaleNames.json": dataMalenamesJson, + "data/Passwords.json": dataPasswordsJson, + "data/Qwerty.json": dataQwertyJson, + "data/Surnames.json": dataSurnamesJson, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "data": &bintree{nil, map[string]*bintree{ + "Dvorak.json": &bintree{dataDvorakJson, map[string]*bintree{}}, + "English.json": &bintree{dataEnglishJson, map[string]*bintree{}}, + "FemaleNames.json": &bintree{dataFemalenamesJson, map[string]*bintree{}}, + "Keypad.json": &bintree{dataKeypadJson, map[string]*bintree{}}, + "L33t.json": &bintree{dataL33tJson, map[string]*bintree{}}, + "MacKeypad.json": &bintree{dataMackeypadJson, map[string]*bintree{}}, + "MaleNames.json": &bintree{dataMalenamesJson, map[string]*bintree{}}, + "Passwords.json": &bintree{dataPasswordsJson, map[string]*bintree{}}, + "Qwerty.json": &bintree{dataQwertyJson, map[string]*bintree{}}, + "Surnames.json": &bintree{dataSurnamesJson, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/entropy/entropyCalculator.go b/vendor/github.com/nbutton23/zxcvbn-go/entropy/entropyCalculator.go new file mode 100644 index 000000000..8f57ea0a4 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/entropy/entropyCalculator.go @@ -0,0 +1,216 @@ +package entropy + +import ( + "github.com/nbutton23/zxcvbn-go/adjacency" + "github.com/nbutton23/zxcvbn-go/match" + "github.com/nbutton23/zxcvbn-go/utils/math" + "math" + "regexp" + "unicode" +) + +const ( + numYears = float64(119) // years match against 1900 - 2019 + numMonths = float64(12) + numDays = float64(31) +) + +var ( + startUpperRx = regexp.MustCompile(`^[A-Z][^A-Z]+$`) + endUpperRx = regexp.MustCompile(`^[^A-Z]+[A-Z]$'`) + allUpperRx = regexp.MustCompile(`^[A-Z]+$`) + keyPadStartingPositions = len(adjacency.GraphMap["keypad"].Graph) + keyPadAvgDegree = adjacency.GraphMap["keypad"].CalculateAvgDegree() +) + +// DictionaryEntropy calculates the entropy of a dictionary match +func DictionaryEntropy(match match.Match, rank float64) float64 { + baseEntropy := math.Log2(rank) + upperCaseEntropy := extraUpperCaseEntropy(match) + //TODO: L33t + return baseEntropy + upperCaseEntropy +} + +func extraUpperCaseEntropy(match match.Match) float64 { + word := match.Token + + allLower := true + + for _, char := range word { + if unicode.IsUpper(char) { + allLower = false + break + } + } + if allLower { + return float64(0) + } + + //a capitalized word is the most common capitalization scheme, + //so it only doubles the search space (uncapitalized + capitalized): 1 extra bit of entropy. + //allcaps and end-capitalized are common enough too, underestimate as 1 extra bit to be safe. + + for _, matcher := range []*regexp.Regexp{startUpperRx, endUpperRx, allUpperRx} { + if matcher.MatchString(word) { + return float64(1) + } + } + //Otherwise calculate the number of ways to capitalize U+L uppercase+lowercase letters with U uppercase letters or + //less. Or, if there's more uppercase than lower (for e.g. PASSwORD), the number of ways to lowercase U+L letters + //with L lowercase letters or less. + + countUpper, countLower := float64(0), float64(0) + for _, char := range word { + if unicode.IsUpper(char) { + countUpper++ + } else if unicode.IsLower(char) { + countLower++ + } + } + totalLenght := countLower + countUpper + var possibililities float64 + + for i := float64(0); i <= math.Min(countUpper, countLower); i++ { + possibililities += float64(zxcvbnmath.NChoseK(totalLenght, i)) + } + + if possibililities < 1 { + return float64(1) + } + + return float64(math.Log2(possibililities)) +} + +// SpatialEntropy calculates the entropy for spatial matches +func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 { + var s, d float64 + if match.DictionaryName == "qwerty" || match.DictionaryName == "dvorak" { + //todo: verify qwerty and dvorak have the same length and degree + s = float64(len(adjacency.BuildQwerty().Graph)) + d = adjacency.BuildQwerty().CalculateAvgDegree() + } else { + s = float64(keyPadStartingPositions) + d = keyPadAvgDegree + } + + possibilities := float64(0) + + length := float64(len(match.Token)) + + //TODO: Should this be <= or just < ? + //Estimate the number of possible patterns w/ length L or less with t turns or less + for i := float64(2); i <= length+1; i++ { + possibleTurns := math.Min(float64(turns), i-1) + for j := float64(1); j <= possibleTurns+1; j++ { + x := zxcvbnmath.NChoseK(i-1, j-1) * s * math.Pow(d, j) + possibilities += x + } + } + + entropy := math.Log2(possibilities) + //add extra entropu for shifted keys. ( % instead of 5 A instead of a) + //Math is similar to extra entropy for uppercase letters in dictionary matches. + + if S := float64(shiftCount); S > float64(0) { + possibilities = float64(0) + U := length - S + + for i := float64(0); i < math.Min(S, U)+1; i++ { + possibilities += zxcvbnmath.NChoseK(S+U, i) + } + + entropy += math.Log2(possibilities) + } + + return entropy +} + +// RepeatEntropy calculates the entropy for repeating entropy +func RepeatEntropy(match match.Match) float64 { + cardinality := CalcBruteForceCardinality(match.Token) + entropy := math.Log2(cardinality * float64(len(match.Token))) + + return entropy +} + +// CalcBruteForceCardinality calculates the brute force cardinality +//TODO: Validate against python +func CalcBruteForceCardinality(password string) float64 { + lower, upper, digits, symbols := float64(0), float64(0), float64(0), float64(0) + + for _, char := range password { + if unicode.IsLower(char) { + lower = float64(26) + } else if unicode.IsDigit(char) { + digits = float64(10) + } else if unicode.IsUpper(char) { + upper = float64(26) + } else { + symbols = float64(33) + } + } + + cardinality := lower + upper + digits + symbols + return cardinality +} + +// SequenceEntropy calculates the entropy for sequences such as 4567 or cdef +func SequenceEntropy(match match.Match, dictionaryLength int, ascending bool) float64 { + firstChar := match.Token[0] + baseEntropy := float64(0) + if string(firstChar) == "a" || string(firstChar) == "1" { + baseEntropy = float64(0) + } else { + baseEntropy = math.Log2(float64(dictionaryLength)) + //TODO: should this be just the first or any char? + if unicode.IsUpper(rune(firstChar)) { + baseEntropy++ + } + } + + if !ascending { + baseEntropy++ + } + return baseEntropy + math.Log2(float64(len(match.Token))) +} + +// ExtraLeetEntropy calulates the added entropy provied by l33t substitustions +func ExtraLeetEntropy(match match.Match, password string) float64 { + var subsitutions float64 + var unsub float64 + subPassword := password[match.I:match.J] + for index, char := range subPassword { + if string(char) != string(match.Token[index]) { + subsitutions++ + } else { + //TODO: Make this only true for 1337 chars that are not subs? + unsub++ + } + } + + var possibilities float64 + + for i := float64(0); i <= math.Min(subsitutions, unsub)+1; i++ { + possibilities += zxcvbnmath.NChoseK(subsitutions+unsub, i) + } + + if possibilities <= 1 { + return float64(1) + } + return math.Log2(possibilities) +} + +// DateEntropy calculates the entropy provided by a date +func DateEntropy(dateMatch match.DateMatch) float64 { + var entropy float64 + if dateMatch.Year < 100 { + entropy = math.Log2(numDays * numMonths * 100) + } else { + entropy = math.Log2(numDays * numMonths * numYears) + } + + if dateMatch.Separator != "" { + entropy += 2 //add two bits for separator selection [/,-,.,etc] + } + return entropy +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/frequency/frequency.go b/vendor/github.com/nbutton23/zxcvbn-go/frequency/frequency.go new file mode 100644 index 000000000..d056e4d4e --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/frequency/frequency.go @@ -0,0 +1,50 @@ +package frequency + +import ( + "encoding/json" + "log" + + "github.com/nbutton23/zxcvbn-go/data" +) + +// List holds a frequency list +type List struct { + Name string + List []string +} + +// Lists holds all the frequency list in a map +var Lists = make(map[string]List) + +func init() { + maleFilePath := getAsset("data/MaleNames.json") + femaleFilePath := getAsset("data/FemaleNames.json") + surnameFilePath := getAsset("data/Surnames.json") + englishFilePath := getAsset("data/English.json") + passwordsFilePath := getAsset("data/Passwords.json") + + Lists["MaleNames"] = getStringListFromAsset(maleFilePath, "MaleNames") + Lists["FemaleNames"] = getStringListFromAsset(femaleFilePath, "FemaleNames") + Lists["Surname"] = getStringListFromAsset(surnameFilePath, "Surname") + Lists["English"] = getStringListFromAsset(englishFilePath, "English") + Lists["Passwords"] = getStringListFromAsset(passwordsFilePath, "Passwords") + +} +func getAsset(name string) []byte { + data, err := data.Asset(name) + if err != nil { + panic("Error getting asset " + name) + } + + return data +} +func getStringListFromAsset(data []byte, name string) List { + + var tempList List + err := json.Unmarshal(data, &tempList) + if err != nil { + log.Fatal(err) + } + tempList.Name = name + return tempList +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/match/match.go b/vendor/github.com/nbutton23/zxcvbn-go/match/match.go new file mode 100644 index 000000000..dd30bea04 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/match/match.go @@ -0,0 +1,44 @@ +package match + +//Matches is an alies for []Match used for sorting +type Matches []Match + +func (s Matches) Len() int { + return len(s) +} +func (s Matches) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} +func (s Matches) Less(i, j int) bool { + if s[i].I < s[j].I { + return true + } else if s[i].I == s[j].I { + return s[i].J < s[j].J + } else { + return false + } +} + +// Match represents different matches +type Match struct { + Pattern string + I, J int + Token string + DictionaryName string + Entropy float64 +} + +//DateMatch is specifilly a match for type date +type DateMatch struct { + Pattern string + I, J int + Token string + Separator string + Day, Month, Year int64 +} + +//Matcher are a func and ID that can be used to match different passwords +type Matcher struct { + MatchingFunc func(password string) []Match + ID string +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/matching/dateMatchers.go b/vendor/github.com/nbutton23/zxcvbn-go/matching/dateMatchers.go new file mode 100644 index 000000000..8dfdf2410 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/matching/dateMatchers.go @@ -0,0 +1,209 @@ +package matching + +import ( + "regexp" + "strconv" + "strings" + + "github.com/nbutton23/zxcvbn-go/entropy" + "github.com/nbutton23/zxcvbn-go/match" +) + +const ( + dateSepMatcherName = "DATESEP" + dateWithOutSepMatcherName = "DATEWITHOUT" +) + +var ( + dateRxYearSuffix = regexp.MustCompile(`((\d{1,2})(\s|-|\/|\\|_|\.)(\d{1,2})(\s|-|\/|\\|_|\.)(19\d{2}|200\d|201\d|\d{2}))`) + dateRxYearPrefix = regexp.MustCompile(`((19\d{2}|200\d|201\d|\d{2})(\s|-|/|\\|_|\.)(\d{1,2})(\s|-|/|\\|_|\.)(\d{1,2}))`) + dateWithOutSepMatch = regexp.MustCompile(`\d{4,8}`) +) + +//FilterDateSepMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher +func FilterDateSepMatcher(m match.Matcher) bool { + return m.ID == dateSepMatcherName +} + +//FilterDateWithoutSepMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher +func FilterDateWithoutSepMatcher(m match.Matcher) bool { + return m.ID == dateWithOutSepMatcherName +} + +func checkDate(day, month, year int64) (bool, int64, int64, int64) { + if (12 <= month && month <= 31) && day <= 12 { + day, month = month, day + } + + if day > 31 || month > 12 { + return false, 0, 0, 0 + } + + if !((1900 <= year && year <= 2019) || (0 <= year && year <= 99)) { + return false, 0, 0, 0 + } + + return true, day, month, year +} + +func dateSepMatcher(password string) []match.Match { + dateMatches := dateSepMatchHelper(password) + + var matches []match.Match + for _, dateMatch := range dateMatches { + match := match.Match{ + I: dateMatch.I, + J: dateMatch.J, + Entropy: entropy.DateEntropy(dateMatch), + DictionaryName: "date_match", + Token: dateMatch.Token, + } + + matches = append(matches, match) + } + + return matches +} +func dateSepMatchHelper(password string) []match.DateMatch { + + var matches []match.DateMatch + + for _, v := range dateRxYearSuffix.FindAllString(password, len(password)) { + splitV := dateRxYearSuffix.FindAllStringSubmatch(v, len(v)) + i := strings.Index(password, v) + j := i + len(v) + day, _ := strconv.ParseInt(splitV[0][4], 10, 16) + month, _ := strconv.ParseInt(splitV[0][2], 10, 16) + year, _ := strconv.ParseInt(splitV[0][6], 10, 16) + match := match.DateMatch{Day: day, Month: month, Year: year, Separator: splitV[0][5], I: i, J: j, Token: password[i:j]} + matches = append(matches, match) + } + + for _, v := range dateRxYearPrefix.FindAllString(password, len(password)) { + splitV := dateRxYearPrefix.FindAllStringSubmatch(v, len(v)) + i := strings.Index(password, v) + j := i + len(v) + day, _ := strconv.ParseInt(splitV[0][4], 10, 16) + month, _ := strconv.ParseInt(splitV[0][6], 10, 16) + year, _ := strconv.ParseInt(splitV[0][2], 10, 16) + match := match.DateMatch{Day: day, Month: month, Year: year, Separator: splitV[0][5], I: i, J: j, Token: password[i:j]} + matches = append(matches, match) + } + + var out []match.DateMatch + for _, match := range matches { + if valid, day, month, year := checkDate(match.Day, match.Month, match.Year); valid { + match.Pattern = "date" + match.Day = day + match.Month = month + match.Year = year + out = append(out, match) + } + } + return out + +} + +type dateMatchCandidate struct { + DayMonth string + Year string + I, J int +} + +type dateMatchCandidateTwo struct { + Day string + Month string + Year string + I, J int +} + +func dateWithoutSepMatch(password string) []match.Match { + dateMatches := dateWithoutSepMatchHelper(password) + + var matches []match.Match + for _, dateMatch := range dateMatches { + match := match.Match{ + I: dateMatch.I, + J: dateMatch.J, + Entropy: entropy.DateEntropy(dateMatch), + DictionaryName: "date_match", + Token: dateMatch.Token, + } + + matches = append(matches, match) + } + + return matches +} + +//TODO Has issues with 6 digit dates +func dateWithoutSepMatchHelper(password string) (matches []match.DateMatch) { + for _, v := range dateWithOutSepMatch.FindAllString(password, len(password)) { + i := strings.Index(password, v) + j := i + len(v) + length := len(v) + lastIndex := length - 1 + var candidatesRoundOne []dateMatchCandidate + + if length <= 6 { + //2-digit year prefix + candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[2:], v[0:2], i, j)) + + //2-digityear suffix + candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-2], v[lastIndex-2:], i, j)) + } + if length >= 6 { + //4-digit year prefix + candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[4:], v[0:4], i, j)) + + //4-digit year sufix + candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-3], v[lastIndex-3:], i, j)) + } + + var candidatesRoundTwo []dateMatchCandidateTwo + for _, c := range candidatesRoundOne { + if len(c.DayMonth) == 2 { + candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:0], c.DayMonth[1:1], c.Year, c.I, c.J)) + } else if len(c.DayMonth) == 3 { + candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:2], c.DayMonth[2:2], c.Year, c.I, c.J)) + candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:0], c.DayMonth[1:3], c.Year, c.I, c.J)) + } else if len(c.DayMonth) == 4 { + candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:2], c.DayMonth[2:4], c.Year, c.I, c.J)) + } + } + + for _, candidate := range candidatesRoundTwo { + intDay, err := strconv.ParseInt(candidate.Day, 10, 16) + if err != nil { + continue + } + + intMonth, err := strconv.ParseInt(candidate.Month, 10, 16) + + if err != nil { + continue + } + + intYear, err := strconv.ParseInt(candidate.Year, 10, 16) + if err != nil { + continue + } + + if ok, _, _, _ := checkDate(intDay, intMonth, intYear); ok { + matches = append(matches, match.DateMatch{Token: password, Pattern: "date", Day: intDay, Month: intMonth, Year: intYear, I: i, J: j}) + } + + } + } + + return matches +} + +func buildDateMatchCandidate(dayMonth, year string, i, j int) dateMatchCandidate { + return dateMatchCandidate{DayMonth: dayMonth, Year: year, I: i, J: j} +} + +func buildDateMatchCandidateTwo(day, month string, year string, i, j int) dateMatchCandidateTwo { + + return dateMatchCandidateTwo{Day: day, Month: month, Year: year, I: i, J: j} +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/matching/dictionaryMatch.go b/vendor/github.com/nbutton23/zxcvbn-go/matching/dictionaryMatch.go new file mode 100644 index 000000000..4ddb2c3b0 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/matching/dictionaryMatch.go @@ -0,0 +1,57 @@ +package matching + +import ( + "strings" + + "github.com/nbutton23/zxcvbn-go/entropy" + "github.com/nbutton23/zxcvbn-go/match" +) + +func buildDictMatcher(dictName string, rankedDict map[string]int) func(password string) []match.Match { + return func(password string) []match.Match { + matches := dictionaryMatch(password, dictName, rankedDict) + for _, v := range matches { + v.DictionaryName = dictName + } + return matches + } + +} + +func dictionaryMatch(password string, dictionaryName string, rankedDict map[string]int) []match.Match { + var results []match.Match + pwLower := strings.ToLower(password) + + pwLowerRunes := []rune(pwLower) + length := len(pwLowerRunes) + + for i := 0; i < length; i++ { + for j := i; j < length; j++ { + word := pwLowerRunes[i : j+1] + if val, ok := rankedDict[string(word)]; ok { + matchDic := match.Match{Pattern: "dictionary", + DictionaryName: dictionaryName, + I: i, + J: j, + Token: string([]rune(password)[i : j+1]), + } + matchDic.Entropy = entropy.DictionaryEntropy(matchDic, float64(val)) + + results = append(results, matchDic) + } + } + } + + return results +} + +func buildRankedDict(unrankedList []string) map[string]int { + + result := make(map[string]int) + + for i, v := range unrankedList { + result[strings.ToLower(v)] = i + 1 + } + + return result +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/matching/leet.go b/vendor/github.com/nbutton23/zxcvbn-go/matching/leet.go new file mode 100644 index 000000000..610f1973f --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/matching/leet.go @@ -0,0 +1,234 @@ +package matching + +import ( + "strings" + + "github.com/nbutton23/zxcvbn-go/entropy" + "github.com/nbutton23/zxcvbn-go/match" +) + +// L33TMatcherName id +const L33TMatcherName = "l33t" + +//FilterL33tMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher +func FilterL33tMatcher(m match.Matcher) bool { + return m.ID == L33TMatcherName +} + +func l33tMatch(password string) []match.Match { + permutations := getPermutations(password) + + var matches []match.Match + + for _, permutation := range permutations { + for _, mather := range dictionaryMatchers { + matches = append(matches, mather.MatchingFunc(permutation)...) + } + } + + for _, match := range matches { + match.Entropy += entropy.ExtraLeetEntropy(match, password) + match.DictionaryName = match.DictionaryName + "_3117" + } + + return matches +} + +// This function creates a list of permutations based on a fixed table stored on data. The table +// will be reduced in order to proceed in the function using only relevant values (see +// relevantL33tSubtable). +func getPermutations(password string) []string { + substitutions := relevantL33tSubtable(password) + permutations := getAllPermutationsOfLeetSubstitutions(password, substitutions) + return permutations +} + +// This function loads the table from data but only keep in memory the values that are present +// inside the provided password. +func relevantL33tSubtable(password string) map[string][]string { + relevantSubs := make(map[string][]string) + for key, values := range l33tTable.Graph { + for _, value := range values { + if strings.Contains(password, value) { + relevantSubs[key] = append(relevantSubs[key], value) + } + } + } + + return relevantSubs +} + +// This function creates the list of permutations of a given password using the provided table as +// reference for its operation. +func getAllPermutationsOfLeetSubstitutions(password string, table map[string][]string) []string { + result := []string{} + + // create a list of tables without conflicting keys/values (this happens for "|", "7" and "1") + noConflictsTables := createListOfMapsWithoutConflicts(table) + for _, noConflictsTable := range noConflictsTables { + substitutionsMaps := createSubstitutionsMapsFromTable(noConflictsTable) + for _, substitutionsMap := range substitutionsMaps { + newValue := createWordForSubstitutionMap(password, substitutionsMap) + if !stringSliceContainsValue(result, newValue) { + result = append(result, newValue) + } + } + } + + return result +} + +// Create the possible list of maps removing the conflicts from it. As an example, the value "|" +// may represent "i" and "l". For each representation of the conflicting value, a new map is +// created. This may grow exponencialy according to the number of conflicts. The number of maps +// returned by this function may be reduced if the relevantL33tSubtable function was called to +// identify only relevant items. +func createListOfMapsWithoutConflicts(table map[string][]string) []map[string][]string { + // the resulting list starts with the provided table + result := []map[string][]string{} + result = append(result, table) + + // iterate over the list of conflicts in order to expand the maps for each one + conflicts := retrieveConflictsListFromTable(table) + for _, value := range conflicts { + newMapList := []map[string][]string{} + + // for each conflict a new list of maps will be created for every already known map + for _, currentMap := range result { + newMaps := createDifferentMapsForLeetChar(currentMap, value) + newMapList = append(newMapList, newMaps...) + } + + result = newMapList + } + + return result +} + +// This function retrieves the list of values that appear for one or more keys. This is usefull to +// know which l33t chars can represent more than one letter. +func retrieveConflictsListFromTable(table map[string][]string) []string { + result := []string{} + foundValues := []string{} + + for _, values := range table { + for _, value := range values { + if stringSliceContainsValue(foundValues, value) { + // only add on results if it was not identified as conflict before + if !stringSliceContainsValue(result, value) { + result = append(result, value) + } + } else { + foundValues = append(foundValues, value) + } + } + } + + return result +} + +// This function aims to create different maps for a given char if this char represents a conflict. +// If the specified char is not a conflit one, the same map will be returned. In scenarios which +// the provided char can not be found on map, an empty list will be returned. This function was +// designed to be used on conflicts situations. +func createDifferentMapsForLeetChar(table map[string][]string, leetChar string) []map[string][]string { + result := []map[string][]string{} + + keysWithSameValue := retrieveListOfKeysWithSpecificValueFromTable(table, leetChar) + for _, key := range keysWithSameValue { + newMap := copyMapRemovingSameValueFromOtherKeys(table, key, leetChar) + result = append(result, newMap) + } + + return result +} + +// This function retrieves the list of keys that can be represented using the given value. +func retrieveListOfKeysWithSpecificValueFromTable(table map[string][]string, valueToFind string) []string { + result := []string{} + + for key, values := range table { + for _, value := range values { + if value == valueToFind && !stringSliceContainsValue(result, key) { + result = append(result, key) + } + } + } + + return result +} + +// This function returns a lsit of substitution map from a given table. Each map in the result will +// provide only one representation for each value. As an example, if the provided map contains the +// values "@" and "4" in the possibilities to represent "a", two maps will be created where one +// will contain "a" mapping to "@" and the other one will provide "a" mapping to "4". +func createSubstitutionsMapsFromTable(table map[string][]string) []map[string]string { + result := []map[string]string{{"": ""}} + + for key, values := range table { + newResult := []map[string]string{} + + for _, mapInCurrentResult := range result { + for _, value := range values { + newMapForValue := copyMap(mapInCurrentResult) + newMapForValue[key] = value + newResult = append(newResult, newMapForValue) + } + } + + result = newResult + } + + // verification to make sure that the slice was filled + if len(result) == 1 && len(result[0]) == 1 && result[0][""] == "" { + return []map[string]string{} + } + + return result +} + +// This function replaces the values provided on substitution map over the provided word. +func createWordForSubstitutionMap(word string, substitutionMap map[string]string) string { + result := word + for key, value := range substitutionMap { + result = strings.Replace(result, value, key, -1) + } + + return result +} + +func stringSliceContainsValue(slice []string, value string) bool { + for _, valueInSlice := range slice { + if valueInSlice == value { + return true + } + } + + return false +} + +func copyMap(table map[string]string) map[string]string { + result := make(map[string]string) + + for key, value := range table { + result[key] = value + } + + return result +} + +// This function creates a new map based on the one provided but excluding possible representations +// of the same value on other keys. +func copyMapRemovingSameValueFromOtherKeys(table map[string][]string, keyToFix string, valueToFix string) map[string][]string { + result := make(map[string][]string) + + for key, values := range table { + for _, value := range values { + if !(value == valueToFix && key != keyToFix) { + result[key] = append(result[key], value) + } + } + } + + return result +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/matching/matching.go b/vendor/github.com/nbutton23/zxcvbn-go/matching/matching.go new file mode 100644 index 000000000..4577db8a4 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/matching/matching.go @@ -0,0 +1,82 @@ +package matching + +import ( + "sort" + + "github.com/nbutton23/zxcvbn-go/adjacency" + "github.com/nbutton23/zxcvbn-go/frequency" + "github.com/nbutton23/zxcvbn-go/match" +) + +var ( + dictionaryMatchers []match.Matcher + matchers []match.Matcher + adjacencyGraphs []adjacency.Graph + l33tTable adjacency.Graph + + sequences map[string]string +) + +func init() { + loadFrequencyList() +} + +// Omnimatch runs all matchers against the password +func Omnimatch(password string, userInputs []string, filters ...func(match.Matcher) bool) (matches []match.Match) { + + //Can I run into the issue where nil is not equal to nil? + if dictionaryMatchers == nil || adjacencyGraphs == nil { + loadFrequencyList() + } + + if userInputs != nil { + userInputMatcher := buildDictMatcher("user_inputs", buildRankedDict(userInputs)) + matches = userInputMatcher(password) + } + + for _, matcher := range matchers { + shouldBeFiltered := false + for i := range filters { + if filters[i](matcher) { + shouldBeFiltered = true + break + } + } + if !shouldBeFiltered { + matches = append(matches, matcher.MatchingFunc(password)...) + } + } + sort.Sort(match.Matches(matches)) + return matches +} + +func loadFrequencyList() { + + for n, list := range frequency.Lists { + dictionaryMatchers = append(dictionaryMatchers, match.Matcher{MatchingFunc: buildDictMatcher(n, buildRankedDict(list.List)), ID: n}) + } + + l33tTable = adjacency.GraphMap["l33t"] + + adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["qwerty"]) + adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["dvorak"]) + adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["keypad"]) + adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["macKeypad"]) + + //l33tFilePath, _ := filepath.Abs("adjacency/L33t.json") + //L33T_TABLE = adjacency.GetAdjancencyGraphFromFile(l33tFilePath, "l33t") + + sequences = make(map[string]string) + sequences["lower"] = "abcdefghijklmnopqrstuvwxyz" + sequences["upper"] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + sequences["digits"] = "0123456789" + + matchers = append(matchers, dictionaryMatchers...) + matchers = append(matchers, match.Matcher{MatchingFunc: spatialMatch, ID: spatialMatcherName}) + matchers = append(matchers, match.Matcher{MatchingFunc: repeatMatch, ID: repeatMatcherName}) + matchers = append(matchers, match.Matcher{MatchingFunc: sequenceMatch, ID: sequenceMatcherName}) + matchers = append(matchers, match.Matcher{MatchingFunc: l33tMatch, ID: L33TMatcherName}) + matchers = append(matchers, match.Matcher{MatchingFunc: dateSepMatcher, ID: dateSepMatcherName}) + matchers = append(matchers, match.Matcher{MatchingFunc: dateWithoutSepMatch, ID: dateWithOutSepMatcherName}) + +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/matching/repeatMatch.go b/vendor/github.com/nbutton23/zxcvbn-go/matching/repeatMatch.go new file mode 100644 index 000000000..a93e45935 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/matching/repeatMatch.go @@ -0,0 +1,67 @@ +package matching + +import ( + "strings" + + "github.com/nbutton23/zxcvbn-go/entropy" + "github.com/nbutton23/zxcvbn-go/match" +) + +const repeatMatcherName = "REPEAT" + +//FilterRepeatMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher +func FilterRepeatMatcher(m match.Matcher) bool { + return m.ID == repeatMatcherName +} + +func repeatMatch(password string) []match.Match { + var matches []match.Match + + //Loop through password. if current == prev currentStreak++ else if currentStreak > 2 {buildMatch; currentStreak = 1} prev = current + var current, prev string + currentStreak := 1 + var i int + var char rune + for i, char = range password { + current = string(char) + if i == 0 { + prev = current + continue + } + + if strings.ToLower(current) == strings.ToLower(prev) { + currentStreak++ + + } else if currentStreak > 2 { + iPos := i - currentStreak + jPos := i - 1 + matchRepeat := match.Match{ + Pattern: "repeat", + I: iPos, + J: jPos, + Token: password[iPos : jPos+1], + DictionaryName: prev} + matchRepeat.Entropy = entropy.RepeatEntropy(matchRepeat) + matches = append(matches, matchRepeat) + currentStreak = 1 + } else { + currentStreak = 1 + } + + prev = current + } + + if currentStreak > 2 { + iPos := i - currentStreak + 1 + jPos := i + matchRepeat := match.Match{ + Pattern: "repeat", + I: iPos, + J: jPos, + Token: password[iPos : jPos+1], + DictionaryName: prev} + matchRepeat.Entropy = entropy.RepeatEntropy(matchRepeat) + matches = append(matches, matchRepeat) + } + return matches +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/matching/sequenceMatch.go b/vendor/github.com/nbutton23/zxcvbn-go/matching/sequenceMatch.go new file mode 100644 index 000000000..e0ed05229 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/matching/sequenceMatch.go @@ -0,0 +1,76 @@ +package matching + +import ( + "strings" + + "github.com/nbutton23/zxcvbn-go/entropy" + "github.com/nbutton23/zxcvbn-go/match" +) + +const sequenceMatcherName = "SEQ" + +//FilterSequenceMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher +func FilterSequenceMatcher(m match.Matcher) bool { + return m.ID == sequenceMatcherName +} + +func sequenceMatch(password string) []match.Match { + var matches []match.Match + for i := 0; i < len(password); { + j := i + 1 + var seq string + var seqName string + seqDirection := 0 + for seqCandidateName, seqCandidate := range sequences { + iN := strings.Index(seqCandidate, string(password[i])) + var jN int + if j < len(password) { + jN = strings.Index(seqCandidate, string(password[j])) + } else { + jN = -1 + } + + if iN > -1 && jN > -1 { + direction := jN - iN + if direction == 1 || direction == -1 { + seq = seqCandidate + seqName = seqCandidateName + seqDirection = direction + break + } + } + + } + + if seq != "" { + for { + var prevN, curN int + if j < len(password) { + prevChar, curChar := password[j-1], password[j] + prevN, curN = strings.Index(seq, string(prevChar)), strings.Index(seq, string(curChar)) + } + + if j == len(password) || curN-prevN != seqDirection { + if j-i > 2 { + matchSequence := match.Match{ + Pattern: "sequence", + I: i, + J: j - 1, + Token: password[i:j], + DictionaryName: seqName, + } + + matchSequence.Entropy = entropy.SequenceEntropy(matchSequence, len(seq), (seqDirection == 1)) + matches = append(matches, matchSequence) + } + break + } else { + j++ + } + + } + } + i = j + } + return matches +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/matching/spatialMatch.go b/vendor/github.com/nbutton23/zxcvbn-go/matching/spatialMatch.go new file mode 100644 index 000000000..fd858f5d1 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/matching/spatialMatch.go @@ -0,0 +1,88 @@ +package matching + +import ( + "strings" + + "github.com/nbutton23/zxcvbn-go/adjacency" + "github.com/nbutton23/zxcvbn-go/entropy" + "github.com/nbutton23/zxcvbn-go/match" +) + +const spatialMatcherName = "SPATIAL" + +//FilterSpatialMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher +func FilterSpatialMatcher(m match.Matcher) bool { + return m.ID == spatialMatcherName +} + +func spatialMatch(password string) (matches []match.Match) { + for _, graph := range adjacencyGraphs { + if graph.Graph != nil { + matches = append(matches, spatialMatchHelper(password, graph)...) + } + } + return matches +} + +func spatialMatchHelper(password string, graph adjacency.Graph) (matches []match.Match) { + + for i := 0; i < len(password)-1; { + j := i + 1 + lastDirection := -99 //an int that it should never be! + turns := 0 + shiftedCount := 0 + + for { + prevChar := password[j-1] + found := false + foundDirection := -1 + curDirection := -1 + //My graphs seem to be wrong. . . and where the hell is qwerty + adjacents := graph.Graph[string(prevChar)] + //Consider growing pattern by one character if j hasn't gone over the edge + if j < len(password) { + curChar := password[j] + for _, adj := range adjacents { + curDirection++ + + if strings.Index(adj, string(curChar)) != -1 { + found = true + foundDirection = curDirection + + if strings.Index(adj, string(curChar)) == 1 { + //index 1 in the adjacency means the key is shifted, 0 means unshifted: A vs a, % vs 5, etc. + //for example, 'q' is adjacent to the entry '2@'. @ is shifted w/ index 1, 2 is unshifted. + shiftedCount++ + } + + if lastDirection != foundDirection { + //adding a turn is correct even in the initial case when last_direction is null: + //every spatial pattern starts with a turn. + turns++ + lastDirection = foundDirection + } + break + } + } + } + + //if the current pattern continued, extend j and try to grow again + if found { + j++ + } else { + //otherwise push the pattern discovered so far, if any... + //don't consider length 1 or 2 chains. + if j-i > 2 { + matchSpc := match.Match{Pattern: "spatial", I: i, J: j - 1, Token: password[i:j], DictionaryName: graph.Name} + matchSpc.Entropy = entropy.SpatialEntropy(matchSpc, turns, shiftedCount) + matches = append(matches, matchSpc) + } + //. . . and then start a new search from the rest of the password + i = j + break + } + } + + } + return matches +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/scoring/scoring.go b/vendor/github.com/nbutton23/zxcvbn-go/scoring/scoring.go new file mode 100644 index 000000000..4f68a6dca --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/scoring/scoring.go @@ -0,0 +1,177 @@ +package scoring + +import ( + "fmt" + "github.com/nbutton23/zxcvbn-go/entropy" + "github.com/nbutton23/zxcvbn-go/match" + "github.com/nbutton23/zxcvbn-go/utils/math" + "math" + "sort" +) + +const ( + //for a hash function like bcrypt/scrypt/PBKDF2, 10ms per guess is a safe lower bound. + //(usually a guess would take longer -- this assumes fast hardware and a small work factor.) + //adjust for your site accordingly if you use another hash function, possibly by + //several orders of magnitude! + singleGuess float64 = 0.010 + numAttackers float64 = 100 //Cores used to make guesses + secondsPerGuess float64 = singleGuess / numAttackers +) + +// MinEntropyMatch is the lowest entropy match found +type MinEntropyMatch struct { + Password string + Entropy float64 + MatchSequence []match.Match + CrackTime float64 + CrackTimeDisplay string + Score int + CalcTime float64 +} + +/* +MinimumEntropyMatchSequence returns the minimum entropy + + Takes a list of overlapping matches, returns the non-overlapping sublist with + minimum entropy. O(nm) dp alg for length-n password with m candidate matches. +*/ +func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntropyMatch { + bruteforceCardinality := float64(entropy.CalcBruteForceCardinality(password)) + upToK := make([]float64, len(password)) + backPointers := make([]match.Match, len(password)) + + for k := 0; k < len(password); k++ { + upToK[k] = get(upToK, k-1) + math.Log2(bruteforceCardinality) + + for _, match := range matches { + if match.J != k { + continue + } + + i, j := match.I, match.J + //see if best entropy up to i-1 + entropy of match is less that current min at j + upTo := get(upToK, i-1) + candidateEntropy := upTo + match.Entropy + + if candidateEntropy < upToK[j] { + upToK[j] = candidateEntropy + match.Entropy = candidateEntropy + backPointers[j] = match + } + } + } + + //walk backwards and decode the best sequence + var matchSequence []match.Match + passwordLen := len(password) + passwordLen-- + for k := passwordLen; k >= 0; { + match := backPointers[k] + if match.Pattern != "" { + matchSequence = append(matchSequence, match) + k = match.I - 1 + + } else { + k-- + } + + } + sort.Sort(match.Matches(matchSequence)) + + makeBruteForceMatch := func(i, j int) match.Match { + return match.Match{Pattern: "bruteforce", + I: i, + J: j, + Token: password[i : j+1], + Entropy: math.Log2(math.Pow(bruteforceCardinality, float64(j-i)))} + + } + + k := 0 + var matchSequenceCopy []match.Match + for _, match := range matchSequence { + i, j := match.I, match.J + if i-k > 0 { + matchSequenceCopy = append(matchSequenceCopy, makeBruteForceMatch(k, i-1)) + } + k = j + 1 + matchSequenceCopy = append(matchSequenceCopy, match) + } + + if k < len(password) { + matchSequenceCopy = append(matchSequenceCopy, makeBruteForceMatch(k, len(password)-1)) + } + var minEntropy float64 + if len(password) == 0 { + minEntropy = float64(0) + } else { + minEntropy = upToK[len(password)-1] + } + + crackTime := roundToXDigits(entropyToCrackTime(minEntropy), 3) + return MinEntropyMatch{Password: password, + Entropy: roundToXDigits(minEntropy, 3), + MatchSequence: matchSequenceCopy, + CrackTime: crackTime, + CrackTimeDisplay: displayTime(crackTime), + Score: crackTimeToScore(crackTime)} + +} +func get(a []float64, i int) float64 { + if i < 0 || i >= len(a) { + return float64(0) + } + + return a[i] +} + +func entropyToCrackTime(entropy float64) float64 { + crackTime := (0.5 * math.Pow(float64(2), entropy)) * secondsPerGuess + + return crackTime +} + +func roundToXDigits(number float64, digits int) float64 { + return zxcvbnmath.Round(number, .5, digits) +} + +func displayTime(seconds float64) string { + formater := "%.1f %s" + minute := float64(60) + hour := minute * float64(60) + day := hour * float64(24) + month := day * float64(31) + year := month * float64(12) + century := year * float64(100) + + if seconds < minute { + return "instant" + } else if seconds < hour { + return fmt.Sprintf(formater, (1 + math.Ceil(seconds/minute)), "minutes") + } else if seconds < day { + return fmt.Sprintf(formater, (1 + math.Ceil(seconds/hour)), "hours") + } else if seconds < month { + return fmt.Sprintf(formater, (1 + math.Ceil(seconds/day)), "days") + } else if seconds < year { + return fmt.Sprintf(formater, (1 + math.Ceil(seconds/month)), "months") + } else if seconds < century { + return fmt.Sprintf(formater, (1 + math.Ceil(seconds/century)), "years") + } else { + return "centuries" + } +} + +func crackTimeToScore(seconds float64) int { + if seconds < math.Pow(10, 2) { + return 0 + } else if seconds < math.Pow(10, 4) { + return 1 + } else if seconds < math.Pow(10, 6) { + return 2 + } else if seconds < math.Pow(10, 8) { + return 3 + } + + return 4 +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/utils/math/mathutils.go b/vendor/github.com/nbutton23/zxcvbn-go/utils/math/mathutils.go new file mode 100644 index 000000000..1b989d194 --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/utils/math/mathutils.go @@ -0,0 +1,40 @@ +package zxcvbnmath + +import "math" + +/* +NChoseK http://blog.plover.com/math/choose.html +I am surprised that I have to define these. . . Maybe i just didn't look hard enough for a lib. +*/ +func NChoseK(n, k float64) float64 { + if k > n { + return 0 + } else if k == 0 { + return 1 + } + + var r float64 = 1 + + for d := float64(1); d <= k; d++ { + r *= n + r /= d + n-- + } + + return r +} + +// Round a number +func Round(val float64, roundOn float64, places int) (newVal float64) { + var round float64 + pow := math.Pow(10, float64(places)) + digit := pow * val + _, div := math.Modf(digit) + if div >= roundOn { + round = math.Ceil(digit) + } else { + round = math.Floor(digit) + } + newVal = round / pow + return +} diff --git a/vendor/github.com/nbutton23/zxcvbn-go/zxcvbn.go b/vendor/github.com/nbutton23/zxcvbn-go/zxcvbn.go new file mode 100644 index 000000000..9c34b1c8c --- /dev/null +++ b/vendor/github.com/nbutton23/zxcvbn-go/zxcvbn.go @@ -0,0 +1,22 @@ +package zxcvbn + +import ( + "time" + + "github.com/nbutton23/zxcvbn-go/match" + "github.com/nbutton23/zxcvbn-go/matching" + "github.com/nbutton23/zxcvbn-go/scoring" + "github.com/nbutton23/zxcvbn-go/utils/math" +) + +// PasswordStrength takes a password, userInputs and optional filters and returns a MinEntropyMatch +func PasswordStrength(password string, userInputs []string, filters ...func(match.Matcher) bool) scoring.MinEntropyMatch { + start := time.Now() + matches := matching.Omnimatch(password, userInputs, filters...) + result := scoring.MinimumEntropyMatchSequence(password, matches) + end := time.Now() + + calcTime := end.Nanosecond() - start.Nanosecond() + result.CalcTime = zxcvbnmath.Round(float64(calcTime)*time.Nanosecond.Seconds(), .5, 3) + return result +} diff --git a/vendor/github.com/pelletier/go-toml/.gitignore b/vendor/github.com/pelletier/go-toml/.gitignore new file mode 100644 index 000000000..99e38bbc5 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/.gitignore @@ -0,0 +1,2 @@ +test_program/test_program_bin +fuzz/ diff --git a/vendor/github.com/pelletier/go-toml/.travis.yml b/vendor/github.com/pelletier/go-toml/.travis.yml new file mode 100644 index 000000000..c9fbf304b --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/.travis.yml @@ -0,0 +1,23 @@ +sudo: false +language: go +go: + - 1.8.x + - 1.9.x + - 1.10.x + - tip +matrix: + allow_failures: + - go: tip + fast_finish: true +script: + - if [ -n "$(go fmt ./...)" ]; then exit 1; fi + - ./test.sh + - ./benchmark.sh $TRAVIS_BRANCH https://github.com/$TRAVIS_REPO_SLUG.git +before_install: + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi +branches: + only: [master] +after_success: + - $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=coverage.out -repotoken $COVERALLS_TOKEN diff --git a/vendor/github.com/pelletier/go-toml/LICENSE b/vendor/github.com/pelletier/go-toml/LICENSE new file mode 100644 index 000000000..583bdae62 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 - 2017 Thomas Pelletier, Eric Anderton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/pelletier/go-toml/README.md b/vendor/github.com/pelletier/go-toml/README.md new file mode 100644 index 000000000..0d357acf3 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/README.md @@ -0,0 +1,131 @@ +# go-toml + +Go library for the [TOML](https://github.com/mojombo/toml) format. + +This library supports TOML version +[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) + +[![GoDoc](https://godoc.org/github.com/pelletier/go-toml?status.svg)](http://godoc.org/github.com/pelletier/go-toml) +[![license](https://img.shields.io/github/license/pelletier/go-toml.svg)](https://github.com/pelletier/go-toml/blob/master/LICENSE) +[![Build Status](https://travis-ci.org/pelletier/go-toml.svg?branch=master)](https://travis-ci.org/pelletier/go-toml) +[![Coverage Status](https://coveralls.io/repos/github/pelletier/go-toml/badge.svg?branch=master)](https://coveralls.io/github/pelletier/go-toml?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/pelletier/go-toml)](https://goreportcard.com/report/github.com/pelletier/go-toml) + +## Features + +Go-toml provides the following features for using data parsed from TOML documents: + +* Load TOML documents from files and string data +* Easily navigate TOML structure using Tree +* Mashaling and unmarshaling to and from data structures +* Line & column position data for all parsed elements +* [Query support similar to JSON-Path](query/) +* Syntax errors contain line and column numbers + +## Import + +```go +import "github.com/pelletier/go-toml" +``` + +## Usage example + +Read a TOML document: + +```go +config, _ := toml.Load(` +[postgres] +user = "pelletier" +password = "mypassword"`) +// retrieve data directly +user := config.Get("postgres.user").(string) + +// or using an intermediate object +postgresConfig := config.Get("postgres").(*toml.Tree) +password := postgresConfig.Get("password").(string) +``` + +Or use Unmarshal: + +```go +type Postgres struct { + User string + Password string +} +type Config struct { + Postgres Postgres +} + +doc := []byte(` +[Postgres] +User = "pelletier" +Password = "mypassword"`) + +config := Config{} +toml.Unmarshal(doc, &config) +fmt.Println("user=", config.Postgres.User) +``` + +Or use a query: + +```go +// use a query to gather elements without walking the tree +q, _ := query.Compile("$..[user,password]") +results := q.Execute(config) +for ii, item := range results.Values() { + fmt.Println("Query result %d: %v", ii, item) +} +``` + +## Documentation + +The documentation and additional examples are available at +[godoc.org](http://godoc.org/github.com/pelletier/go-toml). + +## Tools + +Go-toml provides two handy command line tools: + +* `tomll`: Reads TOML files and lint them. + + ``` + go install github.com/pelletier/go-toml/cmd/tomll + tomll --help + ``` +* `tomljson`: Reads a TOML file and outputs its JSON representation. + + ``` + go install github.com/pelletier/go-toml/cmd/tomljson + tomljson --help + ``` + +## Contribute + +Feel free to report bugs and patches using GitHub's pull requests system on +[pelletier/go-toml](https://github.com/pelletier/go-toml). Any feedback would be +much appreciated! + +### Run tests + +You have to make sure two kind of tests run: + +1. The Go unit tests +2. The TOML examples base + +You can run both of them using `./test.sh`. + +### Fuzzing + +The script `./fuzz.sh` is available to +run [go-fuzz](https://github.com/dvyukov/go-fuzz) on go-toml. + +## Versioning + +Go-toml follows [Semantic Versioning](http://semver.org/). The supported version +of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of +this document. The last two major versions of Go are supported +(see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)). + +## License + +The MIT License (MIT). Read [LICENSE](LICENSE). diff --git a/vendor/github.com/pelletier/go-toml/benchmark.json b/vendor/github.com/pelletier/go-toml/benchmark.json new file mode 100644 index 000000000..86f99c6a8 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.json @@ -0,0 +1,164 @@ +{ + "array": { + "key1": [ + 1, + 2, + 3 + ], + "key2": [ + "red", + "yellow", + "green" + ], + "key3": [ + [ + 1, + 2 + ], + [ + 3, + 4, + 5 + ] + ], + "key4": [ + [ + 1, + 2 + ], + [ + "a", + "b", + "c" + ] + ], + "key5": [ + 1, + 2, + 3 + ], + "key6": [ + 1, + 2 + ] + }, + "boolean": { + "False": false, + "True": true + }, + "datetime": { + "key1": "1979-05-27T07:32:00Z", + "key2": "1979-05-27T00:32:00-07:00", + "key3": "1979-05-27T00:32:00.999999-07:00" + }, + "float": { + "both": { + "key": 6.626e-34 + }, + "exponent": { + "key1": 5e+22, + "key2": 1000000, + "key3": -0.02 + }, + "fractional": { + "key1": 1, + "key2": 3.1415, + "key3": -0.01 + }, + "underscores": { + "key1": 9224617.445991227, + "key2": 1e+100 + } + }, + "fruit": [{ + "name": "apple", + "physical": { + "color": "red", + "shape": "round" + }, + "variety": [{ + "name": "red delicious" + }, + { + "name": "granny smith" + } + ] + }, + { + "name": "banana", + "variety": [{ + "name": "plantain" + }] + } + ], + "integer": { + "key1": 99, + "key2": 42, + "key3": 0, + "key4": -17, + "underscores": { + "key1": 1000, + "key2": 5349221, + "key3": 12345 + } + }, + "products": [{ + "name": "Hammer", + "sku": 738594937 + }, + {}, + { + "color": "gray", + "name": "Nail", + "sku": 284758393 + } + ], + "string": { + "basic": { + "basic": "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF." + }, + "literal": { + "multiline": { + "lines": "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", + "regex2": "I [dw]on't need \\d{2} apples" + }, + "quoted": "Tom \"Dubs\" Preston-Werner", + "regex": "\u003c\\i\\c*\\s*\u003e", + "winpath": "C:\\Users\\nodejs\\templates", + "winpath2": "\\\\ServerX\\admin$\\system32\\" + }, + "multiline": { + "continued": { + "key1": "The quick brown fox jumps over the lazy dog.", + "key2": "The quick brown fox jumps over the lazy dog.", + "key3": "The quick brown fox jumps over the lazy dog." + }, + "key1": "One\nTwo", + "key2": "One\nTwo", + "key3": "One\nTwo" + } + }, + "table": { + "inline": { + "name": { + "first": "Tom", + "last": "Preston-Werner" + }, + "point": { + "x": 1, + "y": 2 + } + }, + "key": "value", + "subtable": { + "key": "another value" + } + }, + "x": { + "y": { + "z": { + "w": {} + } + } + } +} diff --git a/vendor/github.com/pelletier/go-toml/benchmark.sh b/vendor/github.com/pelletier/go-toml/benchmark.sh new file mode 100644 index 000000000..8b8bb528e --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +reference_ref=${1:-master} +reference_git=${2:-.} + +if ! `hash benchstat 2>/dev/null`; then + echo "Installing benchstat" + go get golang.org/x/perf/cmd/benchstat + go install golang.org/x/perf/cmd/benchstat +fi + +tempdir=`mktemp -d /tmp/go-toml-benchmark-XXXXXX` +ref_tempdir="${tempdir}/ref" +ref_benchmark="${ref_tempdir}/benchmark-`echo -n ${reference_ref}|tr -s '/' '-'`.txt" +local_benchmark="`pwd`/benchmark-local.txt" + +echo "=== ${reference_ref} (${ref_tempdir})" +git clone ${reference_git} ${ref_tempdir} >/dev/null 2>/dev/null +pushd ${ref_tempdir} >/dev/null +git checkout ${reference_ref} >/dev/null 2>/dev/null +go test -bench=. -benchmem | tee ${ref_benchmark} +popd >/dev/null + +echo "" +echo "=== local" +go test -bench=. -benchmem | tee ${local_benchmark} + +echo "" +echo "=== diff" +benchstat -delta-test=none ${ref_benchmark} ${local_benchmark} \ No newline at end of file diff --git a/vendor/github.com/pelletier/go-toml/benchmark.toml b/vendor/github.com/pelletier/go-toml/benchmark.toml new file mode 100644 index 000000000..dfd77e096 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.toml @@ -0,0 +1,244 @@ +################################################################################ +## Comment + +# Speak your mind with the hash symbol. They go from the symbol to the end of +# the line. + + +################################################################################ +## Table + +# Tables (also known as hash tables or dictionaries) are collections of +# key/value pairs. They appear in square brackets on a line by themselves. + +[table] + +key = "value" # Yeah, you can do this. + +# Nested tables are denoted by table names with dots in them. Name your tables +# whatever crap you please, just don't use #, ., [ or ]. + +[table.subtable] + +key = "another value" + +# You don't need to specify all the super-tables if you don't want to. TOML +# knows how to do it for you. + +# [x] you +# [x.y] don't +# [x.y.z] need these +[x.y.z.w] # for this to work + + +################################################################################ +## Inline Table + +# Inline tables provide a more compact syntax for expressing tables. They are +# especially useful for grouped data that can otherwise quickly become verbose. +# Inline tables are enclosed in curly braces `{` and `}`. No newlines are +# allowed between the curly braces unless they are valid within a value. + +[table.inline] + +name = { first = "Tom", last = "Preston-Werner" } +point = { x = 1, y = 2 } + + +################################################################################ +## String + +# There are four ways to express strings: basic, multi-line basic, literal, and +# multi-line literal. All strings must contain only valid UTF-8 characters. + +[string.basic] + +basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." + +[string.multiline] + +# The following strings are byte-for-byte equivalent: +key1 = "One\nTwo" +key2 = """One\nTwo""" +key3 = """ +One +Two""" + +[string.multiline.continued] + +# The following strings are byte-for-byte equivalent: +key1 = "The quick brown fox jumps over the lazy dog." + +key2 = """ +The quick brown \ + + + fox jumps over \ + the lazy dog.""" + +key3 = """\ + The quick brown \ + fox jumps over \ + the lazy dog.\ + """ + +[string.literal] + +# What you see is what you get. +winpath = 'C:\Users\nodejs\templates' +winpath2 = '\\ServerX\admin$\system32\' +quoted = 'Tom "Dubs" Preston-Werner' +regex = '<\i\c*\s*>' + + +[string.literal.multiline] + +regex2 = '''I [dw]on't need \d{2} apples''' +lines = ''' +The first newline is +trimmed in raw strings. + All other whitespace + is preserved. +''' + + +################################################################################ +## Integer + +# Integers are whole numbers. Positive numbers may be prefixed with a plus sign. +# Negative numbers are prefixed with a minus sign. + +[integer] + +key1 = +99 +key2 = 42 +key3 = 0 +key4 = -17 + +[integer.underscores] + +# For large numbers, you may use underscores to enhance readability. Each +# underscore must be surrounded by at least one digit. +key1 = 1_000 +key2 = 5_349_221 +key3 = 1_2_3_4_5 # valid but inadvisable + + +################################################################################ +## Float + +# A float consists of an integer part (which may be prefixed with a plus or +# minus sign) followed by a fractional part and/or an exponent part. + +[float.fractional] + +key1 = +1.0 +key2 = 3.1415 +key3 = -0.01 + +[float.exponent] + +key1 = 5e+22 +key2 = 1e6 +key3 = -2E-2 + +[float.both] + +key = 6.626e-34 + +[float.underscores] + +key1 = 9_224_617.445_991_228_313 +key2 = 1e1_00 + + +################################################################################ +## Boolean + +# Booleans are just the tokens you're used to. Always lowercase. + +[boolean] + +True = true +False = false + + +################################################################################ +## Datetime + +# Datetimes are RFC 3339 dates. + +[datetime] + +key1 = 1979-05-27T07:32:00Z +key2 = 1979-05-27T00:32:00-07:00 +key3 = 1979-05-27T00:32:00.999999-07:00 + + +################################################################################ +## Array + +# Arrays are square brackets with other primitives inside. Whitespace is +# ignored. Elements are separated by commas. Data types may not be mixed. + +[array] + +key1 = [ 1, 2, 3 ] +key2 = [ "red", "yellow", "green" ] +key3 = [ [ 1, 2 ], [3, 4, 5] ] +#key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok + +# Arrays can also be multiline. So in addition to ignoring whitespace, arrays +# also ignore newlines between the brackets. Terminating commas are ok before +# the closing bracket. + +key5 = [ + 1, 2, 3 +] +key6 = [ + 1, + 2, # this is ok +] + + +################################################################################ +## Array of Tables + +# These can be expressed by using a table name in double brackets. Each table +# with the same double bracketed name will be an element in the array. The +# tables are inserted in the order encountered. + +[[products]] + +name = "Hammer" +sku = 738594937 + +[[products]] + +[[products]] + +name = "Nail" +sku = 284758393 +color = "gray" + + +# You can create nested arrays of tables as well. + +[[fruit]] + name = "apple" + + [fruit.physical] + color = "red" + shape = "round" + + [[fruit.variety]] + name = "red delicious" + + [[fruit.variety]] + name = "granny smith" + +[[fruit]] + name = "banana" + + [[fruit.variety]] + name = "plantain" diff --git a/vendor/github.com/pelletier/go-toml/benchmark.yml b/vendor/github.com/pelletier/go-toml/benchmark.yml new file mode 100644 index 000000000..0bd19f08a --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.yml @@ -0,0 +1,121 @@ +--- +array: + key1: + - 1 + - 2 + - 3 + key2: + - red + - yellow + - green + key3: + - - 1 + - 2 + - - 3 + - 4 + - 5 + key4: + - - 1 + - 2 + - - a + - b + - c + key5: + - 1 + - 2 + - 3 + key6: + - 1 + - 2 +boolean: + 'False': false + 'True': true +datetime: + key1: '1979-05-27T07:32:00Z' + key2: '1979-05-27T00:32:00-07:00' + key3: '1979-05-27T00:32:00.999999-07:00' +float: + both: + key: 6.626e-34 + exponent: + key1: 5.0e+22 + key2: 1000000 + key3: -0.02 + fractional: + key1: 1 + key2: 3.1415 + key3: -0.01 + underscores: + key1: 9224617.445991227 + key2: 1.0e+100 +fruit: +- name: apple + physical: + color: red + shape: round + variety: + - name: red delicious + - name: granny smith +- name: banana + variety: + - name: plantain +integer: + key1: 99 + key2: 42 + key3: 0 + key4: -17 + underscores: + key1: 1000 + key2: 5349221 + key3: 12345 +products: +- name: Hammer + sku: 738594937 +- {} +- color: gray + name: Nail + sku: 284758393 +string: + basic: + basic: "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF." + literal: + multiline: + lines: | + The first newline is + trimmed in raw strings. + All other whitespace + is preserved. + regex2: I [dw]on't need \d{2} apples + quoted: Tom "Dubs" Preston-Werner + regex: "<\\i\\c*\\s*>" + winpath: C:\Users\nodejs\templates + winpath2: "\\\\ServerX\\admin$\\system32\\" + multiline: + continued: + key1: The quick brown fox jumps over the lazy dog. + key2: The quick brown fox jumps over the lazy dog. + key3: The quick brown fox jumps over the lazy dog. + key1: |- + One + Two + key2: |- + One + Two + key3: |- + One + Two +table: + inline: + name: + first: Tom + last: Preston-Werner + point: + x: 1 + y: 2 + key: value + subtable: + key: another value +x: + y: + z: + w: {} diff --git a/vendor/github.com/pelletier/go-toml/doc.go b/vendor/github.com/pelletier/go-toml/doc.go new file mode 100644 index 000000000..d5fd98c02 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/doc.go @@ -0,0 +1,23 @@ +// Package toml is a TOML parser and manipulation library. +// +// This version supports the specification as described in +// https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md +// +// Marshaling +// +// Go-toml can marshal and unmarshal TOML documents from and to data +// structures. +// +// TOML document as a tree +// +// Go-toml can operate on a TOML document as a tree. Use one of the Load* +// functions to parse TOML data and obtain a Tree instance, then one of its +// methods to manipulate the tree. +// +// JSONPath-like queries +// +// The package github.com/pelletier/go-toml/query implements a system +// similar to JSONPath to quickly retrieve elements of a TOML document using a +// single expression. See the package documentation for more information. +// +package toml diff --git a/vendor/github.com/pelletier/go-toml/example-crlf.toml b/vendor/github.com/pelletier/go-toml/example-crlf.toml new file mode 100644 index 000000000..12950a163 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example-crlf.toml @@ -0,0 +1,29 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it diff --git a/vendor/github.com/pelletier/go-toml/example.toml b/vendor/github.com/pelletier/go-toml/example.toml new file mode 100644 index 000000000..3d902f282 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example.toml @@ -0,0 +1,29 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it diff --git a/vendor/github.com/pelletier/go-toml/fuzz.go b/vendor/github.com/pelletier/go-toml/fuzz.go new file mode 100644 index 000000000..14570c8d3 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/fuzz.go @@ -0,0 +1,31 @@ +// +build gofuzz + +package toml + +func Fuzz(data []byte) int { + tree, err := LoadBytes(data) + if err != nil { + if tree != nil { + panic("tree must be nil if there is an error") + } + return 0 + } + + str, err := tree.ToTomlString() + if err != nil { + if str != "" { + panic(`str must be "" if there is an error`) + } + panic(err) + } + + tree, err = Load(str) + if err != nil { + if tree != nil { + panic("tree must be nil if there is an error") + } + return 0 + } + + return 1 +} diff --git a/vendor/github.com/pelletier/go-toml/fuzz.sh b/vendor/github.com/pelletier/go-toml/fuzz.sh new file mode 100644 index 000000000..3204b4c44 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/fuzz.sh @@ -0,0 +1,15 @@ +#! /bin/sh +set -eu + +go get github.com/dvyukov/go-fuzz/go-fuzz +go get github.com/dvyukov/go-fuzz/go-fuzz-build + +if [ ! -e toml-fuzz.zip ]; then + go-fuzz-build github.com/pelletier/go-toml +fi + +rm -fr fuzz +mkdir -p fuzz/corpus +cp *.toml fuzz/corpus + +go-fuzz -bin=toml-fuzz.zip -workdir=fuzz diff --git a/vendor/github.com/pelletier/go-toml/keysparsing.go b/vendor/github.com/pelletier/go-toml/keysparsing.go new file mode 100644 index 000000000..284db6467 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/keysparsing.go @@ -0,0 +1,85 @@ +// Parsing keys handling both bare and quoted keys. + +package toml + +import ( + "bytes" + "errors" + "fmt" + "unicode" +) + +// Convert the bare key group string to an array. +// The input supports double quotation to allow "." inside the key name, +// but escape sequences are not supported. Lexers must unescape them beforehand. +func parseKey(key string) ([]string, error) { + groups := []string{} + var buffer bytes.Buffer + inQuotes := false + wasInQuotes := false + ignoreSpace := true + expectDot := false + + for _, char := range key { + if ignoreSpace { + if char == ' ' { + continue + } + ignoreSpace = false + } + switch char { + case '"': + if inQuotes { + groups = append(groups, buffer.String()) + buffer.Reset() + wasInQuotes = true + } + inQuotes = !inQuotes + expectDot = false + case '.': + if inQuotes { + buffer.WriteRune(char) + } else { + if !wasInQuotes { + if buffer.Len() == 0 { + return nil, errors.New("empty table key") + } + groups = append(groups, buffer.String()) + buffer.Reset() + } + ignoreSpace = true + expectDot = false + wasInQuotes = false + } + case ' ': + if inQuotes { + buffer.WriteRune(char) + } else { + expectDot = true + } + default: + if !inQuotes && !isValidBareChar(char) { + return nil, fmt.Errorf("invalid bare character: %c", char) + } + if !inQuotes && expectDot { + return nil, errors.New("what?") + } + buffer.WriteRune(char) + expectDot = false + } + } + if inQuotes { + return nil, errors.New("mismatched quotes") + } + if buffer.Len() > 0 { + groups = append(groups, buffer.String()) + } + if len(groups) == 0 { + return nil, errors.New("empty key") + } + return groups, nil +} + +func isValidBareChar(r rune) bool { + return isAlphanumeric(r) || r == '-' || unicode.IsNumber(r) +} diff --git a/vendor/github.com/pelletier/go-toml/lexer.go b/vendor/github.com/pelletier/go-toml/lexer.go new file mode 100644 index 000000000..d11de4285 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/lexer.go @@ -0,0 +1,750 @@ +// TOML lexer. +// +// Written using the principles developed by Rob Pike in +// http://www.youtube.com/watch?v=HxaD_trXwRE + +package toml + +import ( + "bytes" + "errors" + "fmt" + "regexp" + "strconv" + "strings" +) + +var dateRegexp *regexp.Regexp + +// Define state functions +type tomlLexStateFn func() tomlLexStateFn + +// Define lexer +type tomlLexer struct { + inputIdx int + input []rune // Textual source + currentTokenStart int + currentTokenStop int + tokens []token + depth int + line int + col int + endbufferLine int + endbufferCol int +} + +// Basic read operations on input + +func (l *tomlLexer) read() rune { + r := l.peek() + if r == '\n' { + l.endbufferLine++ + l.endbufferCol = 1 + } else { + l.endbufferCol++ + } + l.inputIdx++ + return r +} + +func (l *tomlLexer) next() rune { + r := l.read() + + if r != eof { + l.currentTokenStop++ + } + return r +} + +func (l *tomlLexer) ignore() { + l.currentTokenStart = l.currentTokenStop + l.line = l.endbufferLine + l.col = l.endbufferCol +} + +func (l *tomlLexer) skip() { + l.next() + l.ignore() +} + +func (l *tomlLexer) fastForward(n int) { + for i := 0; i < n; i++ { + l.next() + } +} + +func (l *tomlLexer) emitWithValue(t tokenType, value string) { + l.tokens = append(l.tokens, token{ + Position: Position{l.line, l.col}, + typ: t, + val: value, + }) + l.ignore() +} + +func (l *tomlLexer) emit(t tokenType) { + l.emitWithValue(t, string(l.input[l.currentTokenStart:l.currentTokenStop])) +} + +func (l *tomlLexer) peek() rune { + if l.inputIdx >= len(l.input) { + return eof + } + return l.input[l.inputIdx] +} + +func (l *tomlLexer) peekString(size int) string { + maxIdx := len(l.input) + upperIdx := l.inputIdx + size // FIXME: potential overflow + if upperIdx > maxIdx { + upperIdx = maxIdx + } + return string(l.input[l.inputIdx:upperIdx]) +} + +func (l *tomlLexer) follow(next string) bool { + return next == l.peekString(len(next)) +} + +// Error management + +func (l *tomlLexer) errorf(format string, args ...interface{}) tomlLexStateFn { + l.tokens = append(l.tokens, token{ + Position: Position{l.line, l.col}, + typ: tokenError, + val: fmt.Sprintf(format, args...), + }) + return nil +} + +// State functions + +func (l *tomlLexer) lexVoid() tomlLexStateFn { + for { + next := l.peek() + switch next { + case '[': + return l.lexTableKey + case '#': + return l.lexComment(l.lexVoid) + case '=': + return l.lexEqual + case '\r': + fallthrough + case '\n': + l.skip() + continue + } + + if isSpace(next) { + l.skip() + } + + if l.depth > 0 { + return l.lexRvalue + } + + if isKeyStartChar(next) { + return l.lexKey + } + + if next == eof { + l.next() + break + } + } + + l.emit(tokenEOF) + return nil +} + +func (l *tomlLexer) lexRvalue() tomlLexStateFn { + for { + next := l.peek() + switch next { + case '.': + return l.errorf("cannot start float with a dot") + case '=': + return l.lexEqual + case '[': + l.depth++ + return l.lexLeftBracket + case ']': + l.depth-- + return l.lexRightBracket + case '{': + return l.lexLeftCurlyBrace + case '}': + return l.lexRightCurlyBrace + case '#': + return l.lexComment(l.lexRvalue) + case '"': + return l.lexString + case '\'': + return l.lexLiteralString + case ',': + return l.lexComma + case '\r': + fallthrough + case '\n': + l.skip() + if l.depth == 0 { + return l.lexVoid + } + return l.lexRvalue + case '_': + return l.errorf("cannot start number with underscore") + } + + if l.follow("true") { + return l.lexTrue + } + + if l.follow("false") { + return l.lexFalse + } + + if l.follow("inf") { + return l.lexInf + } + + if l.follow("nan") { + return l.lexNan + } + + if isSpace(next) { + l.skip() + continue + } + + if next == eof { + l.next() + break + } + + possibleDate := l.peekString(35) + dateMatch := dateRegexp.FindString(possibleDate) + if dateMatch != "" { + l.fastForward(len(dateMatch)) + return l.lexDate + } + + if next == '+' || next == '-' || isDigit(next) { + return l.lexNumber + } + + if isAlphanumeric(next) { + return l.lexKey + } + + return l.errorf("no value can start with %c", next) + } + + l.emit(tokenEOF) + return nil +} + +func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn { + l.next() + l.emit(tokenLeftCurlyBrace) + return l.lexRvalue +} + +func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn { + l.next() + l.emit(tokenRightCurlyBrace) + return l.lexRvalue +} + +func (l *tomlLexer) lexDate() tomlLexStateFn { + l.emit(tokenDate) + return l.lexRvalue +} + +func (l *tomlLexer) lexTrue() tomlLexStateFn { + l.fastForward(4) + l.emit(tokenTrue) + return l.lexRvalue +} + +func (l *tomlLexer) lexFalse() tomlLexStateFn { + l.fastForward(5) + l.emit(tokenFalse) + return l.lexRvalue +} + +func (l *tomlLexer) lexInf() tomlLexStateFn { + l.fastForward(3) + l.emit(tokenInf) + return l.lexRvalue +} + +func (l *tomlLexer) lexNan() tomlLexStateFn { + l.fastForward(3) + l.emit(tokenNan) + return l.lexRvalue +} + +func (l *tomlLexer) lexEqual() tomlLexStateFn { + l.next() + l.emit(tokenEqual) + return l.lexRvalue +} + +func (l *tomlLexer) lexComma() tomlLexStateFn { + l.next() + l.emit(tokenComma) + return l.lexRvalue +} + +// Parse the key and emits its value without escape sequences. +// bare keys, basic string keys and literal string keys are supported. +func (l *tomlLexer) lexKey() tomlLexStateFn { + growingString := "" + + for r := l.peek(); isKeyChar(r) || r == '\n' || r == '\r'; r = l.peek() { + if r == '"' { + l.next() + str, err := l.lexStringAsString(`"`, false, true) + if err != nil { + return l.errorf(err.Error()) + } + growingString += str + l.next() + continue + } else if r == '\'' { + l.next() + str, err := l.lexLiteralStringAsString(`'`, false) + if err != nil { + return l.errorf(err.Error()) + } + growingString += str + l.next() + continue + } else if r == '\n' { + return l.errorf("keys cannot contain new lines") + } else if isSpace(r) { + break + } else if !isValidBareChar(r) { + return l.errorf("keys cannot contain %c character", r) + } + growingString += string(r) + l.next() + } + l.emitWithValue(tokenKey, growingString) + return l.lexVoid +} + +func (l *tomlLexer) lexComment(previousState tomlLexStateFn) tomlLexStateFn { + return func() tomlLexStateFn { + for next := l.peek(); next != '\n' && next != eof; next = l.peek() { + if next == '\r' && l.follow("\r\n") { + break + } + l.next() + } + l.ignore() + return previousState + } +} + +func (l *tomlLexer) lexLeftBracket() tomlLexStateFn { + l.next() + l.emit(tokenLeftBracket) + return l.lexRvalue +} + +func (l *tomlLexer) lexLiteralStringAsString(terminator string, discardLeadingNewLine bool) (string, error) { + growingString := "" + + if discardLeadingNewLine { + if l.follow("\r\n") { + l.skip() + l.skip() + } else if l.peek() == '\n' { + l.skip() + } + } + + // find end of string + for { + if l.follow(terminator) { + return growingString, nil + } + + next := l.peek() + if next == eof { + break + } + growingString += string(l.next()) + } + + return "", errors.New("unclosed string") +} + +func (l *tomlLexer) lexLiteralString() tomlLexStateFn { + l.skip() + + // handle special case for triple-quote + terminator := "'" + discardLeadingNewLine := false + if l.follow("''") { + l.skip() + l.skip() + terminator = "'''" + discardLeadingNewLine = true + } + + str, err := l.lexLiteralStringAsString(terminator, discardLeadingNewLine) + if err != nil { + return l.errorf(err.Error()) + } + + l.emitWithValue(tokenString, str) + l.fastForward(len(terminator)) + l.ignore() + return l.lexRvalue +} + +// Lex a string and return the results as a string. +// Terminator is the substring indicating the end of the token. +// The resulting string does not include the terminator. +func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine, acceptNewLines bool) (string, error) { + growingString := "" + + if discardLeadingNewLine { + if l.follow("\r\n") { + l.skip() + l.skip() + } else if l.peek() == '\n' { + l.skip() + } + } + + for { + if l.follow(terminator) { + return growingString, nil + } + + if l.follow("\\") { + l.next() + switch l.peek() { + case '\r': + fallthrough + case '\n': + fallthrough + case '\t': + fallthrough + case ' ': + // skip all whitespace chars following backslash + for strings.ContainsRune("\r\n\t ", l.peek()) { + l.next() + } + case '"': + growingString += "\"" + l.next() + case 'n': + growingString += "\n" + l.next() + case 'b': + growingString += "\b" + l.next() + case 'f': + growingString += "\f" + l.next() + case '/': + growingString += "/" + l.next() + case 't': + growingString += "\t" + l.next() + case 'r': + growingString += "\r" + l.next() + case '\\': + growingString += "\\" + l.next() + case 'u': + l.next() + code := "" + for i := 0; i < 4; i++ { + c := l.peek() + if !isHexDigit(c) { + return "", errors.New("unfinished unicode escape") + } + l.next() + code = code + string(c) + } + intcode, err := strconv.ParseInt(code, 16, 32) + if err != nil { + return "", errors.New("invalid unicode escape: \\u" + code) + } + growingString += string(rune(intcode)) + case 'U': + l.next() + code := "" + for i := 0; i < 8; i++ { + c := l.peek() + if !isHexDigit(c) { + return "", errors.New("unfinished unicode escape") + } + l.next() + code = code + string(c) + } + intcode, err := strconv.ParseInt(code, 16, 64) + if err != nil { + return "", errors.New("invalid unicode escape: \\U" + code) + } + growingString += string(rune(intcode)) + default: + return "", errors.New("invalid escape sequence: \\" + string(l.peek())) + } + } else { + r := l.peek() + + if 0x00 <= r && r <= 0x1F && !(acceptNewLines && (r == '\n' || r == '\r')) { + return "", fmt.Errorf("unescaped control character %U", r) + } + l.next() + growingString += string(r) + } + + if l.peek() == eof { + break + } + } + + return "", errors.New("unclosed string") +} + +func (l *tomlLexer) lexString() tomlLexStateFn { + l.skip() + + // handle special case for triple-quote + terminator := `"` + discardLeadingNewLine := false + acceptNewLines := false + if l.follow(`""`) { + l.skip() + l.skip() + terminator = `"""` + discardLeadingNewLine = true + acceptNewLines = true + } + + str, err := l.lexStringAsString(terminator, discardLeadingNewLine, acceptNewLines) + + if err != nil { + return l.errorf(err.Error()) + } + + l.emitWithValue(tokenString, str) + l.fastForward(len(terminator)) + l.ignore() + return l.lexRvalue +} + +func (l *tomlLexer) lexTableKey() tomlLexStateFn { + l.next() + + if l.peek() == '[' { + // token '[[' signifies an array of tables + l.next() + l.emit(tokenDoubleLeftBracket) + return l.lexInsideTableArrayKey + } + // vanilla table key + l.emit(tokenLeftBracket) + return l.lexInsideTableKey +} + +// Parse the key till "]]", but only bare keys are supported +func (l *tomlLexer) lexInsideTableArrayKey() tomlLexStateFn { + for r := l.peek(); r != eof; r = l.peek() { + switch r { + case ']': + if l.currentTokenStop > l.currentTokenStart { + l.emit(tokenKeyGroupArray) + } + l.next() + if l.peek() != ']' { + break + } + l.next() + l.emit(tokenDoubleRightBracket) + return l.lexVoid + case '[': + return l.errorf("table array key cannot contain ']'") + default: + l.next() + } + } + return l.errorf("unclosed table array key") +} + +// Parse the key till "]" but only bare keys are supported +func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn { + for r := l.peek(); r != eof; r = l.peek() { + switch r { + case ']': + if l.currentTokenStop > l.currentTokenStart { + l.emit(tokenKeyGroup) + } + l.next() + l.emit(tokenRightBracket) + return l.lexVoid + case '[': + return l.errorf("table key cannot contain ']'") + default: + l.next() + } + } + return l.errorf("unclosed table key") +} + +func (l *tomlLexer) lexRightBracket() tomlLexStateFn { + l.next() + l.emit(tokenRightBracket) + return l.lexRvalue +} + +type validRuneFn func(r rune) bool + +func isValidHexRune(r rune) bool { + return r >= 'a' && r <= 'f' || + r >= 'A' && r <= 'F' || + r >= '0' && r <= '9' || + r == '_' +} + +func isValidOctalRune(r rune) bool { + return r >= '0' && r <= '7' || r == '_' +} + +func isValidBinaryRune(r rune) bool { + return r == '0' || r == '1' || r == '_' +} + +func (l *tomlLexer) lexNumber() tomlLexStateFn { + r := l.peek() + + if r == '0' { + follow := l.peekString(2) + if len(follow) == 2 { + var isValidRune validRuneFn + switch follow[1] { + case 'x': + isValidRune = isValidHexRune + case 'o': + isValidRune = isValidOctalRune + case 'b': + isValidRune = isValidBinaryRune + default: + if follow[1] >= 'a' && follow[1] <= 'z' || follow[1] >= 'A' && follow[1] <= 'Z' { + return l.errorf("unknown number base: %s. possible options are x (hex) o (octal) b (binary)", string(follow[1])) + } + } + + if isValidRune != nil { + l.next() + l.next() + digitSeen := false + for { + next := l.peek() + if !isValidRune(next) { + break + } + digitSeen = true + l.next() + } + + if !digitSeen { + return l.errorf("number needs at least one digit") + } + + l.emit(tokenInteger) + + return l.lexRvalue + } + } + } + + if r == '+' || r == '-' { + l.next() + if l.follow("inf") { + return l.lexInf + } + if l.follow("nan") { + return l.lexNan + } + } + + pointSeen := false + expSeen := false + digitSeen := false + for { + next := l.peek() + if next == '.' { + if pointSeen { + return l.errorf("cannot have two dots in one float") + } + l.next() + if !isDigit(l.peek()) { + return l.errorf("float cannot end with a dot") + } + pointSeen = true + } else if next == 'e' || next == 'E' { + expSeen = true + l.next() + r := l.peek() + if r == '+' || r == '-' { + l.next() + } + } else if isDigit(next) { + digitSeen = true + l.next() + } else if next == '_' { + l.next() + } else { + break + } + if pointSeen && !digitSeen { + return l.errorf("cannot start float with a dot") + } + } + + if !digitSeen { + return l.errorf("no digit in that number") + } + if pointSeen || expSeen { + l.emit(tokenFloat) + } else { + l.emit(tokenInteger) + } + return l.lexRvalue +} + +func (l *tomlLexer) run() { + for state := l.lexVoid; state != nil; { + state = state() + } +} + +func init() { + dateRegexp = regexp.MustCompile(`^\d{1,4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})`) +} + +// Entry point +func lexToml(inputBytes []byte) []token { + runes := bytes.Runes(inputBytes) + l := &tomlLexer{ + input: runes, + tokens: make([]token, 0, 256), + line: 1, + col: 1, + endbufferLine: 1, + endbufferCol: 1, + } + l.run() + return l.tokens +} diff --git a/vendor/github.com/pelletier/go-toml/marshal.go b/vendor/github.com/pelletier/go-toml/marshal.go new file mode 100644 index 000000000..671da5564 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal.go @@ -0,0 +1,609 @@ +package toml + +import ( + "bytes" + "errors" + "fmt" + "io" + "reflect" + "strconv" + "strings" + "time" +) + +const tagKeyMultiline = "multiline" + +type tomlOpts struct { + name string + comment string + commented bool + multiline bool + include bool + omitempty bool +} + +type encOpts struct { + quoteMapKeys bool + arraysOneElementPerLine bool +} + +var encOptsDefaults = encOpts{ + quoteMapKeys: false, +} + +var timeType = reflect.TypeOf(time.Time{}) +var marshalerType = reflect.TypeOf(new(Marshaler)).Elem() + +// Check if the given marshall type maps to a Tree primitive +func isPrimitive(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isPrimitive(mtype.Elem()) + case reflect.Bool: + return true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + case reflect.Struct: + return mtype == timeType || isCustomMarshaler(mtype) + default: + return false + } +} + +// Check if the given marshall type maps to a Tree slice +func isTreeSlice(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Slice: + return !isOtherSlice(mtype) + default: + return false + } +} + +// Check if the given marshall type maps to a non-Tree slice +func isOtherSlice(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isOtherSlice(mtype.Elem()) + case reflect.Slice: + return isPrimitive(mtype.Elem()) || isOtherSlice(mtype.Elem()) + default: + return false + } +} + +// Check if the given marshall type maps to a Tree +func isTree(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Map: + return true + case reflect.Struct: + return !isPrimitive(mtype) + default: + return false + } +} + +func isCustomMarshaler(mtype reflect.Type) bool { + return mtype.Implements(marshalerType) +} + +func callCustomMarshaler(mval reflect.Value) ([]byte, error) { + return mval.Interface().(Marshaler).MarshalTOML() +} + +// Marshaler is the interface implemented by types that +// can marshal themselves into valid TOML. +type Marshaler interface { + MarshalTOML() ([]byte, error) +} + +/* +Marshal returns the TOML encoding of v. Behavior is similar to the Go json +encoder, except that there is no concept of a Marshaler interface or MarshalTOML +function for sub-structs, and currently only definite types can be marshaled +(i.e. no `interface{}`). + +The following struct annotations are supported: + + toml:"Field" Overrides the field's name to output. + omitempty When set, empty values and groups are not emitted. + comment:"comment" Emits a # comment on the same line. This supports new lines. + commented:"true" Emits the value as commented. + +Note that pointers are automatically assigned the "omitempty" option, as TOML +explicitly does not handle null values (saying instead the label should be +dropped). + +Tree structural types and corresponding marshal types: + + *Tree (*)struct, (*)map[string]interface{} + []*Tree (*)[](*)struct, (*)[](*)map[string]interface{} + []interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{}) + interface{} (*)primitive + +Tree primitive types and corresponding marshal types: + + uint64 uint, uint8-uint64, pointers to same + int64 int, int8-uint64, pointers to same + float64 float32, float64, pointers to same + string string, pointers to same + bool bool, pointers to same + time.Time time.Time{}, pointers to same +*/ +func Marshal(v interface{}) ([]byte, error) { + return NewEncoder(nil).marshal(v) +} + +// Encoder writes TOML values to an output stream. +type Encoder struct { + w io.Writer + encOpts +} + +// NewEncoder returns a new encoder that writes to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + w: w, + encOpts: encOptsDefaults, + } +} + +// Encode writes the TOML encoding of v to the stream. +// +// See the documentation for Marshal for details. +func (e *Encoder) Encode(v interface{}) error { + b, err := e.marshal(v) + if err != nil { + return err + } + if _, err := e.w.Write(b); err != nil { + return err + } + return nil +} + +// QuoteMapKeys sets up the encoder to encode +// maps with string type keys with quoted TOML keys. +// +// This relieves the character limitations on map keys. +func (e *Encoder) QuoteMapKeys(v bool) *Encoder { + e.quoteMapKeys = v + return e +} + +// ArraysWithOneElementPerLine sets up the encoder to encode arrays +// with more than one element on multiple lines instead of one. +// +// For example: +// +// A = [1,2,3] +// +// Becomes +// +// A = [ +// 1, +// 2, +// 3, +// ] +func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder { + e.arraysOneElementPerLine = v + return e +} + +func (e *Encoder) marshal(v interface{}) ([]byte, error) { + mtype := reflect.TypeOf(v) + if mtype.Kind() != reflect.Struct { + return []byte{}, errors.New("Only a struct can be marshaled to TOML") + } + sval := reflect.ValueOf(v) + if isCustomMarshaler(mtype) { + return callCustomMarshaler(sval) + } + t, err := e.valueToTree(mtype, sval) + if err != nil { + return []byte{}, err + } + + var buf bytes.Buffer + _, err = t.writeTo(&buf, "", "", 0, e.arraysOneElementPerLine) + + return buf.Bytes(), err +} + +// Convert given marshal struct or map value to toml tree +func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) { + if mtype.Kind() == reflect.Ptr { + return e.valueToTree(mtype.Elem(), mval.Elem()) + } + tval := newTree() + switch mtype.Kind() { + case reflect.Struct: + for i := 0; i < mtype.NumField(); i++ { + mtypef, mvalf := mtype.Field(i), mval.Field(i) + opts := tomlOptions(mtypef) + if opts.include && (!opts.omitempty || !isZero(mvalf)) { + val, err := e.valueToToml(mtypef.Type, mvalf) + if err != nil { + return nil, err + } + + tval.SetWithOptions(opts.name, SetOptions{ + Comment: opts.comment, + Commented: opts.commented, + Multiline: opts.multiline, + }, val) + } + } + case reflect.Map: + for _, key := range mval.MapKeys() { + mvalf := mval.MapIndex(key) + val, err := e.valueToToml(mtype.Elem(), mvalf) + if err != nil { + return nil, err + } + if e.quoteMapKeys { + keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine) + if err != nil { + return nil, err + } + tval.SetPath([]string{keyStr}, val) + } else { + tval.Set(key.String(), val) + } + } + } + return tval, nil +} + +// Convert given marshal slice to slice of Toml trees +func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) { + tval := make([]*Tree, mval.Len(), mval.Len()) + for i := 0; i < mval.Len(); i++ { + val, err := e.valueToTree(mtype.Elem(), mval.Index(i)) + if err != nil { + return nil, err + } + tval[i] = val + } + return tval, nil +} + +// Convert given marshal slice to slice of toml values +func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) { + tval := make([]interface{}, mval.Len(), mval.Len()) + for i := 0; i < mval.Len(); i++ { + val, err := e.valueToToml(mtype.Elem(), mval.Index(i)) + if err != nil { + return nil, err + } + tval[i] = val + } + return tval, nil +} + +// Convert given marshal value to toml value +func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) { + if mtype.Kind() == reflect.Ptr { + return e.valueToToml(mtype.Elem(), mval.Elem()) + } + switch { + case isCustomMarshaler(mtype): + return callCustomMarshaler(mval) + case isTree(mtype): + return e.valueToTree(mtype, mval) + case isTreeSlice(mtype): + return e.valueToTreeSlice(mtype, mval) + case isOtherSlice(mtype): + return e.valueToOtherSlice(mtype, mval) + default: + switch mtype.Kind() { + case reflect.Bool: + return mval.Bool(), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return mval.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return mval.Uint(), nil + case reflect.Float32, reflect.Float64: + return mval.Float(), nil + case reflect.String: + return mval.String(), nil + case reflect.Struct: + return mval.Interface().(time.Time), nil + default: + return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind()) + } + } +} + +// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v. +// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for +// sub-structs, and only definite types can be unmarshaled. +func (t *Tree) Unmarshal(v interface{}) error { + d := Decoder{tval: t} + return d.unmarshal(v) +} + +// Marshal returns the TOML encoding of Tree. +// See Marshal() documentation for types mapping table. +func (t *Tree) Marshal() ([]byte, error) { + var buf bytes.Buffer + err := NewEncoder(&buf).Encode(t) + return buf.Bytes(), err +} + +// Unmarshal parses the TOML-encoded data and stores the result in the value +// pointed to by v. Behavior is similar to the Go json encoder, except that there +// is no concept of an Unmarshaler interface or UnmarshalTOML function for +// sub-structs, and currently only definite types can be unmarshaled to (i.e. no +// `interface{}`). +// +// The following struct annotations are supported: +// +// toml:"Field" Overrides the field's name to map to. +// +// See Marshal() documentation for types mapping table. +func Unmarshal(data []byte, v interface{}) error { + t, err := LoadReader(bytes.NewReader(data)) + if err != nil { + return err + } + return t.Unmarshal(v) +} + +// Decoder reads and decodes TOML values from an input stream. +type Decoder struct { + r io.Reader + tval *Tree + encOpts +} + +// NewDecoder returns a new decoder that reads from r. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{ + r: r, + encOpts: encOptsDefaults, + } +} + +// Decode reads a TOML-encoded value from it's input +// and unmarshals it in the value pointed at by v. +// +// See the documentation for Marshal for details. +func (d *Decoder) Decode(v interface{}) error { + var err error + d.tval, err = LoadReader(d.r) + if err != nil { + return err + } + return d.unmarshal(v) +} + +func (d *Decoder) unmarshal(v interface{}) error { + mtype := reflect.TypeOf(v) + if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct { + return errors.New("Only a pointer to struct can be unmarshaled from TOML") + } + + sval, err := d.valueFromTree(mtype.Elem(), d.tval) + if err != nil { + return err + } + reflect.ValueOf(v).Elem().Set(sval) + return nil +} + +// Convert toml tree to marshal struct or map, using marshal type +func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, error) { + if mtype.Kind() == reflect.Ptr { + return d.unwrapPointer(mtype, tval) + } + var mval reflect.Value + switch mtype.Kind() { + case reflect.Struct: + mval = reflect.New(mtype).Elem() + for i := 0; i < mtype.NumField(); i++ { + mtypef := mtype.Field(i) + opts := tomlOptions(mtypef) + if opts.include { + baseKey := opts.name + keysToTry := []string{baseKey, strings.ToLower(baseKey), strings.ToTitle(baseKey)} + for _, key := range keysToTry { + exists := tval.Has(key) + if !exists { + continue + } + val := tval.Get(key) + mvalf, err := d.valueFromToml(mtypef.Type, val) + if err != nil { + return mval, formatError(err, tval.GetPosition(key)) + } + mval.Field(i).Set(mvalf) + break + } + } + } + case reflect.Map: + mval = reflect.MakeMap(mtype) + for _, key := range tval.Keys() { + // TODO: path splits key + val := tval.GetPath([]string{key}) + mvalf, err := d.valueFromToml(mtype.Elem(), val) + if err != nil { + return mval, formatError(err, tval.GetPosition(key)) + } + mval.SetMapIndex(reflect.ValueOf(key), mvalf) + } + } + return mval, nil +} + +// Convert toml value to marshal struct/map slice, using marshal type +func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) { + mval := reflect.MakeSlice(mtype, len(tval), len(tval)) + for i := 0; i < len(tval); i++ { + val, err := d.valueFromTree(mtype.Elem(), tval[i]) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + } + return mval, nil +} + +// Convert toml value to marshal primitive slice, using marshal type +func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) { + mval := reflect.MakeSlice(mtype, len(tval), len(tval)) + for i := 0; i < len(tval); i++ { + val, err := d.valueFromToml(mtype.Elem(), tval[i]) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + } + return mval, nil +} + +// Convert toml value to marshal value, using marshal type +func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error) { + if mtype.Kind() == reflect.Ptr { + return d.unwrapPointer(mtype, tval) + } + + switch tval.(type) { + case *Tree: + if isTree(mtype) { + return d.valueFromTree(mtype, tval.(*Tree)) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval) + case []*Tree: + if isTreeSlice(mtype) { + return d.valueFromTreeSlice(mtype, tval.([]*Tree)) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval) + case []interface{}: + if isOtherSlice(mtype) { + return d.valueFromOtherSlice(mtype, tval.([]interface{})) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval) + default: + switch mtype.Kind() { + case reflect.Bool, reflect.Struct: + val := reflect.ValueOf(tval) + // if this passes for when mtype is reflect.Struct, tval is a time.Time + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.String: + val := reflect.ValueOf(tval) + // stupidly, int64 is convertible to string. So special case this. + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Int()) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if val.Int() < 0 { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowUint(uint64(val.Int())) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Float32, reflect.Float64: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Float()) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + default: + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) + } + } +} + +func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.Value, error) { + val, err := d.valueFromToml(mtype.Elem(), tval) + if err != nil { + return reflect.ValueOf(nil), err + } + mval := reflect.New(mtype.Elem()) + mval.Elem().Set(val) + return mval, nil +} + +func tomlOptions(vf reflect.StructField) tomlOpts { + tag := vf.Tag.Get("toml") + parse := strings.Split(tag, ",") + var comment string + if c := vf.Tag.Get("comment"); c != "" { + comment = c + } + commented, _ := strconv.ParseBool(vf.Tag.Get("commented")) + multiline, _ := strconv.ParseBool(vf.Tag.Get(tagKeyMultiline)) + result := tomlOpts{name: vf.Name, comment: comment, commented: commented, multiline: multiline, include: true, omitempty: false} + if parse[0] != "" { + if parse[0] == "-" && len(parse) == 1 { + result.include = false + } else { + result.name = strings.Trim(parse[0], " ") + } + } + if vf.PkgPath != "" { + result.include = false + } + if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" { + result.omitempty = true + } + if vf.Type.Kind() == reflect.Ptr { + result.omitempty = true + } + return result +} + +func isZero(val reflect.Value) bool { + switch val.Type().Kind() { + case reflect.Map: + fallthrough + case reflect.Array: + fallthrough + case reflect.Slice: + return val.Len() == 0 + default: + return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface()) + } +} + +func formatError(err error, pos Position) error { + if err.Error()[0] == '(' { // Error already contains position information + return err + } + return fmt.Errorf("%s: %s", pos, err) +} diff --git a/vendor/github.com/pelletier/go-toml/marshal_test.toml b/vendor/github.com/pelletier/go-toml/marshal_test.toml new file mode 100644 index 000000000..1c5f98e7a --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal_test.toml @@ -0,0 +1,38 @@ +title = "TOML Marshal Testing" + +[basic] + bool = true + date = 1979-05-27T07:32:00Z + float = 123.4 + int = 5000 + string = "Bite me" + uint = 5001 + +[basic_lists] + bools = [true,false,true] + dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z] + floats = [12.3,45.6,78.9] + ints = [8001,8001,8002] + strings = ["One","Two","Three"] + uints = [5002,5003] + +[basic_map] + one = "one" + two = "two" + +[subdoc] + + [subdoc.first] + name = "First" + + [subdoc.second] + name = "Second" + +[[subdoclist]] + name = "List.First" + +[[subdoclist]] + name = "List.Second" + +[[subdocptrs]] + name = "Second" diff --git a/vendor/github.com/pelletier/go-toml/parser.go b/vendor/github.com/pelletier/go-toml/parser.go new file mode 100644 index 000000000..2d27599a9 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/parser.go @@ -0,0 +1,430 @@ +// TOML Parser. + +package toml + +import ( + "errors" + "fmt" + "math" + "reflect" + "regexp" + "strconv" + "strings" + "time" +) + +type tomlParser struct { + flowIdx int + flow []token + tree *Tree + currentTable []string + seenTableKeys []string +} + +type tomlParserStateFn func() tomlParserStateFn + +// Formats and panics an error message based on a token +func (p *tomlParser) raiseError(tok *token, msg string, args ...interface{}) { + panic(tok.Position.String() + ": " + fmt.Sprintf(msg, args...)) +} + +func (p *tomlParser) run() { + for state := p.parseStart; state != nil; { + state = state() + } +} + +func (p *tomlParser) peek() *token { + if p.flowIdx >= len(p.flow) { + return nil + } + return &p.flow[p.flowIdx] +} + +func (p *tomlParser) assume(typ tokenType) { + tok := p.getToken() + if tok == nil { + p.raiseError(tok, "was expecting token %s, but token stream is empty", tok) + } + if tok.typ != typ { + p.raiseError(tok, "was expecting token %s, but got %s instead", typ, tok) + } +} + +func (p *tomlParser) getToken() *token { + tok := p.peek() + if tok == nil { + return nil + } + p.flowIdx++ + return tok +} + +func (p *tomlParser) parseStart() tomlParserStateFn { + tok := p.peek() + + // end of stream, parsing is finished + if tok == nil { + return nil + } + + switch tok.typ { + case tokenDoubleLeftBracket: + return p.parseGroupArray + case tokenLeftBracket: + return p.parseGroup + case tokenKey: + return p.parseAssign + case tokenEOF: + return nil + default: + p.raiseError(tok, "unexpected token") + } + return nil +} + +func (p *tomlParser) parseGroupArray() tomlParserStateFn { + startToken := p.getToken() // discard the [[ + key := p.getToken() + if key.typ != tokenKeyGroupArray { + p.raiseError(key, "unexpected token %s, was expecting a table array key", key) + } + + // get or create table array element at the indicated part in the path + keys, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid table array key: %s", err) + } + p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries + destTree := p.tree.GetPath(keys) + var array []*Tree + if destTree == nil { + array = make([]*Tree, 0) + } else if target, ok := destTree.([]*Tree); ok && target != nil { + array = destTree.([]*Tree) + } else { + p.raiseError(key, "key %s is already assigned and not of type table array", key) + } + p.currentTable = keys + + // add a new tree to the end of the table array + newTree := newTree() + newTree.position = startToken.Position + array = append(array, newTree) + p.tree.SetPath(p.currentTable, array) + + // remove all keys that were children of this table array + prefix := key.val + "." + found := false + for ii := 0; ii < len(p.seenTableKeys); { + tableKey := p.seenTableKeys[ii] + if strings.HasPrefix(tableKey, prefix) { + p.seenTableKeys = append(p.seenTableKeys[:ii], p.seenTableKeys[ii+1:]...) + } else { + found = (tableKey == key.val) + ii++ + } + } + + // keep this key name from use by other kinds of assignments + if !found { + p.seenTableKeys = append(p.seenTableKeys, key.val) + } + + // move to next parser state + p.assume(tokenDoubleRightBracket) + return p.parseStart +} + +func (p *tomlParser) parseGroup() tomlParserStateFn { + startToken := p.getToken() // discard the [ + key := p.getToken() + if key.typ != tokenKeyGroup { + p.raiseError(key, "unexpected token %s, was expecting a table key", key) + } + for _, item := range p.seenTableKeys { + if item == key.val { + p.raiseError(key, "duplicated tables") + } + } + + p.seenTableKeys = append(p.seenTableKeys, key.val) + keys, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid table array key: %s", err) + } + if err := p.tree.createSubTree(keys, startToken.Position); err != nil { + p.raiseError(key, "%s", err) + } + p.assume(tokenRightBracket) + p.currentTable = keys + return p.parseStart +} + +func (p *tomlParser) parseAssign() tomlParserStateFn { + key := p.getToken() + p.assume(tokenEqual) + + value := p.parseRvalue() + var tableKey []string + if len(p.currentTable) > 0 { + tableKey = p.currentTable + } else { + tableKey = []string{} + } + + // find the table to assign, looking out for arrays of tables + var targetNode *Tree + switch node := p.tree.GetPath(tableKey).(type) { + case []*Tree: + targetNode = node[len(node)-1] + case *Tree: + targetNode = node + default: + p.raiseError(key, "Unknown table type for path: %s", + strings.Join(tableKey, ".")) + } + + // assign value to the found table + keyVals := []string{key.val} + if len(keyVals) != 1 { + p.raiseError(key, "Invalid key") + } + keyVal := keyVals[0] + localKey := []string{keyVal} + finalKey := append(tableKey, keyVal) + if targetNode.GetPath(localKey) != nil { + p.raiseError(key, "The following key was defined twice: %s", + strings.Join(finalKey, ".")) + } + var toInsert interface{} + + switch value.(type) { + case *Tree, []*Tree: + toInsert = value + default: + toInsert = &tomlValue{value: value, position: key.Position} + } + targetNode.values[keyVal] = toInsert + return p.parseStart +} + +var numberUnderscoreInvalidRegexp *regexp.Regexp +var hexNumberUnderscoreInvalidRegexp *regexp.Regexp + +func numberContainsInvalidUnderscore(value string) error { + if numberUnderscoreInvalidRegexp.MatchString(value) { + return errors.New("invalid use of _ in number") + } + return nil +} + +func hexNumberContainsInvalidUnderscore(value string) error { + if hexNumberUnderscoreInvalidRegexp.MatchString(value) { + return errors.New("invalid use of _ in hex number") + } + return nil +} + +func cleanupNumberToken(value string) string { + cleanedVal := strings.Replace(value, "_", "", -1) + return cleanedVal +} + +func (p *tomlParser) parseRvalue() interface{} { + tok := p.getToken() + if tok == nil || tok.typ == tokenEOF { + p.raiseError(tok, "expecting a value") + } + + switch tok.typ { + case tokenString: + return tok.val + case tokenTrue: + return true + case tokenFalse: + return false + case tokenInf: + if tok.val[0] == '-' { + return math.Inf(-1) + } + return math.Inf(1) + case tokenNan: + return math.NaN() + case tokenInteger: + cleanedVal := cleanupNumberToken(tok.val) + var err error + var val int64 + if len(cleanedVal) >= 3 && cleanedVal[0] == '0' { + switch cleanedVal[1] { + case 'x': + err = hexNumberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 16, 64) + case 'o': + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 8, 64) + case 'b': + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 2, 64) + default: + panic("invalid base") // the lexer should catch this first + } + } else { + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal, 10, 64) + } + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenFloat: + err := numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + cleanedVal := cleanupNumberToken(tok.val) + val, err := strconv.ParseFloat(cleanedVal, 64) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenDate: + val, err := time.ParseInLocation(time.RFC3339Nano, tok.val, time.UTC) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenLeftBracket: + return p.parseArray() + case tokenLeftCurlyBrace: + return p.parseInlineTable() + case tokenEqual: + p.raiseError(tok, "cannot have multiple equals for the same key") + case tokenError: + p.raiseError(tok, "%s", tok) + } + + p.raiseError(tok, "never reached") + + return nil +} + +func tokenIsComma(t *token) bool { + return t != nil && t.typ == tokenComma +} + +func (p *tomlParser) parseInlineTable() *Tree { + tree := newTree() + var previous *token +Loop: + for { + follow := p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated inline table") + } + switch follow.typ { + case tokenRightCurlyBrace: + p.getToken() + break Loop + case tokenKey: + if !tokenIsComma(previous) && previous != nil { + p.raiseError(follow, "comma expected between fields in inline table") + } + key := p.getToken() + p.assume(tokenEqual) + value := p.parseRvalue() + tree.Set(key.val, value) + case tokenComma: + if previous == nil { + p.raiseError(follow, "inline table cannot start with a comma") + } + if tokenIsComma(previous) { + p.raiseError(follow, "need field between two commas in inline table") + } + p.getToken() + default: + p.raiseError(follow, "unexpected token type in inline table: %s", follow.String()) + } + previous = follow + } + if tokenIsComma(previous) { + p.raiseError(previous, "trailing comma at the end of inline table") + } + return tree +} + +func (p *tomlParser) parseArray() interface{} { + var array []interface{} + arrayType := reflect.TypeOf(nil) + for { + follow := p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated array") + } + if follow.typ == tokenRightBracket { + p.getToken() + break + } + val := p.parseRvalue() + if arrayType == nil { + arrayType = reflect.TypeOf(val) + } + if reflect.TypeOf(val) != arrayType { + p.raiseError(follow, "mixed types in array") + } + array = append(array, val) + follow = p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated array") + } + if follow.typ != tokenRightBracket && follow.typ != tokenComma { + p.raiseError(follow, "missing comma") + } + if follow.typ == tokenComma { + p.getToken() + } + } + // An array of Trees is actually an array of inline + // tables, which is a shorthand for a table array. If the + // array was not converted from []interface{} to []*Tree, + // the two notations would not be equivalent. + if arrayType == reflect.TypeOf(newTree()) { + tomlArray := make([]*Tree, len(array)) + for i, v := range array { + tomlArray[i] = v.(*Tree) + } + return tomlArray + } + return array +} + +func parseToml(flow []token) *Tree { + result := newTree() + result.position = Position{1, 1} + parser := &tomlParser{ + flowIdx: 0, + flow: flow, + tree: result, + currentTable: make([]string, 0), + seenTableKeys: make([]string, 0), + } + parser.run() + return result +} + +func init() { + numberUnderscoreInvalidRegexp = regexp.MustCompile(`([^\d]_|_[^\d])|_$|^_`) + hexNumberUnderscoreInvalidRegexp = regexp.MustCompile(`(^0x_)|([^\da-f]_|_[^\da-f])|_$|^_`) +} diff --git a/vendor/github.com/pelletier/go-toml/position.go b/vendor/github.com/pelletier/go-toml/position.go new file mode 100644 index 000000000..c17bff87b --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/position.go @@ -0,0 +1,29 @@ +// Position support for go-toml + +package toml + +import ( + "fmt" +) + +// Position of a document element within a TOML document. +// +// Line and Col are both 1-indexed positions for the element's line number and +// column number, respectively. Values of zero or less will cause Invalid(), +// to return true. +type Position struct { + Line int // line within the document + Col int // column within the line +} + +// String representation of the position. +// Displays 1-indexed line and column numbers. +func (p Position) String() string { + return fmt.Sprintf("(%d, %d)", p.Line, p.Col) +} + +// Invalid returns whether or not the position is valid (i.e. with negative or +// null values) +func (p Position) Invalid() bool { + return p.Line <= 0 || p.Col <= 0 +} diff --git a/vendor/github.com/pelletier/go-toml/test.sh b/vendor/github.com/pelletier/go-toml/test.sh new file mode 100644 index 000000000..ba6adf3fc --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/test.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# fail out of the script if anything here fails +set -e +set -o pipefail + +# set the path to the present working directory +export GOPATH=`pwd` + +function git_clone() { + path=$1 + branch=$2 + version=$3 + if [ ! -d "src/$path" ]; then + mkdir -p src/$path + git clone https://$path.git src/$path + fi + pushd src/$path + git checkout "$branch" + git reset --hard "$version" + popd +} + +# Remove potential previous runs +rm -rf src test_program_bin toml-test + +go get github.com/pelletier/go-buffruneio +go get github.com/davecgh/go-spew/spew +go get gopkg.in/yaml.v2 +go get github.com/BurntSushi/toml + +# get code for BurntSushi TOML validation +# pinning all to 'HEAD' for version 0.3.x work (TODO: pin to commit hash when tests stabilize) +git_clone github.com/BurntSushi/toml master HEAD +git_clone github.com/BurntSushi/toml-test master HEAD #was: 0.2.0 HEAD + +# build the BurntSushi test application +go build -o toml-test github.com/BurntSushi/toml-test + +# vendorize the current lib for testing +# NOTE: this basically mocks an install without having to go back out to github for code +mkdir -p src/github.com/pelletier/go-toml/cmd +mkdir -p src/github.com/pelletier/go-toml/query +cp *.go *.toml src/github.com/pelletier/go-toml +cp -R cmd/* src/github.com/pelletier/go-toml/cmd +cp -R query/* src/github.com/pelletier/go-toml/query +go build -o test_program_bin src/github.com/pelletier/go-toml/cmd/test_program.go + +# Run basic unit tests +go test github.com/pelletier/go-toml -covermode=count -coverprofile=coverage.out +go test github.com/pelletier/go-toml/cmd/tomljson +go test github.com/pelletier/go-toml/query + +# run the entire BurntSushi test suite +if [[ $# -eq 0 ]] ; then + echo "Running all BurntSushi tests" + ./toml-test ./test_program_bin | tee test_out +else + # run a specific test + test=$1 + test_path='src/github.com/BurntSushi/toml-test/tests' + valid_test="$test_path/valid/$test" + invalid_test="$test_path/invalid/$test" + + if [ -e "$valid_test.toml" ]; then + echo "Valid Test TOML for $test:" + echo "====" + cat "$valid_test.toml" + + echo "Valid Test JSON for $test:" + echo "====" + cat "$valid_test.json" + + echo "Go-TOML Output for $test:" + echo "====" + cat "$valid_test.toml" | ./test_program_bin + fi + + if [ -e "$invalid_test.toml" ]; then + echo "Invalid Test TOML for $test:" + echo "====" + cat "$invalid_test.toml" + + echo "Go-TOML Output for $test:" + echo "====" + echo "go-toml Output:" + cat "$invalid_test.toml" | ./test_program_bin + fi +fi diff --git a/vendor/github.com/pelletier/go-toml/token.go b/vendor/github.com/pelletier/go-toml/token.go new file mode 100644 index 000000000..1a9081346 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/token.go @@ -0,0 +1,144 @@ +package toml + +import ( + "fmt" + "strconv" + "unicode" +) + +// Define tokens +type tokenType int + +const ( + eof = -(iota + 1) +) + +const ( + tokenError tokenType = iota + tokenEOF + tokenComment + tokenKey + tokenString + tokenInteger + tokenTrue + tokenFalse + tokenFloat + tokenInf + tokenNan + tokenEqual + tokenLeftBracket + tokenRightBracket + tokenLeftCurlyBrace + tokenRightCurlyBrace + tokenLeftParen + tokenRightParen + tokenDoubleLeftBracket + tokenDoubleRightBracket + tokenDate + tokenKeyGroup + tokenKeyGroupArray + tokenComma + tokenColon + tokenDollar + tokenStar + tokenQuestion + tokenDot + tokenDotDot + tokenEOL +) + +var tokenTypeNames = []string{ + "Error", + "EOF", + "Comment", + "Key", + "String", + "Integer", + "True", + "False", + "Float", + "Inf", + "NaN", + "=", + "[", + "]", + "{", + "}", + "(", + ")", + "]]", + "[[", + "Date", + "KeyGroup", + "KeyGroupArray", + ",", + ":", + "$", + "*", + "?", + ".", + "..", + "EOL", +} + +type token struct { + Position + typ tokenType + val string +} + +func (tt tokenType) String() string { + idx := int(tt) + if idx < len(tokenTypeNames) { + return tokenTypeNames[idx] + } + return "Unknown" +} + +func (t token) Int() int { + if result, err := strconv.Atoi(t.val); err != nil { + panic(err) + } else { + return result + } +} + +func (t token) String() string { + switch t.typ { + case tokenEOF: + return "EOF" + case tokenError: + return t.val + } + + return fmt.Sprintf("%q", t.val) +} + +func isSpace(r rune) bool { + return r == ' ' || r == '\t' +} + +func isAlphanumeric(r rune) bool { + return unicode.IsLetter(r) || r == '_' +} + +func isKeyChar(r rune) bool { + // Keys start with the first character that isn't whitespace or [ and end + // with the last non-whitespace character before the equals sign. Keys + // cannot contain a # character." + return !(r == '\r' || r == '\n' || r == eof || r == '=') +} + +func isKeyStartChar(r rune) bool { + return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[') +} + +func isDigit(r rune) bool { + return unicode.IsNumber(r) +} + +func isHexDigit(r rune) bool { + return isDigit(r) || + (r >= 'a' && r <= 'f') || + (r >= 'A' && r <= 'F') +} diff --git a/vendor/github.com/pelletier/go-toml/toml.go b/vendor/github.com/pelletier/go-toml/toml.go new file mode 100644 index 000000000..98c185ad0 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/toml.go @@ -0,0 +1,367 @@ +package toml + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "runtime" + "strings" +) + +type tomlValue struct { + value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list + comment string + commented bool + multiline bool + position Position +} + +// Tree is the result of the parsing of a TOML file. +type Tree struct { + values map[string]interface{} // string -> *tomlValue, *Tree, []*Tree + comment string + commented bool + position Position +} + +func newTree() *Tree { + return &Tree{ + values: make(map[string]interface{}), + position: Position{}, + } +} + +// TreeFromMap initializes a new Tree object using the given map. +func TreeFromMap(m map[string]interface{}) (*Tree, error) { + result, err := toTree(m) + if err != nil { + return nil, err + } + return result.(*Tree), nil +} + +// Position returns the position of the tree. +func (t *Tree) Position() Position { + return t.position +} + +// Has returns a boolean indicating if the given key exists. +func (t *Tree) Has(key string) bool { + if key == "" { + return false + } + return t.HasPath(strings.Split(key, ".")) +} + +// HasPath returns true if the given path of keys exists, false otherwise. +func (t *Tree) HasPath(keys []string) bool { + return t.GetPath(keys) != nil +} + +// Keys returns the keys of the toplevel tree (does not recurse). +func (t *Tree) Keys() []string { + keys := make([]string, len(t.values)) + i := 0 + for k := range t.values { + keys[i] = k + i++ + } + return keys +} + +// Get the value at key in the Tree. +// Key is a dot-separated path (e.g. a.b.c) without single/double quoted strings. +// If you need to retrieve non-bare keys, use GetPath. +// Returns nil if the path does not exist in the tree. +// If keys is of length zero, the current tree is returned. +func (t *Tree) Get(key string) interface{} { + if key == "" { + return t + } + return t.GetPath(strings.Split(key, ".")) +} + +// GetPath returns the element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetPath(keys []string) interface{} { + if len(keys) == 0 { + return t + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return nil + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return nil + } + subtree = node[len(node)-1] + default: + return nil // cannot navigate through other node types + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + return node.value + default: + return node + } +} + +// GetPosition returns the position of the given key. +func (t *Tree) GetPosition(key string) Position { + if key == "" { + return t.position + } + return t.GetPositionPath(strings.Split(key, ".")) +} + +// GetPositionPath returns the element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetPositionPath(keys []string) Position { + if len(keys) == 0 { + return t.position + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return Position{0, 0} + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return Position{0, 0} + } + subtree = node[len(node)-1] + default: + return Position{0, 0} + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + return node.position + case *Tree: + return node.position + case []*Tree: + // go to most recent element + if len(node) == 0 { + return Position{0, 0} + } + return node[len(node)-1].position + default: + return Position{0, 0} + } +} + +// GetDefault works like Get but with a default value +func (t *Tree) GetDefault(key string, def interface{}) interface{} { + val := t.Get(key) + if val == nil { + return def + } + return val +} + +// SetOptions arguments are supplied to the SetWithOptions and SetPathWithOptions functions to modify marshalling behaviour. +// The default values within the struct are valid default options. +type SetOptions struct { + Comment string + Commented bool + Multiline bool +} + +// SetWithOptions is the same as Set, but allows you to provide formatting +// instructions to the key, that will be used by Marshal(). +func (t *Tree) SetWithOptions(key string, opts SetOptions, value interface{}) { + t.SetPathWithOptions(strings.Split(key, "."), opts, value) +} + +// SetPathWithOptions is the same as SetPath, but allows you to provide +// formatting instructions to the key, that will be reused by Marshal(). +func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interface{}) { + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + nextTree, exists := subtree.values[intermediateKey] + if !exists { + nextTree = newTree() + subtree.values[intermediateKey] = nextTree // add new element here + } + switch node := nextTree.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + // create element if it does not exist + subtree.values[intermediateKey] = append(node, newTree()) + } + subtree = node[len(node)-1] + } + } + + var toInsert interface{} + + switch value.(type) { + case *Tree: + tt := value.(*Tree) + tt.comment = opts.Comment + toInsert = value + case []*Tree: + toInsert = value + case *tomlValue: + tt := value.(*tomlValue) + tt.comment = opts.Comment + toInsert = tt + default: + toInsert = &tomlValue{value: value, comment: opts.Comment, commented: opts.Commented, multiline: opts.Multiline} + } + + subtree.values[keys[len(keys)-1]] = toInsert +} + +// Set an element in the tree. +// Key is a dot-separated path (e.g. a.b.c). +// Creates all necessary intermediate trees, if needed. +func (t *Tree) Set(key string, value interface{}) { + t.SetWithComment(key, "", false, value) +} + +// SetWithComment is the same as Set, but allows you to provide comment +// information to the key, that will be reused by Marshal(). +func (t *Tree) SetWithComment(key string, comment string, commented bool, value interface{}) { + t.SetPathWithComment(strings.Split(key, "."), comment, commented, value) +} + +// SetPath sets an element in the tree. +// Keys is an array of path elements (e.g. {"a","b","c"}). +// Creates all necessary intermediate trees, if needed. +func (t *Tree) SetPath(keys []string, value interface{}) { + t.SetPathWithComment(keys, "", false, value) +} + +// SetPathWithComment is the same as SetPath, but allows you to provide comment +// information to the key, that will be reused by Marshal(). +func (t *Tree) SetPathWithComment(keys []string, comment string, commented bool, value interface{}) { + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + nextTree, exists := subtree.values[intermediateKey] + if !exists { + nextTree = newTree() + subtree.values[intermediateKey] = nextTree // add new element here + } + switch node := nextTree.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + // create element if it does not exist + subtree.values[intermediateKey] = append(node, newTree()) + } + subtree = node[len(node)-1] + } + } + + var toInsert interface{} + + switch value.(type) { + case *Tree: + tt := value.(*Tree) + tt.comment = comment + toInsert = value + case []*Tree: + toInsert = value + case *tomlValue: + tt := value.(*tomlValue) + tt.comment = comment + toInsert = tt + default: + toInsert = &tomlValue{value: value, comment: comment, commented: commented} + } + + subtree.values[keys[len(keys)-1]] = toInsert +} + +// createSubTree takes a tree and a key and create the necessary intermediate +// subtrees to create a subtree at that point. In-place. +// +// e.g. passing a.b.c will create (assuming tree is empty) tree[a], tree[a][b] +// and tree[a][b][c] +// +// Returns nil on success, error object on failure +func (t *Tree) createSubTree(keys []string, pos Position) error { + subtree := t + for _, intermediateKey := range keys { + nextTree, exists := subtree.values[intermediateKey] + if !exists { + tree := newTree() + tree.position = pos + subtree.values[intermediateKey] = tree + nextTree = tree + } + + switch node := nextTree.(type) { + case []*Tree: + subtree = node[len(node)-1] + case *Tree: + subtree = node + default: + return fmt.Errorf("unknown type for path %s (%s): %T (%#v)", + strings.Join(keys, "."), intermediateKey, nextTree, nextTree) + } + } + return nil +} + +// LoadBytes creates a Tree from a []byte. +func LoadBytes(b []byte) (tree *Tree, err error) { + defer func() { + if r := recover(); r != nil { + if _, ok := r.(runtime.Error); ok { + panic(r) + } + err = errors.New(r.(string)) + } + }() + tree = parseToml(lexToml(b)) + return +} + +// LoadReader creates a Tree from any io.Reader. +func LoadReader(reader io.Reader) (tree *Tree, err error) { + inputBytes, err := ioutil.ReadAll(reader) + if err != nil { + return + } + tree, err = LoadBytes(inputBytes) + return +} + +// Load creates a Tree from a string. +func Load(content string) (tree *Tree, err error) { + return LoadBytes([]byte(content)) +} + +// LoadFile creates a Tree from a file. +func LoadFile(path string) (tree *Tree, err error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + return LoadReader(file) +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_create.go b/vendor/github.com/pelletier/go-toml/tomltree_create.go new file mode 100644 index 000000000..79610e9b3 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_create.go @@ -0,0 +1,142 @@ +package toml + +import ( + "fmt" + "reflect" + "time" +) + +var kindToType = [reflect.String + 1]reflect.Type{ + reflect.Bool: reflect.TypeOf(true), + reflect.String: reflect.TypeOf(""), + reflect.Float32: reflect.TypeOf(float64(1)), + reflect.Float64: reflect.TypeOf(float64(1)), + reflect.Int: reflect.TypeOf(int64(1)), + reflect.Int8: reflect.TypeOf(int64(1)), + reflect.Int16: reflect.TypeOf(int64(1)), + reflect.Int32: reflect.TypeOf(int64(1)), + reflect.Int64: reflect.TypeOf(int64(1)), + reflect.Uint: reflect.TypeOf(uint64(1)), + reflect.Uint8: reflect.TypeOf(uint64(1)), + reflect.Uint16: reflect.TypeOf(uint64(1)), + reflect.Uint32: reflect.TypeOf(uint64(1)), + reflect.Uint64: reflect.TypeOf(uint64(1)), +} + +// typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found. +// supported values: +// string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32 +func typeFor(k reflect.Kind) reflect.Type { + if k > 0 && int(k) < len(kindToType) { + return kindToType[k] + } + return nil +} + +func simpleValueCoercion(object interface{}) (interface{}, error) { + switch original := object.(type) { + case string, bool, int64, uint64, float64, time.Time: + return original, nil + case int: + return int64(original), nil + case int8: + return int64(original), nil + case int16: + return int64(original), nil + case int32: + return int64(original), nil + case uint: + return uint64(original), nil + case uint8: + return uint64(original), nil + case uint16: + return uint64(original), nil + case uint32: + return uint64(original), nil + case float32: + return float64(original), nil + case fmt.Stringer: + return original.String(), nil + default: + return nil, fmt.Errorf("cannot convert type %T to Tree", object) + } +} + +func sliceToTree(object interface{}) (interface{}, error) { + // arrays are a bit tricky, since they can represent either a + // collection of simple values, which is represented by one + // *tomlValue, or an array of tables, which is represented by an + // array of *Tree. + + // holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice + value := reflect.ValueOf(object) + insideType := value.Type().Elem() + length := value.Len() + if length > 0 { + insideType = reflect.ValueOf(value.Index(0).Interface()).Type() + } + if insideType.Kind() == reflect.Map { + // this is considered as an array of tables + tablesArray := make([]*Tree, 0, length) + for i := 0; i < length; i++ { + table := value.Index(i) + tree, err := toTree(table.Interface()) + if err != nil { + return nil, err + } + tablesArray = append(tablesArray, tree.(*Tree)) + } + return tablesArray, nil + } + + sliceType := typeFor(insideType.Kind()) + if sliceType == nil { + sliceType = insideType + } + + arrayValue := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length) + + for i := 0; i < length; i++ { + val := value.Index(i).Interface() + simpleValue, err := simpleValueCoercion(val) + if err != nil { + return nil, err + } + arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue)) + } + return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil +} + +func toTree(object interface{}) (interface{}, error) { + value := reflect.ValueOf(object) + + if value.Kind() == reflect.Map { + values := map[string]interface{}{} + keys := value.MapKeys() + for _, key := range keys { + if key.Kind() != reflect.String { + if _, ok := key.Interface().(string); !ok { + return nil, fmt.Errorf("map key needs to be a string, not %T (%v)", key.Interface(), key.Kind()) + } + } + + v := value.MapIndex(key) + newValue, err := toTree(v.Interface()) + if err != nil { + return nil, err + } + values[key.String()] = newValue + } + return &Tree{values: values, position: Position{}}, nil + } + + if value.Kind() == reflect.Array || value.Kind() == reflect.Slice { + return sliceToTree(object) + } + + simpleValue, err := simpleValueCoercion(object) + if err != nil { + return nil, err + } + return &tomlValue{value: simpleValue, position: Position{}}, nil +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go new file mode 100644 index 000000000..e4049e29f --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go @@ -0,0 +1,333 @@ +package toml + +import ( + "bytes" + "fmt" + "io" + "math" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +// Encodes a string to a TOML-compliant multi-line string value +// This function is a clone of the existing encodeTomlString function, except that whitespace characters +// are preserved. Quotation marks and backslashes are also not escaped. +func encodeMultilineTomlString(value string) string { + var b bytes.Buffer + + for _, rr := range value { + switch rr { + case '\b': + b.WriteString(`\b`) + case '\t': + b.WriteString("\t") + case '\n': + b.WriteString("\n") + case '\f': + b.WriteString(`\f`) + case '\r': + b.WriteString("\r") + case '"': + b.WriteString(`"`) + case '\\': + b.WriteString(`\`) + default: + intRr := uint16(rr) + if intRr < 0x001F { + b.WriteString(fmt.Sprintf("\\u%0.4X", intRr)) + } else { + b.WriteRune(rr) + } + } + } + return b.String() +} + +// Encodes a string to a TOML-compliant string value +func encodeTomlString(value string) string { + var b bytes.Buffer + + for _, rr := range value { + switch rr { + case '\b': + b.WriteString(`\b`) + case '\t': + b.WriteString(`\t`) + case '\n': + b.WriteString(`\n`) + case '\f': + b.WriteString(`\f`) + case '\r': + b.WriteString(`\r`) + case '"': + b.WriteString(`\"`) + case '\\': + b.WriteString(`\\`) + default: + intRr := uint16(rr) + if intRr < 0x001F { + b.WriteString(fmt.Sprintf("\\u%0.4X", intRr)) + } else { + b.WriteRune(rr) + } + } + } + return b.String() +} + +func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) { + // this interface check is added to dereference the change made in the writeTo function. + // That change was made to allow this function to see formatting options. + tv, ok := v.(*tomlValue) + if ok { + v = tv.value + } else { + tv = &tomlValue{} + } + + switch value := v.(type) { + case uint64: + return strconv.FormatUint(value, 10), nil + case int64: + return strconv.FormatInt(value, 10), nil + case float64: + // Ensure a round float does contain a decimal point. Otherwise feeding + // the output back to the parser would convert to an integer. + if math.Trunc(value) == value { + return strings.ToLower(strconv.FormatFloat(value, 'f', 1, 32)), nil + } + return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil + case string: + if tv.multiline { + return "\"\"\"\n" + encodeMultilineTomlString(value) + "\"\"\"", nil + } + return "\"" + encodeTomlString(value) + "\"", nil + case []byte: + b, _ := v.([]byte) + return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine) + case bool: + if value { + return "true", nil + } + return "false", nil + case time.Time: + return value.Format(time.RFC3339), nil + case nil: + return "", nil + } + + rv := reflect.ValueOf(v) + + if rv.Kind() == reflect.Slice { + var values []string + for i := 0; i < rv.Len(); i++ { + item := rv.Index(i).Interface() + itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine) + if err != nil { + return "", err + } + values = append(values, itemRepr) + } + if arraysOneElementPerLine && len(values) > 1 { + stringBuffer := bytes.Buffer{} + valueIndent := indent + ` ` // TODO: move that to a shared encoder state + + stringBuffer.WriteString("[\n") + + for _, value := range values { + stringBuffer.WriteString(valueIndent) + stringBuffer.WriteString(value) + stringBuffer.WriteString(`,`) + stringBuffer.WriteString("\n") + } + + stringBuffer.WriteString(indent + "]") + + return stringBuffer.String(), nil + } + return "[" + strings.Join(values, ",") + "]", nil + } + return "", fmt.Errorf("unsupported value type %T: %v", v, v) +} + +func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) { + simpleValuesKeys := make([]string, 0) + complexValuesKeys := make([]string, 0) + + for k := range t.values { + v := t.values[k] + switch v.(type) { + case *Tree, []*Tree: + complexValuesKeys = append(complexValuesKeys, k) + default: + simpleValuesKeys = append(simpleValuesKeys, k) + } + } + + sort.Strings(simpleValuesKeys) + sort.Strings(complexValuesKeys) + + for _, k := range simpleValuesKeys { + v, ok := t.values[k].(*tomlValue) + if !ok { + return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) + } + + repr, err := tomlValueStringRepresentation(v, indent, arraysOneElementPerLine) + if err != nil { + return bytesCount, err + } + + if v.comment != "" { + comment := strings.Replace(v.comment, "\n", "\n"+indent+"#", -1) + start := "# " + if strings.HasPrefix(comment, "#") { + start = "" + } + writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment, "\n") + bytesCount += int64(writtenBytesCountComment) + if errc != nil { + return bytesCount, errc + } + } + + var commented string + if v.commented { + commented = "# " + } + writtenBytesCount, err := writeStrings(w, indent, commented, k, " = ", repr, "\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + } + + for _, k := range complexValuesKeys { + v := t.values[k] + + combinedKey := k + if keyspace != "" { + combinedKey = keyspace + "." + combinedKey + } + var commented string + if t.commented { + commented = "# " + } + + switch node := v.(type) { + // node has to be of those two types given how keys are sorted above + case *Tree: + tv, ok := t.values[k].(*Tree) + if !ok { + return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) + } + if tv.comment != "" { + comment := strings.Replace(tv.comment, "\n", "\n"+indent+"#", -1) + start := "# " + if strings.HasPrefix(comment, "#") { + start = "" + } + writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment) + bytesCount += int64(writtenBytesCountComment) + if errc != nil { + return bytesCount, errc + } + } + writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + bytesCount, err = node.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine) + if err != nil { + return bytesCount, err + } + case []*Tree: + for _, subTree := range node { + writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + + bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine) + if err != nil { + return bytesCount, err + } + } + } + } + + return bytesCount, nil +} + +func writeStrings(w io.Writer, s ...string) (int, error) { + var n int + for i := range s { + b, err := io.WriteString(w, s[i]) + n += b + if err != nil { + return n, err + } + } + return n, nil +} + +// WriteTo encode the Tree as Toml and writes it to the writer w. +// Returns the number of bytes written in case of success, or an error if anything happened. +func (t *Tree) WriteTo(w io.Writer) (int64, error) { + return t.writeTo(w, "", "", 0, false) +} + +// ToTomlString generates a human-readable representation of the current tree. +// Output spans multiple lines, and is suitable for ingest by a TOML parser. +// If the conversion cannot be performed, ToString returns a non-nil error. +func (t *Tree) ToTomlString() (string, error) { + var buf bytes.Buffer + _, err := t.WriteTo(&buf) + if err != nil { + return "", err + } + return buf.String(), nil +} + +// String generates a human-readable representation of the current tree. +// Alias of ToString. Present to implement the fmt.Stringer interface. +func (t *Tree) String() string { + result, _ := t.ToTomlString() + return result +} + +// ToMap recursively generates a representation of the tree using Go built-in structures. +// The following types are used: +// +// * bool +// * float64 +// * int64 +// * string +// * uint64 +// * time.Time +// * map[string]interface{} (where interface{} is any of this list) +// * []interface{} (where interface{} is any of this list) +func (t *Tree) ToMap() map[string]interface{} { + result := map[string]interface{}{} + + for k, v := range t.values { + switch node := v.(type) { + case []*Tree: + var array []interface{} + for _, item := range node { + array = append(array, item.ToMap()) + } + result[k] = array + case *Tree: + result[k] = node.ToMap() + case *tomlValue: + result[k] = node.value + } + } + return result +} diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/vendor/github.com/pkg/errors/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml new file mode 100644 index 000000000..d4b92663b --- /dev/null +++ b/vendor/github.com/pkg/errors/.travis.yml @@ -0,0 +1,15 @@ +language: go +go_import_path: github.com/pkg/errors +go: + - 1.4.x + - 1.5.x + - 1.6.x + - 1.7.x + - 1.8.x + - 1.9.x + - 1.10.x + - 1.11.x + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE new file mode 100644 index 000000000..835ba3e75 --- /dev/null +++ b/vendor/github.com/pkg/errors/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2015, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md new file mode 100644 index 000000000..6483ba2af --- /dev/null +++ b/vendor/github.com/pkg/errors/README.md @@ -0,0 +1,52 @@ +# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) + +Package errors provides simple error handling primitives. + +`go get github.com/pkg/errors` + +The traditional error handling idiom in Go is roughly akin to +```go +if err != nil { + return err +} +``` +which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. + +## Adding context to an error + +The errors.Wrap function returns a new error that adds context to the original error. For example +```go +_, err := ioutil.ReadAll(r) +if err != nil { + return errors.Wrap(err, "read failed") +} +``` +## Retrieving the cause of an error + +Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. +```go +type causer interface { + Cause() error +} +``` +`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: +```go +switch err := errors.Cause(err).(type) { +case *MyError: + // handle specifically +default: + // unknown error +} +``` + +[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). + +## Contributing + +We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. + +Before proposing a change, please discuss your change by raising an issue. + +## License + +BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml new file mode 100644 index 000000000..a932eade0 --- /dev/null +++ b/vendor/github.com/pkg/errors/appveyor.yml @@ -0,0 +1,32 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\pkg\errors +shallow_clone: true # for startup speed + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +# http://www.appveyor.com/docs/installed-software +install: + # some helpful output for debugging builds + - go version + - go env + # pre-installed MinGW at C:\MinGW is 32bit only + # but MSYS2 at C:\msys64 has mingw64 + - set PATH=C:\msys64\mingw64\bin;%PATH% + - gcc --version + - g++ --version + +build_script: + - go install -v ./... + +test_script: + - set PATH=C:\gopath\bin;%PATH% + - go test -v ./... + +#artifacts: +# - path: '%GOPATH%\bin\*.exe' +deploy: off diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go new file mode 100644 index 000000000..7421f326f --- /dev/null +++ b/vendor/github.com/pkg/errors/errors.go @@ -0,0 +1,282 @@ +// Package errors provides simple error handling primitives. +// +// The traditional error handling idiom in Go is roughly akin to +// +// if err != nil { +// return err +// } +// +// which when applied recursively up the call stack results in error reports +// without context or debugging information. The errors package allows +// programmers to add context to the failure path in their code in a way +// that does not destroy the original value of the error. +// +// Adding context to an error +// +// The errors.Wrap function returns a new error that adds context to the +// original error by recording a stack trace at the point Wrap is called, +// together with the supplied message. For example +// +// _, err := ioutil.ReadAll(r) +// if err != nil { +// return errors.Wrap(err, "read failed") +// } +// +// If additional control is required, the errors.WithStack and +// errors.WithMessage functions destructure errors.Wrap into its component +// operations: annotating an error with a stack trace and with a message, +// respectively. +// +// Retrieving the cause of an error +// +// Using errors.Wrap constructs a stack of errors, adding context to the +// preceding error. Depending on the nature of the error it may be necessary +// to reverse the operation of errors.Wrap to retrieve the original error +// for inspection. Any error value which implements this interface +// +// type causer interface { +// Cause() error +// } +// +// can be inspected by errors.Cause. errors.Cause will recursively retrieve +// the topmost error that does not implement causer, which is assumed to be +// the original cause. For example: +// +// switch err := errors.Cause(err).(type) { +// case *MyError: +// // handle specifically +// default: +// // unknown error +// } +// +// Although the causer interface is not exported by this package, it is +// considered a part of its stable public interface. +// +// Formatted printing of errors +// +// All error values returned from this package implement fmt.Formatter and can +// be formatted by the fmt package. The following verbs are supported: +// +// %s print the error. If the error has a Cause it will be +// printed recursively. +// %v see %s +// %+v extended format. Each Frame of the error's StackTrace will +// be printed in detail. +// +// Retrieving the stack trace of an error or wrapper +// +// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are +// invoked. This information can be retrieved with the following interface: +// +// type stackTracer interface { +// StackTrace() errors.StackTrace +// } +// +// The returned errors.StackTrace type is defined as +// +// type StackTrace []Frame +// +// The Frame type represents a call site in the stack trace. Frame supports +// the fmt.Formatter interface that can be used for printing information about +// the stack trace of this error. For example: +// +// if err, ok := err.(stackTracer); ok { +// for _, f := range err.StackTrace() { +// fmt.Printf("%+s:%d", f) +// } +// } +// +// Although the stackTracer interface is not exported by this package, it is +// considered a part of its stable public interface. +// +// See the documentation for Frame.Format for more details. +package errors + +import ( + "fmt" + "io" +) + +// New returns an error with the supplied message. +// New also records the stack trace at the point it was called. +func New(message string) error { + return &fundamental{ + msg: message, + stack: callers(), + } +} + +// Errorf formats according to a format specifier and returns the string +// as a value that satisfies error. +// Errorf also records the stack trace at the point it was called. +func Errorf(format string, args ...interface{}) error { + return &fundamental{ + msg: fmt.Sprintf(format, args...), + stack: callers(), + } +} + +// fundamental is an error that has a message and a stack, but no caller. +type fundamental struct { + msg string + *stack +} + +func (f *fundamental) Error() string { return f.msg } + +func (f *fundamental) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + io.WriteString(s, f.msg) + f.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, f.msg) + case 'q': + fmt.Fprintf(s, "%q", f.msg) + } +} + +// WithStack annotates err with a stack trace at the point WithStack was called. +// If err is nil, WithStack returns nil. +func WithStack(err error) error { + if err == nil { + return nil + } + return &withStack{ + err, + callers(), + } +} + +type withStack struct { + error + *stack +} + +func (w *withStack) Cause() error { return w.error } + +func (w *withStack) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v", w.Cause()) + w.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, w.Error()) + case 'q': + fmt.Fprintf(s, "%q", w.Error()) + } +} + +// Wrap returns an error annotating err with a stack trace +// at the point Wrap is called, and the supplied message. +// If err is nil, Wrap returns nil. +func Wrap(err error, message string) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: message, + } + return &withStack{ + err, + callers(), + } +} + +// Wrapf returns an error annotating err with a stack trace +// at the point Wrapf is called, and the format specifier. +// If err is nil, Wrapf returns nil. +func Wrapf(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } + return &withStack{ + err, + callers(), + } +} + +// WithMessage annotates err with a new message. +// If err is nil, WithMessage returns nil. +func WithMessage(err error, message string) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: message, + } +} + +// WithMessagef annotates err with the format specifier. +// If err is nil, WithMessagef returns nil. +func WithMessagef(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } +} + +type withMessage struct { + cause error + msg string +} + +func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } +func (w *withMessage) Cause() error { return w.cause } + +func (w *withMessage) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v\n", w.Cause()) + io.WriteString(s, w.msg) + return + } + fallthrough + case 's', 'q': + io.WriteString(s, w.Error()) + } +} + +// Cause returns the underlying cause of the error, if possible. +// An error value has a cause if it implements the following +// interface: +// +// type causer interface { +// Cause() error +// } +// +// If the error does not implement Cause, the original error will +// be returned. If the error is nil, nil will be returned without further +// investigation. +func Cause(err error) error { + type causer interface { + Cause() error + } + + for err != nil { + cause, ok := err.(causer) + if !ok { + break + } + err = cause.Cause() + } + return err +} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go new file mode 100644 index 000000000..2874a048c --- /dev/null +++ b/vendor/github.com/pkg/errors/stack.go @@ -0,0 +1,147 @@ +package errors + +import ( + "fmt" + "io" + "path" + "runtime" + "strings" +) + +// Frame represents a program counter inside a stack frame. +type Frame uintptr + +// pc returns the program counter for this frame; +// multiple frames may have the same PC value. +func (f Frame) pc() uintptr { return uintptr(f) - 1 } + +// file returns the full path to the file that contains the +// function for this Frame's pc. +func (f Frame) file() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + file, _ := fn.FileLine(f.pc()) + return file +} + +// line returns the line number of source code of the +// function for this Frame's pc. +func (f Frame) line() int { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return 0 + } + _, line := fn.FileLine(f.pc()) + return line +} + +// Format formats the frame according to the fmt.Formatter interface. +// +// %s source file +// %d source line +// %n function name +// %v equivalent to %s:%d +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+s function name and path of source file relative to the compile time +// GOPATH separated by \n\t (\n\t) +// %+v equivalent to %+s:%d +func (f Frame) Format(s fmt.State, verb rune) { + switch verb { + case 's': + switch { + case s.Flag('+'): + pc := f.pc() + fn := runtime.FuncForPC(pc) + if fn == nil { + io.WriteString(s, "unknown") + } else { + file, _ := fn.FileLine(pc) + fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) + } + default: + io.WriteString(s, path.Base(f.file())) + } + case 'd': + fmt.Fprintf(s, "%d", f.line()) + case 'n': + name := runtime.FuncForPC(f.pc()).Name() + io.WriteString(s, funcname(name)) + case 'v': + f.Format(s, 's') + io.WriteString(s, ":") + f.Format(s, 'd') + } +} + +// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). +type StackTrace []Frame + +// Format formats the stack of Frames according to the fmt.Formatter interface. +// +// %s lists source files for each Frame in the stack +// %v lists the source file and line number for each Frame in the stack +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+v Prints filename, function, and line number for each Frame in the stack. +func (st StackTrace) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case s.Flag('+'): + for _, f := range st { + fmt.Fprintf(s, "\n%+v", f) + } + case s.Flag('#'): + fmt.Fprintf(s, "%#v", []Frame(st)) + default: + fmt.Fprintf(s, "%v", []Frame(st)) + } + case 's': + fmt.Fprintf(s, "%s", []Frame(st)) + } +} + +// stack represents a stack of program counters. +type stack []uintptr + +func (s *stack) Format(st fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case st.Flag('+'): + for _, pc := range *s { + f := Frame(pc) + fmt.Fprintf(st, "\n%+v", f) + } + } + } +} + +func (s *stack) StackTrace() StackTrace { + f := make([]Frame, len(*s)) + for i := 0; i < len(f); i++ { + f[i] = Frame((*s)[i]) + } + return f +} + +func callers() *stack { + const depth = 32 + var pcs [depth]uintptr + n := runtime.Callers(3, pcs[:]) + var st stack = pcs[0:n] + return &st +} + +// funcname removes the path prefix component of a function's name reported by func.Name(). +func funcname(name string) string { + i := strings.LastIndex(name, "/") + name = name[i+1:] + i = strings.Index(name, ".") + return name[i+1:] +} diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE new file mode 100644 index 000000000..c67dad612 --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, Patrick Mezard +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + The names of its contributors may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go new file mode 100644 index 000000000..003e99fad --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go @@ -0,0 +1,772 @@ +// Package difflib is a partial port of Python difflib module. +// +// It provides tools to compare sequences of strings and generate textual diffs. +// +// The following class and functions have been ported: +// +// - SequenceMatcher +// +// - unified_diff +// +// - context_diff +// +// Getting unified diffs was the main goal of the port. Keep in mind this code +// is mostly suitable to output text differences in a human friendly way, there +// are no guarantees generated diffs are consumable by patch(1). +package difflib + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func calculateRatio(matches, length int) float64 { + if length > 0 { + return 2.0 * float64(matches) / float64(length) + } + return 1.0 +} + +type Match struct { + A int + B int + Size int +} + +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "

" lines in HTML files). That may be +// because this is the only method of the 3 that has a *concept* of +// "junk" . +// +// Timing: Basic R-O is cubic time worst case and quadratic time expected +// case. SequenceMatcher is quadratic time for the worst case and has +// expected-case behavior dependent in a complicated way on how many +// elements the sequences have in common; best case time is linear. +type SequenceMatcher struct { + a []string + b []string + b2j map[string][]int + IsJunk func(string) bool + autoJunk bool + bJunk map[string]struct{} + matchingBlocks []Match + fullBCount map[string]int + bPopular map[string]struct{} + opCodes []OpCode +} + +func NewMatcher(a, b []string) *SequenceMatcher { + m := SequenceMatcher{autoJunk: true} + m.SetSeqs(a, b) + return &m +} + +func NewMatcherWithJunk(a, b []string, autoJunk bool, + isJunk func(string) bool) *SequenceMatcher { + + m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} + m.SetSeqs(a, b) + return &m +} + +// Set two sequences to be compared. +func (m *SequenceMatcher) SetSeqs(a, b []string) { + m.SetSeq1(a) + m.SetSeq2(b) +} + +// Set the first sequence to be compared. The second sequence to be compared is +// not changed. +// +// SequenceMatcher computes and caches detailed information about the second +// sequence, so if you want to compare one sequence S against many sequences, +// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other +// sequences. +// +// See also SetSeqs() and SetSeq2(). +func (m *SequenceMatcher) SetSeq1(a []string) { + if &a == &m.a { + return + } + m.a = a + m.matchingBlocks = nil + m.opCodes = nil +} + +// Set the second sequence to be compared. The first sequence to be compared is +// not changed. +func (m *SequenceMatcher) SetSeq2(b []string) { + if &b == &m.b { + return + } + m.b = b + m.matchingBlocks = nil + m.opCodes = nil + m.fullBCount = nil + m.chainB() +} + +func (m *SequenceMatcher) chainB() { + // Populate line -> index mapping + b2j := map[string][]int{} + for i, s := range m.b { + indices := b2j[s] + indices = append(indices, i) + b2j[s] = indices + } + + // Purge junk elements + m.bJunk = map[string]struct{}{} + if m.IsJunk != nil { + junk := m.bJunk + for s, _ := range b2j { + if m.IsJunk(s) { + junk[s] = struct{}{} + } + } + for s, _ := range junk { + delete(b2j, s) + } + } + + // Purge remaining popular elements + popular := map[string]struct{}{} + n := len(m.b) + if m.autoJunk && n >= 200 { + ntest := n/100 + 1 + for s, indices := range b2j { + if len(indices) > ntest { + popular[s] = struct{}{} + } + } + for s, _ := range popular { + delete(b2j, s) + } + } + m.bPopular = popular + m.b2j = b2j +} + +func (m *SequenceMatcher) isBJunk(s string) bool { + _, ok := m.bJunk[s] + return ok +} + +// Find longest matching block in a[alo:ahi] and b[blo:bhi]. +// +// If IsJunk is not defined: +// +// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where +// alo <= i <= i+k <= ahi +// blo <= j <= j+k <= bhi +// and for all (i',j',k') meeting those conditions, +// k >= k' +// i <= i' +// and if i == i', j <= j' +// +// In other words, of all maximal matching blocks, return one that +// starts earliest in a, and of all those maximal matching blocks that +// start earliest in a, return the one that starts earliest in b. +// +// If IsJunk is defined, first the longest matching block is +// determined as above, but with the additional restriction that no +// junk element appears in the block. Then that block is extended as +// far as possible by matching (only) junk elements on both sides. So +// the resulting block never matches on junk except as identical junk +// happens to be adjacent to an "interesting" match. +// +// If no blocks match, return (alo, blo, 0). +func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { + // CAUTION: stripping common prefix or suffix would be incorrect. + // E.g., + // ab + // acab + // Longest matching block is "ab", but if common prefix is + // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + // strip, so ends up claiming that ab is changed to acab by + // inserting "ca" in the middle. That's minimal but unintuitive: + // "it's obvious" that someone inserted "ac" at the front. + // Windiff ends up at the same place as diff, but by pairing up + // the unique 'b's and then matching the first two 'a's. + besti, bestj, bestsize := alo, blo, 0 + + // find longest junk-free match + // during an iteration of the loop, j2len[j] = length of longest + // junk-free match ending with a[i-1] and b[j] + j2len := map[int]int{} + for i := alo; i != ahi; i++ { + // look at all instances of a[i] in b; note that because + // b2j has no junk keys, the loop is skipped if a[i] is junk + newj2len := map[int]int{} + for _, j := range m.b2j[m.a[i]] { + // a[i] matches b[j] + if j < blo { + continue + } + if j >= bhi { + break + } + k := j2len[j-1] + 1 + newj2len[j] = k + if k > bestsize { + besti, bestj, bestsize = i-k+1, j-k+1, k + } + } + j2len = newj2len + } + + // Extend the best by non-junk elements on each end. In particular, + // "popular" non-junk elements aren't in b2j, which greatly speeds + // the inner loop above, but also means "the best" match so far + // doesn't contain any junk *or* popular non-junk elements. + for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + !m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + // Now that we have a wholly interesting match (albeit possibly + // empty!), we may as well suck up the matching junk on each + // side of it too. Can't think of a good reason not to, and it + // saves post-processing the (possibly considerable) expense of + // figuring out what to do with it. In the case of an empty + // interesting match, this is clearly the right thing to do, + // because no other kind of match is possible in the regions. + for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + return Match{A: besti, B: bestj, Size: bestsize} +} + +// Return list of triples describing matching subsequences. +// +// Each triple is of the form (i, j, n), and means that +// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in +// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are +// adjacent triples in the list, and the second is not the last triple in the +// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe +// adjacent equal blocks. +// +// The last triple is a dummy, (len(a), len(b), 0), and is the only +// triple with n==0. +func (m *SequenceMatcher) GetMatchingBlocks() []Match { + if m.matchingBlocks != nil { + return m.matchingBlocks + } + + var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match + matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { + match := m.findLongestMatch(alo, ahi, blo, bhi) + i, j, k := match.A, match.B, match.Size + if match.Size > 0 { + if alo < i && blo < j { + matched = matchBlocks(alo, i, blo, j, matched) + } + matched = append(matched, match) + if i+k < ahi && j+k < bhi { + matched = matchBlocks(i+k, ahi, j+k, bhi, matched) + } + } + return matched + } + matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) + + // It's possible that we have adjacent equal blocks in the + // matching_blocks list now. + nonAdjacent := []Match{} + i1, j1, k1 := 0, 0, 0 + for _, b := range matched { + // Is this block adjacent to i1, j1, k1? + i2, j2, k2 := b.A, b.B, b.Size + if i1+k1 == i2 && j1+k1 == j2 { + // Yes, so collapse them -- this just increases the length of + // the first block by the length of the second, and the first + // block so lengthened remains the block to compare against. + k1 += k2 + } else { + // Not adjacent. Remember the first block (k1==0 means it's + // the dummy we started with), and make the second block the + // new block to compare against. + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + i1, j1, k1 = i2, j2, k2 + } + } + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + + nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) + m.matchingBlocks = nonAdjacent + return m.matchingBlocks +} + +// Return list of 5-tuples describing how to turn a into b. +// +// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple +// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the +// tuple preceding it, and likewise for j1 == the previous j2. +// +// The tags are characters, with these meanings: +// +// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] +// +// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. +// +// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. +// +// 'e' (equal): a[i1:i2] == b[j1:j2] +func (m *SequenceMatcher) GetOpCodes() []OpCode { + if m.opCodes != nil { + return m.opCodes + } + i, j := 0, 0 + matching := m.GetMatchingBlocks() + opCodes := make([]OpCode, 0, len(matching)) + for _, m := range matching { + // invariant: we've pumped out correct diffs to change + // a[:i] into b[:j], and the next matching block is + // a[ai:ai+size] == b[bj:bj+size]. So we need to pump + // out a diff to change a[i:ai] into b[j:bj], pump out + // the matching block, and move (i,j) beyond the match + ai, bj, size := m.A, m.B, m.Size + tag := byte(0) + if i < ai && j < bj { + tag = 'r' + } else if i < ai { + tag = 'd' + } else if j < bj { + tag = 'i' + } + if tag > 0 { + opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) + } + i, j = ai+size, bj+size + // the list of matching blocks is terminated by a + // sentinel with size 0 + if size > 0 { + opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) + } + } + m.opCodes = opCodes + return m.opCodes +} + +// Isolate change clusters by eliminating ranges with no changes. +// +// Return a generator of groups with up to n lines of context. +// Each group is in the same format as returned by GetOpCodes(). +func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { + if n < 0 { + n = 3 + } + codes := m.GetOpCodes() + if len(codes) == 0 { + codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} + } + // Fixup leading and trailing groups if they show no changes. + if codes[0].Tag == 'e' { + c := codes[0] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + } + if codes[len(codes)-1].Tag == 'e' { + c := codes[len(codes)-1] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + } + nn := n + n + groups := [][]OpCode{} + group := []OpCode{} + for _, c := range codes { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + // End the current group and start a new one whenever + // there is a large range with no changes. + if c.Tag == 'e' && i2-i1 > nn { + group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), + j1, min(j2, j1+n)}) + groups = append(groups, group) + group = []OpCode{} + i1, j1 = max(i1, i2-n), max(j1, j2-n) + } + group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) + } + if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + groups = append(groups, group) + } + return groups +} + +// Return a measure of the sequences' similarity (float in [0,1]). +// +// Where T is the total number of elements in both sequences, and +// M is the number of matches, this is 2.0*M / T. +// Note that this is 1 if the sequences are identical, and 0 if +// they have nothing in common. +// +// .Ratio() is expensive to compute if you haven't already computed +// .GetMatchingBlocks() or .GetOpCodes(), in which case you may +// want to try .QuickRatio() or .RealQuickRation() first to get an +// upper bound. +func (m *SequenceMatcher) Ratio() float64 { + matches := 0 + for _, m := range m.GetMatchingBlocks() { + matches += m.Size + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() relatively quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute. +func (m *SequenceMatcher) QuickRatio() float64 { + // viewing a and b as multisets, set matches to the cardinality + // of their intersection; this counts the number of matches + // without regard to order, so is clearly an upper bound + if m.fullBCount == nil { + m.fullBCount = map[string]int{} + for _, s := range m.b { + m.fullBCount[s] = m.fullBCount[s] + 1 + } + } + + // avail[x] is the number of times x appears in 'b' less the + // number of times we've seen it in 'a' so far ... kinda + avail := map[string]int{} + matches := 0 + for _, s := range m.a { + n, ok := avail[s] + if !ok { + n = m.fullBCount[s] + } + avail[s] = n - 1 + if n > 0 { + matches += 1 + } + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() very quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute than either .Ratio() or .QuickRatio(). +func (m *SequenceMatcher) RealQuickRatio() float64 { + la, lb := len(m.a), len(m.b) + return calculateRatio(min(la, lb), la+lb) +} + +// Convert range to the "ed" format +func formatRangeUnified(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 1 { + return fmt.Sprintf("%d", beginning) + } + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + return fmt.Sprintf("%d,%d", beginning, length) +} + +// Unified diff parameters +type UnifiedDiff struct { + A []string // First sequence lines + FromFile string // First file name + FromDate string // First file time + B []string // Second sequence lines + ToFile string // Second file name + ToDate string // Second file time + Eol string // Headers end of line, defaults to LF + Context int // Number of context lines +} + +// Compare two sequences of lines; generate the delta as a unified diff. +// +// Unified diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by 'n' which +// defaults to three. +// +// By default, the diff control lines (those with ---, +++, or @@) are +// created with a trailing newline. This is helpful so that inputs +// created from file.readlines() result in diffs that are suitable for +// file.writelines() since both the inputs and outputs have trailing +// newlines. +// +// For inputs that do not have trailing newlines, set the lineterm +// argument to "" so that the output will be uniformly newline free. +// +// The unidiff format normally has a header for filenames and modification +// times. Any or all of these may be specified using strings for +// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. +// The modification times are normally expressed in the ISO 8601 format. +func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + wf := func(format string, args ...interface{}) error { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + return err + } + ws := func(s string) error { + _, err := buf.WriteString(s) + return err + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) + if err != nil { + return err + } + err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) + if err != nil { + return err + } + } + } + first, last := g[0], g[len(g)-1] + range1 := formatRangeUnified(first.I1, last.I2) + range2 := formatRangeUnified(first.J1, last.J2) + if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { + return err + } + for _, c := range g { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + if c.Tag == 'e' { + for _, line := range diff.A[i1:i2] { + if err := ws(" " + line); err != nil { + return err + } + } + continue + } + if c.Tag == 'r' || c.Tag == 'd' { + for _, line := range diff.A[i1:i2] { + if err := ws("-" + line); err != nil { + return err + } + } + } + if c.Tag == 'r' || c.Tag == 'i' { + for _, line := range diff.B[j1:j2] { + if err := ws("+" + line); err != nil { + return err + } + } + } + } + } + return nil +} + +// Like WriteUnifiedDiff but returns the diff a string. +func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteUnifiedDiff(w, diff) + return string(w.Bytes()), err +} + +// Convert range to the "ed" format. +func formatRangeContext(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + if length <= 1 { + return fmt.Sprintf("%d", beginning) + } + return fmt.Sprintf("%d,%d", beginning, beginning+length-1) +} + +type ContextDiff UnifiedDiff + +// Compare two sequences of lines; generate the delta as a context diff. +// +// Context diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by diff.Context +// which defaults to three. +// +// By default, the diff control lines (those with *** or ---) are +// created with a trailing newline. +// +// For inputs that do not have trailing newlines, set the diff.Eol +// argument to "" so that the output will be uniformly newline free. +// +// The context diff format normally has a header for filenames and +// modification times. Any or all of these may be specified using +// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. +// The modification times are normally expressed in the ISO 8601 format. +// If not specified, the strings default to blanks. +func WriteContextDiff(writer io.Writer, diff ContextDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + var diffErr error + wf := func(format string, args ...interface{}) { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + if diffErr == nil && err != nil { + diffErr = err + } + } + ws := func(s string) { + _, err := buf.WriteString(s) + if diffErr == nil && err != nil { + diffErr = err + } + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + prefix := map[byte]string{ + 'i': "+ ", + 'd': "- ", + 'r': "! ", + 'e': " ", + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) + wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) + } + } + + first, last := g[0], g[len(g)-1] + ws("***************" + diff.Eol) + + range1 := formatRangeContext(first.I1, last.I2) + wf("*** %s ****%s", range1, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'd' { + for _, cc := range g { + if cc.Tag == 'i' { + continue + } + for _, line := range diff.A[cc.I1:cc.I2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + + range2 := formatRangeContext(first.J1, last.J2) + wf("--- %s ----%s", range2, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'i' { + for _, cc := range g { + if cc.Tag == 'd' { + continue + } + for _, line := range diff.B[cc.J1:cc.J2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + } + return diffErr +} + +// Like WriteContextDiff but returns the diff a string. +func GetContextDiffString(diff ContextDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteContextDiff(w, diff) + return string(w.Bytes()), err +} + +// Split a string on "\n" while preserving them. The output can be used +// as input for UnifiedDiff and ContextDiff structures. +func SplitLines(s string) []string { + lines := strings.SplitAfter(s, "\n") + lines[len(lines)-1] += "\n" + return lines +} diff --git a/vendor/github.com/ryancurrah/gomodguard/.dockerignore b/vendor/github.com/ryancurrah/gomodguard/.dockerignore new file mode 100644 index 000000000..77738287f --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/.dockerignore @@ -0,0 +1 @@ +dist/ \ No newline at end of file diff --git a/vendor/github.com/ryancurrah/gomodguard/.gitignore b/vendor/github.com/ryancurrah/gomodguard/.gitignore new file mode 100644 index 000000000..5131b46d6 --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/.gitignore @@ -0,0 +1,21 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +/gomodguard + +*.xml + +dist/ diff --git a/vendor/github.com/ryancurrah/gomodguard/.gomodguard.yaml b/vendor/github.com/ryancurrah/gomodguard/.gomodguard.yaml new file mode 100644 index 000000000..c0f061f59 --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/.gomodguard.yaml @@ -0,0 +1,18 @@ +allowed: + modules: # List of allowed modules + - gopkg.in/yaml.v2 + - github.com/go-xmlfmt/xmlfmt + - github.com/phayes/checkstyle + domains: # List of allowed module domains + - golang.org + +blocked: + modules: # List of blocked modules + - github.com/uudashr/go-module: # Blocked module + recommendations: # Recommended modules that should be used instead (Optional) + - golang.org/x/mod + reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional) + - github.com/mitchellh/go-homedir: + recommendations: + - github.com/ryancurrah/gomodguard + reason: "testing if the linted module is not blocked when it is recommended" diff --git a/vendor/github.com/ryancurrah/gomodguard/.goreleaser.yml b/vendor/github.com/ryancurrah/gomodguard/.goreleaser.yml new file mode 100644 index 000000000..20d834992 --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/.goreleaser.yml @@ -0,0 +1,31 @@ +builds: +- main: ./cmd/gomodguard/main.go + env: + - CGO_ENABLED=0 +archives: +- replacements: + darwin: Darwin + linux: Linux + windows: Windows + 386: i386 + amd64: x86_64 +checksum: + name_template: 'checksums.txt' +dockers: +- goos: linux + goarch: amd64 + binaries: + - gomodguard + image_templates: + - "ryancurrah/gomodguard:latest" + - "ryancurrah/gomodguard:{{.Tag}}" + skip_push: false + dockerfile: Dockerfile.goreleaser + build_flag_templates: + - "--pull" + - "--build-arg=gomodguard_VERSION={{.Version}}" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.name={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--label=org.opencontainers.image.source={{.GitURL}}" diff --git a/vendor/github.com/ryancurrah/gomodguard/Dockerfile b/vendor/github.com/ryancurrah/gomodguard/Dockerfile new file mode 100644 index 000000000..719a0ebdb --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/Dockerfile @@ -0,0 +1,17 @@ +ARG GO_VERSION=1.14.2 +ARG ALPINE_VERSION=3.11 +ARG gomodguard_VERSION= + +# ---- Build container +FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS builder +WORKDIR /gomodguard +COPY . . +RUN apk add --no-cache git +RUN go build -o gomodguard cmd/gomodguard/main.go + +# ---- App container +FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} +WORKDIR / +RUN apk --no-cache add ca-certificates +COPY --from=builder gomodguard/gomodguard / +ENTRYPOINT ./gomodguard diff --git a/vendor/github.com/ryancurrah/gomodguard/Dockerfile.goreleaser b/vendor/github.com/ryancurrah/gomodguard/Dockerfile.goreleaser new file mode 100644 index 000000000..57a042a67 --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/Dockerfile.goreleaser @@ -0,0 +1,10 @@ +ARG GO_VERSION=1.14.2 +ARG ALPINE_VERSION=3.11 +ARG gomodguard_VERSION= + +# ---- App container +FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} +WORKDIR / +RUN apk --no-cache add ca-certificates +COPY gomodguard /gomodguard +ENTRYPOINT ./gomodguard diff --git a/vendor/github.com/ryancurrah/gomodguard/LICENSE b/vendor/github.com/ryancurrah/gomodguard/LICENSE new file mode 100644 index 000000000..acd8a81e1 --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Ryan Currah + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/ryancurrah/gomodguard/Makefile b/vendor/github.com/ryancurrah/gomodguard/Makefile new file mode 100644 index 000000000..d765f52d5 --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/Makefile @@ -0,0 +1,37 @@ +current_dir = $(shell pwd) +version = $(shell printf '%s' $$(cat VERSION)) + +.PHONEY: lint +lint: + golangci-lint run -v --enable-all --disable funlen,gochecknoglobals,lll ./... + +.PHONEY: build +build: + go build -o gomodguard cmd/gomodguard/main.go + +.PHONEY: dockerbuild +dockerbuild: + docker build --build-arg GOMODGUARD_VERSION=${version} --tag ryancurrah/gomodguard:${version} . + +.PHONEY: run +run: build + ./gomodguard + +.PHONEY: dockerrun +dockerrun: dockerbuild + docker run -v "${current_dir}/.gomodguard.yaml:/.gomodguard.yaml" ryancurrah/gomodguard:latest + +.PHONEY: release +release: + git tag ${version} + git push --tags + goreleaser --skip-validate --rm-dist + +.PHONEY: clean +clean: + rm -rf dist/ + rm -f gomodguard + +.PHONEY: install-tools-mac +install-tools-mac: + brew install goreleaser/tap/goreleaser diff --git a/vendor/github.com/ryancurrah/gomodguard/README.md b/vendor/github.com/ryancurrah/gomodguard/README.md new file mode 100644 index 000000000..89a2398be --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/README.md @@ -0,0 +1,114 @@ +# gomodguard + + + +Allow and block list linter for direct Go module dependencies. This is useful for organizations where they want to standardize on the modules used and be able to recommend alternative modules. + +## Description + +Allowed and blocked modules are defined in a `.gomodguard.yaml` or `~/.gomodguard.yaml` file. + +Modules can be allowed by module or domain name. When allowed modules are specified any modules not in the allowed configuration are blocked. + +If no allowed modules or domains are specified then all modules are allowed except for blocked ones. + +The linter looks for blocked modules in `go.mod` and searches for imported packages where the imported packages module is blocked. Indirect modules are not considered. + +Alternative modules can be optionally recommended in the blocked modules list. + +If the linted module imports a blocked module but the linted module is in the recommended modules list the blocked module is ignored. Usually, this means the linted module wraps that blocked module for use by other modules, therefore the import of the blocked module should not be blocked. + +Results are printed to `stdout`. + +Logging statements are printed to `stderr`. + +Results can be exported to different report formats. Which can be imported into CI tools. See the help section for more information. + +## Configuration + +```yaml +allowed: + modules: # List of allowed modules + - gopkg.in/yaml.v2 + - github.com/go-xmlfmt/xmlfmt + - github.com/phayes/checkstyle + - github.com/mitchellh/go-homedir + domains: # List of allowed module domains + - golang.org + +blocked: + modules: # List of blocked modules + - github.com/uudashr/go-module: # Blocked module + recommendations: # Recommended modules that should be used instead (Optional) + - golang.org/x/mod + reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional) +``` + +## Usage + +``` +╰─ ./gomodguard -h +Usage: gomodguard [files...] +Also supports package syntax but will use it in relative path, i.e. ./pkg/... +Flags: + -f string + Report results to the specified file. A report type must also be specified + -file string + + -h Show this help text + -help + + -n Don't lint test files + -no-test + + -r string + Report results to one of the following formats: checkstyle. A report file destination must also be specified + -report string +``` + +## Example + +``` +╰─ ./gomodguard -r checkstyle -f gomodguard-checkstyle.xml ./... + +info: allowed modules, [gopkg.in/yaml.v2 github.com/go-xmlfmt/xmlfmt github.com/phayes/checkstyle github.com/mitchellh/go-homedir] +info: allowed module domains, [golang.org] +info: blocked modules, [github.com/uudashr/go-module] +info: found `2` blocked modules in the go.mod file, [github.com/gofrs/uuid github.com/uudashr/go-module] +blocked_example.go:6: import of package `github.com/gofrs/uuid` is blocked because the module is not in the allowed modules list. +blocked_example.go:7: import of package `github.com/uudashr/go-module` is blocked because the module is in the blocked modules list. `golang.org/x/mod` is a recommended module. `mod` is the official go.mod parser library. +``` + +Resulting checkstyle file + +``` +╰─ cat gomodguard-checkstyle.xml + + + + + + + + + + +``` + +## Install + +``` +go get -u github.com/ryancurrah/gomodguard/cmd/gomodguard +``` + +## Develop + +``` +git clone https://github.com/ryancurrah/gomodguard.git && cd gomodguard + +go build -o gomodguard cmd/gomodguard/main.go +``` + +## License + +**MIT** diff --git a/vendor/github.com/ryancurrah/gomodguard/VERSION b/vendor/github.com/ryancurrah/gomodguard/VERSION new file mode 100644 index 000000000..3e7bcf08c --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/VERSION @@ -0,0 +1 @@ +v1.0.4 diff --git a/vendor/github.com/ryancurrah/gomodguard/go.mod b/vendor/github.com/ryancurrah/gomodguard/go.mod new file mode 100644 index 000000000..0f0e92e4e --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/go.mod @@ -0,0 +1,11 @@ +module github.com/ryancurrah/gomodguard + +go 1.14 + +require ( + github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b + github.com/mitchellh/go-homedir v1.1.0 + github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d + golang.org/x/mod v0.2.0 + gopkg.in/yaml.v2 v2.2.8 +) diff --git a/vendor/github.com/ryancurrah/gomodguard/go.sum b/vendor/github.com/ryancurrah/gomodguard/go.sum new file mode 100644 index 000000000..0f4bf3231 --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/go.sum @@ -0,0 +1,24 @@ +github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo= +github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/ryancurrah/gomodguard/gomodguard.go b/vendor/github.com/ryancurrah/gomodguard/gomodguard.go new file mode 100644 index 000000000..cd4f7d66e --- /dev/null +++ b/vendor/github.com/ryancurrah/gomodguard/gomodguard.go @@ -0,0 +1,403 @@ +package gomodguard + +import ( + "bytes" + "encoding/json" + "fmt" + "go/parser" + "go/token" + "io/ioutil" + "log" + "os" + "os/exec" + "strings" + + "golang.org/x/mod/modfile" +) + +var ( + blockedReasonNotInAllowedList = "import of package `%s` is blocked because the module is not in the allowed modules list." + blockedReasonInBlockedList = "import of package `%s` is blocked because the module is in the blocked modules list." + goModFilename = "go.mod" +) + +// Recommendations are alternative modules to use and a reason why. +type Recommendations struct { + Recommendations []string `yaml:"recommendations"` + Reason string `yaml:"reason"` +} + +// IsRecommended returns true if the package provided is in the Recommendations list +func (r *Recommendations) IsRecommended(pkg string) bool { + for n := range r.Recommendations { + if strings.TrimSpace(pkg) == strings.TrimSpace(r.Recommendations[n]) { + return true + } + } + + return false +} + +// String returns the recommended modules and reason message. +func (r *Recommendations) String() string { + msg := "" + + if r == nil { + return msg + } + + for i := range r.Recommendations { + switch { + case len(r.Recommendations) == 1: + msg += fmt.Sprintf("`%s` is a recommended module.", r.Recommendations[i]) + case (i+1) != len(r.Recommendations) && (i+1) == (len(r.Recommendations)-1): + msg += fmt.Sprintf("`%s` ", r.Recommendations[i]) + case (i + 1) != len(r.Recommendations): + msg += fmt.Sprintf("`%s`, ", r.Recommendations[i]) + default: + msg += fmt.Sprintf("and `%s` are recommended modules.", r.Recommendations[i]) + } + } + + if r.Reason != "" { + msg += fmt.Sprintf(" %s", r.Reason) + } + + return msg +} + +// HasRecommendations returns true if the blocked package has +// recommended modules. +func (r *Recommendations) HasRecommendations() bool { + return len(r.Recommendations) > 0 +} + +// BlockedModule is a blocked module name and +// optionally a list of recommended modules +// and a reason message. +type BlockedModule map[string]Recommendations + +// BlockedModules a list of blocked modules. +type BlockedModules []BlockedModule + +// Get returns the modules that are blocked. +func (b BlockedModules) Get() []string { + modules := make([]string, len(b)) + + for i := range b { + for module := range b[i] { + modules[i] = module + break + } + } + + return modules +} + +// RecommendedModules will return a list of recommended modules for the +// package provided. If there is no recommendation nil will be returned. +func (b BlockedModules) RecommendedModules(pkg string) *Recommendations { + for i := range b { + for blockedModule, recommendations := range b[i] { + if strings.HasPrefix(strings.ToLower(pkg), strings.ToLower(blockedModule)) && recommendations.HasRecommendations() { + return &recommendations + } + + break + } + } + + return nil +} + +// IsBlockedPackage returns true if the package name is in +// the blocked modules list. +func (b BlockedModules) IsBlockedPackage(pkg string) bool { + blockedModules := b.Get() + for i := range blockedModules { + if strings.HasPrefix(strings.ToLower(pkg), strings.ToLower(blockedModules[i])) { + return true + } + } + + return false +} + +// IsBlockedModule returns true if the given module name is in the +// blocked modules list. +func (b BlockedModules) IsBlockedModule(module string) bool { + blockedModules := b.Get() + for i := range blockedModules { + if strings.EqualFold(module, strings.TrimSpace(blockedModules[i])) { + return true + } + } + + return false +} + +// Allowed is a list of modules and module +// domains that are allowed to be used. +type Allowed struct { + Modules []string `yaml:"modules"` + Domains []string `yaml:"domains"` +} + +// IsAllowedModule returns true if the given module +// name is in the allowed modules list. +func (a *Allowed) IsAllowedModule(module string) bool { + allowedModules := a.Modules + for i := range allowedModules { + if strings.EqualFold(module, strings.TrimSpace(allowedModules[i])) { + return true + } + } + + return false +} + +// IsAllowedModuleDomain returns true if the given modules domain is +// in the allowed module domains list. +func (a *Allowed) IsAllowedModuleDomain(module string) bool { + allowedDomains := a.Domains + for i := range allowedDomains { + if strings.HasPrefix(strings.ToLower(module), strings.TrimSpace(strings.ToLower(allowedDomains[i]))) { + return true + } + } + + return false +} + +// Blocked is a list of modules that are +// blocked and not to be used. +type Blocked struct { + Modules BlockedModules `yaml:"modules"` +} + +// Configuration of gomodguard allow and block lists. +type Configuration struct { + Allowed Allowed `yaml:"allowed"` + Blocked Blocked `yaml:"blocked"` +} + +// Result represents the result of one error. +type Result struct { + FileName string + LineNumber int + Position token.Position + Reason string +} + +// String returns the filename, line +// number and reason of a Result. +func (r *Result) String() string { + return fmt.Sprintf("%s:%d: %s", r.FileName, r.LineNumber, r.Reason) +} + +// Processor processes Go files. +type Processor struct { + config Configuration + logger *log.Logger + modfile *modfile.File + blockedModulesFromModFile []string + result []Result +} + +// NewProcessor will create a Processor to lint blocked packages. +func NewProcessor(config Configuration, logger *log.Logger) (*Processor, error) { + goModFileBytes, err := loadGoModFile() + if err != nil { + errMsg := fmt.Sprintf("unable to read %s file: %s", goModFilename, err) + + return nil, fmt.Errorf(errMsg) + } + + mfile, err := modfile.Parse(goModFilename, goModFileBytes, nil) + if err != nil { + errMsg := fmt.Sprintf("unable to parse %s file: %s", goModFilename, err) + + return nil, fmt.Errorf(errMsg) + } + + logger.Printf("info: allowed modules, %+v", config.Allowed.Modules) + logger.Printf("info: allowed module domains, %+v", config.Allowed.Domains) + logger.Printf("info: blocked modules, %+v", config.Blocked.Modules.Get()) + + p := &Processor{ + config: config, + logger: logger, + modfile: mfile, + result: []Result{}, + } + + p.setBlockedModulesFromModFile() + + return p, nil +} + +// ProcessFiles takes a string slice with file names (full paths) +// and lints them. +func (p *Processor) ProcessFiles(filenames []string) []Result { + pluralModuleMsg := "s" + if len(p.blockedModulesFromModFile) == 1 { + pluralModuleMsg = "" + } + + p.logger.Printf("info: found `%d` blocked module%s in the %s file, %+v", + len(p.blockedModulesFromModFile), pluralModuleMsg, goModFilename, p.blockedModulesFromModFile) + + for _, filename := range filenames { + data, err := ioutil.ReadFile(filename) + if err != nil { + p.result = append(p.result, Result{ + FileName: filename, + LineNumber: 0, + Reason: fmt.Sprintf("unable to read file, file cannot be linted (%s)", err.Error()), + }) + } + + p.process(filename, data) + } + + return p.result +} + +// process file imports and add lint error if blocked package is imported. +func (p *Processor) process(filename string, data []byte) { + fileSet := token.NewFileSet() + + file, err := parser.ParseFile(fileSet, filename, data, parser.ParseComments) + if err != nil { + p.result = append(p.result, Result{ + FileName: filename, + LineNumber: 0, + Reason: fmt.Sprintf("invalid syntax, file cannot be linted (%s)", err.Error()), + }) + + return + } + + imports := file.Imports + for i := range imports { + importedPkg := strings.TrimSpace(strings.Trim(imports[i].Path.Value, "\"")) + if p.isBlockedPackageFromModFile(importedPkg) { + reason := "" + + if p.config.Blocked.Modules.IsBlockedPackage(importedPkg) { + reason = fmt.Sprintf(blockedReasonInBlockedList, importedPkg) + } else { + reason = fmt.Sprintf(blockedReasonNotInAllowedList, importedPkg) + } + + recommendedModules := p.config.Blocked.Modules.RecommendedModules(importedPkg) + if recommendedModules != nil { + reason += fmt.Sprintf(" %s", recommendedModules.String()) + } + + p.addError(fileSet, imports[i].Pos(), reason) + } + } +} + +// addError adds an error for the file and line number for the current token.Pos +// with the given reason. +func (p *Processor) addError(fileset *token.FileSet, pos token.Pos, reason string) { + position := fileset.Position(pos) + + p.result = append(p.result, Result{ + FileName: position.Filename, + LineNumber: position.Line, + Position: position, + Reason: reason, + }) +} + +// setBlockedModules determines which modules are blocked by reading +// the go.mod file and comparing the require modules to the allowed modules. +func (p *Processor) setBlockedModulesFromModFile() { + blockedModules := make([]string, 0, len(p.modfile.Require)) + requiredModules := p.modfile.Require + lintedModule := p.modfile.Module.Mod.Path + + for i := range requiredModules { + if !requiredModules[i].Indirect { + requiredModule := strings.TrimSpace(requiredModules[i].Mod.Path) + + if p.config.Allowed.IsAllowedModuleDomain(requiredModule) { + continue + } + + if p.config.Allowed.IsAllowedModule(requiredModule) { + continue + } + + requiredModuleIsBlocked := p.config.Blocked.Modules.IsBlockedModule(requiredModule) + + if len(p.config.Allowed.Modules) == 0 && + len(p.config.Allowed.Domains) == 0 && + !requiredModuleIsBlocked { + continue + } + + // If the go.mod file being linted is a recommended module of a blocked module + // and it imports that blocked module, do not set as a blocked. This means + // that the linted module wraps that blocked module + if requiredModuleIsBlocked { + recommendedModules := p.config.Blocked.Modules.RecommendedModules(requiredModule) + + if recommendedModules.IsRecommended(lintedModule) { + continue + } + } + + blockedModules = append(blockedModules, requiredModule) + } + } + + if len(blockedModules) > 0 { + p.blockedModulesFromModFile = blockedModules + } +} + +// isBlockedPackageFromModFile returns true if the imported packages +// module is in the go.mod file and was blocked. +func (p *Processor) isBlockedPackageFromModFile(pkg string) bool { + blockedModulesFromModFile := p.blockedModulesFromModFile + for i := range blockedModulesFromModFile { + if strings.HasPrefix(strings.ToLower(pkg), strings.ToLower(blockedModulesFromModFile[i])) { + return true + } + } + + return false +} + +func loadGoModFile() ([]byte, error) { + cmd := exec.Command("go", "env", "-json") + stdout, _ := cmd.StdoutPipe() + _ = cmd.Start() + + if stdout == nil { + return ioutil.ReadFile(goModFilename) + } + + buf := new(bytes.Buffer) + _, _ = buf.ReadFrom(stdout) + + goEnv := make(map[string]string) + err := json.Unmarshal(buf.Bytes(), &goEnv) + if err != nil { + return ioutil.ReadFile(goModFilename) + } + + if _, ok := goEnv["GOMOD"]; !ok { + return ioutil.ReadFile(goModFilename) + } + + if _, err := os.Stat(goEnv["GOMOD"]); os.IsNotExist(err) { + return ioutil.ReadFile(goModFilename) + } + + return ioutil.ReadFile(goEnv["GOMOD"]) +} diff --git a/vendor/github.com/securego/gosec/v2/.gitignore b/vendor/github.com/securego/gosec/v2/.gitignore new file mode 100644 index 000000000..f282cda24 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/.gitignore @@ -0,0 +1,35 @@ +# transient files +/image + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so +*.swp +/gosec + +# Folders +_obj +_test +vendor +dist + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +.DS_Store + +.vscode diff --git a/vendor/github.com/securego/gosec/v2/.goreleaser.yml b/vendor/github.com/securego/gosec/v2/.goreleaser.yml new file mode 100644 index 000000000..4f8fc4128 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/.goreleaser.yml @@ -0,0 +1,20 @@ +--- +project_name: gosec + +release: + github: + owner: securego + name: gosec + +builds: + - main : ./cmd/gosec/ + binary: gosec + goos: + - darwin + - linux + - windows + goarch: + - amd64 + ldflags: -X main.Version={{.Version}} -X main.GitTag={{.Tag}} -X main.BuildDate={{.Date}} + env: + - CGO_ENABLED=0 diff --git a/vendor/github.com/securego/gosec/v2/Dockerfile b/vendor/github.com/securego/gosec/v2/Dockerfile new file mode 100644 index 000000000..a874697e9 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/Dockerfile @@ -0,0 +1,14 @@ +ARG GO_VERSION +FROM golang:${GO_VERSION}-alpine AS builder +RUN apk add --update --no-cache ca-certificates make git curl gcc libc-dev +RUN mkdir -p /build +WORKDIR /build +COPY . /build/ +RUN go mod download +RUN make build-linux + +FROM golang:${GO_VERSION}-alpine +RUN apk add --update --no-cache ca-certificates git gcc libc-dev +ENV GO111MODULE on +COPY --from=builder /build/gosec /bin/gosec +ENTRYPOINT ["/bin/gosec"] diff --git a/vendor/github.com/securego/gosec/v2/LICENSE.txt b/vendor/github.com/securego/gosec/v2/LICENSE.txt new file mode 100644 index 000000000..1756c7821 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/LICENSE.txt @@ -0,0 +1,154 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable copyright license to +reproduce, prepare Derivative Works of, publicly display, publicly perform, +sublicense, and distribute the Work and such Derivative Works in Source or +Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, +each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) patent +license to make, have made, use, offer to sell, sell, import, and otherwise +transfer the Work, where such license applies only to those patent claims +licensable by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) with the Work +to which such Contribution(s) was submitted. If You institute patent litigation +against any entity (including a cross-claim or counterclaim in a lawsuit) +alleging that the Work or a Contribution incorporated within the Work +constitutes direct or contributory patent infringement, then any patent licenses +granted to You under this License for that Work shall terminate as of the date +such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, and in +Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and You must cause any modified files to carry prominent notices +stating that You changed the files; and You must retain, in the Source form of +any Derivative Works that You distribute, all copyright, patent, trademark, and +attribution notices from the Source form of the Work, excluding those notices +that do not pertain to any part of the Derivative Works; and If the Work +includes a "NOTICE" text file as part of its distribution, then any Derivative +Works that You distribute must include a readable copy of the attribution +notices contained within such NOTICE file, excluding those notices that do not +pertain to any part of the Derivative Works, in at least one of the following +places: within a NOTICE text file distributed as part of the Derivative Works; +within the Source form or documentation, if provided along with the Derivative +Works; or, within a display generated by the Derivative Works, if and wherever +such third-party notices normally appear. The contents of the NOTICE file are +for informational purposes only and do not modify the License. You may add Your +own attribution notices within Derivative Works that You distribute, alongside +or as an addendum to the NOTICE text from the Work, provided that such +additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. 5. Submission of Contributions. +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, +trademarks, service marks, or product names of the Licensor, except as required +for reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in +writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any warranties +or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any risks +associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in +tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to in +writing, shall any Contributor be liable to You for damages, including any +direct, indirect, special, incidental, or consequential damages of any character +arising as a result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, work stoppage, +computer failure or malfunction, or any and all other commercial damages or +losses), even if such Contributor has been advised of the possibility of such +damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or +Derivative Works thereof, You may choose to offer, and charge a fee for, +acceptance of support, warranty, indemnity, or other liability obligations +and/or rights consistent with this License. However, in accepting such +obligations, You may act only on Your own behalf and on Your sole +responsibility, not on behalf of any other Contributor, and only if You agree to +indemnify, defend, and hold each Contributor harmless for any liability incurred +by, or claims asserted against, such Contributor by reason of your accepting any +such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/vendor/github.com/securego/gosec/v2/Makefile b/vendor/github.com/securego/gosec/v2/Makefile new file mode 100644 index 000000000..217651c43 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/Makefile @@ -0,0 +1,71 @@ +GIT_TAG?= $(shell git describe --always --tags) +BIN = gosec +FMT_CMD = $(gofmt -s -l -w $(find . -type f -name '*.go' -not -path './vendor/*') | tee /dev/stderr) +IMAGE_REPO = securego +BUILDFLAGS := '-w -s' +CGO_ENABLED = 0 +GO := GO111MODULE=on go +GO_NOMOD :=GO111MODULE=off go +GOPATH ?= $(shell $(GO) env GOPATH) +GOBIN ?= $(GOPATH)/bin +GOLINT ?= $(GOBIN)/golint +GOSEC ?= $(GOBIN)/gosec +GINKGO ?= $(GOBIN)/ginkgo +GO_VERSION = 1.14 + +default: + $(MAKE) build + +install-test-deps: + $(GO_NOMOD) get -u github.com/onsi/ginkgo/ginkgo + $(GO_NOMOD) get -u golang.org/x/crypto/ssh + $(GO_NOMOD) get -u github.com/lib/pq + +test: install-test-deps build fmt lint sec + $(GINKGO) -r -v + +fmt: + @echo "FORMATTING" + @FORMATTED=`$(GO) fmt ./...` + @([[ ! -z "$(FORMATTED)" ]] && printf "Fixed unformatted files:\n$(FORMATTED)") || true + +lint: + @echo "LINTING" + $(GO_NOMOD) get -u golang.org/x/lint/golint + $(GOLINT) -set_exit_status ./... + @echo "VETTING" + $(GO) vet ./... + +sec: + @echo "SECURITY SCANNING" + ./$(BIN) ./... + +test-coverage: install-test-deps + go test -race -coverprofile=coverage.txt -covermode=atomic + +build: + go build -o $(BIN) ./cmd/gosec/ + +clean: + rm -rf build vendor dist coverage.txt + rm -f release image $(BIN) + +release: + @echo "Releasing the gosec binary..." + goreleaser release + +build-linux: + CGO_ENABLED=$(CGO_ENABLED) GOOS=linux GOARCH=amd64 go build -ldflags $(BUILDFLAGS) -o $(BIN) ./cmd/gosec/ + +image: + @echo "Building the Docker image..." + docker build -t $(IMAGE_REPO)/$(BIN):$(GIT_TAG) --build-arg GO_VERSION=$(GO_VERSION) . + docker tag $(IMAGE_REPO)/$(BIN):$(GIT_TAG) $(IMAGE_REPO)/$(BIN):latest + touch image + +image-push: image + @echo "Pushing the Docker image..." + docker push $(IMAGE_REPO)/$(BIN):$(GIT_TAG) + docker push $(IMAGE_REPO)/$(BIN):latest + +.PHONY: test build clean release image image-push diff --git a/vendor/github.com/securego/gosec/v2/README.md b/vendor/github.com/securego/gosec/v2/README.md new file mode 100644 index 000000000..52be73423 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/README.md @@ -0,0 +1,326 @@ + +# gosec - Golang Security Checker + +Inspects source code for security problems by scanning the Go AST. + + + +## License + +Licensed under the Apache License, Version 2.0 (the "License"). +You may not use this file except in compliance with the License. +You may obtain a copy of the License [here](http://www.apache.org/licenses/LICENSE-2.0). + +## Project status + +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3218/badge)](https://bestpractices.coreinfrastructure.org/projects/3218) +[![Build Status](https://github.com/securego/gosec/workflows/CI/badge.svg)](https://github.com/securego/gosec/actions?query=workflows%3ACI) +[![Coverage Status](https://codecov.io/gh/securego/gosec/branch/master/graph/badge.svg)](https://codecov.io/gh/securego/gosec) +[![GoReport](https://goreportcard.com/badge/github.com/securego/gosec)](https://goreportcard.com/badge/github.com/securego/gosec) +[![GoDoc](https://godoc.org/github.com/securego/gosec?status.svg)](https://godoc.org/github.com/securego/gosec) +[![Docs](https://readthedocs.org/projects/docs/badge/?version=latest)](https://securego.io/) +[![Downloads](https://img.shields.io/github/downloads/securego/gosec/total.svg)](https://github.com/securego/gosec/releases) +[![Docker Pulls](https://img.shields.io/docker/pulls/securego/gosec.svg)](https://hub.docker.com/r/securego/gosec/tags) +[![Slack](http://securego.herokuapp.com/badge.svg)](http://securego.herokuapp.com) + +## Install + +### CI Installation + +```bash +# binary will be $GOPATH/bin/gosec +curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $GOPATH/bin vX.Y.Z + +# or install it into ./bin/ +curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s vX.Y.Z + +# In alpine linux (as it does not come with curl by default) +wget -O - -q https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s vX.Y.Z + +# If you want to use the checksums provided on the "Releases" page +# then you will have to download a tar.gz file for your operating system instead of a binary file +wget https://github.com/securego/gosec/releases/download/vX.Y.Z/gosec_vX.Y.Z_OS.tar.gz + +# The file will be in the current folder where you run the command +# and you can check the checksum like this +echo " gosec_vX.Y.Z_OS.tar.gz" | sha256sum -c - + +gosec --help +``` +### GitHub Action + +You can run `gosec` as a GitHub action as follows: + +```yaml +name: Run Gosec +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + tests: + runs-on: ubuntu-latest + env: + GO111MODULE: on + steps: + - name: Checkout Source + uses: actions/checkout@v2 + - name: Run Gosec Security Scanner + uses: securego/gosec@master + with: + args: ./... +``` + +### Local Installation + +```bash +go get github.com/securego/gosec/cmd/gosec +``` + +## Usage + +Gosec can be configured to only run a subset of rules, to exclude certain file +paths, and produce reports in different formats. By default all rules will be +run against the supplied input files. To recursively scan from the current +directory you can supply `./...` as the input argument. + + +### Available rules + +- G101: Look for hard coded credentials +- G102: Bind to all interfaces +- G103: Audit the use of unsafe block +- G104: Audit errors not checked +- G106: Audit the use of ssh.InsecureIgnoreHostKey +- G107: Url provided to HTTP request as taint input +- G108: Profiling endpoint automatically exposed on /debug/pprof +- G109: Potential Integer overflow made by strconv.Atoi result conversion to int16/32 +- G110: Potential DoS vulnerability via decompression bomb +- G201: SQL query construction using format string +- G202: SQL query construction using string concatenation +- G203: Use of unescaped data in HTML templates +- G204: Audit use of command execution +- G301: Poor file permissions used when creating a directory +- G302: Poor file permissions used with chmod +- G303: Creating tempfile using a predictable path +- G304: File path provided as taint input +- G305: File traversal when extracting zip archive +- G306: Poor file permissions used when writing to a new file +- G307: Deferring a method which returns an error +- G401: Detect the usage of DES, RC4, MD5 or SHA1 +- G402: Look for bad TLS connection settings +- G403: Ensure minimum RSA key length of 2048 bits +- G404: Insecure random number source (rand) +- G501: Import blacklist: crypto/md5 +- G502: Import blacklist: crypto/des +- G503: Import blacklist: crypto/rc4 +- G504: Import blacklist: net/http/cgi +- G505: Import blacklist: crypto/sha1 +- G601: Implicit memory aliasing of items from a range statement + +### Retired rules + +- G105: Audit the use of math/big.Int.Exp - [CVE is fixed](https://github.com/golang/go/issues/15184) + +### Selecting rules + +By default, gosec will run all rules against the supplied file paths. It is however possible to select a subset of rules to run via the `-include=` flag, +or to specify a set of rules to explicitly exclude using the `-exclude=` flag. + +```bash +# Run a specific set of rules +$ gosec -include=G101,G203,G401 ./... + +# Run everything except for rule G303 +$ gosec -exclude=G303 ./... +``` +### CWE Mapping + +Every issue detected by `gosec` is mapped to a [CWE (Common Weakness Enumeration)](http://cwe.mitre.org/data/index.html) which describes in more generic terms the vulnerability. The exact mapping can be found [here](https://github.com/securego/gosec/blob/53be8dd8644ee48802114178cff6eb7e29757414/issue.go#L49). + +### Configuration + +A number of global settings can be provided in a configuration file as follows: + +```JSON +{ + "global": { + "nosec": "enabled", + "audit": "enabled" + } +} +``` + +- `nosec`: this setting will overwrite all `#nosec` directives defined throughout the code base +- `audit`: runs in audit mode which enables addition checks that for normal code analysis might be too nosy + +```bash +# Run with a global configuration file +$ gosec -conf config.json . +``` +Also some rules accept configuration. For instance on rule `G104`, it is possible to define packages along with a list +of functions which will be skipped when auditing the not checked errors: + +```JSON +{ + "G104": { + "io/ioutil": ["WriteFile"] + } +} +``` + +You can also configure the hard-coded credentials rule `G101` with additional patters, or adjust the entropy threshold: + +```JSON +{ + "G101": { + "pattern": "(?i)passwd|pass|password|pwd|secret|private_key|token", + "ingnore_entropy": false, + "entropy_threshold": "80.0", + "per_char_threshold": "3.0", + "trucate": "32" + } +} +``` + +### Dependencies + +gosec will fetch automatically the dependencies of the code which is being analyzed when go module is turned on (e.g.` GO111MODULE=on`). If this is not the case, +the dependencies need to be explicitly downloaded by running the `go get -d` command before the scan. + +### Excluding test files and folders + +gosec will ignore test files across all packages and any dependencies in your vendor directory. + +The scanning of test files can be enabled with the following flag: + +```bash + +gosec -tests ./... +``` + +Also additional folders can be excluded as follows: + +```bash + gosec -exclude-dir=rules -exclude-dir=cmd ./... +``` + +### Annotating code + +As with all automated detection tools, there will be cases of false positives. In cases where gosec reports a failure that has been manually verified as being safe, +it is possible to annotate the code with a `#nosec` comment. + +The annotation causes gosec to stop processing any further nodes within the +AST so can apply to a whole block or more granularly to a single expression. + +```go + +import "md5" // #nosec + + +func main(){ + + /* #nosec */ + if x > y { + h := md5.New() // this will also be ignored + } + +} + +``` + +When a specific false positive has been identified and verified as safe, you may wish to suppress only that single rule (or a specific set of rules) +within a section of code, while continuing to scan for other problems. To do this, you can list the rule(s) to be suppressed within +the `#nosec` annotation, e.g: `/* #nosec G401 */` or `// #nosec G201 G202 G203` + +In some cases you may also want to revisit places where `#nosec` annotations +have been used. To run the scanner and ignore any `#nosec` annotations you +can do the following: + +```bash +gosec -nosec=true ./... +``` + +### Build tags + +gosec is able to pass your [Go build tags](https://golang.org/pkg/go/build/) to the analyzer. +They can be provided as a comma separated list as follows: + +```bash +gosec -tag debug,ignore ./... +``` + +### Output formats + +gosec currently supports `text`, `json`, `yaml`, `csv`, `sonarqube`, `JUnit XML`, `html` and `golint` output formats. By default +results will be reported to stdout, but can also be written to an output +file. The output format is controlled by the `-fmt` flag, and the output file is controlled by the `-out` flag as follows: + +```bash +# Write output in json format to results.json +$ gosec -fmt=json -out=results.json *.go +``` + +## Development + +### Build + +You can build the binary with: +```bash +make +``` + +### Tests + +You can run all unit tests using: +```bash +make test +``` + +### Release + +You can create a release by tagging the version as follows: + +``` bash +git tag v1.0.0 -m "Release version v1.0.0" +git push origin v1.0.0 +``` + +The GitHub [release workflow](.github/workflows/release.yml) triggers immediately after the tag is pushed upstream. This flow will +release the binaries using the [goreleaser](https://goreleaser.com/actions/) action and then it will build and publish the docker image into Docker Hub. + +### Docker image + +You can also build locally the docker image by using the command: + +```bash +make image +``` + +You can run the `gosec` tool in a container against your local Go project. You only have to mount the project +into a volume as follows: + +```bash +docker run -it -v /:/ securego/gosec //... +``` + +### Generate TLS rule + +The configuration of TLS rule can be generated from [Mozilla's TLS ciphers recommendation](https://statics.tls.security.mozilla.org/server-side-tls-conf.json). + +First you need to install the generator tool: + +```bash +go get github.com/securego/gosec/cmd/tlsconfig/... +``` + +You can invoke now the `go generate` in the root of the project: + +```bash +go generate ./... +``` + +This will generate the `rules/tls_config.go` file which will contain the current ciphers recommendation from Mozilla. diff --git a/vendor/github.com/securego/gosec/v2/action.yml b/vendor/github.com/securego/gosec/v2/action.yml new file mode 100644 index 000000000..aab6c8039 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/action.yml @@ -0,0 +1,19 @@ +name: 'Gosec Security Checker' +description: 'Runs the gosec security checker' +author: '@ccojocar' + +inputs: + args: + description: 'Arguments for gosec' + required: true + default: '-h' + +runs: + using: 'docker' + image: 'docker://securego/gosec' + args: + - ${{ inputs.args }} + +branding: + icon: 'shield' + color: 'blue' diff --git a/vendor/github.com/securego/gosec/v2/analyzer.go b/vendor/github.com/securego/gosec/v2/analyzer.go new file mode 100644 index 000000000..ca4440c20 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/analyzer.go @@ -0,0 +1,378 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package gosec holds the central scanning logic used by gosec security scanner +package gosec + +import ( + "fmt" + "go/ast" + "go/build" + "go/token" + "go/types" + "log" + "os" + "path" + "path/filepath" + "reflect" + "regexp" + "strconv" + + "strings" + + "golang.org/x/tools/go/packages" +) + +// LoadMode controls the amount of details to return when loading the packages +const LoadMode = packages.NeedName | + packages.NeedFiles | + packages.NeedCompiledGoFiles | + packages.NeedImports | + packages.NeedTypes | + packages.NeedTypesSizes | + packages.NeedTypesInfo | + packages.NeedSyntax + +// The Context is populated with data parsed from the source code as it is scanned. +// It is passed through to all rule functions as they are called. Rules may use +// this data in conjunction withe the encountered AST node. +type Context struct { + FileSet *token.FileSet + Comments ast.CommentMap + Info *types.Info + Pkg *types.Package + PkgFiles []*ast.File + Root *ast.File + Config Config + Imports *ImportTracker + Ignores []map[string]bool + PassedValues map[string]interface{} +} + +// Metrics used when reporting information about a scanning run. +type Metrics struct { + NumFiles int `json:"files"` + NumLines int `json:"lines"` + NumNosec int `json:"nosec"` + NumFound int `json:"found"` +} + +// Analyzer object is the main object of gosec. It has methods traverse an AST +// and invoke the correct checking rules as on each node as required. +type Analyzer struct { + ignoreNosec bool + ruleset RuleSet + context *Context + config Config + logger *log.Logger + issues []*Issue + stats *Metrics + errors map[string][]Error // keys are file paths; values are the golang errors in those files + tests bool +} + +// NewAnalyzer builds a new analyzer. +func NewAnalyzer(conf Config, tests bool, logger *log.Logger) *Analyzer { + ignoreNoSec := false + if enabled, err := conf.IsGlobalEnabled(Nosec); err == nil { + ignoreNoSec = enabled + } + if logger == nil { + logger = log.New(os.Stderr, "[gosec]", log.LstdFlags) + } + return &Analyzer{ + ignoreNosec: ignoreNoSec, + ruleset: make(RuleSet), + context: &Context{}, + config: conf, + logger: logger, + issues: make([]*Issue, 0, 16), + stats: &Metrics{}, + errors: make(map[string][]Error), + tests: tests, + } +} + +// SetConfig upates the analyzer configuration +func (gosec *Analyzer) SetConfig(conf Config) { + gosec.config = conf +} + +// Config returns the current configuration +func (gosec *Analyzer) Config() Config { + return gosec.config +} + +// LoadRules instantiates all the rules to be used when analyzing source +// packages +func (gosec *Analyzer) LoadRules(ruleDefinitions map[string]RuleBuilder) { + for id, def := range ruleDefinitions { + r, nodes := def(id, gosec.config) + gosec.ruleset.Register(r, nodes...) + } +} + +// Process kicks off the analysis process for a given package +func (gosec *Analyzer) Process(buildTags []string, packagePaths ...string) error { + config := gosec.pkgConfig(buildTags) + for _, pkgPath := range packagePaths { + pkgs, err := gosec.load(pkgPath, config) + if err != nil { + gosec.AppendError(pkgPath, err) + } + for _, pkg := range pkgs { + if pkg.Name != "" { + err := gosec.ParseErrors(pkg) + if err != nil { + return fmt.Errorf("parsing errors in pkg %q: %v", pkg.Name, err) + } + gosec.Check(pkg) + } + } + } + sortErrors(gosec.errors) + return nil +} + +func (gosec *Analyzer) pkgConfig(buildTags []string) *packages.Config { + flags := []string{} + if len(buildTags) > 0 { + tagsFlag := "-tags=" + strings.Join(buildTags, " ") + flags = append(flags, tagsFlag) + } + return &packages.Config{ + Mode: LoadMode, + BuildFlags: flags, + Tests: gosec.tests, + } +} + +func (gosec *Analyzer) load(pkgPath string, conf *packages.Config) ([]*packages.Package, error) { + abspath, err := GetPkgAbsPath(pkgPath) + if err != nil { + gosec.logger.Printf("Skipping: %s. Path doesn't exist.", abspath) + return []*packages.Package{}, nil + } + + gosec.logger.Println("Import directory:", abspath) + basePackage, err := build.Default.ImportDir(pkgPath, build.ImportComment) + if err != nil { + return []*packages.Package{}, fmt.Errorf("importing dir %q: %v", pkgPath, err) + } + + var packageFiles []string + for _, filename := range basePackage.GoFiles { + packageFiles = append(packageFiles, path.Join(pkgPath, filename)) + } + for _, filename := range basePackage.CgoFiles { + packageFiles = append(packageFiles, path.Join(pkgPath, filename)) + } + + if gosec.tests { + testsFiles := []string{} + testsFiles = append(testsFiles, basePackage.TestGoFiles...) + testsFiles = append(testsFiles, basePackage.XTestGoFiles...) + for _, filename := range testsFiles { + packageFiles = append(packageFiles, path.Join(pkgPath, filename)) + } + } + + pkgs, err := packages.Load(conf, packageFiles...) + if err != nil { + return []*packages.Package{}, fmt.Errorf("loading files from package %q: %v", pkgPath, err) + } + return pkgs, nil +} + +// Check runs analysis on the given package +func (gosec *Analyzer) Check(pkg *packages.Package) { + gosec.logger.Println("Checking package:", pkg.Name) + for _, file := range pkg.Syntax { + checkedFile := pkg.Fset.File(file.Pos()).Name() + // Skip the no-Go file from analysis (e.g. a Cgo files is expanded in 3 different files + // stored in the cache which do not need to by analyzed) + if filepath.Ext(checkedFile) != ".go" { + continue + } + gosec.logger.Println("Checking file:", checkedFile) + gosec.context.FileSet = pkg.Fset + gosec.context.Config = gosec.config + gosec.context.Comments = ast.NewCommentMap(gosec.context.FileSet, file, file.Comments) + gosec.context.Root = file + gosec.context.Info = pkg.TypesInfo + gosec.context.Pkg = pkg.Types + gosec.context.PkgFiles = pkg.Syntax + gosec.context.Imports = NewImportTracker() + gosec.context.Imports.TrackFile(file) + gosec.context.PassedValues = make(map[string]interface{}) + ast.Walk(gosec, file) + gosec.stats.NumFiles++ + gosec.stats.NumLines += pkg.Fset.File(file.Pos()).LineCount() + } +} + +// ParseErrors parses the errors from given package +func (gosec *Analyzer) ParseErrors(pkg *packages.Package) error { + if len(pkg.Errors) == 0 { + return nil + } + for _, pkgErr := range pkg.Errors { + parts := strings.Split(pkgErr.Pos, ":") + file := parts[0] + var err error + var line int + if len(parts) > 1 { + if line, err = strconv.Atoi(parts[1]); err != nil { + return fmt.Errorf("parsing line: %v", err) + } + } + var column int + if len(parts) > 2 { + if column, err = strconv.Atoi(parts[2]); err != nil { + return fmt.Errorf("parsing column: %v", err) + } + } + msg := strings.TrimSpace(pkgErr.Msg) + newErr := NewError(line, column, msg) + if errSlice, ok := gosec.errors[file]; ok { + gosec.errors[file] = append(errSlice, *newErr) + } else { + errSlice = []Error{} + gosec.errors[file] = append(errSlice, *newErr) + } + } + return nil +} + +// AppendError appends an error to the file errors +func (gosec *Analyzer) AppendError(file string, err error) { + // Do not report the error for empty packages (e.g. files excluded from build with a tag) + r := regexp.MustCompile(`no buildable Go source files in`) + if r.MatchString(err.Error()) { + return + } + errors := []Error{} + if ferrs, ok := gosec.errors[file]; ok { + errors = ferrs + } + ferr := NewError(0, 0, err.Error()) + errors = append(errors, *ferr) + gosec.errors[file] = errors +} + +// ignore a node (and sub-tree) if it is tagged with a nosec tag comment +func (gosec *Analyzer) ignore(n ast.Node) ([]string, bool) { + if groups, ok := gosec.context.Comments[n]; ok && !gosec.ignoreNosec { + + // Checks if an alternative for #nosec is set and, if not, uses the default. + noSecDefaultTag := "#nosec" + noSecAlternativeTag, err := gosec.config.GetGlobal(NoSecAlternative) + if err != nil { + noSecAlternativeTag = noSecDefaultTag + } + + for _, group := range groups { + + foundDefaultTag := strings.Contains(group.Text(), noSecDefaultTag) + foundAlternativeTag := strings.Contains(group.Text(), noSecAlternativeTag) + + if foundDefaultTag || foundAlternativeTag { + gosec.stats.NumNosec++ + + // Pull out the specific rules that are listed to be ignored. + re := regexp.MustCompile(`(G\d{3})`) + matches := re.FindAllStringSubmatch(group.Text(), -1) + + // If no specific rules were given, ignore everything. + if len(matches) == 0 { + return nil, true + } + + // Find the rule IDs to ignore. + var ignores []string + for _, v := range matches { + ignores = append(ignores, v[1]) + } + return ignores, false + } + } + } + return nil, false +} + +// Visit runs the gosec visitor logic over an AST created by parsing go code. +// Rule methods added with AddRule will be invoked as necessary. +func (gosec *Analyzer) Visit(n ast.Node) ast.Visitor { + // If we've reached the end of this branch, pop off the ignores stack. + if n == nil { + if len(gosec.context.Ignores) > 0 { + gosec.context.Ignores = gosec.context.Ignores[1:] + } + return gosec + } + + // Get any new rule exclusions. + ignoredRules, ignoreAll := gosec.ignore(n) + if ignoreAll { + return nil + } + + // Now create the union of exclusions. + ignores := map[string]bool{} + if len(gosec.context.Ignores) > 0 { + for k, v := range gosec.context.Ignores[0] { + ignores[k] = v + } + } + + for _, v := range ignoredRules { + ignores[v] = true + } + + // Push the new set onto the stack. + gosec.context.Ignores = append([]map[string]bool{ignores}, gosec.context.Ignores...) + + // Track aliased and initialization imports + gosec.context.Imports.TrackImport(n) + + for _, rule := range gosec.ruleset.RegisteredFor(n) { + if _, ok := ignores[rule.ID()]; ok { + continue + } + issue, err := rule.Match(n, gosec.context) + if err != nil { + file, line := GetLocation(n, gosec.context) + file = path.Base(file) + gosec.logger.Printf("Rule error: %v => %s (%s:%d)\n", reflect.TypeOf(rule), err, file, line) + } + if issue != nil { + gosec.issues = append(gosec.issues, issue) + gosec.stats.NumFound++ + } + } + return gosec +} + +// Report returns the current issues discovered and the metrics about the scan +func (gosec *Analyzer) Report() ([]*Issue, *Metrics, map[string][]Error) { + return gosec.issues, gosec.stats, gosec.errors +} + +// Reset clears state such as context, issues and metrics from the configured analyzer +func (gosec *Analyzer) Reset() { + gosec.context = &Context{} + gosec.issues = make([]*Issue, 0, 16) + gosec.stats = &Metrics{} + gosec.ruleset = NewRuleSet() +} diff --git a/vendor/github.com/securego/gosec/v2/call_list.go b/vendor/github.com/securego/gosec/v2/call_list.go new file mode 100644 index 000000000..115c6c88e --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/call_list.go @@ -0,0 +1,109 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gosec + +import ( + "go/ast" + "strings" +) + +const vendorPath = "vendor/" + +type set map[string]bool + +// CallList is used to check for usage of specific packages +// and functions. +type CallList map[string]set + +// NewCallList creates a new empty CallList +func NewCallList() CallList { + return make(CallList) +} + +// AddAll will add several calls to the call list at once +func (c CallList) AddAll(selector string, idents ...string) { + for _, ident := range idents { + c.Add(selector, ident) + } +} + +// Add a selector and call to the call list +func (c CallList) Add(selector, ident string) { + if _, ok := c[selector]; !ok { + c[selector] = make(set) + } + c[selector][ident] = true +} + +// Contains returns true if the package and function are +/// members of this call list. +func (c CallList) Contains(selector, ident string) bool { + if idents, ok := c[selector]; ok { + _, found := idents[ident] + return found + } + return false +} + +// ContainsPointer returns true if a pointer to the selector type or the type +// itself is a members of this call list. +func (c CallList) ContainsPointer(selector, indent string) bool { + if strings.HasPrefix(selector, "*") { + if c.Contains(selector, indent) { + return true + } + s := strings.TrimPrefix(selector, "*") + return c.Contains(s, indent) + } + return false +} + +// ContainsPkgCallExpr resolves the call expression name and type, and then further looks +// up the package path for that type. Finally, it determines if the call exists within the call list +func (c CallList) ContainsPkgCallExpr(n ast.Node, ctx *Context, stripVendor bool) *ast.CallExpr { + selector, ident, err := GetCallInfo(n, ctx) + if err != nil { + return nil + } + + // Use only explicit path (optionally strip vendor path prefix) to reduce conflicts + path, ok := GetImportPath(selector, ctx) + if !ok { + return nil + } + if stripVendor { + if vendorIdx := strings.Index(path, vendorPath); vendorIdx >= 0 { + path = path[vendorIdx+len(vendorPath):] + } + } + if !c.Contains(path, ident) { + return nil + } + + return n.(*ast.CallExpr) +} + +// ContainsCallExpr resolves the call expression name and type, and then determines +// if the call exists with the call list +func (c CallList) ContainsCallExpr(n ast.Node, ctx *Context) *ast.CallExpr { + selector, ident, err := GetCallInfo(n, ctx) + if err != nil { + return nil + } + if !c.Contains(selector, ident) && !c.ContainsPointer(selector, ident) { + return nil + } + + return n.(*ast.CallExpr) +} diff --git a/vendor/github.com/securego/gosec/v2/config.go b/vendor/github.com/securego/gosec/v2/config.go new file mode 100644 index 000000000..5b7f73936 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/config.go @@ -0,0 +1,125 @@ +package gosec + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" +) + +const ( + // Globals are applicable to all rules and used for general + // configuration settings for gosec. + Globals = "global" +) + +// GlobalOption defines the name of the global options +type GlobalOption string + +const ( + // Nosec global option for #nosec directive + Nosec GlobalOption = "nosec" + // Audit global option which indicates that gosec runs in audit mode + Audit GlobalOption = "audit" + // NoSecAlternative global option alternative for #nosec directive + NoSecAlternative GlobalOption = "#nosec" +) + +// Config is used to provide configuration and customization to each of the rules. +type Config map[string]interface{} + +// NewConfig initializes a new configuration instance. The configuration data then +// needs to be loaded via c.ReadFrom(strings.NewReader("config data")) +// or from a *os.File. +func NewConfig() Config { + cfg := make(Config) + cfg[Globals] = make(map[GlobalOption]string) + return cfg +} + +func (c Config) keyToGlobalOptions(key string) GlobalOption { + return GlobalOption(key) +} + +func (c Config) convertGlobals() { + if globals, ok := c[Globals]; ok { + if settings, ok := globals.(map[string]interface{}); ok { + validGlobals := map[GlobalOption]string{} + for k, v := range settings { + validGlobals[c.keyToGlobalOptions(k)] = fmt.Sprintf("%v", v) + } + c[Globals] = validGlobals + } + } +} + +// ReadFrom implements the io.ReaderFrom interface. This +// should be used with io.Reader to load configuration from +//file or from string etc. +func (c Config) ReadFrom(r io.Reader) (int64, error) { + data, err := ioutil.ReadAll(r) + if err != nil { + return int64(len(data)), err + } + if err = json.Unmarshal(data, &c); err != nil { + return int64(len(data)), err + } + c.convertGlobals() + return int64(len(data)), nil +} + +// WriteTo implements the io.WriteTo interface. This should +// be used to save or print out the configuration information. +func (c Config) WriteTo(w io.Writer) (int64, error) { + data, err := json.Marshal(c) + if err != nil { + return int64(len(data)), err + } + return io.Copy(w, bytes.NewReader(data)) +} + +// Get returns the configuration section for the supplied key +func (c Config) Get(section string) (interface{}, error) { + settings, found := c[section] + if !found { + return nil, fmt.Errorf("Section %s not in configuration", section) + } + return settings, nil +} + +// Set section in the configuration to specified value +func (c Config) Set(section string, value interface{}) { + c[section] = value +} + +// GetGlobal returns value associated with global configuration option +func (c Config) GetGlobal(option GlobalOption) (string, error) { + if globals, ok := c[Globals]; ok { + if settings, ok := globals.(map[GlobalOption]string); ok { + if value, ok := settings[option]; ok { + return value, nil + } + return "", fmt.Errorf("global setting for %s not found", option) + } + } + return "", fmt.Errorf("no global config options found") +} + +// SetGlobal associates a value with a global configuration option +func (c Config) SetGlobal(option GlobalOption, value string) { + if globals, ok := c[Globals]; ok { + if settings, ok := globals.(map[GlobalOption]string); ok { + settings[option] = value + } + } +} + +// IsGlobalEnabled checks if a global option is enabled +func (c Config) IsGlobalEnabled(option GlobalOption) (bool, error) { + value, err := c.GetGlobal(option) + if err != nil { + return false, err + } + return (value == "true" || value == "enabled"), nil +} diff --git a/vendor/github.com/securego/gosec/v2/errors.go b/vendor/github.com/securego/gosec/v2/errors.go new file mode 100644 index 000000000..a27aa5821 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/errors.go @@ -0,0 +1,33 @@ +package gosec + +import ( + "sort" +) + +// Error is used when there are golang errors while parsing the AST +type Error struct { + Line int `json:"line"` + Column int `json:"column"` + Err string `json:"error"` +} + +// NewError creates Error object +func NewError(line, column int, err string) *Error { + return &Error{ + Line: line, + Column: column, + Err: err, + } +} + +// sortErros sorts the golang erros by line +func sortErrors(allErrors map[string][]Error) { + for _, errors := range allErrors { + sort.Slice(errors, func(i, j int) bool { + if errors[i].Line == errors[j].Line { + return errors[i].Column <= errors[j].Column + } + return errors[i].Line < errors[j].Line + }) + } +} diff --git a/vendor/github.com/securego/gosec/v2/go.mod b/vendor/github.com/securego/gosec/v2/go.mod new file mode 100644 index 000000000..edfa3434c --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/go.mod @@ -0,0 +1,19 @@ +module github.com/securego/gosec/v2 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/golang/protobuf v1.3.2 // indirect + github.com/gookit/color v1.2.4 + github.com/kr/pretty v0.1.0 // indirect + github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee + github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d + github.com/onsi/ginkgo v1.12.0 + github.com/onsi/gomega v1.9.0 + github.com/stretchr/testify v1.4.0 // indirect + golang.org/x/text v0.3.2 // indirect + golang.org/x/tools v0.0.0-20200331202046-9d5940d49312 + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + gopkg.in/yaml.v2 v2.2.8 +) + +go 1.14 diff --git a/vendor/github.com/securego/gosec/v2/go.sum b/vendor/github.com/securego/gosec/v2/go.sum new file mode 100644 index 000000000..fff56a309 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/go.sum @@ -0,0 +1,82 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gookit/color v1.2.4 h1:xOYBan3Fwlrqj1M1UN2TlHOCRiek3bGzWf/vPnJ1roE= +github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee h1:1xJ+Xi9lYWLaaP4yB67ah0+548CD3110mCPWhVVjFkI= +github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= +github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E= +github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200331202046-9d5940d49312 h1:2PHG+Ia3gK1K2kjxZnSylizb//eyaMG8gDFbOG7wLV8= +golang.org/x/tools v0.0.0-20200331202046-9d5940d49312/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/securego/gosec/v2/helpers.go b/vendor/github.com/securego/gosec/v2/helpers.go new file mode 100644 index 000000000..40dc8e9c3 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/helpers.go @@ -0,0 +1,435 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gosec + +import ( + "errors" + "fmt" + "go/ast" + "go/token" + "go/types" + "os" + "os/user" + "path/filepath" + "regexp" + "runtime" + "strconv" + "strings" +) + +// MatchCallByPackage ensures that the specified package is imported, +// adjusts the name for any aliases and ignores cases that are +// initialization only imports. +// +// Usage: +// node, matched := MatchCallByPackage(n, ctx, "math/rand", "Read") +// +func MatchCallByPackage(n ast.Node, c *Context, pkg string, names ...string) (*ast.CallExpr, bool) { + + importedName, found := GetImportedName(pkg, c) + if !found { + return nil, false + } + + if callExpr, ok := n.(*ast.CallExpr); ok { + packageName, callName, err := GetCallInfo(callExpr, c) + if err != nil { + return nil, false + } + if packageName == importedName { + for _, name := range names { + if callName == name { + return callExpr, true + } + } + } + } + return nil, false +} + +// MatchCompLit will match an ast.CompositeLit based on the supplied type +func MatchCompLit(n ast.Node, ctx *Context, required string) *ast.CompositeLit { + if complit, ok := n.(*ast.CompositeLit); ok { + typeOf := ctx.Info.TypeOf(complit) + if typeOf.String() == required { + return complit + } + } + return nil +} + +// GetInt will read and return an integer value from an ast.BasicLit +func GetInt(n ast.Node) (int64, error) { + if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.INT { + return strconv.ParseInt(node.Value, 0, 64) + } + return 0, fmt.Errorf("Unexpected AST node type: %T", n) +} + +// GetFloat will read and return a float value from an ast.BasicLit +func GetFloat(n ast.Node) (float64, error) { + if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.FLOAT { + return strconv.ParseFloat(node.Value, 64) + } + return 0.0, fmt.Errorf("Unexpected AST node type: %T", n) +} + +// GetChar will read and return a char value from an ast.BasicLit +func GetChar(n ast.Node) (byte, error) { + if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.CHAR { + return node.Value[0], nil + } + return 0, fmt.Errorf("Unexpected AST node type: %T", n) +} + +// GetString will read and return a string value from an ast.BasicLit +func GetString(n ast.Node) (string, error) { + if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.STRING { + return strconv.Unquote(node.Value) + } + return "", fmt.Errorf("Unexpected AST node type: %T", n) +} + +// GetCallObject returns the object and call expression and associated +// object for a given AST node. nil, nil will be returned if the +// object cannot be resolved. +func GetCallObject(n ast.Node, ctx *Context) (*ast.CallExpr, types.Object) { + switch node := n.(type) { + case *ast.CallExpr: + switch fn := node.Fun.(type) { + case *ast.Ident: + return node, ctx.Info.Uses[fn] + case *ast.SelectorExpr: + return node, ctx.Info.Uses[fn.Sel] + } + } + return nil, nil +} + +// GetCallInfo returns the package or type and name associated with a +// call expression. +func GetCallInfo(n ast.Node, ctx *Context) (string, string, error) { + switch node := n.(type) { + case *ast.CallExpr: + switch fn := node.Fun.(type) { + case *ast.SelectorExpr: + switch expr := fn.X.(type) { + case *ast.Ident: + if expr.Obj != nil && expr.Obj.Kind == ast.Var { + t := ctx.Info.TypeOf(expr) + if t != nil { + return t.String(), fn.Sel.Name, nil + } + return "undefined", fn.Sel.Name, fmt.Errorf("missing type info") + } + return expr.Name, fn.Sel.Name, nil + case *ast.SelectorExpr: + if expr.Sel != nil { + t := ctx.Info.TypeOf(expr.Sel) + if t != nil { + return t.String(), fn.Sel.Name, nil + } + return "undefined", fn.Sel.Name, fmt.Errorf("missing type info") + } + case *ast.CallExpr: + switch call := expr.Fun.(type) { + case *ast.Ident: + if call.Name == "new" { + t := ctx.Info.TypeOf(expr.Args[0]) + if t != nil { + return t.String(), fn.Sel.Name, nil + } + return "undefined", fn.Sel.Name, fmt.Errorf("missing type info") + } + if call.Obj != nil { + switch decl := call.Obj.Decl.(type) { + case *ast.FuncDecl: + ret := decl.Type.Results + if ret != nil && len(ret.List) > 0 { + ret1 := ret.List[0] + if ret1 != nil { + t := ctx.Info.TypeOf(ret1.Type) + if t != nil { + return t.String(), fn.Sel.Name, nil + } + return "undefined", fn.Sel.Name, fmt.Errorf("missing type info") + } + } + } + } + + } + } + case *ast.Ident: + return ctx.Pkg.Name(), fn.Name, nil + } + } + + return "", "", fmt.Errorf("unable to determine call info") +} + +// GetCallStringArgsValues returns the values of strings arguments if they can be resolved +func GetCallStringArgsValues(n ast.Node, ctx *Context) []string { + values := []string{} + switch node := n.(type) { + case *ast.CallExpr: + for _, arg := range node.Args { + switch param := arg.(type) { + case *ast.BasicLit: + value, err := GetString(param) + if err == nil { + values = append(values, value) + } + case *ast.Ident: + values = append(values, GetIdentStringValues(param)...) + } + } + } + return values +} + +// GetIdentStringValues return the string values of an Ident if they can be resolved +func GetIdentStringValues(ident *ast.Ident) []string { + values := []string{} + obj := ident.Obj + if obj != nil { + switch decl := obj.Decl.(type) { + case *ast.ValueSpec: + for _, v := range decl.Values { + value, err := GetString(v) + if err == nil { + values = append(values, value) + } + } + case *ast.AssignStmt: + for _, v := range decl.Rhs { + value, err := GetString(v) + if err == nil { + values = append(values, value) + } + } + } + + } + return values +} + +// GetImportedName returns the name used for the package within the +// code. It will resolve aliases and ignores initialization only imports. +func GetImportedName(path string, ctx *Context) (string, bool) { + importName, imported := ctx.Imports.Imported[path] + if !imported { + return "", false + } + + if _, initonly := ctx.Imports.InitOnly[path]; initonly { + return "", false + } + + if alias, ok := ctx.Imports.Aliased[path]; ok { + importName = alias + } + return importName, true +} + +// GetImportPath resolves the full import path of an identifier based on +// the imports in the current context. +func GetImportPath(name string, ctx *Context) (string, bool) { + for path := range ctx.Imports.Imported { + if imported, ok := GetImportedName(path, ctx); ok && imported == name { + return path, true + } + } + return "", false +} + +// GetLocation returns the filename and line number of an ast.Node +func GetLocation(n ast.Node, ctx *Context) (string, int) { + fobj := ctx.FileSet.File(n.Pos()) + return fobj.Name(), fobj.Line(n.Pos()) +} + +// Gopath returns all GOPATHs +func Gopath() []string { + defaultGoPath := runtime.GOROOT() + if u, err := user.Current(); err == nil { + defaultGoPath = filepath.Join(u.HomeDir, "go") + } + path := Getenv("GOPATH", defaultGoPath) + paths := strings.Split(path, string(os.PathListSeparator)) + for idx, path := range paths { + if abs, err := filepath.Abs(path); err == nil { + paths[idx] = abs + } + } + return paths +} + +// Getenv returns the values of the environment variable, otherwise +//returns the default if variable is not set +func Getenv(key, userDefault string) string { + if val := os.Getenv(key); val != "" { + return val + } + return userDefault +} + +// GetPkgRelativePath returns the Go relative relative path derived +// form the given path +func GetPkgRelativePath(path string) (string, error) { + abspath, err := filepath.Abs(path) + if err != nil { + abspath = path + } + if strings.HasSuffix(abspath, ".go") { + abspath = filepath.Dir(abspath) + } + for _, base := range Gopath() { + projectRoot := filepath.FromSlash(fmt.Sprintf("%s/src/", base)) + if strings.HasPrefix(abspath, projectRoot) { + return strings.TrimPrefix(abspath, projectRoot), nil + } + } + return "", errors.New("no project relative path found") +} + +// GetPkgAbsPath returns the Go package absolute path derived from +// the given path +func GetPkgAbsPath(pkgPath string) (string, error) { + absPath, err := filepath.Abs(pkgPath) + if err != nil { + return "", err + } + if _, err := os.Stat(absPath); os.IsNotExist(err) { + return "", errors.New("no project absolute path found") + } + return absPath, nil +} + +// ConcatString recursively concatenates strings from a binary expression +func ConcatString(n *ast.BinaryExpr) (string, bool) { + var s string + // sub expressions are found in X object, Y object is always last BasicLit + if rightOperand, ok := n.Y.(*ast.BasicLit); ok { + if str, err := GetString(rightOperand); err == nil { + s = str + s + } + } else { + return "", false + } + if leftOperand, ok := n.X.(*ast.BinaryExpr); ok { + if recursion, ok := ConcatString(leftOperand); ok { + s = recursion + s + } + } else if leftOperand, ok := n.X.(*ast.BasicLit); ok { + if str, err := GetString(leftOperand); err == nil { + s = str + s + } + } else { + return "", false + } + return s, true +} + +// FindVarIdentities returns array of all variable identities in a given binary expression +func FindVarIdentities(n *ast.BinaryExpr, c *Context) ([]*ast.Ident, bool) { + identities := []*ast.Ident{} + // sub expressions are found in X object, Y object is always the last term + if rightOperand, ok := n.Y.(*ast.Ident); ok { + obj := c.Info.ObjectOf(rightOperand) + if _, ok := obj.(*types.Var); ok && !TryResolve(rightOperand, c) { + identities = append(identities, rightOperand) + } + } + if leftOperand, ok := n.X.(*ast.BinaryExpr); ok { + if leftIdentities, ok := FindVarIdentities(leftOperand, c); ok { + identities = append(identities, leftIdentities...) + } + } else { + if leftOperand, ok := n.X.(*ast.Ident); ok { + obj := c.Info.ObjectOf(leftOperand) + if _, ok := obj.(*types.Var); ok && !TryResolve(leftOperand, c) { + identities = append(identities, leftOperand) + } + } + } + + if len(identities) > 0 { + return identities, true + } + // if nil or error, return false + return nil, false +} + +// PackagePaths returns a slice with all packages path at given root directory +func PackagePaths(root string, excludes []*regexp.Regexp) ([]string, error) { + if strings.HasSuffix(root, "...") { + root = root[0 : len(root)-3] + } else { + return []string{root}, nil + } + paths := map[string]bool{} + err := filepath.Walk(root, func(path string, f os.FileInfo, err error) error { + if filepath.Ext(path) == ".go" { + path = filepath.Dir(path) + if isExcluded(path, excludes) { + return nil + } + paths[path] = true + } + return nil + }) + if err != nil { + return []string{}, err + } + + result := []string{} + for path := range paths { + result = append(result, path) + } + return result, nil +} + +// isExcluded checks if a string matches any of the exclusion regexps +func isExcluded(str string, excludes []*regexp.Regexp) bool { + if excludes == nil { + return false + } + for _, exclude := range excludes { + if exclude != nil && exclude.MatchString(str) { + return true + } + } + return false +} + +// ExcludedDirsRegExp builds the regexps for a list of excluded dirs provided as strings +func ExcludedDirsRegExp(excludedDirs []string) []*regexp.Regexp { + var exps []*regexp.Regexp + for _, excludedDir := range excludedDirs { + str := fmt.Sprintf(`([\\/])?%s([\\/])?`, excludedDir) + r := regexp.MustCompile(str) + exps = append(exps, r) + } + return exps +} + +// RootPath returns the absolute root path of a scan +func RootPath(root string) (string, error) { + if strings.HasSuffix(root, "...") { + root = root[0 : len(root)-3] + } + return filepath.Abs(root) +} diff --git a/vendor/github.com/securego/gosec/v2/import_tracker.go b/vendor/github.com/securego/gosec/v2/import_tracker.go new file mode 100644 index 000000000..cbb8c5518 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/import_tracker.go @@ -0,0 +1,75 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gosec + +import ( + "go/ast" + "go/types" + "strings" +) + +// ImportTracker is used to normalize the packages that have been imported +// by a source file. It is able to differentiate between plain imports, aliased +// imports and init only imports. +type ImportTracker struct { + Imported map[string]string + Aliased map[string]string + InitOnly map[string]bool +} + +// NewImportTracker creates an empty Import tracker instance +func NewImportTracker() *ImportTracker { + return &ImportTracker{ + make(map[string]string), + make(map[string]string), + make(map[string]bool), + } +} + +// TrackFile track all the imports used by the supplied file +func (t *ImportTracker) TrackFile(file *ast.File) { + for _, imp := range file.Imports { + path := strings.Trim(imp.Path.Value, `"`) + parts := strings.Split(path, "/") + if len(parts) > 0 { + name := parts[len(parts)-1] + t.Imported[path] = name + } + } +} + +// TrackPackages tracks all the imports used by the supplied packages +func (t *ImportTracker) TrackPackages(pkgs ...*types.Package) { + for _, pkg := range pkgs { + t.Imported[pkg.Path()] = pkg.Name() + } +} + +// TrackImport tracks imports and handles the 'unsafe' import +func (t *ImportTracker) TrackImport(n ast.Node) { + if imported, ok := n.(*ast.ImportSpec); ok { + path := strings.Trim(imported.Path.Value, `"`) + if imported.Name != nil { + if imported.Name.Name == "_" { + // Initialization only import + t.InitOnly[path] = true + } else { + // Aliased import + t.Aliased[path] = imported.Name.Name + } + } + if path == "unsafe" { + t.Imported[path] = path + } + } +} diff --git a/vendor/github.com/securego/gosec/v2/install.sh b/vendor/github.com/securego/gosec/v2/install.sh new file mode 100644 index 000000000..37bed0a2e --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/install.sh @@ -0,0 +1,372 @@ +#!/bin/sh +set -e +# Code generated by godownloader on 2020-03-02T13:35:13Z. DO NOT EDIT. +# + +usage() { + this=$1 + cat </dev/null +} +echoerr() { + echo "$@" 1>&2 +} +log_prefix() { + echo "$0" +} +_logp=6 +log_set_priority() { + _logp="$1" +} +log_priority() { + if test -z "$1"; then + echo "$_logp" + return + fi + [ "$1" -le "$_logp" ] +} +log_tag() { + case $1 in + 0) echo "emerg" ;; + 1) echo "alert" ;; + 2) echo "crit" ;; + 3) echo "err" ;; + 4) echo "warning" ;; + 5) echo "notice" ;; + 6) echo "info" ;; + 7) echo "debug" ;; + *) echo "$1" ;; + esac +} +log_debug() { + log_priority 7 || return 0 + echoerr "$(log_prefix)" "$(log_tag 7)" "$@" +} +log_info() { + log_priority 6 || return 0 + echoerr "$(log_prefix)" "$(log_tag 6)" "$@" +} +log_err() { + log_priority 3 || return 0 + echoerr "$(log_prefix)" "$(log_tag 3)" "$@" +} +log_crit() { + log_priority 2 || return 0 + echoerr "$(log_prefix)" "$(log_tag 2)" "$@" +} +uname_os() { + os=$(uname -s | tr '[:upper:]' '[:lower:]') + case "$os" in + cygwin_nt*) os="windows" ;; + mingw*) os="windows" ;; + msys_nt*) os="windows" ;; + esac + echo "$os" +} +uname_arch() { + arch=$(uname -m) + case $arch in + x86_64) arch="amd64" ;; + x86) arch="386" ;; + i686) arch="386" ;; + i386) arch="386" ;; + aarch64) arch="arm64" ;; + armv5*) arch="armv5" ;; + armv6*) arch="armv6" ;; + armv7*) arch="armv7" ;; + esac + echo ${arch} +} +uname_os_check() { + os=$(uname_os) + case "$os" in + darwin) return 0 ;; + dragonfly) return 0 ;; + freebsd) return 0 ;; + linux) return 0 ;; + android) return 0 ;; + nacl) return 0 ;; + netbsd) return 0 ;; + openbsd) return 0 ;; + plan9) return 0 ;; + solaris) return 0 ;; + windows) return 0 ;; + esac + log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib" + return 1 +} +uname_arch_check() { + arch=$(uname_arch) + case "$arch" in + 386) return 0 ;; + amd64) return 0 ;; + arm64) return 0 ;; + armv5) return 0 ;; + armv6) return 0 ;; + armv7) return 0 ;; + ppc64) return 0 ;; + ppc64le) return 0 ;; + mips) return 0 ;; + mipsle) return 0 ;; + mips64) return 0 ;; + mips64le) return 0 ;; + s390x) return 0 ;; + amd64p32) return 0 ;; + esac + log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib" + return 1 +} +untar() { + tarball=$1 + case "${tarball}" in + *.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;; + *.tar) tar --no-same-owner -xf "${tarball}" ;; + *.zip) unzip "${tarball}" ;; + *) + log_err "untar unknown archive format for ${tarball}" + return 1 + ;; + esac +} +http_download_curl() { + local_file=$1 + source_url=$2 + header=$3 + if [ -z "$header" ]; then + code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url") + else + code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url") + fi + if [ "$code" != "200" ]; then + log_debug "http_download_curl received HTTP status $code" + return 1 + fi + return 0 +} +http_download_wget() { + local_file=$1 + source_url=$2 + header=$3 + if [ -z "$header" ]; then + wget -q -O "$local_file" "$source_url" + else + wget -q --header "$header" -O "$local_file" "$source_url" + fi +} +http_download() { + log_debug "http_download $2" + if is_command curl; then + http_download_curl "$@" + return + elif is_command wget; then + http_download_wget "$@" + return + fi + log_crit "http_download unable to find wget or curl" + return 1 +} +http_copy() { + tmp=$(mktemp) + http_download "${tmp}" "$1" "$2" || return 1 + body=$(cat "$tmp") + rm -f "${tmp}" + echo "$body" +} +github_release() { + owner_repo=$1 + version=$2 + test -z "$version" && version="latest" + giturl="https://github.com/${owner_repo}/releases/${version}" + json=$(http_copy "$giturl" "Accept:application/json") + test -z "$json" && return 1 + version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//') + test -z "$version" && return 1 + echo "$version" +} +hash_sha256() { + TARGET=${1:-/dev/stdin} + if is_command gsha256sum; then + hash=$(gsha256sum "$TARGET") || return 1 + echo "$hash" | cut -d ' ' -f 1 + elif is_command sha256sum; then + hash=$(sha256sum "$TARGET") || return 1 + echo "$hash" | cut -d ' ' -f 1 + elif is_command shasum; then + hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1 + echo "$hash" | cut -d ' ' -f 1 + elif is_command openssl; then + hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1 + echo "$hash" | cut -d ' ' -f a + else + log_crit "hash_sha256 unable to find command to compute sha-256 hash" + return 1 + fi +} +hash_sha256_verify() { + TARGET=$1 + checksums=$2 + if [ -z "$checksums" ]; then + log_err "hash_sha256_verify checksum file not specified in arg2" + return 1 + fi + BASENAME=${TARGET##*/} + want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1) + if [ -z "$want" ]; then + log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'" + return 1 + fi + got=$(hash_sha256 "$TARGET") + if [ "$want" != "$got" ]; then + log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got" + return 1 + fi +} +cat /dev/null < 1 { + arg := callExpr.Args[1] + if bl, ok := arg.(*ast.BasicLit); ok { + if arg, err := gosec.GetString(bl); err == nil { + if r.pattern.MatchString(arg) { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + } else if ident, ok := arg.(*ast.Ident); ok { + values := gosec.GetIdentStringValues(ident) + for _, value := range values { + if r.pattern.MatchString(value) { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + } + } else if len(callExpr.Args) > 0 { + values := gosec.GetCallStringArgsValues(callExpr.Args[0], c) + for _, value := range values { + if r.pattern.MatchString(value) { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + } + return nil, nil +} + +// NewBindsToAllNetworkInterfaces detects socket connections that are setup to +// listen on all network interfaces. +func NewBindsToAllNetworkInterfaces(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + calls := gosec.NewCallList() + calls.Add("net", "Listen") + calls.Add("crypto/tls", "Listen") + return &bindsToAllNetworkInterfaces{ + calls: calls, + pattern: regexp.MustCompile(`^(0.0.0.0|:).*$`), + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + What: "Binds to all network interfaces", + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/blacklist.go b/vendor/github.com/securego/gosec/v2/rules/blacklist.go new file mode 100644 index 000000000..9bb73381f --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/blacklist.go @@ -0,0 +1,94 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + "strings" + + "github.com/securego/gosec/v2" +) + +type blacklistedImport struct { + gosec.MetaData + Blacklisted map[string]string +} + +func unquote(original string) string { + copy := strings.TrimSpace(original) + copy = strings.TrimLeft(copy, `"`) + return strings.TrimRight(copy, `"`) +} + +func (r *blacklistedImport) ID() string { + return r.MetaData.ID +} + +func (r *blacklistedImport) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + if node, ok := n.(*ast.ImportSpec); ok { + if description, ok := r.Blacklisted[unquote(node.Path.Value)]; ok { + return gosec.NewIssue(c, node, r.ID(), description, r.Severity, r.Confidence), nil + } + } + return nil, nil +} + +// NewBlacklistedImports reports when a blacklisted import is being used. +// Typically when a deprecated technology is being used. +func NewBlacklistedImports(id string, conf gosec.Config, blacklist map[string]string) (gosec.Rule, []ast.Node) { + return &blacklistedImport{ + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + }, + Blacklisted: blacklist, + }, []ast.Node{(*ast.ImportSpec)(nil)} +} + +// NewBlacklistedImportMD5 fails if MD5 is imported +func NewBlacklistedImportMD5(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return NewBlacklistedImports(id, conf, map[string]string{ + "crypto/md5": "Blacklisted import crypto/md5: weak cryptographic primitive", + }) +} + +// NewBlacklistedImportDES fails if DES is imported +func NewBlacklistedImportDES(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return NewBlacklistedImports(id, conf, map[string]string{ + "crypto/des": "Blacklisted import crypto/des: weak cryptographic primitive", + }) +} + +// NewBlacklistedImportRC4 fails if DES is imported +func NewBlacklistedImportRC4(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return NewBlacklistedImports(id, conf, map[string]string{ + "crypto/rc4": "Blacklisted import crypto/rc4: weak cryptographic primitive", + }) +} + +// NewBlacklistedImportCGI fails if CGI is imported +func NewBlacklistedImportCGI(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return NewBlacklistedImports(id, conf, map[string]string{ + "net/http/cgi": "Blacklisted import net/http/cgi: Go versions < 1.6.3 are vulnerable to Httpoxy attack: (CVE-2016-5386)", + }) +} + +// NewBlacklistedImportSHA1 fails if SHA1 is imported +func NewBlacklistedImportSHA1(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return NewBlacklistedImports(id, conf, map[string]string{ + "crypto/sha1": "Blacklisted import crypto/sha1: weak cryptographic primitive", + }) +} diff --git a/vendor/github.com/securego/gosec/v2/rules/decompression-bomb.go b/vendor/github.com/securego/gosec/v2/rules/decompression-bomb.go new file mode 100644 index 000000000..bfc589763 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/decompression-bomb.go @@ -0,0 +1,109 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "fmt" + "go/ast" + + "github.com/securego/gosec/v2" +) + +type decompressionBombCheck struct { + gosec.MetaData + readerCalls gosec.CallList + copyCalls gosec.CallList +} + +func (d *decompressionBombCheck) ID() string { + return d.MetaData.ID +} + +func containsReaderCall(node ast.Node, ctx *gosec.Context, list gosec.CallList) bool { + if list.ContainsPkgCallExpr(node, ctx, false) != nil { + return true + } + // Resolve type info of ident (for *archive/zip.File.Open) + s, idt, _ := gosec.GetCallInfo(node, ctx) + return list.Contains(s, idt) +} + +func (d *decompressionBombCheck) Match(node ast.Node, ctx *gosec.Context) (*gosec.Issue, error) { + var readerVarObj map[*ast.Object]struct{} + + // To check multiple lines, ctx.PassedValues is used to store temporary data. + if _, ok := ctx.PassedValues[d.ID()]; !ok { + readerVarObj = make(map[*ast.Object]struct{}) + ctx.PassedValues[d.ID()] = readerVarObj + } else if pv, ok := ctx.PassedValues[d.ID()].(map[*ast.Object]struct{}); ok { + readerVarObj = pv + } else { + return nil, fmt.Errorf("PassedValues[%s] of Context is not map[*ast.Object]struct{}, but %T", d.ID(), ctx.PassedValues[d.ID()]) + } + + // io.Copy is a common function. + // To reduce false positives, This rule detects code which is used for compressed data only. + switch n := node.(type) { + case *ast.AssignStmt: + for _, expr := range n.Rhs { + if callExpr, ok := expr.(*ast.CallExpr); ok && containsReaderCall(callExpr, ctx, d.readerCalls) { + if idt, ok := n.Lhs[0].(*ast.Ident); ok && idt.Name != "_" { + // Example: + // r, _ := zlib.NewReader(buf) + // Add r's Obj to readerVarObj map + readerVarObj[idt.Obj] = struct{}{} + } + } + } + case *ast.CallExpr: + if d.copyCalls.ContainsPkgCallExpr(n, ctx, false) != nil { + if idt, ok := n.Args[1].(*ast.Ident); ok { + if _, ok := readerVarObj[idt.Obj]; ok { + // Detect io.Copy(x, r) + return gosec.NewIssue(ctx, n, d.ID(), d.What, d.Severity, d.Confidence), nil + } + } + } + } + + return nil, nil +} + +// NewDecompressionBombCheck detects if there is potential DoS vulnerability via decompression bomb +func NewDecompressionBombCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + readerCalls := gosec.NewCallList() + readerCalls.Add("compress/gzip", "NewReader") + readerCalls.AddAll("compress/zlib", "NewReader", "NewReaderDict") + readerCalls.Add("compress/bzip2", "NewReader") + readerCalls.AddAll("compress/flate", "NewReader", "NewReaderDict") + readerCalls.Add("compress/lzw", "NewReader") + readerCalls.Add("archive/tar", "NewReader") + readerCalls.Add("archive/zip", "NewReader") + readerCalls.Add("*archive/zip.File", "Open") + + copyCalls := gosec.NewCallList() + copyCalls.Add("io", "Copy") + + return &decompressionBombCheck{ + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.Medium, + What: "Potential DoS vulnerability via decompression bomb", + }, + readerCalls: readerCalls, + copyCalls: copyCalls, + }, []ast.Node{(*ast.FuncDecl)(nil), (*ast.AssignStmt)(nil), (*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/errors.go b/vendor/github.com/securego/gosec/v2/rules/errors.go new file mode 100644 index 000000000..f16f91d04 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/errors.go @@ -0,0 +1,119 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + "go/types" + + "github.com/securego/gosec/v2" +) + +type noErrorCheck struct { + gosec.MetaData + whitelist gosec.CallList +} + +func (r *noErrorCheck) ID() string { + return r.MetaData.ID +} + +func returnsError(callExpr *ast.CallExpr, ctx *gosec.Context) int { + if tv := ctx.Info.TypeOf(callExpr); tv != nil { + switch t := tv.(type) { + case *types.Tuple: + for pos := 0; pos < t.Len(); pos++ { + variable := t.At(pos) + if variable != nil && variable.Type().String() == "error" { + return pos + } + } + case *types.Named: + if t.String() == "error" { + return 0 + } + } + } + return -1 +} + +func (r *noErrorCheck) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) { + switch stmt := n.(type) { + case *ast.AssignStmt: + cfg := ctx.Config + if enabled, err := cfg.IsGlobalEnabled(gosec.Audit); err == nil && enabled { + for _, expr := range stmt.Rhs { + if callExpr, ok := expr.(*ast.CallExpr); ok && r.whitelist.ContainsCallExpr(expr, ctx) == nil { + pos := returnsError(callExpr, ctx) + if pos < 0 || pos >= len(stmt.Lhs) { + return nil, nil + } + if id, ok := stmt.Lhs[pos].(*ast.Ident); ok && id.Name == "_" { + return gosec.NewIssue(ctx, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + } + } + case *ast.ExprStmt: + if callExpr, ok := stmt.X.(*ast.CallExpr); ok && r.whitelist.ContainsCallExpr(stmt.X, ctx) == nil { + pos := returnsError(callExpr, ctx) + if pos >= 0 { + return gosec.NewIssue(ctx, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + } + return nil, nil +} + +// NewNoErrorCheck detects if the returned error is unchecked +func NewNoErrorCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + // TODO(gm) Come up with sensible defaults here. Or flip it to use a + // black list instead. + whitelist := gosec.NewCallList() + whitelist.AddAll("bytes.Buffer", "Write", "WriteByte", "WriteRune", "WriteString") + whitelist.AddAll("fmt", "Print", "Printf", "Println", "Fprint", "Fprintf", "Fprintln") + whitelist.AddAll("strings.Builder", "Write", "WriteByte", "WriteRune", "WriteString") + whitelist.Add("io.PipeWriter", "CloseWithError") + + if configured, ok := conf["G104"]; ok { + if whitelisted, ok := configured.(map[string]interface{}); ok { + for pkg, funcs := range whitelisted { + if funcs, ok := funcs.([]interface{}); ok { + whitelist.AddAll(pkg, toStringSlice(funcs)...) + } + } + } + } + + return &noErrorCheck{ + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Low, + Confidence: gosec.High, + What: "Errors unhandled.", + }, + whitelist: whitelist, + }, []ast.Node{(*ast.AssignStmt)(nil), (*ast.ExprStmt)(nil)} +} + +func toStringSlice(values []interface{}) []string { + result := []string{} + for _, value := range values { + if value, ok := value.(string); ok { + result = append(result, value) + } + } + return result +} diff --git a/vendor/github.com/securego/gosec/v2/rules/fileperms.go b/vendor/github.com/securego/gosec/v2/rules/fileperms.go new file mode 100644 index 000000000..ffe7b97d5 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/fileperms.go @@ -0,0 +1,111 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "fmt" + "go/ast" + "strconv" + + "github.com/securego/gosec/v2" +) + +type filePermissions struct { + gosec.MetaData + mode int64 + pkg string + calls []string +} + +func (r *filePermissions) ID() string { + return r.MetaData.ID +} + +func getConfiguredMode(conf map[string]interface{}, configKey string, defaultMode int64) int64 { + var mode = defaultMode + if value, ok := conf[configKey]; ok { + switch value := value.(type) { + case int64: + mode = value + case string: + if m, e := strconv.ParseInt(value, 0, 64); e != nil { + mode = defaultMode + } else { + mode = m + } + } + } + return mode +} + +func (r *filePermissions) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + if callexpr, matched := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matched { + modeArg := callexpr.Args[len(callexpr.Args)-1] + if mode, err := gosec.GetInt(modeArg); err == nil && mode > r.mode { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + return nil, nil +} + +// NewWritePerms creates a rule to detect file Writes with bad permissions. +func NewWritePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + mode := getConfiguredMode(conf, "G306", 0600) + return &filePermissions{ + mode: mode, + pkg: "io/ioutil", + calls: []string{"WriteFile"}, + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + What: fmt.Sprintf("Expect WriteFile permissions to be %#o or less", mode), + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} + +// NewFilePerms creates a rule to detect file creation with a more permissive than configured +// permission mask. +func NewFilePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + mode := getConfiguredMode(conf, "G302", 0600) + return &filePermissions{ + mode: mode, + pkg: "os", + calls: []string{"OpenFile", "Chmod"}, + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + What: fmt.Sprintf("Expect file permissions to be %#o or less", mode), + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} + +// NewMkdirPerms creates a rule to detect directory creation with more permissive than +// configured permission mask. +func NewMkdirPerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + mode := getConfiguredMode(conf, "G301", 0750) + return &filePermissions{ + mode: mode, + pkg: "os", + calls: []string{"Mkdir", "MkdirAll"}, + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + What: fmt.Sprintf("Expect directory permissions to be %#o or less", mode), + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go b/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go new file mode 100644 index 000000000..6b360c5b9 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go @@ -0,0 +1,173 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + "go/token" + "regexp" + "strconv" + + zxcvbn "github.com/nbutton23/zxcvbn-go" + "github.com/securego/gosec/v2" +) + +type credentials struct { + gosec.MetaData + pattern *regexp.Regexp + entropyThreshold float64 + perCharThreshold float64 + truncate int + ignoreEntropy bool +} + +func (r *credentials) ID() string { + return r.MetaData.ID +} + +func truncate(s string, n int) string { + if n > len(s) { + return s + } + return s[:n] +} + +func (r *credentials) isHighEntropyString(str string) bool { + s := truncate(str, r.truncate) + info := zxcvbn.PasswordStrength(s, []string{}) + entropyPerChar := info.Entropy / float64(len(s)) + return (info.Entropy >= r.entropyThreshold || + (info.Entropy >= (r.entropyThreshold/2) && + entropyPerChar >= r.perCharThreshold)) +} + +func (r *credentials) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) { + switch node := n.(type) { + case *ast.AssignStmt: + return r.matchAssign(node, ctx) + case *ast.ValueSpec: + return r.matchValueSpec(node, ctx) + case *ast.BinaryExpr: + return r.matchEqualityCheck(node, ctx) + } + return nil, nil +} + +func (r *credentials) matchAssign(assign *ast.AssignStmt, ctx *gosec.Context) (*gosec.Issue, error) { + for _, i := range assign.Lhs { + if ident, ok := i.(*ast.Ident); ok { + if r.pattern.MatchString(ident.Name) { + for _, e := range assign.Rhs { + if val, err := gosec.GetString(e); err == nil { + if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) { + return gosec.NewIssue(ctx, assign, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + } + } + } + } + return nil, nil +} + +func (r *credentials) matchValueSpec(valueSpec *ast.ValueSpec, ctx *gosec.Context) (*gosec.Issue, error) { + for index, ident := range valueSpec.Names { + if r.pattern.MatchString(ident.Name) && valueSpec.Values != nil { + // const foo, bar = "same value" + if len(valueSpec.Values) <= index { + index = len(valueSpec.Values) - 1 + } + if val, err := gosec.GetString(valueSpec.Values[index]); err == nil { + if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) { + return gosec.NewIssue(ctx, valueSpec, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + } + } + return nil, nil +} + +func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec.Context) (*gosec.Issue, error) { + if binaryExpr.Op == token.EQL || binaryExpr.Op == token.NEQ { + if ident, ok := binaryExpr.X.(*ast.Ident); ok { + if r.pattern.MatchString(ident.Name) { + if val, err := gosec.GetString(binaryExpr.Y); err == nil { + if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) { + return gosec.NewIssue(ctx, binaryExpr, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + } + } + } + return nil, nil +} + +// NewHardcodedCredentials attempts to find high entropy string constants being +// assigned to variables that appear to be related to credentials. +func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + pattern := `(?i)passwd|pass|password|pwd|secret|token` + entropyThreshold := 80.0 + perCharThreshold := 3.0 + ignoreEntropy := false + var truncateString = 16 + if val, ok := conf["G101"]; ok { + conf := val.(map[string]interface{}) + if configPattern, ok := conf["pattern"]; ok { + if cfgPattern, ok := configPattern.(string); ok { + pattern = cfgPattern + } + } + if configIgnoreEntropy, ok := conf["ignore_entropy"]; ok { + if cfgIgnoreEntropy, ok := configIgnoreEntropy.(bool); ok { + ignoreEntropy = cfgIgnoreEntropy + } + } + if configEntropyThreshold, ok := conf["entropy_threshold"]; ok { + if cfgEntropyThreshold, ok := configEntropyThreshold.(string); ok { + if parsedNum, err := strconv.ParseFloat(cfgEntropyThreshold, 64); err == nil { + entropyThreshold = parsedNum + } + } + } + if configCharThreshold, ok := conf["per_char_threshold"]; ok { + if cfgCharThreshold, ok := configCharThreshold.(string); ok { + if parsedNum, err := strconv.ParseFloat(cfgCharThreshold, 64); err == nil { + perCharThreshold = parsedNum + } + } + } + if configTruncate, ok := conf["truncate"]; ok { + if cfgTruncate, ok := configTruncate.(string); ok { + if parsedInt, err := strconv.Atoi(cfgTruncate); err == nil { + truncateString = parsedInt + } + } + } + } + + return &credentials{ + pattern: regexp.MustCompile(pattern), + entropyThreshold: entropyThreshold, + perCharThreshold: perCharThreshold, + ignoreEntropy: ignoreEntropy, + truncate: truncateString, + MetaData: gosec.MetaData{ + ID: id, + What: "Potential hardcoded credentials", + Confidence: gosec.Low, + Severity: gosec.High, + }, + }, []ast.Node{(*ast.AssignStmt)(nil), (*ast.ValueSpec)(nil), (*ast.BinaryExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/implicit_aliasing.go b/vendor/github.com/securego/gosec/v2/rules/implicit_aliasing.go new file mode 100644 index 000000000..65c7ae36d --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/implicit_aliasing.go @@ -0,0 +1,116 @@ +package rules + +import ( + "fmt" + "github.com/securego/gosec/v2" + "go/ast" + "go/token" +) + +type implicitAliasing struct { + gosec.MetaData + aliases map[*ast.Object]struct{} + rightBrace token.Pos + acceptableAlias []*ast.UnaryExpr +} + +func (r *implicitAliasing) ID() string { + return r.MetaData.ID +} + +func containsUnary(exprs []*ast.UnaryExpr, expr *ast.UnaryExpr) bool { + for _, e := range exprs { + if e == expr { + return true + } + } + return false +} + +func (r *implicitAliasing) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + switch node := n.(type) { + case *ast.RangeStmt: + // When presented with a range statement, get the underlying Object bound to + // by assignment and add it to our set (r.aliases) of objects to check for. + if key, ok := node.Value.(*ast.Ident); ok { + if assignment, ok := key.Obj.Decl.(*ast.AssignStmt); ok { + if len(assignment.Lhs) < 2 { + return nil, nil + } + + if object, ok := assignment.Lhs[1].(*ast.Ident); ok { + r.aliases[object.Obj] = struct{}{} + + if r.rightBrace < node.Body.Rbrace { + r.rightBrace = node.Body.Rbrace + } + } + } + } + case *ast.UnaryExpr: + // If this unary expression is outside of the last range statement we were looking at + // then clear the list of objects we're concerned about because they're no longer in + // scope + if node.Pos() > r.rightBrace { + r.aliases = make(map[*ast.Object]struct{}) + r.acceptableAlias = make([]*ast.UnaryExpr, 0) + } + + // Short circuit logic to skip checking aliases if we have nothing to check against. + if len(r.aliases) == 0 { + return nil, nil + } + + // If this unary is at the top level of a return statement then it is okay-- + // see *ast.ReturnStmt comment below. + if containsUnary(r.acceptableAlias, node) { + return nil, nil + } + + // If we find a unary op of & (reference) of an object within r.aliases, complain. + if ident, ok := node.X.(*ast.Ident); ok && node.Op.String() == "&" { + if _, contains := r.aliases[ident.Obj]; contains { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + case *ast.ReturnStmt: + // Returning a rangeStmt yielded value is acceptable since only one value will be returned + for _, item := range node.Results { + if unary, ok := item.(*ast.UnaryExpr); ok && unary.Op.String() == "&" { + r.acceptableAlias = append(r.acceptableAlias, unary) + } + } + } + + return nil, nil +} + +// NewImplicitAliasing detects implicit memory aliasing of type: for blah := SomeCall() {... SomeOtherCall(&blah) ...} +func NewImplicitAliasing(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return &implicitAliasing{ + aliases: make(map[*ast.Object]struct{}), + rightBrace: token.NoPos, + acceptableAlias: make([]*ast.UnaryExpr, 0), + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.Medium, + What: fmt.Sprintf("Implicit memory aliasing in for loop."), + }, + }, []ast.Node{(*ast.RangeStmt)(nil), (*ast.UnaryExpr)(nil), (*ast.ReturnStmt)(nil)} +} + +/* +This rule is prone to flag false positives. + +Within GoSec, the rule is just an AST match-- there are a handful of other +implementation strategies which might lend more nuance to the rule at the +cost of allowing false negatives. + +From a tooling side, I'd rather have this rule flag false positives than +potentially have some false negatives-- especially if the sentiment of this +rule (as I understand it, and Go) is that referencing a rangeStmt-yielded +value is kinda strange and does not have a strongly justified use case. + +Which is to say-- a false positive _should_ just be changed. +*/ diff --git a/vendor/github.com/securego/gosec/v2/rules/integer_overflow.go b/vendor/github.com/securego/gosec/v2/rules/integer_overflow.go new file mode 100644 index 000000000..dfcda94a8 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/integer_overflow.go @@ -0,0 +1,89 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "fmt" + "go/ast" + + "github.com/securego/gosec/v2" +) + +type integerOverflowCheck struct { + gosec.MetaData + calls gosec.CallList +} + +func (i *integerOverflowCheck) ID() string { + return i.MetaData.ID +} + +func (i *integerOverflowCheck) Match(node ast.Node, ctx *gosec.Context) (*gosec.Issue, error) { + var atoiVarObj map[*ast.Object]ast.Node + + // To check multiple lines, ctx.PassedValues is used to store temporary data. + if _, ok := ctx.PassedValues[i.ID()]; !ok { + atoiVarObj = make(map[*ast.Object]ast.Node) + ctx.PassedValues[i.ID()] = atoiVarObj + } else if pv, ok := ctx.PassedValues[i.ID()].(map[*ast.Object]ast.Node); ok { + atoiVarObj = pv + } else { + return nil, fmt.Errorf("PassedValues[%s] of Context is not map[*ast.Object]ast.Node, but %T", i.ID(), ctx.PassedValues[i.ID()]) + } + + // strconv.Atoi is a common function. + // To reduce false positives, This rule detects code which is converted to int32/int16 only. + switch n := node.(type) { + case *ast.AssignStmt: + for _, expr := range n.Rhs { + if callExpr, ok := expr.(*ast.CallExpr); ok && i.calls.ContainsPkgCallExpr(callExpr, ctx, false) != nil { + if idt, ok := n.Lhs[0].(*ast.Ident); ok && idt.Name != "_" { + // Example: + // v, _ := strconv.Atoi("1111") + // Add v's Obj to atoiVarObj map + atoiVarObj[idt.Obj] = n + } + } + } + case *ast.CallExpr: + if fun, ok := n.Fun.(*ast.Ident); ok { + if fun.Name == "int32" || fun.Name == "int16" { + if idt, ok := n.Args[0].(*ast.Ident); ok { + if n, ok := atoiVarObj[idt.Obj]; ok { + // Detect int32(v) and int16(v) + return gosec.NewIssue(ctx, n, i.ID(), i.What, i.Severity, i.Confidence), nil + } + } + } + } + } + + return nil, nil +} + +// NewIntegerOverflowCheck detects if there is potential Integer OverFlow +func NewIntegerOverflowCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + calls := gosec.NewCallList() + calls.Add("strconv", "Atoi") + return &integerOverflowCheck{ + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.High, + Confidence: gosec.Medium, + What: "Potential Integer overflow made by strconv.Atoi result conversion to int16/32", + }, + calls: calls, + }, []ast.Node{(*ast.FuncDecl)(nil), (*ast.AssignStmt)(nil), (*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/pprof.go b/vendor/github.com/securego/gosec/v2/rules/pprof.go new file mode 100644 index 000000000..4c99af752 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/pprof.go @@ -0,0 +1,42 @@ +package rules + +import ( + "go/ast" + + "github.com/securego/gosec/v2" +) + +type pprofCheck struct { + gosec.MetaData + importPath string + importName string +} + +// ID returns the ID of the check +func (p *pprofCheck) ID() string { + return p.MetaData.ID +} + +// Match checks for pprof imports +func (p *pprofCheck) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + if node, ok := n.(*ast.ImportSpec); ok { + if p.importPath == unquote(node.Path.Value) && node.Name != nil && p.importName == node.Name.Name { + return gosec.NewIssue(c, node, p.ID(), p.What, p.Severity, p.Confidence), nil + } + } + return nil, nil +} + +// NewPprofCheck detects when the profiling endpoint is automatically exposed +func NewPprofCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return &pprofCheck{ + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.High, + Confidence: gosec.High, + What: "Profiling endpoint is automatically exposed on /debug/pprof", + }, + importPath: "net/http/pprof", + importName: "_", + }, []ast.Node{(*ast.ImportSpec)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/rand.go b/vendor/github.com/securego/gosec/v2/rules/rand.go new file mode 100644 index 000000000..08c28fcad --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/rand.go @@ -0,0 +1,55 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + + "github.com/securego/gosec/v2" +) + +type weakRand struct { + gosec.MetaData + funcNames []string + packagePath string +} + +func (w *weakRand) ID() string { + return w.MetaData.ID +} + +func (w *weakRand) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + for _, funcName := range w.funcNames { + if _, matched := gosec.MatchCallByPackage(n, c, w.packagePath, funcName); matched { + return gosec.NewIssue(c, n, w.ID(), w.What, w.Severity, w.Confidence), nil + } + } + + return nil, nil +} + +// NewWeakRandCheck detects the use of random number generator that isn't cryptographically secure +func NewWeakRandCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return &weakRand{ + funcNames: []string{"Read", "Int"}, + packagePath: "math/rand", + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.High, + Confidence: gosec.Medium, + What: "Use of weak random number generator (math/rand instead of crypto/rand)", + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/readfile.go b/vendor/github.com/securego/gosec/v2/rules/readfile.go new file mode 100644 index 000000000..a52f7425f --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/readfile.go @@ -0,0 +1,106 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + "go/types" + + "github.com/securego/gosec/v2" +) + +type readfile struct { + gosec.MetaData + gosec.CallList + pathJoin gosec.CallList +} + +// ID returns the identifier for this rule +func (r *readfile) ID() string { + return r.MetaData.ID +} + +// isJoinFunc checks if there is a filepath.Join or other join function +func (r *readfile) isJoinFunc(n ast.Node, c *gosec.Context) bool { + if call := r.pathJoin.ContainsPkgCallExpr(n, c, false); call != nil { + for _, arg := range call.Args { + // edge case: check if one of the args is a BinaryExpr + if binExp, ok := arg.(*ast.BinaryExpr); ok { + // iterate and resolve all found identities from the BinaryExpr + if _, ok := gosec.FindVarIdentities(binExp, c); ok { + return true + } + } + + // try and resolve identity + if ident, ok := arg.(*ast.Ident); ok { + obj := c.Info.ObjectOf(ident) + if _, ok := obj.(*types.Var); ok && !gosec.TryResolve(ident, c) { + return true + } + } + } + } + return false +} + +// Match inspects AST nodes to determine if the match the methods `os.Open` or `ioutil.ReadFile` +func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + if node := r.ContainsPkgCallExpr(n, c, false); node != nil { + for _, arg := range node.Args { + // handles path joining functions in Arg + // eg. os.Open(filepath.Join("/tmp/", file)) + if callExpr, ok := arg.(*ast.CallExpr); ok { + if r.isJoinFunc(callExpr, c) { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + // handles binary string concatenation eg. ioutil.Readfile("/tmp/" + file + "/blob") + if binExp, ok := arg.(*ast.BinaryExpr); ok { + // resolve all found identities from the BinaryExpr + if _, ok := gosec.FindVarIdentities(binExp, c); ok { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + + if ident, ok := arg.(*ast.Ident); ok { + obj := c.Info.ObjectOf(ident) + if _, ok := obj.(*types.Var); ok && !gosec.TryResolve(ident, c) { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + } + } + return nil, nil +} + +// NewReadFile detects cases where we read files +func NewReadFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + rule := &readfile{ + pathJoin: gosec.NewCallList(), + CallList: gosec.NewCallList(), + MetaData: gosec.MetaData{ + ID: id, + What: "Potential file inclusion via variable", + Severity: gosec.Medium, + Confidence: gosec.High, + }, + } + rule.pathJoin.Add("path/filepath", "Join") + rule.pathJoin.Add("path", "Join") + rule.Add("io/ioutil", "ReadFile") + rule.Add("os", "Open") + return rule, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/rsa.go b/vendor/github.com/securego/gosec/v2/rules/rsa.go new file mode 100644 index 000000000..f2ed5db53 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/rsa.go @@ -0,0 +1,58 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "fmt" + "go/ast" + + "github.com/securego/gosec/v2" +) + +type weakKeyStrength struct { + gosec.MetaData + calls gosec.CallList + bits int +} + +func (w *weakKeyStrength) ID() string { + return w.MetaData.ID +} + +func (w *weakKeyStrength) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + if callExpr := w.calls.ContainsPkgCallExpr(n, c, false); callExpr != nil { + if bits, err := gosec.GetInt(callExpr.Args[1]); err == nil && bits < (int64)(w.bits) { + return gosec.NewIssue(c, n, w.ID(), w.What, w.Severity, w.Confidence), nil + } + } + return nil, nil +} + +// NewWeakKeyStrength builds a rule that detects RSA keys < 2048 bits +func NewWeakKeyStrength(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + calls := gosec.NewCallList() + calls.Add("crypto/rsa", "GenerateKey") + bits := 2048 + return &weakKeyStrength{ + calls: calls, + bits: bits, + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + What: fmt.Sprintf("RSA keys should be at least %d bits", bits), + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/rulelist.go b/vendor/github.com/securego/gosec/v2/rules/rulelist.go new file mode 100644 index 000000000..06e1dfb97 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/rulelist.go @@ -0,0 +1,116 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import "github.com/securego/gosec/v2" + +// RuleDefinition contains the description of a rule and a mechanism to +// create it. +type RuleDefinition struct { + ID string + Description string + Create gosec.RuleBuilder +} + +// RuleList is a mapping of rule ID's to rule definitions +type RuleList map[string]RuleDefinition + +// Builders returns all the create methods for a given rule list +func (rl RuleList) Builders() map[string]gosec.RuleBuilder { + builders := make(map[string]gosec.RuleBuilder) + for _, def := range rl { + builders[def.ID] = def.Create + } + return builders +} + +// RuleFilter can be used to include or exclude a rule depending on the return +// value of the function +type RuleFilter func(string) bool + +// NewRuleFilter is a closure that will include/exclude the rule ID's based on +// the supplied boolean value. +func NewRuleFilter(action bool, ruleIDs ...string) RuleFilter { + rulelist := make(map[string]bool) + for _, rule := range ruleIDs { + rulelist[rule] = true + } + return func(rule string) bool { + if _, found := rulelist[rule]; found { + return action + } + return !action + } +} + +// Generate the list of rules to use +func Generate(filters ...RuleFilter) RuleList { + rules := []RuleDefinition{ + // misc + {"G101", "Look for hardcoded credentials", NewHardcodedCredentials}, + {"G102", "Bind to all interfaces", NewBindsToAllNetworkInterfaces}, + {"G103", "Audit the use of unsafe block", NewUsingUnsafe}, + {"G104", "Audit errors not checked", NewNoErrorCheck}, + {"G106", "Audit the use of ssh.InsecureIgnoreHostKey function", NewSSHHostKey}, + {"G107", "Url provided to HTTP request as taint input", NewSSRFCheck}, + {"G108", "Profiling endpoint is automatically exposed", NewPprofCheck}, + {"G109", "Converting strconv.Atoi result to int32/int16", NewIntegerOverflowCheck}, + {"G110", "Detect io.Copy instead of io.CopyN when decompression", NewDecompressionBombCheck}, + + // injection + {"G201", "SQL query construction using format string", NewSQLStrFormat}, + {"G202", "SQL query construction using string concatenation", NewSQLStrConcat}, + {"G203", "Use of unescaped data in HTML templates", NewTemplateCheck}, + {"G204", "Audit use of command execution", NewSubproc}, + + // filesystem + {"G301", "Poor file permissions used when creating a directory", NewMkdirPerms}, + {"G302", "Poor file permissions used when creation file or using chmod", NewFilePerms}, + {"G303", "Creating tempfile using a predictable path", NewBadTempFile}, + {"G304", "File path provided as taint input", NewReadFile}, + {"G305", "File path traversal when extracting zip archive", NewArchive}, + {"G306", "Poor file permissions used when writing to a file", NewWritePerms}, + {"G307", "Unsafe defer call of a method returning an error", NewDeferredClosing}, + + // crypto + {"G401", "Detect the usage of DES, RC4, MD5 or SHA1", NewUsesWeakCryptography}, + {"G402", "Look for bad TLS connection settings", NewIntermediateTLSCheck}, + {"G403", "Ensure minimum RSA key length of 2048 bits", NewWeakKeyStrength}, + {"G404", "Insecure random number source (rand)", NewWeakRandCheck}, + + // blacklist + {"G501", "Import blacklist: crypto/md5", NewBlacklistedImportMD5}, + {"G502", "Import blacklist: crypto/des", NewBlacklistedImportDES}, + {"G503", "Import blacklist: crypto/rc4", NewBlacklistedImportRC4}, + {"G504", "Import blacklist: net/http/cgi", NewBlacklistedImportCGI}, + {"G505", "Import blacklist: crypto/sha1", NewBlacklistedImportSHA1}, + + // memory safety + {"G601", "Implicit memory aliasing in RangeStmt", NewImplicitAliasing}, + } + + ruleMap := make(map[string]RuleDefinition) + +RULES: + for _, rule := range rules { + for _, filter := range filters { + if filter(rule.ID) { + continue RULES + } + } + ruleMap[rule.ID] = rule + } + return ruleMap +} diff --git a/vendor/github.com/securego/gosec/v2/rules/sql.go b/vendor/github.com/securego/gosec/v2/rules/sql.go new file mode 100644 index 000000000..3279a3400 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/sql.go @@ -0,0 +1,219 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + "regexp" + + "github.com/securego/gosec/v2" +) + +type sqlStatement struct { + gosec.MetaData + + // Contains a list of patterns which must all match for the rule to match. + patterns []*regexp.Regexp +} + +func (s *sqlStatement) ID() string { + return s.MetaData.ID +} + +// See if the string matches the patterns for the statement. +func (s *sqlStatement) MatchPatterns(str string) bool { + for _, pattern := range s.patterns { + if !pattern.MatchString(str) { + return false + } + } + return true +} + +type sqlStrConcat struct { + sqlStatement +} + +func (s *sqlStrConcat) ID() string { + return s.MetaData.ID +} + +// see if we can figure out what it is +func (s *sqlStrConcat) checkObject(n *ast.Ident, c *gosec.Context) bool { + if n.Obj != nil { + return n.Obj.Kind != ast.Var && n.Obj.Kind != ast.Fun + } + + // Try to resolve unresolved identifiers using other files in same package + for _, file := range c.PkgFiles { + if node, ok := file.Scope.Objects[n.String()]; ok { + return node.Kind != ast.Var && node.Kind != ast.Fun + } + } + return false +} + +// Look for "SELECT * FROM table WHERE " + " ' OR 1=1" +func (s *sqlStrConcat) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + if node, ok := n.(*ast.BinaryExpr); ok { + if start, ok := node.X.(*ast.BasicLit); ok { + if str, e := gosec.GetString(start); e == nil { + if !s.MatchPatterns(str) { + return nil, nil + } + if _, ok := node.Y.(*ast.BasicLit); ok { + return nil, nil // string cat OK + } + if second, ok := node.Y.(*ast.Ident); ok && s.checkObject(second, c) { + return nil, nil + } + return gosec.NewIssue(c, n, s.ID(), s.What, s.Severity, s.Confidence), nil + } + } + } + return nil, nil +} + +// NewSQLStrConcat looks for cases where we are building SQL strings via concatenation +func NewSQLStrConcat(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return &sqlStrConcat{ + sqlStatement: sqlStatement{ + patterns: []*regexp.Regexp{ + regexp.MustCompile(`(?)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) `), + }, + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + What: "SQL string concatenation", + }, + }, + }, []ast.Node{(*ast.BinaryExpr)(nil)} +} + +type sqlStrFormat struct { + sqlStatement + calls gosec.CallList + noIssue gosec.CallList + noIssueQuoted gosec.CallList +} + +// see if we can figure out what it is +func (s *sqlStrFormat) constObject(e ast.Expr, c *gosec.Context) bool { + n, ok := e.(*ast.Ident) + if !ok { + return false + } + + if n.Obj != nil { + return n.Obj.Kind == ast.Con + } + + // Try to resolve unresolved identifiers using other files in same package + for _, file := range c.PkgFiles { + if node, ok := file.Scope.Objects[n.String()]; ok { + return node.Kind == ast.Con + } + } + return false +} + +// Looks for "fmt.Sprintf("SELECT * FROM foo where '%s', userInput)" +func (s *sqlStrFormat) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + + // argIndex changes the function argument which gets matched to the regex + argIndex := 0 + + // TODO(gm) improve confidence if database/sql is being used + if node := s.calls.ContainsPkgCallExpr(n, c, false); node != nil { + // if the function is fmt.Fprintf, search for SQL statement in Args[1] instead + if sel, ok := node.Fun.(*ast.SelectorExpr); ok { + if sel.Sel.Name == "Fprintf" { + // if os.Stderr or os.Stdout is in Arg[0], mark as no issue + if arg, ok := node.Args[0].(*ast.SelectorExpr); ok { + if ident, ok := arg.X.(*ast.Ident); ok { + if s.noIssue.Contains(ident.Name, arg.Sel.Name) { + return nil, nil + } + } + } + // the function is Fprintf so set argIndex = 1 + argIndex = 1 + } + } + + // no formatter + if len(node.Args) == 0 { + return nil, nil + } + + var formatter string + + // concats callexpr arg strings together if needed before regex evaluation + if argExpr, ok := node.Args[argIndex].(*ast.BinaryExpr); ok { + if fullStr, ok := gosec.ConcatString(argExpr); ok { + formatter = fullStr + } + } else if arg, e := gosec.GetString(node.Args[argIndex]); e == nil { + formatter = arg + } + if len(formatter) <= 0 { + return nil, nil + } + + // If all formatter args are quoted or constant, then the SQL construction is safe + if argIndex+1 < len(node.Args) { + allSafe := true + for _, arg := range node.Args[argIndex+1:] { + if n := s.noIssueQuoted.ContainsPkgCallExpr(arg, c, true); n == nil && !s.constObject(arg, c) { + allSafe = false + break + } + } + if allSafe { + return nil, nil + } + } + if s.MatchPatterns(formatter) { + return gosec.NewIssue(c, n, s.ID(), s.What, s.Severity, s.Confidence), nil + } + } + return nil, nil +} + +// NewSQLStrFormat looks for cases where we're building SQL query strings using format strings +func NewSQLStrFormat(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + rule := &sqlStrFormat{ + calls: gosec.NewCallList(), + noIssue: gosec.NewCallList(), + noIssueQuoted: gosec.NewCallList(), + sqlStatement: sqlStatement{ + patterns: []*regexp.Regexp{ + regexp.MustCompile("(?)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) "), + regexp.MustCompile("%[^bdoxXfFp]"), + }, + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + What: "SQL string formatting", + }, + }, + } + rule.calls.AddAll("fmt", "Sprint", "Sprintf", "Sprintln", "Fprintf") + rule.noIssue.AddAll("os", "Stdout", "Stderr") + rule.noIssueQuoted.Add("github.com/lib/pq", "QuoteIdentifier") + return rule, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/ssh.go b/vendor/github.com/securego/gosec/v2/rules/ssh.go new file mode 100644 index 000000000..01f37da51 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/ssh.go @@ -0,0 +1,38 @@ +package rules + +import ( + "go/ast" + + "github.com/securego/gosec/v2" +) + +type sshHostKey struct { + gosec.MetaData + pkg string + calls []string +} + +func (r *sshHostKey) ID() string { + return r.MetaData.ID +} + +func (r *sshHostKey) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) { + if _, matches := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matches { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + return nil, nil +} + +// NewSSHHostKey rule detects the use of insecure ssh HostKeyCallback. +func NewSSHHostKey(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return &sshHostKey{ + pkg: "golang.org/x/crypto/ssh", + calls: []string{"InsecureIgnoreHostKey"}, + MetaData: gosec.MetaData{ + ID: id, + What: "Use of ssh InsecureIgnoreHostKey should be audited", + Severity: gosec.Medium, + Confidence: gosec.High, + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/ssrf.go b/vendor/github.com/securego/gosec/v2/rules/ssrf.go new file mode 100644 index 000000000..86bb8278d --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/ssrf.go @@ -0,0 +1,66 @@ +package rules + +import ( + "go/ast" + "go/types" + + "github.com/securego/gosec/v2" +) + +type ssrf struct { + gosec.MetaData + gosec.CallList +} + +// ID returns the identifier for this rule +func (r *ssrf) ID() string { + return r.MetaData.ID +} + +// ResolveVar tries to resolve the first argument of a call expression +// The first argument is the url +func (r *ssrf) ResolveVar(n *ast.CallExpr, c *gosec.Context) bool { + if len(n.Args) > 0 { + arg := n.Args[0] + if ident, ok := arg.(*ast.Ident); ok { + obj := c.Info.ObjectOf(ident) + if _, ok := obj.(*types.Var); ok { + scope := c.Pkg.Scope() + if scope != nil && scope.Lookup(ident.Name) != nil { + // a URL defined in a variable at package scope can be changed at any time + return true + } + if !gosec.TryResolve(ident, c) { + return true + } + } + } + } + return false +} + +// Match inspects AST nodes to determine if certain net/http methods are called with variable input +func (r *ssrf) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + // Call expression is using http package directly + if node := r.ContainsPkgCallExpr(n, c, false); node != nil { + if r.ResolveVar(node, c) { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + return nil, nil +} + +// NewSSRFCheck detects cases where HTTP requests are sent +func NewSSRFCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + rule := &ssrf{ + CallList: gosec.NewCallList(), + MetaData: gosec.MetaData{ + ID: id, + What: "Potential HTTP request made with variable url", + Severity: gosec.Medium, + Confidence: gosec.Medium, + }, + } + rule.AddAll("net/http", "Do", "Get", "Head", "Post", "PostForm", "RoundTrip") + return rule, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/subproc.go b/vendor/github.com/securego/gosec/v2/rules/subproc.go new file mode 100644 index 000000000..30c32cc03 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/subproc.go @@ -0,0 +1,85 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + "go/types" + + "github.com/securego/gosec/v2" +) + +type subprocess struct { + gosec.MetaData + gosec.CallList +} + +func (r *subprocess) ID() string { + return r.MetaData.ID +} + +// TODO(gm) The only real potential for command injection with a Go project +// is something like this: +// +// syscall.Exec("/bin/sh", []string{"-c", tainted}) +// +// E.g. Input is correctly escaped but the execution context being used +// is unsafe. For example: +// +// syscall.Exec("echo", "foobar" + tainted) +func (r *subprocess) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + if node := r.ContainsPkgCallExpr(n, c, false); node != nil { + args := node.Args + if r.isContext(n, c) { + args = args[1:] + } + for _, arg := range args { + if ident, ok := arg.(*ast.Ident); ok { + obj := c.Info.ObjectOf(ident) + if _, ok := obj.(*types.Var); ok && !gosec.TryResolve(ident, c) { + return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with variable", gosec.Medium, gosec.High), nil + } + } else if !gosec.TryResolve(arg, c) { + // the arg is not a constant or a variable but instead a function call or os.Args[i] + return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with function call as argument or cmd arguments", gosec.Medium, gosec.High), nil + } + } + } + return nil, nil +} + +// isContext checks whether or not the node is a CommandContext call or not +// Thi is requried in order to skip the first argument from the check. +func (r *subprocess) isContext(n ast.Node, ctx *gosec.Context) bool { + selector, indent, err := gosec.GetCallInfo(n, ctx) + if err != nil { + return false + } + if selector == "exec" && indent == "CommandContext" { + return true + } + return false +} + +// NewSubproc detects cases where we are forking out to an external process +func NewSubproc(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + rule := &subprocess{gosec.MetaData{ID: id}, gosec.NewCallList()} + rule.Add("os/exec", "Command") + rule.Add("os/exec", "CommandContext") + rule.Add("syscall", "Exec") + rule.Add("syscall", "ForkExec") + rule.Add("syscall", "StartProcess") + return rule, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/tempfiles.go b/vendor/github.com/securego/gosec/v2/rules/tempfiles.go new file mode 100644 index 000000000..36f0f979b --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/tempfiles.go @@ -0,0 +1,58 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + "regexp" + + "github.com/securego/gosec/v2" +) + +type badTempFile struct { + gosec.MetaData + calls gosec.CallList + args *regexp.Regexp +} + +func (t *badTempFile) ID() string { + return t.MetaData.ID +} + +func (t *badTempFile) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) { + if node := t.calls.ContainsPkgCallExpr(n, c, false); node != nil { + if arg, e := gosec.GetString(node.Args[0]); t.args.MatchString(arg) && e == nil { + return gosec.NewIssue(c, n, t.ID(), t.What, t.Severity, t.Confidence), nil + } + } + return nil, nil +} + +// NewBadTempFile detects direct writes to predictable path in temporary directory +func NewBadTempFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + calls := gosec.NewCallList() + calls.Add("io/ioutil", "WriteFile") + calls.Add("os", "Create") + return &badTempFile{ + calls: calls, + args: regexp.MustCompile(`^/tmp/.*$|^/var/tmp/.*$`), + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + What: "File creation in shared tmp directory without using ioutil.Tempfile", + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/templates.go b/vendor/github.com/securego/gosec/v2/rules/templates.go new file mode 100644 index 000000000..819240905 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/templates.go @@ -0,0 +1,61 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + + "github.com/securego/gosec/v2" +) + +type templateCheck struct { + gosec.MetaData + calls gosec.CallList +} + +func (t *templateCheck) ID() string { + return t.MetaData.ID +} + +func (t *templateCheck) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + if node := t.calls.ContainsPkgCallExpr(n, c, false); node != nil { + for _, arg := range node.Args { + if _, ok := arg.(*ast.BasicLit); !ok { // basic lits are safe + return gosec.NewIssue(c, n, t.ID(), t.What, t.Severity, t.Confidence), nil + } + } + } + return nil, nil +} + +// NewTemplateCheck constructs the template check rule. This rule is used to +// find use of templates where HTML/JS escaping is not being used +func NewTemplateCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + + calls := gosec.NewCallList() + calls.Add("html/template", "HTML") + calls.Add("html/template", "HTMLAttr") + calls.Add("html/template", "JS") + calls.Add("html/template", "URL") + return &templateCheck{ + calls: calls, + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.Low, + What: "this method will not auto-escape HTML. Verify data is well formed.", + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/tls.go b/vendor/github.com/securego/gosec/v2/rules/tls.go new file mode 100644 index 000000000..fab9ee164 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/tls.go @@ -0,0 +1,130 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:generate tlsconfig + +package rules + +import ( + "fmt" + "go/ast" + + "github.com/securego/gosec/v2" +) + +type insecureConfigTLS struct { + gosec.MetaData + MinVersion int16 + MaxVersion int16 + requiredType string + goodCiphers []string +} + +func (t *insecureConfigTLS) ID() string { + return t.MetaData.ID +} + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} + +func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gosec.Context) *gosec.Issue { + + if ciphers, ok := n.(*ast.CompositeLit); ok { + for _, cipher := range ciphers.Elts { + if ident, ok := cipher.(*ast.SelectorExpr); ok { + if !stringInSlice(ident.Sel.Name, t.goodCiphers) { + err := fmt.Sprintf("TLS Bad Cipher Suite: %s", ident.Sel.Name) + return gosec.NewIssue(c, ident, t.ID(), err, gosec.High, gosec.High) + } + } + } + } + return nil +} + +func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gosec.Context) *gosec.Issue { + if ident, ok := n.Key.(*ast.Ident); ok { + switch ident.Name { + + case "InsecureSkipVerify": + if node, ok := n.Value.(*ast.Ident); ok { + if node.Name != "false" { + return gosec.NewIssue(c, n, t.ID(), "TLS InsecureSkipVerify set true.", gosec.High, gosec.High) + } + } else { + // TODO(tk): symbol tab look up to get the actual value + return gosec.NewIssue(c, n, t.ID(), "TLS InsecureSkipVerify may be true.", gosec.High, gosec.Low) + } + + case "PreferServerCipherSuites": + if node, ok := n.Value.(*ast.Ident); ok { + if node.Name == "false" { + return gosec.NewIssue(c, n, t.ID(), "TLS PreferServerCipherSuites set false.", gosec.Medium, gosec.High) + } + } else { + // TODO(tk): symbol tab look up to get the actual value + return gosec.NewIssue(c, n, t.ID(), "TLS PreferServerCipherSuites may be false.", gosec.Medium, gosec.Low) + } + + case "MinVersion": + if ival, ierr := gosec.GetInt(n.Value); ierr == nil { + if (int16)(ival) < t.MinVersion { + return gosec.NewIssue(c, n, t.ID(), "TLS MinVersion too low.", gosec.High, gosec.High) + } + // TODO(tk): symbol tab look up to get the actual value + return gosec.NewIssue(c, n, t.ID(), "TLS MinVersion may be too low.", gosec.High, gosec.Low) + } + + case "MaxVersion": + if ival, ierr := gosec.GetInt(n.Value); ierr == nil { + if (int16)(ival) < t.MaxVersion { + return gosec.NewIssue(c, n, t.ID(), "TLS MaxVersion too low.", gosec.High, gosec.High) + } + // TODO(tk): symbol tab look up to get the actual value + return gosec.NewIssue(c, n, t.ID(), "TLS MaxVersion may be too low.", gosec.High, gosec.Low) + } + + case "CipherSuites": + if ret := t.processTLSCipherSuites(n.Value, c); ret != nil { + return ret + } + + } + + } + return nil +} + +func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil { + actualType := c.Info.TypeOf(complit.Type) + if actualType != nil && actualType.String() == t.requiredType { + for _, elt := range complit.Elts { + if kve, ok := elt.(*ast.KeyValueExpr); ok { + issue := t.processTLSConfVal(kve, c) + if issue != nil { + return issue, nil + } + } + } + } + } + return nil, nil +} diff --git a/vendor/github.com/securego/gosec/v2/rules/tls_config.go b/vendor/github.com/securego/gosec/v2/rules/tls_config.go new file mode 100644 index 000000000..ff4f3fe2e --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/tls_config.go @@ -0,0 +1,88 @@ +package rules + +import ( + "go/ast" + + "github.com/securego/gosec/v2" +) + +// NewModernTLSCheck creates a check for Modern TLS ciphers +// DO NOT EDIT - generated by tlsconfig tool +func NewModernTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return &insecureConfigTLS{ + MetaData: gosec.MetaData{ID: id}, + requiredType: "crypto/tls.Config", + MinVersion: 0x0304, + MaxVersion: 0x0304, + goodCiphers: []string{ + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256", + }, + }, []ast.Node{(*ast.CompositeLit)(nil)} +} + +// NewIntermediateTLSCheck creates a check for Intermediate TLS ciphers +// DO NOT EDIT - generated by tlsconfig tool +func NewIntermediateTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return &insecureConfigTLS{ + MetaData: gosec.MetaData{ID: id}, + requiredType: "crypto/tls.Config", + MinVersion: 0x0303, + MaxVersion: 0x0304, + goodCiphers: []string{ + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", + }, + }, []ast.Node{(*ast.CompositeLit)(nil)} +} + +// NewOldTLSCheck creates a check for Old TLS ciphers +// DO NOT EDIT - generated by tlsconfig tool +func NewOldTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return &insecureConfigTLS{ + MetaData: gosec.MetaData{ID: id}, + requiredType: "crypto/tls.Config", + MinVersion: 0x0301, + MaxVersion: 0x0304, + goodCiphers: []string{ + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_3DES_EDE_CBC_SHA", + }, + }, []ast.Node{(*ast.CompositeLit)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/unsafe.go b/vendor/github.com/securego/gosec/v2/rules/unsafe.go new file mode 100644 index 000000000..88a298fb5 --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/unsafe.go @@ -0,0 +1,53 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + + "github.com/securego/gosec/v2" +) + +type usingUnsafe struct { + gosec.MetaData + pkg string + calls []string +} + +func (r *usingUnsafe) ID() string { + return r.MetaData.ID +} + +func (r *usingUnsafe) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) { + if _, matches := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matches { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + return nil, nil +} + +// NewUsingUnsafe rule detects the use of the unsafe package. This is only +// really useful for auditing purposes. +func NewUsingUnsafe(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + return &usingUnsafe{ + pkg: "unsafe", + calls: []string{"Alignof", "Offsetof", "Sizeof", "Pointer"}, + MetaData: gosec.MetaData{ + ID: id, + What: "Use of unsafe calls should be audited", + Severity: gosec.Low, + Confidence: gosec.High, + }, + }, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/securego/gosec/v2/rules/weakcrypto.go b/vendor/github.com/securego/gosec/v2/rules/weakcrypto.go new file mode 100644 index 000000000..0e45393db --- /dev/null +++ b/vendor/github.com/securego/gosec/v2/rules/weakcrypto.go @@ -0,0 +1,58 @@ +// (c) Copyright 2016 Hewlett Packard Enterprise Development LP +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rules + +import ( + "go/ast" + + "github.com/securego/gosec/v2" +) + +type usesWeakCryptography struct { + gosec.MetaData + blacklist map[string][]string +} + +func (r *usesWeakCryptography) ID() string { + return r.MetaData.ID +} + +func (r *usesWeakCryptography) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { + for pkg, funcs := range r.blacklist { + if _, matched := gosec.MatchCallByPackage(n, c, pkg, funcs...); matched { + return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil + } + } + return nil, nil +} + +// NewUsesWeakCryptography detects uses of des.* md5.* or rc4.* +func NewUsesWeakCryptography(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { + calls := make(map[string][]string) + calls["crypto/des"] = []string{"NewCipher", "NewTripleDESCipher"} + calls["crypto/md5"] = []string{"New", "Sum"} + calls["crypto/sha1"] = []string{"New", "Sum"} + calls["crypto/rc4"] = []string{"NewCipher"} + rule := &usesWeakCryptography{ + blacklist: calls, + MetaData: gosec.MetaData{ + ID: id, + Severity: gosec.Medium, + Confidence: gosec.High, + What: "Use of weak cryptographic primitive", + }, + } + return rule, []ast.Node{(*ast.CallExpr)(nil)} +} diff --git a/vendor/github.com/sirupsen/logrus/.gitignore b/vendor/github.com/sirupsen/logrus/.gitignore new file mode 100644 index 000000000..6b7d7d1e8 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/.gitignore @@ -0,0 +1,2 @@ +logrus +vendor diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml new file mode 100644 index 000000000..848938a6d --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/.travis.yml @@ -0,0 +1,25 @@ +language: go +go_import_path: github.com/sirupsen/logrus +git: + depth: 1 +env: + - GO111MODULE=on + - GO111MODULE=off +go: [ 1.11.x, 1.12.x ] +os: [ linux, osx ] +matrix: + exclude: + - go: 1.12.x + env: GO111MODULE=off + - go: 1.11.x + os: osx +install: + - ./travis/install.sh + - if [[ "$GO111MODULE" == "on" ]]; then go mod download; fi + - if [[ "$GO111MODULE" == "off" ]]; then go get github.com/stretchr/testify/assert golang.org/x/sys/unix github.com/konsorten/go-windows-terminal-sequences; fi +script: + - ./travis/cross_build.sh + - export GOMAXPROCS=4 + - export GORACE=halt_on_error=1 + - go test -race -v ./... + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md new file mode 100644 index 000000000..51a7ab0ca --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md @@ -0,0 +1,200 @@ +# 1.4.2 + * Fixes build break for plan9, nacl, solaris +# 1.4.1 +This new release introduces: + * Enhance TextFormatter to not print caller information when they are empty (#944) + * Remove dependency on golang.org/x/crypto (#932, #943) + +Fixes: + * Fix Entry.WithContext method to return a copy of the initial entry (#941) + +# 1.4.0 +This new release introduces: + * Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848). + * Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter (#909, #911) + * Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919). + +Fixes: + * Fix wrong method calls `Logger.Print` and `Logger.Warningln` (#893). + * Update `Entry.Logf` to not do string formatting unless the log level is enabled (#903) + * Fix infinite recursion on unknown `Level.String()` (#907) + * Fix race condition in `getCaller` (#916). + + +# 1.3.0 +This new release introduces: + * Log, Logf, Logln functions for Logger and Entry that take a Level + +Fixes: + * Building prometheus node_exporter on AIX (#840) + * Race condition in TextFormatter (#468) + * Travis CI import path (#868) + * Remove coloured output on Windows (#862) + * Pointer to func as field in JSONFormatter (#870) + * Properly marshal Levels (#873) + +# 1.2.0 +This new release introduces: + * A new method `SetReportCaller` in the `Logger` to enable the file, line and calling function from which the trace has been issued + * A new trace level named `Trace` whose level is below `Debug` + * A configurable exit function to be called upon a Fatal trace + * The `Level` object now implements `encoding.TextUnmarshaler` interface + +# 1.1.1 +This is a bug fix release. + * fix the build break on Solaris + * don't drop a whole trace in JSONFormatter when a field param is a function pointer which can not be serialized + +# 1.1.0 +This new release introduces: + * several fixes: + * a fix for a race condition on entry formatting + * proper cleanup of previously used entries before putting them back in the pool + * the extra new line at the end of message in text formatter has been removed + * a new global public API to check if a level is activated: IsLevelEnabled + * the following methods have been added to the Logger object + * IsLevelEnabled + * SetFormatter + * SetOutput + * ReplaceHooks + * introduction of go module + * an indent configuration for the json formatter + * output colour support for windows + * the field sort function is now configurable for text formatter + * the CLICOLOR and CLICOLOR\_FORCE environment variable support in text formater + +# 1.0.6 + +This new release introduces: + * a new api WithTime which allows to easily force the time of the log entry + which is mostly useful for logger wrapper + * a fix reverting the immutability of the entry given as parameter to the hooks + a new configuration field of the json formatter in order to put all the fields + in a nested dictionnary + * a new SetOutput method in the Logger + * a new configuration of the textformatter to configure the name of the default keys + * a new configuration of the text formatter to disable the level truncation + +# 1.0.5 + +* Fix hooks race (#707) +* Fix panic deadlock (#695) + +# 1.0.4 + +* Fix race when adding hooks (#612) +* Fix terminal check in AppEngine (#635) + +# 1.0.3 + +* Replace example files with testable examples + +# 1.0.2 + +* bug: quote non-string values in text formatter (#583) +* Make (*Logger) SetLevel a public method + +# 1.0.1 + +* bug: fix escaping in text formatter (#575) + +# 1.0.0 + +* Officially changed name to lower-case +* bug: colors on Windows 10 (#541) +* bug: fix race in accessing level (#512) + +# 0.11.5 + +* feature: add writer and writerlevel to entry (#372) + +# 0.11.4 + +* bug: fix undefined variable on solaris (#493) + +# 0.11.3 + +* formatter: configure quoting of empty values (#484) +* formatter: configure quoting character (default is `"`) (#484) +* bug: fix not importing io correctly in non-linux environments (#481) + +# 0.11.2 + +* bug: fix windows terminal detection (#476) + +# 0.11.1 + +* bug: fix tty detection with custom out (#471) + +# 0.11.0 + +* performance: Use bufferpool to allocate (#370) +* terminal: terminal detection for app-engine (#343) +* feature: exit handler (#375) + +# 0.10.0 + +* feature: Add a test hook (#180) +* feature: `ParseLevel` is now case-insensitive (#326) +* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308) +* performance: avoid re-allocations on `WithFields` (#335) + +# 0.9.0 + +* logrus/text_formatter: don't emit empty msg +* logrus/hooks/airbrake: move out of main repository +* logrus/hooks/sentry: move out of main repository +* logrus/hooks/papertrail: move out of main repository +* logrus/hooks/bugsnag: move out of main repository +* logrus/core: run tests with `-race` +* logrus/core: detect TTY based on `stderr` +* logrus/core: support `WithError` on logger +* logrus/core: Solaris support + +# 0.8.7 + +* logrus/core: fix possible race (#216) +* logrus/doc: small typo fixes and doc improvements + + +# 0.8.6 + +* hooks/raven: allow passing an initialized client + +# 0.8.5 + +* logrus/core: revert #208 + +# 0.8.4 + +* formatter/text: fix data race (#218) + +# 0.8.3 + +* logrus/core: fix entry log level (#208) +* logrus/core: improve performance of text formatter by 40% +* logrus/core: expose `LevelHooks` type +* logrus/core: add support for DragonflyBSD and NetBSD +* formatter/text: print structs more verbosely + +# 0.8.2 + +* logrus: fix more Fatal family functions + +# 0.8.1 + +* logrus: fix not exiting on `Fatalf` and `Fatalln` + +# 0.8.0 + +* logrus: defaults to stderr instead of stdout +* hooks/sentry: add special field for `*http.Request` +* formatter/text: ignore Windows for colors + +# 0.7.3 + +* formatter/\*: allow configuration of timestamp layout + +# 0.7.2 + +* formatter/text: Add configuration option for time format (#158) diff --git a/vendor/github.com/sirupsen/logrus/LICENSE b/vendor/github.com/sirupsen/logrus/LICENSE new file mode 100644 index 000000000..f090cb42f --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Simon Eskildsen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md new file mode 100644 index 000000000..a4796eb07 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/README.md @@ -0,0 +1,495 @@ +# Logrus :walrus: [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus) + +Logrus is a structured logger for Go (golang), completely API compatible with +the standard library logger. + +**Seeing weird case-sensitive problems?** It's in the past been possible to +import Logrus as both upper- and lower-case. Due to the Go package environment, +this caused issues in the community and we needed a standard. Some environments +experienced problems with the upper-case variant, so the lower-case was decided. +Everything using `logrus` will need to use the lower-case: +`github.com/sirupsen/logrus`. Any package that isn't, should be changed. + +To fix Glide, see [these +comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437). +For an in-depth explanation of the casing issue, see [this +comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276). + +**Are you interested in assisting in maintaining Logrus?** Currently I have a +lot of obligations, and I am unable to provide Logrus with the maintainership it +needs. If you'd like to help, please reach out to me at `simon at author's +username dot com`. + +Nicely color-coded in development (when a TTY is attached, otherwise just +plain text): + +![Colored](http://i.imgur.com/PY7qMwd.png) + +With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash +or Splunk: + +```json +{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the +ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"} + +{"level":"warning","msg":"The group's number increased tremendously!", +"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"A giant walrus appears!", +"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.", +"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"} + +{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true, +"time":"2014-03-10 19:57:38.562543128 -0400 EDT"} +``` + +With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not +attached, the output is compatible with the +[logfmt](http://godoc.org/github.com/kr/logfmt) format: + +```text +time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8 +time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 +time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true +time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4 +time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009 +time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true +``` +To ensure this behaviour even if a TTY is attached, set your formatter as follows: + +```go + log.SetFormatter(&log.TextFormatter{ + DisableColors: true, + FullTimestamp: true, + }) +``` + +#### Logging Method Name + +If you wish to add the calling method as a field, instruct the logger via: +```go +log.SetReportCaller(true) +``` +This adds the caller as 'method' like so: + +```json +{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by", +"time":"2014-03-10 19:57:38.562543129 -0400 EDT"} +``` + +```text +time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin +``` +Note that this does add measurable overhead - the cost will depend on the version of Go, but is +between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your +environment via benchmarks: +``` +go test -bench=.*CallerTracing +``` + + +#### Case-sensitivity + +The organization's name was changed to lower-case--and this will not be changed +back. If you are getting import conflicts due to case sensitivity, please use +the lower-case import: `github.com/sirupsen/logrus`. + +#### Example + +The simplest way to use Logrus is simply the package-level exported logger: + +```go +package main + +import ( + log "github.com/sirupsen/logrus" +) + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + }).Info("A walrus appears") +} +``` + +Note that it's completely api-compatible with the stdlib logger, so you can +replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"` +and you'll now have the flexibility of Logrus. You can customize it all you +want: + +```go +package main + +import ( + "os" + log "github.com/sirupsen/logrus" +) + +func init() { + // Log as JSON instead of the default ASCII formatter. + log.SetFormatter(&log.JSONFormatter{}) + + // Output to stdout instead of the default stderr + // Can be any io.Writer, see below for File example + log.SetOutput(os.Stdout) + + // Only log the warning severity or above. + log.SetLevel(log.WarnLevel) +} + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") + + log.WithFields(log.Fields{ + "omg": true, + "number": 122, + }).Warn("The group's number increased tremendously!") + + log.WithFields(log.Fields{ + "omg": true, + "number": 100, + }).Fatal("The ice breaks!") + + // A common pattern is to re-use fields between logging statements by re-using + // the logrus.Entry returned from WithFields() + contextLogger := log.WithFields(log.Fields{ + "common": "this is a common field", + "other": "I also should be logged always", + }) + + contextLogger.Info("I'll be logged with common and other field") + contextLogger.Info("Me too") +} +``` + +For more advanced usage such as logging to multiple locations from the same +application, you can also create an instance of the `logrus` Logger: + +```go +package main + +import ( + "os" + "github.com/sirupsen/logrus" +) + +// Create a new instance of the logger. You can have any number of instances. +var log = logrus.New() + +func main() { + // The API for setting attributes is a little different than the package level + // exported logger. See Godoc. + log.Out = os.Stdout + + // You could set this to any `io.Writer` such as a file + // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) + // if err == nil { + // log.Out = file + // } else { + // log.Info("Failed to log to file, using default stderr") + // } + + log.WithFields(logrus.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") +} +``` + +#### Fields + +Logrus encourages careful, structured logging through logging fields instead of +long, unparseable error messages. For example, instead of: `log.Fatalf("Failed +to send event %s to topic %s with key %d")`, you should log the much more +discoverable: + +```go +log.WithFields(log.Fields{ + "event": event, + "topic": topic, + "key": key, +}).Fatal("Failed to send event") +``` + +We've found this API forces you to think about logging in a way that produces +much more useful logging messages. We've been in countless situations where just +a single added field to a log statement that was already there would've saved us +hours. The `WithFields` call is optional. + +In general, with Logrus using any of the `printf`-family functions should be +seen as a hint you should add a field, however, you can still use the +`printf`-family functions with Logrus. + +#### Default Fields + +Often it's helpful to have fields _always_ attached to log statements in an +application or parts of one. For example, you may want to always log the +`request_id` and `user_ip` in the context of a request. Instead of writing +`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on +every line, you can create a `logrus.Entry` to pass around instead: + +```go +requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip}) +requestLogger.Info("something happened on that request") # will log request_id and user_ip +requestLogger.Warn("something not great happened") +``` + +#### Hooks + +You can add hooks for logging levels. For example to send errors to an exception +tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to +multiple places simultaneously, e.g. syslog. + +Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in +`init`: + +```go +import ( + log "github.com/sirupsen/logrus" + "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake" + logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" + "log/syslog" +) + +func init() { + + // Use the Airbrake hook to report errors that have Error severity or above to + // an exception tracker. You can create custom hooks, see the Hooks section. + log.AddHook(airbrake.NewHook(123, "xyz", "production")) + + hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") + if err != nil { + log.Error("Unable to connect to local syslog daemon") + } else { + log.AddHook(hook) + } +} +``` +Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md). + +A list of currently known of service hook can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks) + + +#### Level logging + +Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic. + +```go +log.Trace("Something very low level.") +log.Debug("Useful debugging information.") +log.Info("Something noteworthy happened!") +log.Warn("You should probably take a look at this.") +log.Error("Something failed but I'm not quitting.") +// Calls os.Exit(1) after logging +log.Fatal("Bye.") +// Calls panic() after logging +log.Panic("I'm bailing.") +``` + +You can set the logging level on a `Logger`, then it will only log entries with +that severity or anything above it: + +```go +// Will log anything that is info or above (warn, error, fatal, panic). Default. +log.SetLevel(log.InfoLevel) +``` + +It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose +environment if your application has that. + +#### Entries + +Besides the fields added with `WithField` or `WithFields` some fields are +automatically added to all logging events: + +1. `time`. The timestamp when the entry was created. +2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after + the `AddFields` call. E.g. `Failed to send event.` +3. `level`. The logging level. E.g. `info`. + +#### Environments + +Logrus has no notion of environment. + +If you wish for hooks and formatters to only be used in specific environments, +you should handle that yourself. For example, if your application has a global +variable `Environment`, which is a string representation of the environment you +could do: + +```go +import ( + log "github.com/sirupsen/logrus" +) + +init() { + // do something here to set environment depending on an environment variable + // or command-line flag + if Environment == "production" { + log.SetFormatter(&log.JSONFormatter{}) + } else { + // The TextFormatter is default, you don't actually have to do this. + log.SetFormatter(&log.TextFormatter{}) + } +} +``` + +This configuration is how `logrus` was intended to be used, but JSON in +production is mostly only useful if you do log aggregation with tools like +Splunk or Logstash. + +#### Formatters + +The built-in logging formatters are: + +* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise + without colors. + * *Note:* to force colored output when there is no TTY, set the `ForceColors` + field to `true`. To force no colored output even if there is a TTY set the + `DisableColors` field to `true`. For Windows, see + [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable). + * When colors are enabled, levels are truncated to 4 characters by default. To disable + truncation set the `DisableLevelTruncation` field to `true`. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter). +* `logrus.JSONFormatter`. Logs fields as JSON. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter). + +Third party logging formatters: + +* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine. +* [`GELF`](https://github.com/fabienm/go-logrus-formatters). Formats entries so they comply to Graylog's [GELF 1.1 specification](http://docs.graylog.org/en/2.4/pages/gelf.html). +* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events. +* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. +* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦. +* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure. + +You can define your formatter by implementing the `Formatter` interface, +requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a +`Fields` type (`map[string]interface{}`) with all your fields as well as the +default ones (see Entries section above): + +```go +type MyJSONFormatter struct { +} + +log.SetFormatter(new(MyJSONFormatter)) + +func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) { + // Note this doesn't include Time, Level and Message which are available on + // the Entry. Consult `godoc` on information about those fields or read the + // source of the official loggers. + serialized, err := json.Marshal(entry.Data) + if err != nil { + return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + } + return append(serialized, '\n'), nil +} +``` + +#### Logger as an `io.Writer` + +Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it. + +```go +w := logger.Writer() +defer w.Close() + +srv := http.Server{ + // create a stdlib log.Logger that writes to + // logrus.Logger. + ErrorLog: log.New(w, "", 0), +} +``` + +Each line written to that writer will be printed the usual way, using formatters +and hooks. The level for those entries is `info`. + +This means that we can override the standard library logger easily: + +```go +logger := logrus.New() +logger.Formatter = &logrus.JSONFormatter{} + +// Use logrus for standard log output +// Note that `log` here references stdlib's log +// Not logrus imported under the name `log`. +log.SetOutput(logger.Writer()) +``` + +#### Rotation + +Log rotation is not provided with Logrus. Log rotation should be done by an +external program (like `logrotate(8)`) that can compress and delete old log +entries. It should not be a feature of the application-level logger. + +#### Tools + +| Tool | Description | +| ---- | ----------- | +|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.| +|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) | + +#### Testing + +Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides: + +* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook +* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any): + +```go +import( + "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSomething(t*testing.T){ + logger, hook := test.NewNullLogger() + logger.Error("Helloerror") + + assert.Equal(t, 1, len(hook.Entries)) + assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level) + assert.Equal(t, "Helloerror", hook.LastEntry().Message) + + hook.Reset() + assert.Nil(t, hook.LastEntry()) +} +``` + +#### Fatal handlers + +Logrus can register one or more functions that will be called when any `fatal` +level message is logged. The registered handlers will be executed before +logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need +to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted. + +``` +... +handler := func() { + // gracefully shutdown something... +} +logrus.RegisterExitHandler(handler) +... +``` + +#### Thread safety + +By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs. +If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking. + +Situation when locking is not needed includes: + +* You have no hooks registered, or hooks calling is already thread-safe. + +* Writing to logger.Out is already thread-safe, for example: + + 1) logger.Out is protected by locks. + + 2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing) + + (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/) diff --git a/vendor/github.com/sirupsen/logrus/alt_exit.go b/vendor/github.com/sirupsen/logrus/alt_exit.go new file mode 100644 index 000000000..8fd189e1c --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/alt_exit.go @@ -0,0 +1,76 @@ +package logrus + +// The following code was sourced and modified from the +// https://github.com/tebeka/atexit package governed by the following license: +// +// Copyright (c) 2012 Miki Tebeka . +// +// 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. + +import ( + "fmt" + "os" +) + +var handlers = []func(){} + +func runHandler(handler func()) { + defer func() { + if err := recover(); err != nil { + fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err) + } + }() + + handler() +} + +func runHandlers() { + for _, handler := range handlers { + runHandler(handler) + } +} + +// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code) +func Exit(code int) { + runHandlers() + os.Exit(code) +} + +// RegisterExitHandler appends a Logrus Exit handler to the list of handlers, +// call logrus.Exit to invoke all handlers. The handlers will also be invoked when +// any Fatal log entry is made. +// +// This method is useful when a caller wishes to use logrus to log a fatal +// message but also needs to gracefully shutdown. An example usecase could be +// closing database connections, or sending a alert that the application is +// closing. +func RegisterExitHandler(handler func()) { + handlers = append(handlers, handler) +} + +// DeferExitHandler prepends a Logrus Exit handler to the list of handlers, +// call logrus.Exit to invoke all handlers. The handlers will also be invoked when +// any Fatal log entry is made. +// +// This method is useful when a caller wishes to use logrus to log a fatal +// message but also needs to gracefully shutdown. An example usecase could be +// closing database connections, or sending a alert that the application is +// closing. +func DeferExitHandler(handler func()) { + handlers = append([]func(){handler}, handlers...) +} diff --git a/vendor/github.com/sirupsen/logrus/appveyor.yml b/vendor/github.com/sirupsen/logrus/appveyor.yml new file mode 100644 index 000000000..96c2ce15f --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/appveyor.yml @@ -0,0 +1,14 @@ +version: "{build}" +platform: x64 +clone_folder: c:\gopath\src\github.com\sirupsen\logrus +environment: + GOPATH: c:\gopath +branches: + only: + - master +install: + - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% + - go version +build_script: + - go get -t + - go test diff --git a/vendor/github.com/sirupsen/logrus/doc.go b/vendor/github.com/sirupsen/logrus/doc.go new file mode 100644 index 000000000..da67aba06 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/doc.go @@ -0,0 +1,26 @@ +/* +Package logrus is a structured logger for Go, completely API compatible with the standard library logger. + + +The simplest way to use Logrus is simply the package-level exported logger: + + package main + + import ( + log "github.com/sirupsen/logrus" + ) + + func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + "number": 1, + "size": 10, + }).Info("A walrus appears") + } + +Output: + time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 + +For a full guide visit https://github.com/sirupsen/logrus +*/ +package logrus diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go new file mode 100644 index 000000000..63e25583c --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/entry.go @@ -0,0 +1,407 @@ +package logrus + +import ( + "bytes" + "context" + "fmt" + "os" + "reflect" + "runtime" + "strings" + "sync" + "time" +) + +var ( + bufferPool *sync.Pool + + // qualified package name, cached at first use + logrusPackage string + + // Positions in the call stack when tracing to report the calling method + minimumCallerDepth int + + // Used for caller information initialisation + callerInitOnce sync.Once +) + +const ( + maximumCallerDepth int = 25 + knownLogrusFrames int = 4 +) + +func init() { + bufferPool = &sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, + } + + // start at the bottom of the stack before the package-name cache is primed + minimumCallerDepth = 1 +} + +// Defines the key when adding errors using WithError. +var ErrorKey = "error" + +// An entry is the final or intermediate Logrus logging entry. It contains all +// the fields passed with WithField{,s}. It's finally logged when Trace, Debug, +// Info, Warn, Error, Fatal or Panic is called on it. These objects can be +// reused and passed around as much as you wish to avoid field duplication. +type Entry struct { + Logger *Logger + + // Contains all the fields set by the user. + Data Fields + + // Time at which the log entry was created + Time time.Time + + // Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic + // This field will be set on entry firing and the value will be equal to the one in Logger struct field. + Level Level + + // Calling method, with package name + Caller *runtime.Frame + + // Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic + Message string + + // When formatter is called in entry.log(), a Buffer may be set to entry + Buffer *bytes.Buffer + + // Contains the context set by the user. Useful for hook processing etc. + Context context.Context + + // err may contain a field formatting error + err string +} + +func NewEntry(logger *Logger) *Entry { + return &Entry{ + Logger: logger, + // Default is three fields, plus one optional. Give a little extra room. + Data: make(Fields, 6), + } +} + +// Returns the string representation from the reader and ultimately the +// formatter. +func (entry *Entry) String() (string, error) { + serialized, err := entry.Logger.Formatter.Format(entry) + if err != nil { + return "", err + } + str := string(serialized) + return str, nil +} + +// Add an error as single field (using the key defined in ErrorKey) to the Entry. +func (entry *Entry) WithError(err error) *Entry { + return entry.WithField(ErrorKey, err) +} + +// Add a context to the Entry. +func (entry *Entry) WithContext(ctx context.Context) *Entry { + return &Entry{Logger: entry.Logger, Data: entry.Data, Time: entry.Time, err: entry.err, Context: ctx} +} + +// Add a single field to the Entry. +func (entry *Entry) WithField(key string, value interface{}) *Entry { + return entry.WithFields(Fields{key: value}) +} + +// Add a map of fields to the Entry. +func (entry *Entry) WithFields(fields Fields) *Entry { + data := make(Fields, len(entry.Data)+len(fields)) + for k, v := range entry.Data { + data[k] = v + } + fieldErr := entry.err + for k, v := range fields { + isErrField := false + if t := reflect.TypeOf(v); t != nil { + switch t.Kind() { + case reflect.Func: + isErrField = true + case reflect.Ptr: + isErrField = t.Elem().Kind() == reflect.Func + } + } + if isErrField { + tmp := fmt.Sprintf("can not add field %q", k) + if fieldErr != "" { + fieldErr = entry.err + ", " + tmp + } else { + fieldErr = tmp + } + } else { + data[k] = v + } + } + return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context} +} + +// Overrides the time of the Entry. +func (entry *Entry) WithTime(t time.Time) *Entry { + return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err, Context: entry.Context} +} + +// getPackageName reduces a fully qualified function name to the package name +// There really ought to be to be a better way... +func getPackageName(f string) string { + for { + lastPeriod := strings.LastIndex(f, ".") + lastSlash := strings.LastIndex(f, "/") + if lastPeriod > lastSlash { + f = f[:lastPeriod] + } else { + break + } + } + + return f +} + +// getCaller retrieves the name of the first non-logrus calling function +func getCaller() *runtime.Frame { + + // cache this package's fully-qualified name + callerInitOnce.Do(func() { + pcs := make([]uintptr, 2) + _ = runtime.Callers(0, pcs) + logrusPackage = getPackageName(runtime.FuncForPC(pcs[1]).Name()) + + // now that we have the cache, we can skip a minimum count of known-logrus functions + // XXX this is dubious, the number of frames may vary + minimumCallerDepth = knownLogrusFrames + }) + + // Restrict the lookback frames to avoid runaway lookups + pcs := make([]uintptr, maximumCallerDepth) + depth := runtime.Callers(minimumCallerDepth, pcs) + frames := runtime.CallersFrames(pcs[:depth]) + + for f, again := frames.Next(); again; f, again = frames.Next() { + pkg := getPackageName(f.Function) + + // If the caller isn't part of this package, we're done + if pkg != logrusPackage { + return &f + } + } + + // if we got here, we failed to find the caller's context + return nil +} + +func (entry Entry) HasCaller() (has bool) { + return entry.Logger != nil && + entry.Logger.ReportCaller && + entry.Caller != nil +} + +// This function is not declared with a pointer value because otherwise +// race conditions will occur when using multiple goroutines +func (entry Entry) log(level Level, msg string) { + var buffer *bytes.Buffer + + // Default to now, but allow users to override if they want. + // + // We don't have to worry about polluting future calls to Entry#log() + // with this assignment because this function is declared with a + // non-pointer receiver. + if entry.Time.IsZero() { + entry.Time = time.Now() + } + + entry.Level = level + entry.Message = msg + if entry.Logger.ReportCaller { + entry.Caller = getCaller() + } + + entry.fireHooks() + + buffer = bufferPool.Get().(*bytes.Buffer) + buffer.Reset() + defer bufferPool.Put(buffer) + entry.Buffer = buffer + + entry.write() + + entry.Buffer = nil + + // To avoid Entry#log() returning a value that only would make sense for + // panic() to use in Entry#Panic(), we avoid the allocation by checking + // directly here. + if level <= PanicLevel { + panic(&entry) + } +} + +func (entry *Entry) fireHooks() { + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + err := entry.Logger.Hooks.Fire(entry.Level, entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) + } +} + +func (entry *Entry) write() { + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + serialized, err := entry.Logger.Formatter.Format(entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) + } else { + _, err = entry.Logger.Out.Write(serialized) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) + } + } +} + +func (entry *Entry) Log(level Level, args ...interface{}) { + if entry.Logger.IsLevelEnabled(level) { + entry.log(level, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Trace(args ...interface{}) { + entry.Log(TraceLevel, args...) +} + +func (entry *Entry) Debug(args ...interface{}) { + entry.Log(DebugLevel, args...) +} + +func (entry *Entry) Print(args ...interface{}) { + entry.Info(args...) +} + +func (entry *Entry) Info(args ...interface{}) { + entry.Log(InfoLevel, args...) +} + +func (entry *Entry) Warn(args ...interface{}) { + entry.Log(WarnLevel, args...) +} + +func (entry *Entry) Warning(args ...interface{}) { + entry.Warn(args...) +} + +func (entry *Entry) Error(args ...interface{}) { + entry.Log(ErrorLevel, args...) +} + +func (entry *Entry) Fatal(args ...interface{}) { + entry.Log(FatalLevel, args...) + entry.Logger.Exit(1) +} + +func (entry *Entry) Panic(args ...interface{}) { + entry.Log(PanicLevel, args...) + panic(fmt.Sprint(args...)) +} + +// Entry Printf family functions + +func (entry *Entry) Logf(level Level, format string, args ...interface{}) { + if entry.Logger.IsLevelEnabled(level) { + entry.Log(level, fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Tracef(format string, args ...interface{}) { + entry.Logf(TraceLevel, format, args...) +} + +func (entry *Entry) Debugf(format string, args ...interface{}) { + entry.Logf(DebugLevel, format, args...) +} + +func (entry *Entry) Infof(format string, args ...interface{}) { + entry.Logf(InfoLevel, format, args...) +} + +func (entry *Entry) Printf(format string, args ...interface{}) { + entry.Infof(format, args...) +} + +func (entry *Entry) Warnf(format string, args ...interface{}) { + entry.Logf(WarnLevel, format, args...) +} + +func (entry *Entry) Warningf(format string, args ...interface{}) { + entry.Warnf(format, args...) +} + +func (entry *Entry) Errorf(format string, args ...interface{}) { + entry.Logf(ErrorLevel, format, args...) +} + +func (entry *Entry) Fatalf(format string, args ...interface{}) { + entry.Logf(FatalLevel, format, args...) + entry.Logger.Exit(1) +} + +func (entry *Entry) Panicf(format string, args ...interface{}) { + entry.Logf(PanicLevel, format, args...) +} + +// Entry Println family functions + +func (entry *Entry) Logln(level Level, args ...interface{}) { + if entry.Logger.IsLevelEnabled(level) { + entry.Log(level, entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Traceln(args ...interface{}) { + entry.Logln(TraceLevel, args...) +} + +func (entry *Entry) Debugln(args ...interface{}) { + entry.Logln(DebugLevel, args...) +} + +func (entry *Entry) Infoln(args ...interface{}) { + entry.Logln(InfoLevel, args...) +} + +func (entry *Entry) Println(args ...interface{}) { + entry.Infoln(args...) +} + +func (entry *Entry) Warnln(args ...interface{}) { + entry.Logln(WarnLevel, args...) +} + +func (entry *Entry) Warningln(args ...interface{}) { + entry.Warnln(args...) +} + +func (entry *Entry) Errorln(args ...interface{}) { + entry.Logln(ErrorLevel, args...) +} + +func (entry *Entry) Fatalln(args ...interface{}) { + entry.Logln(FatalLevel, args...) + entry.Logger.Exit(1) +} + +func (entry *Entry) Panicln(args ...interface{}) { + entry.Logln(PanicLevel, args...) +} + +// Sprintlnn => Sprint no newline. This is to get the behavior of how +// fmt.Sprintln where spaces are always added between operands, regardless of +// their type. Instead of vendoring the Sprintln implementation to spare a +// string allocation, we do the simplest thing. +func (entry *Entry) sprintlnn(args ...interface{}) string { + msg := fmt.Sprintln(args...) + return msg[:len(msg)-1] +} diff --git a/vendor/github.com/sirupsen/logrus/exported.go b/vendor/github.com/sirupsen/logrus/exported.go new file mode 100644 index 000000000..62fc2f219 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/exported.go @@ -0,0 +1,225 @@ +package logrus + +import ( + "context" + "io" + "time" +) + +var ( + // std is the name of the standard logger in stdlib `log` + std = New() +) + +func StandardLogger() *Logger { + return std +} + +// SetOutput sets the standard logger output. +func SetOutput(out io.Writer) { + std.SetOutput(out) +} + +// SetFormatter sets the standard logger formatter. +func SetFormatter(formatter Formatter) { + std.SetFormatter(formatter) +} + +// SetReportCaller sets whether the standard logger will include the calling +// method as a field. +func SetReportCaller(include bool) { + std.SetReportCaller(include) +} + +// SetLevel sets the standard logger level. +func SetLevel(level Level) { + std.SetLevel(level) +} + +// GetLevel returns the standard logger level. +func GetLevel() Level { + return std.GetLevel() +} + +// IsLevelEnabled checks if the log level of the standard logger is greater than the level param +func IsLevelEnabled(level Level) bool { + return std.IsLevelEnabled(level) +} + +// AddHook adds a hook to the standard logger hooks. +func AddHook(hook Hook) { + std.AddHook(hook) +} + +// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key. +func WithError(err error) *Entry { + return std.WithField(ErrorKey, err) +} + +// WithContext creates an entry from the standard logger and adds a context to it. +func WithContext(ctx context.Context) *Entry { + return std.WithContext(ctx) +} + +// WithField creates an entry from the standard logger and adds a field to +// it. If you want multiple fields, use `WithFields`. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithField(key string, value interface{}) *Entry { + return std.WithField(key, value) +} + +// WithFields creates an entry from the standard logger and adds multiple +// fields to it. This is simply a helper for `WithField`, invoking it +// once for each field. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithFields(fields Fields) *Entry { + return std.WithFields(fields) +} + +// WithTime creats an entry from the standard logger and overrides the time of +// logs generated with it. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithTime(t time.Time) *Entry { + return std.WithTime(t) +} + +// Trace logs a message at level Trace on the standard logger. +func Trace(args ...interface{}) { + std.Trace(args...) +} + +// Debug logs a message at level Debug on the standard logger. +func Debug(args ...interface{}) { + std.Debug(args...) +} + +// Print logs a message at level Info on the standard logger. +func Print(args ...interface{}) { + std.Print(args...) +} + +// Info logs a message at level Info on the standard logger. +func Info(args ...interface{}) { + std.Info(args...) +} + +// Warn logs a message at level Warn on the standard logger. +func Warn(args ...interface{}) { + std.Warn(args...) +} + +// Warning logs a message at level Warn on the standard logger. +func Warning(args ...interface{}) { + std.Warning(args...) +} + +// Error logs a message at level Error on the standard logger. +func Error(args ...interface{}) { + std.Error(args...) +} + +// Panic logs a message at level Panic on the standard logger. +func Panic(args ...interface{}) { + std.Panic(args...) +} + +// Fatal logs a message at level Fatal on the standard logger then the process will exit with status set to 1. +func Fatal(args ...interface{}) { + std.Fatal(args...) +} + +// Tracef logs a message at level Trace on the standard logger. +func Tracef(format string, args ...interface{}) { + std.Tracef(format, args...) +} + +// Debugf logs a message at level Debug on the standard logger. +func Debugf(format string, args ...interface{}) { + std.Debugf(format, args...) +} + +// Printf logs a message at level Info on the standard logger. +func Printf(format string, args ...interface{}) { + std.Printf(format, args...) +} + +// Infof logs a message at level Info on the standard logger. +func Infof(format string, args ...interface{}) { + std.Infof(format, args...) +} + +// Warnf logs a message at level Warn on the standard logger. +func Warnf(format string, args ...interface{}) { + std.Warnf(format, args...) +} + +// Warningf logs a message at level Warn on the standard logger. +func Warningf(format string, args ...interface{}) { + std.Warningf(format, args...) +} + +// Errorf logs a message at level Error on the standard logger. +func Errorf(format string, args ...interface{}) { + std.Errorf(format, args...) +} + +// Panicf logs a message at level Panic on the standard logger. +func Panicf(format string, args ...interface{}) { + std.Panicf(format, args...) +} + +// Fatalf logs a message at level Fatal on the standard logger then the process will exit with status set to 1. +func Fatalf(format string, args ...interface{}) { + std.Fatalf(format, args...) +} + +// Traceln logs a message at level Trace on the standard logger. +func Traceln(args ...interface{}) { + std.Traceln(args...) +} + +// Debugln logs a message at level Debug on the standard logger. +func Debugln(args ...interface{}) { + std.Debugln(args...) +} + +// Println logs a message at level Info on the standard logger. +func Println(args ...interface{}) { + std.Println(args...) +} + +// Infoln logs a message at level Info on the standard logger. +func Infoln(args ...interface{}) { + std.Infoln(args...) +} + +// Warnln logs a message at level Warn on the standard logger. +func Warnln(args ...interface{}) { + std.Warnln(args...) +} + +// Warningln logs a message at level Warn on the standard logger. +func Warningln(args ...interface{}) { + std.Warningln(args...) +} + +// Errorln logs a message at level Error on the standard logger. +func Errorln(args ...interface{}) { + std.Errorln(args...) +} + +// Panicln logs a message at level Panic on the standard logger. +func Panicln(args ...interface{}) { + std.Panicln(args...) +} + +// Fatalln logs a message at level Fatal on the standard logger then the process will exit with status set to 1. +func Fatalln(args ...interface{}) { + std.Fatalln(args...) +} diff --git a/vendor/github.com/sirupsen/logrus/formatter.go b/vendor/github.com/sirupsen/logrus/formatter.go new file mode 100644 index 000000000..408883773 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/formatter.go @@ -0,0 +1,78 @@ +package logrus + +import "time" + +// Default key names for the default fields +const ( + defaultTimestampFormat = time.RFC3339 + FieldKeyMsg = "msg" + FieldKeyLevel = "level" + FieldKeyTime = "time" + FieldKeyLogrusError = "logrus_error" + FieldKeyFunc = "func" + FieldKeyFile = "file" +) + +// The Formatter interface is used to implement a custom Formatter. It takes an +// `Entry`. It exposes all the fields, including the default ones: +// +// * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. +// * `entry.Data["time"]`. The timestamp. +// * `entry.Data["level"]. The level the entry was logged at. +// +// Any additional fields added with `WithField` or `WithFields` are also in +// `entry.Data`. Format is expected to return an array of bytes which are then +// logged to `logger.Out`. +type Formatter interface { + Format(*Entry) ([]byte, error) +} + +// This is to not silently overwrite `time`, `msg`, `func` and `level` fields when +// dumping it. If this code wasn't there doing: +// +// logrus.WithField("level", 1).Info("hello") +// +// Would just silently drop the user provided level. Instead with this code +// it'll logged as: +// +// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} +// +// It's not exported because it's still using Data in an opinionated way. It's to +// avoid code duplication between the two default formatters. +func prefixFieldClashes(data Fields, fieldMap FieldMap, reportCaller bool) { + timeKey := fieldMap.resolve(FieldKeyTime) + if t, ok := data[timeKey]; ok { + data["fields."+timeKey] = t + delete(data, timeKey) + } + + msgKey := fieldMap.resolve(FieldKeyMsg) + if m, ok := data[msgKey]; ok { + data["fields."+msgKey] = m + delete(data, msgKey) + } + + levelKey := fieldMap.resolve(FieldKeyLevel) + if l, ok := data[levelKey]; ok { + data["fields."+levelKey] = l + delete(data, levelKey) + } + + logrusErrKey := fieldMap.resolve(FieldKeyLogrusError) + if l, ok := data[logrusErrKey]; ok { + data["fields."+logrusErrKey] = l + delete(data, logrusErrKey) + } + + // If reportCaller is not set, 'func' will not conflict. + if reportCaller { + funcKey := fieldMap.resolve(FieldKeyFunc) + if l, ok := data[funcKey]; ok { + data["fields."+funcKey] = l + } + fileKey := fieldMap.resolve(FieldKeyFile) + if l, ok := data[fileKey]; ok { + data["fields."+fileKey] = l + } + } +} diff --git a/vendor/github.com/sirupsen/logrus/go.mod b/vendor/github.com/sirupsen/logrus/go.mod new file mode 100644 index 000000000..12fdf9898 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/go.mod @@ -0,0 +1,10 @@ +module github.com/sirupsen/logrus + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.1 + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/objx v0.1.1 // indirect + github.com/stretchr/testify v1.2.2 + golang.org/x/sys v0.0.0-20190422165155-953cdadca894 +) diff --git a/vendor/github.com/sirupsen/logrus/go.sum b/vendor/github.com/sirupsen/logrus/go.sum new file mode 100644 index 000000000..596c318b9 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/go.sum @@ -0,0 +1,16 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe h1:CHRGQ8V7OlCYtwaKPJi3iA7J+YdNKdo8j7nG5IgDhjs= +github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/sirupsen/logrus/hooks.go b/vendor/github.com/sirupsen/logrus/hooks.go new file mode 100644 index 000000000..3f151cdc3 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/hooks.go @@ -0,0 +1,34 @@ +package logrus + +// A hook to be fired when logging on the logging levels returned from +// `Levels()` on your implementation of the interface. Note that this is not +// fired in a goroutine or a channel with workers, you should handle such +// functionality yourself if your call is non-blocking and you don't wish for +// the logging calls for levels returned from `Levels()` to block. +type Hook interface { + Levels() []Level + Fire(*Entry) error +} + +// Internal type for storing the hooks on a logger instance. +type LevelHooks map[Level][]Hook + +// Add a hook to an instance of logger. This is called with +// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. +func (hooks LevelHooks) Add(hook Hook) { + for _, level := range hook.Levels() { + hooks[level] = append(hooks[level], hook) + } +} + +// Fire all the hooks for the passed level. Used by `entry.log` to fire +// appropriate hooks for a log entry. +func (hooks LevelHooks) Fire(level Level, entry *Entry) error { + for _, hook := range hooks[level] { + if err := hook.Fire(entry); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go new file mode 100644 index 000000000..098a21a06 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/json_formatter.go @@ -0,0 +1,121 @@ +package logrus + +import ( + "bytes" + "encoding/json" + "fmt" + "runtime" +) + +type fieldKey string + +// FieldMap allows customization of the key names for default fields. +type FieldMap map[fieldKey]string + +func (f FieldMap) resolve(key fieldKey) string { + if k, ok := f[key]; ok { + return k + } + + return string(key) +} + +// JSONFormatter formats logs into parsable json +type JSONFormatter struct { + // TimestampFormat sets the format used for marshaling timestamps. + TimestampFormat string + + // DisableTimestamp allows disabling automatic timestamps in output + DisableTimestamp bool + + // DataKey allows users to put all the log entry parameters into a nested dictionary at a given key. + DataKey string + + // FieldMap allows users to customize the names of keys for default fields. + // As an example: + // formatter := &JSONFormatter{ + // FieldMap: FieldMap{ + // FieldKeyTime: "@timestamp", + // FieldKeyLevel: "@level", + // FieldKeyMsg: "@message", + // FieldKeyFunc: "@caller", + // }, + // } + FieldMap FieldMap + + // CallerPrettyfier can be set by the user to modify the content + // of the function and file keys in the json data when ReportCaller is + // activated. If any of the returned value is the empty string the + // corresponding key will be removed from json fields. + CallerPrettyfier func(*runtime.Frame) (function string, file string) + + // PrettyPrint will indent all json logs + PrettyPrint bool +} + +// Format renders a single log entry +func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { + data := make(Fields, len(entry.Data)+4) + for k, v := range entry.Data { + switch v := v.(type) { + case error: + // Otherwise errors are ignored by `encoding/json` + // https://github.com/sirupsen/logrus/issues/137 + data[k] = v.Error() + default: + data[k] = v + } + } + + if f.DataKey != "" { + newData := make(Fields, 4) + newData[f.DataKey] = data + data = newData + } + + prefixFieldClashes(data, f.FieldMap, entry.HasCaller()) + + timestampFormat := f.TimestampFormat + if timestampFormat == "" { + timestampFormat = defaultTimestampFormat + } + + if entry.err != "" { + data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err + } + if !f.DisableTimestamp { + data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat) + } + data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message + data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String() + if entry.HasCaller() { + funcVal := entry.Caller.Function + fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } + if funcVal != "" { + data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal + } + if fileVal != "" { + data[f.FieldMap.resolve(FieldKeyFile)] = fileVal + } + } + + var b *bytes.Buffer + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + encoder := json.NewEncoder(b) + if f.PrettyPrint { + encoder.SetIndent("", " ") + } + if err := encoder.Encode(data); err != nil { + return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err) + } + + return b.Bytes(), nil +} diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go new file mode 100644 index 000000000..c0c0b1e55 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/logger.go @@ -0,0 +1,351 @@ +package logrus + +import ( + "context" + "io" + "os" + "sync" + "sync/atomic" + "time" +) + +type Logger struct { + // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a + // file, or leave it default which is `os.Stderr`. You can also set this to + // something more adventurous, such as logging to Kafka. + Out io.Writer + // Hooks for the logger instance. These allow firing events based on logging + // levels and log entries. For example, to send errors to an error tracking + // service, log to StatsD or dump the core on fatal errors. + Hooks LevelHooks + // All log entries pass through the formatter before logged to Out. The + // included formatters are `TextFormatter` and `JSONFormatter` for which + // TextFormatter is the default. In development (when a TTY is attached) it + // logs with colors, but to a file it wouldn't. You can easily implement your + // own that implements the `Formatter` interface, see the `README` or included + // formatters for examples. + Formatter Formatter + + // Flag for whether to log caller info (off by default) + ReportCaller bool + + // The logging level the logger should log at. This is typically (and defaults + // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be + // logged. + Level Level + // Used to sync writing to the log. Locking is enabled by Default + mu MutexWrap + // Reusable empty entry + entryPool sync.Pool + // Function to exit the application, defaults to `os.Exit()` + ExitFunc exitFunc +} + +type exitFunc func(int) + +type MutexWrap struct { + lock sync.Mutex + disabled bool +} + +func (mw *MutexWrap) Lock() { + if !mw.disabled { + mw.lock.Lock() + } +} + +func (mw *MutexWrap) Unlock() { + if !mw.disabled { + mw.lock.Unlock() + } +} + +func (mw *MutexWrap) Disable() { + mw.disabled = true +} + +// Creates a new logger. Configuration should be set by changing `Formatter`, +// `Out` and `Hooks` directly on the default logger instance. You can also just +// instantiate your own: +// +// var log = &Logger{ +// Out: os.Stderr, +// Formatter: new(JSONFormatter), +// Hooks: make(LevelHooks), +// Level: logrus.DebugLevel, +// } +// +// It's recommended to make this a global instance called `log`. +func New() *Logger { + return &Logger{ + Out: os.Stderr, + Formatter: new(TextFormatter), + Hooks: make(LevelHooks), + Level: InfoLevel, + ExitFunc: os.Exit, + ReportCaller: false, + } +} + +func (logger *Logger) newEntry() *Entry { + entry, ok := logger.entryPool.Get().(*Entry) + if ok { + return entry + } + return NewEntry(logger) +} + +func (logger *Logger) releaseEntry(entry *Entry) { + entry.Data = map[string]interface{}{} + logger.entryPool.Put(entry) +} + +// Adds a field to the log entry, note that it doesn't log until you call +// Debug, Print, Info, Warn, Error, Fatal or Panic. It only creates a log entry. +// If you want multiple fields, use `WithFields`. +func (logger *Logger) WithField(key string, value interface{}) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithField(key, value) +} + +// Adds a struct of fields to the log entry. All it does is call `WithField` for +// each `Field`. +func (logger *Logger) WithFields(fields Fields) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithFields(fields) +} + +// Add an error as single field to the log entry. All it does is call +// `WithError` for the given `error`. +func (logger *Logger) WithError(err error) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithError(err) +} + +// Add a context to the log entry. +func (logger *Logger) WithContext(ctx context.Context) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithContext(ctx) +} + +// Overrides the time of the log entry. +func (logger *Logger) WithTime(t time.Time) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithTime(t) +} + +func (logger *Logger) Logf(level Level, format string, args ...interface{}) { + if logger.IsLevelEnabled(level) { + entry := logger.newEntry() + entry.Logf(level, format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Tracef(format string, args ...interface{}) { + logger.Logf(TraceLevel, format, args...) +} + +func (logger *Logger) Debugf(format string, args ...interface{}) { + logger.Logf(DebugLevel, format, args...) +} + +func (logger *Logger) Infof(format string, args ...interface{}) { + logger.Logf(InfoLevel, format, args...) +} + +func (logger *Logger) Printf(format string, args ...interface{}) { + entry := logger.newEntry() + entry.Printf(format, args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warnf(format string, args ...interface{}) { + logger.Logf(WarnLevel, format, args...) +} + +func (logger *Logger) Warningf(format string, args ...interface{}) { + logger.Warnf(format, args...) +} + +func (logger *Logger) Errorf(format string, args ...interface{}) { + logger.Logf(ErrorLevel, format, args...) +} + +func (logger *Logger) Fatalf(format string, args ...interface{}) { + logger.Logf(FatalLevel, format, args...) + logger.Exit(1) +} + +func (logger *Logger) Panicf(format string, args ...interface{}) { + logger.Logf(PanicLevel, format, args...) +} + +func (logger *Logger) Log(level Level, args ...interface{}) { + if logger.IsLevelEnabled(level) { + entry := logger.newEntry() + entry.Log(level, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Trace(args ...interface{}) { + logger.Log(TraceLevel, args...) +} + +func (logger *Logger) Debug(args ...interface{}) { + logger.Log(DebugLevel, args...) +} + +func (logger *Logger) Info(args ...interface{}) { + logger.Log(InfoLevel, args...) +} + +func (logger *Logger) Print(args ...interface{}) { + entry := logger.newEntry() + entry.Print(args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warn(args ...interface{}) { + logger.Log(WarnLevel, args...) +} + +func (logger *Logger) Warning(args ...interface{}) { + logger.Warn(args...) +} + +func (logger *Logger) Error(args ...interface{}) { + logger.Log(ErrorLevel, args...) +} + +func (logger *Logger) Fatal(args ...interface{}) { + logger.Log(FatalLevel, args...) + logger.Exit(1) +} + +func (logger *Logger) Panic(args ...interface{}) { + logger.Log(PanicLevel, args...) +} + +func (logger *Logger) Logln(level Level, args ...interface{}) { + if logger.IsLevelEnabled(level) { + entry := logger.newEntry() + entry.Logln(level, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Traceln(args ...interface{}) { + logger.Logln(TraceLevel, args...) +} + +func (logger *Logger) Debugln(args ...interface{}) { + logger.Logln(DebugLevel, args...) +} + +func (logger *Logger) Infoln(args ...interface{}) { + logger.Logln(InfoLevel, args...) +} + +func (logger *Logger) Println(args ...interface{}) { + entry := logger.newEntry() + entry.Println(args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warnln(args ...interface{}) { + logger.Logln(WarnLevel, args...) +} + +func (logger *Logger) Warningln(args ...interface{}) { + logger.Warnln(args...) +} + +func (logger *Logger) Errorln(args ...interface{}) { + logger.Logln(ErrorLevel, args...) +} + +func (logger *Logger) Fatalln(args ...interface{}) { + logger.Logln(FatalLevel, args...) + logger.Exit(1) +} + +func (logger *Logger) Panicln(args ...interface{}) { + logger.Logln(PanicLevel, args...) +} + +func (logger *Logger) Exit(code int) { + runHandlers() + if logger.ExitFunc == nil { + logger.ExitFunc = os.Exit + } + logger.ExitFunc(code) +} + +//When file is opened with appending mode, it's safe to +//write concurrently to a file (within 4k message on Linux). +//In these cases user can choose to disable the lock. +func (logger *Logger) SetNoLock() { + logger.mu.Disable() +} + +func (logger *Logger) level() Level { + return Level(atomic.LoadUint32((*uint32)(&logger.Level))) +} + +// SetLevel sets the logger level. +func (logger *Logger) SetLevel(level Level) { + atomic.StoreUint32((*uint32)(&logger.Level), uint32(level)) +} + +// GetLevel returns the logger level. +func (logger *Logger) GetLevel() Level { + return logger.level() +} + +// AddHook adds a hook to the logger hooks. +func (logger *Logger) AddHook(hook Hook) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Hooks.Add(hook) +} + +// IsLevelEnabled checks if the log level of the logger is greater than the level param +func (logger *Logger) IsLevelEnabled(level Level) bool { + return logger.level() >= level +} + +// SetFormatter sets the logger formatter. +func (logger *Logger) SetFormatter(formatter Formatter) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Formatter = formatter +} + +// SetOutput sets the logger output. +func (logger *Logger) SetOutput(output io.Writer) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Out = output +} + +func (logger *Logger) SetReportCaller(reportCaller bool) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.ReportCaller = reportCaller +} + +// ReplaceHooks replaces the logger hooks and returns the old ones +func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks { + logger.mu.Lock() + oldHooks := logger.Hooks + logger.Hooks = hooks + logger.mu.Unlock() + return oldHooks +} diff --git a/vendor/github.com/sirupsen/logrus/logrus.go b/vendor/github.com/sirupsen/logrus/logrus.go new file mode 100644 index 000000000..8644761f7 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/logrus.go @@ -0,0 +1,186 @@ +package logrus + +import ( + "fmt" + "log" + "strings" +) + +// Fields type, used to pass to `WithFields`. +type Fields map[string]interface{} + +// Level type +type Level uint32 + +// Convert the Level to a string. E.g. PanicLevel becomes "panic". +func (level Level) String() string { + if b, err := level.MarshalText(); err == nil { + return string(b) + } else { + return "unknown" + } +} + +// ParseLevel takes a string level and returns the Logrus log level constant. +func ParseLevel(lvl string) (Level, error) { + switch strings.ToLower(lvl) { + case "panic": + return PanicLevel, nil + case "fatal": + return FatalLevel, nil + case "error": + return ErrorLevel, nil + case "warn", "warning": + return WarnLevel, nil + case "info": + return InfoLevel, nil + case "debug": + return DebugLevel, nil + case "trace": + return TraceLevel, nil + } + + var l Level + return l, fmt.Errorf("not a valid logrus Level: %q", lvl) +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (level *Level) UnmarshalText(text []byte) error { + l, err := ParseLevel(string(text)) + if err != nil { + return err + } + + *level = Level(l) + + return nil +} + +func (level Level) MarshalText() ([]byte, error) { + switch level { + case TraceLevel: + return []byte("trace"), nil + case DebugLevel: + return []byte("debug"), nil + case InfoLevel: + return []byte("info"), nil + case WarnLevel: + return []byte("warning"), nil + case ErrorLevel: + return []byte("error"), nil + case FatalLevel: + return []byte("fatal"), nil + case PanicLevel: + return []byte("panic"), nil + } + + return nil, fmt.Errorf("not a valid logrus level %d", level) +} + +// A constant exposing all logging levels +var AllLevels = []Level{ + PanicLevel, + FatalLevel, + ErrorLevel, + WarnLevel, + InfoLevel, + DebugLevel, + TraceLevel, +} + +// These are the different logging levels. You can set the logging level to log +// on your instance of logger, obtained with `logrus.New()`. +const ( + // PanicLevel level, highest level of severity. Logs and then calls panic with the + // message passed to Debug, Info, ... + PanicLevel Level = iota + // FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the + // logging level is set to Panic. + FatalLevel + // ErrorLevel level. Logs. Used for errors that should definitely be noted. + // Commonly used for hooks to send errors to an error tracking service. + ErrorLevel + // WarnLevel level. Non-critical entries that deserve eyes. + WarnLevel + // InfoLevel level. General operational entries about what's going on inside the + // application. + InfoLevel + // DebugLevel level. Usually only enabled when debugging. Very verbose logging. + DebugLevel + // TraceLevel level. Designates finer-grained informational events than the Debug. + TraceLevel +) + +// Won't compile if StdLogger can't be realized by a log.Logger +var ( + _ StdLogger = &log.Logger{} + _ StdLogger = &Entry{} + _ StdLogger = &Logger{} +) + +// StdLogger is what your logrus-enabled library should take, that way +// it'll accept a stdlib logger and a logrus logger. There's no standard +// interface, this is the closest we get, unfortunately. +type StdLogger interface { + Print(...interface{}) + Printf(string, ...interface{}) + Println(...interface{}) + + Fatal(...interface{}) + Fatalf(string, ...interface{}) + Fatalln(...interface{}) + + Panic(...interface{}) + Panicf(string, ...interface{}) + Panicln(...interface{}) +} + +// The FieldLogger interface generalizes the Entry and Logger types +type FieldLogger interface { + WithField(key string, value interface{}) *Entry + WithFields(fields Fields) *Entry + WithError(err error) *Entry + + Debugf(format string, args ...interface{}) + Infof(format string, args ...interface{}) + Printf(format string, args ...interface{}) + Warnf(format string, args ...interface{}) + Warningf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) + Fatalf(format string, args ...interface{}) + Panicf(format string, args ...interface{}) + + Debug(args ...interface{}) + Info(args ...interface{}) + Print(args ...interface{}) + Warn(args ...interface{}) + Warning(args ...interface{}) + Error(args ...interface{}) + Fatal(args ...interface{}) + Panic(args ...interface{}) + + Debugln(args ...interface{}) + Infoln(args ...interface{}) + Println(args ...interface{}) + Warnln(args ...interface{}) + Warningln(args ...interface{}) + Errorln(args ...interface{}) + Fatalln(args ...interface{}) + Panicln(args ...interface{}) + + // IsDebugEnabled() bool + // IsInfoEnabled() bool + // IsWarnEnabled() bool + // IsErrorEnabled() bool + // IsFatalEnabled() bool + // IsPanicEnabled() bool +} + +// Ext1FieldLogger (the first extension to FieldLogger) is superfluous, it is +// here for consistancy. Do not use. Use Logger or Entry instead. +type Ext1FieldLogger interface { + FieldLogger + Tracef(format string, args ...interface{}) + Trace(args ...interface{}) + Traceln(args ...interface{}) +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go new file mode 100644 index 000000000..2403de981 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go @@ -0,0 +1,11 @@ +// +build appengine + +package logrus + +import ( + "io" +) + +func checkIfTerminal(w io.Writer) bool { + return true +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go new file mode 100644 index 000000000..3c4f43f91 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go @@ -0,0 +1,13 @@ +// +build darwin dragonfly freebsd netbsd openbsd + +package logrus + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TIOCGETA + +func isTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} + diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go b/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go new file mode 100644 index 000000000..97af92c68 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go @@ -0,0 +1,11 @@ +// +build js nacl plan9 + +package logrus + +import ( + "io" +) + +func checkIfTerminal(w io.Writer) bool { + return false +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go new file mode 100644 index 000000000..3293fb3ca --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go @@ -0,0 +1,17 @@ +// +build !appengine,!js,!windows,!nacl,!plan9 + +package logrus + +import ( + "io" + "os" +) + +func checkIfTerminal(w io.Writer) bool { + switch v := w.(type) { + case *os.File: + return isTerminal(int(v.Fd())) + default: + return false + } +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go b/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go new file mode 100644 index 000000000..f6710b3bd --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go @@ -0,0 +1,11 @@ +package logrus + +import ( + "golang.org/x/sys/unix" +) + +// IsTerminal returns true if the given file descriptor is a terminal. +func isTerminal(fd int) bool { + _, err := unix.IoctlGetTermio(fd, unix.TCGETA) + return err == nil +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go new file mode 100644 index 000000000..355dc966f --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go @@ -0,0 +1,13 @@ +// +build linux aix + +package logrus + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETS + +func isTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} + diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_windows.go b/vendor/github.com/sirupsen/logrus/terminal_check_windows.go new file mode 100644 index 000000000..572889db2 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_windows.go @@ -0,0 +1,34 @@ +// +build !appengine,!js,windows + +package logrus + +import ( + "io" + "os" + "syscall" + + sequences "github.com/konsorten/go-windows-terminal-sequences" +) + +func initTerminal(w io.Writer) { + switch v := w.(type) { + case *os.File: + sequences.EnableVirtualTerminalProcessing(syscall.Handle(v.Fd()), true) + } +} + +func checkIfTerminal(w io.Writer) bool { + var ret bool + switch v := w.(type) { + case *os.File: + var mode uint32 + err := syscall.GetConsoleMode(syscall.Handle(v.Fd()), &mode) + ret = (err == nil) + default: + ret = false + } + if ret { + initTerminal(w) + } + return ret +} diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go new file mode 100644 index 000000000..e01587c43 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/text_formatter.go @@ -0,0 +1,295 @@ +package logrus + +import ( + "bytes" + "fmt" + "os" + "runtime" + "sort" + "strings" + "sync" + "time" +) + +const ( + red = 31 + yellow = 33 + blue = 36 + gray = 37 +) + +var baseTimestamp time.Time + +func init() { + baseTimestamp = time.Now() +} + +// TextFormatter formats logs into text +type TextFormatter struct { + // Set to true to bypass checking for a TTY before outputting colors. + ForceColors bool + + // Force disabling colors. + DisableColors bool + + // Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/ + EnvironmentOverrideColors bool + + // Disable timestamp logging. useful when output is redirected to logging + // system that already adds timestamps. + DisableTimestamp bool + + // Enable logging the full timestamp when a TTY is attached instead of just + // the time passed since beginning of execution. + FullTimestamp bool + + // TimestampFormat to use for display when a full timestamp is printed + TimestampFormat string + + // The fields are sorted by default for a consistent output. For applications + // that log extremely frequently and don't use the JSON formatter this may not + // be desired. + DisableSorting bool + + // The keys sorting function, when uninitialized it uses sort.Strings. + SortingFunc func([]string) + + // Disables the truncation of the level text to 4 characters. + DisableLevelTruncation bool + + // QuoteEmptyFields will wrap empty fields in quotes if true + QuoteEmptyFields bool + + // Whether the logger's out is to a terminal + isTerminal bool + + // FieldMap allows users to customize the names of keys for default fields. + // As an example: + // formatter := &TextFormatter{ + // FieldMap: FieldMap{ + // FieldKeyTime: "@timestamp", + // FieldKeyLevel: "@level", + // FieldKeyMsg: "@message"}} + FieldMap FieldMap + + // CallerPrettyfier can be set by the user to modify the content + // of the function and file keys in the data when ReportCaller is + // activated. If any of the returned value is the empty string the + // corresponding key will be removed from fields. + CallerPrettyfier func(*runtime.Frame) (function string, file string) + + terminalInitOnce sync.Once +} + +func (f *TextFormatter) init(entry *Entry) { + if entry.Logger != nil { + f.isTerminal = checkIfTerminal(entry.Logger.Out) + } +} + +func (f *TextFormatter) isColored() bool { + isColored := f.ForceColors || (f.isTerminal && (runtime.GOOS != "windows")) + + if f.EnvironmentOverrideColors { + if force, ok := os.LookupEnv("CLICOLOR_FORCE"); ok && force != "0" { + isColored = true + } else if ok && force == "0" { + isColored = false + } else if os.Getenv("CLICOLOR") == "0" { + isColored = false + } + } + + return isColored && !f.DisableColors +} + +// Format renders a single log entry +func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { + data := make(Fields) + for k, v := range entry.Data { + data[k] = v + } + prefixFieldClashes(data, f.FieldMap, entry.HasCaller()) + keys := make([]string, 0, len(data)) + for k := range data { + keys = append(keys, k) + } + + var funcVal, fileVal string + + fixedKeys := make([]string, 0, 4+len(data)) + if !f.DisableTimestamp { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime)) + } + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLevel)) + if entry.Message != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyMsg)) + } + if entry.err != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError)) + } + if entry.HasCaller() { + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } else { + funcVal = entry.Caller.Function + fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + } + + if funcVal != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFunc)) + } + if fileVal != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFile)) + } + } + + if !f.DisableSorting { + if f.SortingFunc == nil { + sort.Strings(keys) + fixedKeys = append(fixedKeys, keys...) + } else { + if !f.isColored() { + fixedKeys = append(fixedKeys, keys...) + f.SortingFunc(fixedKeys) + } else { + f.SortingFunc(keys) + } + } + } else { + fixedKeys = append(fixedKeys, keys...) + } + + var b *bytes.Buffer + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + f.terminalInitOnce.Do(func() { f.init(entry) }) + + timestampFormat := f.TimestampFormat + if timestampFormat == "" { + timestampFormat = defaultTimestampFormat + } + if f.isColored() { + f.printColored(b, entry, keys, data, timestampFormat) + } else { + + for _, key := range fixedKeys { + var value interface{} + switch { + case key == f.FieldMap.resolve(FieldKeyTime): + value = entry.Time.Format(timestampFormat) + case key == f.FieldMap.resolve(FieldKeyLevel): + value = entry.Level.String() + case key == f.FieldMap.resolve(FieldKeyMsg): + value = entry.Message + case key == f.FieldMap.resolve(FieldKeyLogrusError): + value = entry.err + case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller(): + value = funcVal + case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller(): + value = fileVal + default: + value = data[key] + } + f.appendKeyValue(b, key, value) + } + } + + b.WriteByte('\n') + return b.Bytes(), nil +} + +func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, data Fields, timestampFormat string) { + var levelColor int + switch entry.Level { + case DebugLevel, TraceLevel: + levelColor = gray + case WarnLevel: + levelColor = yellow + case ErrorLevel, FatalLevel, PanicLevel: + levelColor = red + default: + levelColor = blue + } + + levelText := strings.ToUpper(entry.Level.String()) + if !f.DisableLevelTruncation { + levelText = levelText[0:4] + } + + // Remove a single newline if it already exists in the message to keep + // the behavior of logrus text_formatter the same as the stdlib log package + entry.Message = strings.TrimSuffix(entry.Message, "\n") + + caller := "" + if entry.HasCaller() { + funcVal := fmt.Sprintf("%s()", entry.Caller.Function) + fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } + + if fileVal == "" { + caller = funcVal + } else if funcVal == "" { + caller = fileVal + } else { + caller = fileVal + " " + funcVal + } + } + + if f.DisableTimestamp { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, entry.Message) + } else if !f.FullTimestamp { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message) + } else { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message) + } + for _, k := range keys { + v := data[k] + fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k) + f.appendValue(b, v) + } +} + +func (f *TextFormatter) needsQuoting(text string) bool { + if f.QuoteEmptyFields && len(text) == 0 { + return true + } + for _, ch := range text { + if !((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') { + return true + } + } + return false +} + +func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { + if b.Len() > 0 { + b.WriteByte(' ') + } + b.WriteString(key) + b.WriteByte('=') + f.appendValue(b, value) +} + +func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { + stringVal, ok := value.(string) + if !ok { + stringVal = fmt.Sprint(value) + } + + if !f.needsQuoting(stringVal) { + b.WriteString(stringVal) + } else { + b.WriteString(fmt.Sprintf("%q", stringVal)) + } +} diff --git a/vendor/github.com/sirupsen/logrus/writer.go b/vendor/github.com/sirupsen/logrus/writer.go new file mode 100644 index 000000000..9e1f75135 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/writer.go @@ -0,0 +1,64 @@ +package logrus + +import ( + "bufio" + "io" + "runtime" +) + +func (logger *Logger) Writer() *io.PipeWriter { + return logger.WriterLevel(InfoLevel) +} + +func (logger *Logger) WriterLevel(level Level) *io.PipeWriter { + return NewEntry(logger).WriterLevel(level) +} + +func (entry *Entry) Writer() *io.PipeWriter { + return entry.WriterLevel(InfoLevel) +} + +func (entry *Entry) WriterLevel(level Level) *io.PipeWriter { + reader, writer := io.Pipe() + + var printFunc func(args ...interface{}) + + switch level { + case TraceLevel: + printFunc = entry.Trace + case DebugLevel: + printFunc = entry.Debug + case InfoLevel: + printFunc = entry.Info + case WarnLevel: + printFunc = entry.Warn + case ErrorLevel: + printFunc = entry.Error + case FatalLevel: + printFunc = entry.Fatal + case PanicLevel: + printFunc = entry.Panic + default: + printFunc = entry.Print + } + + go entry.writerScanner(reader, printFunc) + runtime.SetFinalizer(writer, writerFinalizer) + + return writer +} + +func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { + scanner := bufio.NewScanner(reader) + for scanner.Scan() { + printFunc(scanner.Text()) + } + if err := scanner.Err(); err != nil { + entry.Errorf("Error while reading from Writer: %s", err) + } + reader.Close() +} + +func writerFinalizer(writer *io.PipeWriter) { + writer.Close() +} diff --git a/vendor/github.com/sourcegraph/go-diff/LICENSE b/vendor/github.com/sourcegraph/go-diff/LICENSE new file mode 100644 index 000000000..0733b6e5f --- /dev/null +++ b/vendor/github.com/sourcegraph/go-diff/LICENSE @@ -0,0 +1,35 @@ +Copyright (c) 2014 Sourcegraph, Inc. + +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. + +----------------------------------------------------------------- + +Portions adapted from python-unidiff: + +Copyright (c) 2012 Matias Bordese + +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: diff --git a/vendor/github.com/sourcegraph/go-diff/diff/diff.go b/vendor/github.com/sourcegraph/go-diff/diff/diff.go new file mode 100644 index 000000000..646602a6c --- /dev/null +++ b/vendor/github.com/sourcegraph/go-diff/diff/diff.go @@ -0,0 +1,76 @@ +package diff + +import "bytes" + +// NOTE: types are code-generated in diff.pb.go. + +//go:generate protoc -I../../../.. -I ../../../../github.com/gogo/protobuf/protobuf -I. --gogo_out=. diff.proto + +// Stat computes the number of lines added/changed/deleted in all +// hunks in this file's diff. +func (d *FileDiff) Stat() Stat { + total := Stat{} + for _, h := range d.Hunks { + total.add(h.Stat()) + } + return total +} + +// Stat computes the number of lines added/changed/deleted in this +// hunk. +func (h *Hunk) Stat() Stat { + lines := bytes.Split(h.Body, []byte{'\n'}) + var last byte + st := Stat{} + for _, line := range lines { + if len(line) == 0 { + last = 0 + continue + } + switch line[0] { + case '-': + if last == '+' { + st.Added-- + st.Changed++ + last = 0 // next line can't change this one since this is already a change + } else { + st.Deleted++ + last = line[0] + } + case '+': + if last == '-' { + st.Deleted-- + st.Changed++ + last = 0 // next line can't change this one since this is already a change + } else { + st.Added++ + last = line[0] + } + default: + last = 0 + } + } + return st +} + +var ( + hunkPrefix = []byte("@@ ") +) + +const hunkHeader = "@@ -%d,%d +%d,%d @@" + +// diffTimeParseLayout is the layout used to parse the time in unified diff file +// header timestamps. +// See https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html. +const diffTimeParseLayout = "2006-01-02 15:04:05 -0700" + +// diffTimeFormatLayout is the layout used to format (i.e., print) the time in unified diff file +// header timestamps. +// See https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html. +const diffTimeFormatLayout = "2006-01-02 15:04:05.000000000 -0700" + +func (s *Stat) add(o Stat) { + s.Added += o.Added + s.Changed += o.Changed + s.Deleted += o.Deleted +} diff --git a/vendor/github.com/sourcegraph/go-diff/diff/diff.pb.go b/vendor/github.com/sourcegraph/go-diff/diff/diff.pb.go new file mode 100644 index 000000000..2e7c27fb4 --- /dev/null +++ b/vendor/github.com/sourcegraph/go-diff/diff/diff.pb.go @@ -0,0 +1,1059 @@ +// Code generated by protoc-gen-gogo. +// source: diff.proto +// DO NOT EDIT! + +/* + Package diff is a generated protocol buffer package. + + It is generated from these files: + diff.proto + + It has these top-level messages: + FileDiff + Hunk + Stat +*/ +package diff + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" + +// discarding unused import gogoproto "github.com/gogo/protobuf/gogoproto" +import pbtypes "sourcegraph.com/sqs/pbtypes" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// A FileDiff represents a unified diff for a single file. +// +// A file unified diff has a header that resembles the following: +// +// --- oldname 2009-10-11 15:12:20.000000000 -0700 +// +++ newname 2009-10-11 15:12:30.000000000 -0700 +type FileDiff struct { + // the original name of the file + OrigName string `protobuf:"bytes,1,opt,name=OrigName,proto3" json:"OrigName,omitempty"` + // the original timestamp (nil if not present) + OrigTime *pbtypes.Timestamp `protobuf:"bytes,2,opt,name=OrigTime" json:"OrigTime,omitempty"` + // the new name of the file (often same as OrigName) + NewName string `protobuf:"bytes,3,opt,name=NewName,proto3" json:"NewName,omitempty"` + // the new timestamp (nil if not present) + NewTime *pbtypes.Timestamp `protobuf:"bytes,4,opt,name=NewTime" json:"NewTime,omitempty"` + // extended header lines (e.g., git's "new mode ", "rename from ", etc.) + Extended []string `protobuf:"bytes,5,rep,name=Extended" json:"Extended,omitempty"` + // hunks that were changed from orig to new + Hunks []*Hunk `protobuf:"bytes,6,rep,name=Hunks" json:"Hunks,omitempty"` +} + +func (m *FileDiff) Reset() { *m = FileDiff{} } +func (m *FileDiff) String() string { return proto.CompactTextString(m) } +func (*FileDiff) ProtoMessage() {} + +// A Hunk represents a series of changes (additions or deletions) in a file's +// unified diff. +type Hunk struct { + // starting line number in original file + OrigStartLine int32 `protobuf:"varint,1,opt,name=OrigStartLine,proto3" json:"OrigStartLine,omitempty"` + // number of lines the hunk applies to in the original file + OrigLines int32 `protobuf:"varint,2,opt,name=OrigLines,proto3" json:"OrigLines,omitempty"` + // if > 0, then the original file had a 'No newline at end of file' mark at this offset + OrigNoNewlineAt int32 `protobuf:"varint,3,opt,name=OrigNoNewlineAt,proto3" json:"OrigNoNewlineAt,omitempty"` + // starting line number in new file + NewStartLine int32 `protobuf:"varint,4,opt,name=NewStartLine,proto3" json:"NewStartLine,omitempty"` + // number of lines the hunk applies to in the new file + NewLines int32 `protobuf:"varint,5,opt,name=NewLines,proto3" json:"NewLines,omitempty"` + // optional section heading + Section string `protobuf:"bytes,6,opt,name=Section,proto3" json:"Section,omitempty"` + // 0-indexed line offset in unified file diff (including section headers); this is + // only set when Hunks are read from entire file diff (i.e., when ReadAllHunks is + // called) This accounts for hunk headers, too, so the StartPosition of the first + // hunk will be 1. + StartPosition int32 `protobuf:"varint,7,opt,name=StartPosition,proto3" json:"StartPosition,omitempty"` + // hunk body (lines prefixed with '-', '+', or ' ') + Body []byte `protobuf:"bytes,8,opt,name=Body,proto3" json:"Body,omitempty"` +} + +func (m *Hunk) Reset() { *m = Hunk{} } +func (m *Hunk) String() string { return proto.CompactTextString(m) } +func (*Hunk) ProtoMessage() {} + +// A Stat is a diff stat that represents the number of lines added/changed/deleted. +type Stat struct { + // number of lines added + Added int32 `protobuf:"varint,1,opt,name=Added,proto3" json:""` + // number of lines changed + Changed int32 `protobuf:"varint,2,opt,name=Changed,proto3" json:""` + // number of lines deleted + Deleted int32 `protobuf:"varint,3,opt,name=Deleted,proto3" json:""` +} + +func (m *Stat) Reset() { *m = Stat{} } +func (m *Stat) String() string { return proto.CompactTextString(m) } +func (*Stat) ProtoMessage() {} + +func (m *FileDiff) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *FileDiff) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.OrigName) > 0 { + data[i] = 0xa + i++ + i = encodeVarintDiff(data, i, uint64(len(m.OrigName))) + i += copy(data[i:], m.OrigName) + } + if m.OrigTime != nil { + data[i] = 0x12 + i++ + i = encodeVarintDiff(data, i, uint64(m.OrigTime.Size())) + n1, err := m.OrigTime.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n1 + } + if len(m.NewName) > 0 { + data[i] = 0x1a + i++ + i = encodeVarintDiff(data, i, uint64(len(m.NewName))) + i += copy(data[i:], m.NewName) + } + if m.NewTime != nil { + data[i] = 0x22 + i++ + i = encodeVarintDiff(data, i, uint64(m.NewTime.Size())) + n2, err := m.NewTime.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n2 + } + if len(m.Extended) > 0 { + for _, s := range m.Extended { + data[i] = 0x2a + i++ + l = len(s) + for l >= 1<<7 { + data[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + data[i] = uint8(l) + i++ + i += copy(data[i:], s) + } + } + if len(m.Hunks) > 0 { + for _, msg := range m.Hunks { + data[i] = 0x32 + i++ + i = encodeVarintDiff(data, i, uint64(msg.Size())) + n, err := msg.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *Hunk) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *Hunk) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.OrigStartLine != 0 { + data[i] = 0x8 + i++ + i = encodeVarintDiff(data, i, uint64(m.OrigStartLine)) + } + if m.OrigLines != 0 { + data[i] = 0x10 + i++ + i = encodeVarintDiff(data, i, uint64(m.OrigLines)) + } + if m.OrigNoNewlineAt != 0 { + data[i] = 0x18 + i++ + i = encodeVarintDiff(data, i, uint64(m.OrigNoNewlineAt)) + } + if m.NewStartLine != 0 { + data[i] = 0x20 + i++ + i = encodeVarintDiff(data, i, uint64(m.NewStartLine)) + } + if m.NewLines != 0 { + data[i] = 0x28 + i++ + i = encodeVarintDiff(data, i, uint64(m.NewLines)) + } + if len(m.Section) > 0 { + data[i] = 0x32 + i++ + i = encodeVarintDiff(data, i, uint64(len(m.Section))) + i += copy(data[i:], m.Section) + } + if m.StartPosition != 0 { + data[i] = 0x38 + i++ + i = encodeVarintDiff(data, i, uint64(m.StartPosition)) + } + if m.Body != nil { + if len(m.Body) > 0 { + data[i] = 0x42 + i++ + i = encodeVarintDiff(data, i, uint64(len(m.Body))) + i += copy(data[i:], m.Body) + } + } + return i, nil +} + +func (m *Stat) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *Stat) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Added != 0 { + data[i] = 0x8 + i++ + i = encodeVarintDiff(data, i, uint64(m.Added)) + } + if m.Changed != 0 { + data[i] = 0x10 + i++ + i = encodeVarintDiff(data, i, uint64(m.Changed)) + } + if m.Deleted != 0 { + data[i] = 0x18 + i++ + i = encodeVarintDiff(data, i, uint64(m.Deleted)) + } + return i, nil +} + +func encodeFixed64Diff(data []byte, offset int, v uint64) int { + data[offset] = uint8(v) + data[offset+1] = uint8(v >> 8) + data[offset+2] = uint8(v >> 16) + data[offset+3] = uint8(v >> 24) + data[offset+4] = uint8(v >> 32) + data[offset+5] = uint8(v >> 40) + data[offset+6] = uint8(v >> 48) + data[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Diff(data []byte, offset int, v uint32) int { + data[offset] = uint8(v) + data[offset+1] = uint8(v >> 8) + data[offset+2] = uint8(v >> 16) + data[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintDiff(data []byte, offset int, v uint64) int { + for v >= 1<<7 { + data[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + data[offset] = uint8(v) + return offset + 1 +} +func (m *FileDiff) Size() (n int) { + var l int + _ = l + l = len(m.OrigName) + if l > 0 { + n += 1 + l + sovDiff(uint64(l)) + } + if m.OrigTime != nil { + l = m.OrigTime.Size() + n += 1 + l + sovDiff(uint64(l)) + } + l = len(m.NewName) + if l > 0 { + n += 1 + l + sovDiff(uint64(l)) + } + if m.NewTime != nil { + l = m.NewTime.Size() + n += 1 + l + sovDiff(uint64(l)) + } + if len(m.Extended) > 0 { + for _, s := range m.Extended { + l = len(s) + n += 1 + l + sovDiff(uint64(l)) + } + } + if len(m.Hunks) > 0 { + for _, e := range m.Hunks { + l = e.Size() + n += 1 + l + sovDiff(uint64(l)) + } + } + return n +} + +func (m *Hunk) Size() (n int) { + var l int + _ = l + if m.OrigStartLine != 0 { + n += 1 + sovDiff(uint64(m.OrigStartLine)) + } + if m.OrigLines != 0 { + n += 1 + sovDiff(uint64(m.OrigLines)) + } + if m.OrigNoNewlineAt != 0 { + n += 1 + sovDiff(uint64(m.OrigNoNewlineAt)) + } + if m.NewStartLine != 0 { + n += 1 + sovDiff(uint64(m.NewStartLine)) + } + if m.NewLines != 0 { + n += 1 + sovDiff(uint64(m.NewLines)) + } + l = len(m.Section) + if l > 0 { + n += 1 + l + sovDiff(uint64(l)) + } + if m.StartPosition != 0 { + n += 1 + sovDiff(uint64(m.StartPosition)) + } + if m.Body != nil { + l = len(m.Body) + if l > 0 { + n += 1 + l + sovDiff(uint64(l)) + } + } + return n +} + +func (m *Stat) Size() (n int) { + var l int + _ = l + if m.Added != 0 { + n += 1 + sovDiff(uint64(m.Added)) + } + if m.Changed != 0 { + n += 1 + sovDiff(uint64(m.Changed)) + } + if m.Deleted != 0 { + n += 1 + sovDiff(uint64(m.Deleted)) + } + return n +} + +func sovDiff(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozDiff(x uint64) (n int) { + return sovDiff(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *FileDiff) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: FileDiff: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FileDiff: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OrigName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthDiff + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OrigName = string(data[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OrigTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthDiff + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.OrigTime == nil { + m.OrigTime = &pbtypes.Timestamp{} + } + if err := m.OrigTime.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthDiff + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NewName = string(data[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthDiff + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.NewTime == nil { + m.NewTime = &pbtypes.Timestamp{} + } + if err := m.NewTime.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Extended", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthDiff + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Extended = append(m.Extended, string(data[iNdEx:postIndex])) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hunks", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthDiff + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hunks = append(m.Hunks, &Hunk{}) + if err := m.Hunks[len(m.Hunks)-1].Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipDiff(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthDiff + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Hunk) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Hunk: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Hunk: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OrigStartLine", wireType) + } + m.OrigStartLine = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.OrigStartLine |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OrigLines", wireType) + } + m.OrigLines = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.OrigLines |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OrigNoNewlineAt", wireType) + } + m.OrigNoNewlineAt = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.OrigNoNewlineAt |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NewStartLine", wireType) + } + m.NewStartLine = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.NewStartLine |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NewLines", wireType) + } + m.NewLines = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.NewLines |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Section", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthDiff + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Section = string(data[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StartPosition", wireType) + } + m.StartPosition = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.StartPosition |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Body", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthDiff + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Body = append([]byte{}, data[iNdEx:postIndex]...) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipDiff(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthDiff + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Stat) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Stat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Stat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Added", wireType) + } + m.Added = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.Added |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Changed", wireType) + } + m.Changed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.Changed |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Deleted", wireType) + } + m.Deleted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDiff + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.Deleted |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipDiff(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthDiff + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipDiff(data []byte) (n int, err error) { + l := len(data) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowDiff + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowDiff + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if data[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowDiff + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthDiff + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowDiff + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipDiff(data[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthDiff = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowDiff = fmt.Errorf("proto: integer overflow") +) diff --git a/vendor/github.com/sourcegraph/go-diff/diff/diff.proto b/vendor/github.com/sourcegraph/go-diff/diff/diff.proto new file mode 100644 index 000000000..8868970f6 --- /dev/null +++ b/vendor/github.com/sourcegraph/go-diff/diff/diff.proto @@ -0,0 +1,81 @@ +syntax = "proto3"; +package diff; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; +import "sourcegraph.com/sqs/pbtypes/timestamp.proto"; + +option (gogoproto.goproto_getters_all) = false; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; + +// A FileDiff represents a unified diff for a single file. +// +// A file unified diff has a header that resembles the following: +// +// --- oldname 2009-10-11 15:12:20.000000000 -0700 +// +++ newname 2009-10-11 15:12:30.000000000 -0700 +message FileDiff { + // the original name of the file + string OrigName = 1; + + // the original timestamp (nil if not present) + pbtypes.Timestamp OrigTime = 2; + + // the new name of the file (often same as OrigName) + string NewName = 3; + + // the new timestamp (nil if not present) + pbtypes.Timestamp NewTime = 4; + + // extended header lines (e.g., git's "new mode ", "rename from ", etc.) + repeated string Extended = 5; + + // hunks that were changed from orig to new + repeated Hunk Hunks = 6; +} + + +// A Hunk represents a series of changes (additions or deletions) in a file's +// unified diff. +message Hunk { + // starting line number in original file + int32 OrigStartLine = 1; + + // number of lines the hunk applies to in the original file + int32 OrigLines = 2; + + // if > 0, then the original file had a 'No newline at end of file' mark at this offset + int32 OrigNoNewlineAt = 3; + + // starting line number in new file + int32 NewStartLine = 4; + + // number of lines the hunk applies to in the new file + int32 NewLines = 5; + + // optional section heading + string Section = 6; + + // 0-indexed line offset in unified file diff (including section headers); this is + // only set when Hunks are read from entire file diff (i.e., when ReadAllHunks is + // called) This accounts for hunk headers, too, so the StartPosition of the first + // hunk will be 1. + int32 StartPosition = 7; + + // hunk body (lines prefixed with '-', '+', or ' ') + bytes Body = 8; +} + +// A Stat is a diff stat that represents the number of lines added/changed/deleted. +message Stat { + // number of lines added + int32 Added = 1 [(gogoproto.jsontag) = ""]; + + // number of lines changed + int32 Changed = 2 [(gogoproto.jsontag) = ""]; + + // number of lines deleted + int32 Deleted = 3 [(gogoproto.jsontag) = ""]; +} + diff --git a/vendor/github.com/sourcegraph/go-diff/diff/doc.go b/vendor/github.com/sourcegraph/go-diff/diff/doc.go new file mode 100644 index 000000000..12fe96a07 --- /dev/null +++ b/vendor/github.com/sourcegraph/go-diff/diff/doc.go @@ -0,0 +1,2 @@ +// Package diff provides a parser for unified diffs. +package diff diff --git a/vendor/github.com/sourcegraph/go-diff/diff/parse.go b/vendor/github.com/sourcegraph/go-diff/diff/parse.go new file mode 100644 index 000000000..1e77df48f --- /dev/null +++ b/vendor/github.com/sourcegraph/go-diff/diff/parse.go @@ -0,0 +1,625 @@ +package diff + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "strings" + "time" + + "sourcegraph.com/sqs/pbtypes" +) + +// ParseMultiFileDiff parses a multi-file unified diff. It returns an error if parsing failed as a whole, but does its +// best to parse as many files in the case of per-file errors. In the case of non-fatal per-file errors, the error +// return value is null and the Errs field in the returned MultiFileDiff is set. +func ParseMultiFileDiff(diff []byte) ([]*FileDiff, error) { + return NewMultiFileDiffReader(bytes.NewReader(diff)).ReadAllFiles() +} + +// NewMultiFileDiffReader returns a new MultiFileDiffReader that reads +// a multi-file unified diff from r. +func NewMultiFileDiffReader(r io.Reader) *MultiFileDiffReader { + return &MultiFileDiffReader{reader: bufio.NewReader(r)} +} + +// MultiFileDiffReader reads a multi-file unified diff. +type MultiFileDiffReader struct { + line int + offset int64 + reader *bufio.Reader + + // TODO(sqs): line and offset tracking in multi-file diffs is broken; add tests and fix + + // nextFileFirstLine is a line that was read by a HunksReader that + // was how it determined the hunk was complete. But to determine + // that, it needed to read the first line of the next file. We + // store nextFileFirstLine so we can "give the first line back" to + // the next file. + nextFileFirstLine []byte +} + +// ReadFile reads the next file unified diff (including headers and +// all hunks) from r. If there are no more files in the diff, it +// returns error io.EOF. +func (r *MultiFileDiffReader) ReadFile() (*FileDiff, error) { + fr := &FileDiffReader{ + line: r.line, + offset: r.offset, + reader: r.reader, + fileHeaderLine: r.nextFileFirstLine, + } + r.nextFileFirstLine = nil + + fd, err := fr.ReadAllHeaders() + if err != nil { + switch e := err.(type) { + case *ParseError: + if e.Err == ErrNoFileHeader || e.Err == ErrExtendedHeadersEOF { + return nil, io.EOF + } + + case OverflowError: + r.nextFileFirstLine = []byte(e) + return fd, nil + + default: + return nil, err + } + } + + // Before reading hunks, check to see if there are any. If there + // aren't any, and there's another file after this file in the + // diff, then the hunks reader will complain ErrNoHunkHeader. It's + // not easy for us to tell from that error alone if that was + // caused by the lack of any hunks, or a malformatted hunk, so we + // need to perform the check here. + hr := fr.HunksReader() + line, err := readLine(r.reader) + if err != nil { + return fd, err + } + line = bytes.TrimSuffix(line, []byte{'\n'}) + if bytes.HasPrefix(line, hunkPrefix) { + hr.nextHunkHeaderLine = line + fd.Hunks, err = hr.ReadAllHunks() + r.line = fr.line + r.offset = fr.offset + if err != nil { + if e0, ok := err.(*ParseError); ok { + if e, ok := e0.Err.(*ErrBadHunkLine); ok { + // This just means we finished reading the hunks for the + // current file. See the ErrBadHunkLine doc for more info. + r.nextFileFirstLine = e.Line + return fd, nil + } + } + return nil, err + } + } else { + // There weren't any hunks, so that line we peeked ahead at + // actually belongs to the next file. Put it back. + r.nextFileFirstLine = line + } + + return fd, nil +} + +// ReadAllFiles reads all file unified diffs (including headers and all +// hunks) remaining in r. +func (r *MultiFileDiffReader) ReadAllFiles() ([]*FileDiff, error) { + var ds []*FileDiff + for { + d, err := r.ReadFile() + if d != nil { + ds = append(ds, d) + } + if err == io.EOF { + return ds, nil + } + if err != nil { + return nil, err + } + } +} + +// ParseFileDiff parses a file unified diff. +func ParseFileDiff(diff []byte) (*FileDiff, error) { + return NewFileDiffReader(bytes.NewReader(diff)).Read() +} + +// NewFileDiffReader returns a new FileDiffReader that reads a file +// unified diff. +func NewFileDiffReader(r io.Reader) *FileDiffReader { + return &FileDiffReader{reader: bufio.NewReader(r)} +} + +// FileDiffReader reads a unified file diff. +type FileDiffReader struct { + line int + offset int64 + reader *bufio.Reader + + // fileHeaderLine is the first file header line, set by: + // + // (1) ReadExtendedHeaders if it encroaches on a file header line + // (which it must to detect when extended headers are done); or + // (2) (*MultiFileDiffReader).ReadFile() if it encroaches on a + // file header line while reading the previous file's hunks (in a + // multi-file diff). + fileHeaderLine []byte +} + +// Read reads a file unified diff, including headers and hunks, from r. +func (r *FileDiffReader) Read() (*FileDiff, error) { + fd, err := r.ReadAllHeaders() + if err != nil { + return nil, err + } + + fd.Hunks, err = r.HunksReader().ReadAllHunks() + if err != nil { + return nil, err + } + + return fd, nil +} + +// ReadAllHeaders reads the file headers and extended headers (if any) +// from a file unified diff. It does not read hunks, and the returned +// FileDiff's Hunks field is nil. To read the hunks, call the +// (*FileDiffReader).HunksReader() method to get a HunksReader and +// read hunks from that. +func (r *FileDiffReader) ReadAllHeaders() (*FileDiff, error) { + var err error + fd := &FileDiff{} + + fd.Extended, err = r.ReadExtendedHeaders() + if pe, ok := err.(*ParseError); ok && pe.Err == ErrExtendedHeadersEOF { + wasEmpty := handleEmpty(fd) + if wasEmpty { + return fd, nil + } + return fd, err + } else if _, ok := err.(OverflowError); ok { + handleEmpty(fd) + return fd, err + } else if err != nil { + return fd, err + } + + var origTime, newTime *time.Time + fd.OrigName, fd.NewName, origTime, newTime, err = r.ReadFileHeaders() + if err != nil { + return nil, err + } + if origTime != nil { + ts := pbtypes.NewTimestamp(*origTime) + fd.OrigTime = &ts + } + if newTime != nil { + ts := pbtypes.NewTimestamp(*newTime) + fd.NewTime = &ts + } + + return fd, nil +} + +// HunksReader returns a new HunksReader that reads hunks from r. The +// HunksReader's line and offset (used in error messages) is set to +// start where the file diff header ended (which means errors have the +// correct position information). +func (r *FileDiffReader) HunksReader() *HunksReader { + return &HunksReader{ + line: r.line, + offset: r.offset, + reader: r.reader, + } +} + +// ReadFileHeaders reads the unified file diff header (the lines that +// start with "---" and "+++" with the orig/new file names and +// timestamps). +func (r *FileDiffReader) ReadFileHeaders() (origName, newName string, origTimestamp, newTimestamp *time.Time, err error) { + origName, origTimestamp, err = r.readOneFileHeader([]byte("--- ")) + if err != nil { + return "", "", nil, nil, err + } + + newName, newTimestamp, err = r.readOneFileHeader([]byte("+++ ")) + if err != nil { + return "", "", nil, nil, err + } + + return origName, newName, origTimestamp, newTimestamp, nil +} + +// readOneFileHeader reads one of the file headers (prefix should be +// either "+++ " or "--- "). +func (r *FileDiffReader) readOneFileHeader(prefix []byte) (filename string, timestamp *time.Time, err error) { + var line []byte + + if r.fileHeaderLine == nil { + var err error + line, err = readLine(r.reader) + if err == io.EOF { + return "", nil, &ParseError{r.line, r.offset, ErrNoFileHeader} + } else if err != nil { + return "", nil, err + } + } else { + line = r.fileHeaderLine + r.fileHeaderLine = nil + } + + if !bytes.HasPrefix(line, prefix) { + return "", nil, &ParseError{r.line, r.offset, ErrBadFileHeader} + } + + r.offset += int64(len(line)) + r.line++ + line = line[len(prefix):] + + trimmedLine := strings.TrimSpace(string(line)) // filenames that contain spaces may be terminated by a tab + parts := strings.SplitN(trimmedLine, "\t", 2) + filename = parts[0] + if len(parts) == 2 { + // Timestamp is optional, but this header has it. + ts, err := time.Parse(diffTimeParseLayout, parts[1]) + if err != nil { + return "", nil, err + } + timestamp = &ts + } + + return filename, timestamp, err +} + +// OverflowError is returned when we have overflowed into the start +// of the next file while reading extended headers. +type OverflowError string + +func (e OverflowError) Error() string { + return fmt.Sprintf("overflowed into next file: %s", e) +} + +// ReadExtendedHeaders reads the extended header lines, if any, from a +// unified diff file (e.g., git's "diff --git a/foo.go b/foo.go", "new +// mode ", "rename from ", etc.). +func (r *FileDiffReader) ReadExtendedHeaders() ([]string, error) { + var xheaders []string + firstLine := true + for { + var line []byte + if r.fileHeaderLine == nil { + var err error + line, err = readLine(r.reader) + if err == io.EOF { + return xheaders, &ParseError{r.line, r.offset, ErrExtendedHeadersEOF} + } else if err != nil { + return xheaders, err + } + } else { + line = r.fileHeaderLine + r.fileHeaderLine = nil + } + + if bytes.HasPrefix(line, []byte("diff --git ")) { + if firstLine { + firstLine = false + } else { + return xheaders, OverflowError(line) + } + } + if bytes.HasPrefix(line, []byte("--- ")) { + // We've reached the file header. + r.fileHeaderLine = line // pass to readOneFileHeader (see fileHeaderLine field doc) + return xheaders, nil + } + + r.line++ + r.offset += int64(len(line)) + xheaders = append(xheaders, string(line)) + } +} + +// handleEmpty detects when FileDiff was an empty diff and will not have any hunks +// that follow. It updates fd fields from the parsed extended headers. +func handleEmpty(fd *FileDiff) (wasEmpty bool) { + switch { + case (len(fd.Extended) == 3 || len(fd.Extended) == 4 && strings.HasPrefix(fd.Extended[3], "Binary files ")) && + strings.HasPrefix(fd.Extended[1], "new file mode ") && strings.HasPrefix(fd.Extended[0], "diff --git "): + + names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2) + fd.OrigName = "/dev/null" + fd.NewName = names[1] + return true + case (len(fd.Extended) == 3 || len(fd.Extended) == 4 && strings.HasPrefix(fd.Extended[3], "Binary files ")) && + strings.HasPrefix(fd.Extended[1], "deleted file mode ") && strings.HasPrefix(fd.Extended[0], "diff --git "): + + names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2) + fd.OrigName = names[0] + fd.NewName = "/dev/null" + return true + case len(fd.Extended) == 4 && strings.HasPrefix(fd.Extended[2], "rename from ") && strings.HasPrefix(fd.Extended[3], "rename to ") && strings.HasPrefix(fd.Extended[0], "diff --git "): + names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2) + fd.OrigName = names[0] + fd.NewName = names[1] + return true + case len(fd.Extended) == 3 && strings.HasPrefix(fd.Extended[2], "Binary files ") && strings.HasPrefix(fd.Extended[0], "diff --git "): + names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2) + fd.OrigName = names[0] + fd.NewName = names[1] + return true + default: + return false + } +} + +var ( + // ErrNoFileHeader is when a file unified diff has no file header + // (i.e., the lines that begin with "---" and "+++"). + ErrNoFileHeader = errors.New("expected file header, got EOF") + + // ErrBadFileHeader is when a file unified diff has a malformed + // file header (i.e., the lines that begin with "---" and "+++"). + ErrBadFileHeader = errors.New("bad file header") + + // ErrExtendedHeadersEOF is when an EOF was encountered while reading extended file headers, which means that there were no ---/+++ headers encountered before hunks (if any) began. + ErrExtendedHeadersEOF = errors.New("expected file header while reading extended headers, got EOF") +) + +// ParseHunks parses hunks from a unified diff. The diff must consist +// only of hunks and not include a file header; if it has a file +// header, use ParseFileDiff. +func ParseHunks(diff []byte) ([]*Hunk, error) { + r := NewHunksReader(bytes.NewReader(diff)) + hunks, err := r.ReadAllHunks() + if err != nil { + return nil, err + } + return hunks, nil +} + +// NewHunksReader returns a new HunksReader that reads unified diff hunks +// from r. +func NewHunksReader(r io.Reader) *HunksReader { + return &HunksReader{reader: bufio.NewReader(r)} +} + +// A HunksReader reads hunks from a unified diff. +type HunksReader struct { + line int + offset int64 + hunk *Hunk + reader *bufio.Reader + + nextHunkHeaderLine []byte +} + +// ReadHunk reads one hunk from r. If there are no more hunks, it +// returns error io.EOF. +func (r *HunksReader) ReadHunk() (*Hunk, error) { + r.hunk = nil + lastLineFromOrig := true + var line []byte + var err error + for { + if r.nextHunkHeaderLine != nil { + // Use stored hunk header line that was scanned in at the + // completion of the previous hunk's ReadHunk. + line = r.nextHunkHeaderLine + r.nextHunkHeaderLine = nil + } else { + line, err = readLine(r.reader) + if err != nil { + if err == io.EOF && r.hunk != nil { + return r.hunk, nil + } + return nil, err + } + } + + // Record position. + r.line++ + r.offset += int64(len(line)) + + if r.hunk == nil { + // Check for presence of hunk header. + if !bytes.HasPrefix(line, hunkPrefix) { + return nil, &ParseError{r.line, r.offset, ErrNoHunkHeader} + } + + // Parse hunk header. + r.hunk = &Hunk{} + items := []interface{}{ + &r.hunk.OrigStartLine, &r.hunk.OrigLines, + &r.hunk.NewStartLine, &r.hunk.NewLines, + } + header, section, err := normalizeHeader(string(line)) + if err != nil { + return nil, &ParseError{r.line, r.offset, err} + } + n, err := fmt.Sscanf(header, hunkHeader, items...) + if err != nil { + return nil, err + } + if n < len(items) { + return nil, &ParseError{r.line, r.offset, &ErrBadHunkHeader{header: string(line)}} + } + + r.hunk.Section = section + } else { + // Read hunk body line. + if bytes.HasPrefix(line, hunkPrefix) { + // Saw start of new hunk, so this hunk is + // complete. But we've already read in the next hunk's + // header, so we need to be sure that the next call to + // ReadHunk starts with that header. + r.nextHunkHeaderLine = line + + // Rewind position. + r.line-- + r.offset -= int64(len(line)) + + return r.hunk, nil + } + + if len(line) >= 1 && !linePrefix(line[0]) { + // Bad hunk header line. If we're reading a multi-file + // diff, this may be the end of the current + // file. Return a "rich" error that lets our caller + // handle that case. + return r.hunk, &ParseError{r.line, r.offset, &ErrBadHunkLine{Line: line}} + } + if bytes.Equal(line, []byte(noNewlineMessage)) { + if lastLineFromOrig { + // Retain the newline in the body (otherwise the + // diff line would be like "-a+b", where "+b" is + // the the next line of the new file, which is not + // validly formatted) but record that the orig had + // no newline. + r.hunk.OrigNoNewlineAt = int32(len(r.hunk.Body)) + } else { + // Remove previous line's newline. + if len(r.hunk.Body) != 0 { + r.hunk.Body = r.hunk.Body[:len(r.hunk.Body)-1] + } + } + continue + } + + if len(line) > 0 { + lastLineFromOrig = line[0] == '-' + } + + r.hunk.Body = append(r.hunk.Body, line...) + r.hunk.Body = append(r.hunk.Body, '\n') + } + } +} + +const noNewlineMessage = `\ No newline at end of file` + +// linePrefixes is the set of all characters a valid line in a diff +// hunk can start with. '\' can appear in diffs when no newline is +// present at the end of a file. +// See: 'http://www.gnu.org/software/diffutils/manual/diffutils.html#Incomplete-Lines' +var linePrefixes = []byte{' ', '-', '+', '\\'} + +// linePrefix returns true if 'c' is in 'linePrefixes'. +func linePrefix(c byte) bool { + for _, p := range linePrefixes { + if p == c { + return true + } + } + return false +} + +// normalizeHeader takes a header of the form: +// "@@ -linestart[,chunksize] +linestart[,chunksize] @@ section" +// and returns two strings, with the first in the form: +// "@@ -linestart,chunksize +linestart,chunksize @@". +// where linestart and chunksize are both integers. The second is the +// optional section header. chunksize may be omitted from the header +// if its value is 1. normalizeHeader returns an error if the header +// is not in the correct format. +func normalizeHeader(header string) (string, string, error) { + // Split the header into five parts: the first '@@', the two + // ranges, the last '@@', and the optional section. + pieces := strings.SplitN(header, " ", 5) + if len(pieces) < 4 { + return "", "", &ErrBadHunkHeader{header: header} + } + + if pieces[0] != "@@" { + return "", "", &ErrBadHunkHeader{header: header} + } + for i := 1; i < 3; i++ { + if !strings.ContainsRune(pieces[i], ',') { + pieces[i] = pieces[i] + ",1" + } + } + if pieces[3] != "@@" { + return "", "", &ErrBadHunkHeader{header: header} + } + + var section string + if len(pieces) == 5 { + section = pieces[4] + } + return strings.Join(pieces, " "), strings.TrimSpace(section), nil +} + +// ReadAllHunks reads all remaining hunks from r. A successful call +// returns err == nil, not err == EOF. Because ReadAllHunks is defined +// to read until EOF, it does not treat end of file as an error to be +// reported. +func (r *HunksReader) ReadAllHunks() ([]*Hunk, error) { + var hunks []*Hunk + linesRead := int32(0) + for { + hunk, err := r.ReadHunk() + if err == io.EOF { + return hunks, nil + } + if hunk != nil { + linesRead++ // account for the hunk header line + hunk.StartPosition = linesRead + hunks = append(hunks, hunk) + linesRead += int32(bytes.Count(hunk.Body, []byte{'\n'})) + } + if err != nil { + return hunks, err + } + } +} + +// A ParseError is a description of a unified diff syntax error. +type ParseError struct { + Line int // Line where the error occurred + Offset int64 // Offset where the error occurred + Err error // The actual error +} + +func (e *ParseError) Error() string { + return fmt.Sprintf("line %d, char %d: %s", e.Line, e.Offset, e.Err) +} + +// ErrNoHunkHeader indicates that a unified diff hunk header was +// expected but not found during parsing. +var ErrNoHunkHeader = errors.New("no hunk header") + +// ErrBadHunkHeader indicates that a malformed unified diff hunk +// header was encountered during parsing. +type ErrBadHunkHeader struct { + header string +} + +func (e *ErrBadHunkHeader) Error() string { + if e.header == "" { + return "bad hunk header" + } + return "bad hunk header: " + e.header +} + +// ErrBadHunkLine is when a line not beginning with ' ', '-', '+', or +// '\' is encountered while reading a hunk. In the context of reading +// a single hunk or file, it is an unexpected error. In a multi-file +// diff, however, it indicates that the current file's diff is +// complete (and remaining diff data will describe another file +// unified diff). +type ErrBadHunkLine struct { + Line []byte +} + +func (e *ErrBadHunkLine) Error() string { + m := "bad hunk line (does not start with ' ', '-', '+', or '\\')" + if len(e.Line) == 0 { + return m + } + return m + ": " + string(e.Line) +} diff --git a/vendor/github.com/sourcegraph/go-diff/diff/print.go b/vendor/github.com/sourcegraph/go-diff/diff/print.go new file mode 100644 index 000000000..d440cb9ad --- /dev/null +++ b/vendor/github.com/sourcegraph/go-diff/diff/print.go @@ -0,0 +1,140 @@ +package diff + +import ( + "bytes" + "fmt" + "io" + "time" + + "sourcegraph.com/sqs/pbtypes" +) + +// PrintMultiFileDiff prints a multi-file diff in unified diff format. +func PrintMultiFileDiff(ds []*FileDiff) ([]byte, error) { + var buf bytes.Buffer + for _, d := range ds { + diff, err := PrintFileDiff(d) + if err != nil { + return nil, err + } + if _, err := buf.Write(diff); err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} + +// PrintFileDiff prints a FileDiff in unified diff format. +// +// TODO(sqs): handle escaping whitespace/etc. chars in filenames +func PrintFileDiff(d *FileDiff) ([]byte, error) { + var buf bytes.Buffer + + for _, xheader := range d.Extended { + if _, err := fmt.Fprintln(&buf, xheader); err != nil { + return nil, err + } + } + + if d.Hunks == nil { + return buf.Bytes(), nil + } + + if err := printFileHeader(&buf, "--- ", d.OrigName, timePtr(d.OrigTime)); err != nil { + return nil, err + } + if err := printFileHeader(&buf, "+++ ", d.NewName, timePtr(d.NewTime)); err != nil { + return nil, err + } + + ph, err := PrintHunks(d.Hunks) + if err != nil { + return nil, err + } + + if _, err := buf.Write(ph); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func timePtr(ts *pbtypes.Timestamp) *time.Time { + if ts == nil { + return nil + } + t := ts.Time() + return &t +} + +func printFileHeader(w io.Writer, prefix string, filename string, timestamp *time.Time) error { + if _, err := fmt.Fprint(w, prefix, filename); err != nil { + return err + } + if timestamp != nil { + if _, err := fmt.Fprint(w, "\t", timestamp.Format(diffTimeFormatLayout)); err != nil { + return err + } + } + if _, err := fmt.Fprintln(w); err != nil { + return err + } + return nil +} + +// PrintHunks prints diff hunks in unified diff format. +func PrintHunks(hunks []*Hunk) ([]byte, error) { + var buf bytes.Buffer + for _, hunk := range hunks { + _, err := fmt.Fprintf(&buf, + "@@ -%d,%d +%d,%d @@", hunk.OrigStartLine, hunk.OrigLines, hunk.NewStartLine, hunk.NewLines, + ) + if err != nil { + return nil, err + } + if hunk.Section != "" { + _, err := fmt.Fprint(&buf, " ", hunk.Section) + if err != nil { + return nil, err + } + } + if _, err := fmt.Fprintln(&buf); err != nil { + return nil, err + } + + if hunk.OrigNoNewlineAt == 0 { + if _, err := buf.Write(hunk.Body); err != nil { + return nil, err + } + } else { + if _, err := buf.Write(hunk.Body[:hunk.OrigNoNewlineAt]); err != nil { + return nil, err + } + if err := printNoNewlineMessage(&buf); err != nil { + return nil, err + } + if _, err := buf.Write(hunk.Body[hunk.OrigNoNewlineAt:]); err != nil { + return nil, err + } + } + + if !bytes.HasSuffix(hunk.Body, []byte{'\n'}) { + if _, err := fmt.Fprintln(&buf); err != nil { + return nil, err + } + if err := printNoNewlineMessage(&buf); err != nil { + return nil, err + } + } + } + return buf.Bytes(), nil +} + +func printNoNewlineMessage(w io.Writer) error { + if _, err := w.Write([]byte(noNewlineMessage)); err != nil { + return err + } + if _, err := fmt.Fprintln(w); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go b/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go new file mode 100644 index 000000000..395fb7baf --- /dev/null +++ b/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go @@ -0,0 +1,37 @@ +package diff + +import ( + "bufio" + "io" +) + +// readLine is a helper that mimics the functionality of calling bufio.Scanner.Scan() and +// bufio.Scanner.Bytes(), but without the token size limitation. It will read and return +// the next line in the Reader with the trailing newline stripped. It will return an +// io.EOF error when there is nothing left to read (at the start of the function call). It +// will return any other errors it receives from the underlying call to ReadBytes. +func readLine(r *bufio.Reader) ([]byte, error) { + line_, err := r.ReadBytes('\n') + if err == io.EOF { + if len(line_) == 0 { + return nil, io.EOF + } + + // ReadBytes returned io.EOF, because it didn't find another newline, but there is + // still the remainder of the file to return as a line. + line := line_ + return line, nil + } else if err != nil { + return nil, err + } + line := line_[0 : len(line_)-1] + return dropCR(line), nil +} + +// dropCR drops a terminal \r from the data. +func dropCR(data []byte) []byte { + if len(data) > 0 && data[len(data)-1] == '\r' { + return data[0 : len(data)-1] + } + return data +} diff --git a/vendor/github.com/spf13/afero/.travis.yml b/vendor/github.com/spf13/afero/.travis.yml new file mode 100644 index 000000000..0637db726 --- /dev/null +++ b/vendor/github.com/spf13/afero/.travis.yml @@ -0,0 +1,21 @@ +sudo: false +language: go + +go: + - 1.9 + - "1.10" + - tip + +os: + - linux + - osx + +matrix: + allow_failures: + - go: tip + fast_finish: true + +script: + - go build + - go test -race -v ./... + diff --git a/vendor/github.com/spf13/afero/LICENSE.txt b/vendor/github.com/spf13/afero/LICENSE.txt new file mode 100644 index 000000000..298f0e266 --- /dev/null +++ b/vendor/github.com/spf13/afero/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/vendor/github.com/spf13/afero/README.md b/vendor/github.com/spf13/afero/README.md new file mode 100644 index 000000000..0c9b04b53 --- /dev/null +++ b/vendor/github.com/spf13/afero/README.md @@ -0,0 +1,452 @@ +![afero logo-sm](https://cloud.githubusercontent.com/assets/173412/11490338/d50e16dc-97a5-11e5-8b12-019a300d0fcb.png) + +A FileSystem Abstraction System for Go + +[![Build Status](https://travis-ci.org/spf13/afero.svg)](https://travis-ci.org/spf13/afero) [![Build status](https://ci.appveyor.com/api/projects/status/github/spf13/afero?branch=master&svg=true)](https://ci.appveyor.com/project/spf13/afero) [![GoDoc](https://godoc.org/github.com/spf13/afero?status.svg)](https://godoc.org/github.com/spf13/afero) [![Join the chat at https://gitter.im/spf13/afero](https://badges.gitter.im/Dev%20Chat.svg)](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +# Overview + +Afero is an filesystem framework providing a simple, uniform and universal API +interacting with any filesystem, as an abstraction layer providing interfaces, +types and methods. Afero has an exceptionally clean interface and simple design +without needless constructors or initialization methods. + +Afero is also a library providing a base set of interoperable backend +filesystems that make it easy to work with afero while retaining all the power +and benefit of the os and ioutil packages. + +Afero provides significant improvements over using the os package alone, most +notably the ability to create mock and testing filesystems without relying on the disk. + +It is suitable for use in a any situation where you would consider using the OS +package as it provides an additional abstraction that makes it easy to use a +memory backed file system during testing. It also adds support for the http +filesystem for full interoperability. + + +## Afero Features + +* A single consistent API for accessing a variety of filesystems +* Interoperation between a variety of file system types +* A set of interfaces to encourage and enforce interoperability between backends +* An atomic cross platform memory backed file system +* Support for compositional (union) file systems by combining multiple file systems acting as one +* Specialized backends which modify existing filesystems (Read Only, Regexp filtered) +* A set of utility functions ported from io, ioutil & hugo to be afero aware + + +# Using Afero + +Afero is easy to use and easier to adopt. + +A few different ways you could use Afero: + +* Use the interfaces alone to define you own file system. +* Wrap for the OS packages. +* Define different filesystems for different parts of your application. +* Use Afero for mock filesystems while testing + +## Step 1: Install Afero + +First use go get to install the latest version of the library. + + $ go get github.com/spf13/afero + +Next include Afero in your application. +```go +import "github.com/spf13/afero" +``` + +## Step 2: Declare a backend + +First define a package variable and set it to a pointer to a filesystem. +```go +var AppFs = afero.NewMemMapFs() + +or + +var AppFs = afero.NewOsFs() +``` +It is important to note that if you repeat the composite literal you +will be using a completely new and isolated filesystem. In the case of +OsFs it will still use the same underlying filesystem but will reduce +the ability to drop in other filesystems as desired. + +## Step 3: Use it like you would the OS package + +Throughout your application use any function and method like you normally +would. + +So if my application before had: +```go +os.Open('/tmp/foo') +``` +We would replace it with: +```go +AppFs.Open('/tmp/foo') +``` + +`AppFs` being the variable we defined above. + + +## List of all available functions + +File System Methods Available: +```go +Chmod(name string, mode os.FileMode) : error +Chtimes(name string, atime time.Time, mtime time.Time) : error +Create(name string) : File, error +Mkdir(name string, perm os.FileMode) : error +MkdirAll(path string, perm os.FileMode) : error +Name() : string +Open(name string) : File, error +OpenFile(name string, flag int, perm os.FileMode) : File, error +Remove(name string) : error +RemoveAll(path string) : error +Rename(oldname, newname string) : error +Stat(name string) : os.FileInfo, error +``` +File Interfaces and Methods Available: +```go +io.Closer +io.Reader +io.ReaderAt +io.Seeker +io.Writer +io.WriterAt + +Name() : string +Readdir(count int) : []os.FileInfo, error +Readdirnames(n int) : []string, error +Stat() : os.FileInfo, error +Sync() : error +Truncate(size int64) : error +WriteString(s string) : ret int, err error +``` +In some applications it may make sense to define a new package that +simply exports the file system variable for easy access from anywhere. + +## Using Afero's utility functions + +Afero provides a set of functions to make it easier to use the underlying file systems. +These functions have been primarily ported from io & ioutil with some developed for Hugo. + +The afero utilities support all afero compatible backends. + +The list of utilities includes: + +```go +DirExists(path string) (bool, error) +Exists(path string) (bool, error) +FileContainsBytes(filename string, subslice []byte) (bool, error) +GetTempDir(subPath string) string +IsDir(path string) (bool, error) +IsEmpty(path string) (bool, error) +ReadDir(dirname string) ([]os.FileInfo, error) +ReadFile(filename string) ([]byte, error) +SafeWriteReader(path string, r io.Reader) (err error) +TempDir(dir, prefix string) (name string, err error) +TempFile(dir, prefix string) (f File, err error) +Walk(root string, walkFn filepath.WalkFunc) error +WriteFile(filename string, data []byte, perm os.FileMode) error +WriteReader(path string, r io.Reader) (err error) +``` +For a complete list see [Afero's GoDoc](https://godoc.org/github.com/spf13/afero) + +They are available under two different approaches to use. You can either call +them directly where the first parameter of each function will be the file +system, or you can declare a new `Afero`, a custom type used to bind these +functions as methods to a given filesystem. + +### Calling utilities directly + +```go +fs := new(afero.MemMapFs) +f, err := afero.TempFile(fs,"", "ioutil-test") + +``` + +### Calling via Afero + +```go +fs := afero.NewMemMapFs() +afs := &afero.Afero{Fs: fs} +f, err := afs.TempFile("", "ioutil-test") +``` + +## Using Afero for Testing + +There is a large benefit to using a mock filesystem for testing. It has a +completely blank state every time it is initialized and can be easily +reproducible regardless of OS. You could create files to your heart’s content +and the file access would be fast while also saving you from all the annoying +issues with deleting temporary files, Windows file locking, etc. The MemMapFs +backend is perfect for testing. + +* Much faster than performing I/O operations on disk +* Avoid security issues and permissions +* Far more control. 'rm -rf /' with confidence +* Test setup is far more easier to do +* No test cleanup needed + +One way to accomplish this is to define a variable as mentioned above. +In your application this will be set to afero.NewOsFs() during testing you +can set it to afero.NewMemMapFs(). + +It wouldn't be uncommon to have each test initialize a blank slate memory +backend. To do this I would define my `appFS = afero.NewOsFs()` somewhere +appropriate in my application code. This approach ensures that Tests are order +independent, with no test relying on the state left by an earlier test. + +Then in my tests I would initialize a new MemMapFs for each test: +```go +func TestExist(t *testing.T) { + appFS := afero.NewMemMapFs() + // create test files and directories + appFS.MkdirAll("src/a", 0755) + afero.WriteFile(appFS, "src/a/b", []byte("file b"), 0644) + afero.WriteFile(appFS, "src/c", []byte("file c"), 0644) + name := "src/c" + _, err := appFS.Stat(name) + if os.IsNotExist(err) { + t.Errorf("file \"%s\" does not exist.\n", name) + } +} +``` + +# Available Backends + +## Operating System Native + +### OsFs + +The first is simply a wrapper around the native OS calls. This makes it +very easy to use as all of the calls are the same as the existing OS +calls. It also makes it trivial to have your code use the OS during +operation and a mock filesystem during testing or as needed. + +```go +appfs := afero.NewOsFs() +appfs.MkdirAll("src/a", 0755)) +``` + +## Memory Backed Storage + +### MemMapFs + +Afero also provides a fully atomic memory backed filesystem perfect for use in +mocking and to speed up unnecessary disk io when persistence isn’t +necessary. It is fully concurrent and will work within go routines +safely. + +```go +mm := afero.NewMemMapFs() +mm.MkdirAll("src/a", 0755)) +``` + +#### InMemoryFile + +As part of MemMapFs, Afero also provides an atomic, fully concurrent memory +backed file implementation. This can be used in other memory backed file +systems with ease. Plans are to add a radix tree memory stored file +system using InMemoryFile. + +## Network Interfaces + +### SftpFs + +Afero has experimental support for secure file transfer protocol (sftp). Which can +be used to perform file operations over a encrypted channel. + +## Filtering Backends + +### BasePathFs + +The BasePathFs restricts all operations to a given path within an Fs. +The given file name to the operations on this Fs will be prepended with +the base path before calling the source Fs. + +```go +bp := afero.NewBasePathFs(afero.NewOsFs(), "/base/path") +``` + +### ReadOnlyFs + +A thin wrapper around the source Fs providing a read only view. + +```go +fs := afero.NewReadOnlyFs(afero.NewOsFs()) +_, err := fs.Create("/file.txt") +// err = syscall.EPERM +``` + +# RegexpFs + +A filtered view on file names, any file NOT matching +the passed regexp will be treated as non-existing. +Files not matching the regexp provided will not be created. +Directories are not filtered. + +```go +fs := afero.NewRegexpFs(afero.NewMemMapFs(), regexp.MustCompile(`\.txt$`)) +_, err := fs.Create("/file.html") +// err = syscall.ENOENT +``` + +### HttpFs + +Afero provides an http compatible backend which can wrap any of the existing +backends. + +The Http package requires a slightly specific version of Open which +returns an http.File type. + +Afero provides an httpFs file system which satisfies this requirement. +Any Afero FileSystem can be used as an httpFs. + +```go +httpFs := afero.NewHttpFs() +fileserver := http.FileServer(httpFs.Dir())) +http.Handle("/", fileserver) +``` + +## Composite Backends + +Afero provides the ability have two filesystems (or more) act as a single +file system. + +### CacheOnReadFs + +The CacheOnReadFs will lazily make copies of any accessed files from the base +layer into the overlay. Subsequent reads will be pulled from the overlay +directly permitting the request is within the cache duration of when it was +created in the overlay. + +If the base filesystem is writeable, any changes to files will be +done first to the base, then to the overlay layer. Write calls to open file +handles like `Write()` or `Truncate()` to the overlay first. + +To writing files to the overlay only, you can use the overlay Fs directly (not +via the union Fs). + +Cache files in the layer for the given time.Duration, a cache duration of 0 +means "forever" meaning the file will not be re-requested from the base ever. + +A read-only base will make the overlay also read-only but still copy files +from the base to the overlay when they're not present (or outdated) in the +caching layer. + +```go +base := afero.NewOsFs() +layer := afero.NewMemMapFs() +ufs := afero.NewCacheOnReadFs(base, layer, 100 * time.Second) +``` + +### CopyOnWriteFs() + +The CopyOnWriteFs is a read only base file system with a potentially +writeable layer on top. + +Read operations will first look in the overlay and if not found there, will +serve the file from the base. + +Changes to the file system will only be made in the overlay. + +Any attempt to modify a file found only in the base will copy the file to the +overlay layer before modification (including opening a file with a writable +handle). + +Removing and Renaming files present only in the base layer is not currently +permitted. If a file is present in the base layer and the overlay, only the +overlay will be removed/renamed. + +```go + base := afero.NewOsFs() + roBase := afero.NewReadOnlyFs(base) + ufs := afero.NewCopyOnWriteFs(roBase, afero.NewMemMapFs()) + + fh, _ = ufs.Create("/home/test/file2.txt") + fh.WriteString("This is a test") + fh.Close() +``` + +In this example all write operations will only occur in memory (MemMapFs) +leaving the base filesystem (OsFs) untouched. + + +## Desired/possible backends + +The following is a short list of possible backends we hope someone will +implement: + +* SSH +* ZIP +* TAR +* S3 + +# About the project + +## What's in the name + +Afero comes from the latin roots Ad-Facere. + +**"Ad"** is a prefix meaning "to". + +**"Facere"** is a form of the root "faciō" making "make or do". + +The literal meaning of afero is "to make" or "to do" which seems very fitting +for a library that allows one to make files and directories and do things with them. + +The English word that shares the same roots as Afero is "affair". Affair shares +the same concept but as a noun it means "something that is made or done" or "an +object of a particular type". + +It's also nice that unlike some of my other libraries (hugo, cobra, viper) it +Googles very well. + +## Release Notes + +* **0.10.0** 2015.12.10 + * Full compatibility with Windows + * Introduction of afero utilities + * Test suite rewritten to work cross platform + * Normalize paths for MemMapFs + * Adding Sync to the file interface + * **Breaking Change** Walk and ReadDir have changed parameter order + * Moving types used by MemMapFs to a subpackage + * General bugfixes and improvements +* **0.9.0** 2015.11.05 + * New Walk function similar to filepath.Walk + * MemMapFs.OpenFile handles O_CREATE, O_APPEND, O_TRUNC + * MemMapFs.Remove now really deletes the file + * InMemoryFile.Readdir and Readdirnames work correctly + * InMemoryFile functions lock it for concurrent access + * Test suite improvements +* **0.8.0** 2014.10.28 + * First public version + * Interfaces feel ready for people to build using + * Interfaces satisfy all known uses + * MemMapFs passes the majority of the OS test suite + * OsFs passes the majority of the OS test suite + +## Contributing + +1. Fork it +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create new Pull Request + +## Contributors + +Names in no particular order: + +* [spf13](https://github.com/spf13) +* [jaqx0r](https://github.com/jaqx0r) +* [mbertschler](https://github.com/mbertschler) +* [xor-gate](https://github.com/xor-gate) + +## License + +Afero is released under the Apache 2.0 license. See +[LICENSE.txt](https://github.com/spf13/afero/blob/master/LICENSE.txt) diff --git a/vendor/github.com/spf13/afero/afero.go b/vendor/github.com/spf13/afero/afero.go new file mode 100644 index 000000000..f5b5e127c --- /dev/null +++ b/vendor/github.com/spf13/afero/afero.go @@ -0,0 +1,108 @@ +// Copyright © 2014 Steve Francia . +// Copyright 2013 tsuru authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package afero provides types and methods for interacting with the filesystem, +// as an abstraction layer. + +// Afero also provides a few implementations that are mostly interoperable. One that +// uses the operating system filesystem, one that uses memory to store files +// (cross platform) and an interface that should be implemented if you want to +// provide your own filesystem. + +package afero + +import ( + "errors" + "io" + "os" + "time" +) + +type Afero struct { + Fs +} + +// File represents a file in the filesystem. +type File interface { + io.Closer + io.Reader + io.ReaderAt + io.Seeker + io.Writer + io.WriterAt + + Name() string + Readdir(count int) ([]os.FileInfo, error) + Readdirnames(n int) ([]string, error) + Stat() (os.FileInfo, error) + Sync() error + Truncate(size int64) error + WriteString(s string) (ret int, err error) +} + +// Fs is the filesystem interface. +// +// Any simulated or real filesystem should implement this interface. +type Fs interface { + // Create creates a file in the filesystem, returning the file and an + // error, if any happens. + Create(name string) (File, error) + + // Mkdir creates a directory in the filesystem, return an error if any + // happens. + Mkdir(name string, perm os.FileMode) error + + // MkdirAll creates a directory path and all parents that does not exist + // yet. + MkdirAll(path string, perm os.FileMode) error + + // Open opens a file, returning it or an error, if any happens. + Open(name string) (File, error) + + // OpenFile opens a file using the given flags and the given mode. + OpenFile(name string, flag int, perm os.FileMode) (File, error) + + // Remove removes a file identified by name, returning an error, if any + // happens. + Remove(name string) error + + // RemoveAll removes a directory path and any children it contains. It + // does not fail if the path does not exist (return nil). + RemoveAll(path string) error + + // Rename renames a file. + Rename(oldname, newname string) error + + // Stat returns a FileInfo describing the named file, or an error, if any + // happens. + Stat(name string) (os.FileInfo, error) + + // The name of this FileSystem + Name() string + + //Chmod changes the mode of the named file to mode. + Chmod(name string, mode os.FileMode) error + + //Chtimes changes the access and modification times of the named file + Chtimes(name string, atime time.Time, mtime time.Time) error +} + +var ( + ErrFileClosed = errors.New("File is closed") + ErrOutOfRange = errors.New("Out of range") + ErrTooLarge = errors.New("Too large") + ErrFileNotFound = os.ErrNotExist + ErrFileExists = os.ErrExist + ErrDestinationExists = os.ErrExist +) diff --git a/vendor/github.com/spf13/afero/appveyor.yml b/vendor/github.com/spf13/afero/appveyor.yml new file mode 100644 index 000000000..a633ad500 --- /dev/null +++ b/vendor/github.com/spf13/afero/appveyor.yml @@ -0,0 +1,15 @@ +version: '{build}' +clone_folder: C:\gopath\src\github.com\spf13\afero +environment: + GOPATH: C:\gopath +build_script: +- cmd: >- + go version + + go env + + go get -v github.com/spf13/afero/... + + go build github.com/spf13/afero +test_script: +- cmd: go test -race -v github.com/spf13/afero/... diff --git a/vendor/github.com/spf13/afero/basepath.go b/vendor/github.com/spf13/afero/basepath.go new file mode 100644 index 000000000..616ff8ff7 --- /dev/null +++ b/vendor/github.com/spf13/afero/basepath.go @@ -0,0 +1,180 @@ +package afero + +import ( + "os" + "path/filepath" + "runtime" + "strings" + "time" +) + +var _ Lstater = (*BasePathFs)(nil) + +// The BasePathFs restricts all operations to a given path within an Fs. +// The given file name to the operations on this Fs will be prepended with +// the base path before calling the base Fs. +// Any file name (after filepath.Clean()) outside this base path will be +// treated as non existing file. +// +// Note that it does not clean the error messages on return, so you may +// reveal the real path on errors. +type BasePathFs struct { + source Fs + path string +} + +type BasePathFile struct { + File + path string +} + +func (f *BasePathFile) Name() string { + sourcename := f.File.Name() + return strings.TrimPrefix(sourcename, filepath.Clean(f.path)) +} + +func NewBasePathFs(source Fs, path string) Fs { + return &BasePathFs{source: source, path: path} +} + +// on a file outside the base path it returns the given file name and an error, +// else the given file with the base path prepended +func (b *BasePathFs) RealPath(name string) (path string, err error) { + if err := validateBasePathName(name); err != nil { + return name, err + } + + bpath := filepath.Clean(b.path) + path = filepath.Clean(filepath.Join(bpath, name)) + if !strings.HasPrefix(path, bpath) { + return name, os.ErrNotExist + } + + return path, nil +} + +func validateBasePathName(name string) error { + if runtime.GOOS != "windows" { + // Not much to do here; + // the virtual file paths all look absolute on *nix. + return nil + } + + // On Windows a common mistake would be to provide an absolute OS path + // We could strip out the base part, but that would not be very portable. + if filepath.IsAbs(name) { + return os.ErrNotExist + } + + return nil +} + +func (b *BasePathFs) Chtimes(name string, atime, mtime time.Time) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "chtimes", Path: name, Err: err} + } + return b.source.Chtimes(name, atime, mtime) +} + +func (b *BasePathFs) Chmod(name string, mode os.FileMode) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "chmod", Path: name, Err: err} + } + return b.source.Chmod(name, mode) +} + +func (b *BasePathFs) Name() string { + return "BasePathFs" +} + +func (b *BasePathFs) Stat(name string) (fi os.FileInfo, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "stat", Path: name, Err: err} + } + return b.source.Stat(name) +} + +func (b *BasePathFs) Rename(oldname, newname string) (err error) { + if oldname, err = b.RealPath(oldname); err != nil { + return &os.PathError{Op: "rename", Path: oldname, Err: err} + } + if newname, err = b.RealPath(newname); err != nil { + return &os.PathError{Op: "rename", Path: newname, Err: err} + } + return b.source.Rename(oldname, newname) +} + +func (b *BasePathFs) RemoveAll(name string) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "remove_all", Path: name, Err: err} + } + return b.source.RemoveAll(name) +} + +func (b *BasePathFs) Remove(name string) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "remove", Path: name, Err: err} + } + return b.source.Remove(name) +} + +func (b *BasePathFs) OpenFile(name string, flag int, mode os.FileMode) (f File, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "openfile", Path: name, Err: err} + } + sourcef, err := b.source.OpenFile(name, flag, mode) + if err != nil { + return nil, err + } + return &BasePathFile{sourcef, b.path}, nil +} + +func (b *BasePathFs) Open(name string) (f File, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "open", Path: name, Err: err} + } + sourcef, err := b.source.Open(name) + if err != nil { + return nil, err + } + return &BasePathFile{File: sourcef, path: b.path}, nil +} + +func (b *BasePathFs) Mkdir(name string, mode os.FileMode) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + return b.source.Mkdir(name, mode) +} + +func (b *BasePathFs) MkdirAll(name string, mode os.FileMode) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + return b.source.MkdirAll(name, mode) +} + +func (b *BasePathFs) Create(name string) (f File, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "create", Path: name, Err: err} + } + sourcef, err := b.source.Create(name) + if err != nil { + return nil, err + } + return &BasePathFile{File: sourcef, path: b.path}, nil +} + +func (b *BasePathFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + name, err := b.RealPath(name) + if err != nil { + return nil, false, &os.PathError{Op: "lstat", Path: name, Err: err} + } + if lstater, ok := b.source.(Lstater); ok { + return lstater.LstatIfPossible(name) + } + fi, err := b.source.Stat(name) + return fi, false, err +} + +// vim: ts=4 sw=4 noexpandtab nolist syn=go diff --git a/vendor/github.com/spf13/afero/cacheOnReadFs.go b/vendor/github.com/spf13/afero/cacheOnReadFs.go new file mode 100644 index 000000000..29a26c67d --- /dev/null +++ b/vendor/github.com/spf13/afero/cacheOnReadFs.go @@ -0,0 +1,290 @@ +package afero + +import ( + "os" + "syscall" + "time" +) + +// If the cache duration is 0, cache time will be unlimited, i.e. once +// a file is in the layer, the base will never be read again for this file. +// +// For cache times greater than 0, the modification time of a file is +// checked. Note that a lot of file system implementations only allow a +// resolution of a second for timestamps... or as the godoc for os.Chtimes() +// states: "The underlying filesystem may truncate or round the values to a +// less precise time unit." +// +// This caching union will forward all write calls also to the base file +// system first. To prevent writing to the base Fs, wrap it in a read-only +// filter - Note: this will also make the overlay read-only, for writing files +// in the overlay, use the overlay Fs directly, not via the union Fs. +type CacheOnReadFs struct { + base Fs + layer Fs + cacheTime time.Duration +} + +func NewCacheOnReadFs(base Fs, layer Fs, cacheTime time.Duration) Fs { + return &CacheOnReadFs{base: base, layer: layer, cacheTime: cacheTime} +} + +type cacheState int + +const ( + // not present in the overlay, unknown if it exists in the base: + cacheMiss cacheState = iota + // present in the overlay and in base, base file is newer: + cacheStale + // present in the overlay - with cache time == 0 it may exist in the base, + // with cacheTime > 0 it exists in the base and is same age or newer in the + // overlay + cacheHit + // happens if someone writes directly to the overlay without + // going through this union + cacheLocal +) + +func (u *CacheOnReadFs) cacheStatus(name string) (state cacheState, fi os.FileInfo, err error) { + var lfi, bfi os.FileInfo + lfi, err = u.layer.Stat(name) + if err == nil { + if u.cacheTime == 0 { + return cacheHit, lfi, nil + } + if lfi.ModTime().Add(u.cacheTime).Before(time.Now()) { + bfi, err = u.base.Stat(name) + if err != nil { + return cacheLocal, lfi, nil + } + if bfi.ModTime().After(lfi.ModTime()) { + return cacheStale, bfi, nil + } + } + return cacheHit, lfi, nil + } + + if err == syscall.ENOENT || os.IsNotExist(err) { + return cacheMiss, nil, nil + } + + return cacheMiss, nil, err +} + +func (u *CacheOnReadFs) copyToLayer(name string) error { + return copyToLayer(u.base, u.layer, name) +} + +func (u *CacheOnReadFs) Chtimes(name string, atime, mtime time.Time) error { + st, _, err := u.cacheStatus(name) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit: + err = u.base.Chtimes(name, atime, mtime) + case cacheStale, cacheMiss: + if err := u.copyToLayer(name); err != nil { + return err + } + err = u.base.Chtimes(name, atime, mtime) + } + if err != nil { + return err + } + return u.layer.Chtimes(name, atime, mtime) +} + +func (u *CacheOnReadFs) Chmod(name string, mode os.FileMode) error { + st, _, err := u.cacheStatus(name) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit: + err = u.base.Chmod(name, mode) + case cacheStale, cacheMiss: + if err := u.copyToLayer(name); err != nil { + return err + } + err = u.base.Chmod(name, mode) + } + if err != nil { + return err + } + return u.layer.Chmod(name, mode) +} + +func (u *CacheOnReadFs) Stat(name string) (os.FileInfo, error) { + st, fi, err := u.cacheStatus(name) + if err != nil { + return nil, err + } + switch st { + case cacheMiss: + return u.base.Stat(name) + default: // cacheStale has base, cacheHit and cacheLocal the layer os.FileInfo + return fi, nil + } +} + +func (u *CacheOnReadFs) Rename(oldname, newname string) error { + st, _, err := u.cacheStatus(oldname) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit: + err = u.base.Rename(oldname, newname) + case cacheStale, cacheMiss: + if err := u.copyToLayer(oldname); err != nil { + return err + } + err = u.base.Rename(oldname, newname) + } + if err != nil { + return err + } + return u.layer.Rename(oldname, newname) +} + +func (u *CacheOnReadFs) Remove(name string) error { + st, _, err := u.cacheStatus(name) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit, cacheStale, cacheMiss: + err = u.base.Remove(name) + } + if err != nil { + return err + } + return u.layer.Remove(name) +} + +func (u *CacheOnReadFs) RemoveAll(name string) error { + st, _, err := u.cacheStatus(name) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit, cacheStale, cacheMiss: + err = u.base.RemoveAll(name) + } + if err != nil { + return err + } + return u.layer.RemoveAll(name) +} + +func (u *CacheOnReadFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + st, _, err := u.cacheStatus(name) + if err != nil { + return nil, err + } + switch st { + case cacheLocal, cacheHit: + default: + if err := u.copyToLayer(name); err != nil { + return nil, err + } + } + if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 { + bfi, err := u.base.OpenFile(name, flag, perm) + if err != nil { + return nil, err + } + lfi, err := u.layer.OpenFile(name, flag, perm) + if err != nil { + bfi.Close() // oops, what if O_TRUNC was set and file opening in the layer failed...? + return nil, err + } + return &UnionFile{Base: bfi, Layer: lfi}, nil + } + return u.layer.OpenFile(name, flag, perm) +} + +func (u *CacheOnReadFs) Open(name string) (File, error) { + st, fi, err := u.cacheStatus(name) + if err != nil { + return nil, err + } + + switch st { + case cacheLocal: + return u.layer.Open(name) + + case cacheMiss: + bfi, err := u.base.Stat(name) + if err != nil { + return nil, err + } + if bfi.IsDir() { + return u.base.Open(name) + } + if err := u.copyToLayer(name); err != nil { + return nil, err + } + return u.layer.Open(name) + + case cacheStale: + if !fi.IsDir() { + if err := u.copyToLayer(name); err != nil { + return nil, err + } + return u.layer.Open(name) + } + case cacheHit: + if !fi.IsDir() { + return u.layer.Open(name) + } + } + // the dirs from cacheHit, cacheStale fall down here: + bfile, _ := u.base.Open(name) + lfile, err := u.layer.Open(name) + if err != nil && bfile == nil { + return nil, err + } + return &UnionFile{Base: bfile, Layer: lfile}, nil +} + +func (u *CacheOnReadFs) Mkdir(name string, perm os.FileMode) error { + err := u.base.Mkdir(name, perm) + if err != nil { + return err + } + return u.layer.MkdirAll(name, perm) // yes, MkdirAll... we cannot assume it exists in the cache +} + +func (u *CacheOnReadFs) Name() string { + return "CacheOnReadFs" +} + +func (u *CacheOnReadFs) MkdirAll(name string, perm os.FileMode) error { + err := u.base.MkdirAll(name, perm) + if err != nil { + return err + } + return u.layer.MkdirAll(name, perm) +} + +func (u *CacheOnReadFs) Create(name string) (File, error) { + bfh, err := u.base.Create(name) + if err != nil { + return nil, err + } + lfh, err := u.layer.Create(name) + if err != nil { + // oops, see comment about OS_TRUNC above, should we remove? then we have to + // remember if the file did not exist before + bfh.Close() + return nil, err + } + return &UnionFile{Base: bfh, Layer: lfh}, nil +} diff --git a/vendor/github.com/spf13/afero/const_bsds.go b/vendor/github.com/spf13/afero/const_bsds.go new file mode 100644 index 000000000..5728243d9 --- /dev/null +++ b/vendor/github.com/spf13/afero/const_bsds.go @@ -0,0 +1,22 @@ +// Copyright © 2016 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build darwin openbsd freebsd netbsd dragonfly + +package afero + +import ( + "syscall" +) + +const BADFD = syscall.EBADF diff --git a/vendor/github.com/spf13/afero/const_win_unix.go b/vendor/github.com/spf13/afero/const_win_unix.go new file mode 100644 index 000000000..968fc2783 --- /dev/null +++ b/vendor/github.com/spf13/afero/const_win_unix.go @@ -0,0 +1,25 @@ +// Copyright © 2016 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +build !darwin +// +build !openbsd +// +build !freebsd +// +build !dragonfly +// +build !netbsd + +package afero + +import ( + "syscall" +) + +const BADFD = syscall.EBADFD diff --git a/vendor/github.com/spf13/afero/copyOnWriteFs.go b/vendor/github.com/spf13/afero/copyOnWriteFs.go new file mode 100644 index 000000000..9aef39794 --- /dev/null +++ b/vendor/github.com/spf13/afero/copyOnWriteFs.go @@ -0,0 +1,292 @@ +package afero + +import ( + "fmt" + "os" + "path/filepath" + "syscall" + "time" +) + +var _ Lstater = (*CopyOnWriteFs)(nil) + +// The CopyOnWriteFs is a union filesystem: a read only base file system with +// a possibly writeable layer on top. Changes to the file system will only +// be made in the overlay: Changing an existing file in the base layer which +// is not present in the overlay will copy the file to the overlay ("changing" +// includes also calls to e.g. Chtimes() and Chmod()). +// +// Reading directories is currently only supported via Open(), not OpenFile(). +type CopyOnWriteFs struct { + base Fs + layer Fs +} + +func NewCopyOnWriteFs(base Fs, layer Fs) Fs { + return &CopyOnWriteFs{base: base, layer: layer} +} + +// Returns true if the file is not in the overlay +func (u *CopyOnWriteFs) isBaseFile(name string) (bool, error) { + if _, err := u.layer.Stat(name); err == nil { + return false, nil + } + _, err := u.base.Stat(name) + if err != nil { + if oerr, ok := err.(*os.PathError); ok { + if oerr.Err == os.ErrNotExist || oerr.Err == syscall.ENOENT || oerr.Err == syscall.ENOTDIR { + return false, nil + } + } + if err == syscall.ENOENT { + return false, nil + } + } + return true, err +} + +func (u *CopyOnWriteFs) copyToLayer(name string) error { + return copyToLayer(u.base, u.layer, name) +} + +func (u *CopyOnWriteFs) Chtimes(name string, atime, mtime time.Time) error { + b, err := u.isBaseFile(name) + if err != nil { + return err + } + if b { + if err := u.copyToLayer(name); err != nil { + return err + } + } + return u.layer.Chtimes(name, atime, mtime) +} + +func (u *CopyOnWriteFs) Chmod(name string, mode os.FileMode) error { + b, err := u.isBaseFile(name) + if err != nil { + return err + } + if b { + if err := u.copyToLayer(name); err != nil { + return err + } + } + return u.layer.Chmod(name, mode) +} + +func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) { + fi, err := u.layer.Stat(name) + if err != nil { + isNotExist := u.isNotExist(err) + if isNotExist { + return u.base.Stat(name) + } + return nil, err + } + return fi, nil +} + +func (u *CopyOnWriteFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + llayer, ok1 := u.layer.(Lstater) + lbase, ok2 := u.base.(Lstater) + + if ok1 { + fi, b, err := llayer.LstatIfPossible(name) + if err == nil { + return fi, b, nil + } + + if !u.isNotExist(err) { + return nil, b, err + } + } + + if ok2 { + fi, b, err := lbase.LstatIfPossible(name) + if err == nil { + return fi, b, nil + } + if !u.isNotExist(err) { + return nil, b, err + } + } + + fi, err := u.Stat(name) + + return fi, false, err +} + +func (u *CopyOnWriteFs) isNotExist(err error) bool { + if e, ok := err.(*os.PathError); ok { + err = e.Err + } + if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR { + return true + } + return false +} + +// Renaming files present only in the base layer is not permitted +func (u *CopyOnWriteFs) Rename(oldname, newname string) error { + b, err := u.isBaseFile(oldname) + if err != nil { + return err + } + if b { + return syscall.EPERM + } + return u.layer.Rename(oldname, newname) +} + +// Removing files present only in the base layer is not permitted. If +// a file is present in the base layer and the overlay, only the overlay +// will be removed. +func (u *CopyOnWriteFs) Remove(name string) error { + err := u.layer.Remove(name) + switch err { + case syscall.ENOENT: + _, err = u.base.Stat(name) + if err == nil { + return syscall.EPERM + } + return syscall.ENOENT + default: + return err + } +} + +func (u *CopyOnWriteFs) RemoveAll(name string) error { + err := u.layer.RemoveAll(name) + switch err { + case syscall.ENOENT: + _, err = u.base.Stat(name) + if err == nil { + return syscall.EPERM + } + return syscall.ENOENT + default: + return err + } +} + +func (u *CopyOnWriteFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + b, err := u.isBaseFile(name) + if err != nil { + return nil, err + } + + if flag&(os.O_WRONLY|os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 { + if b { + if err = u.copyToLayer(name); err != nil { + return nil, err + } + return u.layer.OpenFile(name, flag, perm) + } + + dir := filepath.Dir(name) + isaDir, err := IsDir(u.base, dir) + if err != nil && !os.IsNotExist(err) { + return nil, err + } + if isaDir { + if err = u.layer.MkdirAll(dir, 0777); err != nil { + return nil, err + } + return u.layer.OpenFile(name, flag, perm) + } + + isaDir, err = IsDir(u.layer, dir) + if err != nil { + return nil, err + } + if isaDir { + return u.layer.OpenFile(name, flag, perm) + } + + return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOTDIR} // ...or os.ErrNotExist? + } + if b { + return u.base.OpenFile(name, flag, perm) + } + return u.layer.OpenFile(name, flag, perm) +} + +// This function handles the 9 different possibilities caused +// by the union which are the intersection of the following... +// layer: doesn't exist, exists as a file, and exists as a directory +// base: doesn't exist, exists as a file, and exists as a directory +func (u *CopyOnWriteFs) Open(name string) (File, error) { + // Since the overlay overrides the base we check that first + b, err := u.isBaseFile(name) + if err != nil { + return nil, err + } + + // If overlay doesn't exist, return the base (base state irrelevant) + if b { + return u.base.Open(name) + } + + // If overlay is a file, return it (base state irrelevant) + dir, err := IsDir(u.layer, name) + if err != nil { + return nil, err + } + if !dir { + return u.layer.Open(name) + } + + // Overlay is a directory, base state now matters. + // Base state has 3 states to check but 2 outcomes: + // A. It's a file or non-readable in the base (return just the overlay) + // B. It's an accessible directory in the base (return a UnionFile) + + // If base is file or nonreadable, return overlay + dir, err = IsDir(u.base, name) + if !dir || err != nil { + return u.layer.Open(name) + } + + // Both base & layer are directories + // Return union file (if opens are without error) + bfile, bErr := u.base.Open(name) + lfile, lErr := u.layer.Open(name) + + // If either have errors at this point something is very wrong. Return nil and the errors + if bErr != nil || lErr != nil { + return nil, fmt.Errorf("BaseErr: %v\nOverlayErr: %v", bErr, lErr) + } + + return &UnionFile{Base: bfile, Layer: lfile}, nil +} + +func (u *CopyOnWriteFs) Mkdir(name string, perm os.FileMode) error { + dir, err := IsDir(u.base, name) + if err != nil { + return u.layer.MkdirAll(name, perm) + } + if dir { + return syscall.EEXIST + } + return u.layer.MkdirAll(name, perm) +} + +func (u *CopyOnWriteFs) Name() string { + return "CopyOnWriteFs" +} + +func (u *CopyOnWriteFs) MkdirAll(name string, perm os.FileMode) error { + dir, err := IsDir(u.base, name) + if err != nil { + return u.layer.MkdirAll(name, perm) + } + if dir { + return syscall.EEXIST + } + return u.layer.MkdirAll(name, perm) +} + +func (u *CopyOnWriteFs) Create(name string) (File, error) { + return u.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666) +} diff --git a/vendor/github.com/spf13/afero/go.mod b/vendor/github.com/spf13/afero/go.mod new file mode 100644 index 000000000..9eff4fed5 --- /dev/null +++ b/vendor/github.com/spf13/afero/go.mod @@ -0,0 +1 @@ +module github.com/spf13/afero diff --git a/vendor/github.com/spf13/afero/httpFs.go b/vendor/github.com/spf13/afero/httpFs.go new file mode 100644 index 000000000..c42193688 --- /dev/null +++ b/vendor/github.com/spf13/afero/httpFs.go @@ -0,0 +1,110 @@ +// Copyright © 2014 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "errors" + "net/http" + "os" + "path" + "path/filepath" + "strings" + "time" +) + +type httpDir struct { + basePath string + fs HttpFs +} + +func (d httpDir) Open(name string) (http.File, error) { + if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 || + strings.Contains(name, "\x00") { + return nil, errors.New("http: invalid character in file path") + } + dir := string(d.basePath) + if dir == "" { + dir = "." + } + + f, err := d.fs.Open(filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name)))) + if err != nil { + return nil, err + } + return f, nil +} + +type HttpFs struct { + source Fs +} + +func NewHttpFs(source Fs) *HttpFs { + return &HttpFs{source: source} +} + +func (h HttpFs) Dir(s string) *httpDir { + return &httpDir{basePath: s, fs: h} +} + +func (h HttpFs) Name() string { return "h HttpFs" } + +func (h HttpFs) Create(name string) (File, error) { + return h.source.Create(name) +} + +func (h HttpFs) Chmod(name string, mode os.FileMode) error { + return h.source.Chmod(name, mode) +} + +func (h HttpFs) Chtimes(name string, atime time.Time, mtime time.Time) error { + return h.source.Chtimes(name, atime, mtime) +} + +func (h HttpFs) Mkdir(name string, perm os.FileMode) error { + return h.source.Mkdir(name, perm) +} + +func (h HttpFs) MkdirAll(path string, perm os.FileMode) error { + return h.source.MkdirAll(path, perm) +} + +func (h HttpFs) Open(name string) (http.File, error) { + f, err := h.source.Open(name) + if err == nil { + if httpfile, ok := f.(http.File); ok { + return httpfile, nil + } + } + return nil, err +} + +func (h HttpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + return h.source.OpenFile(name, flag, perm) +} + +func (h HttpFs) Remove(name string) error { + return h.source.Remove(name) +} + +func (h HttpFs) RemoveAll(path string) error { + return h.source.RemoveAll(path) +} + +func (h HttpFs) Rename(oldname, newname string) error { + return h.source.Rename(oldname, newname) +} + +func (h HttpFs) Stat(name string) (os.FileInfo, error) { + return h.source.Stat(name) +} diff --git a/vendor/github.com/spf13/afero/ioutil.go b/vendor/github.com/spf13/afero/ioutil.go new file mode 100644 index 000000000..5c3a3d8ff --- /dev/null +++ b/vendor/github.com/spf13/afero/ioutil.go @@ -0,0 +1,230 @@ +// Copyright ©2015 The Go Authors +// Copyright ©2015 Steve Francia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "bytes" + "io" + "os" + "path/filepath" + "sort" + "strconv" + "sync" + "time" +) + +// byName implements sort.Interface. +type byName []os.FileInfo + +func (f byName) Len() int { return len(f) } +func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() } +func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] } + +// ReadDir reads the directory named by dirname and returns +// a list of sorted directory entries. +func (a Afero) ReadDir(dirname string) ([]os.FileInfo, error) { + return ReadDir(a.Fs, dirname) +} + +func ReadDir(fs Fs, dirname string) ([]os.FileInfo, error) { + f, err := fs.Open(dirname) + if err != nil { + return nil, err + } + list, err := f.Readdir(-1) + f.Close() + if err != nil { + return nil, err + } + sort.Sort(byName(list)) + return list, nil +} + +// ReadFile reads the file named by filename and returns the contents. +// A successful call returns err == nil, not err == EOF. Because ReadFile +// reads the whole file, it does not treat an EOF from Read as an error +// to be reported. +func (a Afero) ReadFile(filename string) ([]byte, error) { + return ReadFile(a.Fs, filename) +} + +func ReadFile(fs Fs, filename string) ([]byte, error) { + f, err := fs.Open(filename) + if err != nil { + return nil, err + } + defer f.Close() + // It's a good but not certain bet that FileInfo will tell us exactly how much to + // read, so let's try it but be prepared for the answer to be wrong. + var n int64 + + if fi, err := f.Stat(); err == nil { + // Don't preallocate a huge buffer, just in case. + if size := fi.Size(); size < 1e9 { + n = size + } + } + // As initial capacity for readAll, use n + a little extra in case Size is zero, + // and to avoid another allocation after Read has filled the buffer. The readAll + // call will read into its allocated internal buffer cheaply. If the size was + // wrong, we'll either waste some space off the end or reallocate as needed, but + // in the overwhelmingly common case we'll get it just right. + return readAll(f, n+bytes.MinRead) +} + +// readAll reads from r until an error or EOF and returns the data it read +// from the internal buffer allocated with a specified capacity. +func readAll(r io.Reader, capacity int64) (b []byte, err error) { + buf := bytes.NewBuffer(make([]byte, 0, capacity)) + // If the buffer overflows, we will get bytes.ErrTooLarge. + // Return that as an error. Any other panic remains. + defer func() { + e := recover() + if e == nil { + return + } + if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge { + err = panicErr + } else { + panic(e) + } + }() + _, err = buf.ReadFrom(r) + return buf.Bytes(), err +} + +// ReadAll reads from r until an error or EOF and returns the data it read. +// A successful call returns err == nil, not err == EOF. Because ReadAll is +// defined to read from src until EOF, it does not treat an EOF from Read +// as an error to be reported. +func ReadAll(r io.Reader) ([]byte, error) { + return readAll(r, bytes.MinRead) +} + +// WriteFile writes data to a file named by filename. +// If the file does not exist, WriteFile creates it with permissions perm; +// otherwise WriteFile truncates it before writing. +func (a Afero) WriteFile(filename string, data []byte, perm os.FileMode) error { + return WriteFile(a.Fs, filename, data, perm) +} + +func WriteFile(fs Fs, filename string, data []byte, perm os.FileMode) error { + f, err := fs.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) + if err != nil { + return err + } + n, err := f.Write(data) + if err == nil && n < len(data) { + err = io.ErrShortWrite + } + if err1 := f.Close(); err == nil { + err = err1 + } + return err +} + +// Random number state. +// We generate random temporary file names so that there's a good +// chance the file doesn't exist yet - keeps the number of tries in +// TempFile to a minimum. +var rand uint32 +var randmu sync.Mutex + +func reseed() uint32 { + return uint32(time.Now().UnixNano() + int64(os.Getpid())) +} + +func nextSuffix() string { + randmu.Lock() + r := rand + if r == 0 { + r = reseed() + } + r = r*1664525 + 1013904223 // constants from Numerical Recipes + rand = r + randmu.Unlock() + return strconv.Itoa(int(1e9 + r%1e9))[1:] +} + +// TempFile creates a new temporary file in the directory dir +// with a name beginning with prefix, opens the file for reading +// and writing, and returns the resulting *File. +// If dir is the empty string, TempFile uses the default directory +// for temporary files (see os.TempDir). +// Multiple programs calling TempFile simultaneously +// will not choose the same file. The caller can use f.Name() +// to find the pathname of the file. It is the caller's responsibility +// to remove the file when no longer needed. +func (a Afero) TempFile(dir, prefix string) (f File, err error) { + return TempFile(a.Fs, dir, prefix) +} + +func TempFile(fs Fs, dir, prefix string) (f File, err error) { + if dir == "" { + dir = os.TempDir() + } + + nconflict := 0 + for i := 0; i < 10000; i++ { + name := filepath.Join(dir, prefix+nextSuffix()) + f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) + if os.IsExist(err) { + if nconflict++; nconflict > 10 { + randmu.Lock() + rand = reseed() + randmu.Unlock() + } + continue + } + break + } + return +} + +// TempDir creates a new temporary directory in the directory dir +// with a name beginning with prefix and returns the path of the +// new directory. If dir is the empty string, TempDir uses the +// default directory for temporary files (see os.TempDir). +// Multiple programs calling TempDir simultaneously +// will not choose the same directory. It is the caller's responsibility +// to remove the directory when no longer needed. +func (a Afero) TempDir(dir, prefix string) (name string, err error) { + return TempDir(a.Fs, dir, prefix) +} +func TempDir(fs Fs, dir, prefix string) (name string, err error) { + if dir == "" { + dir = os.TempDir() + } + + nconflict := 0 + for i := 0; i < 10000; i++ { + try := filepath.Join(dir, prefix+nextSuffix()) + err = fs.Mkdir(try, 0700) + if os.IsExist(err) { + if nconflict++; nconflict > 10 { + randmu.Lock() + rand = reseed() + randmu.Unlock() + } + continue + } + if err == nil { + name = try + } + break + } + return +} diff --git a/vendor/github.com/spf13/afero/lstater.go b/vendor/github.com/spf13/afero/lstater.go new file mode 100644 index 000000000..89c1bfc0a --- /dev/null +++ b/vendor/github.com/spf13/afero/lstater.go @@ -0,0 +1,27 @@ +// Copyright © 2018 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "os" +) + +// Lstater is an optional interface in Afero. It is only implemented by the +// filesystems saying so. +// It will call Lstat if the filesystem iself is, or it delegates to, the os filesystem. +// Else it will call Stat. +// In addtion to the FileInfo, it will return a boolean telling whether Lstat was called or not. +type Lstater interface { + LstatIfPossible(name string) (os.FileInfo, bool, error) +} diff --git a/vendor/github.com/spf13/afero/match.go b/vendor/github.com/spf13/afero/match.go new file mode 100644 index 000000000..c18a87fb7 --- /dev/null +++ b/vendor/github.com/spf13/afero/match.go @@ -0,0 +1,110 @@ +// Copyright © 2014 Steve Francia . +// Copyright 2009 The Go Authors. All rights reserved. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "path/filepath" + "sort" + "strings" +) + +// Glob returns the names of all files matching pattern or nil +// if there is no matching file. The syntax of patterns is the same +// as in Match. The pattern may describe hierarchical names such as +// /usr/*/bin/ed (assuming the Separator is '/'). +// +// Glob ignores file system errors such as I/O errors reading directories. +// The only possible returned error is ErrBadPattern, when pattern +// is malformed. +// +// This was adapted from (http://golang.org/pkg/path/filepath) and uses several +// built-ins from that package. +func Glob(fs Fs, pattern string) (matches []string, err error) { + if !hasMeta(pattern) { + // Lstat not supported by a ll filesystems. + if _, err = lstatIfPossible(fs, pattern); err != nil { + return nil, nil + } + return []string{pattern}, nil + } + + dir, file := filepath.Split(pattern) + switch dir { + case "": + dir = "." + case string(filepath.Separator): + // nothing + default: + dir = dir[0 : len(dir)-1] // chop off trailing separator + } + + if !hasMeta(dir) { + return glob(fs, dir, file, nil) + } + + var m []string + m, err = Glob(fs, dir) + if err != nil { + return + } + for _, d := range m { + matches, err = glob(fs, d, file, matches) + if err != nil { + return + } + } + return +} + +// glob searches for files matching pattern in the directory dir +// and appends them to matches. If the directory cannot be +// opened, it returns the existing matches. New matches are +// added in lexicographical order. +func glob(fs Fs, dir, pattern string, matches []string) (m []string, e error) { + m = matches + fi, err := fs.Stat(dir) + if err != nil { + return + } + if !fi.IsDir() { + return + } + d, err := fs.Open(dir) + if err != nil { + return + } + defer d.Close() + + names, _ := d.Readdirnames(-1) + sort.Strings(names) + + for _, n := range names { + matched, err := filepath.Match(pattern, n) + if err != nil { + return m, err + } + if matched { + m = append(m, filepath.Join(dir, n)) + } + } + return +} + +// hasMeta reports whether path contains any of the magic characters +// recognized by Match. +func hasMeta(path string) bool { + // TODO(niemeyer): Should other magic characters be added here? + return strings.IndexAny(path, "*?[") >= 0 +} diff --git a/vendor/github.com/spf13/afero/mem/dir.go b/vendor/github.com/spf13/afero/mem/dir.go new file mode 100644 index 000000000..e104013f4 --- /dev/null +++ b/vendor/github.com/spf13/afero/mem/dir.go @@ -0,0 +1,37 @@ +// Copyright © 2014 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mem + +type Dir interface { + Len() int + Names() []string + Files() []*FileData + Add(*FileData) + Remove(*FileData) +} + +func RemoveFromMemDir(dir *FileData, f *FileData) { + dir.memDir.Remove(f) +} + +func AddToMemDir(dir *FileData, f *FileData) { + dir.memDir.Add(f) +} + +func InitializeDir(d *FileData) { + if d.memDir == nil { + d.dir = true + d.memDir = &DirMap{} + } +} diff --git a/vendor/github.com/spf13/afero/mem/dirmap.go b/vendor/github.com/spf13/afero/mem/dirmap.go new file mode 100644 index 000000000..03a57ee5b --- /dev/null +++ b/vendor/github.com/spf13/afero/mem/dirmap.go @@ -0,0 +1,43 @@ +// Copyright © 2015 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mem + +import "sort" + +type DirMap map[string]*FileData + +func (m DirMap) Len() int { return len(m) } +func (m DirMap) Add(f *FileData) { m[f.name] = f } +func (m DirMap) Remove(f *FileData) { delete(m, f.name) } +func (m DirMap) Files() (files []*FileData) { + for _, f := range m { + files = append(files, f) + } + sort.Sort(filesSorter(files)) + return files +} + +// implement sort.Interface for []*FileData +type filesSorter []*FileData + +func (s filesSorter) Len() int { return len(s) } +func (s filesSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s filesSorter) Less(i, j int) bool { return s[i].name < s[j].name } + +func (m DirMap) Names() (names []string) { + for x := range m { + names = append(names, x) + } + return names +} diff --git a/vendor/github.com/spf13/afero/mem/file.go b/vendor/github.com/spf13/afero/mem/file.go new file mode 100644 index 000000000..7af2fb56f --- /dev/null +++ b/vendor/github.com/spf13/afero/mem/file.go @@ -0,0 +1,317 @@ +// Copyright © 2015 Steve Francia . +// Copyright 2013 tsuru authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mem + +import ( + "bytes" + "errors" + "io" + "os" + "path/filepath" + "sync" + "sync/atomic" +) + +import "time" + +const FilePathSeparator = string(filepath.Separator) + +type File struct { + // atomic requires 64-bit alignment for struct field access + at int64 + readDirCount int64 + closed bool + readOnly bool + fileData *FileData +} + +func NewFileHandle(data *FileData) *File { + return &File{fileData: data} +} + +func NewReadOnlyFileHandle(data *FileData) *File { + return &File{fileData: data, readOnly: true} +} + +func (f File) Data() *FileData { + return f.fileData +} + +type FileData struct { + sync.Mutex + name string + data []byte + memDir Dir + dir bool + mode os.FileMode + modtime time.Time +} + +func (d *FileData) Name() string { + d.Lock() + defer d.Unlock() + return d.name +} + +func CreateFile(name string) *FileData { + return &FileData{name: name, mode: os.ModeTemporary, modtime: time.Now()} +} + +func CreateDir(name string) *FileData { + return &FileData{name: name, memDir: &DirMap{}, dir: true} +} + +func ChangeFileName(f *FileData, newname string) { + f.Lock() + f.name = newname + f.Unlock() +} + +func SetMode(f *FileData, mode os.FileMode) { + f.Lock() + f.mode = mode + f.Unlock() +} + +func SetModTime(f *FileData, mtime time.Time) { + f.Lock() + setModTime(f, mtime) + f.Unlock() +} + +func setModTime(f *FileData, mtime time.Time) { + f.modtime = mtime +} + +func GetFileInfo(f *FileData) *FileInfo { + return &FileInfo{f} +} + +func (f *File) Open() error { + atomic.StoreInt64(&f.at, 0) + atomic.StoreInt64(&f.readDirCount, 0) + f.fileData.Lock() + f.closed = false + f.fileData.Unlock() + return nil +} + +func (f *File) Close() error { + f.fileData.Lock() + f.closed = true + if !f.readOnly { + setModTime(f.fileData, time.Now()) + } + f.fileData.Unlock() + return nil +} + +func (f *File) Name() string { + return f.fileData.Name() +} + +func (f *File) Stat() (os.FileInfo, error) { + return &FileInfo{f.fileData}, nil +} + +func (f *File) Sync() error { + return nil +} + +func (f *File) Readdir(count int) (res []os.FileInfo, err error) { + if !f.fileData.dir { + return nil, &os.PathError{Op: "readdir", Path: f.fileData.name, Err: errors.New("not a dir")} + } + var outLength int64 + + f.fileData.Lock() + files := f.fileData.memDir.Files()[f.readDirCount:] + if count > 0 { + if len(files) < count { + outLength = int64(len(files)) + } else { + outLength = int64(count) + } + if len(files) == 0 { + err = io.EOF + } + } else { + outLength = int64(len(files)) + } + f.readDirCount += outLength + f.fileData.Unlock() + + res = make([]os.FileInfo, outLength) + for i := range res { + res[i] = &FileInfo{files[i]} + } + + return res, err +} + +func (f *File) Readdirnames(n int) (names []string, err error) { + fi, err := f.Readdir(n) + names = make([]string, len(fi)) + for i, f := range fi { + _, names[i] = filepath.Split(f.Name()) + } + return names, err +} + +func (f *File) Read(b []byte) (n int, err error) { + f.fileData.Lock() + defer f.fileData.Unlock() + if f.closed == true { + return 0, ErrFileClosed + } + if len(b) > 0 && int(f.at) == len(f.fileData.data) { + return 0, io.EOF + } + if int(f.at) > len(f.fileData.data) { + return 0, io.ErrUnexpectedEOF + } + if len(f.fileData.data)-int(f.at) >= len(b) { + n = len(b) + } else { + n = len(f.fileData.data) - int(f.at) + } + copy(b, f.fileData.data[f.at:f.at+int64(n)]) + atomic.AddInt64(&f.at, int64(n)) + return +} + +func (f *File) ReadAt(b []byte, off int64) (n int, err error) { + atomic.StoreInt64(&f.at, off) + return f.Read(b) +} + +func (f *File) Truncate(size int64) error { + if f.closed == true { + return ErrFileClosed + } + if f.readOnly { + return &os.PathError{Op: "truncate", Path: f.fileData.name, Err: errors.New("file handle is read only")} + } + if size < 0 { + return ErrOutOfRange + } + if size > int64(len(f.fileData.data)) { + diff := size - int64(len(f.fileData.data)) + f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{00}, int(diff))...) + } else { + f.fileData.data = f.fileData.data[0:size] + } + setModTime(f.fileData, time.Now()) + return nil +} + +func (f *File) Seek(offset int64, whence int) (int64, error) { + if f.closed == true { + return 0, ErrFileClosed + } + switch whence { + case 0: + atomic.StoreInt64(&f.at, offset) + case 1: + atomic.AddInt64(&f.at, int64(offset)) + case 2: + atomic.StoreInt64(&f.at, int64(len(f.fileData.data))+offset) + } + return f.at, nil +} + +func (f *File) Write(b []byte) (n int, err error) { + if f.readOnly { + return 0, &os.PathError{Op: "write", Path: f.fileData.name, Err: errors.New("file handle is read only")} + } + n = len(b) + cur := atomic.LoadInt64(&f.at) + f.fileData.Lock() + defer f.fileData.Unlock() + diff := cur - int64(len(f.fileData.data)) + var tail []byte + if n+int(cur) < len(f.fileData.data) { + tail = f.fileData.data[n+int(cur):] + } + if diff > 0 { + f.fileData.data = append(bytes.Repeat([]byte{00}, int(diff)), b...) + f.fileData.data = append(f.fileData.data, tail...) + } else { + f.fileData.data = append(f.fileData.data[:cur], b...) + f.fileData.data = append(f.fileData.data, tail...) + } + setModTime(f.fileData, time.Now()) + + atomic.StoreInt64(&f.at, int64(len(f.fileData.data))) + return +} + +func (f *File) WriteAt(b []byte, off int64) (n int, err error) { + atomic.StoreInt64(&f.at, off) + return f.Write(b) +} + +func (f *File) WriteString(s string) (ret int, err error) { + return f.Write([]byte(s)) +} + +func (f *File) Info() *FileInfo { + return &FileInfo{f.fileData} +} + +type FileInfo struct { + *FileData +} + +// Implements os.FileInfo +func (s *FileInfo) Name() string { + s.Lock() + _, name := filepath.Split(s.name) + s.Unlock() + return name +} +func (s *FileInfo) Mode() os.FileMode { + s.Lock() + defer s.Unlock() + return s.mode +} +func (s *FileInfo) ModTime() time.Time { + s.Lock() + defer s.Unlock() + return s.modtime +} +func (s *FileInfo) IsDir() bool { + s.Lock() + defer s.Unlock() + return s.dir +} +func (s *FileInfo) Sys() interface{} { return nil } +func (s *FileInfo) Size() int64 { + if s.IsDir() { + return int64(42) + } + s.Lock() + defer s.Unlock() + return int64(len(s.data)) +} + +var ( + ErrFileClosed = errors.New("File is closed") + ErrOutOfRange = errors.New("Out of range") + ErrTooLarge = errors.New("Too large") + ErrFileNotFound = os.ErrNotExist + ErrFileExists = os.ErrExist + ErrDestinationExists = os.ErrExist +) diff --git a/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/spf13/afero/memmap.go new file mode 100644 index 000000000..09498e70f --- /dev/null +++ b/vendor/github.com/spf13/afero/memmap.go @@ -0,0 +1,365 @@ +// Copyright © 2014 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "fmt" + "log" + "os" + "path/filepath" + "strings" + "sync" + "time" + + "github.com/spf13/afero/mem" +) + +type MemMapFs struct { + mu sync.RWMutex + data map[string]*mem.FileData + init sync.Once +} + +func NewMemMapFs() Fs { + return &MemMapFs{} +} + +func (m *MemMapFs) getData() map[string]*mem.FileData { + m.init.Do(func() { + m.data = make(map[string]*mem.FileData) + // Root should always exist, right? + // TODO: what about windows? + m.data[FilePathSeparator] = mem.CreateDir(FilePathSeparator) + }) + return m.data +} + +func (*MemMapFs) Name() string { return "MemMapFS" } + +func (m *MemMapFs) Create(name string) (File, error) { + name = normalizePath(name) + m.mu.Lock() + file := mem.CreateFile(name) + m.getData()[name] = file + m.registerWithParent(file) + m.mu.Unlock() + return mem.NewFileHandle(file), nil +} + +func (m *MemMapFs) unRegisterWithParent(fileName string) error { + f, err := m.lockfreeOpen(fileName) + if err != nil { + return err + } + parent := m.findParent(f) + if parent == nil { + log.Panic("parent of ", f.Name(), " is nil") + } + + parent.Lock() + mem.RemoveFromMemDir(parent, f) + parent.Unlock() + return nil +} + +func (m *MemMapFs) findParent(f *mem.FileData) *mem.FileData { + pdir, _ := filepath.Split(f.Name()) + pdir = filepath.Clean(pdir) + pfile, err := m.lockfreeOpen(pdir) + if err != nil { + return nil + } + return pfile +} + +func (m *MemMapFs) registerWithParent(f *mem.FileData) { + if f == nil { + return + } + parent := m.findParent(f) + if parent == nil { + pdir := filepath.Dir(filepath.Clean(f.Name())) + err := m.lockfreeMkdir(pdir, 0777) + if err != nil { + //log.Println("Mkdir error:", err) + return + } + parent, err = m.lockfreeOpen(pdir) + if err != nil { + //log.Println("Open after Mkdir error:", err) + return + } + } + + parent.Lock() + mem.InitializeDir(parent) + mem.AddToMemDir(parent, f) + parent.Unlock() +} + +func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error { + name = normalizePath(name) + x, ok := m.getData()[name] + if ok { + // Only return ErrFileExists if it's a file, not a directory. + i := mem.FileInfo{FileData: x} + if !i.IsDir() { + return ErrFileExists + } + } else { + item := mem.CreateDir(name) + m.getData()[name] = item + m.registerWithParent(item) + } + return nil +} + +func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error { + name = normalizePath(name) + + m.mu.RLock() + _, ok := m.getData()[name] + m.mu.RUnlock() + if ok { + return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists} + } + + m.mu.Lock() + item := mem.CreateDir(name) + m.getData()[name] = item + m.registerWithParent(item) + m.mu.Unlock() + + m.Chmod(name, perm|os.ModeDir) + + return nil +} + +func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error { + err := m.Mkdir(path, perm) + if err != nil { + if err.(*os.PathError).Err == ErrFileExists { + return nil + } + return err + } + return nil +} + +// Handle some relative paths +func normalizePath(path string) string { + path = filepath.Clean(path) + + switch path { + case ".": + return FilePathSeparator + case "..": + return FilePathSeparator + default: + return path + } +} + +func (m *MemMapFs) Open(name string) (File, error) { + f, err := m.open(name) + if f != nil { + return mem.NewReadOnlyFileHandle(f), err + } + return nil, err +} + +func (m *MemMapFs) openWrite(name string) (File, error) { + f, err := m.open(name) + if f != nil { + return mem.NewFileHandle(f), err + } + return nil, err +} + +func (m *MemMapFs) open(name string) (*mem.FileData, error) { + name = normalizePath(name) + + m.mu.RLock() + f, ok := m.getData()[name] + m.mu.RUnlock() + if !ok { + return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound} + } + return f, nil +} + +func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) { + name = normalizePath(name) + f, ok := m.getData()[name] + if ok { + return f, nil + } else { + return nil, ErrFileNotFound + } +} + +func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + chmod := false + file, err := m.openWrite(name) + if os.IsNotExist(err) && (flag&os.O_CREATE > 0) { + file, err = m.Create(name) + chmod = true + } + if err != nil { + return nil, err + } + if flag == os.O_RDONLY { + file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data()) + } + if flag&os.O_APPEND > 0 { + _, err = file.Seek(0, os.SEEK_END) + if err != nil { + file.Close() + return nil, err + } + } + if flag&os.O_TRUNC > 0 && flag&(os.O_RDWR|os.O_WRONLY) > 0 { + err = file.Truncate(0) + if err != nil { + file.Close() + return nil, err + } + } + if chmod { + m.Chmod(name, perm) + } + return file, nil +} + +func (m *MemMapFs) Remove(name string) error { + name = normalizePath(name) + + m.mu.Lock() + defer m.mu.Unlock() + + if _, ok := m.getData()[name]; ok { + err := m.unRegisterWithParent(name) + if err != nil { + return &os.PathError{Op: "remove", Path: name, Err: err} + } + delete(m.getData(), name) + } else { + return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist} + } + return nil +} + +func (m *MemMapFs) RemoveAll(path string) error { + path = normalizePath(path) + m.mu.Lock() + m.unRegisterWithParent(path) + m.mu.Unlock() + + m.mu.RLock() + defer m.mu.RUnlock() + + for p, _ := range m.getData() { + if strings.HasPrefix(p, path) { + m.mu.RUnlock() + m.mu.Lock() + delete(m.getData(), p) + m.mu.Unlock() + m.mu.RLock() + } + } + return nil +} + +func (m *MemMapFs) Rename(oldname, newname string) error { + oldname = normalizePath(oldname) + newname = normalizePath(newname) + + if oldname == newname { + return nil + } + + m.mu.RLock() + defer m.mu.RUnlock() + if _, ok := m.getData()[oldname]; ok { + m.mu.RUnlock() + m.mu.Lock() + m.unRegisterWithParent(oldname) + fileData := m.getData()[oldname] + delete(m.getData(), oldname) + mem.ChangeFileName(fileData, newname) + m.getData()[newname] = fileData + m.registerWithParent(fileData) + m.mu.Unlock() + m.mu.RLock() + } else { + return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound} + } + return nil +} + +func (m *MemMapFs) Stat(name string) (os.FileInfo, error) { + f, err := m.Open(name) + if err != nil { + return nil, err + } + fi := mem.GetFileInfo(f.(*mem.File).Data()) + return fi, nil +} + +func (m *MemMapFs) Chmod(name string, mode os.FileMode) error { + name = normalizePath(name) + + m.mu.RLock() + f, ok := m.getData()[name] + m.mu.RUnlock() + if !ok { + return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound} + } + + m.mu.Lock() + mem.SetMode(f, mode) + m.mu.Unlock() + + return nil +} + +func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error { + name = normalizePath(name) + + m.mu.RLock() + f, ok := m.getData()[name] + m.mu.RUnlock() + if !ok { + return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound} + } + + m.mu.Lock() + mem.SetModTime(f, mtime) + m.mu.Unlock() + + return nil +} + +func (m *MemMapFs) List() { + for _, x := range m.data { + y := mem.FileInfo{FileData: x} + fmt.Println(x.Name(), y.Size()) + } +} + +// func debugMemMapList(fs Fs) { +// if x, ok := fs.(*MemMapFs); ok { +// x.List() +// } +// } diff --git a/vendor/github.com/spf13/afero/os.go b/vendor/github.com/spf13/afero/os.go new file mode 100644 index 000000000..13cc1b84c --- /dev/null +++ b/vendor/github.com/spf13/afero/os.go @@ -0,0 +1,101 @@ +// Copyright © 2014 Steve Francia . +// Copyright 2013 tsuru authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "os" + "time" +) + +var _ Lstater = (*OsFs)(nil) + +// OsFs is a Fs implementation that uses functions provided by the os package. +// +// For details in any method, check the documentation of the os package +// (http://golang.org/pkg/os/). +type OsFs struct{} + +func NewOsFs() Fs { + return &OsFs{} +} + +func (OsFs) Name() string { return "OsFs" } + +func (OsFs) Create(name string) (File, error) { + f, e := os.Create(name) + if f == nil { + // while this looks strange, we need to return a bare nil (of type nil) not + // a nil value of type *os.File or nil won't be nil + return nil, e + } + return f, e +} + +func (OsFs) Mkdir(name string, perm os.FileMode) error { + return os.Mkdir(name, perm) +} + +func (OsFs) MkdirAll(path string, perm os.FileMode) error { + return os.MkdirAll(path, perm) +} + +func (OsFs) Open(name string) (File, error) { + f, e := os.Open(name) + if f == nil { + // while this looks strange, we need to return a bare nil (of type nil) not + // a nil value of type *os.File or nil won't be nil + return nil, e + } + return f, e +} + +func (OsFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + f, e := os.OpenFile(name, flag, perm) + if f == nil { + // while this looks strange, we need to return a bare nil (of type nil) not + // a nil value of type *os.File or nil won't be nil + return nil, e + } + return f, e +} + +func (OsFs) Remove(name string) error { + return os.Remove(name) +} + +func (OsFs) RemoveAll(path string) error { + return os.RemoveAll(path) +} + +func (OsFs) Rename(oldname, newname string) error { + return os.Rename(oldname, newname) +} + +func (OsFs) Stat(name string) (os.FileInfo, error) { + return os.Stat(name) +} + +func (OsFs) Chmod(name string, mode os.FileMode) error { + return os.Chmod(name, mode) +} + +func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error { + return os.Chtimes(name, atime, mtime) +} + +func (OsFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + fi, err := os.Lstat(name) + return fi, true, err +} diff --git a/vendor/github.com/spf13/afero/path.go b/vendor/github.com/spf13/afero/path.go new file mode 100644 index 000000000..18f60a0f6 --- /dev/null +++ b/vendor/github.com/spf13/afero/path.go @@ -0,0 +1,106 @@ +// Copyright ©2015 The Go Authors +// Copyright ©2015 Steve Francia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "os" + "path/filepath" + "sort" +) + +// readDirNames reads the directory named by dirname and returns +// a sorted list of directory entries. +// adapted from https://golang.org/src/path/filepath/path.go +func readDirNames(fs Fs, dirname string) ([]string, error) { + f, err := fs.Open(dirname) + if err != nil { + return nil, err + } + names, err := f.Readdirnames(-1) + f.Close() + if err != nil { + return nil, err + } + sort.Strings(names) + return names, nil +} + +// walk recursively descends path, calling walkFn +// adapted from https://golang.org/src/path/filepath/path.go +func walk(fs Fs, path string, info os.FileInfo, walkFn filepath.WalkFunc) error { + err := walkFn(path, info, nil) + if err != nil { + if info.IsDir() && err == filepath.SkipDir { + return nil + } + return err + } + + if !info.IsDir() { + return nil + } + + names, err := readDirNames(fs, path) + if err != nil { + return walkFn(path, info, err) + } + + for _, name := range names { + filename := filepath.Join(path, name) + fileInfo, err := lstatIfPossible(fs, filename) + if err != nil { + if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir { + return err + } + } else { + err = walk(fs, filename, fileInfo, walkFn) + if err != nil { + if !fileInfo.IsDir() || err != filepath.SkipDir { + return err + } + } + } + } + return nil +} + +// if the filesystem supports it, use Lstat, else use fs.Stat +func lstatIfPossible(fs Fs, path string) (os.FileInfo, error) { + if lfs, ok := fs.(Lstater); ok { + fi, _, err := lfs.LstatIfPossible(path) + return fi, err + } + return fs.Stat(path) +} + +// Walk walks the file tree rooted at root, calling walkFn for each file or +// directory in the tree, including root. All errors that arise visiting files +// and directories are filtered by walkFn. The files are walked in lexical +// order, which makes the output deterministic but means that for very +// large directories Walk can be inefficient. +// Walk does not follow symbolic links. + +func (a Afero) Walk(root string, walkFn filepath.WalkFunc) error { + return Walk(a.Fs, root, walkFn) +} + +func Walk(fs Fs, root string, walkFn filepath.WalkFunc) error { + info, err := lstatIfPossible(fs, root) + if err != nil { + return walkFn(root, nil, err) + } + return walk(fs, root, info, walkFn) +} diff --git a/vendor/github.com/spf13/afero/readonlyfs.go b/vendor/github.com/spf13/afero/readonlyfs.go new file mode 100644 index 000000000..c6376ec37 --- /dev/null +++ b/vendor/github.com/spf13/afero/readonlyfs.go @@ -0,0 +1,80 @@ +package afero + +import ( + "os" + "syscall" + "time" +) + +var _ Lstater = (*ReadOnlyFs)(nil) + +type ReadOnlyFs struct { + source Fs +} + +func NewReadOnlyFs(source Fs) Fs { + return &ReadOnlyFs{source: source} +} + +func (r *ReadOnlyFs) ReadDir(name string) ([]os.FileInfo, error) { + return ReadDir(r.source, name) +} + +func (r *ReadOnlyFs) Chtimes(n string, a, m time.Time) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) Chmod(n string, m os.FileMode) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) Name() string { + return "ReadOnlyFilter" +} + +func (r *ReadOnlyFs) Stat(name string) (os.FileInfo, error) { + return r.source.Stat(name) +} + +func (r *ReadOnlyFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + if lsf, ok := r.source.(Lstater); ok { + return lsf.LstatIfPossible(name) + } + fi, err := r.Stat(name) + return fi, false, err +} + +func (r *ReadOnlyFs) Rename(o, n string) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) RemoveAll(p string) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) Remove(n string) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 { + return nil, syscall.EPERM + } + return r.source.OpenFile(name, flag, perm) +} + +func (r *ReadOnlyFs) Open(n string) (File, error) { + return r.source.Open(n) +} + +func (r *ReadOnlyFs) Mkdir(n string, p os.FileMode) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) MkdirAll(n string, p os.FileMode) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) Create(n string) (File, error) { + return nil, syscall.EPERM +} diff --git a/vendor/github.com/spf13/afero/regexpfs.go b/vendor/github.com/spf13/afero/regexpfs.go new file mode 100644 index 000000000..9d92dbc05 --- /dev/null +++ b/vendor/github.com/spf13/afero/regexpfs.go @@ -0,0 +1,214 @@ +package afero + +import ( + "os" + "regexp" + "syscall" + "time" +) + +// The RegexpFs filters files (not directories) by regular expression. Only +// files matching the given regexp will be allowed, all others get a ENOENT error ( +// "No such file or directory"). +// +type RegexpFs struct { + re *regexp.Regexp + source Fs +} + +func NewRegexpFs(source Fs, re *regexp.Regexp) Fs { + return &RegexpFs{source: source, re: re} +} + +type RegexpFile struct { + f File + re *regexp.Regexp +} + +func (r *RegexpFs) matchesName(name string) error { + if r.re == nil { + return nil + } + if r.re.MatchString(name) { + return nil + } + return syscall.ENOENT +} + +func (r *RegexpFs) dirOrMatches(name string) error { + dir, err := IsDir(r.source, name) + if err != nil { + return err + } + if dir { + return nil + } + return r.matchesName(name) +} + +func (r *RegexpFs) Chtimes(name string, a, m time.Time) error { + if err := r.dirOrMatches(name); err != nil { + return err + } + return r.source.Chtimes(name, a, m) +} + +func (r *RegexpFs) Chmod(name string, mode os.FileMode) error { + if err := r.dirOrMatches(name); err != nil { + return err + } + return r.source.Chmod(name, mode) +} + +func (r *RegexpFs) Name() string { + return "RegexpFs" +} + +func (r *RegexpFs) Stat(name string) (os.FileInfo, error) { + if err := r.dirOrMatches(name); err != nil { + return nil, err + } + return r.source.Stat(name) +} + +func (r *RegexpFs) Rename(oldname, newname string) error { + dir, err := IsDir(r.source, oldname) + if err != nil { + return err + } + if dir { + return nil + } + if err := r.matchesName(oldname); err != nil { + return err + } + if err := r.matchesName(newname); err != nil { + return err + } + return r.source.Rename(oldname, newname) +} + +func (r *RegexpFs) RemoveAll(p string) error { + dir, err := IsDir(r.source, p) + if err != nil { + return err + } + if !dir { + if err := r.matchesName(p); err != nil { + return err + } + } + return r.source.RemoveAll(p) +} + +func (r *RegexpFs) Remove(name string) error { + if err := r.dirOrMatches(name); err != nil { + return err + } + return r.source.Remove(name) +} + +func (r *RegexpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + if err := r.dirOrMatches(name); err != nil { + return nil, err + } + return r.source.OpenFile(name, flag, perm) +} + +func (r *RegexpFs) Open(name string) (File, error) { + dir, err := IsDir(r.source, name) + if err != nil { + return nil, err + } + if !dir { + if err := r.matchesName(name); err != nil { + return nil, err + } + } + f, err := r.source.Open(name) + return &RegexpFile{f: f, re: r.re}, nil +} + +func (r *RegexpFs) Mkdir(n string, p os.FileMode) error { + return r.source.Mkdir(n, p) +} + +func (r *RegexpFs) MkdirAll(n string, p os.FileMode) error { + return r.source.MkdirAll(n, p) +} + +func (r *RegexpFs) Create(name string) (File, error) { + if err := r.matchesName(name); err != nil { + return nil, err + } + return r.source.Create(name) +} + +func (f *RegexpFile) Close() error { + return f.f.Close() +} + +func (f *RegexpFile) Read(s []byte) (int, error) { + return f.f.Read(s) +} + +func (f *RegexpFile) ReadAt(s []byte, o int64) (int, error) { + return f.f.ReadAt(s, o) +} + +func (f *RegexpFile) Seek(o int64, w int) (int64, error) { + return f.f.Seek(o, w) +} + +func (f *RegexpFile) Write(s []byte) (int, error) { + return f.f.Write(s) +} + +func (f *RegexpFile) WriteAt(s []byte, o int64) (int, error) { + return f.f.WriteAt(s, o) +} + +func (f *RegexpFile) Name() string { + return f.f.Name() +} + +func (f *RegexpFile) Readdir(c int) (fi []os.FileInfo, err error) { + var rfi []os.FileInfo + rfi, err = f.f.Readdir(c) + if err != nil { + return nil, err + } + for _, i := range rfi { + if i.IsDir() || f.re.MatchString(i.Name()) { + fi = append(fi, i) + } + } + return fi, nil +} + +func (f *RegexpFile) Readdirnames(c int) (n []string, err error) { + fi, err := f.Readdir(c) + if err != nil { + return nil, err + } + for _, s := range fi { + n = append(n, s.Name()) + } + return n, nil +} + +func (f *RegexpFile) Stat() (os.FileInfo, error) { + return f.f.Stat() +} + +func (f *RegexpFile) Sync() error { + return f.f.Sync() +} + +func (f *RegexpFile) Truncate(s int64) error { + return f.f.Truncate(s) +} + +func (f *RegexpFile) WriteString(s string) (int, error) { + return f.f.WriteString(s) +} diff --git a/vendor/github.com/spf13/afero/unionFile.go b/vendor/github.com/spf13/afero/unionFile.go new file mode 100644 index 000000000..1e78f7d1e --- /dev/null +++ b/vendor/github.com/spf13/afero/unionFile.go @@ -0,0 +1,305 @@ +package afero + +import ( + "io" + "os" + "path/filepath" + "syscall" +) + +// The UnionFile implements the afero.File interface and will be returned +// when reading a directory present at least in the overlay or opening a file +// for writing. +// +// The calls to +// Readdir() and Readdirnames() merge the file os.FileInfo / names from the +// base and the overlay - for files present in both layers, only those +// from the overlay will be used. +// +// When opening files for writing (Create() / OpenFile() with the right flags) +// the operations will be done in both layers, starting with the overlay. A +// successful read in the overlay will move the cursor position in the base layer +// by the number of bytes read. +type UnionFile struct { + Base File + Layer File + Merger DirsMerger + off int + files []os.FileInfo +} + +func (f *UnionFile) Close() error { + // first close base, so we have a newer timestamp in the overlay. If we'd close + // the overlay first, we'd get a cacheStale the next time we access this file + // -> cache would be useless ;-) + if f.Base != nil { + f.Base.Close() + } + if f.Layer != nil { + return f.Layer.Close() + } + return BADFD +} + +func (f *UnionFile) Read(s []byte) (int, error) { + if f.Layer != nil { + n, err := f.Layer.Read(s) + if (err == nil || err == io.EOF) && f.Base != nil { + // advance the file position also in the base file, the next + // call may be a write at this position (or a seek with SEEK_CUR) + if _, seekErr := f.Base.Seek(int64(n), os.SEEK_CUR); seekErr != nil { + // only overwrite err in case the seek fails: we need to + // report an eventual io.EOF to the caller + err = seekErr + } + } + return n, err + } + if f.Base != nil { + return f.Base.Read(s) + } + return 0, BADFD +} + +func (f *UnionFile) ReadAt(s []byte, o int64) (int, error) { + if f.Layer != nil { + n, err := f.Layer.ReadAt(s, o) + if (err == nil || err == io.EOF) && f.Base != nil { + _, err = f.Base.Seek(o+int64(n), os.SEEK_SET) + } + return n, err + } + if f.Base != nil { + return f.Base.ReadAt(s, o) + } + return 0, BADFD +} + +func (f *UnionFile) Seek(o int64, w int) (pos int64, err error) { + if f.Layer != nil { + pos, err = f.Layer.Seek(o, w) + if (err == nil || err == io.EOF) && f.Base != nil { + _, err = f.Base.Seek(o, w) + } + return pos, err + } + if f.Base != nil { + return f.Base.Seek(o, w) + } + return 0, BADFD +} + +func (f *UnionFile) Write(s []byte) (n int, err error) { + if f.Layer != nil { + n, err = f.Layer.Write(s) + if err == nil && f.Base != nil { // hmm, do we have fixed size files where a write may hit the EOF mark? + _, err = f.Base.Write(s) + } + return n, err + } + if f.Base != nil { + return f.Base.Write(s) + } + return 0, BADFD +} + +func (f *UnionFile) WriteAt(s []byte, o int64) (n int, err error) { + if f.Layer != nil { + n, err = f.Layer.WriteAt(s, o) + if err == nil && f.Base != nil { + _, err = f.Base.WriteAt(s, o) + } + return n, err + } + if f.Base != nil { + return f.Base.WriteAt(s, o) + } + return 0, BADFD +} + +func (f *UnionFile) Name() string { + if f.Layer != nil { + return f.Layer.Name() + } + return f.Base.Name() +} + +// DirsMerger is how UnionFile weaves two directories together. +// It takes the FileInfo slices from the layer and the base and returns a +// single view. +type DirsMerger func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) + +var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) { + var files = make(map[string]os.FileInfo) + + for _, fi := range lofi { + files[fi.Name()] = fi + } + + for _, fi := range bofi { + if _, exists := files[fi.Name()]; !exists { + files[fi.Name()] = fi + } + } + + rfi := make([]os.FileInfo, len(files)) + + i := 0 + for _, fi := range files { + rfi[i] = fi + i++ + } + + return rfi, nil + +} + +// Readdir will weave the two directories together and +// return a single view of the overlayed directories +func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { + var merge DirsMerger = f.Merger + if merge == nil { + merge = defaultUnionMergeDirsFn + } + + if f.off == 0 { + var lfi []os.FileInfo + if f.Layer != nil { + lfi, err = f.Layer.Readdir(-1) + if err != nil { + return nil, err + } + } + + var bfi []os.FileInfo + if f.Base != nil { + bfi, err = f.Base.Readdir(-1) + if err != nil { + return nil, err + } + + } + merged, err := merge(lfi, bfi) + if err != nil { + return nil, err + } + f.files = append(f.files, merged...) + } + if c == -1 { + return f.files[f.off:], nil + } + defer func() { f.off += c }() + return f.files[f.off:c], nil +} + +func (f *UnionFile) Readdirnames(c int) ([]string, error) { + rfi, err := f.Readdir(c) + if err != nil { + return nil, err + } + var names []string + for _, fi := range rfi { + names = append(names, fi.Name()) + } + return names, nil +} + +func (f *UnionFile) Stat() (os.FileInfo, error) { + if f.Layer != nil { + return f.Layer.Stat() + } + if f.Base != nil { + return f.Base.Stat() + } + return nil, BADFD +} + +func (f *UnionFile) Sync() (err error) { + if f.Layer != nil { + err = f.Layer.Sync() + if err == nil && f.Base != nil { + err = f.Base.Sync() + } + return err + } + if f.Base != nil { + return f.Base.Sync() + } + return BADFD +} + +func (f *UnionFile) Truncate(s int64) (err error) { + if f.Layer != nil { + err = f.Layer.Truncate(s) + if err == nil && f.Base != nil { + err = f.Base.Truncate(s) + } + return err + } + if f.Base != nil { + return f.Base.Truncate(s) + } + return BADFD +} + +func (f *UnionFile) WriteString(s string) (n int, err error) { + if f.Layer != nil { + n, err = f.Layer.WriteString(s) + if err == nil && f.Base != nil { + _, err = f.Base.WriteString(s) + } + return n, err + } + if f.Base != nil { + return f.Base.WriteString(s) + } + return 0, BADFD +} + +func copyToLayer(base Fs, layer Fs, name string) error { + bfh, err := base.Open(name) + if err != nil { + return err + } + defer bfh.Close() + + // First make sure the directory exists + exists, err := Exists(layer, filepath.Dir(name)) + if err != nil { + return err + } + if !exists { + err = layer.MkdirAll(filepath.Dir(name), 0777) // FIXME? + if err != nil { + return err + } + } + + // Create the file on the overlay + lfh, err := layer.Create(name) + if err != nil { + return err + } + n, err := io.Copy(lfh, bfh) + if err != nil { + // If anything fails, clean up the file + layer.Remove(name) + lfh.Close() + return err + } + + bfi, err := bfh.Stat() + if err != nil || bfi.Size() != n { + layer.Remove(name) + lfh.Close() + return syscall.EIO + } + + err = lfh.Close() + if err != nil { + layer.Remove(name) + lfh.Close() + return err + } + return layer.Chtimes(name, bfi.ModTime(), bfi.ModTime()) +} diff --git a/vendor/github.com/spf13/afero/util.go b/vendor/github.com/spf13/afero/util.go new file mode 100644 index 000000000..4f253f481 --- /dev/null +++ b/vendor/github.com/spf13/afero/util.go @@ -0,0 +1,330 @@ +// Copyright ©2015 Steve Francia +// Portions Copyright ©2015 The Hugo Authors +// Portions Copyright 2016-present Bjørn Erik Pedersen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "unicode" + + "golang.org/x/text/transform" + "golang.org/x/text/unicode/norm" +) + +// Filepath separator defined by os.Separator. +const FilePathSeparator = string(filepath.Separator) + +// Takes a reader and a path and writes the content +func (a Afero) WriteReader(path string, r io.Reader) (err error) { + return WriteReader(a.Fs, path, r) +} + +func WriteReader(fs Fs, path string, r io.Reader) (err error) { + dir, _ := filepath.Split(path) + ospath := filepath.FromSlash(dir) + + if ospath != "" { + err = fs.MkdirAll(ospath, 0777) // rwx, rw, r + if err != nil { + if err != os.ErrExist { + return err + } + } + } + + file, err := fs.Create(path) + if err != nil { + return + } + defer file.Close() + + _, err = io.Copy(file, r) + return +} + +// Same as WriteReader but checks to see if file/directory already exists. +func (a Afero) SafeWriteReader(path string, r io.Reader) (err error) { + return SafeWriteReader(a.Fs, path, r) +} + +func SafeWriteReader(fs Fs, path string, r io.Reader) (err error) { + dir, _ := filepath.Split(path) + ospath := filepath.FromSlash(dir) + + if ospath != "" { + err = fs.MkdirAll(ospath, 0777) // rwx, rw, r + if err != nil { + return + } + } + + exists, err := Exists(fs, path) + if err != nil { + return + } + if exists { + return fmt.Errorf("%v already exists", path) + } + + file, err := fs.Create(path) + if err != nil { + return + } + defer file.Close() + + _, err = io.Copy(file, r) + return +} + +func (a Afero) GetTempDir(subPath string) string { + return GetTempDir(a.Fs, subPath) +} + +// GetTempDir returns the default temp directory with trailing slash +// if subPath is not empty then it will be created recursively with mode 777 rwx rwx rwx +func GetTempDir(fs Fs, subPath string) string { + addSlash := func(p string) string { + if FilePathSeparator != p[len(p)-1:] { + p = p + FilePathSeparator + } + return p + } + dir := addSlash(os.TempDir()) + + if subPath != "" { + // preserve windows backslash :-( + if FilePathSeparator == "\\" { + subPath = strings.Replace(subPath, "\\", "____", -1) + } + dir = dir + UnicodeSanitize((subPath)) + if FilePathSeparator == "\\" { + dir = strings.Replace(dir, "____", "\\", -1) + } + + if exists, _ := Exists(fs, dir); exists { + return addSlash(dir) + } + + err := fs.MkdirAll(dir, 0777) + if err != nil { + panic(err) + } + dir = addSlash(dir) + } + return dir +} + +// Rewrite string to remove non-standard path characters +func UnicodeSanitize(s string) string { + source := []rune(s) + target := make([]rune, 0, len(source)) + + for _, r := range source { + if unicode.IsLetter(r) || + unicode.IsDigit(r) || + unicode.IsMark(r) || + r == '.' || + r == '/' || + r == '\\' || + r == '_' || + r == '-' || + r == '%' || + r == ' ' || + r == '#' { + target = append(target, r) + } + } + + return string(target) +} + +// Transform characters with accents into plain forms. +func NeuterAccents(s string) string { + t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC) + result, _, _ := transform.String(t, string(s)) + + return result +} + +func isMn(r rune) bool { + return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks +} + +func (a Afero) FileContainsBytes(filename string, subslice []byte) (bool, error) { + return FileContainsBytes(a.Fs, filename, subslice) +} + +// Check if a file contains a specified byte slice. +func FileContainsBytes(fs Fs, filename string, subslice []byte) (bool, error) { + f, err := fs.Open(filename) + if err != nil { + return false, err + } + defer f.Close() + + return readerContainsAny(f, subslice), nil +} + +func (a Afero) FileContainsAnyBytes(filename string, subslices [][]byte) (bool, error) { + return FileContainsAnyBytes(a.Fs, filename, subslices) +} + +// Check if a file contains any of the specified byte slices. +func FileContainsAnyBytes(fs Fs, filename string, subslices [][]byte) (bool, error) { + f, err := fs.Open(filename) + if err != nil { + return false, err + } + defer f.Close() + + return readerContainsAny(f, subslices...), nil +} + +// readerContains reports whether any of the subslices is within r. +func readerContainsAny(r io.Reader, subslices ...[]byte) bool { + + if r == nil || len(subslices) == 0 { + return false + } + + largestSlice := 0 + + for _, sl := range subslices { + if len(sl) > largestSlice { + largestSlice = len(sl) + } + } + + if largestSlice == 0 { + return false + } + + bufflen := largestSlice * 4 + halflen := bufflen / 2 + buff := make([]byte, bufflen) + var err error + var n, i int + + for { + i++ + if i == 1 { + n, err = io.ReadAtLeast(r, buff[:halflen], halflen) + } else { + if i != 2 { + // shift left to catch overlapping matches + copy(buff[:], buff[halflen:]) + } + n, err = io.ReadAtLeast(r, buff[halflen:], halflen) + } + + if n > 0 { + for _, sl := range subslices { + if bytes.Contains(buff, sl) { + return true + } + } + } + + if err != nil { + break + } + } + return false +} + +func (a Afero) DirExists(path string) (bool, error) { + return DirExists(a.Fs, path) +} + +// DirExists checks if a path exists and is a directory. +func DirExists(fs Fs, path string) (bool, error) { + fi, err := fs.Stat(path) + if err == nil && fi.IsDir() { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func (a Afero) IsDir(path string) (bool, error) { + return IsDir(a.Fs, path) +} + +// IsDir checks if a given path is a directory. +func IsDir(fs Fs, path string) (bool, error) { + fi, err := fs.Stat(path) + if err != nil { + return false, err + } + return fi.IsDir(), nil +} + +func (a Afero) IsEmpty(path string) (bool, error) { + return IsEmpty(a.Fs, path) +} + +// IsEmpty checks if a given file or directory is empty. +func IsEmpty(fs Fs, path string) (bool, error) { + if b, _ := Exists(fs, path); !b { + return false, fmt.Errorf("%q path does not exist", path) + } + fi, err := fs.Stat(path) + if err != nil { + return false, err + } + if fi.IsDir() { + f, err := fs.Open(path) + if err != nil { + return false, err + } + defer f.Close() + list, err := f.Readdir(-1) + return len(list) == 0, nil + } + return fi.Size() == 0, nil +} + +func (a Afero) Exists(path string) (bool, error) { + return Exists(a.Fs, path) +} + +// Check if a file or directory exists. +func Exists(fs Fs, path string) (bool, error) { + _, err := fs.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func FullBaseFsPath(basePathFs *BasePathFs, relativePath string) string { + combinedPath := filepath.Join(basePathFs.path, relativePath) + if parent, ok := basePathFs.source.(*BasePathFs); ok { + return FullBaseFsPath(parent, combinedPath) + } + + return combinedPath +} diff --git a/vendor/github.com/spf13/cast/.gitignore b/vendor/github.com/spf13/cast/.gitignore new file mode 100644 index 000000000..53053a8ac --- /dev/null +++ b/vendor/github.com/spf13/cast/.gitignore @@ -0,0 +1,25 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test + +*.bench diff --git a/vendor/github.com/spf13/cast/.travis.yml b/vendor/github.com/spf13/cast/.travis.yml new file mode 100644 index 000000000..6420d1c27 --- /dev/null +++ b/vendor/github.com/spf13/cast/.travis.yml @@ -0,0 +1,15 @@ +language: go +env: + - GO111MODULE=on +sudo: required +go: + - "1.11.x" + - tip +os: + - linux +matrix: + allow_failures: + - go: tip + fast_finish: true +script: + - make check diff --git a/vendor/github.com/spf13/cast/LICENSE b/vendor/github.com/spf13/cast/LICENSE new file mode 100644 index 000000000..4527efb9c --- /dev/null +++ b/vendor/github.com/spf13/cast/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Steve Francia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/spf13/cast/Makefile b/vendor/github.com/spf13/cast/Makefile new file mode 100644 index 000000000..7ccf8930b --- /dev/null +++ b/vendor/github.com/spf13/cast/Makefile @@ -0,0 +1,38 @@ +# A Self-Documenting Makefile: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html + +.PHONY: check fmt lint test test-race vet test-cover-html help +.DEFAULT_GOAL := help + +check: test-race fmt vet lint ## Run tests and linters + +test: ## Run tests + go test ./... + +test-race: ## Run tests with race detector + go test -race ./... + +fmt: ## Run gofmt linter + @for d in `go list` ; do \ + if [ "`gofmt -l -s $$GOPATH/src/$$d | tee /dev/stderr`" ]; then \ + echo "^ improperly formatted go files" && echo && exit 1; \ + fi \ + done + +lint: ## Run golint linter + @for d in `go list` ; do \ + if [ "`golint $$d | tee /dev/stderr`" ]; then \ + echo "^ golint errors!" && echo && exit 1; \ + fi \ + done + +vet: ## Run go vet linter + @if [ "`go vet | tee /dev/stderr`" ]; then \ + echo "^ go vet errors!" && echo && exit 1; \ + fi + +test-cover-html: ## Generate test coverage report + go test -coverprofile=coverage.out -covermode=count + go tool cover -func=coverage.out + +help: + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/vendor/github.com/spf13/cast/README.md b/vendor/github.com/spf13/cast/README.md new file mode 100644 index 000000000..e6939397d --- /dev/null +++ b/vendor/github.com/spf13/cast/README.md @@ -0,0 +1,75 @@ +cast +==== +[![GoDoc](https://godoc.org/github.com/spf13/cast?status.svg)](https://godoc.org/github.com/spf13/cast) +[![Build Status](https://api.travis-ci.org/spf13/cast.svg?branch=master)](https://travis-ci.org/spf13/cast) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast) + +Easy and safe casting from one type to another in Go + +Don’t Panic! ... Cast + +## What is Cast? + +Cast is a library to convert between different go types in a consistent and easy way. + +Cast provides simple functions to easily convert a number to a string, an +interface into a bool, etc. Cast does this intelligently when an obvious +conversion is possible. It doesn’t make any attempts to guess what you meant, +for example you can only convert a string to an int when it is a string +representation of an int such as “8”. Cast was developed for use in +[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON +for meta data. + +## Why use Cast? + +When working with dynamic data in Go you often need to cast or convert the data +from one type into another. Cast goes beyond just using type assertion (though +it uses that when possible) to provide a very straightforward and convenient +library. + +If you are working with interfaces to handle things like dynamic content +you’ll need an easy way to convert an interface into a given type. This +is the library for you. + +If you are taking in data from YAML, TOML or JSON or other formats which lack +full types, then Cast is the library for you. + +## Usage + +Cast provides a handful of To_____ methods. These methods will always return +the desired type. **If input is provided that will not convert to that type, the +0 or nil value for that type will be returned**. + +Cast also provides identical methods To_____E. These return the same result as +the To_____ methods, plus an additional error which tells you if it successfully +converted. Using these methods you can tell the difference between when the +input matched the zero value or when the conversion failed and the zero value +was returned. + +The following examples are merely a sample of what is available. Please review +the code for a complete set. + +### Example ‘ToString’: + + cast.ToString("mayonegg") // "mayonegg" + cast.ToString(8) // "8" + cast.ToString(8.31) // "8.31" + cast.ToString([]byte("one time")) // "one time" + cast.ToString(nil) // "" + + var foo interface{} = "one more time" + cast.ToString(foo) // "one more time" + + +### Example ‘ToInt’: + + cast.ToInt(8) // 8 + cast.ToInt(8.31) // 8 + cast.ToInt("8") // 8 + cast.ToInt(true) // 1 + cast.ToInt(false) // 0 + + var eight interface{} = 8 + cast.ToInt(eight) // 8 + cast.ToInt(nil) // 0 + diff --git a/vendor/github.com/spf13/cast/cast.go b/vendor/github.com/spf13/cast/cast.go new file mode 100644 index 000000000..9fba638d4 --- /dev/null +++ b/vendor/github.com/spf13/cast/cast.go @@ -0,0 +1,171 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// Package cast provides easy and safe casting in Go. +package cast + +import "time" + +// ToBool casts an interface to a bool type. +func ToBool(i interface{}) bool { + v, _ := ToBoolE(i) + return v +} + +// ToTime casts an interface to a time.Time type. +func ToTime(i interface{}) time.Time { + v, _ := ToTimeE(i) + return v +} + +// ToDuration casts an interface to a time.Duration type. +func ToDuration(i interface{}) time.Duration { + v, _ := ToDurationE(i) + return v +} + +// ToFloat64 casts an interface to a float64 type. +func ToFloat64(i interface{}) float64 { + v, _ := ToFloat64E(i) + return v +} + +// ToFloat32 casts an interface to a float32 type. +func ToFloat32(i interface{}) float32 { + v, _ := ToFloat32E(i) + return v +} + +// ToInt64 casts an interface to an int64 type. +func ToInt64(i interface{}) int64 { + v, _ := ToInt64E(i) + return v +} + +// ToInt32 casts an interface to an int32 type. +func ToInt32(i interface{}) int32 { + v, _ := ToInt32E(i) + return v +} + +// ToInt16 casts an interface to an int16 type. +func ToInt16(i interface{}) int16 { + v, _ := ToInt16E(i) + return v +} + +// ToInt8 casts an interface to an int8 type. +func ToInt8(i interface{}) int8 { + v, _ := ToInt8E(i) + return v +} + +// ToInt casts an interface to an int type. +func ToInt(i interface{}) int { + v, _ := ToIntE(i) + return v +} + +// ToUint casts an interface to a uint type. +func ToUint(i interface{}) uint { + v, _ := ToUintE(i) + return v +} + +// ToUint64 casts an interface to a uint64 type. +func ToUint64(i interface{}) uint64 { + v, _ := ToUint64E(i) + return v +} + +// ToUint32 casts an interface to a uint32 type. +func ToUint32(i interface{}) uint32 { + v, _ := ToUint32E(i) + return v +} + +// ToUint16 casts an interface to a uint16 type. +func ToUint16(i interface{}) uint16 { + v, _ := ToUint16E(i) + return v +} + +// ToUint8 casts an interface to a uint8 type. +func ToUint8(i interface{}) uint8 { + v, _ := ToUint8E(i) + return v +} + +// ToString casts an interface to a string type. +func ToString(i interface{}) string { + v, _ := ToStringE(i) + return v +} + +// ToStringMapString casts an interface to a map[string]string type. +func ToStringMapString(i interface{}) map[string]string { + v, _ := ToStringMapStringE(i) + return v +} + +// ToStringMapStringSlice casts an interface to a map[string][]string type. +func ToStringMapStringSlice(i interface{}) map[string][]string { + v, _ := ToStringMapStringSliceE(i) + return v +} + +// ToStringMapBool casts an interface to a map[string]bool type. +func ToStringMapBool(i interface{}) map[string]bool { + v, _ := ToStringMapBoolE(i) + return v +} + +// ToStringMapInt casts an interface to a map[string]int type. +func ToStringMapInt(i interface{}) map[string]int { + v, _ := ToStringMapIntE(i) + return v +} + +// ToStringMapInt64 casts an interface to a map[string]int64 type. +func ToStringMapInt64(i interface{}) map[string]int64 { + v, _ := ToStringMapInt64E(i) + return v +} + +// ToStringMap casts an interface to a map[string]interface{} type. +func ToStringMap(i interface{}) map[string]interface{} { + v, _ := ToStringMapE(i) + return v +} + +// ToSlice casts an interface to a []interface{} type. +func ToSlice(i interface{}) []interface{} { + v, _ := ToSliceE(i) + return v +} + +// ToBoolSlice casts an interface to a []bool type. +func ToBoolSlice(i interface{}) []bool { + v, _ := ToBoolSliceE(i) + return v +} + +// ToStringSlice casts an interface to a []string type. +func ToStringSlice(i interface{}) []string { + v, _ := ToStringSliceE(i) + return v +} + +// ToIntSlice casts an interface to a []int type. +func ToIntSlice(i interface{}) []int { + v, _ := ToIntSliceE(i) + return v +} + +// ToDurationSlice casts an interface to a []time.Duration type. +func ToDurationSlice(i interface{}) []time.Duration { + v, _ := ToDurationSliceE(i) + return v +} diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go new file mode 100644 index 000000000..a4859fb0a --- /dev/null +++ b/vendor/github.com/spf13/cast/caste.go @@ -0,0 +1,1249 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package cast + +import ( + "encoding/json" + "errors" + "fmt" + "html/template" + "reflect" + "strconv" + "strings" + "time" +) + +var errNegativeNotAllowed = errors.New("unable to cast negative value") + +// ToTimeE casts an interface to a time.Time type. +func ToTimeE(i interface{}) (tim time.Time, err error) { + i = indirect(i) + + switch v := i.(type) { + case time.Time: + return v, nil + case string: + return StringToDate(v) + case int: + return time.Unix(int64(v), 0), nil + case int64: + return time.Unix(v, 0), nil + case int32: + return time.Unix(int64(v), 0), nil + case uint: + return time.Unix(int64(v), 0), nil + case uint64: + return time.Unix(int64(v), 0), nil + case uint32: + return time.Unix(int64(v), 0), nil + default: + return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i) + } +} + +// ToDurationE casts an interface to a time.Duration type. +func ToDurationE(i interface{}) (d time.Duration, err error) { + i = indirect(i) + + switch s := i.(type) { + case time.Duration: + return s, nil + case int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8: + d = time.Duration(ToInt64(s)) + return + case float32, float64: + d = time.Duration(ToFloat64(s)) + return + case string: + if strings.ContainsAny(s, "nsuµmh") { + d, err = time.ParseDuration(s) + } else { + d, err = time.ParseDuration(s + "ns") + } + return + default: + err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i) + return + } +} + +// ToBoolE casts an interface to a bool type. +func ToBoolE(i interface{}) (bool, error) { + i = indirect(i) + + switch b := i.(type) { + case bool: + return b, nil + case nil: + return false, nil + case int: + if i.(int) != 0 { + return true, nil + } + return false, nil + case string: + return strconv.ParseBool(i.(string)) + default: + return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i) + } +} + +// ToFloat64E casts an interface to a float64 type. +func ToFloat64E(i interface{}) (float64, error) { + i = indirect(i) + + switch s := i.(type) { + case float64: + return s, nil + case float32: + return float64(s), nil + case int: + return float64(s), nil + case int64: + return float64(s), nil + case int32: + return float64(s), nil + case int16: + return float64(s), nil + case int8: + return float64(s), nil + case uint: + return float64(s), nil + case uint64: + return float64(s), nil + case uint32: + return float64(s), nil + case uint16: + return float64(s), nil + case uint8: + return float64(s), nil + case string: + v, err := strconv.ParseFloat(s, 64) + if err == nil { + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + } +} + +// ToFloat32E casts an interface to a float32 type. +func ToFloat32E(i interface{}) (float32, error) { + i = indirect(i) + + switch s := i.(type) { + case float64: + return float32(s), nil + case float32: + return s, nil + case int: + return float32(s), nil + case int64: + return float32(s), nil + case int32: + return float32(s), nil + case int16: + return float32(s), nil + case int8: + return float32(s), nil + case uint: + return float32(s), nil + case uint64: + return float32(s), nil + case uint32: + return float32(s), nil + case uint16: + return float32(s), nil + case uint8: + return float32(s), nil + case string: + v, err := strconv.ParseFloat(s, 32) + if err == nil { + return float32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + } +} + +// ToInt64E casts an interface to an int64 type. +func ToInt64E(i interface{}) (int64, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return int64(s), nil + case int64: + return s, nil + case int32: + return int64(s), nil + case int16: + return int64(s), nil + case int8: + return int64(s), nil + case uint: + return int64(s), nil + case uint64: + return int64(s), nil + case uint32: + return int64(s), nil + case uint16: + return int64(s), nil + case uint8: + return int64(s), nil + case float64: + return int64(s), nil + case float32: + return int64(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + } +} + +// ToInt32E casts an interface to an int32 type. +func ToInt32E(i interface{}) (int32, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return int32(s), nil + case int64: + return int32(s), nil + case int32: + return s, nil + case int16: + return int32(s), nil + case int8: + return int32(s), nil + case uint: + return int32(s), nil + case uint64: + return int32(s), nil + case uint32: + return int32(s), nil + case uint16: + return int32(s), nil + case uint8: + return int32(s), nil + case float64: + return int32(s), nil + case float32: + return int32(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) + } +} + +// ToInt16E casts an interface to an int16 type. +func ToInt16E(i interface{}) (int16, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return int16(s), nil + case int64: + return int16(s), nil + case int32: + return int16(s), nil + case int16: + return s, nil + case int8: + return int16(s), nil + case uint: + return int16(s), nil + case uint64: + return int16(s), nil + case uint32: + return int16(s), nil + case uint16: + return int16(s), nil + case uint8: + return int16(s), nil + case float64: + return int16(s), nil + case float32: + return int16(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int16(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + } +} + +// ToInt8E casts an interface to an int8 type. +func ToInt8E(i interface{}) (int8, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return int8(s), nil + case int64: + return int8(s), nil + case int32: + return int8(s), nil + case int16: + return int8(s), nil + case int8: + return s, nil + case uint: + return int8(s), nil + case uint64: + return int8(s), nil + case uint32: + return int8(s), nil + case uint16: + return int8(s), nil + case uint8: + return int8(s), nil + case float64: + return int8(s), nil + case float32: + return int8(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int8(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + } +} + +// ToIntE casts an interface to an int type. +func ToIntE(i interface{}) (int, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return s, nil + case int64: + return int(s), nil + case int32: + return int(s), nil + case int16: + return int(s), nil + case int8: + return int(s), nil + case uint: + return int(s), nil + case uint64: + return int(s), nil + case uint32: + return int(s), nil + case uint16: + return int(s), nil + case uint8: + return int(s), nil + case float64: + return int(s), nil + case float32: + return int(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) + } +} + +// ToUintE casts an interface to a uint type. +func ToUintE(i interface{}) (uint, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 0) + if err == nil { + return uint(v), nil + } + return 0, fmt.Errorf("unable to cast %#v to uint: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case uint: + return s, nil + case uint64: + return uint(s), nil + case uint32: + return uint(s), nil + case uint16: + return uint(s), nil + case uint8: + return uint(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) + } +} + +// ToUint64E casts an interface to a uint64 type. +func ToUint64E(i interface{}) (uint64, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 64) + if err == nil { + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v to uint64: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case uint: + return uint64(s), nil + case uint64: + return s, nil + case uint32: + return uint64(s), nil + case uint16: + return uint64(s), nil + case uint8: + return uint64(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) + } +} + +// ToUint32E casts an interface to a uint32 type. +func ToUint32E(i interface{}) (uint32, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 32) + if err == nil { + return uint32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v to uint32: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case uint: + return uint32(s), nil + case uint64: + return uint32(s), nil + case uint32: + return s, nil + case uint16: + return uint32(s), nil + case uint8: + return uint32(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) + } +} + +// ToUint16E casts an interface to a uint16 type. +func ToUint16E(i interface{}) (uint16, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 16) + if err == nil { + return uint16(v), nil + } + return 0, fmt.Errorf("unable to cast %#v to uint16: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case uint: + return uint16(s), nil + case uint64: + return uint16(s), nil + case uint32: + return uint16(s), nil + case uint16: + return s, nil + case uint8: + return uint16(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) + } +} + +// ToUint8E casts an interface to a uint type. +func ToUint8E(i interface{}) (uint8, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 8) + if err == nil { + return uint8(v), nil + } + return 0, fmt.Errorf("unable to cast %#v to uint8: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case uint: + return uint8(s), nil + case uint64: + return uint8(s), nil + case uint32: + return uint8(s), nil + case uint16: + return uint8(s), nil + case uint8: + return s, nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i) + } +} + +// From html/template/content.go +// Copyright 2011 The Go Authors. All rights reserved. +// indirect returns the value, after dereferencing as many times +// as necessary to reach the base type (or nil). +func indirect(a interface{}) interface{} { + if a == nil { + return nil + } + if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr { + // Avoid creating a reflect.Value if it's not a pointer. + return a + } + v := reflect.ValueOf(a) + for v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + return v.Interface() +} + +// From html/template/content.go +// Copyright 2011 The Go Authors. All rights reserved. +// indirectToStringerOrError returns the value, after dereferencing as many times +// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer +// or error, +func indirectToStringerOrError(a interface{}) interface{} { + if a == nil { + return nil + } + + var errorType = reflect.TypeOf((*error)(nil)).Elem() + var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() + + v := reflect.ValueOf(a) + for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + return v.Interface() +} + +// ToStringE casts an interface to a string type. +func ToStringE(i interface{}) (string, error) { + i = indirectToStringerOrError(i) + + switch s := i.(type) { + case string: + return s, nil + case bool: + return strconv.FormatBool(s), nil + case float64: + return strconv.FormatFloat(s, 'f', -1, 64), nil + case float32: + return strconv.FormatFloat(float64(s), 'f', -1, 32), nil + case int: + return strconv.Itoa(s), nil + case int64: + return strconv.FormatInt(s, 10), nil + case int32: + return strconv.Itoa(int(s)), nil + case int16: + return strconv.FormatInt(int64(s), 10), nil + case int8: + return strconv.FormatInt(int64(s), 10), nil + case uint: + return strconv.FormatInt(int64(s), 10), nil + case uint64: + return strconv.FormatInt(int64(s), 10), nil + case uint32: + return strconv.FormatInt(int64(s), 10), nil + case uint16: + return strconv.FormatInt(int64(s), 10), nil + case uint8: + return strconv.FormatInt(int64(s), 10), nil + case []byte: + return string(s), nil + case template.HTML: + return string(s), nil + case template.URL: + return string(s), nil + case template.JS: + return string(s), nil + case template.CSS: + return string(s), nil + case template.HTMLAttr: + return string(s), nil + case nil: + return "", nil + case fmt.Stringer: + return s.String(), nil + case error: + return s.Error(), nil + default: + return "", fmt.Errorf("unable to cast %#v of type %T to string", i, i) + } +} + +// ToStringMapStringE casts an interface to a map[string]string type. +func ToStringMapStringE(i interface{}) (map[string]string, error) { + var m = map[string]string{} + + switch v := i.(type) { + case map[string]string: + return v, nil + case map[string]interface{}: + for k, val := range v { + m[ToString(k)] = ToString(val) + } + return m, nil + case map[interface{}]string: + for k, val := range v { + m[ToString(k)] = ToString(val) + } + return m, nil + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToString(val) + } + return m, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + default: + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]string", i, i) + } +} + +// ToStringMapStringSliceE casts an interface to a map[string][]string type. +func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { + var m = map[string][]string{} + + switch v := i.(type) { + case map[string][]string: + return v, nil + case map[string][]interface{}: + for k, val := range v { + m[ToString(k)] = ToStringSlice(val) + } + return m, nil + case map[string]string: + for k, val := range v { + m[ToString(k)] = []string{val} + } + case map[string]interface{}: + for k, val := range v { + switch vt := val.(type) { + case []interface{}: + m[ToString(k)] = ToStringSlice(vt) + case []string: + m[ToString(k)] = vt + default: + m[ToString(k)] = []string{ToString(val)} + } + } + return m, nil + case map[interface{}][]string: + for k, val := range v { + m[ToString(k)] = ToStringSlice(val) + } + return m, nil + case map[interface{}]string: + for k, val := range v { + m[ToString(k)] = ToStringSlice(val) + } + return m, nil + case map[interface{}][]interface{}: + for k, val := range v { + m[ToString(k)] = ToStringSlice(val) + } + return m, nil + case map[interface{}]interface{}: + for k, val := range v { + key, err := ToStringE(k) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) + } + value, err := ToStringSliceE(val) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) + } + m[key] = value + } + case string: + err := jsonStringToObject(v, &m) + return m, err + default: + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) + } + return m, nil +} + +// ToStringMapBoolE casts an interface to a map[string]bool type. +func ToStringMapBoolE(i interface{}) (map[string]bool, error) { + var m = map[string]bool{} + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToBool(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[ToString(k)] = ToBool(val) + } + return m, nil + case map[string]bool: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + default: + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]bool", i, i) + } +} + +// ToStringMapE casts an interface to a map[string]interface{} type. +func ToStringMapE(i interface{}) (map[string]interface{}, error) { + var m = map[string]interface{}{} + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = val + } + return m, nil + case map[string]interface{}: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + default: + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]interface{}", i, i) + } +} + +// ToStringMapIntE casts an interface to a map[string]int{} type. +func ToStringMapIntE(i interface{}) (map[string]int, error) { + var m = map[string]int{} + if i == nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToInt(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[k] = ToInt(val) + } + return m, nil + case map[string]int: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + } + + if reflect.TypeOf(i).Kind() != reflect.Map { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + + mVal := reflect.ValueOf(m) + v := reflect.ValueOf(i) + for _, keyVal := range v.MapKeys() { + val, err := ToIntE(v.MapIndex(keyVal).Interface()) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + mVal.SetMapIndex(keyVal, reflect.ValueOf(val)) + } + return m, nil +} + +// ToStringMapInt64E casts an interface to a map[string]int64{} type. +func ToStringMapInt64E(i interface{}) (map[string]int64, error) { + var m = map[string]int64{} + if i == nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToInt64(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[k] = ToInt64(val) + } + return m, nil + case map[string]int64: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + } + + if reflect.TypeOf(i).Kind() != reflect.Map { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + mVal := reflect.ValueOf(m) + v := reflect.ValueOf(i) + for _, keyVal := range v.MapKeys() { + val, err := ToInt64E(v.MapIndex(keyVal).Interface()) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + mVal.SetMapIndex(keyVal, reflect.ValueOf(val)) + } + return m, nil +} + +// ToSliceE casts an interface to a []interface{} type. +func ToSliceE(i interface{}) ([]interface{}, error) { + var s []interface{} + + switch v := i.(type) { + case []interface{}: + return append(s, v...), nil + case []map[string]interface{}: + for _, u := range v { + s = append(s, u) + } + return s, nil + default: + return s, fmt.Errorf("unable to cast %#v of type %T to []interface{}", i, i) + } +} + +// ToBoolSliceE casts an interface to a []bool type. +func ToBoolSliceE(i interface{}) ([]bool, error) { + if i == nil { + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } + + switch v := i.(type) { + case []bool: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]bool, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToBoolE(s.Index(j).Interface()) + if err != nil { + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } + a[j] = val + } + return a, nil + default: + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } +} + +// ToStringSliceE casts an interface to a []string type. +func ToStringSliceE(i interface{}) ([]string, error) { + var a []string + + switch v := i.(type) { + case []interface{}: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []string: + return v, nil + case string: + return strings.Fields(v), nil + case interface{}: + str, err := ToStringE(v) + if err != nil { + return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) + } + return []string{str}, nil + default: + return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) + } +} + +// ToIntSliceE casts an interface to a []int type. +func ToIntSliceE(i interface{}) ([]int, error) { + if i == nil { + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) + } + + switch v := i.(type) { + case []int: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]int, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToIntE(s.Index(j).Interface()) + if err != nil { + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) + } + a[j] = val + } + return a, nil + default: + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) + } +} + +// ToDurationSliceE casts an interface to a []time.Duration type. +func ToDurationSliceE(i interface{}) ([]time.Duration, error) { + if i == nil { + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } + + switch v := i.(type) { + case []time.Duration: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]time.Duration, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToDurationE(s.Index(j).Interface()) + if err != nil { + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } + a[j] = val + } + return a, nil + default: + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } +} + +// StringToDate attempts to parse a string into a time.Time type using a +// predefined list of formats. If no suitable format is found, an error is +// returned. +func StringToDate(s string) (time.Time, error) { + return parseDateWith(s, []string{ + time.RFC3339, + "2006-01-02T15:04:05", // iso8601 without timezone + time.RFC1123Z, + time.RFC1123, + time.RFC822Z, + time.RFC822, + time.RFC850, + time.ANSIC, + time.UnixDate, + time.RubyDate, + "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String() + "2006-01-02", + "02 Jan 2006", + "2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon + "2006-01-02 15:04:05 -07:00", + "2006-01-02 15:04:05 -0700", + "2006-01-02 15:04:05Z07:00", // RFC3339 without T + "2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon + "2006-01-02 15:04:05", + time.Kitchen, + time.Stamp, + time.StampMilli, + time.StampMicro, + time.StampNano, + }) +} + +func parseDateWith(s string, dates []string) (d time.Time, e error) { + for _, dateType := range dates { + if d, e = time.Parse(dateType, s); e == nil { + return + } + } + return d, fmt.Errorf("unable to parse date: %s", s) +} + +// jsonStringToObject attempts to unmarshall a string as JSON into +// the object passed as pointer. +func jsonStringToObject(s string, v interface{}) error { + data := []byte(s) + return json.Unmarshal(data, v) +} diff --git a/vendor/github.com/spf13/cast/go.mod b/vendor/github.com/spf13/cast/go.mod new file mode 100644 index 000000000..c1c0232dd --- /dev/null +++ b/vendor/github.com/spf13/cast/go.mod @@ -0,0 +1,7 @@ +module github.com/spf13/cast + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.2.2 +) diff --git a/vendor/github.com/spf13/cast/go.sum b/vendor/github.com/spf13/cast/go.sum new file mode 100644 index 000000000..e03ee77d9 --- /dev/null +++ b/vendor/github.com/spf13/cast/go.sum @@ -0,0 +1,6 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/vendor/github.com/spf13/cobra/.gitignore b/vendor/github.com/spf13/cobra/.gitignore new file mode 100644 index 000000000..3b053c59e --- /dev/null +++ b/vendor/github.com/spf13/cobra/.gitignore @@ -0,0 +1,38 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +# Vim files https://github.com/github/gitignore/blob/master/Global/Vim.gitignore +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags + +*.exe + +cobra.test + +.idea/* diff --git a/vendor/github.com/spf13/cobra/.mailmap b/vendor/github.com/spf13/cobra/.mailmap new file mode 100644 index 000000000..94ec53068 --- /dev/null +++ b/vendor/github.com/spf13/cobra/.mailmap @@ -0,0 +1,3 @@ +Steve Francia +Bjørn Erik Pedersen +Fabiano Franz diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml new file mode 100644 index 000000000..38b85f499 --- /dev/null +++ b/vendor/github.com/spf13/cobra/.travis.yml @@ -0,0 +1,31 @@ +language: go + +stages: + - diff + - test + +go: + - 1.10.x + - 1.11.x + - 1.12.x + - tip + +matrix: + allow_failures: + - go: tip + include: + - stage: diff + go: 1.12.x + script: diff -u <(echo -n) <(gofmt -d -s .) + +before_install: + - mkdir -p bin + - curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.6.0/shellcheck + - chmod +x bin/shellcheck + - go get -u github.com/kyoh86/richgo +script: + - PATH=$PATH:$PWD/bin richgo test -v ./... + - go build + - if [ -z $NOVET ]; then + diff -u <(echo -n) <(go vet . 2>&1 | grep -vE 'ExampleCommand|bash_completions.*Fprint'); + fi diff --git a/vendor/github.com/spf13/cobra/LICENSE.txt b/vendor/github.com/spf13/cobra/LICENSE.txt new file mode 100644 index 000000000..298f0e266 --- /dev/null +++ b/vendor/github.com/spf13/cobra/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md new file mode 100644 index 000000000..60c5a425b --- /dev/null +++ b/vendor/github.com/spf13/cobra/README.md @@ -0,0 +1,741 @@ +![cobra logo](https://cloud.githubusercontent.com/assets/173412/10886352/ad566232-814f-11e5-9cd0-aa101788c117.png) + +Cobra is both a library for creating powerful modern CLI applications as well as a program to generate applications and command files. + +Many of the most widely used Go projects are built using Cobra, such as: +[Kubernetes](http://kubernetes.io/), +[Hugo](http://gohugo.io), +[rkt](https://github.com/coreos/rkt), +[etcd](https://github.com/coreos/etcd), +[Moby (former Docker)](https://github.com/moby/moby), +[Docker (distribution)](https://github.com/docker/distribution), +[OpenShift](https://www.openshift.com/), +[Delve](https://github.com/derekparker/delve), +[GopherJS](http://www.gopherjs.org/), +[CockroachDB](http://www.cockroachlabs.com/), +[Bleve](http://www.blevesearch.com/), +[ProjectAtomic (enterprise)](http://www.projectatomic.io/), +[Giant Swarm's gsctl](https://github.com/giantswarm/gsctl), +[Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack), +[rclone](http://rclone.org/), +[nehm](https://github.com/bogem/nehm), +[Pouch](https://github.com/alibaba/pouch), +[Istio](https://istio.io), +[Prototool](https://github.com/uber/prototool), +[mattermost-server](https://github.com/mattermost/mattermost-server), +[Gardener](https://github.com/gardener/gardenctl), +etc. + +[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra) +[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra) +[![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra) + +# Table of Contents + +- [Overview](#overview) +- [Concepts](#concepts) + * [Commands](#commands) + * [Flags](#flags) +- [Installing](#installing) +- [Getting Started](#getting-started) + * [Using the Cobra Generator](#using-the-cobra-generator) + * [Using the Cobra Library](#using-the-cobra-library) + * [Working with Flags](#working-with-flags) + * [Positional and Custom Arguments](#positional-and-custom-arguments) + * [Example](#example) + * [Help Command](#help-command) + * [Usage Message](#usage-message) + * [PreRun and PostRun Hooks](#prerun-and-postrun-hooks) + * [Suggestions when "unknown command" happens](#suggestions-when-unknown-command-happens) + * [Generating documentation for your command](#generating-documentation-for-your-command) + * [Generating bash completions](#generating-bash-completions) + * [Generating zsh completions](#generating-zsh-completions) +- [Contributing](#contributing) +- [License](#license) + +# Overview + +Cobra is a library providing a simple interface to create powerful modern CLI +interfaces similar to git & go tools. + +Cobra is also an application that will generate your application scaffolding to rapidly +develop a Cobra-based application. + +Cobra provides: +* Easy subcommand-based CLIs: `app server`, `app fetch`, etc. +* Fully POSIX-compliant flags (including short & long versions) +* Nested subcommands +* Global, local and cascading flags +* Easy generation of applications & commands with `cobra init appname` & `cobra add cmdname` +* Intelligent suggestions (`app srver`... did you mean `app server`?) +* Automatic help generation for commands and flags +* Automatic help flag recognition of `-h`, `--help`, etc. +* Automatically generated bash autocomplete for your application +* Automatically generated man pages for your application +* Command aliases so you can change things without breaking them +* The flexibility to define your own help, usage, etc. +* Optional tight integration with [viper](http://github.com/spf13/viper) for 12-factor apps + +# Concepts + +Cobra is built on a structure of commands, arguments & flags. + +**Commands** represent actions, **Args** are things and **Flags** are modifiers for those actions. + +The best applications will read like sentences when used. Users will know how +to use the application because they will natively understand how to use it. + +The pattern to follow is +`APPNAME VERB NOUN --ADJECTIVE.` + or +`APPNAME COMMAND ARG --FLAG` + +A few good real world examples may better illustrate this point. + +In the following example, 'server' is a command, and 'port' is a flag: + + hugo server --port=1313 + +In this command we are telling Git to clone the url bare. + + git clone URL --bare + +## Commands + +Command is the central point of the application. Each interaction that +the application supports will be contained in a Command. A command can +have children commands and optionally run an action. + +In the example above, 'server' is the command. + +[More about cobra.Command](https://godoc.org/github.com/spf13/cobra#Command) + +## Flags + +A flag is a way to modify the behavior of a command. Cobra supports +fully POSIX-compliant flags as well as the Go [flag package](https://golang.org/pkg/flag/). +A Cobra command can define flags that persist through to children commands +and flags that are only available to that command. + +In the example above, 'port' is the flag. + +Flag functionality is provided by the [pflag +library](https://github.com/spf13/pflag), a fork of the flag standard library +which maintains the same interface while adding POSIX compliance. + +# Installing +Using Cobra is easy. First, use `go get` to install the latest version +of the library. This command will install the `cobra` generator executable +along with the library and its dependencies: + + go get -u github.com/spf13/cobra/cobra + +Next, include Cobra in your application: + +```go +import "github.com/spf13/cobra" +``` + +# Getting Started + +While you are welcome to provide your own organization, typically a Cobra-based +application will follow the following organizational structure: + +``` + ▾ appName/ + ▾ cmd/ + add.go + your.go + commands.go + here.go + main.go +``` + +In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra. + +```go +package main + +import ( + "{pathToYourApp}/cmd" +) + +func main() { + cmd.Execute() +} +``` + +## Using the Cobra Generator + +Cobra provides its own program that will create your application and add any +commands you want. It's the easiest way to incorporate Cobra into your application. + +[Here](https://github.com/spf13/cobra/blob/master/cobra/README.md) you can find more information about it. + +## Using the Cobra Library + +To manually implement Cobra you need to create a bare main.go file and a rootCmd file. +You will optionally provide additional commands as you see fit. + +### Create rootCmd + +Cobra doesn't require any special constructors. Simply create your commands. + +Ideally you place this in app/cmd/root.go: + +```go +var rootCmd = &cobra.Command{ + Use: "hugo", + Short: "Hugo is a very fast static site generator", + Long: `A Fast and Flexible Static Site Generator built with + love by spf13 and friends in Go. + Complete documentation is available at http://hugo.spf13.com`, + Run: func(cmd *cobra.Command, args []string) { + // Do Stuff Here + }, +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} +``` + +You will additionally define flags and handle configuration in your init() function. + +For example cmd/root.go: + +```go +import ( + "fmt" + "os" + + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func init() { + cobra.OnInitialize(initConfig) + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") + rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/") + rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") + rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") + rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") + viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) + viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase")) + viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")) + viper.SetDefault("author", "NAME HERE ") + viper.SetDefault("license", "apache") +} + +func initConfig() { + // Don't forget to read config either from cfgFile or from home directory! + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".cobra" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".cobra") + } + + if err := viper.ReadInConfig(); err != nil { + fmt.Println("Can't read config:", err) + os.Exit(1) + } +} +``` + +### Create your main.go + +With the root command you need to have your main function execute it. +Execute should be run on the root for clarity, though it can be called on any command. + +In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. + +```go +package main + +import ( + "{pathToYourApp}/cmd" +) + +func main() { + cmd.Execute() +} +``` + +### Create additional commands + +Additional commands can be defined and typically are each given their own file +inside of the cmd/ directory. + +If you wanted to create a version command you would create cmd/version.go and +populate it with the following: + +```go +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(versionCmd) +} + +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Print the version number of Hugo", + Long: `All software has versions. This is Hugo's`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") + }, +} +``` + +## Working with Flags + +Flags provide modifiers to control how the action command operates. + +### Assign flags to a command + +Since the flags are defined and used in different locations, we need to +define a variable outside with the correct scope to assign the flag to +work with. + +```go +var Verbose bool +var Source string +``` + +There are two different approaches to assign a flag. + +### Persistent Flags + +A flag can be 'persistent' meaning that this flag will be available to the +command it's assigned to as well as every command under that command. For +global flags, assign a flag as a persistent flag on the root. + +```go +rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") +``` + +### Local Flags + +A flag can also be assigned locally which will only apply to that specific command. + +```go +localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") +``` + +### Local Flag on Parent Commands + +By default Cobra only parses local flags on the target command, any local flags on +parent commands are ignored. By enabling `Command.TraverseChildren` Cobra will +parse local flags on each command before executing the target command. + +```go +command := cobra.Command{ + Use: "print [OPTIONS] [COMMANDS]", + TraverseChildren: true, +} +``` + +### Bind Flags with Config + +You can also bind your flags with [viper](https://github.com/spf13/viper): +```go +var author string + +func init() { + rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution") + viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) +} +``` + +In this example the persistent flag `author` is bound with `viper`. +**Note**, that the variable `author` will not be set to the value from config, +when the `--author` flag is not provided by user. + +More in [viper documentation](https://github.com/spf13/viper#working-with-flags). + +### Required flags + +Flags are optional by default. If instead you wish your command to report an error +when a flag has not been set, mark it as required: +```go +rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)") +rootCmd.MarkFlagRequired("region") +``` + +## Positional and Custom Arguments + +Validation of positional arguments can be specified using the `Args` field +of `Command`. + +The following validators are built in: + +- `NoArgs` - the command will report an error if there are any positional args. +- `ArbitraryArgs` - the command will accept any args. +- `OnlyValidArgs` - the command will report an error if there are any positional args that are not in the `ValidArgs` field of `Command`. +- `MinimumNArgs(int)` - the command will report an error if there are not at least N positional args. +- `MaximumNArgs(int)` - the command will report an error if there are more than N positional args. +- `ExactArgs(int)` - the command will report an error if there are not exactly N positional args. +- `ExactValidArgs(int)` - the command will report an error if there are not exactly N positional args OR if there are any positional args that are not in the `ValidArgs` field of `Command` +- `RangeArgs(min, max)` - the command will report an error if the number of args is not between the minimum and maximum number of expected args. + +An example of setting the custom validator: + +```go +var cmd = &cobra.Command{ + Short: "hello", + Args: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return errors.New("requires a color argument") + } + if myapp.IsValidColor(args[0]) { + return nil + } + return fmt.Errorf("invalid color specified: %s", args[0]) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hello, World!") + }, +} +``` + +## Example + +In the example below, we have defined three commands. Two are at the top level +and one (cmdTimes) is a child of one of the top commands. In this case the root +is not executable meaning that a subcommand is required. This is accomplished +by not providing a 'Run' for the 'rootCmd'. + +We have only defined one flag for a single command. + +More documentation about flags is available at https://github.com/spf13/pflag + +```go +package main + +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" +) + +func main() { + var echoTimes int + + var cmdPrint = &cobra.Command{ + Use: "print [string to print]", + Short: "Print anything to the screen", + Long: `print is for printing anything back to the screen. +For many years people have printed back to the screen.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Print: " + strings.Join(args, " ")) + }, + } + + var cmdEcho = &cobra.Command{ + Use: "echo [string to echo]", + Short: "Echo anything to the screen", + Long: `echo is for echoing anything back. +Echo works a lot like print, except it has a child command.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Print: " + strings.Join(args, " ")) + }, + } + + var cmdTimes = &cobra.Command{ + Use: "times [string to echo]", + Short: "Echo anything to the screen more times", + Long: `echo things multiple times back to the user by providing +a count and a string.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + for i := 0; i < echoTimes; i++ { + fmt.Println("Echo: " + strings.Join(args, " ")) + } + }, + } + + cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") + + var rootCmd = &cobra.Command{Use: "app"} + rootCmd.AddCommand(cmdPrint, cmdEcho) + cmdEcho.AddCommand(cmdTimes) + rootCmd.Execute() +} +``` + +For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/). + +## Help Command + +Cobra automatically adds a help command to your application when you have subcommands. +This will be called when a user runs 'app help'. Additionally, help will also +support all other commands as input. Say, for instance, you have a command called +'create' without any additional configuration; Cobra will work when 'app help +create' is called. Every command will automatically have the '--help' flag added. + +### Example + +The following output is automatically generated by Cobra. Nothing beyond the +command and flag definitions are needed. + + $ cobra help + + Cobra is a CLI library for Go that empowers applications. + This application is a tool to generate the needed files + to quickly create a Cobra application. + + Usage: + cobra [command] + + Available Commands: + add Add a command to a Cobra Application + help Help about any command + init Initialize a Cobra Application + + Flags: + -a, --author string author name for copyright attribution (default "YOUR NAME") + --config string config file (default is $HOME/.cobra.yaml) + -h, --help help for cobra + -l, --license string name of license for the project + --viper use Viper for configuration (default true) + + Use "cobra [command] --help" for more information about a command. + + +Help is just a command like any other. There is no special logic or behavior +around it. In fact, you can provide your own if you want. + +### Defining your own help + +You can provide your own Help command or your own template for the default command to use +with following functions: + +```go +cmd.SetHelpCommand(cmd *Command) +cmd.SetHelpFunc(f func(*Command, []string)) +cmd.SetHelpTemplate(s string) +``` + +The latter two will also apply to any children commands. + +## Usage Message + +When the user provides an invalid flag or invalid command, Cobra responds by +showing the user the 'usage'. + +### Example +You may recognize this from the help above. That's because the default help +embeds the usage as part of its output. + + $ cobra --invalid + Error: unknown flag: --invalid + Usage: + cobra [command] + + Available Commands: + add Add a command to a Cobra Application + help Help about any command + init Initialize a Cobra Application + + Flags: + -a, --author string author name for copyright attribution (default "YOUR NAME") + --config string config file (default is $HOME/.cobra.yaml) + -h, --help help for cobra + -l, --license string name of license for the project + --viper use Viper for configuration (default true) + + Use "cobra [command] --help" for more information about a command. + +### Defining your own usage +You can provide your own usage function or template for Cobra to use. +Like help, the function and template are overridable through public methods: + +```go +cmd.SetUsageFunc(f func(*Command) error) +cmd.SetUsageTemplate(s string) +``` + +## Version Flag + +Cobra adds a top-level '--version' flag if the Version field is set on the root command. +Running an application with the '--version' flag will print the version to stdout using +the version template. The template can be customized using the +`cmd.SetVersionTemplate(s string)` function. + +## PreRun and PostRun Hooks + +It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order: + +- `PersistentPreRun` +- `PreRun` +- `Run` +- `PostRun` +- `PersistentPostRun` + +An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`: + +```go +package main + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func main() { + + var rootCmd = &cobra.Command{ + Use: "root [sub]", + Short: "My root command", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) + }, + PreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd Run with args: %v\n", args) + }, + PostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) + }, + PersistentPostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) + }, + } + + var subCmd = &cobra.Command{ + Use: "sub [no options!]", + Short: "My subcommand", + PreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PreRun with args: %v\n", args) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd Run with args: %v\n", args) + }, + PostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PostRun with args: %v\n", args) + }, + PersistentPostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) + }, + } + + rootCmd.AddCommand(subCmd) + + rootCmd.SetArgs([]string{""}) + rootCmd.Execute() + fmt.Println() + rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) + rootCmd.Execute() +} +``` + +Output: +``` +Inside rootCmd PersistentPreRun with args: [] +Inside rootCmd PreRun with args: [] +Inside rootCmd Run with args: [] +Inside rootCmd PostRun with args: [] +Inside rootCmd PersistentPostRun with args: [] + +Inside rootCmd PersistentPreRun with args: [arg1 arg2] +Inside subCmd PreRun with args: [arg1 arg2] +Inside subCmd Run with args: [arg1 arg2] +Inside subCmd PostRun with args: [arg1 arg2] +Inside subCmd PersistentPostRun with args: [arg1 arg2] +``` + +## Suggestions when "unknown command" happens + +Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example: + +``` +$ hugo srever +Error: unknown command "srever" for "hugo" + +Did you mean this? + server + +Run 'hugo --help' for usage. +``` + +Suggestions are automatic based on every subcommand registered and use an implementation of [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion. + +If you need to disable suggestions or tweak the string distance in your command, use: + +```go +command.DisableSuggestions = true +``` + +or + +```go +command.SuggestionsMinimumDistance = 1 +``` + +You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but makes sense in your set of commands and for some which you don't want aliases. Example: + +``` +$ kubectl remove +Error: unknown command "remove" for "kubectl" + +Did you mean this? + delete + +Run 'kubectl help' for usage. +``` + +## Generating documentation for your command + +Cobra can generate documentation based on subcommands, flags, etc. in the following formats: + +- [Markdown](doc/md_docs.md) +- [ReStructured Text](doc/rest_docs.md) +- [Man Page](doc/man_docs.md) + +## Generating bash completions + +Cobra can generate a bash-completion file. If you add more information to your command, these completions can be amazingly powerful and flexible. Read more about it in [Bash Completions](bash_completions.md). + +## Generating zsh completions + +Cobra can generate zsh-completion file. Read more about it in +[Zsh Completions](zsh_completions.md). + +# Contributing + +1. Fork it +2. Download your fork to your PC (`git clone https://github.com/your_username/cobra && cd cobra`) +3. Create your feature branch (`git checkout -b my-new-feature`) +4. Make changes and add them (`git add .`) +5. Commit your changes (`git commit -m 'Add some feature'`) +6. Push to the branch (`git push origin my-new-feature`) +7. Create new pull request + +# License + +Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt) diff --git a/vendor/github.com/spf13/cobra/args.go b/vendor/github.com/spf13/cobra/args.go new file mode 100644 index 000000000..c4d820b85 --- /dev/null +++ b/vendor/github.com/spf13/cobra/args.go @@ -0,0 +1,101 @@ +package cobra + +import ( + "fmt" +) + +type PositionalArgs func(cmd *Command, args []string) error + +// Legacy arg validation has the following behaviour: +// - root commands with no subcommands can take arbitrary arguments +// - root commands with subcommands will do subcommand validity checking +// - subcommands will always accept arbitrary arguments +func legacyArgs(cmd *Command, args []string) error { + // no subcommand, always take args + if !cmd.HasSubCommands() { + return nil + } + + // root command with subcommands, do subcommand checking. + if !cmd.HasParent() && len(args) > 0 { + return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + return nil +} + +// NoArgs returns an error if any args are included. +func NoArgs(cmd *Command, args []string) error { + if len(args) > 0 { + return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath()) + } + return nil +} + +// OnlyValidArgs returns an error if any args are not in the list of ValidArgs. +func OnlyValidArgs(cmd *Command, args []string) error { + if len(cmd.ValidArgs) > 0 { + for _, v := range args { + if !stringInSlice(v, cmd.ValidArgs) { + return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + } + } + return nil +} + +// ArbitraryArgs never returns an error. +func ArbitraryArgs(cmd *Command, args []string) error { + return nil +} + +// MinimumNArgs returns an error if there is not at least N args. +func MinimumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < n { + return fmt.Errorf("requires at least %d arg(s), only received %d", n, len(args)) + } + return nil + } +} + +// MaximumNArgs returns an error if there are more than N args. +func MaximumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) > n { + return fmt.Errorf("accepts at most %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// ExactArgs returns an error if there are not exactly n args. +func ExactArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) != n { + return fmt.Errorf("accepts %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// ExactValidArgs returns an error if +// there are not exactly N positional args OR +// there are any positional args that are not in the `ValidArgs` field of `Command` +func ExactValidArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if err := ExactArgs(n)(cmd, args); err != nil { + return err + } + return OnlyValidArgs(cmd, args) + } +} + +// RangeArgs returns an error if the number of args is not within the expected range. +func RangeArgs(min int, max int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < min || len(args) > max { + return fmt.Errorf("accepts between %d and %d arg(s), received %d", min, max, len(args)) + } + return nil + } +} diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go new file mode 100644 index 000000000..57bb8e1b3 --- /dev/null +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -0,0 +1,547 @@ +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "sort" + "strings" + + "github.com/spf13/pflag" +) + +// Annotations for Bash completion. +const ( + BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions" + BashCompCustom = "cobra_annotation_bash_completion_custom" + BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag" + BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir" +) + +func writePreamble(buf *bytes.Buffer, name string) { + buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name)) + buf.WriteString(fmt.Sprintf(` +__%[1]s_debug() +{ + if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then + echo "$*" >> "${BASH_COMP_DEBUG_FILE}" + fi +} + +# Homebrew on Macs have version 1.3 of bash-completion which doesn't include +# _init_completion. This is a very minimal version of that function. +__%[1]s_init_completion() +{ + COMPREPLY=() + _get_comp_words_by_ref "$@" cur prev words cword +} + +__%[1]s_index_of_word() +{ + local w word=$1 + shift + index=0 + for w in "$@"; do + [[ $w = "$word" ]] && return + index=$((index+1)) + done + index=-1 +} + +__%[1]s_contains_word() +{ + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done + return 1 +} + +__%[1]s_handle_reply() +{ + __%[1]s_debug "${FUNCNAME[0]}" + case $cur in + -*) + if [[ $(type -t compopt) = "builtin" ]]; then + compopt -o nospace + fi + local allflags + if [ ${#must_have_one_flag[@]} -ne 0 ]; then + allflags=("${must_have_one_flag[@]}") + else + allflags=("${flags[*]} ${two_word_flags[*]}") + fi + COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") ) + if [[ $(type -t compopt) = "builtin" ]]; then + [[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace + fi + + # complete after --flag=abc + if [[ $cur == *=* ]]; then + if [[ $(type -t compopt) = "builtin" ]]; then + compopt +o nospace + fi + + local index flag + flag="${cur%%=*}" + __%[1]s_index_of_word "${flag}" "${flags_with_completion[@]}" + COMPREPLY=() + if [[ ${index} -ge 0 ]]; then + PREFIX="" + cur="${cur#*=}" + ${flags_completion[${index}]} + if [ -n "${ZSH_VERSION}" ]; then + # zsh completion needs --flag= prefix + eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )" + fi + fi + fi + return 0; + ;; + esac + + # check if we are handling a flag with special work handling + local index + __%[1]s_index_of_word "${prev}" "${flags_with_completion[@]}" + if [[ ${index} -ge 0 ]]; then + ${flags_completion[${index}]} + return + fi + + # we are parsing a flag and don't have a special handler, no completion + if [[ ${cur} != "${words[cword]}" ]]; then + return + fi + + local completions + completions=("${commands[@]}") + if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then + completions=("${must_have_one_noun[@]}") + fi + if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then + completions+=("${must_have_one_flag[@]}") + fi + COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") ) + + if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then + COMPREPLY=( $(compgen -W "${noun_aliases[*]}" -- "$cur") ) + fi + + if [[ ${#COMPREPLY[@]} -eq 0 ]]; then + if declare -F __%[1]s_custom_func >/dev/null; then + # try command name qualified custom func + __%[1]s_custom_func + else + # otherwise fall back to unqualified for compatibility + declare -F __custom_func >/dev/null && __custom_func + fi + fi + + # available in bash-completion >= 2, not always present on macOS + if declare -F __ltrim_colon_completions >/dev/null; then + __ltrim_colon_completions "$cur" + fi + + # If there is only 1 completion and it is a flag with an = it will be completed + # but we don't want a space after the = + if [[ "${#COMPREPLY[@]}" -eq "1" ]] && [[ $(type -t compopt) = "builtin" ]] && [[ "${COMPREPLY[0]}" == --*= ]]; then + compopt -o nospace + fi +} + +# The arguments should be in the form "ext1|ext2|extn" +__%[1]s_handle_filename_extension_flag() +{ + local ext="$1" + _filedir "@(${ext})" +} + +__%[1]s_handle_subdirs_in_dir_flag() +{ + local dir="$1" + pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 +} + +__%[1]s_handle_flag() +{ + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + + # if a command required a flag, and we found it, unset must_have_one_flag() + local flagname=${words[c]} + local flagvalue + # if the word contained an = + if [[ ${words[c]} == *"="* ]]; then + flagvalue=${flagname#*=} # take in as flagvalue after the = + flagname=${flagname%%=*} # strip everything after the = + flagname="${flagname}=" # but put the = back + fi + __%[1]s_debug "${FUNCNAME[0]}: looking for ${flagname}" + if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}"; then + must_have_one_flag=() + fi + + # if you set a flag which only applies to this command, don't show subcommands + if __%[1]s_contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then + commands=() + fi + + # keep flag value with flagname as flaghash + # flaghash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then + if [ -n "${flagvalue}" ] ; then + flaghash[${flagname}]=${flagvalue} + elif [ -n "${words[ $((c+1)) ]}" ] ; then + flaghash[${flagname}]=${words[ $((c+1)) ]} + else + flaghash[${flagname}]="true" # pad "true" for bool flag + fi + fi + + # skip the argument to a two word flag + if [[ ${words[c]} != *"="* ]] && __%[1]s_contains_word "${words[c]}" "${two_word_flags[@]}"; then + __%[1]s_debug "${FUNCNAME[0]}: found a flag ${words[c]}, skip the next argument" + c=$((c+1)) + # if we are looking for a flags value, don't show commands + if [[ $c -eq $cword ]]; then + commands=() + fi + fi + + c=$((c+1)) + +} + +__%[1]s_handle_noun() +{ + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + + if __%[1]s_contains_word "${words[c]}" "${must_have_one_noun[@]}"; then + must_have_one_noun=() + elif __%[1]s_contains_word "${words[c]}" "${noun_aliases[@]}"; then + must_have_one_noun=() + fi + + nouns+=("${words[c]}") + c=$((c+1)) +} + +__%[1]s_handle_command() +{ + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + + local next_command + if [[ -n ${last_command} ]]; then + next_command="_${last_command}_${words[c]//:/__}" + else + if [[ $c -eq 0 ]]; then + next_command="_%[1]s_root_command" + else + next_command="_${words[c]//:/__}" + fi + fi + c=$((c+1)) + __%[1]s_debug "${FUNCNAME[0]}: looking for ${next_command}" + declare -F "$next_command" >/dev/null && $next_command +} + +__%[1]s_handle_word() +{ + if [[ $c -ge $cword ]]; then + __%[1]s_handle_reply + return + fi + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + if [[ "${words[c]}" == -* ]]; then + __%[1]s_handle_flag + elif __%[1]s_contains_word "${words[c]}" "${commands[@]}"; then + __%[1]s_handle_command + elif [[ $c -eq 0 ]]; then + __%[1]s_handle_command + elif __%[1]s_contains_word "${words[c]}" "${command_aliases[@]}"; then + # aliashash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then + words[c]=${aliashash[${words[c]}]} + __%[1]s_handle_command + else + __%[1]s_handle_noun + fi + else + __%[1]s_handle_noun + fi + __%[1]s_handle_word +} + +`, name)) +} + +func writePostscript(buf *bytes.Buffer, name string) { + name = strings.Replace(name, ":", "__", -1) + buf.WriteString(fmt.Sprintf("__start_%s()\n", name)) + buf.WriteString(fmt.Sprintf(`{ + local cur prev words cword + declare -A flaghash 2>/dev/null || : + declare -A aliashash 2>/dev/null || : + if declare -F _init_completion >/dev/null 2>&1; then + _init_completion -s || return + else + __%[1]s_init_completion -n "=" || return + fi + + local c=0 + local flags=() + local two_word_flags=() + local local_nonpersistent_flags=() + local flags_with_completion=() + local flags_completion=() + local commands=("%[1]s") + local must_have_one_flag=() + local must_have_one_noun=() + local last_command + local nouns=() + + __%[1]s_handle_word +} + +`, name)) + buf.WriteString(fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then + complete -o default -F __start_%s %s +else + complete -o default -o nospace -F __start_%s %s +fi + +`, name, name, name, name)) + buf.WriteString("# ex: ts=4 sw=4 et filetype=sh\n") +} + +func writeCommands(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" commands=()\n") + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c == cmd.helpCommand { + continue + } + buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name())) + writeCmdAliases(buf, c) + } + buf.WriteString("\n") +} + +func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string, cmd *Command) { + for key, value := range annotations { + switch key { + case BashCompFilenameExt: + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + + var ext string + if len(value) > 0 { + ext = fmt.Sprintf("__%s_handle_filename_extension_flag ", cmd.Root().Name()) + strings.Join(value, "|") + } else { + ext = "_filedir" + } + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext)) + case BashCompCustom: + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + if len(value) > 0 { + handlers := strings.Join(value, "; ") + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", handlers)) + } else { + buf.WriteString(" flags_completion+=(:)\n") + } + case BashCompSubdirsInDir: + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + + var ext string + if len(value) == 1 { + ext = fmt.Sprintf("__%s_handle_subdirs_in_dir_flag ", cmd.Root().Name()) + value[0] + } else { + ext = "_filedir -d" + } + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext)) + } + } +} + +func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) { + name := flag.Shorthand + format := " " + if len(flag.NoOptDefVal) == 0 { + format += "two_word_" + } + format += "flags+=(\"-%s\")\n" + buf.WriteString(fmt.Sprintf(format, name)) + writeFlagHandler(buf, "-"+name, flag.Annotations, cmd) +} + +func writeFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) { + name := flag.Name + format := " flags+=(\"--%s" + if len(flag.NoOptDefVal) == 0 { + format += "=" + } + format += "\")\n" + buf.WriteString(fmt.Sprintf(format, name)) + if len(flag.NoOptDefVal) == 0 { + format = " two_word_flags+=(\"--%s\")\n" + buf.WriteString(fmt.Sprintf(format, name)) + } + writeFlagHandler(buf, "--"+name, flag.Annotations, cmd) +} + +func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) { + name := flag.Name + format := " local_nonpersistent_flags+=(\"--%s" + if len(flag.NoOptDefVal) == 0 { + format += "=" + } + format += "\")\n" + buf.WriteString(fmt.Sprintf(format, name)) +} + +func writeFlags(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(` flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + +`) + localNonPersistentFlags := cmd.LocalNonPersistentFlags() + cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } + writeFlag(buf, flag, cmd) + if len(flag.Shorthand) > 0 { + writeShortFlag(buf, flag, cmd) + } + if localNonPersistentFlags.Lookup(flag.Name) != nil { + writeLocalNonPersistentFlag(buf, flag) + } + }) + cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } + writeFlag(buf, flag, cmd) + if len(flag.Shorthand) > 0 { + writeShortFlag(buf, flag, cmd) + } + }) + + buf.WriteString("\n") +} + +func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" must_have_one_flag=()\n") + flags := cmd.NonInheritedFlags() + flags.VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } + for key := range flag.Annotations { + switch key { + case BashCompOneRequiredFlag: + format := " must_have_one_flag+=(\"--%s" + if flag.Value.Type() != "bool" { + format += "=" + } + format += "\")\n" + buf.WriteString(fmt.Sprintf(format, flag.Name)) + + if len(flag.Shorthand) > 0 { + buf.WriteString(fmt.Sprintf(" must_have_one_flag+=(\"-%s\")\n", flag.Shorthand)) + } + } + } + }) +} + +func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" must_have_one_noun=()\n") + sort.Sort(sort.StringSlice(cmd.ValidArgs)) + for _, value := range cmd.ValidArgs { + buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value)) + } +} + +func writeCmdAliases(buf *bytes.Buffer, cmd *Command) { + if len(cmd.Aliases) == 0 { + return + } + + sort.Sort(sort.StringSlice(cmd.Aliases)) + + buf.WriteString(fmt.Sprint(` if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then`, "\n")) + for _, value := range cmd.Aliases { + buf.WriteString(fmt.Sprintf(" command_aliases+=(%q)\n", value)) + buf.WriteString(fmt.Sprintf(" aliashash[%q]=%q\n", value, cmd.Name())) + } + buf.WriteString(` fi`) + buf.WriteString("\n") +} +func writeArgAliases(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" noun_aliases=()\n") + sort.Sort(sort.StringSlice(cmd.ArgAliases)) + for _, value := range cmd.ArgAliases { + buf.WriteString(fmt.Sprintf(" noun_aliases+=(%q)\n", value)) + } +} + +func gen(buf *bytes.Buffer, cmd *Command) { + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c == cmd.helpCommand { + continue + } + gen(buf, c) + } + commandName := cmd.CommandPath() + commandName = strings.Replace(commandName, " ", "_", -1) + commandName = strings.Replace(commandName, ":", "__", -1) + + if cmd.Root() == cmd { + buf.WriteString(fmt.Sprintf("_%s_root_command()\n{\n", commandName)) + } else { + buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName)) + } + + buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName)) + buf.WriteString("\n") + buf.WriteString(" command_aliases=()\n") + buf.WriteString("\n") + + writeCommands(buf, cmd) + writeFlags(buf, cmd) + writeRequiredFlag(buf, cmd) + writeRequiredNouns(buf, cmd) + writeArgAliases(buf, cmd) + buf.WriteString("}\n\n") +} + +// GenBashCompletion generates bash completion file and writes to the passed writer. +func (c *Command) GenBashCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + writePreamble(buf, c.Name()) + if len(c.BashCompletionFunction) > 0 { + buf.WriteString(c.BashCompletionFunction + "\n") + } + gen(buf, c) + writePostscript(buf, c.Name()) + + _, err := buf.WriteTo(w) + return err +} + +func nonCompletableFlag(flag *pflag.Flag) bool { + return flag.Hidden || len(flag.Deprecated) > 0 +} + +// GenBashCompletionFile generates bash completion file. +func (c *Command) GenBashCompletionFile(filename string) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenBashCompletion(outFile) +} diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md new file mode 100644 index 000000000..4ac61ee13 --- /dev/null +++ b/vendor/github.com/spf13/cobra/bash_completions.md @@ -0,0 +1,256 @@ +# Generating Bash Completions For Your Own cobra.Command + +If you are using the generator you can create a completion command by running + +```bash +cobra add completion +``` + +Update the help text show how to install the bash_completion Linux show here [Kubectl docs show mac options](https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion) + +Writing the shell script to stdout allows the most flexible use. + +```go +// completionCmd represents the completion command +var completionCmd = &cobra.Command{ + Use: "completion", + Short: "Generates bash completion scripts", + Long: `To load completion run + +. <(bitbucket completion) + +To configure your bash shell to load completions for each session add to your bashrc + +# ~/.bashrc or ~/.profile +. <(bitbucket completion) +`, + Run: func(cmd *cobra.Command, args []string) { + rootCmd.GenBashCompletion(os.Stdout); + }, +} +``` + +**Note:** The cobra generator may include messages printed to stdout for example if the config file is loaded, this will break the auto complete script + + +## Example from kubectl + +Generating bash completions from a cobra command is incredibly easy. An actual program which does so for the kubernetes kubectl binary is as follows: + +```go +package main + +import ( + "io/ioutil" + "os" + + "k8s.io/kubernetes/pkg/kubectl/cmd" + "k8s.io/kubernetes/pkg/kubectl/cmd/util" +) + +func main() { + kubectl := cmd.NewKubectlCommand(util.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + kubectl.GenBashCompletionFile("out.sh") +} +``` + +`out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior. + +## Creating your own custom functions + +Some more actual code that works in kubernetes: + +```bash +const ( + bash_completion_func = `__kubectl_parse_get() +{ + local kubectl_output out + if kubectl_output=$(kubectl get --no-headers "$1" 2>/dev/null); then + out=($(echo "${kubectl_output}" | awk '{print $1}')) + COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) + fi +} + +__kubectl_get_resource() +{ + if [[ ${#nouns[@]} -eq 0 ]]; then + return 1 + fi + __kubectl_parse_get ${nouns[${#nouns[@]} -1]} + if [[ $? -eq 0 ]]; then + return 0 + fi +} + +__kubectl_custom_func() { + case ${last_command} in + kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop) + __kubectl_get_resource + return + ;; + *) + ;; + esac +} +`) +``` + +And then I set that in my command definition: + +```go +cmds := &cobra.Command{ + Use: "kubectl", + Short: "kubectl controls the Kubernetes cluster manager", + Long: `kubectl controls the Kubernetes cluster manager. + +Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, + Run: runHelp, + BashCompletionFunction: bash_completion_func, +} +``` + +The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__kubectl_custom_func()` (`___custom_func()`) to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__kubectl_customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__kubectl_custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`. `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`. So it will call `__kubectl_parse_get pod`. `__kubectl_parse_get` will actually call out to kubernetes and get any pods. It will then set `COMPREPLY` to valid pods! + +## Have the completions code complete your 'nouns' + +In the above example "pod" was assumed to already be typed. But if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like: + +```go +validArgs []string = { "pod", "node", "service", "replicationcontroller" } + +cmd := &cobra.Command{ + Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)", + Short: "Display one or many resources", + Long: get_long, + Example: get_example, + Run: func(cmd *cobra.Command, args []string) { + err := RunGet(f, out, cmd, args) + util.CheckErr(err) + }, + ValidArgs: validArgs, +} +``` + +Notice we put the "ValidArgs" on the "get" subcommand. Doing so will give results like + +```bash +# kubectl get [tab][tab] +node pod replicationcontroller service +``` + +## Plural form and shortcuts for nouns + +If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`: + +```go +argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" } + +cmd := &cobra.Command{ + ... + ValidArgs: validArgs, + ArgAliases: argAliases +} +``` + +The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by +the completion algorithm if entered manually, e.g. in: + +```bash +# kubectl get rc [tab][tab] +backend frontend database +``` + +Note that without declaring `rc` as an alias, the completion algorithm would show the list of nouns +in this example again instead of the replication controllers. + +## Mark flags as required + +Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab]. Marking a flag as 'Required' is incredibly easy. + +```go +cmd.MarkFlagRequired("pod") +cmd.MarkFlagRequired("container") +``` + +and you'll get something like + +```bash +# kubectl exec [tab][tab][tab] +-c --container= -p --pod= +``` + +# Specify valid filename extensions for flags that take a filename + +In this example we use --filename= and expect to get a json or yaml file as the argument. To make this easier we annotate the --filename flag with valid filename extensions. + +```go + annotations := []string{"json", "yaml", "yml"} + annotation := make(map[string][]string) + annotation[cobra.BashCompFilenameExt] = annotations + + flag := &pflag.Flag{ + Name: "filename", + Shorthand: "f", + Usage: usage, + Value: value, + DefValue: value.String(), + Annotations: annotation, + } + cmd.Flags().AddFlag(flag) +``` + +Now when you run a command with this filename flag you'll get something like + +```bash +# kubectl create -f +test/ example/ rpmbuild/ +hello.yml test.json +``` + +So while there are many other files in the CWD it only shows me subdirs and those with valid extensions. + +# Specify custom flag completion + +Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specify +a custom flag completion function with cobra.BashCompCustom: + +```go + annotation := make(map[string][]string) + annotation[cobra.BashCompCustom] = []string{"__kubectl_get_namespaces"} + + flag := &pflag.Flag{ + Name: "namespace", + Usage: usage, + Annotations: annotation, + } + cmd.Flags().AddFlag(flag) +``` + +In addition add the `__handle_namespace_flag` implementation in the `BashCompletionFunction` +value, e.g.: + +```bash +__kubectl_get_namespaces() +{ + local template + template="{{ range .items }}{{ .metadata.name }} {{ end }}" + local kubectl_out + if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then + COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) ) + fi +} +``` +# Using bash aliases for commands + +You can also configure the `bash aliases` for the commands and they will also support completions. + +```bash +alias aliasname=origcommand +complete -o default -F __start_origcommand aliasname + +# and now when you run `aliasname` completion will make +# suggestions as it did for `origcommand`. + +$) aliasname +completion firstcommand secondcommand +``` diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go new file mode 100644 index 000000000..6505c070b --- /dev/null +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -0,0 +1,207 @@ +// Copyright © 2013 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Commands similar to git, go tools and other modern CLI tools +// inspired by go, go-Commander, gh and subcommand + +package cobra + +import ( + "fmt" + "io" + "reflect" + "strconv" + "strings" + "text/template" + "time" + "unicode" +) + +var templateFuncs = template.FuncMap{ + "trim": strings.TrimSpace, + "trimRightSpace": trimRightSpace, + "trimTrailingWhitespaces": trimRightSpace, + "appendIfNotPresent": appendIfNotPresent, + "rpad": rpad, + "gt": Gt, + "eq": Eq, +} + +var initializers []func() + +// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing +// to automatically enable in CLI tools. +// Set this to true to enable it. +var EnablePrefixMatching = false + +// EnableCommandSorting controls sorting of the slice of commands, which is turned on by default. +// To disable sorting, set it to false. +var EnableCommandSorting = true + +// MousetrapHelpText enables an information splash screen on Windows +// if the CLI is started from explorer.exe. +// To disable the mousetrap, just set this variable to blank string (""). +// Works only on Microsoft Windows. +var MousetrapHelpText string = `This is a command line tool. + +You need to open cmd.exe and run it from there. +` + +// MousetrapDisplayDuration controls how long the MousetrapHelpText message is displayed on Windows +// if the CLI is started from explorer.exe. Set to 0 to wait for the return key to be pressed. +// To disable the mousetrap, just set MousetrapHelpText to blank string (""). +// Works only on Microsoft Windows. +var MousetrapDisplayDuration time.Duration = 5 * time.Second + +// AddTemplateFunc adds a template function that's available to Usage and Help +// template generation. +func AddTemplateFunc(name string, tmplFunc interface{}) { + templateFuncs[name] = tmplFunc +} + +// AddTemplateFuncs adds multiple template functions that are available to Usage and +// Help template generation. +func AddTemplateFuncs(tmplFuncs template.FuncMap) { + for k, v := range tmplFuncs { + templateFuncs[k] = v + } +} + +// OnInitialize sets the passed functions to be run when each command's +// Execute method is called. +func OnInitialize(y ...func()) { + initializers = append(initializers, y...) +} + +// FIXME Gt is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, +// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as +// ints and then compared. +func Gt(a interface{}, b interface{}) bool { + var left, right int64 + av := reflect.ValueOf(a) + + switch av.Kind() { + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + left = int64(av.Len()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + left = av.Int() + case reflect.String: + left, _ = strconv.ParseInt(av.String(), 10, 64) + } + + bv := reflect.ValueOf(b) + + switch bv.Kind() { + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + right = int64(bv.Len()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + right = bv.Int() + case reflect.String: + right, _ = strconv.ParseInt(bv.String(), 10, 64) + } + + return left > right +} + +// FIXME Eq is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic. +func Eq(a interface{}, b interface{}) bool { + av := reflect.ValueOf(a) + bv := reflect.ValueOf(b) + + switch av.Kind() { + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + panic("Eq called on unsupported type") + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return av.Int() == bv.Int() + case reflect.String: + return av.String() == bv.String() + } + return false +} + +func trimRightSpace(s string) string { + return strings.TrimRightFunc(s, unicode.IsSpace) +} + +// FIXME appendIfNotPresent is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s. +func appendIfNotPresent(s, stringToAppend string) string { + if strings.Contains(s, stringToAppend) { + return s + } + return s + " " + stringToAppend +} + +// rpad adds padding to the right of a string. +func rpad(s string, padding int) string { + template := fmt.Sprintf("%%-%ds", padding) + return fmt.Sprintf(template, s) +} + +// tmpl executes the given template text on data, writing the result to w. +func tmpl(w io.Writer, text string, data interface{}) error { + t := template.New("top") + t.Funcs(templateFuncs) + template.Must(t.Parse(text)) + return t.Execute(w, data) +} + +// ld compares two strings and returns the levenshtein distance between them. +func ld(s, t string, ignoreCase bool) int { + if ignoreCase { + s = strings.ToLower(s) + t = strings.ToLower(t) + } + d := make([][]int, len(s)+1) + for i := range d { + d[i] = make([]int, len(t)+1) + } + for i := range d { + d[i][0] = i + } + for j := range d[0] { + d[0][j] = j + } + for j := 1; j <= len(t); j++ { + for i := 1; i <= len(s); i++ { + if s[i-1] == t[j-1] { + d[i][j] = d[i-1][j-1] + } else { + min := d[i-1][j] + if d[i][j-1] < min { + min = d[i][j-1] + } + if d[i-1][j-1] < min { + min = d[i-1][j-1] + } + d[i][j] = min + 1 + } + } + + } + return d[len(s)][len(t)] +} + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go new file mode 100644 index 000000000..c7e898303 --- /dev/null +++ b/vendor/github.com/spf13/cobra/command.go @@ -0,0 +1,1594 @@ +// Copyright © 2013 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. +// In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + + flag "github.com/spf13/pflag" +) + +// FParseErrWhitelist configures Flag parse errors to be ignored +type FParseErrWhitelist flag.ParseErrorsWhitelist + +// Command is just that, a command for your application. +// E.g. 'go run ...' - 'run' is the command. Cobra requires +// you to define the usage and description as part of your command +// definition to ensure usability. +type Command struct { + // Use is the one-line usage message. + Use string + + // Aliases is an array of aliases that can be used instead of the first word in Use. + Aliases []string + + // SuggestFor is an array of command names for which this command will be suggested - + // similar to aliases but only suggests. + SuggestFor []string + + // Short is the short description shown in the 'help' output. + Short string + + // Long is the long message shown in the 'help ' output. + Long string + + // Example is examples of how to use the command. + Example string + + // ValidArgs is list of all valid non-flag arguments that are accepted in bash completions + ValidArgs []string + + // Expected arguments + Args PositionalArgs + + // ArgAliases is List of aliases for ValidArgs. + // These are not suggested to the user in the bash completion, + // but accepted if entered manually. + ArgAliases []string + + // BashCompletionFunction is custom functions used by the bash autocompletion generator. + BashCompletionFunction string + + // Deprecated defines, if this command is deprecated and should print this string when used. + Deprecated string + + // Hidden defines, if this command is hidden and should NOT show up in the list of available commands. + Hidden bool + + // Annotations are key/value pairs that can be used by applications to identify or + // group commands. + Annotations map[string]string + + // Version defines the version for this command. If this value is non-empty and the command does not + // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, + // will print content of the "Version" variable. + Version string + + // The *Run functions are executed in the following order: + // * PersistentPreRun() + // * PreRun() + // * Run() + // * PostRun() + // * PersistentPostRun() + // All functions get the same args, the arguments after the command name. + // + // PersistentPreRun: children of this command will inherit and execute. + PersistentPreRun func(cmd *Command, args []string) + // PersistentPreRunE: PersistentPreRun but returns an error. + PersistentPreRunE func(cmd *Command, args []string) error + // PreRun: children of this command will not inherit. + PreRun func(cmd *Command, args []string) + // PreRunE: PreRun but returns an error. + PreRunE func(cmd *Command, args []string) error + // Run: Typically the actual work function. Most commands will only implement this. + Run func(cmd *Command, args []string) + // RunE: Run but returns an error. + RunE func(cmd *Command, args []string) error + // PostRun: run after the Run command. + PostRun func(cmd *Command, args []string) + // PostRunE: PostRun but returns an error. + PostRunE func(cmd *Command, args []string) error + // PersistentPostRun: children of this command will inherit and execute after PostRun. + PersistentPostRun func(cmd *Command, args []string) + // PersistentPostRunE: PersistentPostRun but returns an error. + PersistentPostRunE func(cmd *Command, args []string) error + + // SilenceErrors is an option to quiet errors down stream. + SilenceErrors bool + + // SilenceUsage is an option to silence usage when an error occurs. + SilenceUsage bool + + // DisableFlagParsing disables the flag parsing. + // If this is true all flags will be passed to the command as arguments. + DisableFlagParsing bool + + // DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...") + // will be printed by generating docs for this command. + DisableAutoGenTag bool + + // DisableFlagsInUseLine will disable the addition of [flags] to the usage + // line of a command when printing help or generating docs + DisableFlagsInUseLine bool + + // DisableSuggestions disables the suggestions based on Levenshtein distance + // that go along with 'unknown command' messages. + DisableSuggestions bool + // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. + // Must be > 0. + SuggestionsMinimumDistance int + + // TraverseChildren parses flags on all parents before executing child command. + TraverseChildren bool + + //FParseErrWhitelist flag parse errors to be ignored + FParseErrWhitelist FParseErrWhitelist + + // commands is the list of commands supported by this program. + commands []*Command + // parent is a parent command for this command. + parent *Command + // Max lengths of commands' string lengths for use in padding. + commandsMaxUseLen int + commandsMaxCommandPathLen int + commandsMaxNameLen int + // commandsAreSorted defines, if command slice are sorted or not. + commandsAreSorted bool + // commandCalledAs is the name or alias value used to call this command. + commandCalledAs struct { + name string + called bool + } + + // args is actual args parsed from flags. + args []string + // flagErrorBuf contains all error messages from pflag. + flagErrorBuf *bytes.Buffer + // flags is full set of flags. + flags *flag.FlagSet + // pflags contains persistent flags. + pflags *flag.FlagSet + // lflags contains local flags. + lflags *flag.FlagSet + // iflags contains inherited flags. + iflags *flag.FlagSet + // parentsPflags is all persistent flags of cmd's parents. + parentsPflags *flag.FlagSet + // globNormFunc is the global normalization function + // that we can use on every pflag set and children commands + globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName + + // usageFunc is usage func defined by user. + usageFunc func(*Command) error + // usageTemplate is usage template defined by user. + usageTemplate string + // flagErrorFunc is func defined by user and it's called when the parsing of + // flags returns an error. + flagErrorFunc func(*Command, error) error + // helpTemplate is help template defined by user. + helpTemplate string + // helpFunc is help func defined by user. + helpFunc func(*Command, []string) + // helpCommand is command with usage 'help'. If it's not defined by user, + // cobra uses default help command. + helpCommand *Command + // versionTemplate is the version template defined by user. + versionTemplate string + + // inReader is a reader defined by the user that replaces stdin + inReader io.Reader + // outWriter is a writer defined by the user that replaces stdout + outWriter io.Writer + // errWriter is a writer defined by the user that replaces stderr + errWriter io.Writer +} + +// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden +// particularly useful when testing. +func (c *Command) SetArgs(a []string) { + c.args = a +} + +// SetOutput sets the destination for usage and error messages. +// If output is nil, os.Stderr is used. +// Deprecated: Use SetOut and/or SetErr instead +func (c *Command) SetOutput(output io.Writer) { + c.outWriter = output + c.errWriter = output +} + +// SetOut sets the destination for usage messages. +// If newOut is nil, os.Stdout is used. +func (c *Command) SetOut(newOut io.Writer) { + c.outWriter = newOut +} + +// SetErr sets the destination for error messages. +// If newErr is nil, os.Stderr is used. +func (c *Command) SetErr(newErr io.Writer) { + c.errWriter = newErr +} + +// SetOut sets the source for input data +// If newIn is nil, os.Stdin is used. +func (c *Command) SetIn(newIn io.Reader) { + c.inReader = newIn +} + +// SetUsageFunc sets usage function. Usage can be defined by application. +func (c *Command) SetUsageFunc(f func(*Command) error) { + c.usageFunc = f +} + +// SetUsageTemplate sets usage template. Can be defined by Application. +func (c *Command) SetUsageTemplate(s string) { + c.usageTemplate = s +} + +// SetFlagErrorFunc sets a function to generate an error when flag parsing +// fails. +func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) { + c.flagErrorFunc = f +} + +// SetHelpFunc sets help function. Can be defined by Application. +func (c *Command) SetHelpFunc(f func(*Command, []string)) { + c.helpFunc = f +} + +// SetHelpCommand sets help command. +func (c *Command) SetHelpCommand(cmd *Command) { + c.helpCommand = cmd +} + +// SetHelpTemplate sets help template to be used. Application can use it to set custom template. +func (c *Command) SetHelpTemplate(s string) { + c.helpTemplate = s +} + +// SetVersionTemplate sets version template to be used. Application can use it to set custom template. +func (c *Command) SetVersionTemplate(s string) { + c.versionTemplate = s +} + +// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. +// The user should not have a cyclic dependency on commands. +func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) { + c.Flags().SetNormalizeFunc(n) + c.PersistentFlags().SetNormalizeFunc(n) + c.globNormFunc = n + + for _, command := range c.commands { + command.SetGlobalNormalizationFunc(n) + } +} + +// OutOrStdout returns output to stdout. +func (c *Command) OutOrStdout() io.Writer { + return c.getOut(os.Stdout) +} + +// OutOrStderr returns output to stderr +func (c *Command) OutOrStderr() io.Writer { + return c.getOut(os.Stderr) +} + +// ErrOrStderr returns output to stderr +func (c *Command) ErrOrStderr() io.Writer { + return c.getErr(os.Stderr) +} + +// ErrOrStderr returns output to stderr +func (c *Command) InOrStdin() io.Reader { + return c.getIn(os.Stdin) +} + +func (c *Command) getOut(def io.Writer) io.Writer { + if c.outWriter != nil { + return c.outWriter + } + if c.HasParent() { + return c.parent.getOut(def) + } + return def +} + +func (c *Command) getErr(def io.Writer) io.Writer { + if c.errWriter != nil { + return c.errWriter + } + if c.HasParent() { + return c.parent.getErr(def) + } + return def +} + +func (c *Command) getIn(def io.Reader) io.Reader { + if c.inReader != nil { + return c.inReader + } + if c.HasParent() { + return c.parent.getIn(def) + } + return def +} + +// UsageFunc returns either the function set by SetUsageFunc for this command +// or a parent, or it returns a default usage function. +func (c *Command) UsageFunc() (f func(*Command) error) { + if c.usageFunc != nil { + return c.usageFunc + } + if c.HasParent() { + return c.Parent().UsageFunc() + } + return func(c *Command) error { + c.mergePersistentFlags() + err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c) + if err != nil { + c.Println(err) + } + return err + } +} + +// Usage puts out the usage for the command. +// Used when a user provides invalid input. +// Can be defined by user by overriding UsageFunc. +func (c *Command) Usage() error { + return c.UsageFunc()(c) +} + +// HelpFunc returns either the function set by SetHelpFunc for this command +// or a parent, or it returns a function with default help behavior. +func (c *Command) HelpFunc() func(*Command, []string) { + if c.helpFunc != nil { + return c.helpFunc + } + if c.HasParent() { + return c.Parent().HelpFunc() + } + return func(c *Command, a []string) { + c.mergePersistentFlags() + err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c) + if err != nil { + c.Println(err) + } + } +} + +// Help puts out the help for the command. +// Used when a user calls help [command]. +// Can be defined by user by overriding HelpFunc. +func (c *Command) Help() error { + c.HelpFunc()(c, []string{}) + return nil +} + +// UsageString returns usage string. +func (c *Command) UsageString() string { + // Storing normal writers + tmpOutput := c.outWriter + tmpErr := c.errWriter + + bb := new(bytes.Buffer) + c.outWriter = bb + c.errWriter = bb + + c.Usage() + + // Setting things back to normal + c.outWriter = tmpOutput + c.errWriter = tmpErr + + return bb.String() +} + +// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this +// command or a parent, or it returns a function which returns the original +// error. +func (c *Command) FlagErrorFunc() (f func(*Command, error) error) { + if c.flagErrorFunc != nil { + return c.flagErrorFunc + } + + if c.HasParent() { + return c.parent.FlagErrorFunc() + } + return func(c *Command, err error) error { + return err + } +} + +var minUsagePadding = 25 + +// UsagePadding return padding for the usage. +func (c *Command) UsagePadding() int { + if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen { + return minUsagePadding + } + return c.parent.commandsMaxUseLen +} + +var minCommandPathPadding = 11 + +// CommandPathPadding return padding for the command path. +func (c *Command) CommandPathPadding() int { + if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen { + return minCommandPathPadding + } + return c.parent.commandsMaxCommandPathLen +} + +var minNamePadding = 11 + +// NamePadding returns padding for the name. +func (c *Command) NamePadding() int { + if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen { + return minNamePadding + } + return c.parent.commandsMaxNameLen +} + +// UsageTemplate returns usage template for the command. +func (c *Command) UsageTemplate() string { + if c.usageTemplate != "" { + return c.usageTemplate + } + + if c.HasParent() { + return c.parent.UsageTemplate() + } + return `Usage:{{if .Runnable}} + {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} + {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} + +Aliases: + {{.NameAndAliases}}{{end}}{{if .HasExample}} + +Examples: +{{.Example}}{{end}}{{if .HasAvailableSubCommands}} + +Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} + +Flags: +{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} + +Global Flags: +{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} + +Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} + {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} + +Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} +` +} + +// HelpTemplate return help template for the command. +func (c *Command) HelpTemplate() string { + if c.helpTemplate != "" { + return c.helpTemplate + } + + if c.HasParent() { + return c.parent.HelpTemplate() + } + return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} + +{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` +} + +// VersionTemplate return version template for the command. +func (c *Command) VersionTemplate() string { + if c.versionTemplate != "" { + return c.versionTemplate + } + + if c.HasParent() { + return c.parent.VersionTemplate() + } + return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}} +` +} + +func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { + flag := fs.Lookup(name) + if flag == nil { + return false + } + return flag.NoOptDefVal != "" +} + +func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool { + if len(name) == 0 { + return false + } + + flag := fs.ShorthandLookup(name[:1]) + if flag == nil { + return false + } + return flag.NoOptDefVal != "" +} + +func stripFlags(args []string, c *Command) []string { + if len(args) == 0 { + return args + } + c.mergePersistentFlags() + + commands := []string{} + flags := c.Flags() + +Loop: + for len(args) > 0 { + s := args[0] + args = args[1:] + switch { + case s == "--": + // "--" terminates the flags + break Loop + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + // If '--flag arg' then + // delete arg from args. + fallthrough // (do the same as below) + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // If '-f arg' then + // delete 'arg' from args or break the loop if len(args) <= 1. + if len(args) <= 1 { + break Loop + } else { + args = args[1:] + continue + } + case s != "" && !strings.HasPrefix(s, "-"): + commands = append(commands, s) + } + } + + return commands +} + +// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like +// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]). +func argsMinusFirstX(args []string, x string) []string { + for i, y := range args { + if x == y { + ret := []string{} + ret = append(ret, args[:i]...) + ret = append(ret, args[i+1:]...) + return ret + } + } + return args +} + +func isFlagArg(arg string) bool { + return ((len(arg) >= 3 && arg[1] == '-') || + (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) +} + +// Find the target command given the args and command tree +// Meant to be run on the highest node. Only searches down. +func (c *Command) Find(args []string) (*Command, []string, error) { + var innerfind func(*Command, []string) (*Command, []string) + + innerfind = func(c *Command, innerArgs []string) (*Command, []string) { + argsWOflags := stripFlags(innerArgs, c) + if len(argsWOflags) == 0 { + return c, innerArgs + } + nextSubCmd := argsWOflags[0] + + cmd := c.findNext(nextSubCmd) + if cmd != nil { + return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) + } + return c, innerArgs + } + + commandFound, a := innerfind(c, args) + if commandFound.Args == nil { + return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound)) + } + return commandFound, a, nil +} + +func (c *Command) findSuggestions(arg string) string { + if c.DisableSuggestions { + return "" + } + if c.SuggestionsMinimumDistance <= 0 { + c.SuggestionsMinimumDistance = 2 + } + suggestionsString := "" + if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 { + suggestionsString += "\n\nDid you mean this?\n" + for _, s := range suggestions { + suggestionsString += fmt.Sprintf("\t%v\n", s) + } + } + return suggestionsString +} + +func (c *Command) findNext(next string) *Command { + matches := make([]*Command, 0) + for _, cmd := range c.commands { + if cmd.Name() == next || cmd.HasAlias(next) { + cmd.commandCalledAs.name = next + return cmd + } + if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) { + matches = append(matches, cmd) + } + } + + if len(matches) == 1 { + return matches[0] + } + + return nil +} + +// Traverse the command tree to find the command, and parse args for +// each parent. +func (c *Command) Traverse(args []string) (*Command, []string, error) { + flags := []string{} + inFlag := false + + for i, arg := range args { + switch { + // A long flag with a space separated value + case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="): + // TODO: this isn't quite right, we should really check ahead for 'true' or 'false' + inFlag = !hasNoOptDefVal(arg[2:], c.Flags()) + flags = append(flags, arg) + continue + // A short flag with a space separated value + case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()): + inFlag = true + flags = append(flags, arg) + continue + // The value for a flag + case inFlag: + inFlag = false + flags = append(flags, arg) + continue + // A flag without a value, or with an `=` separated value + case isFlagArg(arg): + flags = append(flags, arg) + continue + } + + cmd := c.findNext(arg) + if cmd == nil { + return c, args, nil + } + + if err := c.ParseFlags(flags); err != nil { + return nil, args, err + } + return cmd.Traverse(args[i+1:]) + } + return c, args, nil +} + +// SuggestionsFor provides suggestions for the typedName. +func (c *Command) SuggestionsFor(typedName string) []string { + suggestions := []string{} + for _, cmd := range c.commands { + if cmd.IsAvailableCommand() { + levenshteinDistance := ld(typedName, cmd.Name(), true) + suggestByLevenshtein := levenshteinDistance <= c.SuggestionsMinimumDistance + suggestByPrefix := strings.HasPrefix(strings.ToLower(cmd.Name()), strings.ToLower(typedName)) + if suggestByLevenshtein || suggestByPrefix { + suggestions = append(suggestions, cmd.Name()) + } + for _, explicitSuggestion := range cmd.SuggestFor { + if strings.EqualFold(typedName, explicitSuggestion) { + suggestions = append(suggestions, cmd.Name()) + } + } + } + } + return suggestions +} + +// VisitParents visits all parents of the command and invokes fn on each parent. +func (c *Command) VisitParents(fn func(*Command)) { + if c.HasParent() { + fn(c.Parent()) + c.Parent().VisitParents(fn) + } +} + +// Root finds root command. +func (c *Command) Root() *Command { + if c.HasParent() { + return c.Parent().Root() + } + return c +} + +// ArgsLenAtDash will return the length of c.Flags().Args at the moment +// when a -- was found during args parsing. +func (c *Command) ArgsLenAtDash() int { + return c.Flags().ArgsLenAtDash() +} + +func (c *Command) execute(a []string) (err error) { + if c == nil { + return fmt.Errorf("Called Execute() on a nil Command") + } + + if len(c.Deprecated) > 0 { + c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated) + } + + // initialize help and version flag at the last point possible to allow for user + // overriding + c.InitDefaultHelpFlag() + c.InitDefaultVersionFlag() + + err = c.ParseFlags(a) + if err != nil { + return c.FlagErrorFunc()(c, err) + } + + // If help is called, regardless of other flags, return we want help. + // Also say we need help if the command isn't runnable. + helpVal, err := c.Flags().GetBool("help") + if err != nil { + // should be impossible to get here as we always declare a help + // flag in InitDefaultHelpFlag() + c.Println("\"help\" flag declared as non-bool. Please correct your code") + return err + } + + if helpVal { + return flag.ErrHelp + } + + // for back-compat, only add version flag behavior if version is defined + if c.Version != "" { + versionVal, err := c.Flags().GetBool("version") + if err != nil { + c.Println("\"version\" flag declared as non-bool. Please correct your code") + return err + } + if versionVal { + err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c) + if err != nil { + c.Println(err) + } + return err + } + } + + if !c.Runnable() { + return flag.ErrHelp + } + + c.preRun() + + argWoFlags := c.Flags().Args() + if c.DisableFlagParsing { + argWoFlags = a + } + + if err := c.ValidateArgs(argWoFlags); err != nil { + return err + } + + for p := c; p != nil; p = p.Parent() { + if p.PersistentPreRunE != nil { + if err := p.PersistentPreRunE(c, argWoFlags); err != nil { + return err + } + break + } else if p.PersistentPreRun != nil { + p.PersistentPreRun(c, argWoFlags) + break + } + } + if c.PreRunE != nil { + if err := c.PreRunE(c, argWoFlags); err != nil { + return err + } + } else if c.PreRun != nil { + c.PreRun(c, argWoFlags) + } + + if err := c.validateRequiredFlags(); err != nil { + return err + } + if c.RunE != nil { + if err := c.RunE(c, argWoFlags); err != nil { + return err + } + } else { + c.Run(c, argWoFlags) + } + if c.PostRunE != nil { + if err := c.PostRunE(c, argWoFlags); err != nil { + return err + } + } else if c.PostRun != nil { + c.PostRun(c, argWoFlags) + } + for p := c; p != nil; p = p.Parent() { + if p.PersistentPostRunE != nil { + if err := p.PersistentPostRunE(c, argWoFlags); err != nil { + return err + } + break + } else if p.PersistentPostRun != nil { + p.PersistentPostRun(c, argWoFlags) + break + } + } + + return nil +} + +func (c *Command) preRun() { + for _, x := range initializers { + x() + } +} + +// Execute uses the args (os.Args[1:] by default) +// and run through the command tree finding appropriate matches +// for commands and then corresponding flags. +func (c *Command) Execute() error { + _, err := c.ExecuteC() + return err +} + +// ExecuteC executes the command. +func (c *Command) ExecuteC() (cmd *Command, err error) { + // Regardless of what command execute is called on, run on Root only + if c.HasParent() { + return c.Root().ExecuteC() + } + + // windows hook + if preExecHookFn != nil { + preExecHookFn(c) + } + + // initialize help as the last point possible to allow for user + // overriding + c.InitDefaultHelpCmd() + + args := c.args + + // Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155 + if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" { + args = os.Args[1:] + } + + var flags []string + if c.TraverseChildren { + cmd, flags, err = c.Traverse(args) + } else { + cmd, flags, err = c.Find(args) + } + if err != nil { + // If found parse to a subcommand and then failed, talk about the subcommand + if cmd != nil { + c = cmd + } + if !c.SilenceErrors { + c.Println("Error:", err.Error()) + c.Printf("Run '%v --help' for usage.\n", c.CommandPath()) + } + return c, err + } + + cmd.commandCalledAs.called = true + if cmd.commandCalledAs.name == "" { + cmd.commandCalledAs.name = cmd.Name() + } + + err = cmd.execute(flags) + if err != nil { + // Always show help if requested, even if SilenceErrors is in + // effect + if err == flag.ErrHelp { + cmd.HelpFunc()(cmd, args) + return cmd, nil + } + + // If root command has SilentErrors flagged, + // all subcommands should respect it + if !cmd.SilenceErrors && !c.SilenceErrors { + c.Println("Error:", err.Error()) + } + + // If root command has SilentUsage flagged, + // all subcommands should respect it + if !cmd.SilenceUsage && !c.SilenceUsage { + c.Println(cmd.UsageString()) + } + } + return cmd, err +} + +func (c *Command) ValidateArgs(args []string) error { + if c.Args == nil { + return nil + } + return c.Args(c, args) +} + +func (c *Command) validateRequiredFlags() error { + flags := c.Flags() + missingFlagNames := []string{} + flags.VisitAll(func(pflag *flag.Flag) { + requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag] + if !found { + return + } + if (requiredAnnotation[0] == "true") && !pflag.Changed { + missingFlagNames = append(missingFlagNames, pflag.Name) + } + }) + + if len(missingFlagNames) > 0 { + return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`)) + } + return nil +} + +// InitDefaultHelpFlag adds default help flag to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help flag, it will do nothing. +func (c *Command) InitDefaultHelpFlag() { + c.mergePersistentFlags() + if c.Flags().Lookup("help") == nil { + usage := "help for " + if c.Name() == "" { + usage += "this command" + } else { + usage += c.Name() + } + c.Flags().BoolP("help", "h", false, usage) + } +} + +// InitDefaultVersionFlag adds default version flag to c. +// It is called automatically by executing the c. +// If c already has a version flag, it will do nothing. +// If c.Version is empty, it will do nothing. +func (c *Command) InitDefaultVersionFlag() { + if c.Version == "" { + return + } + + c.mergePersistentFlags() + if c.Flags().Lookup("version") == nil { + usage := "version for " + if c.Name() == "" { + usage += "this command" + } else { + usage += c.Name() + } + c.Flags().Bool("version", false, usage) + } +} + +// InitDefaultHelpCmd adds default help command to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help command or c has no subcommands, it will do nothing. +func (c *Command) InitDefaultHelpCmd() { + if !c.HasSubCommands() { + return + } + + if c.helpCommand == nil { + c.helpCommand = &Command{ + Use: "help [command]", + Short: "Help about any command", + Long: `Help provides help for any command in the application. +Simply type ` + c.Name() + ` help [path to command] for full details.`, + + Run: func(c *Command, args []string) { + cmd, _, e := c.Root().Find(args) + if cmd == nil || e != nil { + c.Printf("Unknown help topic %#q\n", args) + c.Root().Usage() + } else { + cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown + cmd.Help() + } + }, + } + } + c.RemoveCommand(c.helpCommand) + c.AddCommand(c.helpCommand) +} + +// ResetCommands delete parent, subcommand and help command from c. +func (c *Command) ResetCommands() { + c.parent = nil + c.commands = nil + c.helpCommand = nil + c.parentsPflags = nil +} + +// Sorts commands by their names. +type commandSorterByName []*Command + +func (c commandSorterByName) Len() int { return len(c) } +func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] } +func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() } + +// Commands returns a sorted slice of child commands. +func (c *Command) Commands() []*Command { + // do not sort commands if it already sorted or sorting was disabled + if EnableCommandSorting && !c.commandsAreSorted { + sort.Sort(commandSorterByName(c.commands)) + c.commandsAreSorted = true + } + return c.commands +} + +// AddCommand adds one or more commands to this parent command. +func (c *Command) AddCommand(cmds ...*Command) { + for i, x := range cmds { + if cmds[i] == c { + panic("Command can't be a child of itself") + } + cmds[i].parent = c + // update max lengths + usageLen := len(x.Use) + if usageLen > c.commandsMaxUseLen { + c.commandsMaxUseLen = usageLen + } + commandPathLen := len(x.CommandPath()) + if commandPathLen > c.commandsMaxCommandPathLen { + c.commandsMaxCommandPathLen = commandPathLen + } + nameLen := len(x.Name()) + if nameLen > c.commandsMaxNameLen { + c.commandsMaxNameLen = nameLen + } + // If global normalization function exists, update all children + if c.globNormFunc != nil { + x.SetGlobalNormalizationFunc(c.globNormFunc) + } + c.commands = append(c.commands, x) + c.commandsAreSorted = false + } +} + +// RemoveCommand removes one or more commands from a parent command. +func (c *Command) RemoveCommand(cmds ...*Command) { + commands := []*Command{} +main: + for _, command := range c.commands { + for _, cmd := range cmds { + if command == cmd { + command.parent = nil + continue main + } + } + commands = append(commands, command) + } + c.commands = commands + // recompute all lengths + c.commandsMaxUseLen = 0 + c.commandsMaxCommandPathLen = 0 + c.commandsMaxNameLen = 0 + for _, command := range c.commands { + usageLen := len(command.Use) + if usageLen > c.commandsMaxUseLen { + c.commandsMaxUseLen = usageLen + } + commandPathLen := len(command.CommandPath()) + if commandPathLen > c.commandsMaxCommandPathLen { + c.commandsMaxCommandPathLen = commandPathLen + } + nameLen := len(command.Name()) + if nameLen > c.commandsMaxNameLen { + c.commandsMaxNameLen = nameLen + } + } +} + +// Print is a convenience method to Print to the defined output, fallback to Stderr if not set. +func (c *Command) Print(i ...interface{}) { + fmt.Fprint(c.OutOrStderr(), i...) +} + +// Println is a convenience method to Println to the defined output, fallback to Stderr if not set. +func (c *Command) Println(i ...interface{}) { + c.Print(fmt.Sprintln(i...)) +} + +// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set. +func (c *Command) Printf(format string, i ...interface{}) { + c.Print(fmt.Sprintf(format, i...)) +} + +// PrintErr is a convenience method to Print to the defined Err output, fallback to Stderr if not set. +func (c *Command) PrintErr(i ...interface{}) { + fmt.Fprint(c.ErrOrStderr(), i...) +} + +// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set. +func (c *Command) PrintErrln(i ...interface{}) { + c.Print(fmt.Sprintln(i...)) +} + +// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set. +func (c *Command) PrintErrf(format string, i ...interface{}) { + c.Print(fmt.Sprintf(format, i...)) +} + +// CommandPath returns the full path to this command. +func (c *Command) CommandPath() string { + if c.HasParent() { + return c.Parent().CommandPath() + " " + c.Name() + } + return c.Name() +} + +// UseLine puts out the full usage for a given command (including parents). +func (c *Command) UseLine() string { + var useline string + if c.HasParent() { + useline = c.parent.CommandPath() + " " + c.Use + } else { + useline = c.Use + } + if c.DisableFlagsInUseLine { + return useline + } + if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") { + useline += " [flags]" + } + return useline +} + +// DebugFlags used to determine which flags have been assigned to which commands +// and which persist. +func (c *Command) DebugFlags() { + c.Println("DebugFlags called on", c.Name()) + var debugflags func(*Command) + + debugflags = func(x *Command) { + if x.HasFlags() || x.HasPersistentFlags() { + c.Println(x.Name()) + } + if x.HasFlags() { + x.flags.VisitAll(func(f *flag.Flag) { + if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]") + } else { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]") + } + }) + } + if x.HasPersistentFlags() { + x.pflags.VisitAll(func(f *flag.Flag) { + if x.HasFlags() { + if x.flags.Lookup(f.Name) == nil { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]") + } + } else { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]") + } + }) + } + c.Println(x.flagErrorBuf) + if x.HasSubCommands() { + for _, y := range x.commands { + debugflags(y) + } + } + } + + debugflags(c) +} + +// Name returns the command's name: the first word in the use line. +func (c *Command) Name() string { + name := c.Use + i := strings.Index(name, " ") + if i >= 0 { + name = name[:i] + } + return name +} + +// HasAlias determines if a given string is an alias of the command. +func (c *Command) HasAlias(s string) bool { + for _, a := range c.Aliases { + if a == s { + return true + } + } + return false +} + +// CalledAs returns the command name or alias that was used to invoke +// this command or an empty string if the command has not been called. +func (c *Command) CalledAs() string { + if c.commandCalledAs.called { + return c.commandCalledAs.name + } + return "" +} + +// hasNameOrAliasPrefix returns true if the Name or any of aliases start +// with prefix +func (c *Command) hasNameOrAliasPrefix(prefix string) bool { + if strings.HasPrefix(c.Name(), prefix) { + c.commandCalledAs.name = c.Name() + return true + } + for _, alias := range c.Aliases { + if strings.HasPrefix(alias, prefix) { + c.commandCalledAs.name = alias + return true + } + } + return false +} + +// NameAndAliases returns a list of the command name and all aliases +func (c *Command) NameAndAliases() string { + return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ") +} + +// HasExample determines if the command has example. +func (c *Command) HasExample() bool { + return len(c.Example) > 0 +} + +// Runnable determines if the command is itself runnable. +func (c *Command) Runnable() bool { + return c.Run != nil || c.RunE != nil +} + +// HasSubCommands determines if the command has children commands. +func (c *Command) HasSubCommands() bool { + return len(c.commands) > 0 +} + +// IsAvailableCommand determines if a command is available as a non-help command +// (this includes all non deprecated/hidden commands). +func (c *Command) IsAvailableCommand() bool { + if len(c.Deprecated) != 0 || c.Hidden { + return false + } + + if c.HasParent() && c.Parent().helpCommand == c { + return false + } + + if c.Runnable() || c.HasAvailableSubCommands() { + return true + } + + return false +} + +// IsAdditionalHelpTopicCommand determines if a command is an additional +// help topic command; additional help topic command is determined by the +// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that +// are runnable/hidden/deprecated. +// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924. +func (c *Command) IsAdditionalHelpTopicCommand() bool { + // if a command is runnable, deprecated, or hidden it is not a 'help' command + if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden { + return false + } + + // if any non-help sub commands are found, the command is not a 'help' command + for _, sub := range c.commands { + if !sub.IsAdditionalHelpTopicCommand() { + return false + } + } + + // the command either has no sub commands, or no non-help sub commands + return true +} + +// HasHelpSubCommands determines if a command has any available 'help' sub commands +// that need to be shown in the usage/help default template under 'additional help +// topics'. +func (c *Command) HasHelpSubCommands() bool { + // return true on the first found available 'help' sub command + for _, sub := range c.commands { + if sub.IsAdditionalHelpTopicCommand() { + return true + } + } + + // the command either has no sub commands, or no available 'help' sub commands + return false +} + +// HasAvailableSubCommands determines if a command has available sub commands that +// need to be shown in the usage/help default template under 'available commands'. +func (c *Command) HasAvailableSubCommands() bool { + // return true on the first found available (non deprecated/help/hidden) + // sub command + for _, sub := range c.commands { + if sub.IsAvailableCommand() { + return true + } + } + + // the command either has no sub commands, or no available (non deprecated/help/hidden) + // sub commands + return false +} + +// HasParent determines if the command is a child command. +func (c *Command) HasParent() bool { + return c.parent != nil +} + +// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist. +func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName { + return c.globNormFunc +} + +// Flags returns the complete FlagSet that applies +// to this command (local and persistent declared here and by all parents). +func (c *Command) Flags() *flag.FlagSet { + if c.flags == nil { + c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.flags.SetOutput(c.flagErrorBuf) + } + + return c.flags +} + +// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands. +func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { + persistentFlags := c.PersistentFlags() + + out := flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.LocalFlags().VisitAll(func(f *flag.Flag) { + if persistentFlags.Lookup(f.Name) == nil { + out.AddFlag(f) + } + }) + return out +} + +// LocalFlags returns the local FlagSet specifically set in the current command. +func (c *Command) LocalFlags() *flag.FlagSet { + c.mergePersistentFlags() + + if c.lflags == nil { + c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.lflags.SetOutput(c.flagErrorBuf) + } + c.lflags.SortFlags = c.Flags().SortFlags + if c.globNormFunc != nil { + c.lflags.SetNormalizeFunc(c.globNormFunc) + } + + addToLocal := func(f *flag.Flag) { + if c.lflags.Lookup(f.Name) == nil && c.parentsPflags.Lookup(f.Name) == nil { + c.lflags.AddFlag(f) + } + } + c.Flags().VisitAll(addToLocal) + c.PersistentFlags().VisitAll(addToLocal) + return c.lflags +} + +// InheritedFlags returns all flags which were inherited from parent commands. +func (c *Command) InheritedFlags() *flag.FlagSet { + c.mergePersistentFlags() + + if c.iflags == nil { + c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.iflags.SetOutput(c.flagErrorBuf) + } + + local := c.LocalFlags() + if c.globNormFunc != nil { + c.iflags.SetNormalizeFunc(c.globNormFunc) + } + + c.parentsPflags.VisitAll(func(f *flag.Flag) { + if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil { + c.iflags.AddFlag(f) + } + }) + return c.iflags +} + +// NonInheritedFlags returns all flags which were not inherited from parent commands. +func (c *Command) NonInheritedFlags() *flag.FlagSet { + return c.LocalFlags() +} + +// PersistentFlags returns the persistent FlagSet specifically set in the current command. +func (c *Command) PersistentFlags() *flag.FlagSet { + if c.pflags == nil { + c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.pflags.SetOutput(c.flagErrorBuf) + } + return c.pflags +} + +// ResetFlags deletes all flags from command. +func (c *Command) ResetFlags() { + c.flagErrorBuf = new(bytes.Buffer) + c.flagErrorBuf.Reset() + c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags.SetOutput(c.flagErrorBuf) + c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags.SetOutput(c.flagErrorBuf) + + c.lflags = nil + c.iflags = nil + c.parentsPflags = nil +} + +// HasFlags checks if the command contains any flags (local plus persistent from the entire structure). +func (c *Command) HasFlags() bool { + return c.Flags().HasFlags() +} + +// HasPersistentFlags checks if the command contains persistent flags. +func (c *Command) HasPersistentFlags() bool { + return c.PersistentFlags().HasFlags() +} + +// HasLocalFlags checks if the command has flags specifically declared locally. +func (c *Command) HasLocalFlags() bool { + return c.LocalFlags().HasFlags() +} + +// HasInheritedFlags checks if the command has flags inherited from its parent command. +func (c *Command) HasInheritedFlags() bool { + return c.InheritedFlags().HasFlags() +} + +// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire +// structure) which are not hidden or deprecated. +func (c *Command) HasAvailableFlags() bool { + return c.Flags().HasAvailableFlags() +} + +// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated. +func (c *Command) HasAvailablePersistentFlags() bool { + return c.PersistentFlags().HasAvailableFlags() +} + +// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden +// or deprecated. +func (c *Command) HasAvailableLocalFlags() bool { + return c.LocalFlags().HasAvailableFlags() +} + +// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are +// not hidden or deprecated. +func (c *Command) HasAvailableInheritedFlags() bool { + return c.InheritedFlags().HasAvailableFlags() +} + +// Flag climbs up the command tree looking for matching flag. +func (c *Command) Flag(name string) (flag *flag.Flag) { + flag = c.Flags().Lookup(name) + + if flag == nil { + flag = c.persistentFlag(name) + } + + return +} + +// Recursively find matching persistent flag. +func (c *Command) persistentFlag(name string) (flag *flag.Flag) { + if c.HasPersistentFlags() { + flag = c.PersistentFlags().Lookup(name) + } + + if flag == nil { + c.updateParentsPflags() + flag = c.parentsPflags.Lookup(name) + } + return +} + +// ParseFlags parses persistent flag tree and local flags. +func (c *Command) ParseFlags(args []string) error { + if c.DisableFlagParsing { + return nil + } + + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + beforeErrorBufLen := c.flagErrorBuf.Len() + c.mergePersistentFlags() + + //do it here after merging all flags and just before parse + c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist) + + err := c.Flags().Parse(args) + // Print warnings if they occurred (e.g. deprecated flag messages). + if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil { + c.Print(c.flagErrorBuf.String()) + } + + return err +} + +// Parent returns a commands parent command. +func (c *Command) Parent() *Command { + return c.parent +} + +// mergePersistentFlags merges c.PersistentFlags() to c.Flags() +// and adds missing persistent flags of all parents. +func (c *Command) mergePersistentFlags() { + c.updateParentsPflags() + c.Flags().AddFlagSet(c.PersistentFlags()) + c.Flags().AddFlagSet(c.parentsPflags) +} + +// updateParentsPflags updates c.parentsPflags by adding +// new persistent flags of all parents. +// If c.parentsPflags == nil, it makes new. +func (c *Command) updateParentsPflags() { + if c.parentsPflags == nil { + c.parentsPflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.parentsPflags.SetOutput(c.flagErrorBuf) + c.parentsPflags.SortFlags = false + } + + if c.globNormFunc != nil { + c.parentsPflags.SetNormalizeFunc(c.globNormFunc) + } + + c.Root().PersistentFlags().AddFlagSet(flag.CommandLine) + + c.VisitParents(func(parent *Command) { + c.parentsPflags.AddFlagSet(parent.PersistentFlags()) + }) +} diff --git a/vendor/github.com/spf13/cobra/command_notwin.go b/vendor/github.com/spf13/cobra/command_notwin.go new file mode 100644 index 000000000..6159c1cc1 --- /dev/null +++ b/vendor/github.com/spf13/cobra/command_notwin.go @@ -0,0 +1,5 @@ +// +build !windows + +package cobra + +var preExecHookFn func(*Command) diff --git a/vendor/github.com/spf13/cobra/command_win.go b/vendor/github.com/spf13/cobra/command_win.go new file mode 100644 index 000000000..8768b1736 --- /dev/null +++ b/vendor/github.com/spf13/cobra/command_win.go @@ -0,0 +1,26 @@ +// +build windows + +package cobra + +import ( + "fmt" + "os" + "time" + + "github.com/inconshreveable/mousetrap" +) + +var preExecHookFn = preExecHook + +func preExecHook(c *Command) { + if MousetrapHelpText != "" && mousetrap.StartedByExplorer() { + c.Print(MousetrapHelpText) + if MousetrapDisplayDuration > 0 { + time.Sleep(MousetrapDisplayDuration) + } else { + c.Println("Press return to continue...") + fmt.Scanln() + } + os.Exit(1) + } +} diff --git a/vendor/github.com/spf13/cobra/go.mod b/vendor/github.com/spf13/cobra/go.mod new file mode 100644 index 000000000..9a9eb65a3 --- /dev/null +++ b/vendor/github.com/spf13/cobra/go.mod @@ -0,0 +1,13 @@ +module github.com/spf13/cobra + +go 1.12 + +require ( + github.com/BurntSushi/toml v0.3.1 // indirect + github.com/cpuguy83/go-md2man v1.0.10 + github.com/inconshreveable/mousetrap v1.0.0 + github.com/mitchellh/go-homedir v1.1.0 + github.com/spf13/pflag v1.0.3 + github.com/spf13/viper v1.3.2 + gopkg.in/yaml.v2 v2.2.2 +) diff --git a/vendor/github.com/spf13/cobra/go.sum b/vendor/github.com/spf13/cobra/go.sum new file mode 100644 index 000000000..9761f4d03 --- /dev/null +++ b/vendor/github.com/spf13/cobra/go.sum @@ -0,0 +1,51 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/spf13/cobra/powershell_completions.go b/vendor/github.com/spf13/cobra/powershell_completions.go new file mode 100644 index 000000000..756c61b9d --- /dev/null +++ b/vendor/github.com/spf13/cobra/powershell_completions.go @@ -0,0 +1,100 @@ +// PowerShell completions are based on the amazing work from clap: +// https://github.com/clap-rs/clap/blob/3294d18efe5f264d12c9035f404c7d189d4824e1/src/completions/powershell.rs +// +// The generated scripts require PowerShell v5.0+ (which comes Windows 10, but +// can be downloaded separately for windows 7 or 8.1). + +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "strings" + + "github.com/spf13/pflag" +) + +var powerShellCompletionTemplate = `using namespace System.Management.Automation +using namespace System.Management.Automation.Language +Register-ArgumentCompleter -Native -CommandName '%s' -ScriptBlock { + param($wordToComplete, $commandAst, $cursorPosition) + $commandElements = $commandAst.CommandElements + $command = @( + '%s' + for ($i = 1; $i -lt $commandElements.Count; $i++) { + $element = $commandElements[$i] + if ($element -isnot [StringConstantExpressionAst] -or + $element.StringConstantType -ne [StringConstantType]::BareWord -or + $element.Value.StartsWith('-')) { + break + } + $element.Value + } + ) -join ';' + $completions = @(switch ($command) {%s + }) + $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | + Sort-Object -Property ListItemText +}` + +func generatePowerShellSubcommandCases(out io.Writer, cmd *Command, previousCommandName string) { + var cmdName string + if previousCommandName == "" { + cmdName = cmd.Name() + } else { + cmdName = fmt.Sprintf("%s;%s", previousCommandName, cmd.Name()) + } + + fmt.Fprintf(out, "\n '%s' {", cmdName) + + cmd.Flags().VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } + usage := escapeStringForPowerShell(flag.Usage) + if len(flag.Shorthand) > 0 { + fmt.Fprintf(out, "\n [CompletionResult]::new('-%s', '%s', [CompletionResultType]::ParameterName, '%s')", flag.Shorthand, flag.Shorthand, usage) + } + fmt.Fprintf(out, "\n [CompletionResult]::new('--%s', '%s', [CompletionResultType]::ParameterName, '%s')", flag.Name, flag.Name, usage) + }) + + for _, subCmd := range cmd.Commands() { + usage := escapeStringForPowerShell(subCmd.Short) + fmt.Fprintf(out, "\n [CompletionResult]::new('%s', '%s', [CompletionResultType]::ParameterValue, '%s')", subCmd.Name(), subCmd.Name(), usage) + } + + fmt.Fprint(out, "\n break\n }") + + for _, subCmd := range cmd.Commands() { + generatePowerShellSubcommandCases(out, subCmd, cmdName) + } +} + +func escapeStringForPowerShell(s string) string { + return strings.Replace(s, "'", "''", -1) +} + +// GenPowerShellCompletion generates PowerShell completion file and writes to the passed writer. +func (c *Command) GenPowerShellCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + + var subCommandCases bytes.Buffer + generatePowerShellSubcommandCases(&subCommandCases, c, "") + fmt.Fprintf(buf, powerShellCompletionTemplate, c.Name(), c.Name(), subCommandCases.String()) + + _, err := buf.WriteTo(w) + return err +} + +// GenPowerShellCompletionFile generates PowerShell completion file. +func (c *Command) GenPowerShellCompletionFile(filename string) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenPowerShellCompletion(outFile) +} diff --git a/vendor/github.com/spf13/cobra/powershell_completions.md b/vendor/github.com/spf13/cobra/powershell_completions.md new file mode 100644 index 000000000..afed80240 --- /dev/null +++ b/vendor/github.com/spf13/cobra/powershell_completions.md @@ -0,0 +1,14 @@ +# Generating PowerShell Completions For Your Own cobra.Command + +Cobra can generate PowerShell completion scripts. Users need PowerShell version 5.0 or above, which comes with Windows 10 and can be downloaded separately for Windows 7 or 8.1. They can then write the completions to a file and source this file from their PowerShell profile, which is referenced by the `$Profile` environment variable. See `Get-Help about_Profiles` for more info about PowerShell profiles. + +# What's supported + +- Completion for subcommands using their `.Short` description +- Completion for non-hidden flags using their `.Name` and `.Shorthand` + +# What's not yet supported + +- Command aliases +- Required, filename or custom flags (they will work like normal flags) +- Custom completion scripts diff --git a/vendor/github.com/spf13/cobra/shell_completions.go b/vendor/github.com/spf13/cobra/shell_completions.go new file mode 100644 index 000000000..ba0af9cb5 --- /dev/null +++ b/vendor/github.com/spf13/cobra/shell_completions.go @@ -0,0 +1,85 @@ +package cobra + +import ( + "github.com/spf13/pflag" +) + +// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, +// and causes your command to report an error if invoked without the flag. +func (c *Command) MarkFlagRequired(name string) error { + return MarkFlagRequired(c.Flags(), name) +} + +// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag if it exists, +// and causes your command to report an error if invoked without the flag. +func (c *Command) MarkPersistentFlagRequired(name string) error { + return MarkFlagRequired(c.PersistentFlags(), name) +} + +// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, +// and causes your command to report an error if invoked without the flag. +func MarkFlagRequired(flags *pflag.FlagSet, name string) error { + return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"}) +} + +// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists. +// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. +func (c *Command) MarkFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.Flags(), name, extensions...) +} + +// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. +// Generated bash autocompletion will call the bash function f for the flag. +func (c *Command) MarkFlagCustom(name string, f string) error { + return MarkFlagCustom(c.Flags(), name, f) +} + +// MarkPersistentFlagFilename instructs the various shell completion +// implementations to limit completions for this persistent flag to the +// specified extensions (patterns). +// +// Shell Completion compatibility matrix: bash, zsh +func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.PersistentFlags(), name, extensions...) +} + +// MarkFlagFilename instructs the various shell completion implementations to +// limit completions for this flag to the specified extensions (patterns). +// +// Shell Completion compatibility matrix: bash, zsh +func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error { + return flags.SetAnnotation(name, BashCompFilenameExt, extensions) +} + +// MarkFlagCustom instructs the various shell completion implementations to +// limit completions for this flag to the specified extensions (patterns). +// +// Shell Completion compatibility matrix: bash, zsh +func MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error { + return flags.SetAnnotation(name, BashCompCustom, []string{f}) +} + +// MarkFlagDirname instructs the various shell completion implementations to +// complete only directories with this named flag. +// +// Shell Completion compatibility matrix: zsh +func (c *Command) MarkFlagDirname(name string) error { + return MarkFlagDirname(c.Flags(), name) +} + +// MarkPersistentFlagDirname instructs the various shell completion +// implementations to complete only directories with this persistent named flag. +// +// Shell Completion compatibility matrix: zsh +func (c *Command) MarkPersistentFlagDirname(name string) error { + return MarkFlagDirname(c.PersistentFlags(), name) +} + +// MarkFlagDirname instructs the various shell completion implementations to +// complete only directories with this specified flag. +// +// Shell Completion compatibility matrix: zsh +func MarkFlagDirname(flags *pflag.FlagSet, name string) error { + zshPattern := "-(/)" + return flags.SetAnnotation(name, zshCompDirname, []string{zshPattern}) +} diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go new file mode 100644 index 000000000..12755482f --- /dev/null +++ b/vendor/github.com/spf13/cobra/zsh_completions.go @@ -0,0 +1,336 @@ +package cobra + +import ( + "encoding/json" + "fmt" + "io" + "os" + "sort" + "strings" + "text/template" + + "github.com/spf13/pflag" +) + +const ( + zshCompArgumentAnnotation = "cobra_annotations_zsh_completion_argument_annotation" + zshCompArgumentFilenameComp = "cobra_annotations_zsh_completion_argument_file_completion" + zshCompArgumentWordComp = "cobra_annotations_zsh_completion_argument_word_completion" + zshCompDirname = "cobra_annotations_zsh_dirname" +) + +var ( + zshCompFuncMap = template.FuncMap{ + "genZshFuncName": zshCompGenFuncName, + "extractFlags": zshCompExtractFlag, + "genFlagEntryForZshArguments": zshCompGenFlagEntryForArguments, + "extractArgsCompletions": zshCompExtractArgumentCompletionHintsForRendering, + } + zshCompletionText = ` +{{/* should accept Command (that contains subcommands) as parameter */}} +{{define "argumentsC" -}} +{{ $cmdPath := genZshFuncName .}} +function {{$cmdPath}} { + local -a commands + + _arguments -C \{{- range extractFlags .}} + {{genFlagEntryForZshArguments .}} \{{- end}} + "1: :->cmnds" \ + "*::arg:->args" + + case $state in + cmnds) + commands=({{range .Commands}}{{if not .Hidden}} + "{{.Name}}:{{.Short}}"{{end}}{{end}} + ) + _describe "command" commands + ;; + esac + + case "$words[1]" in {{- range .Commands}}{{if not .Hidden}} + {{.Name}}) + {{$cmdPath}}_{{.Name}} + ;;{{end}}{{end}} + esac +} +{{range .Commands}}{{if not .Hidden}} +{{template "selectCmdTemplate" .}} +{{- end}}{{end}} +{{- end}} + +{{/* should accept Command without subcommands as parameter */}} +{{define "arguments" -}} +function {{genZshFuncName .}} { +{{" _arguments"}}{{range extractFlags .}} \ + {{genFlagEntryForZshArguments . -}} +{{end}}{{range extractArgsCompletions .}} \ + {{.}}{{end}} +} +{{end}} + +{{/* dispatcher for commands with or without subcommands */}} +{{define "selectCmdTemplate" -}} +{{if .Hidden}}{{/* ignore hidden*/}}{{else -}} +{{if .Commands}}{{template "argumentsC" .}}{{else}}{{template "arguments" .}}{{end}} +{{- end}} +{{- end}} + +{{/* template entry point */}} +{{define "Main" -}} +#compdef _{{.Name}} {{.Name}} + +{{template "selectCmdTemplate" .}} +{{end}} +` +) + +// zshCompArgsAnnotation is used to encode/decode zsh completion for +// arguments to/from Command.Annotations. +type zshCompArgsAnnotation map[int]zshCompArgHint + +type zshCompArgHint struct { + // Indicates the type of the completion to use. One of: + // zshCompArgumentFilenameComp or zshCompArgumentWordComp + Tipe string `json:"type"` + + // A value for the type above (globs for file completion or words) + Options []string `json:"options"` +} + +// GenZshCompletionFile generates zsh completion file. +func (c *Command) GenZshCompletionFile(filename string) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenZshCompletion(outFile) +} + +// GenZshCompletion generates a zsh completion file and writes to the passed +// writer. The completion always run on the root command regardless of the +// command it was called from. +func (c *Command) GenZshCompletion(w io.Writer) error { + tmpl, err := template.New("Main").Funcs(zshCompFuncMap).Parse(zshCompletionText) + if err != nil { + return fmt.Errorf("error creating zsh completion template: %v", err) + } + return tmpl.Execute(w, c.Root()) +} + +// MarkZshCompPositionalArgumentFile marks the specified argument (first +// argument is 1) as completed by file selection. patterns (e.g. "*.txt") are +// optional - if not provided the completion will search for all files. +func (c *Command) MarkZshCompPositionalArgumentFile(argPosition int, patterns ...string) error { + if argPosition < 1 { + return fmt.Errorf("Invalid argument position (%d)", argPosition) + } + annotation, err := c.zshCompGetArgsAnnotations() + if err != nil { + return err + } + if c.zshcompArgsAnnotationnIsDuplicatePosition(annotation, argPosition) { + return fmt.Errorf("Duplicate annotation for positional argument at index %d", argPosition) + } + annotation[argPosition] = zshCompArgHint{ + Tipe: zshCompArgumentFilenameComp, + Options: patterns, + } + return c.zshCompSetArgsAnnotations(annotation) +} + +// MarkZshCompPositionalArgumentWords marks the specified positional argument +// (first argument is 1) as completed by the provided words. At east one word +// must be provided, spaces within words will be offered completion with +// "word\ word". +func (c *Command) MarkZshCompPositionalArgumentWords(argPosition int, words ...string) error { + if argPosition < 1 { + return fmt.Errorf("Invalid argument position (%d)", argPosition) + } + if len(words) == 0 { + return fmt.Errorf("Trying to set empty word list for positional argument %d", argPosition) + } + annotation, err := c.zshCompGetArgsAnnotations() + if err != nil { + return err + } + if c.zshcompArgsAnnotationnIsDuplicatePosition(annotation, argPosition) { + return fmt.Errorf("Duplicate annotation for positional argument at index %d", argPosition) + } + annotation[argPosition] = zshCompArgHint{ + Tipe: zshCompArgumentWordComp, + Options: words, + } + return c.zshCompSetArgsAnnotations(annotation) +} + +func zshCompExtractArgumentCompletionHintsForRendering(c *Command) ([]string, error) { + var result []string + annotation, err := c.zshCompGetArgsAnnotations() + if err != nil { + return nil, err + } + for k, v := range annotation { + s, err := zshCompRenderZshCompArgHint(k, v) + if err != nil { + return nil, err + } + result = append(result, s) + } + if len(c.ValidArgs) > 0 { + if _, positionOneExists := annotation[1]; !positionOneExists { + s, err := zshCompRenderZshCompArgHint(1, zshCompArgHint{ + Tipe: zshCompArgumentWordComp, + Options: c.ValidArgs, + }) + if err != nil { + return nil, err + } + result = append(result, s) + } + } + sort.Strings(result) + return result, nil +} + +func zshCompRenderZshCompArgHint(i int, z zshCompArgHint) (string, error) { + switch t := z.Tipe; t { + case zshCompArgumentFilenameComp: + var globs []string + for _, g := range z.Options { + globs = append(globs, fmt.Sprintf(`-g "%s"`, g)) + } + return fmt.Sprintf(`'%d: :_files %s'`, i, strings.Join(globs, " ")), nil + case zshCompArgumentWordComp: + var words []string + for _, w := range z.Options { + words = append(words, fmt.Sprintf("%q", w)) + } + return fmt.Sprintf(`'%d: :(%s)'`, i, strings.Join(words, " ")), nil + default: + return "", fmt.Errorf("Invalid zsh argument completion annotation: %s", t) + } +} + +func (c *Command) zshcompArgsAnnotationnIsDuplicatePosition(annotation zshCompArgsAnnotation, position int) bool { + _, dup := annotation[position] + return dup +} + +func (c *Command) zshCompGetArgsAnnotations() (zshCompArgsAnnotation, error) { + annotation := make(zshCompArgsAnnotation) + annotationString, ok := c.Annotations[zshCompArgumentAnnotation] + if !ok { + return annotation, nil + } + err := json.Unmarshal([]byte(annotationString), &annotation) + if err != nil { + return annotation, fmt.Errorf("Error unmarshaling zsh argument annotation: %v", err) + } + return annotation, nil +} + +func (c *Command) zshCompSetArgsAnnotations(annotation zshCompArgsAnnotation) error { + jsn, err := json.Marshal(annotation) + if err != nil { + return fmt.Errorf("Error marshaling zsh argument annotation: %v", err) + } + if c.Annotations == nil { + c.Annotations = make(map[string]string) + } + c.Annotations[zshCompArgumentAnnotation] = string(jsn) + return nil +} + +func zshCompGenFuncName(c *Command) string { + if c.HasParent() { + return zshCompGenFuncName(c.Parent()) + "_" + c.Name() + } + return "_" + c.Name() +} + +func zshCompExtractFlag(c *Command) []*pflag.Flag { + var flags []*pflag.Flag + c.LocalFlags().VisitAll(func(f *pflag.Flag) { + if !f.Hidden { + flags = append(flags, f) + } + }) + c.InheritedFlags().VisitAll(func(f *pflag.Flag) { + if !f.Hidden { + flags = append(flags, f) + } + }) + return flags +} + +// zshCompGenFlagEntryForArguments returns an entry that matches _arguments +// zsh-completion parameters. It's too complicated to generate in a template. +func zshCompGenFlagEntryForArguments(f *pflag.Flag) string { + if f.Name == "" || f.Shorthand == "" { + return zshCompGenFlagEntryForSingleOptionFlag(f) + } + return zshCompGenFlagEntryForMultiOptionFlag(f) +} + +func zshCompGenFlagEntryForSingleOptionFlag(f *pflag.Flag) string { + var option, multiMark, extras string + + if zshCompFlagCouldBeSpecifiedMoreThenOnce(f) { + multiMark = "*" + } + + option = "--" + f.Name + if option == "--" { + option = "-" + f.Shorthand + } + extras = zshCompGenFlagEntryExtras(f) + + return fmt.Sprintf(`'%s%s[%s]%s'`, multiMark, option, zshCompQuoteFlagDescription(f.Usage), extras) +} + +func zshCompGenFlagEntryForMultiOptionFlag(f *pflag.Flag) string { + var options, parenMultiMark, curlyMultiMark, extras string + + if zshCompFlagCouldBeSpecifiedMoreThenOnce(f) { + parenMultiMark = "*" + curlyMultiMark = "\\*" + } + + options = fmt.Sprintf(`'(%s-%s %s--%s)'{%s-%s,%s--%s}`, + parenMultiMark, f.Shorthand, parenMultiMark, f.Name, curlyMultiMark, f.Shorthand, curlyMultiMark, f.Name) + extras = zshCompGenFlagEntryExtras(f) + + return fmt.Sprintf(`%s'[%s]%s'`, options, zshCompQuoteFlagDescription(f.Usage), extras) +} + +func zshCompGenFlagEntryExtras(f *pflag.Flag) string { + if f.NoOptDefVal != "" { + return "" + } + + extras := ":" // allow options for flag (even without assistance) + for key, values := range f.Annotations { + switch key { + case zshCompDirname: + extras = fmt.Sprintf(":filename:_files -g %q", values[0]) + case BashCompFilenameExt: + extras = ":filename:_files" + for _, pattern := range values { + extras = extras + fmt.Sprintf(` -g "%s"`, pattern) + } + } + } + + return extras +} + +func zshCompFlagCouldBeSpecifiedMoreThenOnce(f *pflag.Flag) bool { + return strings.Contains(f.Value.Type(), "Slice") || + strings.Contains(f.Value.Type(), "Array") +} + +func zshCompQuoteFlagDescription(s string) string { + return strings.Replace(s, "'", `'\''`, -1) +} diff --git a/vendor/github.com/spf13/cobra/zsh_completions.md b/vendor/github.com/spf13/cobra/zsh_completions.md new file mode 100644 index 000000000..df9c2eac9 --- /dev/null +++ b/vendor/github.com/spf13/cobra/zsh_completions.md @@ -0,0 +1,39 @@ +## Generating Zsh Completion for your cobra.Command + +Cobra supports native Zsh completion generated from the root `cobra.Command`. +The generated completion script should be put somewhere in your `$fpath` named +`_`. + +### What's Supported + +* Completion for all non-hidden subcommands using their `.Short` description. +* Completion for all non-hidden flags using the following rules: + * Filename completion works by marking the flag with `cmd.MarkFlagFilename...` + family of commands. + * The requirement for argument to the flag is decided by the `.NoOptDefVal` + flag value - if it's empty then completion will expect an argument. + * Flags of one of the various `*Array` and `*Slice` types supports multiple + specifications (with or without argument depending on the specific type). +* Completion of positional arguments using the following rules: + * Argument position for all options below starts at `1`. If argument position + `0` is requested it will raise an error. + * Use `command.MarkZshCompPositionalArgumentFile` to complete filenames. Glob + patterns (e.g. `"*.log"`) are optional - if not specified it will offer to + complete all file types. + * Use `command.MarkZshCompPositionalArgumentWords` to offer specific words for + completion. At least one word is required. + * It's possible to specify completion for some arguments and leave some + unspecified (e.g. offer words for second argument but nothing for first + argument). This will cause no completion for first argument but words + completion for second argument. + * If no argument completion was specified for 1st argument (but optionally was + specified for 2nd) and the command has `ValidArgs` it will be used as + completion options for 1st argument. + * Argument completions only offered for commands with no subcommands. + +### What's not yet Supported + +* Custom completion scripts are not supported yet (We should probably create zsh + specific one, doesn't make sense to re-use the bash one as the functions will + be different). +* Whatever other feature you're looking for and doesn't exist :) diff --git a/vendor/github.com/spf13/jwalterweatherman/.gitignore b/vendor/github.com/spf13/jwalterweatherman/.gitignore new file mode 100644 index 000000000..00268614f --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/spf13/jwalterweatherman/LICENSE b/vendor/github.com/spf13/jwalterweatherman/LICENSE new file mode 100644 index 000000000..4527efb9c --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Steve Francia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/spf13/jwalterweatherman/README.md b/vendor/github.com/spf13/jwalterweatherman/README.md new file mode 100644 index 000000000..932a23fc6 --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/README.md @@ -0,0 +1,148 @@ +jWalterWeatherman +================= + +Seamless printing to the terminal (stdout) and logging to a io.Writer +(file) that’s as easy to use as fmt.Println. + +![and_that__s_why_you_always_leave_a_note_by_jonnyetc-d57q7um](https://cloud.githubusercontent.com/assets/173412/11002937/ccd01654-847d-11e5-828e-12ebaf582eaf.jpg) +Graphic by [JonnyEtc](http://jonnyetc.deviantart.com/art/And-That-s-Why-You-Always-Leave-a-Note-315311422) + +JWW is primarily a wrapper around the excellent standard log library. It +provides a few advantages over using the standard log library alone. + +1. Ready to go out of the box. +2. One library for both printing to the terminal and logging (to files). +3. Really easy to log to either a temp file or a file you specify. + + +I really wanted a very straightforward library that could seamlessly do +the following things. + +1. Replace all the println, printf, etc statements thoughout my code with + something more useful +2. Allow the user to easily control what levels are printed to stdout +3. Allow the user to easily control what levels are logged +4. Provide an easy mechanism (like fmt.Println) to print info to the user + which can be easily logged as well +5. Due to 2 & 3 provide easy verbose mode for output and logs +6. Not have any unnecessary initialization cruft. Just use it. + +# Usage + +## Step 1. Use it +Put calls throughout your source based on type of feedback. +No initialization or setup needs to happen. Just start calling things. + +Available Loggers are: + + * TRACE + * DEBUG + * INFO + * WARN + * ERROR + * CRITICAL + * FATAL + +These each are loggers based on the log standard library and follow the +standard usage. Eg. + +```go + import ( + jww "github.com/spf13/jwalterweatherman" + ) + + ... + + if err != nil { + + // This is a pretty serious error and the user should know about + // it. It will be printed to the terminal as well as logged under the + // default thresholds. + + jww.ERROR.Println(err) + } + + if err2 != nil { + // This error isn’t going to materially change the behavior of the + // application, but it’s something that may not be what the user + // expects. Under the default thresholds, Warn will be logged, but + // not printed to the terminal. + + jww.WARN.Println(err2) + } + + // Information that’s relevant to what’s happening, but not very + // important for the user. Under the default thresholds this will be + // discarded. + + jww.INFO.Printf("information %q", response) + +``` + +NOTE: You can also use the library in a non-global setting by creating an instance of a Notebook: + +```go +notepad = jww.NewNotepad(jww.LevelInfo, jww.LevelTrace, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) +notepad.WARN.Println("Some warning"") +``` + +_Why 7 levels?_ + +Maybe you think that 7 levels are too much for any application... and you +are probably correct. Just because there are seven levels doesn’t mean +that you should be using all 7 levels. Pick the right set for your needs. +Remember they only have to mean something to your project. + +## Step 2. Optionally configure JWW + +Under the default thresholds : + + * Debug, Trace & Info goto /dev/null + * Warn and above is logged (when a log file/io.Writer is provided) + * Error and above is printed to the terminal (stdout) + +### Changing the thresholds + +The threshold can be changed at any time, but will only affect calls that +execute after the change was made. + +This is very useful if your application has a verbose mode. Of course you +can decide what verbose means to you or even have multiple levels of +verbosity. + + +```go + import ( + jww "github.com/spf13/jwalterweatherman" + ) + + if Verbose { + jww.SetLogThreshold(jww.LevelTrace) + jww.SetStdoutThreshold(jww.LevelInfo) + } +``` + +Note that JWW's own internal output uses log levels as well, so set the log +level before making any other calls if you want to see what it's up to. + + +### Setting a log file + +JWW can log to any `io.Writer`: + + +```go + + jww.SetLogOutput(customWriter) + +``` + + +# More information + +This is an early release. I’ve been using it for a while and this is the +third interface I’ve tried. I like this one pretty well, but no guarantees +that it won’t change a bit. + +I wrote this for use in [hugo](https://gohugo.io). If you are looking +for a static website engine that’s super fast please checkout Hugo. diff --git a/vendor/github.com/spf13/jwalterweatherman/default_notepad.go b/vendor/github.com/spf13/jwalterweatherman/default_notepad.go new file mode 100644 index 000000000..bcb763403 --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/default_notepad.go @@ -0,0 +1,113 @@ +// Copyright © 2016 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "io" + "io/ioutil" + "log" + "os" +) + +var ( + TRACE *log.Logger + DEBUG *log.Logger + INFO *log.Logger + WARN *log.Logger + ERROR *log.Logger + CRITICAL *log.Logger + FATAL *log.Logger + + LOG *log.Logger + FEEDBACK *Feedback + + defaultNotepad *Notepad +) + +func reloadDefaultNotepad() { + TRACE = defaultNotepad.TRACE + DEBUG = defaultNotepad.DEBUG + INFO = defaultNotepad.INFO + WARN = defaultNotepad.WARN + ERROR = defaultNotepad.ERROR + CRITICAL = defaultNotepad.CRITICAL + FATAL = defaultNotepad.FATAL + + LOG = defaultNotepad.LOG + FEEDBACK = defaultNotepad.FEEDBACK +} + +func init() { + defaultNotepad = NewNotepad(LevelError, LevelWarn, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) + reloadDefaultNotepad() +} + +// SetLogThreshold set the log threshold for the default notepad. Trace by default. +func SetLogThreshold(threshold Threshold) { + defaultNotepad.SetLogThreshold(threshold) + reloadDefaultNotepad() +} + +// SetLogOutput set the log output for the default notepad. Discarded by default. +func SetLogOutput(handle io.Writer) { + defaultNotepad.SetLogOutput(handle) + reloadDefaultNotepad() +} + +// SetStdoutThreshold set the standard output threshold for the default notepad. +// Info by default. +func SetStdoutThreshold(threshold Threshold) { + defaultNotepad.SetStdoutThreshold(threshold) + reloadDefaultNotepad() +} + +// SetPrefix set the prefix for the default logger. Empty by default. +func SetPrefix(prefix string) { + defaultNotepad.SetPrefix(prefix) + reloadDefaultNotepad() +} + +// SetFlags set the flags for the default logger. "log.Ldate | log.Ltime" by default. +func SetFlags(flags int) { + defaultNotepad.SetFlags(flags) + reloadDefaultNotepad() +} + +// Level returns the current global log threshold. +func LogThreshold() Threshold { + return defaultNotepad.logThreshold +} + +// Level returns the current global output threshold. +func StdoutThreshold() Threshold { + return defaultNotepad.stdoutThreshold +} + +// GetStdoutThreshold returns the defined Treshold for the log logger. +func GetLogThreshold() Threshold { + return defaultNotepad.GetLogThreshold() +} + +// GetStdoutThreshold returns the Treshold for the stdout logger. +func GetStdoutThreshold() Threshold { + return defaultNotepad.GetStdoutThreshold() +} + +// LogCountForLevel returns the number of log invocations for a given threshold. +func LogCountForLevel(l Threshold) uint64 { + return defaultNotepad.LogCountForLevel(l) +} + +// LogCountForLevelsGreaterThanorEqualTo returns the number of log invocations +// greater than or equal to a given threshold. +func LogCountForLevelsGreaterThanorEqualTo(threshold Threshold) uint64 { + return defaultNotepad.LogCountForLevelsGreaterThanorEqualTo(threshold) +} + +// ResetLogCounters resets the invocation counters for all levels. +func ResetLogCounters() { + defaultNotepad.ResetLogCounters() +} diff --git a/vendor/github.com/spf13/jwalterweatherman/go.mod b/vendor/github.com/spf13/jwalterweatherman/go.mod new file mode 100644 index 000000000..bce549c04 --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/go.mod @@ -0,0 +1 @@ +module github.com/spf13/jwalterweatherman diff --git a/vendor/github.com/spf13/jwalterweatherman/log_counter.go b/vendor/github.com/spf13/jwalterweatherman/log_counter.go new file mode 100644 index 000000000..11423ac41 --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/log_counter.go @@ -0,0 +1,55 @@ +// Copyright © 2016 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "sync/atomic" +) + +type logCounter struct { + counter uint64 +} + +func (c *logCounter) incr() { + atomic.AddUint64(&c.counter, 1) +} + +func (c *logCounter) resetCounter() { + atomic.StoreUint64(&c.counter, 0) +} + +func (c *logCounter) getCount() uint64 { + return atomic.LoadUint64(&c.counter) +} + +func (c *logCounter) Write(p []byte) (n int, err error) { + c.incr() + return len(p), nil +} + +// LogCountForLevel returns the number of log invocations for a given threshold. +func (n *Notepad) LogCountForLevel(l Threshold) uint64 { + return n.logCounters[l].getCount() +} + +// LogCountForLevelsGreaterThanorEqualTo returns the number of log invocations +// greater than or equal to a given threshold. +func (n *Notepad) LogCountForLevelsGreaterThanorEqualTo(threshold Threshold) uint64 { + var cnt uint64 + + for i := int(threshold); i < len(n.logCounters); i++ { + cnt += n.LogCountForLevel(Threshold(i)) + } + + return cnt +} + +// ResetLogCounters resets the invocation counters for all levels. +func (n *Notepad) ResetLogCounters() { + for _, np := range n.logCounters { + np.resetCounter() + } +} diff --git a/vendor/github.com/spf13/jwalterweatherman/notepad.go b/vendor/github.com/spf13/jwalterweatherman/notepad.go new file mode 100644 index 000000000..ae5aaf711 --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/notepad.go @@ -0,0 +1,194 @@ +// Copyright © 2016 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "fmt" + "io" + "log" +) + +type Threshold int + +func (t Threshold) String() string { + return prefixes[t] +} + +const ( + LevelTrace Threshold = iota + LevelDebug + LevelInfo + LevelWarn + LevelError + LevelCritical + LevelFatal +) + +var prefixes map[Threshold]string = map[Threshold]string{ + LevelTrace: "TRACE", + LevelDebug: "DEBUG", + LevelInfo: "INFO", + LevelWarn: "WARN", + LevelError: "ERROR", + LevelCritical: "CRITICAL", + LevelFatal: "FATAL", +} + +// Notepad is where you leave a note! +type Notepad struct { + TRACE *log.Logger + DEBUG *log.Logger + INFO *log.Logger + WARN *log.Logger + ERROR *log.Logger + CRITICAL *log.Logger + FATAL *log.Logger + + LOG *log.Logger + FEEDBACK *Feedback + + loggers [7]**log.Logger + logHandle io.Writer + outHandle io.Writer + logThreshold Threshold + stdoutThreshold Threshold + prefix string + flags int + + // One per Threshold + logCounters [7]*logCounter +} + +// NewNotepad create a new notepad. +func NewNotepad(outThreshold Threshold, logThreshold Threshold, outHandle, logHandle io.Writer, prefix string, flags int) *Notepad { + n := &Notepad{} + + n.loggers = [7]**log.Logger{&n.TRACE, &n.DEBUG, &n.INFO, &n.WARN, &n.ERROR, &n.CRITICAL, &n.FATAL} + n.outHandle = outHandle + n.logHandle = logHandle + n.stdoutThreshold = outThreshold + n.logThreshold = logThreshold + + if len(prefix) != 0 { + n.prefix = "[" + prefix + "] " + } else { + n.prefix = "" + } + + n.flags = flags + + n.LOG = log.New(n.logHandle, + "LOG: ", + n.flags) + n.FEEDBACK = &Feedback{out: log.New(outHandle, "", 0), log: n.LOG} + + n.init() + return n +} + +// init creates the loggers for each level depending on the notepad thresholds. +func (n *Notepad) init() { + logAndOut := io.MultiWriter(n.outHandle, n.logHandle) + + for t, logger := range n.loggers { + threshold := Threshold(t) + counter := &logCounter{} + n.logCounters[t] = counter + prefix := n.prefix + threshold.String() + " " + + switch { + case threshold >= n.logThreshold && threshold >= n.stdoutThreshold: + *logger = log.New(io.MultiWriter(counter, logAndOut), prefix, n.flags) + + case threshold >= n.logThreshold: + *logger = log.New(io.MultiWriter(counter, n.logHandle), prefix, n.flags) + + case threshold >= n.stdoutThreshold: + *logger = log.New(io.MultiWriter(counter, n.outHandle), prefix, n.flags) + + default: + // counter doesn't care about prefix and flags, so don't use them + // for performance. + *logger = log.New(counter, "", 0) + } + } +} + +// SetLogThreshold changes the threshold above which messages are written to the +// log file. +func (n *Notepad) SetLogThreshold(threshold Threshold) { + n.logThreshold = threshold + n.init() +} + +// SetLogOutput changes the file where log messages are written. +func (n *Notepad) SetLogOutput(handle io.Writer) { + n.logHandle = handle + n.init() +} + +// GetStdoutThreshold returns the defined Treshold for the log logger. +func (n *Notepad) GetLogThreshold() Threshold { + return n.logThreshold +} + +// SetStdoutThreshold changes the threshold above which messages are written to the +// standard output. +func (n *Notepad) SetStdoutThreshold(threshold Threshold) { + n.stdoutThreshold = threshold + n.init() +} + +// GetStdoutThreshold returns the Treshold for the stdout logger. +func (n *Notepad) GetStdoutThreshold() Threshold { + return n.stdoutThreshold +} + +// SetPrefix changes the prefix used by the notepad. Prefixes are displayed between +// brackets at the beginning of the line. An empty prefix won't be displayed at all. +func (n *Notepad) SetPrefix(prefix string) { + if len(prefix) != 0 { + n.prefix = "[" + prefix + "] " + } else { + n.prefix = "" + } + n.init() +} + +// SetFlags choose which flags the logger will display (after prefix and message +// level). See the package log for more informations on this. +func (n *Notepad) SetFlags(flags int) { + n.flags = flags + n.init() +} + +// Feedback writes plainly to the outHandle while +// logging with the standard extra information (date, file, etc). +type Feedback struct { + out *log.Logger + log *log.Logger +} + +func (fb *Feedback) Println(v ...interface{}) { + fb.output(fmt.Sprintln(v...)) +} + +func (fb *Feedback) Printf(format string, v ...interface{}) { + fb.output(fmt.Sprintf(format, v...)) +} + +func (fb *Feedback) Print(v ...interface{}) { + fb.output(fmt.Sprint(v...)) +} + +func (fb *Feedback) output(s string) { + if fb.out != nil { + fb.out.Output(2, s) + } + if fb.log != nil { + fb.log.Output(2, s) + } +} diff --git a/vendor/github.com/spf13/pflag/.gitignore b/vendor/github.com/spf13/pflag/.gitignore new file mode 100644 index 000000000..c3da29013 --- /dev/null +++ b/vendor/github.com/spf13/pflag/.gitignore @@ -0,0 +1,2 @@ +.idea/* + diff --git a/vendor/github.com/spf13/pflag/.travis.yml b/vendor/github.com/spf13/pflag/.travis.yml new file mode 100644 index 000000000..00d04cb9b --- /dev/null +++ b/vendor/github.com/spf13/pflag/.travis.yml @@ -0,0 +1,22 @@ +sudo: false + +language: go + +go: + - 1.9.x + - 1.10.x + - 1.11.x + - tip + +matrix: + allow_failures: + - go: tip + +install: + - go get golang.org/x/lint/golint + - export PATH=$GOPATH/bin:$PATH + - go install ./... + +script: + - verify/all.sh -v + - go test ./... diff --git a/vendor/github.com/spf13/pflag/LICENSE b/vendor/github.com/spf13/pflag/LICENSE new file mode 100644 index 000000000..63ed1cfea --- /dev/null +++ b/vendor/github.com/spf13/pflag/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 Alex Ogier. All rights reserved. +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. diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md new file mode 100644 index 000000000..7eacc5bdb --- /dev/null +++ b/vendor/github.com/spf13/pflag/README.md @@ -0,0 +1,296 @@ +[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag) +[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag) + +## Description + +pflag is a drop-in replacement for Go's flag package, implementing +POSIX/GNU-style --flags. + +pflag is compatible with the [GNU extensions to the POSIX recommendations +for command-line options][1]. For a more precise description, see the +"Command-line flag syntax" section below. + +[1]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html + +pflag is available under the same style of BSD license as the Go language, +which can be found in the LICENSE file. + +## Installation + +pflag is available using the standard `go get` command. + +Install by running: + + go get github.com/spf13/pflag + +Run tests by running: + + go test github.com/spf13/pflag + +## Usage + +pflag is a drop-in replacement of Go's native flag package. If you import +pflag under the name "flag" then all code should continue to function +with no changes. + +``` go +import flag "github.com/spf13/pflag" +``` + +There is one exception to this: if you directly instantiate the Flag struct +there is one more field "Shorthand" that you will need to set. +Most code never instantiates this struct directly, and instead uses +functions such as String(), BoolVar(), and Var(), and is therefore +unaffected. + +Define flags using flag.String(), Bool(), Int(), etc. + +This declares an integer flag, -flagname, stored in the pointer ip, with type *int. + +``` go +var ip *int = flag.Int("flagname", 1234, "help message for flagname") +``` + +If you like, you can bind the flag to a variable using the Var() functions. + +``` go +var flagvar int +func init() { + flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") +} +``` + +Or you can create custom flags that satisfy the Value interface (with +pointer receivers) and couple them to flag parsing by + +``` go +flag.Var(&flagVal, "name", "help message for flagname") +``` + +For such flags, the default value is just the initial value of the variable. + +After all flags are defined, call + +``` go +flag.Parse() +``` + +to parse the command line into the defined flags. + +Flags may then be used directly. If you're using the flags themselves, +they are all pointers; if you bind to variables, they're values. + +``` go +fmt.Println("ip has value ", *ip) +fmt.Println("flagvar has value ", flagvar) +``` + +There are helper functions available to get the value stored in a Flag if you have a FlagSet but find +it difficult to keep up with all of the pointers in your code. +If you have a pflag.FlagSet with a flag called 'flagname' of type int you +can use GetInt() to get the int value. But notice that 'flagname' must exist +and it must be an int. GetString("flagname") will fail. + +``` go +i, err := flagset.GetInt("flagname") +``` + +After parsing, the arguments after the flag are available as the +slice flag.Args() or individually as flag.Arg(i). +The arguments are indexed from 0 through flag.NArg()-1. + +The pflag package also defines some new functions that are not in flag, +that give one-letter shorthands for flags. You can use these by appending +'P' to the name of any function that defines a flag. + +``` go +var ip = flag.IntP("flagname", "f", 1234, "help message") +var flagvar bool +func init() { + flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") +} +flag.VarP(&flagVal, "varname", "v", "help message") +``` + +Shorthand letters can be used with single dashes on the command line. +Boolean shorthand flags can be combined with other shorthand flags. + +The default set of command-line flags is controlled by +top-level functions. The FlagSet type allows one to define +independent sets of flags, such as to implement subcommands +in a command-line interface. The methods of FlagSet are +analogous to the top-level functions for the command-line +flag set. + +## Setting no option default values for flags + +After you create a flag it is possible to set the pflag.NoOptDefVal for +the given flag. Doing this changes the meaning of the flag slightly. If +a flag has a NoOptDefVal and the flag is set on the command line without +an option the flag will be set to the NoOptDefVal. For example given: + +``` go +var ip = flag.IntP("flagname", "f", 1234, "help message") +flag.Lookup("flagname").NoOptDefVal = "4321" +``` + +Would result in something like + +| Parsed Arguments | Resulting Value | +| ------------- | ------------- | +| --flagname=1357 | ip=1357 | +| --flagname | ip=4321 | +| [nothing] | ip=1234 | + +## Command line flag syntax + +``` +--flag // boolean flags, or flags with no option default values +--flag x // only on flags without a default value +--flag=x +``` + +Unlike the flag package, a single dash before an option means something +different than a double dash. Single dashes signify a series of shorthand +letters for flags. All but the last shorthand letter must be boolean flags +or a flag with a default value + +``` +// boolean or flags where the 'no option default value' is set +-f +-f=true +-abc +but +-b true is INVALID + +// non-boolean and flags without a 'no option default value' +-n 1234 +-n=1234 +-n1234 + +// mixed +-abcs "hello" +-absd="hello" +-abcs1234 +``` + +Flag parsing stops after the terminator "--". Unlike the flag package, +flags can be interspersed with arguments anywhere on the command line +before this terminator. + +Integer flags accept 1234, 0664, 0x1234 and may be negative. +Boolean flags (in their long form) accept 1, 0, t, f, true, false, +TRUE, FALSE, True, False. +Duration flags accept any input valid for time.ParseDuration. + +## Mutating or "Normalizing" Flag names + +It is possible to set a custom flag name 'normalization function.' It allows flag names to be mutated both when created in the code and when used on the command line to some 'normalized' form. The 'normalized' form is used for comparison. Two examples of using the custom normalization func follow. + +**Example #1**: You want -, _, and . in flags to compare the same. aka --my-flag == --my_flag == --my.flag + +``` go +func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName { + from := []string{"-", "_"} + to := "." + for _, sep := range from { + name = strings.Replace(name, sep, to, -1) + } + return pflag.NormalizedName(name) +} + +myFlagSet.SetNormalizeFunc(wordSepNormalizeFunc) +``` + +**Example #2**: You want to alias two flags. aka --old-flag-name == --new-flag-name + +``` go +func aliasNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName { + switch name { + case "old-flag-name": + name = "new-flag-name" + break + } + return pflag.NormalizedName(name) +} + +myFlagSet.SetNormalizeFunc(aliasNormalizeFunc) +``` + +## Deprecating a flag or its shorthand +It is possible to deprecate a flag, or just its shorthand. Deprecating a flag/shorthand hides it from help text and prints a usage message when the deprecated flag/shorthand is used. + +**Example #1**: You want to deprecate a flag named "badflag" as well as inform the users what flag they should use instead. +```go +// deprecate a flag by specifying its name and a usage message +flags.MarkDeprecated("badflag", "please use --good-flag instead") +``` +This hides "badflag" from help text, and prints `Flag --badflag has been deprecated, please use --good-flag instead` when "badflag" is used. + +**Example #2**: You want to keep a flag name "noshorthandflag" but deprecate its shortname "n". +```go +// deprecate a flag shorthand by specifying its flag name and a usage message +flags.MarkShorthandDeprecated("noshorthandflag", "please use --noshorthandflag only") +``` +This hides the shortname "n" from help text, and prints `Flag shorthand -n has been deprecated, please use --noshorthandflag only` when the shorthand "n" is used. + +Note that usage message is essential here, and it should not be empty. + +## Hidden flags +It is possible to mark a flag as hidden, meaning it will still function as normal, however will not show up in usage/help text. + +**Example**: You have a flag named "secretFlag" that you need for internal use only and don't want it showing up in help text, or for its usage text to be available. +```go +// hide a flag by specifying its name +flags.MarkHidden("secretFlag") +``` + +## Disable sorting of flags +`pflag` allows you to disable sorting of flags for help and usage message. + +**Example**: +```go +flags.BoolP("verbose", "v", false, "verbose output") +flags.String("coolflag", "yeaah", "it's really cool flag") +flags.Int("usefulflag", 777, "sometimes it's very useful") +flags.SortFlags = false +flags.PrintDefaults() +``` +**Output**: +``` + -v, --verbose verbose output + --coolflag string it's really cool flag (default "yeaah") + --usefulflag int sometimes it's very useful (default 777) +``` + + +## Supporting Go flags when using pflag +In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary +to support flags defined by third-party dependencies (e.g. `golang/glog`). + +**Example**: You want to add the Go flags to the `CommandLine` flagset +```go +import ( + goflag "flag" + flag "github.com/spf13/pflag" +) + +var ip *int = flag.Int("flagname", 1234, "help message for flagname") + +func main() { + flag.CommandLine.AddGoFlagSet(goflag.CommandLine) + flag.Parse() +} +``` + +## More info + +You can see the full reference documentation of the pflag package +[at godoc.org][3], or through go's standard documentation system by +running `godoc -http=:6060` and browsing to +[http://localhost:6060/pkg/github.com/spf13/pflag][2] after +installation. + +[2]: http://localhost:6060/pkg/github.com/spf13/pflag +[3]: http://godoc.org/github.com/spf13/pflag diff --git a/vendor/github.com/spf13/pflag/bool.go b/vendor/github.com/spf13/pflag/bool.go new file mode 100644 index 000000000..c4c5c0bfd --- /dev/null +++ b/vendor/github.com/spf13/pflag/bool.go @@ -0,0 +1,94 @@ +package pflag + +import "strconv" + +// optional interface to indicate boolean flags that can be +// supplied without "=value" text +type boolFlag interface { + Value + IsBoolFlag() bool +} + +// -- bool Value +type boolValue bool + +func newBoolValue(val bool, p *bool) *boolValue { + *p = val + return (*boolValue)(p) +} + +func (b *boolValue) Set(s string) error { + v, err := strconv.ParseBool(s) + *b = boolValue(v) + return err +} + +func (b *boolValue) Type() string { + return "bool" +} + +func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) } + +func (b *boolValue) IsBoolFlag() bool { return true } + +func boolConv(sval string) (interface{}, error) { + return strconv.ParseBool(sval) +} + +// GetBool return the bool value of a flag with the given name +func (f *FlagSet) GetBool(name string) (bool, error) { + val, err := f.getFlagType(name, "bool", boolConv) + if err != nil { + return false, err + } + return val.(bool), nil +} + +// BoolVar defines a bool flag with specified name, default value, and usage string. +// The argument p points to a bool variable in which to store the value of the flag. +func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) { + f.BoolVarP(p, name, "", value, usage) +} + +// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolVarP(p *bool, name, shorthand string, value bool, usage string) { + flag := f.VarPF(newBoolValue(value, p), name, shorthand, usage) + flag.NoOptDefVal = "true" +} + +// BoolVar defines a bool flag with specified name, default value, and usage string. +// The argument p points to a bool variable in which to store the value of the flag. +func BoolVar(p *bool, name string, value bool, usage string) { + BoolVarP(p, name, "", value, usage) +} + +// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash. +func BoolVarP(p *bool, name, shorthand string, value bool, usage string) { + flag := CommandLine.VarPF(newBoolValue(value, p), name, shorthand, usage) + flag.NoOptDefVal = "true" +} + +// Bool defines a bool flag with specified name, default value, and usage string. +// The return value is the address of a bool variable that stores the value of the flag. +func (f *FlagSet) Bool(name string, value bool, usage string) *bool { + return f.BoolP(name, "", value, usage) +} + +// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolP(name, shorthand string, value bool, usage string) *bool { + p := new(bool) + f.BoolVarP(p, name, shorthand, value, usage) + return p +} + +// Bool defines a bool flag with specified name, default value, and usage string. +// The return value is the address of a bool variable that stores the value of the flag. +func Bool(name string, value bool, usage string) *bool { + return BoolP(name, "", value, usage) +} + +// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash. +func BoolP(name, shorthand string, value bool, usage string) *bool { + b := CommandLine.BoolP(name, shorthand, value, usage) + return b +} diff --git a/vendor/github.com/spf13/pflag/bool_slice.go b/vendor/github.com/spf13/pflag/bool_slice.go new file mode 100644 index 000000000..3731370d6 --- /dev/null +++ b/vendor/github.com/spf13/pflag/bool_slice.go @@ -0,0 +1,185 @@ +package pflag + +import ( + "io" + "strconv" + "strings" +) + +// -- boolSlice Value +type boolSliceValue struct { + value *[]bool + changed bool +} + +func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue { + bsv := new(boolSliceValue) + bsv.value = p + *bsv.value = val + return bsv +} + +// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag. +// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended. +func (s *boolSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + boolStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse boolean values into slice + out := make([]bool, 0, len(boolStrSlice)) + for _, boolStr := range boolStrSlice { + b, err := strconv.ParseBool(strings.TrimSpace(boolStr)) + if err != nil { + return err + } + out = append(out, b) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *boolSliceValue) Type() string { + return "boolSlice" +} + +// String defines a "native" format for this boolean slice flag value. +func (s *boolSliceValue) String() string { + + boolStrSlice := make([]string, len(*s.value)) + for i, b := range *s.value { + boolStrSlice[i] = strconv.FormatBool(b) + } + + out, _ := writeAsCSV(boolStrSlice) + + return "[" + out + "]" +} + +func (s *boolSliceValue) fromString(val string) (bool, error) { + return strconv.ParseBool(val) +} + +func (s *boolSliceValue) toString(val bool) string { + return strconv.FormatBool(val) +} + +func (s *boolSliceValue) Append(val string) error { + i, err := s.fromString(val) + if err != nil { + return err + } + *s.value = append(*s.value, i) + return nil +} + +func (s *boolSliceValue) Replace(val []string) error { + out := make([]bool, len(val)) + for i, d := range val { + var err error + out[i], err = s.fromString(d) + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *boolSliceValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = s.toString(d) + } + return out +} + +func boolSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []bool{}, nil + } + ss := strings.Split(val, ",") + out := make([]bool, len(ss)) + for i, t := range ss { + var err error + out[i], err = strconv.ParseBool(t) + if err != nil { + return nil, err + } + } + return out, nil +} + +// GetBoolSlice returns the []bool value of a flag with the given name. +func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) { + val, err := f.getFlagType(name, "boolSlice", boolSliceConv) + if err != nil { + return []bool{}, err + } + return val.([]bool), nil +} + +// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) { + f.VarP(newBoolSliceValue(value, p), name, "", usage) +} + +// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) { + f.VarP(newBoolSliceValue(value, p), name, shorthand, usage) +} + +// BoolSliceVar defines a []bool flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func BoolSliceVar(p *[]bool, name string, value []bool, usage string) { + CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage) +} + +// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash. +func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) { + CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage) +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool { + p := []bool{} + f.BoolSliceVarP(&p, name, "", value, usage) + return &p +} + +// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool { + p := []bool{} + f.BoolSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func BoolSlice(name string, value []bool, usage string) *[]bool { + return CommandLine.BoolSliceP(name, "", value, usage) +} + +// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash. +func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool { + return CommandLine.BoolSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/bytes.go b/vendor/github.com/spf13/pflag/bytes.go new file mode 100644 index 000000000..67d530457 --- /dev/null +++ b/vendor/github.com/spf13/pflag/bytes.go @@ -0,0 +1,209 @@ +package pflag + +import ( + "encoding/base64" + "encoding/hex" + "fmt" + "strings" +) + +// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded +type bytesHexValue []byte + +// String implements pflag.Value.String. +func (bytesHex bytesHexValue) String() string { + return fmt.Sprintf("%X", []byte(bytesHex)) +} + +// Set implements pflag.Value.Set. +func (bytesHex *bytesHexValue) Set(value string) error { + bin, err := hex.DecodeString(strings.TrimSpace(value)) + + if err != nil { + return err + } + + *bytesHex = bin + + return nil +} + +// Type implements pflag.Value.Type. +func (*bytesHexValue) Type() string { + return "bytesHex" +} + +func newBytesHexValue(val []byte, p *[]byte) *bytesHexValue { + *p = val + return (*bytesHexValue)(p) +} + +func bytesHexConv(sval string) (interface{}, error) { + + bin, err := hex.DecodeString(sval) + + if err == nil { + return bin, nil + } + + return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err) +} + +// GetBytesHex return the []byte value of a flag with the given name +func (f *FlagSet) GetBytesHex(name string) ([]byte, error) { + val, err := f.getFlagType(name, "bytesHex", bytesHexConv) + + if err != nil { + return []byte{}, err + } + + return val.([]byte), nil +} + +// BytesHexVar defines an []byte flag with specified name, default value, and usage string. +// The argument p points to an []byte variable in which to store the value of the flag. +func (f *FlagSet) BytesHexVar(p *[]byte, name string, value []byte, usage string) { + f.VarP(newBytesHexValue(value, p), name, "", usage) +} + +// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) { + f.VarP(newBytesHexValue(value, p), name, shorthand, usage) +} + +// BytesHexVar defines an []byte flag with specified name, default value, and usage string. +// The argument p points to an []byte variable in which to store the value of the flag. +func BytesHexVar(p *[]byte, name string, value []byte, usage string) { + CommandLine.VarP(newBytesHexValue(value, p), name, "", usage) +} + +// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash. +func BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) { + CommandLine.VarP(newBytesHexValue(value, p), name, shorthand, usage) +} + +// BytesHex defines an []byte flag with specified name, default value, and usage string. +// The return value is the address of an []byte variable that stores the value of the flag. +func (f *FlagSet) BytesHex(name string, value []byte, usage string) *[]byte { + p := new([]byte) + f.BytesHexVarP(p, name, "", value, usage) + return p +} + +// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BytesHexP(name, shorthand string, value []byte, usage string) *[]byte { + p := new([]byte) + f.BytesHexVarP(p, name, shorthand, value, usage) + return p +} + +// BytesHex defines an []byte flag with specified name, default value, and usage string. +// The return value is the address of an []byte variable that stores the value of the flag. +func BytesHex(name string, value []byte, usage string) *[]byte { + return CommandLine.BytesHexP(name, "", value, usage) +} + +// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash. +func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte { + return CommandLine.BytesHexP(name, shorthand, value, usage) +} + +// BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded +type bytesBase64Value []byte + +// String implements pflag.Value.String. +func (bytesBase64 bytesBase64Value) String() string { + return base64.StdEncoding.EncodeToString([]byte(bytesBase64)) +} + +// Set implements pflag.Value.Set. +func (bytesBase64 *bytesBase64Value) Set(value string) error { + bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value)) + + if err != nil { + return err + } + + *bytesBase64 = bin + + return nil +} + +// Type implements pflag.Value.Type. +func (*bytesBase64Value) Type() string { + return "bytesBase64" +} + +func newBytesBase64Value(val []byte, p *[]byte) *bytesBase64Value { + *p = val + return (*bytesBase64Value)(p) +} + +func bytesBase64ValueConv(sval string) (interface{}, error) { + + bin, err := base64.StdEncoding.DecodeString(sval) + if err == nil { + return bin, nil + } + + return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err) +} + +// GetBytesBase64 return the []byte value of a flag with the given name +func (f *FlagSet) GetBytesBase64(name string) ([]byte, error) { + val, err := f.getFlagType(name, "bytesBase64", bytesBase64ValueConv) + + if err != nil { + return []byte{}, err + } + + return val.([]byte), nil +} + +// BytesBase64Var defines an []byte flag with specified name, default value, and usage string. +// The argument p points to an []byte variable in which to store the value of the flag. +func (f *FlagSet) BytesBase64Var(p *[]byte, name string, value []byte, usage string) { + f.VarP(newBytesBase64Value(value, p), name, "", usage) +} + +// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) { + f.VarP(newBytesBase64Value(value, p), name, shorthand, usage) +} + +// BytesBase64Var defines an []byte flag with specified name, default value, and usage string. +// The argument p points to an []byte variable in which to store the value of the flag. +func BytesBase64Var(p *[]byte, name string, value []byte, usage string) { + CommandLine.VarP(newBytesBase64Value(value, p), name, "", usage) +} + +// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash. +func BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) { + CommandLine.VarP(newBytesBase64Value(value, p), name, shorthand, usage) +} + +// BytesBase64 defines an []byte flag with specified name, default value, and usage string. +// The return value is the address of an []byte variable that stores the value of the flag. +func (f *FlagSet) BytesBase64(name string, value []byte, usage string) *[]byte { + p := new([]byte) + f.BytesBase64VarP(p, name, "", value, usage) + return p +} + +// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte { + p := new([]byte) + f.BytesBase64VarP(p, name, shorthand, value, usage) + return p +} + +// BytesBase64 defines an []byte flag with specified name, default value, and usage string. +// The return value is the address of an []byte variable that stores the value of the flag. +func BytesBase64(name string, value []byte, usage string) *[]byte { + return CommandLine.BytesBase64P(name, "", value, usage) +} + +// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash. +func BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte { + return CommandLine.BytesBase64P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/count.go b/vendor/github.com/spf13/pflag/count.go new file mode 100644 index 000000000..a0b2679f7 --- /dev/null +++ b/vendor/github.com/spf13/pflag/count.go @@ -0,0 +1,96 @@ +package pflag + +import "strconv" + +// -- count Value +type countValue int + +func newCountValue(val int, p *int) *countValue { + *p = val + return (*countValue)(p) +} + +func (i *countValue) Set(s string) error { + // "+1" means that no specific value was passed, so increment + if s == "+1" { + *i = countValue(*i + 1) + return nil + } + v, err := strconv.ParseInt(s, 0, 0) + *i = countValue(v) + return err +} + +func (i *countValue) Type() string { + return "count" +} + +func (i *countValue) String() string { return strconv.Itoa(int(*i)) } + +func countConv(sval string) (interface{}, error) { + i, err := strconv.Atoi(sval) + if err != nil { + return nil, err + } + return i, nil +} + +// GetCount return the int value of a flag with the given name +func (f *FlagSet) GetCount(name string) (int, error) { + val, err := f.getFlagType(name, "count", countConv) + if err != nil { + return 0, err + } + return val.(int), nil +} + +// CountVar defines a count flag with specified name, default value, and usage string. +// The argument p points to an int variable in which to store the value of the flag. +// A count flag will add 1 to its value every time it is found on the command line +func (f *FlagSet) CountVar(p *int, name string, usage string) { + f.CountVarP(p, name, "", usage) +} + +// CountVarP is like CountVar only take a shorthand for the flag name. +func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) { + flag := f.VarPF(newCountValue(0, p), name, shorthand, usage) + flag.NoOptDefVal = "+1" +} + +// CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set +func CountVar(p *int, name string, usage string) { + CommandLine.CountVar(p, name, usage) +} + +// CountVarP is like CountVar only take a shorthand for the flag name. +func CountVarP(p *int, name, shorthand string, usage string) { + CommandLine.CountVarP(p, name, shorthand, usage) +} + +// Count defines a count flag with specified name, default value, and usage string. +// The return value is the address of an int variable that stores the value of the flag. +// A count flag will add 1 to its value every time it is found on the command line +func (f *FlagSet) Count(name string, usage string) *int { + p := new(int) + f.CountVarP(p, name, "", usage) + return p +} + +// CountP is like Count only takes a shorthand for the flag name. +func (f *FlagSet) CountP(name, shorthand string, usage string) *int { + p := new(int) + f.CountVarP(p, name, shorthand, usage) + return p +} + +// Count defines a count flag with specified name, default value, and usage string. +// The return value is the address of an int variable that stores the value of the flag. +// A count flag will add 1 to its value evey time it is found on the command line +func Count(name string, usage string) *int { + return CommandLine.CountP(name, "", usage) +} + +// CountP is like Count only takes a shorthand for the flag name. +func CountP(name, shorthand string, usage string) *int { + return CommandLine.CountP(name, shorthand, usage) +} diff --git a/vendor/github.com/spf13/pflag/duration.go b/vendor/github.com/spf13/pflag/duration.go new file mode 100644 index 000000000..e9debef88 --- /dev/null +++ b/vendor/github.com/spf13/pflag/duration.go @@ -0,0 +1,86 @@ +package pflag + +import ( + "time" +) + +// -- time.Duration Value +type durationValue time.Duration + +func newDurationValue(val time.Duration, p *time.Duration) *durationValue { + *p = val + return (*durationValue)(p) +} + +func (d *durationValue) Set(s string) error { + v, err := time.ParseDuration(s) + *d = durationValue(v) + return err +} + +func (d *durationValue) Type() string { + return "duration" +} + +func (d *durationValue) String() string { return (*time.Duration)(d).String() } + +func durationConv(sval string) (interface{}, error) { + return time.ParseDuration(sval) +} + +// GetDuration return the duration value of a flag with the given name +func (f *FlagSet) GetDuration(name string) (time.Duration, error) { + val, err := f.getFlagType(name, "duration", durationConv) + if err != nil { + return 0, err + } + return val.(time.Duration), nil +} + +// DurationVar defines a time.Duration flag with specified name, default value, and usage string. +// The argument p points to a time.Duration variable in which to store the value of the flag. +func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) { + f.VarP(newDurationValue(value, p), name, "", usage) +} + +// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) { + f.VarP(newDurationValue(value, p), name, shorthand, usage) +} + +// DurationVar defines a time.Duration flag with specified name, default value, and usage string. +// The argument p points to a time.Duration variable in which to store the value of the flag. +func DurationVar(p *time.Duration, name string, value time.Duration, usage string) { + CommandLine.VarP(newDurationValue(value, p), name, "", usage) +} + +// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash. +func DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) { + CommandLine.VarP(newDurationValue(value, p), name, shorthand, usage) +} + +// Duration defines a time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a time.Duration variable that stores the value of the flag. +func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration { + p := new(time.Duration) + f.DurationVarP(p, name, "", value, usage) + return p +} + +// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration { + p := new(time.Duration) + f.DurationVarP(p, name, shorthand, value, usage) + return p +} + +// Duration defines a time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a time.Duration variable that stores the value of the flag. +func Duration(name string, value time.Duration, usage string) *time.Duration { + return CommandLine.DurationP(name, "", value, usage) +} + +// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash. +func DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration { + return CommandLine.DurationP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/duration_slice.go b/vendor/github.com/spf13/pflag/duration_slice.go new file mode 100644 index 000000000..badadda53 --- /dev/null +++ b/vendor/github.com/spf13/pflag/duration_slice.go @@ -0,0 +1,166 @@ +package pflag + +import ( + "fmt" + "strings" + "time" +) + +// -- durationSlice Value +type durationSliceValue struct { + value *[]time.Duration + changed bool +} + +func newDurationSliceValue(val []time.Duration, p *[]time.Duration) *durationSliceValue { + dsv := new(durationSliceValue) + dsv.value = p + *dsv.value = val + return dsv +} + +func (s *durationSliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]time.Duration, len(ss)) + for i, d := range ss { + var err error + out[i], err = time.ParseDuration(d) + if err != nil { + return err + } + + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *durationSliceValue) Type() string { + return "durationSlice" +} + +func (s *durationSliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%s", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func (s *durationSliceValue) fromString(val string) (time.Duration, error) { + return time.ParseDuration(val) +} + +func (s *durationSliceValue) toString(val time.Duration) string { + return fmt.Sprintf("%s", val) +} + +func (s *durationSliceValue) Append(val string) error { + i, err := s.fromString(val) + if err != nil { + return err + } + *s.value = append(*s.value, i) + return nil +} + +func (s *durationSliceValue) Replace(val []string) error { + out := make([]time.Duration, len(val)) + for i, d := range val { + var err error + out[i], err = s.fromString(d) + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *durationSliceValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = s.toString(d) + } + return out +} + +func durationSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []time.Duration{}, nil + } + ss := strings.Split(val, ",") + out := make([]time.Duration, len(ss)) + for i, d := range ss { + var err error + out[i], err = time.ParseDuration(d) + if err != nil { + return nil, err + } + + } + return out, nil +} + +// GetDurationSlice returns the []time.Duration value of a flag with the given name +func (f *FlagSet) GetDurationSlice(name string) ([]time.Duration, error) { + val, err := f.getFlagType(name, "durationSlice", durationSliceConv) + if err != nil { + return []time.Duration{}, err + } + return val.([]time.Duration), nil +} + +// DurationSliceVar defines a durationSlice flag with specified name, default value, and usage string. +// The argument p points to a []time.Duration variable in which to store the value of the flag. +func (f *FlagSet) DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) { + f.VarP(newDurationSliceValue(value, p), name, "", usage) +} + +// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) { + f.VarP(newDurationSliceValue(value, p), name, shorthand, usage) +} + +// DurationSliceVar defines a duration[] flag with specified name, default value, and usage string. +// The argument p points to a duration[] variable in which to store the value of the flag. +func DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) { + CommandLine.VarP(newDurationSliceValue(value, p), name, "", usage) +} + +// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash. +func DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) { + CommandLine.VarP(newDurationSliceValue(value, p), name, shorthand, usage) +} + +// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a []time.Duration variable that stores the value of the flag. +func (f *FlagSet) DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration { + p := []time.Duration{} + f.DurationSliceVarP(&p, name, "", value, usage) + return &p +} + +// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration { + p := []time.Duration{} + f.DurationSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a []time.Duration variable that stores the value of the flag. +func DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration { + return CommandLine.DurationSliceP(name, "", value, usage) +} + +// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash. +func DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration { + return CommandLine.DurationSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go new file mode 100644 index 000000000..24a5036e9 --- /dev/null +++ b/vendor/github.com/spf13/pflag/flag.go @@ -0,0 +1,1239 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package pflag is a drop-in replacement for Go's flag package, implementing +POSIX/GNU-style --flags. + +pflag is compatible with the GNU extensions to the POSIX recommendations +for command-line options. See +http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html + +Usage: + +pflag is a drop-in replacement of Go's native flag package. If you import +pflag under the name "flag" then all code should continue to function +with no changes. + + import flag "github.com/spf13/pflag" + +There is one exception to this: if you directly instantiate the Flag struct +there is one more field "Shorthand" that you will need to set. +Most code never instantiates this struct directly, and instead uses +functions such as String(), BoolVar(), and Var(), and is therefore +unaffected. + +Define flags using flag.String(), Bool(), Int(), etc. + +This declares an integer flag, -flagname, stored in the pointer ip, with type *int. + var ip = flag.Int("flagname", 1234, "help message for flagname") +If you like, you can bind the flag to a variable using the Var() functions. + var flagvar int + func init() { + flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") + } +Or you can create custom flags that satisfy the Value interface (with +pointer receivers) and couple them to flag parsing by + flag.Var(&flagVal, "name", "help message for flagname") +For such flags, the default value is just the initial value of the variable. + +After all flags are defined, call + flag.Parse() +to parse the command line into the defined flags. + +Flags may then be used directly. If you're using the flags themselves, +they are all pointers; if you bind to variables, they're values. + fmt.Println("ip has value ", *ip) + fmt.Println("flagvar has value ", flagvar) + +After parsing, the arguments after the flag are available as the +slice flag.Args() or individually as flag.Arg(i). +The arguments are indexed from 0 through flag.NArg()-1. + +The pflag package also defines some new functions that are not in flag, +that give one-letter shorthands for flags. You can use these by appending +'P' to the name of any function that defines a flag. + var ip = flag.IntP("flagname", "f", 1234, "help message") + var flagvar bool + func init() { + flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") + } + flag.VarP(&flagval, "varname", "v", "help message") +Shorthand letters can be used with single dashes on the command line. +Boolean shorthand flags can be combined with other shorthand flags. + +Command line flag syntax: + --flag // boolean flags only + --flag=x + +Unlike the flag package, a single dash before an option means something +different than a double dash. Single dashes signify a series of shorthand +letters for flags. All but the last shorthand letter must be boolean flags. + // boolean flags + -f + -abc + // non-boolean flags + -n 1234 + -Ifile + // mixed + -abcs "hello" + -abcn1234 + +Flag parsing stops after the terminator "--". Unlike the flag package, +flags can be interspersed with arguments anywhere on the command line +before this terminator. + +Integer flags accept 1234, 0664, 0x1234 and may be negative. +Boolean flags (in their long form) accept 1, 0, t, f, true, false, +TRUE, FALSE, True, False. +Duration flags accept any input valid for time.ParseDuration. + +The default set of command-line flags is controlled by +top-level functions. The FlagSet type allows one to define +independent sets of flags, such as to implement subcommands +in a command-line interface. The methods of FlagSet are +analogous to the top-level functions for the command-line +flag set. +*/ +package pflag + +import ( + "bytes" + "errors" + goflag "flag" + "fmt" + "io" + "os" + "sort" + "strings" +) + +// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. +var ErrHelp = errors.New("pflag: help requested") + +// ErrorHandling defines how to handle flag parsing errors. +type ErrorHandling int + +const ( + // ContinueOnError will return an err from Parse() if an error is found + ContinueOnError ErrorHandling = iota + // ExitOnError will call os.Exit(2) if an error is found when parsing + ExitOnError + // PanicOnError will panic() if an error is found when parsing flags + PanicOnError +) + +// ParseErrorsWhitelist defines the parsing errors that can be ignored +type ParseErrorsWhitelist struct { + // UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags + UnknownFlags bool +} + +// NormalizedName is a flag name that has been normalized according to rules +// for the FlagSet (e.g. making '-' and '_' equivalent). +type NormalizedName string + +// A FlagSet represents a set of defined flags. +type FlagSet struct { + // Usage is the function called when an error occurs while parsing flags. + // The field is a function (not a method) that may be changed to point to + // a custom error handler. + Usage func() + + // SortFlags is used to indicate, if user wants to have sorted flags in + // help/usage messages. + SortFlags bool + + // ParseErrorsWhitelist is used to configure a whitelist of errors + ParseErrorsWhitelist ParseErrorsWhitelist + + name string + parsed bool + actual map[NormalizedName]*Flag + orderedActual []*Flag + sortedActual []*Flag + formal map[NormalizedName]*Flag + orderedFormal []*Flag + sortedFormal []*Flag + shorthands map[byte]*Flag + args []string // arguments after flags + argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- + errorHandling ErrorHandling + output io.Writer // nil means stderr; use out() accessor + interspersed bool // allow interspersed option/non-option args + normalizeNameFunc func(f *FlagSet, name string) NormalizedName + + addedGoFlagSets []*goflag.FlagSet +} + +// A Flag represents the state of a flag. +type Flag struct { + Name string // name as it appears on command line + Shorthand string // one-letter abbreviated flag + Usage string // help message + Value Value // value as set + DefValue string // default value (as text); for usage message + Changed bool // If the user set the value (or if left to default) + NoOptDefVal string // default value (as text); if the flag is on the command line without any options + Deprecated string // If this flag is deprecated, this string is the new or now thing to use + Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text + ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use + Annotations map[string][]string // used by cobra.Command bash autocomple code +} + +// Value is the interface to the dynamic value stored in a flag. +// (The default value is represented as a string.) +type Value interface { + String() string + Set(string) error + Type() string +} + +// SliceValue is a secondary interface to all flags which hold a list +// of values. This allows full control over the value of list flags, +// and avoids complicated marshalling and unmarshalling to csv. +type SliceValue interface { + // Append adds the specified value to the end of the flag value list. + Append(string) error + // Replace will fully overwrite any data currently in the flag value list. + Replace([]string) error + // GetSlice returns the flag value list as an array of strings. + GetSlice() []string +} + +// sortFlags returns the flags as a slice in lexicographical sorted order. +func sortFlags(flags map[NormalizedName]*Flag) []*Flag { + list := make(sort.StringSlice, len(flags)) + i := 0 + for k := range flags { + list[i] = string(k) + i++ + } + list.Sort() + result := make([]*Flag, len(list)) + for i, name := range list { + result[i] = flags[NormalizedName(name)] + } + return result +} + +// SetNormalizeFunc allows you to add a function which can translate flag names. +// Flags added to the FlagSet will be translated and then when anything tries to +// look up the flag that will also be translated. So it would be possible to create +// a flag named "getURL" and have it translated to "geturl". A user could then pass +// "--getUrl" which may also be translated to "geturl" and everything will work. +func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) { + f.normalizeNameFunc = n + f.sortedFormal = f.sortedFormal[:0] + for fname, flag := range f.formal { + nname := f.normalizeFlagName(flag.Name) + if fname == nname { + continue + } + flag.Name = string(nname) + delete(f.formal, fname) + f.formal[nname] = flag + if _, set := f.actual[fname]; set { + delete(f.actual, fname) + f.actual[nname] = flag + } + } +} + +// GetNormalizeFunc returns the previously set NormalizeFunc of a function which +// does no translation, if not set previously. +func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedName { + if f.normalizeNameFunc != nil { + return f.normalizeNameFunc + } + return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) } +} + +func (f *FlagSet) normalizeFlagName(name string) NormalizedName { + n := f.GetNormalizeFunc() + return n(f, name) +} + +func (f *FlagSet) out() io.Writer { + if f.output == nil { + return os.Stderr + } + return f.output +} + +// SetOutput sets the destination for usage and error messages. +// If output is nil, os.Stderr is used. +func (f *FlagSet) SetOutput(output io.Writer) { + f.output = output +} + +// VisitAll visits the flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits all flags, even those not set. +func (f *FlagSet) VisitAll(fn func(*Flag)) { + if len(f.formal) == 0 { + return + } + + var flags []*Flag + if f.SortFlags { + if len(f.formal) != len(f.sortedFormal) { + f.sortedFormal = sortFlags(f.formal) + } + flags = f.sortedFormal + } else { + flags = f.orderedFormal + } + + for _, flag := range flags { + fn(flag) + } +} + +// HasFlags returns a bool to indicate if the FlagSet has any flags defined. +func (f *FlagSet) HasFlags() bool { + return len(f.formal) > 0 +} + +// HasAvailableFlags returns a bool to indicate if the FlagSet has any flags +// that are not hidden. +func (f *FlagSet) HasAvailableFlags() bool { + for _, flag := range f.formal { + if !flag.Hidden { + return true + } + } + return false +} + +// VisitAll visits the command-line flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits all flags, even those not set. +func VisitAll(fn func(*Flag)) { + CommandLine.VisitAll(fn) +} + +// Visit visits the flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits only those flags that have been set. +func (f *FlagSet) Visit(fn func(*Flag)) { + if len(f.actual) == 0 { + return + } + + var flags []*Flag + if f.SortFlags { + if len(f.actual) != len(f.sortedActual) { + f.sortedActual = sortFlags(f.actual) + } + flags = f.sortedActual + } else { + flags = f.orderedActual + } + + for _, flag := range flags { + fn(flag) + } +} + +// Visit visits the command-line flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits only those flags that have been set. +func Visit(fn func(*Flag)) { + CommandLine.Visit(fn) +} + +// Lookup returns the Flag structure of the named flag, returning nil if none exists. +func (f *FlagSet) Lookup(name string) *Flag { + return f.lookup(f.normalizeFlagName(name)) +} + +// ShorthandLookup returns the Flag structure of the short handed flag, +// returning nil if none exists. +// It panics, if len(name) > 1. +func (f *FlagSet) ShorthandLookup(name string) *Flag { + if name == "" { + return nil + } + if len(name) > 1 { + msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name) + fmt.Fprintf(f.out(), msg) + panic(msg) + } + c := name[0] + return f.shorthands[c] +} + +// lookup returns the Flag structure of the named flag, returning nil if none exists. +func (f *FlagSet) lookup(name NormalizedName) *Flag { + return f.formal[name] +} + +// func to return a given type for a given flag name +func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) { + flag := f.Lookup(name) + if flag == nil { + err := fmt.Errorf("flag accessed but not defined: %s", name) + return nil, err + } + + if flag.Value.Type() != ftype { + err := fmt.Errorf("trying to get %s value of flag of type %s", ftype, flag.Value.Type()) + return nil, err + } + + sval := flag.Value.String() + result, err := convFunc(sval) + if err != nil { + return nil, err + } + return result, nil +} + +// ArgsLenAtDash will return the length of f.Args at the moment when a -- was +// found during arg parsing. This allows your program to know which args were +// before the -- and which came after. +func (f *FlagSet) ArgsLenAtDash() int { + return f.argsLenAtDash +} + +// MarkDeprecated indicated that a flag is deprecated in your program. It will +// continue to function but will not show up in help or usage messages. Using +// this flag will also print the given usageMessage. +func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { + flag := f.Lookup(name) + if flag == nil { + return fmt.Errorf("flag %q does not exist", name) + } + if usageMessage == "" { + return fmt.Errorf("deprecated message for flag %q must be set", name) + } + flag.Deprecated = usageMessage + flag.Hidden = true + return nil +} + +// MarkShorthandDeprecated will mark the shorthand of a flag deprecated in your +// program. It will continue to function but will not show up in help or usage +// messages. Using this flag will also print the given usageMessage. +func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error { + flag := f.Lookup(name) + if flag == nil { + return fmt.Errorf("flag %q does not exist", name) + } + if usageMessage == "" { + return fmt.Errorf("deprecated message for flag %q must be set", name) + } + flag.ShorthandDeprecated = usageMessage + return nil +} + +// MarkHidden sets a flag to 'hidden' in your program. It will continue to +// function but will not show up in help or usage messages. +func (f *FlagSet) MarkHidden(name string) error { + flag := f.Lookup(name) + if flag == nil { + return fmt.Errorf("flag %q does not exist", name) + } + flag.Hidden = true + return nil +} + +// Lookup returns the Flag structure of the named command-line flag, +// returning nil if none exists. +func Lookup(name string) *Flag { + return CommandLine.Lookup(name) +} + +// ShorthandLookup returns the Flag structure of the short handed flag, +// returning nil if none exists. +func ShorthandLookup(name string) *Flag { + return CommandLine.ShorthandLookup(name) +} + +// Set sets the value of the named flag. +func (f *FlagSet) Set(name, value string) error { + normalName := f.normalizeFlagName(name) + flag, ok := f.formal[normalName] + if !ok { + return fmt.Errorf("no such flag -%v", name) + } + + err := flag.Value.Set(value) + if err != nil { + var flagName string + if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { + flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name) + } else { + flagName = fmt.Sprintf("--%s", flag.Name) + } + return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err) + } + + if !flag.Changed { + if f.actual == nil { + f.actual = make(map[NormalizedName]*Flag) + } + f.actual[normalName] = flag + f.orderedActual = append(f.orderedActual, flag) + + flag.Changed = true + } + + if flag.Deprecated != "" { + fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) + } + return nil +} + +// SetAnnotation allows one to set arbitrary annotations on a flag in the FlagSet. +// This is sometimes used by spf13/cobra programs which want to generate additional +// bash completion information. +func (f *FlagSet) SetAnnotation(name, key string, values []string) error { + normalName := f.normalizeFlagName(name) + flag, ok := f.formal[normalName] + if !ok { + return fmt.Errorf("no such flag -%v", name) + } + if flag.Annotations == nil { + flag.Annotations = map[string][]string{} + } + flag.Annotations[key] = values + return nil +} + +// Changed returns true if the flag was explicitly set during Parse() and false +// otherwise +func (f *FlagSet) Changed(name string) bool { + flag := f.Lookup(name) + // If a flag doesn't exist, it wasn't changed.... + if flag == nil { + return false + } + return flag.Changed +} + +// Set sets the value of the named command-line flag. +func Set(name, value string) error { + return CommandLine.Set(name, value) +} + +// PrintDefaults prints, to standard error unless configured +// otherwise, the default values of all defined flags in the set. +func (f *FlagSet) PrintDefaults() { + usages := f.FlagUsages() + fmt.Fprint(f.out(), usages) +} + +// defaultIsZeroValue returns true if the default value for this flag represents +// a zero value. +func (f *Flag) defaultIsZeroValue() bool { + switch f.Value.(type) { + case boolFlag: + return f.DefValue == "false" + case *durationValue: + // Beginning in Go 1.7, duration zero values are "0s" + return f.DefValue == "0" || f.DefValue == "0s" + case *intValue, *int8Value, *int32Value, *int64Value, *uintValue, *uint8Value, *uint16Value, *uint32Value, *uint64Value, *countValue, *float32Value, *float64Value: + return f.DefValue == "0" + case *stringValue: + return f.DefValue == "" + case *ipValue, *ipMaskValue, *ipNetValue: + return f.DefValue == "" + case *intSliceValue, *stringSliceValue, *stringArrayValue: + return f.DefValue == "[]" + default: + switch f.Value.String() { + case "false": + return true + case "": + return true + case "": + return true + case "0": + return true + } + return false + } +} + +// UnquoteUsage extracts a back-quoted name from the usage +// string for a flag and returns it and the un-quoted usage. +// Given "a `name` to show" it returns ("name", "a name to show"). +// If there are no back quotes, the name is an educated guess of the +// type of the flag's value, or the empty string if the flag is boolean. +func UnquoteUsage(flag *Flag) (name string, usage string) { + // Look for a back-quoted name, but avoid the strings package. + usage = flag.Usage + for i := 0; i < len(usage); i++ { + if usage[i] == '`' { + for j := i + 1; j < len(usage); j++ { + if usage[j] == '`' { + name = usage[i+1 : j] + usage = usage[:i] + name + usage[j+1:] + return name, usage + } + } + break // Only one back quote; use type name. + } + } + + name = flag.Value.Type() + switch name { + case "bool": + name = "" + case "float64": + name = "float" + case "int64": + name = "int" + case "uint64": + name = "uint" + case "stringSlice": + name = "strings" + case "intSlice": + name = "ints" + case "uintSlice": + name = "uints" + case "boolSlice": + name = "bools" + } + + return +} + +// Splits the string `s` on whitespace into an initial substring up to +// `i` runes in length and the remainder. Will go `slop` over `i` if +// that encompasses the entire string (which allows the caller to +// avoid short orphan words on the final line). +func wrapN(i, slop int, s string) (string, string) { + if i+slop > len(s) { + return s, "" + } + + w := strings.LastIndexAny(s[:i], " \t\n") + if w <= 0 { + return s, "" + } + nlPos := strings.LastIndex(s[:i], "\n") + if nlPos > 0 && nlPos < w { + return s[:nlPos], s[nlPos+1:] + } + return s[:w], s[w+1:] +} + +// Wraps the string `s` to a maximum width `w` with leading indent +// `i`. The first line is not indented (this is assumed to be done by +// caller). Pass `w` == 0 to do no wrapping +func wrap(i, w int, s string) string { + if w == 0 { + return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1) + } + + // space between indent i and end of line width w into which + // we should wrap the text. + wrap := w - i + + var r, l string + + // Not enough space for sensible wrapping. Wrap as a block on + // the next line instead. + if wrap < 24 { + i = 16 + wrap = w - i + r += "\n" + strings.Repeat(" ", i) + } + // If still not enough space then don't even try to wrap. + if wrap < 24 { + return strings.Replace(s, "\n", r, -1) + } + + // Try to avoid short orphan words on the final line, by + // allowing wrapN to go a bit over if that would fit in the + // remainder of the line. + slop := 5 + wrap = wrap - slop + + // Handle first line, which is indented by the caller (or the + // special case above) + l, s = wrapN(wrap, slop, s) + r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1) + + // Now wrap the rest + for s != "" { + var t string + + t, s = wrapN(wrap, slop, s) + r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1) + } + + return r + +} + +// FlagUsagesWrapped returns a string containing the usage information +// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no +// wrapping) +func (f *FlagSet) FlagUsagesWrapped(cols int) string { + buf := new(bytes.Buffer) + + lines := make([]string, 0, len(f.formal)) + + maxlen := 0 + f.VisitAll(func(flag *Flag) { + if flag.Hidden { + return + } + + line := "" + if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { + line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name) + } else { + line = fmt.Sprintf(" --%s", flag.Name) + } + + varname, usage := UnquoteUsage(flag) + if varname != "" { + line += " " + varname + } + if flag.NoOptDefVal != "" { + switch flag.Value.Type() { + case "string": + line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal) + case "bool": + if flag.NoOptDefVal != "true" { + line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) + } + case "count": + if flag.NoOptDefVal != "+1" { + line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) + } + default: + line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) + } + } + + // This special character will be replaced with spacing once the + // correct alignment is calculated + line += "\x00" + if len(line) > maxlen { + maxlen = len(line) + } + + line += usage + if !flag.defaultIsZeroValue() { + if flag.Value.Type() == "string" { + line += fmt.Sprintf(" (default %q)", flag.DefValue) + } else { + line += fmt.Sprintf(" (default %s)", flag.DefValue) + } + } + if len(flag.Deprecated) != 0 { + line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated) + } + + lines = append(lines, line) + }) + + for _, line := range lines { + sidx := strings.Index(line, "\x00") + spacing := strings.Repeat(" ", maxlen-sidx) + // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx + fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:])) + } + + return buf.String() +} + +// FlagUsages returns a string containing the usage information for all flags in +// the FlagSet +func (f *FlagSet) FlagUsages() string { + return f.FlagUsagesWrapped(0) +} + +// PrintDefaults prints to standard error the default values of all defined command-line flags. +func PrintDefaults() { + CommandLine.PrintDefaults() +} + +// defaultUsage is the default function to print a usage message. +func defaultUsage(f *FlagSet) { + fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) + f.PrintDefaults() +} + +// NOTE: Usage is not just defaultUsage(CommandLine) +// because it serves (via godoc flag Usage) as the example +// for how to write your own usage function. + +// Usage prints to standard error a usage message documenting all defined command-line flags. +// The function is a variable that may be changed to point to a custom function. +// By default it prints a simple header and calls PrintDefaults; for details about the +// format of the output and how to control it, see the documentation for PrintDefaults. +var Usage = func() { + fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) + PrintDefaults() +} + +// NFlag returns the number of flags that have been set. +func (f *FlagSet) NFlag() int { return len(f.actual) } + +// NFlag returns the number of command-line flags that have been set. +func NFlag() int { return len(CommandLine.actual) } + +// Arg returns the i'th argument. Arg(0) is the first remaining argument +// after flags have been processed. +func (f *FlagSet) Arg(i int) string { + if i < 0 || i >= len(f.args) { + return "" + } + return f.args[i] +} + +// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument +// after flags have been processed. +func Arg(i int) string { + return CommandLine.Arg(i) +} + +// NArg is the number of arguments remaining after flags have been processed. +func (f *FlagSet) NArg() int { return len(f.args) } + +// NArg is the number of arguments remaining after flags have been processed. +func NArg() int { return len(CommandLine.args) } + +// Args returns the non-flag arguments. +func (f *FlagSet) Args() []string { return f.args } + +// Args returns the non-flag command-line arguments. +func Args() []string { return CommandLine.args } + +// Var defines a flag with the specified name and usage string. The type and +// value of the flag are represented by the first argument, of type Value, which +// typically holds a user-defined implementation of Value. For instance, the +// caller could create a flag that turns a comma-separated string into a slice +// of strings by giving the slice the methods of Value; in particular, Set would +// decompose the comma-separated string into the slice. +func (f *FlagSet) Var(value Value, name string, usage string) { + f.VarP(value, name, "", usage) +} + +// VarPF is like VarP, but returns the flag created +func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag { + // Remember the default value as a string; it won't change. + flag := &Flag{ + Name: name, + Shorthand: shorthand, + Usage: usage, + Value: value, + DefValue: value.String(), + } + f.AddFlag(flag) + return flag +} + +// VarP is like Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { + f.VarPF(value, name, shorthand, usage) +} + +// AddFlag will add the flag to the FlagSet +func (f *FlagSet) AddFlag(flag *Flag) { + normalizedFlagName := f.normalizeFlagName(flag.Name) + + _, alreadyThere := f.formal[normalizedFlagName] + if alreadyThere { + msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) + fmt.Fprintln(f.out(), msg) + panic(msg) // Happens only if flags are declared with identical names + } + if f.formal == nil { + f.formal = make(map[NormalizedName]*Flag) + } + + flag.Name = string(normalizedFlagName) + f.formal[normalizedFlagName] = flag + f.orderedFormal = append(f.orderedFormal, flag) + + if flag.Shorthand == "" { + return + } + if len(flag.Shorthand) > 1 { + msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand) + fmt.Fprintf(f.out(), msg) + panic(msg) + } + if f.shorthands == nil { + f.shorthands = make(map[byte]*Flag) + } + c := flag.Shorthand[0] + used, alreadyThere := f.shorthands[c] + if alreadyThere { + msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name) + fmt.Fprintf(f.out(), msg) + panic(msg) + } + f.shorthands[c] = flag +} + +// AddFlagSet adds one FlagSet to another. If a flag is already present in f +// the flag from newSet will be ignored. +func (f *FlagSet) AddFlagSet(newSet *FlagSet) { + if newSet == nil { + return + } + newSet.VisitAll(func(flag *Flag) { + if f.Lookup(flag.Name) == nil { + f.AddFlag(flag) + } + }) +} + +// Var defines a flag with the specified name and usage string. The type and +// value of the flag are represented by the first argument, of type Value, which +// typically holds a user-defined implementation of Value. For instance, the +// caller could create a flag that turns a comma-separated string into a slice +// of strings by giving the slice the methods of Value; in particular, Set would +// decompose the comma-separated string into the slice. +func Var(value Value, name string, usage string) { + CommandLine.VarP(value, name, "", usage) +} + +// VarP is like Var, but accepts a shorthand letter that can be used after a single dash. +func VarP(value Value, name, shorthand, usage string) { + CommandLine.VarP(value, name, shorthand, usage) +} + +// failf prints to standard error a formatted error and usage message and +// returns the error. +func (f *FlagSet) failf(format string, a ...interface{}) error { + err := fmt.Errorf(format, a...) + if f.errorHandling != ContinueOnError { + fmt.Fprintln(f.out(), err) + f.usage() + } + return err +} + +// usage calls the Usage method for the flag set, or the usage function if +// the flag set is CommandLine. +func (f *FlagSet) usage() { + if f == CommandLine { + Usage() + } else if f.Usage == nil { + defaultUsage(f) + } else { + f.Usage() + } +} + +//--unknown (args will be empty) +//--unknown --next-flag ... (args will be --next-flag ...) +//--unknown arg ... (args will be arg ...) +func stripUnknownFlagValue(args []string) []string { + if len(args) == 0 { + //--unknown + return args + } + + first := args[0] + if len(first) > 0 && first[0] == '-' { + //--unknown --next-flag ... + return args + } + + //--unknown arg ... (args will be arg ...) + if len(args) > 1 { + return args[1:] + } + return nil +} + +func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) { + a = args + name := s[2:] + if len(name) == 0 || name[0] == '-' || name[0] == '=' { + err = f.failf("bad flag syntax: %s", s) + return + } + + split := strings.SplitN(name, "=", 2) + name = split[0] + flag, exists := f.formal[f.normalizeFlagName(name)] + + if !exists { + switch { + case name == "help": + f.usage() + return a, ErrHelp + case f.ParseErrorsWhitelist.UnknownFlags: + // --unknown=unknownval arg ... + // we do not want to lose arg in this case + if len(split) >= 2 { + return a, nil + } + + return stripUnknownFlagValue(a), nil + default: + err = f.failf("unknown flag: --%s", name) + return + } + } + + var value string + if len(split) == 2 { + // '--flag=arg' + value = split[1] + } else if flag.NoOptDefVal != "" { + // '--flag' (arg was optional) + value = flag.NoOptDefVal + } else if len(a) > 0 { + // '--flag arg' + value = a[0] + a = a[1:] + } else { + // '--flag' (arg was required) + err = f.failf("flag needs an argument: %s", s) + return + } + + err = fn(flag, value) + if err != nil { + f.failf(err.Error()) + } + return +} + +func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) { + outArgs = args + + if strings.HasPrefix(shorthands, "test.") { + return + } + + outShorts = shorthands[1:] + c := shorthands[0] + + flag, exists := f.shorthands[c] + if !exists { + switch { + case c == 'h': + f.usage() + err = ErrHelp + return + case f.ParseErrorsWhitelist.UnknownFlags: + // '-f=arg arg ...' + // we do not want to lose arg in this case + if len(shorthands) > 2 && shorthands[1] == '=' { + outShorts = "" + return + } + + outArgs = stripUnknownFlagValue(outArgs) + return + default: + err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) + return + } + } + + var value string + if len(shorthands) > 2 && shorthands[1] == '=' { + // '-f=arg' + value = shorthands[2:] + outShorts = "" + } else if flag.NoOptDefVal != "" { + // '-f' (arg was optional) + value = flag.NoOptDefVal + } else if len(shorthands) > 1 { + // '-farg' + value = shorthands[1:] + outShorts = "" + } else if len(args) > 0 { + // '-f arg' + value = args[0] + outArgs = args[1:] + } else { + // '-f' (arg was required) + err = f.failf("flag needs an argument: %q in -%s", c, shorthands) + return + } + + if flag.ShorthandDeprecated != "" { + fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) + } + + err = fn(flag, value) + if err != nil { + f.failf(err.Error()) + } + return +} + +func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) { + a = args + shorthands := s[1:] + + // "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv"). + for len(shorthands) > 0 { + shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn) + if err != nil { + return + } + } + + return +} + +func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) { + for len(args) > 0 { + s := args[0] + args = args[1:] + if len(s) == 0 || s[0] != '-' || len(s) == 1 { + if !f.interspersed { + f.args = append(f.args, s) + f.args = append(f.args, args...) + return nil + } + f.args = append(f.args, s) + continue + } + + if s[1] == '-' { + if len(s) == 2 { // "--" terminates the flags + f.argsLenAtDash = len(f.args) + f.args = append(f.args, args...) + break + } + args, err = f.parseLongArg(s, args, fn) + } else { + args, err = f.parseShortArg(s, args, fn) + } + if err != nil { + return + } + } + return +} + +// Parse parses flag definitions from the argument list, which should not +// include the command name. Must be called after all flags in the FlagSet +// are defined and before flags are accessed by the program. +// The return value will be ErrHelp if -help was set but not defined. +func (f *FlagSet) Parse(arguments []string) error { + if f.addedGoFlagSets != nil { + for _, goFlagSet := range f.addedGoFlagSets { + goFlagSet.Parse(nil) + } + } + f.parsed = true + + if len(arguments) < 0 { + return nil + } + + f.args = make([]string, 0, len(arguments)) + + set := func(flag *Flag, value string) error { + return f.Set(flag.Name, value) + } + + err := f.parseArgs(arguments, set) + if err != nil { + switch f.errorHandling { + case ContinueOnError: + return err + case ExitOnError: + fmt.Println(err) + os.Exit(2) + case PanicOnError: + panic(err) + } + } + return nil +} + +type parseFunc func(flag *Flag, value string) error + +// ParseAll parses flag definitions from the argument list, which should not +// include the command name. The arguments for fn are flag and value. Must be +// called after all flags in the FlagSet are defined and before flags are +// accessed by the program. The return value will be ErrHelp if -help was set +// but not defined. +func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error { + f.parsed = true + f.args = make([]string, 0, len(arguments)) + + err := f.parseArgs(arguments, fn) + if err != nil { + switch f.errorHandling { + case ContinueOnError: + return err + case ExitOnError: + os.Exit(2) + case PanicOnError: + panic(err) + } + } + return nil +} + +// Parsed reports whether f.Parse has been called. +func (f *FlagSet) Parsed() bool { + return f.parsed +} + +// Parse parses the command-line flags from os.Args[1:]. Must be called +// after all flags are defined and before flags are accessed by the program. +func Parse() { + // Ignore errors; CommandLine is set for ExitOnError. + CommandLine.Parse(os.Args[1:]) +} + +// ParseAll parses the command-line flags from os.Args[1:] and called fn for each. +// The arguments for fn are flag and value. Must be called after all flags are +// defined and before flags are accessed by the program. +func ParseAll(fn func(flag *Flag, value string) error) { + // Ignore errors; CommandLine is set for ExitOnError. + CommandLine.ParseAll(os.Args[1:], fn) +} + +// SetInterspersed sets whether to support interspersed option/non-option arguments. +func SetInterspersed(interspersed bool) { + CommandLine.SetInterspersed(interspersed) +} + +// Parsed returns true if the command-line flags have been parsed. +func Parsed() bool { + return CommandLine.Parsed() +} + +// CommandLine is the default set of command-line flags, parsed from os.Args. +var CommandLine = NewFlagSet(os.Args[0], ExitOnError) + +// NewFlagSet returns a new, empty flag set with the specified name, +// error handling property and SortFlags set to true. +func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { + f := &FlagSet{ + name: name, + errorHandling: errorHandling, + argsLenAtDash: -1, + interspersed: true, + SortFlags: true, + } + return f +} + +// SetInterspersed sets whether to support interspersed option/non-option arguments. +func (f *FlagSet) SetInterspersed(interspersed bool) { + f.interspersed = interspersed +} + +// Init sets the name and error handling property for a flag set. +// By default, the zero FlagSet uses an empty name and the +// ContinueOnError error handling policy. +func (f *FlagSet) Init(name string, errorHandling ErrorHandling) { + f.name = name + f.errorHandling = errorHandling + f.argsLenAtDash = -1 +} diff --git a/vendor/github.com/spf13/pflag/float32.go b/vendor/github.com/spf13/pflag/float32.go new file mode 100644 index 000000000..a243f81f7 --- /dev/null +++ b/vendor/github.com/spf13/pflag/float32.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- float32 Value +type float32Value float32 + +func newFloat32Value(val float32, p *float32) *float32Value { + *p = val + return (*float32Value)(p) +} + +func (f *float32Value) Set(s string) error { + v, err := strconv.ParseFloat(s, 32) + *f = float32Value(v) + return err +} + +func (f *float32Value) Type() string { + return "float32" +} + +func (f *float32Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 32) } + +func float32Conv(sval string) (interface{}, error) { + v, err := strconv.ParseFloat(sval, 32) + if err != nil { + return 0, err + } + return float32(v), nil +} + +// GetFloat32 return the float32 value of a flag with the given name +func (f *FlagSet) GetFloat32(name string) (float32, error) { + val, err := f.getFlagType(name, "float32", float32Conv) + if err != nil { + return 0, err + } + return val.(float32), nil +} + +// Float32Var defines a float32 flag with specified name, default value, and usage string. +// The argument p points to a float32 variable in which to store the value of the flag. +func (f *FlagSet) Float32Var(p *float32, name string, value float32, usage string) { + f.VarP(newFloat32Value(value, p), name, "", usage) +} + +// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float32VarP(p *float32, name, shorthand string, value float32, usage string) { + f.VarP(newFloat32Value(value, p), name, shorthand, usage) +} + +// Float32Var defines a float32 flag with specified name, default value, and usage string. +// The argument p points to a float32 variable in which to store the value of the flag. +func Float32Var(p *float32, name string, value float32, usage string) { + CommandLine.VarP(newFloat32Value(value, p), name, "", usage) +} + +// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash. +func Float32VarP(p *float32, name, shorthand string, value float32, usage string) { + CommandLine.VarP(newFloat32Value(value, p), name, shorthand, usage) +} + +// Float32 defines a float32 flag with specified name, default value, and usage string. +// The return value is the address of a float32 variable that stores the value of the flag. +func (f *FlagSet) Float32(name string, value float32, usage string) *float32 { + p := new(float32) + f.Float32VarP(p, name, "", value, usage) + return p +} + +// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float32P(name, shorthand string, value float32, usage string) *float32 { + p := new(float32) + f.Float32VarP(p, name, shorthand, value, usage) + return p +} + +// Float32 defines a float32 flag with specified name, default value, and usage string. +// The return value is the address of a float32 variable that stores the value of the flag. +func Float32(name string, value float32, usage string) *float32 { + return CommandLine.Float32P(name, "", value, usage) +} + +// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash. +func Float32P(name, shorthand string, value float32, usage string) *float32 { + return CommandLine.Float32P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/float32_slice.go b/vendor/github.com/spf13/pflag/float32_slice.go new file mode 100644 index 000000000..caa352741 --- /dev/null +++ b/vendor/github.com/spf13/pflag/float32_slice.go @@ -0,0 +1,174 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- float32Slice Value +type float32SliceValue struct { + value *[]float32 + changed bool +} + +func newFloat32SliceValue(val []float32, p *[]float32) *float32SliceValue { + isv := new(float32SliceValue) + isv.value = p + *isv.value = val + return isv +} + +func (s *float32SliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]float32, len(ss)) + for i, d := range ss { + var err error + var temp64 float64 + temp64, err = strconv.ParseFloat(d, 32) + if err != nil { + return err + } + out[i] = float32(temp64) + + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *float32SliceValue) Type() string { + return "float32Slice" +} + +func (s *float32SliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%f", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func (s *float32SliceValue) fromString(val string) (float32, error) { + t64, err := strconv.ParseFloat(val, 32) + if err != nil { + return 0, err + } + return float32(t64), nil +} + +func (s *float32SliceValue) toString(val float32) string { + return fmt.Sprintf("%f", val) +} + +func (s *float32SliceValue) Append(val string) error { + i, err := s.fromString(val) + if err != nil { + return err + } + *s.value = append(*s.value, i) + return nil +} + +func (s *float32SliceValue) Replace(val []string) error { + out := make([]float32, len(val)) + for i, d := range val { + var err error + out[i], err = s.fromString(d) + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *float32SliceValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = s.toString(d) + } + return out +} + +func float32SliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []float32{}, nil + } + ss := strings.Split(val, ",") + out := make([]float32, len(ss)) + for i, d := range ss { + var err error + var temp64 float64 + temp64, err = strconv.ParseFloat(d, 32) + if err != nil { + return nil, err + } + out[i] = float32(temp64) + + } + return out, nil +} + +// GetFloat32Slice return the []float32 value of a flag with the given name +func (f *FlagSet) GetFloat32Slice(name string) ([]float32, error) { + val, err := f.getFlagType(name, "float32Slice", float32SliceConv) + if err != nil { + return []float32{}, err + } + return val.([]float32), nil +} + +// Float32SliceVar defines a float32Slice flag with specified name, default value, and usage string. +// The argument p points to a []float32 variable in which to store the value of the flag. +func (f *FlagSet) Float32SliceVar(p *[]float32, name string, value []float32, usage string) { + f.VarP(newFloat32SliceValue(value, p), name, "", usage) +} + +// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) { + f.VarP(newFloat32SliceValue(value, p), name, shorthand, usage) +} + +// Float32SliceVar defines a float32[] flag with specified name, default value, and usage string. +// The argument p points to a float32[] variable in which to store the value of the flag. +func Float32SliceVar(p *[]float32, name string, value []float32, usage string) { + CommandLine.VarP(newFloat32SliceValue(value, p), name, "", usage) +} + +// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash. +func Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) { + CommandLine.VarP(newFloat32SliceValue(value, p), name, shorthand, usage) +} + +// Float32Slice defines a []float32 flag with specified name, default value, and usage string. +// The return value is the address of a []float32 variable that stores the value of the flag. +func (f *FlagSet) Float32Slice(name string, value []float32, usage string) *[]float32 { + p := []float32{} + f.Float32SliceVarP(&p, name, "", value, usage) + return &p +} + +// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 { + p := []float32{} + f.Float32SliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// Float32Slice defines a []float32 flag with specified name, default value, and usage string. +// The return value is the address of a []float32 variable that stores the value of the flag. +func Float32Slice(name string, value []float32, usage string) *[]float32 { + return CommandLine.Float32SliceP(name, "", value, usage) +} + +// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash. +func Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 { + return CommandLine.Float32SliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/float64.go b/vendor/github.com/spf13/pflag/float64.go new file mode 100644 index 000000000..04b5492a7 --- /dev/null +++ b/vendor/github.com/spf13/pflag/float64.go @@ -0,0 +1,84 @@ +package pflag + +import "strconv" + +// -- float64 Value +type float64Value float64 + +func newFloat64Value(val float64, p *float64) *float64Value { + *p = val + return (*float64Value)(p) +} + +func (f *float64Value) Set(s string) error { + v, err := strconv.ParseFloat(s, 64) + *f = float64Value(v) + return err +} + +func (f *float64Value) Type() string { + return "float64" +} + +func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) } + +func float64Conv(sval string) (interface{}, error) { + return strconv.ParseFloat(sval, 64) +} + +// GetFloat64 return the float64 value of a flag with the given name +func (f *FlagSet) GetFloat64(name string) (float64, error) { + val, err := f.getFlagType(name, "float64", float64Conv) + if err != nil { + return 0, err + } + return val.(float64), nil +} + +// Float64Var defines a float64 flag with specified name, default value, and usage string. +// The argument p points to a float64 variable in which to store the value of the flag. +func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) { + f.VarP(newFloat64Value(value, p), name, "", usage) +} + +// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float64VarP(p *float64, name, shorthand string, value float64, usage string) { + f.VarP(newFloat64Value(value, p), name, shorthand, usage) +} + +// Float64Var defines a float64 flag with specified name, default value, and usage string. +// The argument p points to a float64 variable in which to store the value of the flag. +func Float64Var(p *float64, name string, value float64, usage string) { + CommandLine.VarP(newFloat64Value(value, p), name, "", usage) +} + +// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash. +func Float64VarP(p *float64, name, shorthand string, value float64, usage string) { + CommandLine.VarP(newFloat64Value(value, p), name, shorthand, usage) +} + +// Float64 defines a float64 flag with specified name, default value, and usage string. +// The return value is the address of a float64 variable that stores the value of the flag. +func (f *FlagSet) Float64(name string, value float64, usage string) *float64 { + p := new(float64) + f.Float64VarP(p, name, "", value, usage) + return p +} + +// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float64P(name, shorthand string, value float64, usage string) *float64 { + p := new(float64) + f.Float64VarP(p, name, shorthand, value, usage) + return p +} + +// Float64 defines a float64 flag with specified name, default value, and usage string. +// The return value is the address of a float64 variable that stores the value of the flag. +func Float64(name string, value float64, usage string) *float64 { + return CommandLine.Float64P(name, "", value, usage) +} + +// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash. +func Float64P(name, shorthand string, value float64, usage string) *float64 { + return CommandLine.Float64P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/float64_slice.go b/vendor/github.com/spf13/pflag/float64_slice.go new file mode 100644 index 000000000..85bf3073d --- /dev/null +++ b/vendor/github.com/spf13/pflag/float64_slice.go @@ -0,0 +1,166 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- float64Slice Value +type float64SliceValue struct { + value *[]float64 + changed bool +} + +func newFloat64SliceValue(val []float64, p *[]float64) *float64SliceValue { + isv := new(float64SliceValue) + isv.value = p + *isv.value = val + return isv +} + +func (s *float64SliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]float64, len(ss)) + for i, d := range ss { + var err error + out[i], err = strconv.ParseFloat(d, 64) + if err != nil { + return err + } + + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *float64SliceValue) Type() string { + return "float64Slice" +} + +func (s *float64SliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%f", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func (s *float64SliceValue) fromString(val string) (float64, error) { + return strconv.ParseFloat(val, 64) +} + +func (s *float64SliceValue) toString(val float64) string { + return fmt.Sprintf("%f", val) +} + +func (s *float64SliceValue) Append(val string) error { + i, err := s.fromString(val) + if err != nil { + return err + } + *s.value = append(*s.value, i) + return nil +} + +func (s *float64SliceValue) Replace(val []string) error { + out := make([]float64, len(val)) + for i, d := range val { + var err error + out[i], err = s.fromString(d) + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *float64SliceValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = s.toString(d) + } + return out +} + +func float64SliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []float64{}, nil + } + ss := strings.Split(val, ",") + out := make([]float64, len(ss)) + for i, d := range ss { + var err error + out[i], err = strconv.ParseFloat(d, 64) + if err != nil { + return nil, err + } + + } + return out, nil +} + +// GetFloat64Slice return the []float64 value of a flag with the given name +func (f *FlagSet) GetFloat64Slice(name string) ([]float64, error) { + val, err := f.getFlagType(name, "float64Slice", float64SliceConv) + if err != nil { + return []float64{}, err + } + return val.([]float64), nil +} + +// Float64SliceVar defines a float64Slice flag with specified name, default value, and usage string. +// The argument p points to a []float64 variable in which to store the value of the flag. +func (f *FlagSet) Float64SliceVar(p *[]float64, name string, value []float64, usage string) { + f.VarP(newFloat64SliceValue(value, p), name, "", usage) +} + +// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) { + f.VarP(newFloat64SliceValue(value, p), name, shorthand, usage) +} + +// Float64SliceVar defines a float64[] flag with specified name, default value, and usage string. +// The argument p points to a float64[] variable in which to store the value of the flag. +func Float64SliceVar(p *[]float64, name string, value []float64, usage string) { + CommandLine.VarP(newFloat64SliceValue(value, p), name, "", usage) +} + +// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash. +func Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) { + CommandLine.VarP(newFloat64SliceValue(value, p), name, shorthand, usage) +} + +// Float64Slice defines a []float64 flag with specified name, default value, and usage string. +// The return value is the address of a []float64 variable that stores the value of the flag. +func (f *FlagSet) Float64Slice(name string, value []float64, usage string) *[]float64 { + p := []float64{} + f.Float64SliceVarP(&p, name, "", value, usage) + return &p +} + +// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 { + p := []float64{} + f.Float64SliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// Float64Slice defines a []float64 flag with specified name, default value, and usage string. +// The return value is the address of a []float64 variable that stores the value of the flag. +func Float64Slice(name string, value []float64, usage string) *[]float64 { + return CommandLine.Float64SliceP(name, "", value, usage) +} + +// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash. +func Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 { + return CommandLine.Float64SliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/go.mod b/vendor/github.com/spf13/pflag/go.mod new file mode 100644 index 000000000..b2287eec1 --- /dev/null +++ b/vendor/github.com/spf13/pflag/go.mod @@ -0,0 +1,3 @@ +module github.com/spf13/pflag + +go 1.12 diff --git a/vendor/github.com/spf13/pflag/go.sum b/vendor/github.com/spf13/pflag/go.sum new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/github.com/spf13/pflag/golangflag.go b/vendor/github.com/spf13/pflag/golangflag.go new file mode 100644 index 000000000..d3dd72b7f --- /dev/null +++ b/vendor/github.com/spf13/pflag/golangflag.go @@ -0,0 +1,105 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pflag + +import ( + goflag "flag" + "reflect" + "strings" +) + +// flagValueWrapper implements pflag.Value around a flag.Value. The main +// difference here is the addition of the Type method that returns a string +// name of the type. As this is generally unknown, we approximate that with +// reflection. +type flagValueWrapper struct { + inner goflag.Value + flagType string +} + +// We are just copying the boolFlag interface out of goflag as that is what +// they use to decide if a flag should get "true" when no arg is given. +type goBoolFlag interface { + goflag.Value + IsBoolFlag() bool +} + +func wrapFlagValue(v goflag.Value) Value { + // If the flag.Value happens to also be a pflag.Value, just use it directly. + if pv, ok := v.(Value); ok { + return pv + } + + pv := &flagValueWrapper{ + inner: v, + } + + t := reflect.TypeOf(v) + if t.Kind() == reflect.Interface || t.Kind() == reflect.Ptr { + t = t.Elem() + } + + pv.flagType = strings.TrimSuffix(t.Name(), "Value") + return pv +} + +func (v *flagValueWrapper) String() string { + return v.inner.String() +} + +func (v *flagValueWrapper) Set(s string) error { + return v.inner.Set(s) +} + +func (v *flagValueWrapper) Type() string { + return v.flagType +} + +// PFlagFromGoFlag will return a *pflag.Flag given a *flag.Flag +// If the *flag.Flag.Name was a single character (ex: `v`) it will be accessiblei +// with both `-v` and `--v` in flags. If the golang flag was more than a single +// character (ex: `verbose`) it will only be accessible via `--verbose` +func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { + // Remember the default value as a string; it won't change. + flag := &Flag{ + Name: goflag.Name, + Usage: goflag.Usage, + Value: wrapFlagValue(goflag.Value), + // Looks like golang flags don't set DefValue correctly :-( + //DefValue: goflag.DefValue, + DefValue: goflag.Value.String(), + } + // Ex: if the golang flag was -v, allow both -v and --v to work + if len(flag.Name) == 1 { + flag.Shorthand = flag.Name + } + if fv, ok := goflag.Value.(goBoolFlag); ok && fv.IsBoolFlag() { + flag.NoOptDefVal = "true" + } + return flag +} + +// AddGoFlag will add the given *flag.Flag to the pflag.FlagSet +func (f *FlagSet) AddGoFlag(goflag *goflag.Flag) { + if f.Lookup(goflag.Name) != nil { + return + } + newflag := PFlagFromGoFlag(goflag) + f.AddFlag(newflag) +} + +// AddGoFlagSet will add the given *flag.FlagSet to the pflag.FlagSet +func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) { + if newSet == nil { + return + } + newSet.VisitAll(func(goflag *goflag.Flag) { + f.AddGoFlag(goflag) + }) + if f.addedGoFlagSets == nil { + f.addedGoFlagSets = make([]*goflag.FlagSet, 0) + } + f.addedGoFlagSets = append(f.addedGoFlagSets, newSet) +} diff --git a/vendor/github.com/spf13/pflag/int.go b/vendor/github.com/spf13/pflag/int.go new file mode 100644 index 000000000..1474b89df --- /dev/null +++ b/vendor/github.com/spf13/pflag/int.go @@ -0,0 +1,84 @@ +package pflag + +import "strconv" + +// -- int Value +type intValue int + +func newIntValue(val int, p *int) *intValue { + *p = val + return (*intValue)(p) +} + +func (i *intValue) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 64) + *i = intValue(v) + return err +} + +func (i *intValue) Type() string { + return "int" +} + +func (i *intValue) String() string { return strconv.Itoa(int(*i)) } + +func intConv(sval string) (interface{}, error) { + return strconv.Atoi(sval) +} + +// GetInt return the int value of a flag with the given name +func (f *FlagSet) GetInt(name string) (int, error) { + val, err := f.getFlagType(name, "int", intConv) + if err != nil { + return 0, err + } + return val.(int), nil +} + +// IntVar defines an int flag with specified name, default value, and usage string. +// The argument p points to an int variable in which to store the value of the flag. +func (f *FlagSet) IntVar(p *int, name string, value int, usage string) { + f.VarP(newIntValue(value, p), name, "", usage) +} + +// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IntVarP(p *int, name, shorthand string, value int, usage string) { + f.VarP(newIntValue(value, p), name, shorthand, usage) +} + +// IntVar defines an int flag with specified name, default value, and usage string. +// The argument p points to an int variable in which to store the value of the flag. +func IntVar(p *int, name string, value int, usage string) { + CommandLine.VarP(newIntValue(value, p), name, "", usage) +} + +// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash. +func IntVarP(p *int, name, shorthand string, value int, usage string) { + CommandLine.VarP(newIntValue(value, p), name, shorthand, usage) +} + +// Int defines an int flag with specified name, default value, and usage string. +// The return value is the address of an int variable that stores the value of the flag. +func (f *FlagSet) Int(name string, value int, usage string) *int { + p := new(int) + f.IntVarP(p, name, "", value, usage) + return p +} + +// IntP is like Int, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IntP(name, shorthand string, value int, usage string) *int { + p := new(int) + f.IntVarP(p, name, shorthand, value, usage) + return p +} + +// Int defines an int flag with specified name, default value, and usage string. +// The return value is the address of an int variable that stores the value of the flag. +func Int(name string, value int, usage string) *int { + return CommandLine.IntP(name, "", value, usage) +} + +// IntP is like Int, but accepts a shorthand letter that can be used after a single dash. +func IntP(name, shorthand string, value int, usage string) *int { + return CommandLine.IntP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int16.go b/vendor/github.com/spf13/pflag/int16.go new file mode 100644 index 000000000..f1a01d05e --- /dev/null +++ b/vendor/github.com/spf13/pflag/int16.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- int16 Value +type int16Value int16 + +func newInt16Value(val int16, p *int16) *int16Value { + *p = val + return (*int16Value)(p) +} + +func (i *int16Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 16) + *i = int16Value(v) + return err +} + +func (i *int16Value) Type() string { + return "int16" +} + +func (i *int16Value) String() string { return strconv.FormatInt(int64(*i), 10) } + +func int16Conv(sval string) (interface{}, error) { + v, err := strconv.ParseInt(sval, 0, 16) + if err != nil { + return 0, err + } + return int16(v), nil +} + +// GetInt16 returns the int16 value of a flag with the given name +func (f *FlagSet) GetInt16(name string) (int16, error) { + val, err := f.getFlagType(name, "int16", int16Conv) + if err != nil { + return 0, err + } + return val.(int16), nil +} + +// Int16Var defines an int16 flag with specified name, default value, and usage string. +// The argument p points to an int16 variable in which to store the value of the flag. +func (f *FlagSet) Int16Var(p *int16, name string, value int16, usage string) { + f.VarP(newInt16Value(value, p), name, "", usage) +} + +// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int16VarP(p *int16, name, shorthand string, value int16, usage string) { + f.VarP(newInt16Value(value, p), name, shorthand, usage) +} + +// Int16Var defines an int16 flag with specified name, default value, and usage string. +// The argument p points to an int16 variable in which to store the value of the flag. +func Int16Var(p *int16, name string, value int16, usage string) { + CommandLine.VarP(newInt16Value(value, p), name, "", usage) +} + +// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash. +func Int16VarP(p *int16, name, shorthand string, value int16, usage string) { + CommandLine.VarP(newInt16Value(value, p), name, shorthand, usage) +} + +// Int16 defines an int16 flag with specified name, default value, and usage string. +// The return value is the address of an int16 variable that stores the value of the flag. +func (f *FlagSet) Int16(name string, value int16, usage string) *int16 { + p := new(int16) + f.Int16VarP(p, name, "", value, usage) + return p +} + +// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int16P(name, shorthand string, value int16, usage string) *int16 { + p := new(int16) + f.Int16VarP(p, name, shorthand, value, usage) + return p +} + +// Int16 defines an int16 flag with specified name, default value, and usage string. +// The return value is the address of an int16 variable that stores the value of the flag. +func Int16(name string, value int16, usage string) *int16 { + return CommandLine.Int16P(name, "", value, usage) +} + +// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash. +func Int16P(name, shorthand string, value int16, usage string) *int16 { + return CommandLine.Int16P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int32.go b/vendor/github.com/spf13/pflag/int32.go new file mode 100644 index 000000000..9b95944f0 --- /dev/null +++ b/vendor/github.com/spf13/pflag/int32.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- int32 Value +type int32Value int32 + +func newInt32Value(val int32, p *int32) *int32Value { + *p = val + return (*int32Value)(p) +} + +func (i *int32Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 32) + *i = int32Value(v) + return err +} + +func (i *int32Value) Type() string { + return "int32" +} + +func (i *int32Value) String() string { return strconv.FormatInt(int64(*i), 10) } + +func int32Conv(sval string) (interface{}, error) { + v, err := strconv.ParseInt(sval, 0, 32) + if err != nil { + return 0, err + } + return int32(v), nil +} + +// GetInt32 return the int32 value of a flag with the given name +func (f *FlagSet) GetInt32(name string) (int32, error) { + val, err := f.getFlagType(name, "int32", int32Conv) + if err != nil { + return 0, err + } + return val.(int32), nil +} + +// Int32Var defines an int32 flag with specified name, default value, and usage string. +// The argument p points to an int32 variable in which to store the value of the flag. +func (f *FlagSet) Int32Var(p *int32, name string, value int32, usage string) { + f.VarP(newInt32Value(value, p), name, "", usage) +} + +// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int32VarP(p *int32, name, shorthand string, value int32, usage string) { + f.VarP(newInt32Value(value, p), name, shorthand, usage) +} + +// Int32Var defines an int32 flag with specified name, default value, and usage string. +// The argument p points to an int32 variable in which to store the value of the flag. +func Int32Var(p *int32, name string, value int32, usage string) { + CommandLine.VarP(newInt32Value(value, p), name, "", usage) +} + +// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash. +func Int32VarP(p *int32, name, shorthand string, value int32, usage string) { + CommandLine.VarP(newInt32Value(value, p), name, shorthand, usage) +} + +// Int32 defines an int32 flag with specified name, default value, and usage string. +// The return value is the address of an int32 variable that stores the value of the flag. +func (f *FlagSet) Int32(name string, value int32, usage string) *int32 { + p := new(int32) + f.Int32VarP(p, name, "", value, usage) + return p +} + +// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int32P(name, shorthand string, value int32, usage string) *int32 { + p := new(int32) + f.Int32VarP(p, name, shorthand, value, usage) + return p +} + +// Int32 defines an int32 flag with specified name, default value, and usage string. +// The return value is the address of an int32 variable that stores the value of the flag. +func Int32(name string, value int32, usage string) *int32 { + return CommandLine.Int32P(name, "", value, usage) +} + +// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash. +func Int32P(name, shorthand string, value int32, usage string) *int32 { + return CommandLine.Int32P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int32_slice.go b/vendor/github.com/spf13/pflag/int32_slice.go new file mode 100644 index 000000000..ff128ff06 --- /dev/null +++ b/vendor/github.com/spf13/pflag/int32_slice.go @@ -0,0 +1,174 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- int32Slice Value +type int32SliceValue struct { + value *[]int32 + changed bool +} + +func newInt32SliceValue(val []int32, p *[]int32) *int32SliceValue { + isv := new(int32SliceValue) + isv.value = p + *isv.value = val + return isv +} + +func (s *int32SliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]int32, len(ss)) + for i, d := range ss { + var err error + var temp64 int64 + temp64, err = strconv.ParseInt(d, 0, 32) + if err != nil { + return err + } + out[i] = int32(temp64) + + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *int32SliceValue) Type() string { + return "int32Slice" +} + +func (s *int32SliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%d", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func (s *int32SliceValue) fromString(val string) (int32, error) { + t64, err := strconv.ParseInt(val, 0, 32) + if err != nil { + return 0, err + } + return int32(t64), nil +} + +func (s *int32SliceValue) toString(val int32) string { + return fmt.Sprintf("%d", val) +} + +func (s *int32SliceValue) Append(val string) error { + i, err := s.fromString(val) + if err != nil { + return err + } + *s.value = append(*s.value, i) + return nil +} + +func (s *int32SliceValue) Replace(val []string) error { + out := make([]int32, len(val)) + for i, d := range val { + var err error + out[i], err = s.fromString(d) + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *int32SliceValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = s.toString(d) + } + return out +} + +func int32SliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []int32{}, nil + } + ss := strings.Split(val, ",") + out := make([]int32, len(ss)) + for i, d := range ss { + var err error + var temp64 int64 + temp64, err = strconv.ParseInt(d, 0, 32) + if err != nil { + return nil, err + } + out[i] = int32(temp64) + + } + return out, nil +} + +// GetInt32Slice return the []int32 value of a flag with the given name +func (f *FlagSet) GetInt32Slice(name string) ([]int32, error) { + val, err := f.getFlagType(name, "int32Slice", int32SliceConv) + if err != nil { + return []int32{}, err + } + return val.([]int32), nil +} + +// Int32SliceVar defines a int32Slice flag with specified name, default value, and usage string. +// The argument p points to a []int32 variable in which to store the value of the flag. +func (f *FlagSet) Int32SliceVar(p *[]int32, name string, value []int32, usage string) { + f.VarP(newInt32SliceValue(value, p), name, "", usage) +} + +// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) { + f.VarP(newInt32SliceValue(value, p), name, shorthand, usage) +} + +// Int32SliceVar defines a int32[] flag with specified name, default value, and usage string. +// The argument p points to a int32[] variable in which to store the value of the flag. +func Int32SliceVar(p *[]int32, name string, value []int32, usage string) { + CommandLine.VarP(newInt32SliceValue(value, p), name, "", usage) +} + +// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash. +func Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) { + CommandLine.VarP(newInt32SliceValue(value, p), name, shorthand, usage) +} + +// Int32Slice defines a []int32 flag with specified name, default value, and usage string. +// The return value is the address of a []int32 variable that stores the value of the flag. +func (f *FlagSet) Int32Slice(name string, value []int32, usage string) *[]int32 { + p := []int32{} + f.Int32SliceVarP(&p, name, "", value, usage) + return &p +} + +// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 { + p := []int32{} + f.Int32SliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// Int32Slice defines a []int32 flag with specified name, default value, and usage string. +// The return value is the address of a []int32 variable that stores the value of the flag. +func Int32Slice(name string, value []int32, usage string) *[]int32 { + return CommandLine.Int32SliceP(name, "", value, usage) +} + +// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash. +func Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 { + return CommandLine.Int32SliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int64.go b/vendor/github.com/spf13/pflag/int64.go new file mode 100644 index 000000000..0026d781d --- /dev/null +++ b/vendor/github.com/spf13/pflag/int64.go @@ -0,0 +1,84 @@ +package pflag + +import "strconv" + +// -- int64 Value +type int64Value int64 + +func newInt64Value(val int64, p *int64) *int64Value { + *p = val + return (*int64Value)(p) +} + +func (i *int64Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 64) + *i = int64Value(v) + return err +} + +func (i *int64Value) Type() string { + return "int64" +} + +func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) } + +func int64Conv(sval string) (interface{}, error) { + return strconv.ParseInt(sval, 0, 64) +} + +// GetInt64 return the int64 value of a flag with the given name +func (f *FlagSet) GetInt64(name string) (int64, error) { + val, err := f.getFlagType(name, "int64", int64Conv) + if err != nil { + return 0, err + } + return val.(int64), nil +} + +// Int64Var defines an int64 flag with specified name, default value, and usage string. +// The argument p points to an int64 variable in which to store the value of the flag. +func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) { + f.VarP(newInt64Value(value, p), name, "", usage) +} + +// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int64VarP(p *int64, name, shorthand string, value int64, usage string) { + f.VarP(newInt64Value(value, p), name, shorthand, usage) +} + +// Int64Var defines an int64 flag with specified name, default value, and usage string. +// The argument p points to an int64 variable in which to store the value of the flag. +func Int64Var(p *int64, name string, value int64, usage string) { + CommandLine.VarP(newInt64Value(value, p), name, "", usage) +} + +// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash. +func Int64VarP(p *int64, name, shorthand string, value int64, usage string) { + CommandLine.VarP(newInt64Value(value, p), name, shorthand, usage) +} + +// Int64 defines an int64 flag with specified name, default value, and usage string. +// The return value is the address of an int64 variable that stores the value of the flag. +func (f *FlagSet) Int64(name string, value int64, usage string) *int64 { + p := new(int64) + f.Int64VarP(p, name, "", value, usage) + return p +} + +// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int64P(name, shorthand string, value int64, usage string) *int64 { + p := new(int64) + f.Int64VarP(p, name, shorthand, value, usage) + return p +} + +// Int64 defines an int64 flag with specified name, default value, and usage string. +// The return value is the address of an int64 variable that stores the value of the flag. +func Int64(name string, value int64, usage string) *int64 { + return CommandLine.Int64P(name, "", value, usage) +} + +// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash. +func Int64P(name, shorthand string, value int64, usage string) *int64 { + return CommandLine.Int64P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int64_slice.go b/vendor/github.com/spf13/pflag/int64_slice.go new file mode 100644 index 000000000..25464638f --- /dev/null +++ b/vendor/github.com/spf13/pflag/int64_slice.go @@ -0,0 +1,166 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- int64Slice Value +type int64SliceValue struct { + value *[]int64 + changed bool +} + +func newInt64SliceValue(val []int64, p *[]int64) *int64SliceValue { + isv := new(int64SliceValue) + isv.value = p + *isv.value = val + return isv +} + +func (s *int64SliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]int64, len(ss)) + for i, d := range ss { + var err error + out[i], err = strconv.ParseInt(d, 0, 64) + if err != nil { + return err + } + + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *int64SliceValue) Type() string { + return "int64Slice" +} + +func (s *int64SliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%d", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func (s *int64SliceValue) fromString(val string) (int64, error) { + return strconv.ParseInt(val, 0, 64) +} + +func (s *int64SliceValue) toString(val int64) string { + return fmt.Sprintf("%d", val) +} + +func (s *int64SliceValue) Append(val string) error { + i, err := s.fromString(val) + if err != nil { + return err + } + *s.value = append(*s.value, i) + return nil +} + +func (s *int64SliceValue) Replace(val []string) error { + out := make([]int64, len(val)) + for i, d := range val { + var err error + out[i], err = s.fromString(d) + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *int64SliceValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = s.toString(d) + } + return out +} + +func int64SliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []int64{}, nil + } + ss := strings.Split(val, ",") + out := make([]int64, len(ss)) + for i, d := range ss { + var err error + out[i], err = strconv.ParseInt(d, 0, 64) + if err != nil { + return nil, err + } + + } + return out, nil +} + +// GetInt64Slice return the []int64 value of a flag with the given name +func (f *FlagSet) GetInt64Slice(name string) ([]int64, error) { + val, err := f.getFlagType(name, "int64Slice", int64SliceConv) + if err != nil { + return []int64{}, err + } + return val.([]int64), nil +} + +// Int64SliceVar defines a int64Slice flag with specified name, default value, and usage string. +// The argument p points to a []int64 variable in which to store the value of the flag. +func (f *FlagSet) Int64SliceVar(p *[]int64, name string, value []int64, usage string) { + f.VarP(newInt64SliceValue(value, p), name, "", usage) +} + +// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) { + f.VarP(newInt64SliceValue(value, p), name, shorthand, usage) +} + +// Int64SliceVar defines a int64[] flag with specified name, default value, and usage string. +// The argument p points to a int64[] variable in which to store the value of the flag. +func Int64SliceVar(p *[]int64, name string, value []int64, usage string) { + CommandLine.VarP(newInt64SliceValue(value, p), name, "", usage) +} + +// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash. +func Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) { + CommandLine.VarP(newInt64SliceValue(value, p), name, shorthand, usage) +} + +// Int64Slice defines a []int64 flag with specified name, default value, and usage string. +// The return value is the address of a []int64 variable that stores the value of the flag. +func (f *FlagSet) Int64Slice(name string, value []int64, usage string) *[]int64 { + p := []int64{} + f.Int64SliceVarP(&p, name, "", value, usage) + return &p +} + +// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 { + p := []int64{} + f.Int64SliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// Int64Slice defines a []int64 flag with specified name, default value, and usage string. +// The return value is the address of a []int64 variable that stores the value of the flag. +func Int64Slice(name string, value []int64, usage string) *[]int64 { + return CommandLine.Int64SliceP(name, "", value, usage) +} + +// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash. +func Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 { + return CommandLine.Int64SliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int8.go b/vendor/github.com/spf13/pflag/int8.go new file mode 100644 index 000000000..4da92228e --- /dev/null +++ b/vendor/github.com/spf13/pflag/int8.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- int8 Value +type int8Value int8 + +func newInt8Value(val int8, p *int8) *int8Value { + *p = val + return (*int8Value)(p) +} + +func (i *int8Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 8) + *i = int8Value(v) + return err +} + +func (i *int8Value) Type() string { + return "int8" +} + +func (i *int8Value) String() string { return strconv.FormatInt(int64(*i), 10) } + +func int8Conv(sval string) (interface{}, error) { + v, err := strconv.ParseInt(sval, 0, 8) + if err != nil { + return 0, err + } + return int8(v), nil +} + +// GetInt8 return the int8 value of a flag with the given name +func (f *FlagSet) GetInt8(name string) (int8, error) { + val, err := f.getFlagType(name, "int8", int8Conv) + if err != nil { + return 0, err + } + return val.(int8), nil +} + +// Int8Var defines an int8 flag with specified name, default value, and usage string. +// The argument p points to an int8 variable in which to store the value of the flag. +func (f *FlagSet) Int8Var(p *int8, name string, value int8, usage string) { + f.VarP(newInt8Value(value, p), name, "", usage) +} + +// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int8VarP(p *int8, name, shorthand string, value int8, usage string) { + f.VarP(newInt8Value(value, p), name, shorthand, usage) +} + +// Int8Var defines an int8 flag with specified name, default value, and usage string. +// The argument p points to an int8 variable in which to store the value of the flag. +func Int8Var(p *int8, name string, value int8, usage string) { + CommandLine.VarP(newInt8Value(value, p), name, "", usage) +} + +// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash. +func Int8VarP(p *int8, name, shorthand string, value int8, usage string) { + CommandLine.VarP(newInt8Value(value, p), name, shorthand, usage) +} + +// Int8 defines an int8 flag with specified name, default value, and usage string. +// The return value is the address of an int8 variable that stores the value of the flag. +func (f *FlagSet) Int8(name string, value int8, usage string) *int8 { + p := new(int8) + f.Int8VarP(p, name, "", value, usage) + return p +} + +// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int8P(name, shorthand string, value int8, usage string) *int8 { + p := new(int8) + f.Int8VarP(p, name, shorthand, value, usage) + return p +} + +// Int8 defines an int8 flag with specified name, default value, and usage string. +// The return value is the address of an int8 variable that stores the value of the flag. +func Int8(name string, value int8, usage string) *int8 { + return CommandLine.Int8P(name, "", value, usage) +} + +// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash. +func Int8P(name, shorthand string, value int8, usage string) *int8 { + return CommandLine.Int8P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int_slice.go b/vendor/github.com/spf13/pflag/int_slice.go new file mode 100644 index 000000000..e71c39d91 --- /dev/null +++ b/vendor/github.com/spf13/pflag/int_slice.go @@ -0,0 +1,158 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- intSlice Value +type intSliceValue struct { + value *[]int + changed bool +} + +func newIntSliceValue(val []int, p *[]int) *intSliceValue { + isv := new(intSliceValue) + isv.value = p + *isv.value = val + return isv +} + +func (s *intSliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]int, len(ss)) + for i, d := range ss { + var err error + out[i], err = strconv.Atoi(d) + if err != nil { + return err + } + + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *intSliceValue) Type() string { + return "intSlice" +} + +func (s *intSliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%d", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func (s *intSliceValue) Append(val string) error { + i, err := strconv.Atoi(val) + if err != nil { + return err + } + *s.value = append(*s.value, i) + return nil +} + +func (s *intSliceValue) Replace(val []string) error { + out := make([]int, len(val)) + for i, d := range val { + var err error + out[i], err = strconv.Atoi(d) + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *intSliceValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = strconv.Itoa(d) + } + return out +} + +func intSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []int{}, nil + } + ss := strings.Split(val, ",") + out := make([]int, len(ss)) + for i, d := range ss { + var err error + out[i], err = strconv.Atoi(d) + if err != nil { + return nil, err + } + + } + return out, nil +} + +// GetIntSlice return the []int value of a flag with the given name +func (f *FlagSet) GetIntSlice(name string) ([]int, error) { + val, err := f.getFlagType(name, "intSlice", intSliceConv) + if err != nil { + return []int{}, err + } + return val.([]int), nil +} + +// IntSliceVar defines a intSlice flag with specified name, default value, and usage string. +// The argument p points to a []int variable in which to store the value of the flag. +func (f *FlagSet) IntSliceVar(p *[]int, name string, value []int, usage string) { + f.VarP(newIntSliceValue(value, p), name, "", usage) +} + +// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) { + f.VarP(newIntSliceValue(value, p), name, shorthand, usage) +} + +// IntSliceVar defines a int[] flag with specified name, default value, and usage string. +// The argument p points to a int[] variable in which to store the value of the flag. +func IntSliceVar(p *[]int, name string, value []int, usage string) { + CommandLine.VarP(newIntSliceValue(value, p), name, "", usage) +} + +// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash. +func IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) { + CommandLine.VarP(newIntSliceValue(value, p), name, shorthand, usage) +} + +// IntSlice defines a []int flag with specified name, default value, and usage string. +// The return value is the address of a []int variable that stores the value of the flag. +func (f *FlagSet) IntSlice(name string, value []int, usage string) *[]int { + p := []int{} + f.IntSliceVarP(&p, name, "", value, usage) + return &p +} + +// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IntSliceP(name, shorthand string, value []int, usage string) *[]int { + p := []int{} + f.IntSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// IntSlice defines a []int flag with specified name, default value, and usage string. +// The return value is the address of a []int variable that stores the value of the flag. +func IntSlice(name string, value []int, usage string) *[]int { + return CommandLine.IntSliceP(name, "", value, usage) +} + +// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash. +func IntSliceP(name, shorthand string, value []int, usage string) *[]int { + return CommandLine.IntSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ip.go b/vendor/github.com/spf13/pflag/ip.go new file mode 100644 index 000000000..3d414ba69 --- /dev/null +++ b/vendor/github.com/spf13/pflag/ip.go @@ -0,0 +1,94 @@ +package pflag + +import ( + "fmt" + "net" + "strings" +) + +// -- net.IP value +type ipValue net.IP + +func newIPValue(val net.IP, p *net.IP) *ipValue { + *p = val + return (*ipValue)(p) +} + +func (i *ipValue) String() string { return net.IP(*i).String() } +func (i *ipValue) Set(s string) error { + ip := net.ParseIP(strings.TrimSpace(s)) + if ip == nil { + return fmt.Errorf("failed to parse IP: %q", s) + } + *i = ipValue(ip) + return nil +} + +func (i *ipValue) Type() string { + return "ip" +} + +func ipConv(sval string) (interface{}, error) { + ip := net.ParseIP(sval) + if ip != nil { + return ip, nil + } + return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval) +} + +// GetIP return the net.IP value of a flag with the given name +func (f *FlagSet) GetIP(name string) (net.IP, error) { + val, err := f.getFlagType(name, "ip", ipConv) + if err != nil { + return nil, err + } + return val.(net.IP), nil +} + +// IPVar defines an net.IP flag with specified name, default value, and usage string. +// The argument p points to an net.IP variable in which to store the value of the flag. +func (f *FlagSet) IPVar(p *net.IP, name string, value net.IP, usage string) { + f.VarP(newIPValue(value, p), name, "", usage) +} + +// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) { + f.VarP(newIPValue(value, p), name, shorthand, usage) +} + +// IPVar defines an net.IP flag with specified name, default value, and usage string. +// The argument p points to an net.IP variable in which to store the value of the flag. +func IPVar(p *net.IP, name string, value net.IP, usage string) { + CommandLine.VarP(newIPValue(value, p), name, "", usage) +} + +// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash. +func IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) { + CommandLine.VarP(newIPValue(value, p), name, shorthand, usage) +} + +// IP defines an net.IP flag with specified name, default value, and usage string. +// The return value is the address of an net.IP variable that stores the value of the flag. +func (f *FlagSet) IP(name string, value net.IP, usage string) *net.IP { + p := new(net.IP) + f.IPVarP(p, name, "", value, usage) + return p +} + +// IPP is like IP, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPP(name, shorthand string, value net.IP, usage string) *net.IP { + p := new(net.IP) + f.IPVarP(p, name, shorthand, value, usage) + return p +} + +// IP defines an net.IP flag with specified name, default value, and usage string. +// The return value is the address of an net.IP variable that stores the value of the flag. +func IP(name string, value net.IP, usage string) *net.IP { + return CommandLine.IPP(name, "", value, usage) +} + +// IPP is like IP, but accepts a shorthand letter that can be used after a single dash. +func IPP(name, shorthand string, value net.IP, usage string) *net.IP { + return CommandLine.IPP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ip_slice.go b/vendor/github.com/spf13/pflag/ip_slice.go new file mode 100644 index 000000000..775faae4f --- /dev/null +++ b/vendor/github.com/spf13/pflag/ip_slice.go @@ -0,0 +1,186 @@ +package pflag + +import ( + "fmt" + "io" + "net" + "strings" +) + +// -- ipSlice Value +type ipSliceValue struct { + value *[]net.IP + changed bool +} + +func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue { + ipsv := new(ipSliceValue) + ipsv.value = p + *ipsv.value = val + return ipsv +} + +// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag. +// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended. +func (s *ipSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + ipStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse ip values into slice + out := make([]net.IP, 0, len(ipStrSlice)) + for _, ipStr := range ipStrSlice { + ip := net.ParseIP(strings.TrimSpace(ipStr)) + if ip == nil { + return fmt.Errorf("invalid string being converted to IP address: %s", ipStr) + } + out = append(out, ip) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *ipSliceValue) Type() string { + return "ipSlice" +} + +// String defines a "native" format for this net.IP slice flag value. +func (s *ipSliceValue) String() string { + + ipStrSlice := make([]string, len(*s.value)) + for i, ip := range *s.value { + ipStrSlice[i] = ip.String() + } + + out, _ := writeAsCSV(ipStrSlice) + + return "[" + out + "]" +} + +func (s *ipSliceValue) fromString(val string) (net.IP, error) { + return net.ParseIP(strings.TrimSpace(val)), nil +} + +func (s *ipSliceValue) toString(val net.IP) string { + return val.String() +} + +func (s *ipSliceValue) Append(val string) error { + i, err := s.fromString(val) + if err != nil { + return err + } + *s.value = append(*s.value, i) + return nil +} + +func (s *ipSliceValue) Replace(val []string) error { + out := make([]net.IP, len(val)) + for i, d := range val { + var err error + out[i], err = s.fromString(d) + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *ipSliceValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = s.toString(d) + } + return out +} + +func ipSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []net.IP{}, nil + } + ss := strings.Split(val, ",") + out := make([]net.IP, len(ss)) + for i, sval := range ss { + ip := net.ParseIP(strings.TrimSpace(sval)) + if ip == nil { + return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval) + } + out[i] = ip + } + return out, nil +} + +// GetIPSlice returns the []net.IP value of a flag with the given name +func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) { + val, err := f.getFlagType(name, "ipSlice", ipSliceConv) + if err != nil { + return []net.IP{}, err + } + return val.([]net.IP), nil +} + +// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string. +// The argument p points to a []net.IP variable in which to store the value of the flag. +func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { + f.VarP(newIPSliceValue(value, p), name, "", usage) +} + +// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { + f.VarP(newIPSliceValue(value, p), name, shorthand, usage) +} + +// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string. +// The argument p points to a []net.IP variable in which to store the value of the flag. +func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { + CommandLine.VarP(newIPSliceValue(value, p), name, "", usage) +} + +// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. +func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { + CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage) +} + +// IPSlice defines a []net.IP flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of that flag. +func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP { + p := []net.IP{} + f.IPSliceVarP(&p, name, "", value, usage) + return &p +} + +// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { + p := []net.IP{} + f.IPSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// IPSlice defines a []net.IP flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of the flag. +func IPSlice(name string, value []net.IP, usage string) *[]net.IP { + return CommandLine.IPSliceP(name, "", value, usage) +} + +// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. +func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { + return CommandLine.IPSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ipmask.go b/vendor/github.com/spf13/pflag/ipmask.go new file mode 100644 index 000000000..5bd44bd21 --- /dev/null +++ b/vendor/github.com/spf13/pflag/ipmask.go @@ -0,0 +1,122 @@ +package pflag + +import ( + "fmt" + "net" + "strconv" +) + +// -- net.IPMask value +type ipMaskValue net.IPMask + +func newIPMaskValue(val net.IPMask, p *net.IPMask) *ipMaskValue { + *p = val + return (*ipMaskValue)(p) +} + +func (i *ipMaskValue) String() string { return net.IPMask(*i).String() } +func (i *ipMaskValue) Set(s string) error { + ip := ParseIPv4Mask(s) + if ip == nil { + return fmt.Errorf("failed to parse IP mask: %q", s) + } + *i = ipMaskValue(ip) + return nil +} + +func (i *ipMaskValue) Type() string { + return "ipMask" +} + +// ParseIPv4Mask written in IP form (e.g. 255.255.255.0). +// This function should really belong to the net package. +func ParseIPv4Mask(s string) net.IPMask { + mask := net.ParseIP(s) + if mask == nil { + if len(s) != 8 { + return nil + } + // net.IPMask.String() actually outputs things like ffffff00 + // so write a horrible parser for that as well :-( + m := []int{} + for i := 0; i < 4; i++ { + b := "0x" + s[2*i:2*i+2] + d, err := strconv.ParseInt(b, 0, 0) + if err != nil { + return nil + } + m = append(m, int(d)) + } + s := fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3]) + mask = net.ParseIP(s) + if mask == nil { + return nil + } + } + return net.IPv4Mask(mask[12], mask[13], mask[14], mask[15]) +} + +func parseIPv4Mask(sval string) (interface{}, error) { + mask := ParseIPv4Mask(sval) + if mask == nil { + return nil, fmt.Errorf("unable to parse %s as net.IPMask", sval) + } + return mask, nil +} + +// GetIPv4Mask return the net.IPv4Mask value of a flag with the given name +func (f *FlagSet) GetIPv4Mask(name string) (net.IPMask, error) { + val, err := f.getFlagType(name, "ipMask", parseIPv4Mask) + if err != nil { + return nil, err + } + return val.(net.IPMask), nil +} + +// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string. +// The argument p points to an net.IPMask variable in which to store the value of the flag. +func (f *FlagSet) IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) { + f.VarP(newIPMaskValue(value, p), name, "", usage) +} + +// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) { + f.VarP(newIPMaskValue(value, p), name, shorthand, usage) +} + +// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string. +// The argument p points to an net.IPMask variable in which to store the value of the flag. +func IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) { + CommandLine.VarP(newIPMaskValue(value, p), name, "", usage) +} + +// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash. +func IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) { + CommandLine.VarP(newIPMaskValue(value, p), name, shorthand, usage) +} + +// IPMask defines an net.IPMask flag with specified name, default value, and usage string. +// The return value is the address of an net.IPMask variable that stores the value of the flag. +func (f *FlagSet) IPMask(name string, value net.IPMask, usage string) *net.IPMask { + p := new(net.IPMask) + f.IPMaskVarP(p, name, "", value, usage) + return p +} + +// IPMaskP is like IPMask, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask { + p := new(net.IPMask) + f.IPMaskVarP(p, name, shorthand, value, usage) + return p +} + +// IPMask defines an net.IPMask flag with specified name, default value, and usage string. +// The return value is the address of an net.IPMask variable that stores the value of the flag. +func IPMask(name string, value net.IPMask, usage string) *net.IPMask { + return CommandLine.IPMaskP(name, "", value, usage) +} + +// IPMaskP is like IP, but accepts a shorthand letter that can be used after a single dash. +func IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask { + return CommandLine.IPMaskP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ipnet.go b/vendor/github.com/spf13/pflag/ipnet.go new file mode 100644 index 000000000..e2c1b8bcd --- /dev/null +++ b/vendor/github.com/spf13/pflag/ipnet.go @@ -0,0 +1,98 @@ +package pflag + +import ( + "fmt" + "net" + "strings" +) + +// IPNet adapts net.IPNet for use as a flag. +type ipNetValue net.IPNet + +func (ipnet ipNetValue) String() string { + n := net.IPNet(ipnet) + return n.String() +} + +func (ipnet *ipNetValue) Set(value string) error { + _, n, err := net.ParseCIDR(strings.TrimSpace(value)) + if err != nil { + return err + } + *ipnet = ipNetValue(*n) + return nil +} + +func (*ipNetValue) Type() string { + return "ipNet" +} + +func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue { + *p = val + return (*ipNetValue)(p) +} + +func ipNetConv(sval string) (interface{}, error) { + _, n, err := net.ParseCIDR(strings.TrimSpace(sval)) + if err == nil { + return *n, nil + } + return nil, fmt.Errorf("invalid string being converted to IPNet: %s", sval) +} + +// GetIPNet return the net.IPNet value of a flag with the given name +func (f *FlagSet) GetIPNet(name string) (net.IPNet, error) { + val, err := f.getFlagType(name, "ipNet", ipNetConv) + if err != nil { + return net.IPNet{}, err + } + return val.(net.IPNet), nil +} + +// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string. +// The argument p points to an net.IPNet variable in which to store the value of the flag. +func (f *FlagSet) IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) { + f.VarP(newIPNetValue(value, p), name, "", usage) +} + +// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) { + f.VarP(newIPNetValue(value, p), name, shorthand, usage) +} + +// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string. +// The argument p points to an net.IPNet variable in which to store the value of the flag. +func IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) { + CommandLine.VarP(newIPNetValue(value, p), name, "", usage) +} + +// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash. +func IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) { + CommandLine.VarP(newIPNetValue(value, p), name, shorthand, usage) +} + +// IPNet defines an net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of an net.IPNet variable that stores the value of the flag. +func (f *FlagSet) IPNet(name string, value net.IPNet, usage string) *net.IPNet { + p := new(net.IPNet) + f.IPNetVarP(p, name, "", value, usage) + return p +} + +// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet { + p := new(net.IPNet) + f.IPNetVarP(p, name, shorthand, value, usage) + return p +} + +// IPNet defines an net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of an net.IPNet variable that stores the value of the flag. +func IPNet(name string, value net.IPNet, usage string) *net.IPNet { + return CommandLine.IPNetP(name, "", value, usage) +} + +// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash. +func IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet { + return CommandLine.IPNetP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string.go b/vendor/github.com/spf13/pflag/string.go new file mode 100644 index 000000000..04e0a26ff --- /dev/null +++ b/vendor/github.com/spf13/pflag/string.go @@ -0,0 +1,80 @@ +package pflag + +// -- string Value +type stringValue string + +func newStringValue(val string, p *string) *stringValue { + *p = val + return (*stringValue)(p) +} + +func (s *stringValue) Set(val string) error { + *s = stringValue(val) + return nil +} +func (s *stringValue) Type() string { + return "string" +} + +func (s *stringValue) String() string { return string(*s) } + +func stringConv(sval string) (interface{}, error) { + return sval, nil +} + +// GetString return the string value of a flag with the given name +func (f *FlagSet) GetString(name string) (string, error) { + val, err := f.getFlagType(name, "string", stringConv) + if err != nil { + return "", err + } + return val.(string), nil +} + +// StringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a string variable in which to store the value of the flag. +func (f *FlagSet) StringVar(p *string, name string, value string, usage string) { + f.VarP(newStringValue(value, p), name, "", usage) +} + +// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringVarP(p *string, name, shorthand string, value string, usage string) { + f.VarP(newStringValue(value, p), name, shorthand, usage) +} + +// StringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a string variable in which to store the value of the flag. +func StringVar(p *string, name string, value string, usage string) { + CommandLine.VarP(newStringValue(value, p), name, "", usage) +} + +// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash. +func StringVarP(p *string, name, shorthand string, value string, usage string) { + CommandLine.VarP(newStringValue(value, p), name, shorthand, usage) +} + +// String defines a string flag with specified name, default value, and usage string. +// The return value is the address of a string variable that stores the value of the flag. +func (f *FlagSet) String(name string, value string, usage string) *string { + p := new(string) + f.StringVarP(p, name, "", value, usage) + return p +} + +// StringP is like String, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringP(name, shorthand string, value string, usage string) *string { + p := new(string) + f.StringVarP(p, name, shorthand, value, usage) + return p +} + +// String defines a string flag with specified name, default value, and usage string. +// The return value is the address of a string variable that stores the value of the flag. +func String(name string, value string, usage string) *string { + return CommandLine.StringP(name, "", value, usage) +} + +// StringP is like String, but accepts a shorthand letter that can be used after a single dash. +func StringP(name, shorthand string, value string, usage string) *string { + return CommandLine.StringP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go new file mode 100644 index 000000000..4894af818 --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_array.go @@ -0,0 +1,129 @@ +package pflag + +// -- stringArray Value +type stringArrayValue struct { + value *[]string + changed bool +} + +func newStringArrayValue(val []string, p *[]string) *stringArrayValue { + ssv := new(stringArrayValue) + ssv.value = p + *ssv.value = val + return ssv +} + +func (s *stringArrayValue) Set(val string) error { + if !s.changed { + *s.value = []string{val} + s.changed = true + } else { + *s.value = append(*s.value, val) + } + return nil +} + +func (s *stringArrayValue) Append(val string) error { + *s.value = append(*s.value, val) + return nil +} + +func (s *stringArrayValue) Replace(val []string) error { + out := make([]string, len(val)) + for i, d := range val { + var err error + out[i] = d + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *stringArrayValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = d + } + return out +} + +func (s *stringArrayValue) Type() string { + return "stringArray" +} + +func (s *stringArrayValue) String() string { + str, _ := writeAsCSV(*s.value) + return "[" + str + "]" +} + +func stringArrayConv(sval string) (interface{}, error) { + sval = sval[1 : len(sval)-1] + // An empty string would cause a array with one (empty) string + if len(sval) == 0 { + return []string{}, nil + } + return readAsCSV(sval) +} + +// GetStringArray return the []string value of a flag with the given name +func (f *FlagSet) GetStringArray(name string) ([]string, error) { + val, err := f.getFlagType(name, "stringArray", stringArrayConv) + if err != nil { + return []string{}, err + } + return val.([]string), nil +} + +// StringArrayVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the values of the multiple flags. +// The value of each argument will not try to be separated by comma. Use a StringSlice for that. +func (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) { + f.VarP(newStringArrayValue(value, p), name, "", usage) +} + +// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) { + f.VarP(newStringArrayValue(value, p), name, shorthand, usage) +} + +// StringArrayVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the value of the flag. +// The value of each argument will not try to be separated by comma. Use a StringSlice for that. +func StringArrayVar(p *[]string, name string, value []string, usage string) { + CommandLine.VarP(newStringArrayValue(value, p), name, "", usage) +} + +// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash. +func StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) { + CommandLine.VarP(newStringArrayValue(value, p), name, shorthand, usage) +} + +// StringArray defines a string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma. Use a StringSlice for that. +func (f *FlagSet) StringArray(name string, value []string, usage string) *[]string { + p := []string{} + f.StringArrayVarP(&p, name, "", value, usage) + return &p +} + +// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringArrayP(name, shorthand string, value []string, usage string) *[]string { + p := []string{} + f.StringArrayVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringArray defines a string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma. Use a StringSlice for that. +func StringArray(name string, value []string, usage string) *[]string { + return CommandLine.StringArrayP(name, "", value, usage) +} + +// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash. +func StringArrayP(name, shorthand string, value []string, usage string) *[]string { + return CommandLine.StringArrayP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_slice.go b/vendor/github.com/spf13/pflag/string_slice.go new file mode 100644 index 000000000..3cb2e69db --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_slice.go @@ -0,0 +1,163 @@ +package pflag + +import ( + "bytes" + "encoding/csv" + "strings" +) + +// -- stringSlice Value +type stringSliceValue struct { + value *[]string + changed bool +} + +func newStringSliceValue(val []string, p *[]string) *stringSliceValue { + ssv := new(stringSliceValue) + ssv.value = p + *ssv.value = val + return ssv +} + +func readAsCSV(val string) ([]string, error) { + if val == "" { + return []string{}, nil + } + stringReader := strings.NewReader(val) + csvReader := csv.NewReader(stringReader) + return csvReader.Read() +} + +func writeAsCSV(vals []string) (string, error) { + b := &bytes.Buffer{} + w := csv.NewWriter(b) + err := w.Write(vals) + if err != nil { + return "", err + } + w.Flush() + return strings.TrimSuffix(b.String(), "\n"), nil +} + +func (s *stringSliceValue) Set(val string) error { + v, err := readAsCSV(val) + if err != nil { + return err + } + if !s.changed { + *s.value = v + } else { + *s.value = append(*s.value, v...) + } + s.changed = true + return nil +} + +func (s *stringSliceValue) Type() string { + return "stringSlice" +} + +func (s *stringSliceValue) String() string { + str, _ := writeAsCSV(*s.value) + return "[" + str + "]" +} + +func (s *stringSliceValue) Append(val string) error { + *s.value = append(*s.value, val) + return nil +} + +func (s *stringSliceValue) Replace(val []string) error { + *s.value = val + return nil +} + +func (s *stringSliceValue) GetSlice() []string { + return *s.value +} + +func stringSliceConv(sval string) (interface{}, error) { + sval = sval[1 : len(sval)-1] + // An empty string would cause a slice with one (empty) string + if len(sval) == 0 { + return []string{}, nil + } + return readAsCSV(sval) +} + +// GetStringSlice return the []string value of a flag with the given name +func (f *FlagSet) GetStringSlice(name string) ([]string, error) { + val, err := f.getFlagType(name, "stringSlice", stringSliceConv) + if err != nil { + return []string{}, err + } + return val.([]string), nil +} + +// StringSliceVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the value of the flag. +// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. +// For example: +// --ss="v1,v2" --ss="v3" +// will result in +// []string{"v1", "v2", "v3"} +func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) { + f.VarP(newStringSliceValue(value, p), name, "", usage) +} + +// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) { + f.VarP(newStringSliceValue(value, p), name, shorthand, usage) +} + +// StringSliceVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the value of the flag. +// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. +// For example: +// --ss="v1,v2" --ss="v3" +// will result in +// []string{"v1", "v2", "v3"} +func StringSliceVar(p *[]string, name string, value []string, usage string) { + CommandLine.VarP(newStringSliceValue(value, p), name, "", usage) +} + +// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash. +func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) { + CommandLine.VarP(newStringSliceValue(value, p), name, shorthand, usage) +} + +// StringSlice defines a string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. +// For example: +// --ss="v1,v2" --ss="v3" +// will result in +// []string{"v1", "v2", "v3"} +func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string { + p := []string{} + f.StringSliceVarP(&p, name, "", value, usage) + return &p +} + +// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage string) *[]string { + p := []string{} + f.StringSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringSlice defines a string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. +// For example: +// --ss="v1,v2" --ss="v3" +// will result in +// []string{"v1", "v2", "v3"} +func StringSlice(name string, value []string, usage string) *[]string { + return CommandLine.StringSliceP(name, "", value, usage) +} + +// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash. +func StringSliceP(name, shorthand string, value []string, usage string) *[]string { + return CommandLine.StringSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_to_int.go b/vendor/github.com/spf13/pflag/string_to_int.go new file mode 100644 index 000000000..5ceda3965 --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_to_int.go @@ -0,0 +1,149 @@ +package pflag + +import ( + "bytes" + "fmt" + "strconv" + "strings" +) + +// -- stringToInt Value +type stringToIntValue struct { + value *map[string]int + changed bool +} + +func newStringToIntValue(val map[string]int, p *map[string]int) *stringToIntValue { + ssv := new(stringToIntValue) + ssv.value = p + *ssv.value = val + return ssv +} + +// Format: a=1,b=2 +func (s *stringToIntValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make(map[string]int, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return fmt.Errorf("%s must be formatted as key=value", pair) + } + var err error + out[kv[0]], err = strconv.Atoi(kv[1]) + if err != nil { + return err + } + } + if !s.changed { + *s.value = out + } else { + for k, v := range out { + (*s.value)[k] = v + } + } + s.changed = true + return nil +} + +func (s *stringToIntValue) Type() string { + return "stringToInt" +} + +func (s *stringToIntValue) String() string { + var buf bytes.Buffer + i := 0 + for k, v := range *s.value { + if i > 0 { + buf.WriteRune(',') + } + buf.WriteString(k) + buf.WriteRune('=') + buf.WriteString(strconv.Itoa(v)) + i++ + } + return "[" + buf.String() + "]" +} + +func stringToIntConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // An empty string would cause an empty map + if len(val) == 0 { + return map[string]int{}, nil + } + ss := strings.Split(val, ",") + out := make(map[string]int, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return nil, fmt.Errorf("%s must be formatted as key=value", pair) + } + var err error + out[kv[0]], err = strconv.Atoi(kv[1]) + if err != nil { + return nil, err + } + } + return out, nil +} + +// GetStringToInt return the map[string]int value of a flag with the given name +func (f *FlagSet) GetStringToInt(name string) (map[string]int, error) { + val, err := f.getFlagType(name, "stringToInt", stringToIntConv) + if err != nil { + return map[string]int{}, err + } + return val.(map[string]int), nil +} + +// StringToIntVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]int variable in which to store the values of the multiple flags. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) { + f.VarP(newStringToIntValue(value, p), name, "", usage) +} + +// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) { + f.VarP(newStringToIntValue(value, p), name, shorthand, usage) +} + +// StringToIntVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]int variable in which to store the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) { + CommandLine.VarP(newStringToIntValue(value, p), name, "", usage) +} + +// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash. +func StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) { + CommandLine.VarP(newStringToIntValue(value, p), name, shorthand, usage) +} + +// StringToInt defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]int variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToInt(name string, value map[string]int, usage string) *map[string]int { + p := map[string]int{} + f.StringToIntVarP(&p, name, "", value, usage) + return &p +} + +// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int { + p := map[string]int{} + f.StringToIntVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringToInt defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]int variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToInt(name string, value map[string]int, usage string) *map[string]int { + return CommandLine.StringToIntP(name, "", value, usage) +} + +// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash. +func StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int { + return CommandLine.StringToIntP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_to_int64.go b/vendor/github.com/spf13/pflag/string_to_int64.go new file mode 100644 index 000000000..a807a04a0 --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_to_int64.go @@ -0,0 +1,149 @@ +package pflag + +import ( + "bytes" + "fmt" + "strconv" + "strings" +) + +// -- stringToInt64 Value +type stringToInt64Value struct { + value *map[string]int64 + changed bool +} + +func newStringToInt64Value(val map[string]int64, p *map[string]int64) *stringToInt64Value { + ssv := new(stringToInt64Value) + ssv.value = p + *ssv.value = val + return ssv +} + +// Format: a=1,b=2 +func (s *stringToInt64Value) Set(val string) error { + ss := strings.Split(val, ",") + out := make(map[string]int64, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return fmt.Errorf("%s must be formatted as key=value", pair) + } + var err error + out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64) + if err != nil { + return err + } + } + if !s.changed { + *s.value = out + } else { + for k, v := range out { + (*s.value)[k] = v + } + } + s.changed = true + return nil +} + +func (s *stringToInt64Value) Type() string { + return "stringToInt64" +} + +func (s *stringToInt64Value) String() string { + var buf bytes.Buffer + i := 0 + for k, v := range *s.value { + if i > 0 { + buf.WriteRune(',') + } + buf.WriteString(k) + buf.WriteRune('=') + buf.WriteString(strconv.FormatInt(v, 10)) + i++ + } + return "[" + buf.String() + "]" +} + +func stringToInt64Conv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // An empty string would cause an empty map + if len(val) == 0 { + return map[string]int64{}, nil + } + ss := strings.Split(val, ",") + out := make(map[string]int64, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return nil, fmt.Errorf("%s must be formatted as key=value", pair) + } + var err error + out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64) + if err != nil { + return nil, err + } + } + return out, nil +} + +// GetStringToInt64 return the map[string]int64 value of a flag with the given name +func (f *FlagSet) GetStringToInt64(name string) (map[string]int64, error) { + val, err := f.getFlagType(name, "stringToInt64", stringToInt64Conv) + if err != nil { + return map[string]int64{}, err + } + return val.(map[string]int64), nil +} + +// StringToInt64Var defines a string flag with specified name, default value, and usage string. +// The argument p point64s to a map[string]int64 variable in which to store the values of the multiple flags. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) { + f.VarP(newStringToInt64Value(value, p), name, "", usage) +} + +// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) { + f.VarP(newStringToInt64Value(value, p), name, shorthand, usage) +} + +// StringToInt64Var defines a string flag with specified name, default value, and usage string. +// The argument p point64s to a map[string]int64 variable in which to store the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) { + CommandLine.VarP(newStringToInt64Value(value, p), name, "", usage) +} + +// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash. +func StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) { + CommandLine.VarP(newStringToInt64Value(value, p), name, shorthand, usage) +} + +// StringToInt64 defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]int64 variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 { + p := map[string]int64{} + f.StringToInt64VarP(&p, name, "", value, usage) + return &p +} + +// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 { + p := map[string]int64{} + f.StringToInt64VarP(&p, name, shorthand, value, usage) + return &p +} + +// StringToInt64 defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]int64 variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 { + return CommandLine.StringToInt64P(name, "", value, usage) +} + +// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash. +func StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 { + return CommandLine.StringToInt64P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_to_string.go b/vendor/github.com/spf13/pflag/string_to_string.go new file mode 100644 index 000000000..890a01afc --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_to_string.go @@ -0,0 +1,160 @@ +package pflag + +import ( + "bytes" + "encoding/csv" + "fmt" + "strings" +) + +// -- stringToString Value +type stringToStringValue struct { + value *map[string]string + changed bool +} + +func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue { + ssv := new(stringToStringValue) + ssv.value = p + *ssv.value = val + return ssv +} + +// Format: a=1,b=2 +func (s *stringToStringValue) Set(val string) error { + var ss []string + n := strings.Count(val, "=") + switch n { + case 0: + return fmt.Errorf("%s must be formatted as key=value", val) + case 1: + ss = append(ss, strings.Trim(val, `"`)) + default: + r := csv.NewReader(strings.NewReader(val)) + var err error + ss, err = r.Read() + if err != nil { + return err + } + } + + out := make(map[string]string, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return fmt.Errorf("%s must be formatted as key=value", pair) + } + out[kv[0]] = kv[1] + } + if !s.changed { + *s.value = out + } else { + for k, v := range out { + (*s.value)[k] = v + } + } + s.changed = true + return nil +} + +func (s *stringToStringValue) Type() string { + return "stringToString" +} + +func (s *stringToStringValue) String() string { + records := make([]string, 0, len(*s.value)>>1) + for k, v := range *s.value { + records = append(records, k+"="+v) + } + + var buf bytes.Buffer + w := csv.NewWriter(&buf) + if err := w.Write(records); err != nil { + panic(err) + } + w.Flush() + return "[" + strings.TrimSpace(buf.String()) + "]" +} + +func stringToStringConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // An empty string would cause an empty map + if len(val) == 0 { + return map[string]string{}, nil + } + r := csv.NewReader(strings.NewReader(val)) + ss, err := r.Read() + if err != nil { + return nil, err + } + out := make(map[string]string, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return nil, fmt.Errorf("%s must be formatted as key=value", pair) + } + out[kv[0]] = kv[1] + } + return out, nil +} + +// GetStringToString return the map[string]string value of a flag with the given name +func (f *FlagSet) GetStringToString(name string) (map[string]string, error) { + val, err := f.getFlagType(name, "stringToString", stringToStringConv) + if err != nil { + return map[string]string{}, err + } + return val.(map[string]string), nil +} + +// StringToStringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]string variable in which to store the values of the multiple flags. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) { + f.VarP(newStringToStringValue(value, p), name, "", usage) +} + +// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) { + f.VarP(newStringToStringValue(value, p), name, shorthand, usage) +} + +// StringToStringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]string variable in which to store the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) { + CommandLine.VarP(newStringToStringValue(value, p), name, "", usage) +} + +// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash. +func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) { + CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage) +} + +// StringToString defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string { + p := map[string]string{} + f.StringToStringVarP(&p, name, "", value, usage) + return &p +} + +// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string { + p := map[string]string{} + f.StringToStringVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringToString defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToString(name string, value map[string]string, usage string) *map[string]string { + return CommandLine.StringToStringP(name, "", value, usage) +} + +// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash. +func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string { + return CommandLine.StringToStringP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint.go b/vendor/github.com/spf13/pflag/uint.go new file mode 100644 index 000000000..dcbc2b758 --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint Value +type uintValue uint + +func newUintValue(val uint, p *uint) *uintValue { + *p = val + return (*uintValue)(p) +} + +func (i *uintValue) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 64) + *i = uintValue(v) + return err +} + +func (i *uintValue) Type() string { + return "uint" +} + +func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uintConv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 0) + if err != nil { + return 0, err + } + return uint(v), nil +} + +// GetUint return the uint value of a flag with the given name +func (f *FlagSet) GetUint(name string) (uint, error) { + val, err := f.getFlagType(name, "uint", uintConv) + if err != nil { + return 0, err + } + return val.(uint), nil +} + +// UintVar defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) { + f.VarP(newUintValue(value, p), name, "", usage) +} + +// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintVarP(p *uint, name, shorthand string, value uint, usage string) { + f.VarP(newUintValue(value, p), name, shorthand, usage) +} + +// UintVar defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func UintVar(p *uint, name string, value uint, usage string) { + CommandLine.VarP(newUintValue(value, p), name, "", usage) +} + +// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash. +func UintVarP(p *uint, name, shorthand string, value uint, usage string) { + CommandLine.VarP(newUintValue(value, p), name, shorthand, usage) +} + +// Uint defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func (f *FlagSet) Uint(name string, value uint, usage string) *uint { + p := new(uint) + f.UintVarP(p, name, "", value, usage) + return p +} + +// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintP(name, shorthand string, value uint, usage string) *uint { + p := new(uint) + f.UintVarP(p, name, shorthand, value, usage) + return p +} + +// Uint defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func Uint(name string, value uint, usage string) *uint { + return CommandLine.UintP(name, "", value, usage) +} + +// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash. +func UintP(name, shorthand string, value uint, usage string) *uint { + return CommandLine.UintP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint16.go b/vendor/github.com/spf13/pflag/uint16.go new file mode 100644 index 000000000..7e9914edd --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint16.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint16 value +type uint16Value uint16 + +func newUint16Value(val uint16, p *uint16) *uint16Value { + *p = val + return (*uint16Value)(p) +} + +func (i *uint16Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 16) + *i = uint16Value(v) + return err +} + +func (i *uint16Value) Type() string { + return "uint16" +} + +func (i *uint16Value) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uint16Conv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 16) + if err != nil { + return 0, err + } + return uint16(v), nil +} + +// GetUint16 return the uint16 value of a flag with the given name +func (f *FlagSet) GetUint16(name string) (uint16, error) { + val, err := f.getFlagType(name, "uint16", uint16Conv) + if err != nil { + return 0, err + } + return val.(uint16), nil +} + +// Uint16Var defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func (f *FlagSet) Uint16Var(p *uint16, name string, value uint16, usage string) { + f.VarP(newUint16Value(value, p), name, "", usage) +} + +// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) { + f.VarP(newUint16Value(value, p), name, shorthand, usage) +} + +// Uint16Var defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func Uint16Var(p *uint16, name string, value uint16, usage string) { + CommandLine.VarP(newUint16Value(value, p), name, "", usage) +} + +// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash. +func Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) { + CommandLine.VarP(newUint16Value(value, p), name, shorthand, usage) +} + +// Uint16 defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func (f *FlagSet) Uint16(name string, value uint16, usage string) *uint16 { + p := new(uint16) + f.Uint16VarP(p, name, "", value, usage) + return p +} + +// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint16P(name, shorthand string, value uint16, usage string) *uint16 { + p := new(uint16) + f.Uint16VarP(p, name, shorthand, value, usage) + return p +} + +// Uint16 defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func Uint16(name string, value uint16, usage string) *uint16 { + return CommandLine.Uint16P(name, "", value, usage) +} + +// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash. +func Uint16P(name, shorthand string, value uint16, usage string) *uint16 { + return CommandLine.Uint16P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint32.go b/vendor/github.com/spf13/pflag/uint32.go new file mode 100644 index 000000000..d8024539b --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint32.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint32 value +type uint32Value uint32 + +func newUint32Value(val uint32, p *uint32) *uint32Value { + *p = val + return (*uint32Value)(p) +} + +func (i *uint32Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 32) + *i = uint32Value(v) + return err +} + +func (i *uint32Value) Type() string { + return "uint32" +} + +func (i *uint32Value) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uint32Conv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 32) + if err != nil { + return 0, err + } + return uint32(v), nil +} + +// GetUint32 return the uint32 value of a flag with the given name +func (f *FlagSet) GetUint32(name string) (uint32, error) { + val, err := f.getFlagType(name, "uint32", uint32Conv) + if err != nil { + return 0, err + } + return val.(uint32), nil +} + +// Uint32Var defines a uint32 flag with specified name, default value, and usage string. +// The argument p points to a uint32 variable in which to store the value of the flag. +func (f *FlagSet) Uint32Var(p *uint32, name string, value uint32, usage string) { + f.VarP(newUint32Value(value, p), name, "", usage) +} + +// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) { + f.VarP(newUint32Value(value, p), name, shorthand, usage) +} + +// Uint32Var defines a uint32 flag with specified name, default value, and usage string. +// The argument p points to a uint32 variable in which to store the value of the flag. +func Uint32Var(p *uint32, name string, value uint32, usage string) { + CommandLine.VarP(newUint32Value(value, p), name, "", usage) +} + +// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash. +func Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) { + CommandLine.VarP(newUint32Value(value, p), name, shorthand, usage) +} + +// Uint32 defines a uint32 flag with specified name, default value, and usage string. +// The return value is the address of a uint32 variable that stores the value of the flag. +func (f *FlagSet) Uint32(name string, value uint32, usage string) *uint32 { + p := new(uint32) + f.Uint32VarP(p, name, "", value, usage) + return p +} + +// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint32P(name, shorthand string, value uint32, usage string) *uint32 { + p := new(uint32) + f.Uint32VarP(p, name, shorthand, value, usage) + return p +} + +// Uint32 defines a uint32 flag with specified name, default value, and usage string. +// The return value is the address of a uint32 variable that stores the value of the flag. +func Uint32(name string, value uint32, usage string) *uint32 { + return CommandLine.Uint32P(name, "", value, usage) +} + +// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash. +func Uint32P(name, shorthand string, value uint32, usage string) *uint32 { + return CommandLine.Uint32P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint64.go b/vendor/github.com/spf13/pflag/uint64.go new file mode 100644 index 000000000..f62240f2c --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint64.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint64 Value +type uint64Value uint64 + +func newUint64Value(val uint64, p *uint64) *uint64Value { + *p = val + return (*uint64Value)(p) +} + +func (i *uint64Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 64) + *i = uint64Value(v) + return err +} + +func (i *uint64Value) Type() string { + return "uint64" +} + +func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uint64Conv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 64) + if err != nil { + return 0, err + } + return uint64(v), nil +} + +// GetUint64 return the uint64 value of a flag with the given name +func (f *FlagSet) GetUint64(name string) (uint64, error) { + val, err := f.getFlagType(name, "uint64", uint64Conv) + if err != nil { + return 0, err + } + return val.(uint64), nil +} + +// Uint64Var defines a uint64 flag with specified name, default value, and usage string. +// The argument p points to a uint64 variable in which to store the value of the flag. +func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) { + f.VarP(newUint64Value(value, p), name, "", usage) +} + +// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) { + f.VarP(newUint64Value(value, p), name, shorthand, usage) +} + +// Uint64Var defines a uint64 flag with specified name, default value, and usage string. +// The argument p points to a uint64 variable in which to store the value of the flag. +func Uint64Var(p *uint64, name string, value uint64, usage string) { + CommandLine.VarP(newUint64Value(value, p), name, "", usage) +} + +// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash. +func Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) { + CommandLine.VarP(newUint64Value(value, p), name, shorthand, usage) +} + +// Uint64 defines a uint64 flag with specified name, default value, and usage string. +// The return value is the address of a uint64 variable that stores the value of the flag. +func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 { + p := new(uint64) + f.Uint64VarP(p, name, "", value, usage) + return p +} + +// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint64P(name, shorthand string, value uint64, usage string) *uint64 { + p := new(uint64) + f.Uint64VarP(p, name, shorthand, value, usage) + return p +} + +// Uint64 defines a uint64 flag with specified name, default value, and usage string. +// The return value is the address of a uint64 variable that stores the value of the flag. +func Uint64(name string, value uint64, usage string) *uint64 { + return CommandLine.Uint64P(name, "", value, usage) +} + +// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash. +func Uint64P(name, shorthand string, value uint64, usage string) *uint64 { + return CommandLine.Uint64P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint8.go b/vendor/github.com/spf13/pflag/uint8.go new file mode 100644 index 000000000..bb0e83c1f --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint8.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint8 Value +type uint8Value uint8 + +func newUint8Value(val uint8, p *uint8) *uint8Value { + *p = val + return (*uint8Value)(p) +} + +func (i *uint8Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 8) + *i = uint8Value(v) + return err +} + +func (i *uint8Value) Type() string { + return "uint8" +} + +func (i *uint8Value) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uint8Conv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 8) + if err != nil { + return 0, err + } + return uint8(v), nil +} + +// GetUint8 return the uint8 value of a flag with the given name +func (f *FlagSet) GetUint8(name string) (uint8, error) { + val, err := f.getFlagType(name, "uint8", uint8Conv) + if err != nil { + return 0, err + } + return val.(uint8), nil +} + +// Uint8Var defines a uint8 flag with specified name, default value, and usage string. +// The argument p points to a uint8 variable in which to store the value of the flag. +func (f *FlagSet) Uint8Var(p *uint8, name string, value uint8, usage string) { + f.VarP(newUint8Value(value, p), name, "", usage) +} + +// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) { + f.VarP(newUint8Value(value, p), name, shorthand, usage) +} + +// Uint8Var defines a uint8 flag with specified name, default value, and usage string. +// The argument p points to a uint8 variable in which to store the value of the flag. +func Uint8Var(p *uint8, name string, value uint8, usage string) { + CommandLine.VarP(newUint8Value(value, p), name, "", usage) +} + +// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash. +func Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) { + CommandLine.VarP(newUint8Value(value, p), name, shorthand, usage) +} + +// Uint8 defines a uint8 flag with specified name, default value, and usage string. +// The return value is the address of a uint8 variable that stores the value of the flag. +func (f *FlagSet) Uint8(name string, value uint8, usage string) *uint8 { + p := new(uint8) + f.Uint8VarP(p, name, "", value, usage) + return p +} + +// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint8P(name, shorthand string, value uint8, usage string) *uint8 { + p := new(uint8) + f.Uint8VarP(p, name, shorthand, value, usage) + return p +} + +// Uint8 defines a uint8 flag with specified name, default value, and usage string. +// The return value is the address of a uint8 variable that stores the value of the flag. +func Uint8(name string, value uint8, usage string) *uint8 { + return CommandLine.Uint8P(name, "", value, usage) +} + +// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash. +func Uint8P(name, shorthand string, value uint8, usage string) *uint8 { + return CommandLine.Uint8P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint_slice.go b/vendor/github.com/spf13/pflag/uint_slice.go new file mode 100644 index 000000000..5fa924835 --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint_slice.go @@ -0,0 +1,168 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- uintSlice Value +type uintSliceValue struct { + value *[]uint + changed bool +} + +func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue { + uisv := new(uintSliceValue) + uisv.value = p + *uisv.value = val + return uisv +} + +func (s *uintSliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]uint, len(ss)) + for i, d := range ss { + u, err := strconv.ParseUint(d, 10, 0) + if err != nil { + return err + } + out[i] = uint(u) + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *uintSliceValue) Type() string { + return "uintSlice" +} + +func (s *uintSliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%d", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func (s *uintSliceValue) fromString(val string) (uint, error) { + t, err := strconv.ParseUint(val, 10, 0) + if err != nil { + return 0, err + } + return uint(t), nil +} + +func (s *uintSliceValue) toString(val uint) string { + return fmt.Sprintf("%d", val) +} + +func (s *uintSliceValue) Append(val string) error { + i, err := s.fromString(val) + if err != nil { + return err + } + *s.value = append(*s.value, i) + return nil +} + +func (s *uintSliceValue) Replace(val []string) error { + out := make([]uint, len(val)) + for i, d := range val { + var err error + out[i], err = s.fromString(d) + if err != nil { + return err + } + } + *s.value = out + return nil +} + +func (s *uintSliceValue) GetSlice() []string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = s.toString(d) + } + return out +} + +func uintSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []uint{}, nil + } + ss := strings.Split(val, ",") + out := make([]uint, len(ss)) + for i, d := range ss { + u, err := strconv.ParseUint(d, 10, 0) + if err != nil { + return nil, err + } + out[i] = uint(u) + } + return out, nil +} + +// GetUintSlice returns the []uint value of a flag with the given name. +func (f *FlagSet) GetUintSlice(name string) ([]uint, error) { + val, err := f.getFlagType(name, "uintSlice", uintSliceConv) + if err != nil { + return []uint{}, err + } + return val.([]uint), nil +} + +// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string. +// The argument p points to a []uint variable in which to store the value of the flag. +func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) { + f.VarP(newUintSliceValue(value, p), name, "", usage) +} + +// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) { + f.VarP(newUintSliceValue(value, p), name, shorthand, usage) +} + +// UintSliceVar defines a uint[] flag with specified name, default value, and usage string. +// The argument p points to a uint[] variable in which to store the value of the flag. +func UintSliceVar(p *[]uint, name string, value []uint, usage string) { + CommandLine.VarP(newUintSliceValue(value, p), name, "", usage) +} + +// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash. +func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) { + CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage) +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint { + p := []uint{} + f.UintSliceVarP(&p, name, "", value, usage) + return &p +} + +// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint { + p := []uint{} + f.UintSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func UintSlice(name string, value []uint, usage string) *[]uint { + return CommandLine.UintSliceP(name, "", value, usage) +} + +// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash. +func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint { + return CommandLine.UintSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/viper/.gitignore b/vendor/github.com/spf13/viper/.gitignore new file mode 100644 index 000000000..d6941f324 --- /dev/null +++ b/vendor/github.com/spf13/viper/.gitignore @@ -0,0 +1,20 @@ +/bin/ +/build/ +/var/ +/vendor/ + +# IDE integration +/.vscode/* +!/.vscode/launch.json +!/.vscode/tasks.json +/.idea/* +!/.idea/codeStyles/ +!/.idea/copyright/ +!/.idea/dataSources.xml +!/.idea/*.iml +!/.idea/externalDependencies.xml +!/.idea/go.imports.xml +!/.idea/modules.xml +!/.idea/runConfigurations/ +!/.idea/scopes/ +!/.idea/sqldialects.xml diff --git a/vendor/github.com/spf13/viper/.golangci.yml b/vendor/github.com/spf13/viper/.golangci.yml new file mode 100644 index 000000000..0ea9249e7 --- /dev/null +++ b/vendor/github.com/spf13/viper/.golangci.yml @@ -0,0 +1,24 @@ +linters-settings: + golint: + min-confidence: 0.1 + goimports: + local-prefixes: github.com/spf13/viper + +linters: + enable-all: true + disable: + - funlen + - maligned + + # TODO: fix me + - wsl + - gochecknoinits + - gosimple + - gochecknoglobals + - errcheck + - lll + - godox + - scopelint + - gocyclo + - gocognit + - gocritic \ No newline at end of file diff --git a/vendor/github.com/spf13/viper/.travis.yml b/vendor/github.com/spf13/viper/.travis.yml new file mode 100644 index 000000000..ed677bbb8 --- /dev/null +++ b/vendor/github.com/spf13/viper/.travis.yml @@ -0,0 +1,32 @@ +go_import_path: github.com/spf13/viper + +language: go + +env: + global: + - GO111MODULE="on" + - GOFLAGS="-mod=readonly" + +go: + - 1.11.x + - 1.12.x + - 1.13.x + - tip + +os: + - linux + - osx + +matrix: + allow_failures: + - go: tip + fast_finish: true + +script: + - go install ./... + - diff -u <(echo -n) <(gofmt -d .) + - go test -v ./... + +after_success: + - go get -u -d github.com/spf13/hugo + - cd $GOPATH/src/github.com/spf13/hugo && make && ./hugo -s docs && cd - diff --git a/vendor/github.com/spf13/viper/LICENSE b/vendor/github.com/spf13/viper/LICENSE new file mode 100644 index 000000000..4527efb9c --- /dev/null +++ b/vendor/github.com/spf13/viper/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Steve Francia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/spf13/viper/Makefile b/vendor/github.com/spf13/viper/Makefile new file mode 100644 index 000000000..e39b8b5ef --- /dev/null +++ b/vendor/github.com/spf13/viper/Makefile @@ -0,0 +1,71 @@ +# A Self-Documenting Makefile: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html + +OS = $(shell uname | tr A-Z a-z) + +# Build variables +BUILD_DIR ?= build +ifeq (${VERBOSE}, 1) +ifeq ($(filter -v,${GOARGS}),) + GOARGS += -v +endif +TEST_FORMAT = short-verbose +endif + +# Dependency versions +GOTESTSUM_VERSION = 0.3.5 +GOLANGCI_VERSION = 1.21.0 + +# Add the ability to override some variables +# Use with care +-include override.mk + +.PHONY: clear +clear: ## Clear the working area and the project + rm -rf bin/ + +.PHONY: check +check: test lint ## Run tests and linters + +bin/gotestsum: bin/gotestsum-${GOTESTSUM_VERSION} + @ln -sf gotestsum-${GOTESTSUM_VERSION} bin/gotestsum +bin/gotestsum-${GOTESTSUM_VERSION}: + @mkdir -p bin + curl -L https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_${OS}_amd64.tar.gz | tar -zOxf - gotestsum > ./bin/gotestsum-${GOTESTSUM_VERSION} && chmod +x ./bin/gotestsum-${GOTESTSUM_VERSION} + +TEST_PKGS ?= ./... +TEST_REPORT_NAME ?= results.xml +.PHONY: test +test: TEST_REPORT ?= main +test: TEST_FORMAT ?= short +test: SHELL = /bin/bash +test: bin/gotestsum ## Run tests + @mkdir -p ${BUILD_DIR}/test_results/${TEST_REPORT} + bin/gotestsum --no-summary=skipped --junitfile ${BUILD_DIR}/test_results/${TEST_REPORT}/${TEST_REPORT_NAME} --format ${TEST_FORMAT} -- $(filter-out -v,${GOARGS}) $(if ${TEST_PKGS},${TEST_PKGS},./...) + +bin/golangci-lint: bin/golangci-lint-${GOLANGCI_VERSION} + @ln -sf golangci-lint-${GOLANGCI_VERSION} bin/golangci-lint +bin/golangci-lint-${GOLANGCI_VERSION}: + @mkdir -p bin + curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | BINARY=golangci-lint bash -s -- v${GOLANGCI_VERSION} + @mv bin/golangci-lint $@ + +.PHONY: lint +lint: bin/golangci-lint ## Run linter + bin/golangci-lint run + +.PHONY: fix +fix: bin/golangci-lint ## Fix lint violations + bin/golangci-lint run --fix + +.PHONY: list +list: ## List all make targets + @${MAKE} -pRrn : -f $(MAKEFILE_LIST) 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | sort + +.PHONY: help +.DEFAULT_GOAL := help +help: + @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +# Variable outputting/exporting rules +var-%: ; @echo $($*) +varexport-%: ; @echo $*=$($*) diff --git a/vendor/github.com/spf13/viper/README.md b/vendor/github.com/spf13/viper/README.md new file mode 100644 index 000000000..327308bc6 --- /dev/null +++ b/vendor/github.com/spf13/viper/README.md @@ -0,0 +1,761 @@ +![viper logo](https://cloud.githubusercontent.com/assets/173412/10886745/998df88a-8151-11e5-9448-4736db51020d.png) + +Go configuration with fangs! + +[![Actions](https://github.com/spf13/viper/workflows/CI/badge.svg)](https://github.com/spf13/viper) +[![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![GoDoc](https://godoc.org/github.com/spf13/viper?status.svg)](https://godoc.org/github.com/spf13/viper) + +Many Go projects are built using Viper including: + +* [Hugo](http://gohugo.io) +* [EMC RexRay](http://rexray.readthedocs.org/en/stable/) +* [Imgur’s Incus](https://github.com/Imgur/incus) +* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) +* [Docker Notary](https://github.com/docker/Notary) +* [BloomApi](https://www.bloomapi.com/) +* [doctl](https://github.com/digitalocean/doctl) +* [Clairctl](https://github.com/jgsqware/clairctl) +* [Mercure](https://mercure.rocks) + + +## Install + +```console +go get github.com/spf13/viper +``` + + +## What is Viper? + +Viper is a complete configuration solution for Go applications including 12-Factor apps. It is designed +to work within an application, and can handle all types of configuration needs +and formats. It supports: + +* setting defaults +* reading from JSON, TOML, YAML, HCL, envfile and Java properties config files +* live watching and re-reading of config files (optional) +* reading from environment variables +* reading from remote config systems (etcd or Consul), and watching changes +* reading from command line flags +* reading from buffer +* setting explicit values + +Viper can be thought of as a registry for all of your applications configuration needs. + + +## Why Viper? + +When building a modern application, you don’t want to worry about +configuration file formats; you want to focus on building awesome software. +Viper is here to help with that. + +Viper does the following for you: + +1. Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, INI, envfile or Java properties formats. +2. Provide a mechanism to set default values for your different configuration options. +3. Provide a mechanism to set override values for options specified through command line flags. +4. Provide an alias system to easily rename parameters without breaking existing code. +5. Make it easy to tell the difference between when a user has provided a command line or config file which is the same as the default. + +Viper uses the following precedence order. Each item takes precedence over the item below it: + + * explicit call to `Set` + * flag + * env + * config + * key/value store + * default + +**Important:** Viper configuration keys are case insensitive. +There are ongoing discussions about making that optional. + + +## Putting Values into Viper + +### Establishing Defaults + +A good configuration system will support default values. A default value is not +required for a key, but it’s useful in the event that a key hasn't been set via +config file, environment variable, remote configuration or flag. + +Examples: + +```go +viper.SetDefault("ContentDir", "content") +viper.SetDefault("LayoutDir", "layouts") +viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"}) +``` + +### Reading Config Files + +Viper requires minimal configuration so it knows where to look for config files. +Viper supports JSON, TOML, YAML, HCL, INI, envfile and Java Properties files. Viper can search multiple paths, but +currently a single Viper instance only supports a single configuration file. +Viper does not default to any configuration search paths leaving defaults decision +to an application. + +Here is an example of how to use Viper to search for and read a configuration file. +None of the specific paths are required, but at least one path should be provided +where a configuration file is expected. + +```go +viper.SetConfigName("config") // name of config file (without extension) +viper.AddConfigPath("/etc/appname/") // path to look for the config file in +viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths +viper.AddConfigPath(".") // optionally look for config in the working directory +err := viper.ReadInConfig() // Find and read the config file +if err != nil { // Handle errors reading the config file + panic(fmt.Errorf("Fatal error config file: %s \n", err)) +} +``` + +You can handle the specific case where no config file is found like this: + +```go +if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + // Config file not found; ignore error if desired + } else { + // Config file was found but another error was produced + } +} + +// Config file found and successfully parsed +``` + +*NOTE:* You can also have a file without an extension and specify the format programmaticaly. For those configuration files that lie in the home of the user without any extension like `.bashrc` + +### Writing Config Files + +Reading from config files is useful, but at times you want to store all modifications made at run time. +For that, a bunch of commands are available, each with its own purpose: + +* WriteConfig - writes the current viper configuration to the predefined path, if exists. Errors if no predefined path. Will overwrite the current config file, if it exists. +* SafeWriteConfig - writes the current viper configuration to the predefined path. Errors if no predefined path. Will not overwrite the current config file, if it exists. +* WriteConfigAs - writes the current viper configuration to the given filepath. Will overwrite the given file, if it exists. +* SafeWriteConfigAs - writes the current viper configuration to the given filepath. Will not overwrite the given file, if it exists. + +As a rule of the thumb, everything marked with safe won't overwrite any file, but just create if not existent, whilst the default behavior is to create or truncate. + +A small examples section: + +```go +viper.WriteConfig() // writes current config to predefined path set by 'viper.AddConfigPath()' and 'viper.SetConfigName' +viper.SafeWriteConfig() +viper.WriteConfigAs("/path/to/my/.config") +viper.SafeWriteConfigAs("/path/to/my/.config") // will error since it has already been written +viper.SafeWriteConfigAs("/path/to/my/.other_config") +``` + +### Watching and re-reading config files + +Viper supports the ability to have your application live read a config file while running. + +Gone are the days of needing to restart a server to have a config take effect, +viper powered applications can read an update to a config file while running and +not miss a beat. + +Simply tell the viper instance to watchConfig. +Optionally you can provide a function for Viper to run each time a change occurs. + +**Make sure you add all of the configPaths prior to calling `WatchConfig()`** + +```go +viper.WatchConfig() +viper.OnConfigChange(func(e fsnotify.Event) { + fmt.Println("Config file changed:", e.Name) +}) +``` + +### Reading Config from io.Reader + +Viper predefines many configuration sources such as files, environment +variables, flags, and remote K/V store, but you are not bound to them. You can +also implement your own required configuration source and feed it to viper. + +```go +viper.SetConfigType("yaml") // or viper.SetConfigType("YAML") + +// any approach to require this configuration into your program. +var yamlExample = []byte(` +Hacker: true +name: steve +hobbies: +- skateboarding +- snowboarding +- go +clothing: + jacket: leather + trousers: denim +age: 35 +eyes : brown +beard: true +`) + +viper.ReadConfig(bytes.NewBuffer(yamlExample)) + +viper.Get("name") // this would be "steve" +``` + +### Setting Overrides + +These could be from a command line flag, or from your own application logic. + +```go +viper.Set("Verbose", true) +viper.Set("LogFile", LogFile) +``` + +### Registering and Using Aliases + +Aliases permit a single value to be referenced by multiple keys + +```go +viper.RegisterAlias("loud", "Verbose") + +viper.Set("verbose", true) // same result as next line +viper.Set("loud", true) // same result as prior line + +viper.GetBool("loud") // true +viper.GetBool("verbose") // true +``` + +### Working with Environment Variables + +Viper has full support for environment variables. This enables 12 factor +applications out of the box. There are five methods that exist to aid working +with ENV: + + * `AutomaticEnv()` + * `BindEnv(string...) : error` + * `SetEnvPrefix(string)` + * `SetEnvKeyReplacer(string...) *strings.Replacer` + * `AllowEmptyEnv(bool)` + +_When working with ENV variables, it’s important to recognize that Viper +treats ENV variables as case sensitive._ + +Viper provides a mechanism to try to ensure that ENV variables are unique. By +using `SetEnvPrefix`, you can tell Viper to use a prefix while reading from +the environment variables. Both `BindEnv` and `AutomaticEnv` will use this +prefix. + +`BindEnv` takes one or two parameters. The first parameter is the key name, the +second is the name of the environment variable. The name of the environment +variable is case sensitive. If the ENV variable name is not provided, then +Viper will automatically assume that the ENV variable matches the following format: prefix + "_" + the key name in ALL CAPS. When you explicitly provide the ENV variable name (the second parameter), +it **does not** automatically add the prefix. For example if the second parameter is "id", +Viper will look for the ENV variable "ID". + +One important thing to recognize when working with ENV variables is that the +value will be read each time it is accessed. Viper does not fix the value when +the `BindEnv` is called. + +`AutomaticEnv` is a powerful helper especially when combined with +`SetEnvPrefix`. When called, Viper will check for an environment variable any +time a `viper.Get` request is made. It will apply the following rules. It will +check for a environment variable with a name matching the key uppercased and +prefixed with the `EnvPrefix` if set. + +`SetEnvKeyReplacer` allows you to use a `strings.Replacer` object to rewrite Env +keys to an extent. This is useful if you want to use `-` or something in your +`Get()` calls, but want your environmental variables to use `_` delimiters. An +example of using it can be found in `viper_test.go`. + +Alternatively, you can use `EnvKeyReplacer` with `NewWithOptions` factory function. +Unlike `SetEnvKeyReplacer`, it accepts a `StringReplacer` interface allowing you to write custom string replacing logic. + +By default empty environment variables are considered unset and will fall back to +the next configuration source. To treat empty environment variables as set, use +the `AllowEmptyEnv` method. + +#### Env example + +```go +SetEnvPrefix("spf") // will be uppercased automatically +BindEnv("id") + +os.Setenv("SPF_ID", "13") // typically done outside of the app + +id := Get("id") // 13 +``` + +### Working with Flags + +Viper has the ability to bind to flags. Specifically, Viper supports `Pflags` +as used in the [Cobra](https://github.com/spf13/cobra) library. + +Like `BindEnv`, the value is not set when the binding method is called, but when +it is accessed. This means you can bind as early as you want, even in an +`init()` function. + +For individual flags, the `BindPFlag()` method provides this functionality. + +Example: + +```go +serverCmd.Flags().Int("port", 1138, "Port to run Application server on") +viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) +``` + +You can also bind an existing set of pflags (pflag.FlagSet): + +Example: + +```go +pflag.Int("flagname", 1234, "help message for flagname") + +pflag.Parse() +viper.BindPFlags(pflag.CommandLine) + +i := viper.GetInt("flagname") // retrieve values from viper instead of pflag +``` + +The use of [pflag](https://github.com/spf13/pflag/) in Viper does not preclude +the use of other packages that use the [flag](https://golang.org/pkg/flag/) +package from the standard library. The pflag package can handle the flags +defined for the flag package by importing these flags. This is accomplished +by a calling a convenience function provided by the pflag package called +AddGoFlagSet(). + +Example: + +```go +package main + +import ( + "flag" + "github.com/spf13/pflag" +) + +func main() { + + // using standard library "flag" package + flag.Int("flagname", 1234, "help message for flagname") + + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) + pflag.Parse() + viper.BindPFlags(pflag.CommandLine) + + i := viper.GetInt("flagname") // retrieve value from viper + + ... +} +``` + +#### Flag interfaces + +Viper provides two Go interfaces to bind other flag systems if you don’t use `Pflags`. + +`FlagValue` represents a single flag. This is a very simple example on how to implement this interface: + +```go +type myFlag struct {} +func (f myFlag) HasChanged() bool { return false } +func (f myFlag) Name() string { return "my-flag-name" } +func (f myFlag) ValueString() string { return "my-flag-value" } +func (f myFlag) ValueType() string { return "string" } +``` + +Once your flag implements this interface, you can simply tell Viper to bind it: + +```go +viper.BindFlagValue("my-flag-name", myFlag{}) +``` + +`FlagValueSet` represents a group of flags. This is a very simple example on how to implement this interface: + +```go +type myFlagSet struct { + flags []myFlag +} + +func (f myFlagSet) VisitAll(fn func(FlagValue)) { + for _, flag := range flags { + fn(flag) + } +} +``` + +Once your flag set implements this interface, you can simply tell Viper to bind it: + +```go +fSet := myFlagSet{ + flags: []myFlag{myFlag{}, myFlag{}}, +} +viper.BindFlagValues("my-flags", fSet) +``` + +### Remote Key/Value Store Support + +To enable remote support in Viper, do a blank import of the `viper/remote` +package: + +`import _ "github.com/spf13/viper/remote"` + +Viper will read a config string (as JSON, TOML, YAML, HCL or envfile) retrieved from a path +in a Key/Value store such as etcd or Consul. These values take precedence over +default values, but are overridden by configuration values retrieved from disk, +flags, or environment variables. + +Viper uses [crypt](https://github.com/xordataexchange/crypt) to retrieve +configuration from the K/V store, which means that you can store your +configuration values encrypted and have them automatically decrypted if you have +the correct gpg keyring. Encryption is optional. + +You can use remote configuration in conjunction with local configuration, or +independently of it. + +`crypt` has a command-line helper that you can use to put configurations in your +K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001. + +```bash +$ go get github.com/xordataexchange/crypt/bin/crypt +$ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json +``` + +Confirm that your value was set: + +```bash +$ crypt get -plaintext /config/hugo.json +``` + +See the `crypt` documentation for examples of how to set encrypted values, or +how to use Consul. + +### Remote Key/Value Store Example - Unencrypted + +#### etcd +```go +viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json") +viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv" +err := viper.ReadRemoteConfig() +``` + +#### Consul +You need to set a key to Consul key/value storage with JSON value containing your desired config. +For example, create a Consul key/value store key `MY_CONSUL_KEY` with value: + +```json +{ + "port": 8080, + "hostname": "myhostname.com" +} +``` + +```go +viper.AddRemoteProvider("consul", "localhost:8500", "MY_CONSUL_KEY") +viper.SetConfigType("json") // Need to explicitly set this to json +err := viper.ReadRemoteConfig() + +fmt.Println(viper.Get("port")) // 8080 +fmt.Println(viper.Get("hostname")) // myhostname.com +``` + +### Remote Key/Value Store Example - Encrypted + +```go +viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg") +viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv" +err := viper.ReadRemoteConfig() +``` + +### Watching Changes in etcd - Unencrypted + +```go +// alternatively, you can create a new viper instance. +var runtime_viper = viper.New() + +runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml") +runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv" + +// read from remote config the first time. +err := runtime_viper.ReadRemoteConfig() + +// unmarshal config +runtime_viper.Unmarshal(&runtime_conf) + +// open a goroutine to watch remote changes forever +go func(){ + for { + time.Sleep(time.Second * 5) // delay after each request + + // currently, only tested with etcd support + err := runtime_viper.WatchRemoteConfig() + if err != nil { + log.Errorf("unable to read remote config: %v", err) + continue + } + + // unmarshal new config into our runtime config struct. you can also use channel + // to implement a signal to notify the system of the changes + runtime_viper.Unmarshal(&runtime_conf) + } +}() +``` + +## Getting Values From Viper + +In Viper, there are a few ways to get a value depending on the value’s type. +The following functions and methods exist: + + * `Get(key string) : interface{}` + * `GetBool(key string) : bool` + * `GetFloat64(key string) : float64` + * `GetInt(key string) : int` + * `GetIntSlice(key string) : []int` + * `GetString(key string) : string` + * `GetStringMap(key string) : map[string]interface{}` + * `GetStringMapString(key string) : map[string]string` + * `GetStringSlice(key string) : []string` + * `GetTime(key string) : time.Time` + * `GetDuration(key string) : time.Duration` + * `IsSet(key string) : bool` + * `AllSettings() : map[string]interface{}` + +One important thing to recognize is that each Get function will return a zero +value if it’s not found. To check if a given key exists, the `IsSet()` method +has been provided. + +Example: +```go +viper.GetString("logfile") // case-insensitive Setting & Getting +if viper.GetBool("verbose") { + fmt.Println("verbose enabled") +} +``` +### Accessing nested keys + +The accessor methods also accept formatted paths to deeply nested keys. For +example, if the following JSON file is loaded: + +```json +{ + "host": { + "address": "localhost", + "port": 5799 + }, + "datastore": { + "metric": { + "host": "127.0.0.1", + "port": 3099 + }, + "warehouse": { + "host": "198.0.0.1", + "port": 2112 + } + } +} + +``` + +Viper can access a nested field by passing a `.` delimited path of keys: + +```go +GetString("datastore.metric.host") // (returns "127.0.0.1") +``` + +This obeys the precedence rules established above; the search for the path +will cascade through the remaining configuration registries until found. + +For example, given this configuration file, both `datastore.metric.host` and +`datastore.metric.port` are already defined (and may be overridden). If in addition +`datastore.metric.protocol` was defined in the defaults, Viper would also find it. + +However, if `datastore.metric` was overridden (by a flag, an environment variable, +the `Set()` method, …) with an immediate value, then all sub-keys of +`datastore.metric` become undefined, they are “shadowed” by the higher-priority +configuration level. + +Lastly, if there exists a key that matches the delimited key path, its value +will be returned instead. E.g. + +```json +{ + "datastore.metric.host": "0.0.0.0", + "host": { + "address": "localhost", + "port": 5799 + }, + "datastore": { + "metric": { + "host": "127.0.0.1", + "port": 3099 + }, + "warehouse": { + "host": "198.0.0.1", + "port": 2112 + } + } +} + +GetString("datastore.metric.host") // returns "0.0.0.0" +``` + +### Extract sub-tree + +Extract sub-tree from Viper. + +For example, `viper` represents: + +```json +app: + cache1: + max-items: 100 + item-size: 64 + cache2: + max-items: 200 + item-size: 80 +``` + +After executing: + +```go +subv := viper.Sub("app.cache1") +``` + +`subv` represents: + +```json +max-items: 100 +item-size: 64 +``` + +Suppose we have: + +```go +func NewCache(cfg *Viper) *Cache {...} +``` + +which creates a cache based on config information formatted as `subv`. +Now it’s easy to create these 2 caches separately as: + +```go +cfg1 := viper.Sub("app.cache1") +cache1 := NewCache(cfg1) + +cfg2 := viper.Sub("app.cache2") +cache2 := NewCache(cfg2) +``` + +### Unmarshaling + +You also have the option of Unmarshaling all or a specific value to a struct, map, +etc. + +There are two methods to do this: + + * `Unmarshal(rawVal interface{}) : error` + * `UnmarshalKey(key string, rawVal interface{}) : error` + +Example: + +```go +type config struct { + Port int + Name string + PathMap string `mapstructure:"path_map"` +} + +var C config + +err := viper.Unmarshal(&C) +if err != nil { + t.Fatalf("unable to decode into struct, %v", err) +} +``` + +If you want to unmarshal configuration where the keys themselves contain dot (the default key delimiter), +you have to change the delimiter: + +```go +v := viper.NewWithOptions(viper.KeyDelimiter("::")) + +v.SetDefault("chart::values", map[string]interface{}{ + "ingress": map[string]interface{}{ + "annotations": map[string]interface{}{ + "traefik.frontend.rule.type": "PathPrefix", + "traefik.ingress.kubernetes.io/ssl-redirect": "true", + }, + }, +}) + +type config struct { + Chart struct{ + Values map[string]interface{} + } +} + +var C config + +v.Unmarshal(&C) +``` + +Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default. + +### Marshalling to string + +You may need to marshal all the settings held in viper into a string rather than write them to a file. +You can use your favorite format's marshaller with the config returned by `AllSettings()`. + +```go +import ( + yaml "gopkg.in/yaml.v2" + // ... +) + +func yamlStringSettings() string { + c := viper.AllSettings() + bs, err := yaml.Marshal(c) + if err != nil { + log.Fatalf("unable to marshal config to YAML: %v", err) + } + return string(bs) +} +``` + +## Viper or Vipers? + +Viper comes ready to use out of the box. There is no configuration or +initialization needed to begin using Viper. Since most applications will want +to use a single central repository for their configuration, the viper package +provides this. It is similar to a singleton. + +In all of the examples above, they demonstrate using viper in its singleton +style approach. + +### Working with multiple vipers + +You can also create many different vipers for use in your application. Each will +have its own unique set of configurations and values. Each can read from a +different config file, key value store, etc. All of the functions that viper +package supports are mirrored as methods on a viper. + +Example: + +```go +x := viper.New() +y := viper.New() + +x.SetDefault("ContentDir", "content") +y.SetDefault("ContentDir", "foobar") + +//... +``` + +When working with multiple vipers, it is up to the user to keep track of the +different vipers. + +## Q & A + +Q: Why is it called “Viper”? + +A: Viper is designed to be a [companion](http://en.wikipedia.org/wiki/Viper_(G.I._Joe)) +to [Cobra](https://github.com/spf13/cobra). While both can operate completely +independently, together they make a powerful pair to handle much of your +application foundation needs. + +Q: Why is it called “Cobra”? + +A: Is there a better name for a [commander](http://en.wikipedia.org/wiki/Cobra_Commander)? diff --git a/vendor/github.com/spf13/viper/flags.go b/vendor/github.com/spf13/viper/flags.go new file mode 100644 index 000000000..b5ddbf5d4 --- /dev/null +++ b/vendor/github.com/spf13/viper/flags.go @@ -0,0 +1,57 @@ +package viper + +import "github.com/spf13/pflag" + +// FlagValueSet is an interface that users can implement +// to bind a set of flags to viper. +type FlagValueSet interface { + VisitAll(fn func(FlagValue)) +} + +// FlagValue is an interface that users can implement +// to bind different flags to viper. +type FlagValue interface { + HasChanged() bool + Name() string + ValueString() string + ValueType() string +} + +// pflagValueSet is a wrapper around *pflag.ValueSet +// that implements FlagValueSet. +type pflagValueSet struct { + flags *pflag.FlagSet +} + +// VisitAll iterates over all *pflag.Flag inside the *pflag.FlagSet. +func (p pflagValueSet) VisitAll(fn func(flag FlagValue)) { + p.flags.VisitAll(func(flag *pflag.Flag) { + fn(pflagValue{flag}) + }) +} + +// pflagValue is a wrapper aroung *pflag.flag +// that implements FlagValue +type pflagValue struct { + flag *pflag.Flag +} + +// HasChanged returns whether the flag has changes or not. +func (p pflagValue) HasChanged() bool { + return p.flag.Changed +} + +// Name returns the name of the flag. +func (p pflagValue) Name() string { + return p.flag.Name +} + +// ValueString returns the value of the flag as a string. +func (p pflagValue) ValueString() string { + return p.flag.Value.String() +} + +// ValueType returns the type of the flag as a string. +func (p pflagValue) ValueType() string { + return p.flag.Value.Type() +} diff --git a/vendor/github.com/spf13/viper/go.mod b/vendor/github.com/spf13/viper/go.mod new file mode 100644 index 000000000..0e358cbef --- /dev/null +++ b/vendor/github.com/spf13/viper/go.mod @@ -0,0 +1,48 @@ +module github.com/spf13/viper + +go 1.12 + +require ( + github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 // indirect + github.com/coreos/bbolt v1.3.2 // indirect + github.com/coreos/etcd v3.3.10+incompatible // indirect + github.com/coreos/go-semver v0.2.0 // indirect + github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e // indirect + github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/fsnotify/fsnotify v1.4.7 + github.com/gogo/protobuf v1.2.1 // indirect + github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect + github.com/google/btree v1.0.0 // indirect + github.com/gorilla/websocket v1.4.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.9.0 // indirect + github.com/hashicorp/hcl v1.0.0 + github.com/jonboulle/clockwork v0.1.0 // indirect + github.com/magiconair/properties v1.8.1 + github.com/mitchellh/mapstructure v1.1.2 + github.com/pelletier/go-toml v1.2.0 + github.com/prometheus/client_golang v0.9.3 // indirect + github.com/smartystreets/goconvey v1.6.4 // indirect + github.com/soheilhy/cmux v0.1.4 // indirect + github.com/spf13/afero v1.1.2 + github.com/spf13/cast v1.3.0 + github.com/spf13/jwalterweatherman v1.0.0 + github.com/spf13/pflag v1.0.3 + github.com/stretchr/testify v1.2.2 + github.com/subosito/gotenv v1.2.0 + github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect + github.com/ugorji/go v1.1.4 // indirect + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect + github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 + go.etcd.io/bbolt v1.3.2 // indirect + go.uber.org/atomic v1.4.0 // indirect + go.uber.org/multierr v1.1.0 // indirect + go.uber.org/zap v1.10.0 // indirect + golang.org/x/net v0.0.0-20190522155817-f3200d17e092 // indirect + golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect + google.golang.org/grpc v1.21.0 // indirect + gopkg.in/ini.v1 v1.51.0 + gopkg.in/yaml.v2 v2.2.4 +) diff --git a/vendor/github.com/spf13/viper/go.sum b/vendor/github.com/spf13/viper/go.sum new file mode 100644 index 000000000..d75aee23d --- /dev/null +++ b/vendor/github.com/spf13/viper/go.sum @@ -0,0 +1,192 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/spf13/viper/util.go b/vendor/github.com/spf13/viper/util.go new file mode 100644 index 000000000..b78896963 --- /dev/null +++ b/vendor/github.com/spf13/viper/util.go @@ -0,0 +1,221 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// Viper is a application configuration system. +// It believes that applications can be configured a variety of ways +// via flags, ENVIRONMENT variables, configuration files retrieved +// from the file system, or a remote key/value store. + +package viper + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "unicode" + + "github.com/spf13/afero" + "github.com/spf13/cast" + jww "github.com/spf13/jwalterweatherman" +) + +// ConfigParseError denotes failing to parse configuration file. +type ConfigParseError struct { + err error +} + +// Error returns the formatted configuration error. +func (pe ConfigParseError) Error() string { + return fmt.Sprintf("While parsing config: %s", pe.err.Error()) +} + +// toCaseInsensitiveValue checks if the value is a map; +// if so, create a copy and lower-case the keys recursively. +func toCaseInsensitiveValue(value interface{}) interface{} { + switch v := value.(type) { + case map[interface{}]interface{}: + value = copyAndInsensitiviseMap(cast.ToStringMap(v)) + case map[string]interface{}: + value = copyAndInsensitiviseMap(v) + } + + return value +} + +// copyAndInsensitiviseMap behaves like insensitiviseMap, but creates a copy of +// any map it makes case insensitive. +func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} { + nm := make(map[string]interface{}) + + for key, val := range m { + lkey := strings.ToLower(key) + switch v := val.(type) { + case map[interface{}]interface{}: + nm[lkey] = copyAndInsensitiviseMap(cast.ToStringMap(v)) + case map[string]interface{}: + nm[lkey] = copyAndInsensitiviseMap(v) + default: + nm[lkey] = v + } + } + + return nm +} + +func insensitiviseMap(m map[string]interface{}) { + for key, val := range m { + switch val.(type) { + case map[interface{}]interface{}: + // nested map: cast and recursively insensitivise + val = cast.ToStringMap(val) + insensitiviseMap(val.(map[string]interface{})) + case map[string]interface{}: + // nested map: recursively insensitivise + insensitiviseMap(val.(map[string]interface{})) + } + + lower := strings.ToLower(key) + if key != lower { + // remove old key (not lower-cased) + delete(m, key) + } + // update map + m[lower] = val + } +} + +func absPathify(inPath string) string { + jww.INFO.Println("Trying to resolve absolute path to", inPath) + + if strings.HasPrefix(inPath, "$HOME") { + inPath = userHomeDir() + inPath[5:] + } + + if strings.HasPrefix(inPath, "$") { + end := strings.Index(inPath, string(os.PathSeparator)) + inPath = os.Getenv(inPath[1:end]) + inPath[end:] + } + + if filepath.IsAbs(inPath) { + return filepath.Clean(inPath) + } + + p, err := filepath.Abs(inPath) + if err == nil { + return filepath.Clean(p) + } + + jww.ERROR.Println("Couldn't discover absolute path") + jww.ERROR.Println(err) + return "" +} + +// Check if file Exists +func exists(fs afero.Fs, path string) (bool, error) { + stat, err := fs.Stat(path) + if err == nil { + return !stat.IsDir(), nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} + +func userHomeDir() string { + if runtime.GOOS == "windows" { + home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + if home == "" { + home = os.Getenv("USERPROFILE") + } + return home + } + return os.Getenv("HOME") +} + +func safeMul(a, b uint) uint { + c := a * b + if a > 1 && b > 1 && c/b != a { + return 0 + } + return c +} + +// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes +func parseSizeInBytes(sizeStr string) uint { + sizeStr = strings.TrimSpace(sizeStr) + lastChar := len(sizeStr) - 1 + multiplier := uint(1) + + if lastChar > 0 { + if sizeStr[lastChar] == 'b' || sizeStr[lastChar] == 'B' { + if lastChar > 1 { + switch unicode.ToLower(rune(sizeStr[lastChar-1])) { + case 'k': + multiplier = 1 << 10 + sizeStr = strings.TrimSpace(sizeStr[:lastChar-1]) + case 'm': + multiplier = 1 << 20 + sizeStr = strings.TrimSpace(sizeStr[:lastChar-1]) + case 'g': + multiplier = 1 << 30 + sizeStr = strings.TrimSpace(sizeStr[:lastChar-1]) + default: + multiplier = 1 + sizeStr = strings.TrimSpace(sizeStr[:lastChar]) + } + } + } + } + + size := cast.ToInt(sizeStr) + if size < 0 { + size = 0 + } + + return safeMul(uint(size), multiplier) +} + +// deepSearch scans deep maps, following the key indexes listed in the +// sequence "path". +// The last value is expected to be another map, and is returned. +// +// In case intermediate keys do not exist, or map to a non-map value, +// a new map is created and inserted, and the search continues from there: +// the initial map "m" may be modified! +func deepSearch(m map[string]interface{}, path []string) map[string]interface{} { + for _, k := range path { + m2, ok := m[k] + if !ok { + // intermediate key does not exist + // => create it and continue from there + m3 := make(map[string]interface{}) + m[k] = m3 + m = m3 + continue + } + m3, ok := m2.(map[string]interface{}) + if !ok { + // intermediate key is a value + // => replace with a new map + m3 = make(map[string]interface{}) + m[k] = m3 + } + // continue search from here + m = m3 + } + return m +} diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go new file mode 100644 index 000000000..eb2f5177a --- /dev/null +++ b/vendor/github.com/spf13/viper/viper.go @@ -0,0 +1,2011 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// Viper is an application configuration system. +// It believes that applications can be configured a variety of ways +// via flags, ENVIRONMENT variables, configuration files retrieved +// from the file system, or a remote key/value store. + +// Each item takes precedence over the item below it: + +// overrides +// flag +// env +// config +// key/value store +// default + +package viper + +import ( + "bytes" + "encoding/csv" + "encoding/json" + "errors" + "fmt" + "io" + "log" + "os" + "path/filepath" + "reflect" + "strings" + "sync" + "time" + + "github.com/fsnotify/fsnotify" + "github.com/hashicorp/hcl" + "github.com/hashicorp/hcl/hcl/printer" + "github.com/magiconair/properties" + "github.com/mitchellh/mapstructure" + "github.com/pelletier/go-toml" + "github.com/spf13/afero" + "github.com/spf13/cast" + jww "github.com/spf13/jwalterweatherman" + "github.com/spf13/pflag" + "github.com/subosito/gotenv" + "gopkg.in/ini.v1" + "gopkg.in/yaml.v2" +) + +// ConfigMarshalError happens when failing to marshal the configuration. +type ConfigMarshalError struct { + err error +} + +// Error returns the formatted configuration error. +func (e ConfigMarshalError) Error() string { + return fmt.Sprintf("While marshaling config: %s", e.err.Error()) +} + +var v *Viper + +type RemoteResponse struct { + Value []byte + Error error +} + +func init() { + v = New() +} + +type remoteConfigFactory interface { + Get(rp RemoteProvider) (io.Reader, error) + Watch(rp RemoteProvider) (io.Reader, error) + WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool) +} + +// RemoteConfig is optional, see the remote package +var RemoteConfig remoteConfigFactory + +// UnsupportedConfigError denotes encountering an unsupported +// configuration filetype. +type UnsupportedConfigError string + +// Error returns the formatted configuration error. +func (str UnsupportedConfigError) Error() string { + return fmt.Sprintf("Unsupported Config Type %q", string(str)) +} + +// UnsupportedRemoteProviderError denotes encountering an unsupported remote +// provider. Currently only etcd and Consul are supported. +type UnsupportedRemoteProviderError string + +// Error returns the formatted remote provider error. +func (str UnsupportedRemoteProviderError) Error() string { + return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) +} + +// RemoteConfigError denotes encountering an error while trying to +// pull the configuration from the remote provider. +type RemoteConfigError string + +// Error returns the formatted remote provider error +func (rce RemoteConfigError) Error() string { + return fmt.Sprintf("Remote Configurations Error: %s", string(rce)) +} + +// ConfigFileNotFoundError denotes failing to find configuration file. +type ConfigFileNotFoundError struct { + name, locations string +} + +// Error returns the formatted configuration error. +func (fnfe ConfigFileNotFoundError) Error() string { + return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations) +} + +// ConfigFileAlreadyExistsError denotes failure to write new configuration file. +type ConfigFileAlreadyExistsError string + +// Error returns the formatted error when configuration already exists. +func (faee ConfigFileAlreadyExistsError) Error() string { + return fmt.Sprintf("Config File %q Already Exists", string(faee)) +} + +// A DecoderConfigOption can be passed to viper.Unmarshal to configure +// mapstructure.DecoderConfig options +type DecoderConfigOption func(*mapstructure.DecoderConfig) + +// DecodeHook returns a DecoderConfigOption which overrides the default +// DecoderConfig.DecodeHook value, the default is: +// +// mapstructure.ComposeDecodeHookFunc( +// mapstructure.StringToTimeDurationHookFunc(), +// mapstructure.StringToSliceHookFunc(","), +// ) +func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption { + return func(c *mapstructure.DecoderConfig) { + c.DecodeHook = hook + } +} + +// Viper is a prioritized configuration registry. It +// maintains a set of configuration sources, fetches +// values to populate those, and provides them according +// to the source's priority. +// The priority of the sources is the following: +// 1. overrides +// 2. flags +// 3. env. variables +// 4. config file +// 5. key/value store +// 6. defaults +// +// For example, if values from the following sources were loaded: +// +// Defaults : { +// "secret": "", +// "user": "default", +// "endpoint": "https://localhost" +// } +// Config : { +// "user": "root" +// "secret": "defaultsecret" +// } +// Env : { +// "secret": "somesecretkey" +// } +// +// The resulting config will have the following values: +// +// { +// "secret": "somesecretkey", +// "user": "root", +// "endpoint": "https://localhost" +// } +type Viper struct { + // Delimiter that separates a list of keys + // used to access a nested value in one go + keyDelim string + + // A set of paths to look for the config file in + configPaths []string + + // The filesystem to read config from. + fs afero.Fs + + // A set of remote providers to search for the configuration + remoteProviders []*defaultRemoteProvider + + // Name of file to look for inside the path + configName string + configFile string + configType string + configPermissions os.FileMode + envPrefix string + + automaticEnvApplied bool + envKeyReplacer StringReplacer + allowEmptyEnv bool + + config map[string]interface{} + override map[string]interface{} + defaults map[string]interface{} + kvstore map[string]interface{} + pflags map[string]FlagValue + env map[string]string + aliases map[string]string + typeByDefValue bool + + // Store read properties on the object so that we can write back in order with comments. + // This will only be used if the configuration read is a properties file. + properties *properties.Properties + + onConfigChange func(fsnotify.Event) +} + +// New returns an initialized Viper instance. +func New() *Viper { + v := new(Viper) + v.keyDelim = "." + v.configName = "config" + v.configPermissions = os.FileMode(0644) + v.fs = afero.NewOsFs() + v.config = make(map[string]interface{}) + v.override = make(map[string]interface{}) + v.defaults = make(map[string]interface{}) + v.kvstore = make(map[string]interface{}) + v.pflags = make(map[string]FlagValue) + v.env = make(map[string]string) + v.aliases = make(map[string]string) + v.typeByDefValue = false + + return v +} + +// Option configures Viper using the functional options paradigm popularized by Rob Pike and Dave Cheney. +// If you're unfamiliar with this style, +// see https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html and +// https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis. +type Option interface { + apply(v *Viper) +} + +type optionFunc func(v *Viper) + +func (fn optionFunc) apply(v *Viper) { + fn(v) +} + +// KeyDelimiter sets the delimiter used for determining key parts. +// By default it's value is ".". +func KeyDelimiter(d string) Option { + return optionFunc(func(v *Viper) { + v.keyDelim = d + }) +} + +// StringReplacer applies a set of replacements to a string. +type StringReplacer interface { + // Replace returns a copy of s with all replacements performed. + Replace(s string) string +} + +// EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys. +func EnvKeyReplacer(r StringReplacer) Option { + return optionFunc(func(v *Viper) { + v.envKeyReplacer = r + }) +} + +// NewWithOptions creates a new Viper instance. +func NewWithOptions(opts ...Option) *Viper { + v := New() + + for _, opt := range opts { + opt.apply(v) + } + + return v +} + +// Reset is intended for testing, will reset all to default settings. +// In the public interface for the viper package so applications +// can use it in their testing as well. +func Reset() { + v = New() + SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} + SupportedRemoteProviders = []string{"etcd", "consul"} +} + +type defaultRemoteProvider struct { + provider string + endpoint string + path string + secretKeyring string +} + +func (rp defaultRemoteProvider) Provider() string { + return rp.provider +} + +func (rp defaultRemoteProvider) Endpoint() string { + return rp.endpoint +} + +func (rp defaultRemoteProvider) Path() string { + return rp.path +} + +func (rp defaultRemoteProvider) SecretKeyring() string { + return rp.secretKeyring +} + +// RemoteProvider stores the configuration necessary +// to connect to a remote key/value store. +// Optional secretKeyring to unencrypt encrypted values +// can be provided. +type RemoteProvider interface { + Provider() string + Endpoint() string + Path() string + SecretKeyring() string +} + +// SupportedExts are universally supported extensions. +var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} + +// SupportedRemoteProviders are universally supported remote providers. +var SupportedRemoteProviders = []string{"etcd", "consul"} + +func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } +func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) { + v.onConfigChange = run +} + +func WatchConfig() { v.WatchConfig() } + +func (v *Viper) WatchConfig() { + initWG := sync.WaitGroup{} + initWG.Add(1) + go func() { + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + // we have to watch the entire directory to pick up renames/atomic saves in a cross-platform way + filename, err := v.getConfigFile() + if err != nil { + log.Printf("error: %v\n", err) + initWG.Done() + return + } + + configFile := filepath.Clean(filename) + configDir, _ := filepath.Split(configFile) + realConfigFile, _ := filepath.EvalSymlinks(filename) + + eventsWG := sync.WaitGroup{} + eventsWG.Add(1) + go func() { + for { + select { + case event, ok := <-watcher.Events: + if !ok { // 'Events' channel is closed + eventsWG.Done() + return + } + currentConfigFile, _ := filepath.EvalSymlinks(filename) + // we only care about the config file with the following cases: + // 1 - if the config file was modified or created + // 2 - if the real path to the config file changed (eg: k8s ConfigMap replacement) + const writeOrCreateMask = fsnotify.Write | fsnotify.Create + if (filepath.Clean(event.Name) == configFile && + event.Op&writeOrCreateMask != 0) || + (currentConfigFile != "" && currentConfigFile != realConfigFile) { + realConfigFile = currentConfigFile + err := v.ReadInConfig() + if err != nil { + log.Printf("error reading config file: %v\n", err) + } + if v.onConfigChange != nil { + v.onConfigChange(event) + } + } else if filepath.Clean(event.Name) == configFile && + event.Op&fsnotify.Remove&fsnotify.Remove != 0 { + eventsWG.Done() + return + } + + case err, ok := <-watcher.Errors: + if ok { // 'Errors' channel is not closed + log.Printf("watcher error: %v\n", err) + } + eventsWG.Done() + return + } + } + }() + watcher.Add(configDir) + initWG.Done() // done initializing the watch in this go routine, so the parent routine can move on... + eventsWG.Wait() // now, wait for event loop to end in this go-routine... + }() + initWG.Wait() // make sure that the go routine above fully ended before returning +} + +// SetConfigFile explicitly defines the path, name and extension of the config file. +// Viper will use this and not check any of the config paths. +func SetConfigFile(in string) { v.SetConfigFile(in) } +func (v *Viper) SetConfigFile(in string) { + if in != "" { + v.configFile = in + } +} + +// SetEnvPrefix defines a prefix that ENVIRONMENT variables will use. +// E.g. if your prefix is "spf", the env registry will look for env +// variables that start with "SPF_". +func SetEnvPrefix(in string) { v.SetEnvPrefix(in) } +func (v *Viper) SetEnvPrefix(in string) { + if in != "" { + v.envPrefix = in + } +} + +func (v *Viper) mergeWithEnvPrefix(in string) string { + if v.envPrefix != "" { + return strings.ToUpper(v.envPrefix + "_" + in) + } + + return strings.ToUpper(in) +} + +// AllowEmptyEnv tells Viper to consider set, +// but empty environment variables as valid values instead of falling back. +// For backward compatibility reasons this is false by default. +func AllowEmptyEnv(allowEmptyEnv bool) { v.AllowEmptyEnv(allowEmptyEnv) } +func (v *Viper) AllowEmptyEnv(allowEmptyEnv bool) { + v.allowEmptyEnv = allowEmptyEnv +} + +// TODO: should getEnv logic be moved into find(). Can generalize the use of +// rewriting keys many things, Ex: Get('someKey') -> some_key +// (camel case to snake case for JSON keys perhaps) + +// getEnv is a wrapper around os.Getenv which replaces characters in the original +// key. This allows env vars which have different keys than the config object +// keys. +func (v *Viper) getEnv(key string) (string, bool) { + if v.envKeyReplacer != nil { + key = v.envKeyReplacer.Replace(key) + } + + val, ok := os.LookupEnv(key) + + return val, ok && (v.allowEmptyEnv || val != "") +} + +// ConfigFileUsed returns the file used to populate the config registry. +func ConfigFileUsed() string { return v.ConfigFileUsed() } +func (v *Viper) ConfigFileUsed() string { return v.configFile } + +// AddConfigPath adds a path for Viper to search for the config file in. +// Can be called multiple times to define multiple search paths. +func AddConfigPath(in string) { v.AddConfigPath(in) } +func (v *Viper) AddConfigPath(in string) { + if in != "" { + absin := absPathify(in) + jww.INFO.Println("adding", absin, "to paths to search") + if !stringInSlice(absin, v.configPaths) { + v.configPaths = append(v.configPaths, absin) + } + } +} + +// AddRemoteProvider adds a remote configuration source. +// Remote Providers are searched in the order they are added. +// provider is a string value, "etcd" or "consul" are currently supported. +// endpoint is the url. etcd requires http://ip:port consul requires ip:port +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp" +func AddRemoteProvider(provider, endpoint, path string) error { + return v.AddRemoteProvider(provider, endpoint, path) +} +func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { + if !stringInSlice(provider, SupportedRemoteProviders) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint) + rp := &defaultRemoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +// AddSecureRemoteProvider adds a remote configuration source. +// Secure Remote Providers are searched in the order they are added. +// provider is a string value, "etcd" or "consul" are currently supported. +// endpoint is the url. etcd requires http://ip:port consul requires ip:port +// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp" +// Secure Remote Providers are implemented with github.com/xordataexchange/crypt +func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) +} + +func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + if !stringInSlice(provider, SupportedRemoteProviders) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint) + rp := &defaultRemoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + secretKeyring: secretkeyring, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool { + for _, y := range v.remoteProviders { + if reflect.DeepEqual(y, p) { + return true + } + } + return false +} + +// searchMap recursively searches for a value for path in source map. +// Returns nil if not found. +// Note: This assumes that the path entries and map keys are lower cased. +func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} { + if len(path) == 0 { + return source + } + + next, ok := source[path[0]] + if ok { + // Fast path + if len(path) == 1 { + return next + } + + // Nested case + switch next.(type) { + case map[interface{}]interface{}: + return v.searchMap(cast.ToStringMap(next), path[1:]) + case map[string]interface{}: + // Type assertion is safe here since it is only reached + // if the type of `next` is the same as the type being asserted + return v.searchMap(next.(map[string]interface{}), path[1:]) + default: + // got a value but nested key expected, return "nil" for not found + return nil + } + } + return nil +} + +// searchMapWithPathPrefixes recursively searches for a value for path in source map. +// +// While searchMap() considers each path element as a single map key, this +// function searches for, and prioritizes, merged path elements. +// e.g., if in the source, "foo" is defined with a sub-key "bar", and "foo.bar" +// is also defined, this latter value is returned for path ["foo", "bar"]. +// +// This should be useful only at config level (other maps may not contain dots +// in their keys). +// +// Note: This assumes that the path entries and map keys are lower cased. +func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path []string) interface{} { + if len(path) == 0 { + return source + } + + // search for path prefixes, starting from the longest one + for i := len(path); i > 0; i-- { + prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim)) + + next, ok := source[prefixKey] + if ok { + // Fast path + if i == len(path) { + return next + } + + // Nested case + var val interface{} + switch next.(type) { + case map[interface{}]interface{}: + val = v.searchMapWithPathPrefixes(cast.ToStringMap(next), path[i:]) + case map[string]interface{}: + // Type assertion is safe here since it is only reached + // if the type of `next` is the same as the type being asserted + val = v.searchMapWithPathPrefixes(next.(map[string]interface{}), path[i:]) + default: + // got a value but nested key expected, do nothing and look for next prefix + } + if val != nil { + return val + } + } + } + + // not found + return nil +} + +// isPathShadowedInDeepMap makes sure the given path is not shadowed somewhere +// on its path in the map. +// e.g., if "foo.bar" has a value in the given map, it “shadows” +// "foo.bar.baz" in a lower-priority map +func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{}) string { + var parentVal interface{} + for i := 1; i < len(path); i++ { + parentVal = v.searchMap(m, path[0:i]) + if parentVal == nil { + // not found, no need to add more path elements + return "" + } + switch parentVal.(type) { + case map[interface{}]interface{}: + continue + case map[string]interface{}: + continue + default: + // parentVal is a regular value which shadows "path" + return strings.Join(path[0:i], v.keyDelim) + } + } + return "" +} + +// isPathShadowedInFlatMap makes sure the given path is not shadowed somewhere +// in a sub-path of the map. +// e.g., if "foo.bar" has a value in the given map, it “shadows” +// "foo.bar.baz" in a lower-priority map +func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string { + // unify input map + var m map[string]interface{} + switch mi.(type) { + case map[string]string, map[string]FlagValue: + m = cast.ToStringMap(mi) + default: + return "" + } + + // scan paths + var parentKey string + for i := 1; i < len(path); i++ { + parentKey = strings.Join(path[0:i], v.keyDelim) + if _, ok := m[parentKey]; ok { + return parentKey + } + } + return "" +} + +// isPathShadowedInAutoEnv makes sure the given path is not shadowed somewhere +// in the environment, when automatic env is on. +// e.g., if "foo.bar" has a value in the environment, it “shadows” +// "foo.bar.baz" in a lower-priority map +func (v *Viper) isPathShadowedInAutoEnv(path []string) string { + var parentKey string + for i := 1; i < len(path); i++ { + parentKey = strings.Join(path[0:i], v.keyDelim) + if _, ok := v.getEnv(v.mergeWithEnvPrefix(parentKey)); ok { + return parentKey + } + } + return "" +} + +// SetTypeByDefaultValue enables or disables the inference of a key value's +// type when the Get function is used based upon a key's default value as +// opposed to the value returned based on the normal fetch logic. +// +// For example, if a key has a default value of []string{} and the same key +// is set via an environment variable to "a b c", a call to the Get function +// would return a string slice for the key if the key's type is inferred by +// the default value and the Get function would return: +// +// []string {"a", "b", "c"} +// +// Otherwise the Get function would return: +// +// "a b c" +func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) } +func (v *Viper) SetTypeByDefaultValue(enable bool) { + v.typeByDefValue = enable +} + +// GetViper gets the global Viper instance. +func GetViper() *Viper { + return v +} + +// Get can retrieve any value given the key to use. +// Get is case-insensitive for a key. +// Get has the behavior of returning the value associated with the first +// place from where it is set. Viper will check in the following order: +// override, flag, env, config file, key/value store, default +// +// Get returns an interface. For a specific value use one of the Get____ methods. +func Get(key string) interface{} { return v.Get(key) } +func (v *Viper) Get(key string) interface{} { + lcaseKey := strings.ToLower(key) + val := v.find(lcaseKey, true) + if val == nil { + return nil + } + + if v.typeByDefValue { + // TODO(bep) this branch isn't covered by a single test. + valType := val + path := strings.Split(lcaseKey, v.keyDelim) + defVal := v.searchMap(v.defaults, path) + if defVal != nil { + valType = defVal + } + + switch valType.(type) { + case bool: + return cast.ToBool(val) + case string: + return cast.ToString(val) + case int32, int16, int8, int: + return cast.ToInt(val) + case uint: + return cast.ToUint(val) + case uint32: + return cast.ToUint32(val) + case uint64: + return cast.ToUint64(val) + case int64: + return cast.ToInt64(val) + case float64, float32: + return cast.ToFloat64(val) + case time.Time: + return cast.ToTime(val) + case time.Duration: + return cast.ToDuration(val) + case []string: + return cast.ToStringSlice(val) + case []int: + return cast.ToIntSlice(val) + } + } + + return val +} + +// Sub returns new Viper instance representing a sub tree of this instance. +// Sub is case-insensitive for a key. +func Sub(key string) *Viper { return v.Sub(key) } +func (v *Viper) Sub(key string) *Viper { + subv := New() + data := v.Get(key) + if data == nil { + return nil + } + + if reflect.TypeOf(data).Kind() == reflect.Map { + subv.config = cast.ToStringMap(data) + return subv + } + return nil +} + +// GetString returns the value associated with the key as a string. +func GetString(key string) string { return v.GetString(key) } +func (v *Viper) GetString(key string) string { + return cast.ToString(v.Get(key)) +} + +// GetBool returns the value associated with the key as a boolean. +func GetBool(key string) bool { return v.GetBool(key) } +func (v *Viper) GetBool(key string) bool { + return cast.ToBool(v.Get(key)) +} + +// GetInt returns the value associated with the key as an integer. +func GetInt(key string) int { return v.GetInt(key) } +func (v *Viper) GetInt(key string) int { + return cast.ToInt(v.Get(key)) +} + +// GetInt32 returns the value associated with the key as an integer. +func GetInt32(key string) int32 { return v.GetInt32(key) } +func (v *Viper) GetInt32(key string) int32 { + return cast.ToInt32(v.Get(key)) +} + +// GetInt64 returns the value associated with the key as an integer. +func GetInt64(key string) int64 { return v.GetInt64(key) } +func (v *Viper) GetInt64(key string) int64 { + return cast.ToInt64(v.Get(key)) +} + +// GetUint returns the value associated with the key as an unsigned integer. +func GetUint(key string) uint { return v.GetUint(key) } +func (v *Viper) GetUint(key string) uint { + return cast.ToUint(v.Get(key)) +} + +// GetUint32 returns the value associated with the key as an unsigned integer. +func GetUint32(key string) uint32 { return v.GetUint32(key) } +func (v *Viper) GetUint32(key string) uint32 { + return cast.ToUint32(v.Get(key)) +} + +// GetUint64 returns the value associated with the key as an unsigned integer. +func GetUint64(key string) uint64 { return v.GetUint64(key) } +func (v *Viper) GetUint64(key string) uint64 { + return cast.ToUint64(v.Get(key)) +} + +// GetFloat64 returns the value associated with the key as a float64. +func GetFloat64(key string) float64 { return v.GetFloat64(key) } +func (v *Viper) GetFloat64(key string) float64 { + return cast.ToFloat64(v.Get(key)) +} + +// GetTime returns the value associated with the key as time. +func GetTime(key string) time.Time { return v.GetTime(key) } +func (v *Viper) GetTime(key string) time.Time { + return cast.ToTime(v.Get(key)) +} + +// GetDuration returns the value associated with the key as a duration. +func GetDuration(key string) time.Duration { return v.GetDuration(key) } +func (v *Viper) GetDuration(key string) time.Duration { + return cast.ToDuration(v.Get(key)) +} + +// GetIntSlice returns the value associated with the key as a slice of int values. +func GetIntSlice(key string) []int { return v.GetIntSlice(key) } +func (v *Viper) GetIntSlice(key string) []int { + return cast.ToIntSlice(v.Get(key)) +} + +// GetStringSlice returns the value associated with the key as a slice of strings. +func GetStringSlice(key string) []string { return v.GetStringSlice(key) } +func (v *Viper) GetStringSlice(key string) []string { + return cast.ToStringSlice(v.Get(key)) +} + +// GetStringMap returns the value associated with the key as a map of interfaces. +func GetStringMap(key string) map[string]interface{} { return v.GetStringMap(key) } +func (v *Viper) GetStringMap(key string) map[string]interface{} { + return cast.ToStringMap(v.Get(key)) +} + +// GetStringMapString returns the value associated with the key as a map of strings. +func GetStringMapString(key string) map[string]string { return v.GetStringMapString(key) } +func (v *Viper) GetStringMapString(key string) map[string]string { + return cast.ToStringMapString(v.Get(key)) +} + +// GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings. +func GetStringMapStringSlice(key string) map[string][]string { return v.GetStringMapStringSlice(key) } +func (v *Viper) GetStringMapStringSlice(key string) map[string][]string { + return cast.ToStringMapStringSlice(v.Get(key)) +} + +// GetSizeInBytes returns the size of the value associated with the given key +// in bytes. +func GetSizeInBytes(key string) uint { return v.GetSizeInBytes(key) } +func (v *Viper) GetSizeInBytes(key string) uint { + sizeStr := cast.ToString(v.Get(key)) + return parseSizeInBytes(sizeStr) +} + +// UnmarshalKey takes a single key and unmarshals it into a Struct. +func UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { + return v.UnmarshalKey(key, rawVal, opts...) +} +func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { + err := decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) + + if err != nil { + return err + } + + return nil +} + +// Unmarshal unmarshals the config into a Struct. Make sure that the tags +// on the fields of the structure are properly set. +func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { + return v.Unmarshal(rawVal, opts...) +} +func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { + err := decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...)) + + if err != nil { + return err + } + + return nil +} + +// defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot +// of time.Duration values & string slices +func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { + c := &mapstructure.DecoderConfig{ + Metadata: nil, + Result: output, + WeaklyTypedInput: true, + DecodeHook: mapstructure.ComposeDecodeHookFunc( + mapstructure.StringToTimeDurationHookFunc(), + mapstructure.StringToSliceHookFunc(","), + ), + } + for _, opt := range opts { + opt(c) + } + return c +} + +// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality +func decode(input interface{}, config *mapstructure.DecoderConfig) error { + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return err + } + return decoder.Decode(input) +} + +// UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent +// in the destination struct. +func UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error { + return v.UnmarshalExact(rawVal, opts...) +} +func (v *Viper) UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error { + config := defaultDecoderConfig(rawVal, opts...) + config.ErrorUnused = true + + err := decode(v.AllSettings(), config) + + if err != nil { + return err + } + + return nil +} + +// BindPFlags binds a full flag set to the configuration, using each flag's long +// name as the config key. +func BindPFlags(flags *pflag.FlagSet) error { return v.BindPFlags(flags) } +func (v *Viper) BindPFlags(flags *pflag.FlagSet) error { + return v.BindFlagValues(pflagValueSet{flags}) +} + +// BindPFlag binds a specific key to a pflag (as used by cobra). +// Example (where serverCmd is a Cobra instance): +// +// serverCmd.Flags().Int("port", 1138, "Port to run Application server on") +// Viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) +// +func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) } +func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error { + return v.BindFlagValue(key, pflagValue{flag}) +} + +// BindFlagValues binds a full FlagValue set to the configuration, using each flag's long +// name as the config key. +func BindFlagValues(flags FlagValueSet) error { return v.BindFlagValues(flags) } +func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) { + flags.VisitAll(func(flag FlagValue) { + if err = v.BindFlagValue(flag.Name(), flag); err != nil { + return + } + }) + return nil +} + +// BindFlagValue binds a specific key to a FlagValue. +// Example (where serverCmd is a Cobra instance): +// +// serverCmd.Flags().Int("port", 1138, "Port to run Application server on") +// Viper.BindFlagValue("port", serverCmd.Flags().Lookup("port")) +// +func BindFlagValue(key string, flag FlagValue) error { return v.BindFlagValue(key, flag) } +func (v *Viper) BindFlagValue(key string, flag FlagValue) error { + if flag == nil { + return fmt.Errorf("flag for %q is nil", key) + } + v.pflags[strings.ToLower(key)] = flag + return nil +} + +// BindEnv binds a Viper key to a ENV variable. +// ENV variables are case sensitive. +// If only a key is provided, it will use the env key matching the key, uppercased. +// EnvPrefix will be used when set when env name is not provided. +func BindEnv(input ...string) error { return v.BindEnv(input...) } +func (v *Viper) BindEnv(input ...string) error { + var key, envkey string + if len(input) == 0 { + return fmt.Errorf("missing key to bind to") + } + + key = strings.ToLower(input[0]) + + if len(input) == 1 { + envkey = v.mergeWithEnvPrefix(key) + } else { + envkey = input[1] + } + + v.env[key] = envkey + + return nil +} + +// Given a key, find the value. +// +// Viper will check to see if an alias exists first. +// Viper will then check in the following order: +// flag, env, config file, key/value store. +// Lastly, if no value was found and flagDefault is true, and if the key +// corresponds to a flag, the flag's default value is returned. +// +// Note: this assumes a lower-cased key given. +func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} { + var ( + val interface{} + exists bool + path = strings.Split(lcaseKey, v.keyDelim) + nested = len(path) > 1 + ) + + // compute the path through the nested maps to the nested value + if nested && v.isPathShadowedInDeepMap(path, castMapStringToMapInterface(v.aliases)) != "" { + return nil + } + + // if the requested key is an alias, then return the proper key + lcaseKey = v.realKey(lcaseKey) + path = strings.Split(lcaseKey, v.keyDelim) + nested = len(path) > 1 + + // Set() override first + val = v.searchMap(v.override, path) + if val != nil { + return val + } + if nested && v.isPathShadowedInDeepMap(path, v.override) != "" { + return nil + } + + // PFlag override next + flag, exists := v.pflags[lcaseKey] + if exists && flag.HasChanged() { + switch flag.ValueType() { + case "int", "int8", "int16", "int32", "int64": + return cast.ToInt(flag.ValueString()) + case "bool": + return cast.ToBool(flag.ValueString()) + case "stringSlice": + s := strings.TrimPrefix(flag.ValueString(), "[") + s = strings.TrimSuffix(s, "]") + res, _ := readAsCSV(s) + return res + case "intSlice": + s := strings.TrimPrefix(flag.ValueString(), "[") + s = strings.TrimSuffix(s, "]") + res, _ := readAsCSV(s) + return cast.ToIntSlice(res) + default: + return flag.ValueString() + } + } + if nested && v.isPathShadowedInFlatMap(path, v.pflags) != "" { + return nil + } + + // Env override next + if v.automaticEnvApplied { + // even if it hasn't been registered, if automaticEnv is used, + // check any Get request + if val, ok := v.getEnv(v.mergeWithEnvPrefix(lcaseKey)); ok { + return val + } + if nested && v.isPathShadowedInAutoEnv(path) != "" { + return nil + } + } + envkey, exists := v.env[lcaseKey] + if exists { + if val, ok := v.getEnv(envkey); ok { + return val + } + } + if nested && v.isPathShadowedInFlatMap(path, v.env) != "" { + return nil + } + + // Config file next + val = v.searchMapWithPathPrefixes(v.config, path) + if val != nil { + return val + } + if nested && v.isPathShadowedInDeepMap(path, v.config) != "" { + return nil + } + + // K/V store next + val = v.searchMap(v.kvstore, path) + if val != nil { + return val + } + if nested && v.isPathShadowedInDeepMap(path, v.kvstore) != "" { + return nil + } + + // Default next + val = v.searchMap(v.defaults, path) + if val != nil { + return val + } + if nested && v.isPathShadowedInDeepMap(path, v.defaults) != "" { + return nil + } + + if flagDefault { + // last chance: if no value is found and a flag does exist for the key, + // get the flag's default value even if the flag's value has not been set. + if flag, exists := v.pflags[lcaseKey]; exists { + switch flag.ValueType() { + case "int", "int8", "int16", "int32", "int64": + return cast.ToInt(flag.ValueString()) + case "bool": + return cast.ToBool(flag.ValueString()) + case "stringSlice": + s := strings.TrimPrefix(flag.ValueString(), "[") + s = strings.TrimSuffix(s, "]") + res, _ := readAsCSV(s) + return res + case "intSlice": + s := strings.TrimPrefix(flag.ValueString(), "[") + s = strings.TrimSuffix(s, "]") + res, _ := readAsCSV(s) + return cast.ToIntSlice(res) + default: + return flag.ValueString() + } + } + // last item, no need to check shadowing + } + + return nil +} + +func readAsCSV(val string) ([]string, error) { + if val == "" { + return []string{}, nil + } + stringReader := strings.NewReader(val) + csvReader := csv.NewReader(stringReader) + return csvReader.Read() +} + +// IsSet checks to see if the key has been set in any of the data locations. +// IsSet is case-insensitive for a key. +func IsSet(key string) bool { return v.IsSet(key) } +func (v *Viper) IsSet(key string) bool { + lcaseKey := strings.ToLower(key) + val := v.find(lcaseKey, false) + return val != nil +} + +// AutomaticEnv has Viper check ENV variables for all. +// keys set in config, default & flags +func AutomaticEnv() { v.AutomaticEnv() } +func (v *Viper) AutomaticEnv() { + v.automaticEnvApplied = true +} + +// SetEnvKeyReplacer sets the strings.Replacer on the viper object +// Useful for mapping an environmental variable to a key that does +// not match it. +func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) } +func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) { + v.envKeyReplacer = r +} + +// RegisterAlias creates an alias that provides another accessor for the same key. +// This enables one to change a name without breaking the application. +func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) } +func (v *Viper) RegisterAlias(alias string, key string) { + v.registerAlias(alias, strings.ToLower(key)) +} + +func (v *Viper) registerAlias(alias string, key string) { + alias = strings.ToLower(alias) + if alias != key && alias != v.realKey(key) { + _, exists := v.aliases[alias] + + if !exists { + // if we alias something that exists in one of the maps to another + // name, we'll never be able to get that value using the original + // name, so move the config value to the new realkey. + if val, ok := v.config[alias]; ok { + delete(v.config, alias) + v.config[key] = val + } + if val, ok := v.kvstore[alias]; ok { + delete(v.kvstore, alias) + v.kvstore[key] = val + } + if val, ok := v.defaults[alias]; ok { + delete(v.defaults, alias) + v.defaults[key] = val + } + if val, ok := v.override[alias]; ok { + delete(v.override, alias) + v.override[key] = val + } + v.aliases[alias] = key + } + } else { + jww.WARN.Println("Creating circular reference alias", alias, key, v.realKey(key)) + } +} + +func (v *Viper) realKey(key string) string { + newkey, exists := v.aliases[key] + if exists { + jww.DEBUG.Println("Alias", key, "to", newkey) + return v.realKey(newkey) + } + return key +} + +// InConfig checks to see if the given key (or an alias) is in the config file. +func InConfig(key string) bool { return v.InConfig(key) } +func (v *Viper) InConfig(key string) bool { + // if the requested key is an alias, then return the proper key + key = v.realKey(key) + + _, exists := v.config[key] + return exists +} + +// SetDefault sets the default value for this key. +// SetDefault is case-insensitive for a key. +// Default only used when no value is provided by the user via flag, config or ENV. +func SetDefault(key string, value interface{}) { v.SetDefault(key, value) } +func (v *Viper) SetDefault(key string, value interface{}) { + // If alias passed in, then set the proper default + key = v.realKey(strings.ToLower(key)) + value = toCaseInsensitiveValue(value) + + path := strings.Split(key, v.keyDelim) + lastKey := strings.ToLower(path[len(path)-1]) + deepestMap := deepSearch(v.defaults, path[0:len(path)-1]) + + // set innermost value + deepestMap[lastKey] = value +} + +// Set sets the value for the key in the override register. +// Set is case-insensitive for a key. +// Will be used instead of values obtained via +// flags, config file, ENV, default, or key/value store. +func Set(key string, value interface{}) { v.Set(key, value) } +func (v *Viper) Set(key string, value interface{}) { + // If alias passed in, then set the proper override + key = v.realKey(strings.ToLower(key)) + value = toCaseInsensitiveValue(value) + + path := strings.Split(key, v.keyDelim) + lastKey := strings.ToLower(path[len(path)-1]) + deepestMap := deepSearch(v.override, path[0:len(path)-1]) + + // set innermost value + deepestMap[lastKey] = value +} + +// ReadInConfig will discover and load the configuration file from disk +// and key/value stores, searching in one of the defined paths. +func ReadInConfig() error { return v.ReadInConfig() } +func (v *Viper) ReadInConfig() error { + jww.INFO.Println("Attempting to read in config file") + filename, err := v.getConfigFile() + if err != nil { + return err + } + + if !stringInSlice(v.getConfigType(), SupportedExts) { + return UnsupportedConfigError(v.getConfigType()) + } + + jww.DEBUG.Println("Reading file: ", filename) + file, err := afero.ReadFile(v.fs, filename) + if err != nil { + return err + } + + config := make(map[string]interface{}) + + err = v.unmarshalReader(bytes.NewReader(file), config) + if err != nil { + return err + } + + v.config = config + return nil +} + +// MergeInConfig merges a new configuration with an existing config. +func MergeInConfig() error { return v.MergeInConfig() } +func (v *Viper) MergeInConfig() error { + jww.INFO.Println("Attempting to merge in config file") + filename, err := v.getConfigFile() + if err != nil { + return err + } + + if !stringInSlice(v.getConfigType(), SupportedExts) { + return UnsupportedConfigError(v.getConfigType()) + } + + file, err := afero.ReadFile(v.fs, filename) + if err != nil { + return err + } + + return v.MergeConfig(bytes.NewReader(file)) +} + +// ReadConfig will read a configuration file, setting existing keys to nil if the +// key does not exist in the file. +func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } +func (v *Viper) ReadConfig(in io.Reader) error { + v.config = make(map[string]interface{}) + return v.unmarshalReader(in, v.config) +} + +// MergeConfig merges a new configuration with an existing config. +func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } +func (v *Viper) MergeConfig(in io.Reader) error { + cfg := make(map[string]interface{}) + if err := v.unmarshalReader(in, cfg); err != nil { + return err + } + return v.MergeConfigMap(cfg) +} + +// MergeConfigMap merges the configuration from the map given with an existing config. +// Note that the map given may be modified. +func MergeConfigMap(cfg map[string]interface{}) error { return v.MergeConfigMap(cfg) } +func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error { + if v.config == nil { + v.config = make(map[string]interface{}) + } + insensitiviseMap(cfg) + mergeMaps(cfg, v.config, nil) + return nil +} + +// WriteConfig writes the current configuration to a file. +func WriteConfig() error { return v.WriteConfig() } +func (v *Viper) WriteConfig() error { + filename, err := v.getConfigFile() + if err != nil { + return err + } + return v.writeConfig(filename, true) +} + +// SafeWriteConfig writes current configuration to file only if the file does not exist. +func SafeWriteConfig() error { return v.SafeWriteConfig() } +func (v *Viper) SafeWriteConfig() error { + if len(v.configPaths) < 1 { + return errors.New("missing configuration for 'configPath'") + } + return v.SafeWriteConfigAs(filepath.Join(v.configPaths[0], v.configName+"."+v.configType)) +} + +// WriteConfigAs writes current configuration to a given filename. +func WriteConfigAs(filename string) error { return v.WriteConfigAs(filename) } +func (v *Viper) WriteConfigAs(filename string) error { + return v.writeConfig(filename, true) +} + +// SafeWriteConfigAs writes current configuration to a given filename if it does not exist. +func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) } +func (v *Viper) SafeWriteConfigAs(filename string) error { + alreadyExists, err := afero.Exists(v.fs, filename) + if alreadyExists && err == nil { + return ConfigFileAlreadyExistsError(filename) + } + return v.writeConfig(filename, false) +} + +func (v *Viper) writeConfig(filename string, force bool) error { + jww.INFO.Println("Attempting to write configuration to file.") + ext := filepath.Ext(filename) + if len(ext) <= 1 { + return fmt.Errorf("filename: %s requires valid extension", filename) + } + configType := ext[1:] + if !stringInSlice(configType, SupportedExts) { + return UnsupportedConfigError(configType) + } + if v.config == nil { + v.config = make(map[string]interface{}) + } + flags := os.O_CREATE | os.O_TRUNC | os.O_WRONLY + if !force { + flags |= os.O_EXCL + } + f, err := v.fs.OpenFile(filename, flags, v.configPermissions) + if err != nil { + return err + } + defer f.Close() + + if err := v.marshalWriter(f, configType); err != nil { + return err + } + + return f.Sync() +} + +// Unmarshal a Reader into a map. +// Should probably be an unexported function. +func unmarshalReader(in io.Reader, c map[string]interface{}) error { + return v.unmarshalReader(in, c) +} +func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error { + buf := new(bytes.Buffer) + buf.ReadFrom(in) + + switch strings.ToLower(v.getConfigType()) { + case "yaml", "yml": + if err := yaml.Unmarshal(buf.Bytes(), &c); err != nil { + return ConfigParseError{err} + } + + case "json": + if err := json.Unmarshal(buf.Bytes(), &c); err != nil { + return ConfigParseError{err} + } + + case "hcl": + obj, err := hcl.Parse(buf.String()) + if err != nil { + return ConfigParseError{err} + } + if err = hcl.DecodeObject(&c, obj); err != nil { + return ConfigParseError{err} + } + + case "toml": + tree, err := toml.LoadReader(buf) + if err != nil { + return ConfigParseError{err} + } + tmap := tree.ToMap() + for k, v := range tmap { + c[k] = v + } + + case "dotenv", "env": + env, err := gotenv.StrictParse(buf) + if err != nil { + return ConfigParseError{err} + } + for k, v := range env { + c[k] = v + } + + case "properties", "props", "prop": + v.properties = properties.NewProperties() + var err error + if v.properties, err = properties.Load(buf.Bytes(), properties.UTF8); err != nil { + return ConfigParseError{err} + } + for _, key := range v.properties.Keys() { + value, _ := v.properties.Get(key) + // recursively build nested maps + path := strings.Split(key, ".") + lastKey := strings.ToLower(path[len(path)-1]) + deepestMap := deepSearch(c, path[0:len(path)-1]) + // set innermost value + deepestMap[lastKey] = value + } + + case "ini": + cfg := ini.Empty() + err := cfg.Append(buf.Bytes()) + if err != nil { + return ConfigParseError{err} + } + sections := cfg.Sections() + for i := 0; i < len(sections); i++ { + section := sections[i] + keys := section.Keys() + for j := 0; j < len(keys); j++ { + key := keys[j] + value := cfg.Section(section.Name()).Key(key.Name()).String() + c[section.Name()+"."+key.Name()] = value + } + } + } + + insensitiviseMap(c) + return nil +} + +// Marshal a map into Writer. +func (v *Viper) marshalWriter(f afero.File, configType string) error { + c := v.AllSettings() + switch configType { + case "json": + b, err := json.MarshalIndent(c, "", " ") + if err != nil { + return ConfigMarshalError{err} + } + _, err = f.WriteString(string(b)) + if err != nil { + return ConfigMarshalError{err} + } + + case "hcl": + b, err := json.Marshal(c) + if err != nil { + return ConfigMarshalError{err} + } + ast, err := hcl.Parse(string(b)) + if err != nil { + return ConfigMarshalError{err} + } + err = printer.Fprint(f, ast.Node) + if err != nil { + return ConfigMarshalError{err} + } + + case "prop", "props", "properties": + if v.properties == nil { + v.properties = properties.NewProperties() + } + p := v.properties + for _, key := range v.AllKeys() { + _, _, err := p.Set(key, v.GetString(key)) + if err != nil { + return ConfigMarshalError{err} + } + } + _, err := p.WriteComment(f, "#", properties.UTF8) + if err != nil { + return ConfigMarshalError{err} + } + + case "dotenv", "env": + lines := []string{} + for _, key := range v.AllKeys() { + envName := strings.ToUpper(strings.Replace(key, ".", "_", -1)) + val := v.Get(key) + lines = append(lines, fmt.Sprintf("%v=%v", envName, val)) + } + s := strings.Join(lines, "\n") + if _, err := f.WriteString(s); err != nil { + return ConfigMarshalError{err} + } + + case "toml": + t, err := toml.TreeFromMap(c) + if err != nil { + return ConfigMarshalError{err} + } + s := t.String() + if _, err := f.WriteString(s); err != nil { + return ConfigMarshalError{err} + } + + case "yaml", "yml": + b, err := yaml.Marshal(c) + if err != nil { + return ConfigMarshalError{err} + } + if _, err = f.WriteString(string(b)); err != nil { + return ConfigMarshalError{err} + } + + case "ini": + keys := v.AllKeys() + cfg := ini.Empty() + ini.PrettyFormat = false + for i := 0; i < len(keys); i++ { + key := keys[i] + lastSep := strings.LastIndex(key, ".") + sectionName := key[:(lastSep)] + keyName := key[(lastSep + 1):] + if sectionName == "default" { + sectionName = "" + } + cfg.Section(sectionName).Key(keyName).SetValue(Get(key).(string)) + } + cfg.WriteTo(f) + } + return nil +} + +func keyExists(k string, m map[string]interface{}) string { + lk := strings.ToLower(k) + for mk := range m { + lmk := strings.ToLower(mk) + if lmk == lk { + return mk + } + } + return "" +} + +func castToMapStringInterface( + src map[interface{}]interface{}) map[string]interface{} { + tgt := map[string]interface{}{} + for k, v := range src { + tgt[fmt.Sprintf("%v", k)] = v + } + return tgt +} + +func castMapStringToMapInterface(src map[string]string) map[string]interface{} { + tgt := map[string]interface{}{} + for k, v := range src { + tgt[k] = v + } + return tgt +} + +func castMapFlagToMapInterface(src map[string]FlagValue) map[string]interface{} { + tgt := map[string]interface{}{} + for k, v := range src { + tgt[k] = v + } + return tgt +} + +// mergeMaps merges two maps. The `itgt` parameter is for handling go-yaml's +// insistence on parsing nested structures as `map[interface{}]interface{}` +// instead of using a `string` as the key for nest structures beyond one level +// deep. Both map types are supported as there is a go-yaml fork that uses +// `map[string]interface{}` instead. +func mergeMaps( + src, tgt map[string]interface{}, itgt map[interface{}]interface{}) { + for sk, sv := range src { + tk := keyExists(sk, tgt) + if tk == "" { + jww.TRACE.Printf("tk=\"\", tgt[%s]=%v", sk, sv) + tgt[sk] = sv + if itgt != nil { + itgt[sk] = sv + } + continue + } + + tv, ok := tgt[tk] + if !ok { + jww.TRACE.Printf("tgt[%s] != ok, tgt[%s]=%v", tk, sk, sv) + tgt[sk] = sv + if itgt != nil { + itgt[sk] = sv + } + continue + } + + svType := reflect.TypeOf(sv) + tvType := reflect.TypeOf(tv) + if svType != tvType { + jww.ERROR.Printf( + "svType != tvType; key=%s, st=%v, tt=%v, sv=%v, tv=%v", + sk, svType, tvType, sv, tv) + continue + } + + jww.TRACE.Printf("processing key=%s, st=%v, tt=%v, sv=%v, tv=%v", + sk, svType, tvType, sv, tv) + + switch ttv := tv.(type) { + case map[interface{}]interface{}: + jww.TRACE.Printf("merging maps (must convert)") + tsv := sv.(map[interface{}]interface{}) + ssv := castToMapStringInterface(tsv) + stv := castToMapStringInterface(ttv) + mergeMaps(ssv, stv, ttv) + case map[string]interface{}: + jww.TRACE.Printf("merging maps") + mergeMaps(sv.(map[string]interface{}), ttv, nil) + default: + jww.TRACE.Printf("setting value") + tgt[tk] = sv + if itgt != nil { + itgt[tk] = sv + } + } + } +} + +// ReadRemoteConfig attempts to get configuration from a remote source +// and read it in the remote configuration registry. +func ReadRemoteConfig() error { return v.ReadRemoteConfig() } +func (v *Viper) ReadRemoteConfig() error { + return v.getKeyValueConfig() +} + +func WatchRemoteConfig() error { return v.WatchRemoteConfig() } +func (v *Viper) WatchRemoteConfig() error { + return v.watchKeyValueConfig() +} + +func (v *Viper) WatchRemoteConfigOnChannel() error { + return v.watchKeyValueConfigOnChannel() +} + +// Retrieve the first found remote configuration. +func (v *Viper) getKeyValueConfig() error { + if RemoteConfig == nil { + return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") + } + + for _, rp := range v.remoteProviders { + val, err := v.getRemoteConfig(rp) + if err != nil { + continue + } + v.kvstore = val + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { + reader, err := RemoteConfig.Get(provider) + if err != nil { + return nil, err + } + err = v.unmarshalReader(reader, v.kvstore) + return v.kvstore, err +} + +// Retrieve the first found remote configuration. +func (v *Viper) watchKeyValueConfigOnChannel() error { + for _, rp := range v.remoteProviders { + respc, _ := RemoteConfig.WatchChannel(rp) + // Todo: Add quit channel + go func(rc <-chan *RemoteResponse) { + for { + b := <-rc + reader := bytes.NewReader(b.Value) + v.unmarshalReader(reader, v.kvstore) + } + }(respc) + return nil + } + return RemoteConfigError("No Files Found") +} + +// Retrieve the first found remote configuration. +func (v *Viper) watchKeyValueConfig() error { + for _, rp := range v.remoteProviders { + val, err := v.watchRemoteConfig(rp) + if err != nil { + continue + } + v.kvstore = val + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { + reader, err := RemoteConfig.Watch(provider) + if err != nil { + return nil, err + } + err = v.unmarshalReader(reader, v.kvstore) + return v.kvstore, err +} + +// AllKeys returns all keys holding a value, regardless of where they are set. +// Nested keys are returned with a v.keyDelim separator +func AllKeys() []string { return v.AllKeys() } +func (v *Viper) AllKeys() []string { + m := map[string]bool{} + // add all paths, by order of descending priority to ensure correct shadowing + m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "") + m = v.flattenAndMergeMap(m, v.override, "") + m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags)) + m = v.mergeFlatMap(m, castMapStringToMapInterface(v.env)) + m = v.flattenAndMergeMap(m, v.config, "") + m = v.flattenAndMergeMap(m, v.kvstore, "") + m = v.flattenAndMergeMap(m, v.defaults, "") + + // convert set of paths to list + a := make([]string, 0, len(m)) + for x := range m { + a = append(a, x) + } + return a +} + +// flattenAndMergeMap recursively flattens the given map into a map[string]bool +// of key paths (used as a set, easier to manipulate than a []string): +// - each path is merged into a single key string, delimited with v.keyDelim +// - if a path is shadowed by an earlier value in the initial shadow map, +// it is skipped. +// The resulting set of paths is merged to the given shadow set at the same time. +func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool { + if shadow != nil && prefix != "" && shadow[prefix] { + // prefix is shadowed => nothing more to flatten + return shadow + } + if shadow == nil { + shadow = make(map[string]bool) + } + + var m2 map[string]interface{} + if prefix != "" { + prefix += v.keyDelim + } + for k, val := range m { + fullKey := prefix + k + switch val.(type) { + case map[string]interface{}: + m2 = val.(map[string]interface{}) + case map[interface{}]interface{}: + m2 = cast.ToStringMap(val) + default: + // immediate value + shadow[strings.ToLower(fullKey)] = true + continue + } + // recursively merge to shadow map + shadow = v.flattenAndMergeMap(shadow, m2, fullKey) + } + return shadow +} + +// mergeFlatMap merges the given maps, excluding values of the second map +// shadowed by values from the first map. +func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool { + // scan keys +outer: + for k := range m { + path := strings.Split(k, v.keyDelim) + // scan intermediate paths + var parentKey string + for i := 1; i < len(path); i++ { + parentKey = strings.Join(path[0:i], v.keyDelim) + if shadow[parentKey] { + // path is shadowed, continue + continue outer + } + } + // add key + shadow[strings.ToLower(k)] = true + } + return shadow +} + +// AllSettings merges all settings and returns them as a map[string]interface{}. +func AllSettings() map[string]interface{} { return v.AllSettings() } +func (v *Viper) AllSettings() map[string]interface{} { + m := map[string]interface{}{} + // start from the list of keys, and construct the map one value at a time + for _, k := range v.AllKeys() { + value := v.Get(k) + if value == nil { + // should not happen, since AllKeys() returns only keys holding a value, + // check just in case anything changes + continue + } + path := strings.Split(k, v.keyDelim) + lastKey := strings.ToLower(path[len(path)-1]) + deepestMap := deepSearch(m, path[0:len(path)-1]) + // set innermost value + deepestMap[lastKey] = value + } + return m +} + +// SetFs sets the filesystem to use to read configuration. +func SetFs(fs afero.Fs) { v.SetFs(fs) } +func (v *Viper) SetFs(fs afero.Fs) { + v.fs = fs +} + +// SetConfigName sets name for the config file. +// Does not include extension. +func SetConfigName(in string) { v.SetConfigName(in) } +func (v *Viper) SetConfigName(in string) { + if in != "" { + v.configName = in + v.configFile = "" + } +} + +// SetConfigType sets the type of the configuration returned by the +// remote source, e.g. "json". +func SetConfigType(in string) { v.SetConfigType(in) } +func (v *Viper) SetConfigType(in string) { + if in != "" { + v.configType = in + } +} + +// SetConfigPermissions sets the permissions for the config file. +func SetConfigPermissions(perm os.FileMode) { v.SetConfigPermissions(perm) } +func (v *Viper) SetConfigPermissions(perm os.FileMode) { + v.configPermissions = perm.Perm() +} + +func (v *Viper) getConfigType() string { + if v.configType != "" { + return v.configType + } + + cf, err := v.getConfigFile() + if err != nil { + return "" + } + + ext := filepath.Ext(cf) + + if len(ext) > 1 { + return ext[1:] + } + + return "" +} + +func (v *Viper) getConfigFile() (string, error) { + if v.configFile == "" { + cf, err := v.findConfigFile() + if err != nil { + return "", err + } + v.configFile = cf + } + return v.configFile, nil +} + +func (v *Viper) searchInPath(in string) (filename string) { + jww.DEBUG.Println("Searching for config in ", in) + for _, ext := range SupportedExts { + jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext)) + if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b { + jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext)) + return filepath.Join(in, v.configName+"."+ext) + } + } + + if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b { + return filepath.Join(in, v.configName) + } + + return "" +} + +// Search all configPaths for any config file. +// Returns the first path that exists (and is a config file). +func (v *Viper) findConfigFile() (string, error) { + jww.INFO.Println("Searching for config in ", v.configPaths) + + for _, cp := range v.configPaths { + file := v.searchInPath(cp) + if file != "" { + return file, nil + } + } + return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} +} + +// Debug prints all configuration registries for debugging +// purposes. +func Debug() { v.Debug() } +func (v *Viper) Debug() { + fmt.Printf("Aliases:\n%#v\n", v.aliases) + fmt.Printf("Override:\n%#v\n", v.override) + fmt.Printf("PFlags:\n%#v\n", v.pflags) + fmt.Printf("Env:\n%#v\n", v.env) + fmt.Printf("Key/Value Store:\n%#v\n", v.kvstore) + fmt.Printf("Config:\n%#v\n", v.config) + fmt.Printf("Defaults:\n%#v\n", v.defaults) +} diff --git a/vendor/github.com/stretchr/objx/.codeclimate.yml b/vendor/github.com/stretchr/objx/.codeclimate.yml new file mode 100644 index 000000000..010d4ccd5 --- /dev/null +++ b/vendor/github.com/stretchr/objx/.codeclimate.yml @@ -0,0 +1,13 @@ +engines: + gofmt: + enabled: true + golint: + enabled: true + govet: + enabled: true + +exclude_patterns: +- ".github/" +- "vendor/" +- "codegen/" +- "doc.go" diff --git a/vendor/github.com/stretchr/objx/.gitignore b/vendor/github.com/stretchr/objx/.gitignore new file mode 100644 index 000000000..ea58090bd --- /dev/null +++ b/vendor/github.com/stretchr/objx/.gitignore @@ -0,0 +1,11 @@ +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out diff --git a/vendor/github.com/stretchr/objx/.travis.yml b/vendor/github.com/stretchr/objx/.travis.yml new file mode 100644 index 000000000..a63efa59d --- /dev/null +++ b/vendor/github.com/stretchr/objx/.travis.yml @@ -0,0 +1,25 @@ +language: go +go: + - 1.8 + - 1.9 + - tip + +env: + global: + - CC_TEST_REPORTER_ID=68feaa3410049ce73e145287acbcdacc525087a30627f96f04e579e75bd71c00 + +before_script: + - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter + - chmod +x ./cc-test-reporter + - ./cc-test-reporter before-build + +install: +- go get github.com/go-task/task/cmd/task + +script: +- task dl-deps +- task lint +- task test-coverage + +after_script: + - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT diff --git a/vendor/github.com/stretchr/objx/Gopkg.lock b/vendor/github.com/stretchr/objx/Gopkg.lock new file mode 100644 index 000000000..eebe342a9 --- /dev/null +++ b/vendor/github.com/stretchr/objx/Gopkg.lock @@ -0,0 +1,30 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require" + ] + revision = "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c" + version = "v1.2.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "2d160a7dea4ffd13c6c31dab40373822f9d78c73beba016d662bef8f7a998876" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/stretchr/objx/Gopkg.toml b/vendor/github.com/stretchr/objx/Gopkg.toml new file mode 100644 index 000000000..d70f1570b --- /dev/null +++ b/vendor/github.com/stretchr/objx/Gopkg.toml @@ -0,0 +1,8 @@ +[prune] + unused-packages = true + non-go = true + go-tests = true + +[[constraint]] + name = "github.com/stretchr/testify" + version = "~1.2.0" diff --git a/vendor/github.com/stretchr/objx/LICENSE b/vendor/github.com/stretchr/objx/LICENSE new file mode 100644 index 000000000..44d4d9d5a --- /dev/null +++ b/vendor/github.com/stretchr/objx/LICENSE @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) 2014 Stretchr, Inc. +Copyright (c) 2017-2018 objx contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/stretchr/objx/README.md b/vendor/github.com/stretchr/objx/README.md new file mode 100644 index 000000000..be5750c94 --- /dev/null +++ b/vendor/github.com/stretchr/objx/README.md @@ -0,0 +1,80 @@ +# Objx +[![Build Status](https://travis-ci.org/stretchr/objx.svg?branch=master)](https://travis-ci.org/stretchr/objx) +[![Go Report Card](https://goreportcard.com/badge/github.com/stretchr/objx)](https://goreportcard.com/report/github.com/stretchr/objx) +[![Maintainability](https://api.codeclimate.com/v1/badges/1d64bc6c8474c2074f2b/maintainability)](https://codeclimate.com/github/stretchr/objx/maintainability) +[![Test Coverage](https://api.codeclimate.com/v1/badges/1d64bc6c8474c2074f2b/test_coverage)](https://codeclimate.com/github/stretchr/objx/test_coverage) +[![Sourcegraph](https://sourcegraph.com/github.com/stretchr/objx/-/badge.svg)](https://sourcegraph.com/github.com/stretchr/objx) +[![GoDoc](https://godoc.org/github.com/stretchr/objx?status.svg)](https://godoc.org/github.com/stretchr/objx) + +Objx - Go package for dealing with maps, slices, JSON and other data. + +Get started: + +- Install Objx with [one line of code](#installation), or [update it with another](#staying-up-to-date) +- Check out the API Documentation http://godoc.org/github.com/stretchr/objx + +## Overview +Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes a powerful `Get` method (among others) that allows you to easily and quickly get access to data within the map, without having to worry too much about type assertions, missing data, default values etc. + +### Pattern +Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy. Call one of the `objx.` functions to create your `objx.Map` to get going: + + m, err := objx.FromJSON(json) + +NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, the rest will be optimistic and try to figure things out without panicking. + +Use `Get` to access the value you're interested in. You can use dot and array +notation too: + + m.Get("places[0].latlng") + +Once you have sought the `Value` you're interested in, you can use the `Is*` methods to determine its type. + + if m.Get("code").IsStr() { // Your code... } + +Or you can just assume the type, and use one of the strong type methods to extract the real value: + + m.Get("code").Int() + +If there's no value there (or if it's the wrong type) then a default value will be returned, or you can be explicit about the default value. + + Get("code").Int(-1) + +If you're dealing with a slice of data as a value, Objx provides many useful methods for iterating, manipulating and selecting that data. You can find out more by exploring the index below. + +### Reading data +A simple example of how to use Objx: + + // Use MustFromJSON to make an objx.Map from some JSON + m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) + + // Get the details + name := m.Get("name").Str() + age := m.Get("age").Int() + + // Get their nickname (or use their name if they don't have one) + nickname := m.Get("nickname").Str(name) + +### Ranging +Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For example, to `range` the data, do what you would expect: + + m := objx.MustFromJSON(json) + for key, value := range m { + // Your code... + } + +## Installation +To install Objx, use go get: + + go get github.com/stretchr/objx + +### Staying up to date +To update Objx to the latest version, run: + + go get -u github.com/stretchr/objx + +### Supported go versions +We support the lastest two major Go versions, which are 1.8 and 1.9 at the moment. + +## Contributing +Please feel free to submit issues, fork the repository and send pull requests! diff --git a/vendor/github.com/stretchr/objx/Taskfile.yml b/vendor/github.com/stretchr/objx/Taskfile.yml new file mode 100644 index 000000000..f8035641f --- /dev/null +++ b/vendor/github.com/stretchr/objx/Taskfile.yml @@ -0,0 +1,32 @@ +default: + deps: [test] + +dl-deps: + desc: Downloads cli dependencies + cmds: + - go get -u github.com/golang/lint/golint + - go get -u github.com/golang/dep/cmd/dep + +update-deps: + desc: Updates dependencies + cmds: + - dep ensure + - dep ensure -update + +lint: + desc: Runs golint + cmds: + - go fmt $(go list ./... | grep -v /vendor/) + - go vet $(go list ./... | grep -v /vendor/) + - golint $(ls *.go | grep -v "doc.go") + silent: true + +test: + desc: Runs go tests + cmds: + - go test -race . + +test-coverage: + desc: Runs go tests and calucates test coverage + cmds: + - go test -coverprofile=c.out . diff --git a/vendor/github.com/stretchr/objx/accessors.go b/vendor/github.com/stretchr/objx/accessors.go new file mode 100644 index 000000000..204356a22 --- /dev/null +++ b/vendor/github.com/stretchr/objx/accessors.go @@ -0,0 +1,148 @@ +package objx + +import ( + "regexp" + "strconv" + "strings" +) + +// arrayAccesRegexString is the regex used to extract the array number +// from the access path +const arrayAccesRegexString = `^(.+)\[([0-9]+)\]$` + +// arrayAccesRegex is the compiled arrayAccesRegexString +var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString) + +// Get gets the value using the specified selector and +// returns it inside a new Obj object. +// +// If it cannot find the value, Get will return a nil +// value inside an instance of Obj. +// +// Get can only operate directly on map[string]interface{} and []interface. +// +// Example +// +// To access the title of the third chapter of the second book, do: +// +// o.Get("books[1].chapters[2].title") +func (m Map) Get(selector string) *Value { + rawObj := access(m, selector, nil, false) + return &Value{data: rawObj} +} + +// Set sets the value using the specified selector and +// returns the object on which Set was called. +// +// Set can only operate directly on map[string]interface{} and []interface +// +// Example +// +// To set the title of the third chapter of the second book, do: +// +// o.Set("books[1].chapters[2].title","Time to Go") +func (m Map) Set(selector string, value interface{}) Map { + access(m, selector, value, true) + return m +} + +// access accesses the object using the selector and performs the +// appropriate action. +func access(current, selector, value interface{}, isSet bool) interface{} { + switch selector.(type) { + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: + if array, ok := current.([]interface{}); ok { + index := intFromInterface(selector) + if index >= len(array) { + return nil + } + return array[index] + } + return nil + + case string: + selStr := selector.(string) + selSegs := strings.SplitN(selStr, PathSeparator, 2) + thisSel := selSegs[0] + index := -1 + var err error + + if strings.Contains(thisSel, "[") { + arrayMatches := arrayAccesRegex.FindStringSubmatch(thisSel) + if len(arrayMatches) > 0 { + // Get the key into the map + thisSel = arrayMatches[1] + + // Get the index into the array at the key + index, err = strconv.Atoi(arrayMatches[2]) + + if err != nil { + // This should never happen. If it does, something has gone + // seriously wrong. Panic. + panic("objx: Array index is not an integer. Must use array[int].") + } + } + } + if curMap, ok := current.(Map); ok { + current = map[string]interface{}(curMap) + } + // get the object in question + switch current.(type) { + case map[string]interface{}: + curMSI := current.(map[string]interface{}) + if len(selSegs) <= 1 && isSet { + curMSI[thisSel] = value + return nil + } + current = curMSI[thisSel] + default: + current = nil + } + // do we need to access the item of an array? + if index > -1 { + if array, ok := current.([]interface{}); ok { + if index < len(array) { + current = array[index] + } else { + current = nil + } + } + } + if len(selSegs) > 1 { + current = access(current, selSegs[1], value, isSet) + } + } + return current +} + +// intFromInterface converts an interface object to the largest +// representation of an unsigned integer using a type switch and +// assertions +func intFromInterface(selector interface{}) int { + var value int + switch selector.(type) { + case int: + value = selector.(int) + case int8: + value = int(selector.(int8)) + case int16: + value = int(selector.(int16)) + case int32: + value = int(selector.(int32)) + case int64: + value = int(selector.(int64)) + case uint: + value = int(selector.(uint)) + case uint8: + value = int(selector.(uint8)) + case uint16: + value = int(selector.(uint16)) + case uint32: + value = int(selector.(uint32)) + case uint64: + value = int(selector.(uint64)) + default: + return 0 + } + return value +} diff --git a/vendor/github.com/stretchr/objx/constants.go b/vendor/github.com/stretchr/objx/constants.go new file mode 100644 index 000000000..f9eb42a25 --- /dev/null +++ b/vendor/github.com/stretchr/objx/constants.go @@ -0,0 +1,13 @@ +package objx + +const ( + // PathSeparator is the character used to separate the elements + // of the keypath. + // + // For example, `location.address.city` + PathSeparator string = "." + + // SignatureSeparator is the character that is used to + // separate the Base64 string from the security signature. + SignatureSeparator = "_" +) diff --git a/vendor/github.com/stretchr/objx/conversions.go b/vendor/github.com/stretchr/objx/conversions.go new file mode 100644 index 000000000..5e020f310 --- /dev/null +++ b/vendor/github.com/stretchr/objx/conversions.go @@ -0,0 +1,108 @@ +package objx + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "net/url" +) + +// JSON converts the contained object to a JSON string +// representation +func (m Map) JSON() (string, error) { + result, err := json.Marshal(m) + if err != nil { + err = errors.New("objx: JSON encode failed with: " + err.Error()) + } + return string(result), err +} + +// MustJSON converts the contained object to a JSON string +// representation and panics if there is an error +func (m Map) MustJSON() string { + result, err := m.JSON() + if err != nil { + panic(err.Error()) + } + return result +} + +// Base64 converts the contained object to a Base64 string +// representation of the JSON string representation +func (m Map) Base64() (string, error) { + var buf bytes.Buffer + + jsonData, err := m.JSON() + if err != nil { + return "", err + } + + encoder := base64.NewEncoder(base64.StdEncoding, &buf) + _, err = encoder.Write([]byte(jsonData)) + if err != nil { + return "", err + } + _ = encoder.Close() + + return buf.String(), nil +} + +// MustBase64 converts the contained object to a Base64 string +// representation of the JSON string representation and panics +// if there is an error +func (m Map) MustBase64() string { + result, err := m.Base64() + if err != nil { + panic(err.Error()) + } + return result +} + +// SignedBase64 converts the contained object to a Base64 string +// representation of the JSON string representation and signs it +// using the provided key. +func (m Map) SignedBase64(key string) (string, error) { + base64, err := m.Base64() + if err != nil { + return "", err + } + + sig := HashWithKey(base64, key) + return base64 + SignatureSeparator + sig, nil +} + +// MustSignedBase64 converts the contained object to a Base64 string +// representation of the JSON string representation and signs it +// using the provided key and panics if there is an error +func (m Map) MustSignedBase64(key string) string { + result, err := m.SignedBase64(key) + if err != nil { + panic(err.Error()) + } + return result +} + +/* + URL Query + ------------------------------------------------ +*/ + +// URLValues creates a url.Values object from an Obj. This +// function requires that the wrapped object be a map[string]interface{} +func (m Map) URLValues() url.Values { + vals := make(url.Values) + for k, v := range m { + //TODO: can this be done without sprintf? + vals.Set(k, fmt.Sprintf("%v", v)) + } + return vals +} + +// URLQuery gets an encoded URL query representing the given +// Obj. This function requires that the wrapped object be a +// map[string]interface{} +func (m Map) URLQuery() (string, error) { + return m.URLValues().Encode(), nil +} diff --git a/vendor/github.com/stretchr/objx/doc.go b/vendor/github.com/stretchr/objx/doc.go new file mode 100644 index 000000000..6d6af1a83 --- /dev/null +++ b/vendor/github.com/stretchr/objx/doc.go @@ -0,0 +1,66 @@ +/* +Objx - Go package for dealing with maps, slices, JSON and other data. + +Overview + +Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes +a powerful `Get` method (among others) that allows you to easily and quickly get +access to data within the map, without having to worry too much about type assertions, +missing data, default values etc. + +Pattern + +Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy. +Call one of the `objx.` functions to create your `objx.Map` to get going: + + m, err := objx.FromJSON(json) + +NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, +the rest will be optimistic and try to figure things out without panicking. + +Use `Get` to access the value you're interested in. You can use dot and array +notation too: + + m.Get("places[0].latlng") + +Once you have sought the `Value` you're interested in, you can use the `Is*` methods to determine its type. + + if m.Get("code").IsStr() { // Your code... } + +Or you can just assume the type, and use one of the strong type methods to extract the real value: + + m.Get("code").Int() + +If there's no value there (or if it's the wrong type) then a default value will be returned, +or you can be explicit about the default value. + + Get("code").Int(-1) + +If you're dealing with a slice of data as a value, Objx provides many useful methods for iterating, +manipulating and selecting that data. You can find out more by exploring the index below. + +Reading data + +A simple example of how to use Objx: + + // Use MustFromJSON to make an objx.Map from some JSON + m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) + + // Get the details + name := m.Get("name").Str() + age := m.Get("age").Int() + + // Get their nickname (or use their name if they don't have one) + nickname := m.Get("nickname").Str(name) + +Ranging + +Since `objx.Map` is a `map[string]interface{}` you can treat it as such. +For example, to `range` the data, do what you would expect: + + m := objx.MustFromJSON(json) + for key, value := range m { + // Your code... + } +*/ +package objx diff --git a/vendor/github.com/stretchr/objx/map.go b/vendor/github.com/stretchr/objx/map.go new file mode 100644 index 000000000..406bc8926 --- /dev/null +++ b/vendor/github.com/stretchr/objx/map.go @@ -0,0 +1,190 @@ +package objx + +import ( + "encoding/base64" + "encoding/json" + "errors" + "io/ioutil" + "net/url" + "strings" +) + +// MSIConvertable is an interface that defines methods for converting your +// custom types to a map[string]interface{} representation. +type MSIConvertable interface { + // MSI gets a map[string]interface{} (msi) representing the + // object. + MSI() map[string]interface{} +} + +// Map provides extended functionality for working with +// untyped data, in particular map[string]interface (msi). +type Map map[string]interface{} + +// Value returns the internal value instance +func (m Map) Value() *Value { + return &Value{data: m} +} + +// Nil represents a nil Map. +var Nil = New(nil) + +// New creates a new Map containing the map[string]interface{} in the data argument. +// If the data argument is not a map[string]interface, New attempts to call the +// MSI() method on the MSIConvertable interface to create one. +func New(data interface{}) Map { + if _, ok := data.(map[string]interface{}); !ok { + if converter, ok := data.(MSIConvertable); ok { + data = converter.MSI() + } else { + return nil + } + } + return Map(data.(map[string]interface{})) +} + +// MSI creates a map[string]interface{} and puts it inside a new Map. +// +// The arguments follow a key, value pattern. +// +// +// Returns nil if any key argument is non-string or if there are an odd number of arguments. +// +// Example +// +// To easily create Maps: +// +// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true)) +// +// // creates an Map equivalent to +// m := objx.Map{"name": "Mat", "age": 29, "subobj": objx.Map{"active": true}} +func MSI(keyAndValuePairs ...interface{}) Map { + newMap := Map{} + keyAndValuePairsLen := len(keyAndValuePairs) + if keyAndValuePairsLen%2 != 0 { + return nil + } + for i := 0; i < keyAndValuePairsLen; i = i + 2 { + key := keyAndValuePairs[i] + value := keyAndValuePairs[i+1] + + // make sure the key is a string + keyString, keyStringOK := key.(string) + if !keyStringOK { + return nil + } + newMap[keyString] = value + } + return newMap +} + +// ****** Conversion Constructors + +// MustFromJSON creates a new Map containing the data specified in the +// jsonString. +// +// Panics if the JSON is invalid. +func MustFromJSON(jsonString string) Map { + o, err := FromJSON(jsonString) + if err != nil { + panic("objx: MustFromJSON failed with error: " + err.Error()) + } + return o +} + +// FromJSON creates a new Map containing the data specified in the +// jsonString. +// +// Returns an error if the JSON is invalid. +func FromJSON(jsonString string) (Map, error) { + var data interface{} + err := json.Unmarshal([]byte(jsonString), &data) + if err != nil { + return Nil, err + } + return New(data), nil +} + +// FromBase64 creates a new Obj containing the data specified +// in the Base64 string. +// +// The string is an encoded JSON string returned by Base64 +func FromBase64(base64String string) (Map, error) { + decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String)) + decoded, err := ioutil.ReadAll(decoder) + if err != nil { + return nil, err + } + return FromJSON(string(decoded)) +} + +// MustFromBase64 creates a new Obj containing the data specified +// in the Base64 string and panics if there is an error. +// +// The string is an encoded JSON string returned by Base64 +func MustFromBase64(base64String string) Map { + result, err := FromBase64(base64String) + if err != nil { + panic("objx: MustFromBase64 failed with error: " + err.Error()) + } + return result +} + +// FromSignedBase64 creates a new Obj containing the data specified +// in the Base64 string. +// +// The string is an encoded JSON string returned by SignedBase64 +func FromSignedBase64(base64String, key string) (Map, error) { + parts := strings.Split(base64String, SignatureSeparator) + if len(parts) != 2 { + return nil, errors.New("objx: Signed base64 string is malformed") + } + + sig := HashWithKey(parts[0], key) + if parts[1] != sig { + return nil, errors.New("objx: Signature for base64 data does not match") + } + return FromBase64(parts[0]) +} + +// MustFromSignedBase64 creates a new Obj containing the data specified +// in the Base64 string and panics if there is an error. +// +// The string is an encoded JSON string returned by Base64 +func MustFromSignedBase64(base64String, key string) Map { + result, err := FromSignedBase64(base64String, key) + if err != nil { + panic("objx: MustFromSignedBase64 failed with error: " + err.Error()) + } + return result +} + +// FromURLQuery generates a new Obj by parsing the specified +// query. +// +// For queries with multiple values, the first value is selected. +func FromURLQuery(query string) (Map, error) { + vals, err := url.ParseQuery(query) + if err != nil { + return nil, err + } + m := Map{} + for k, vals := range vals { + m[k] = vals[0] + } + return m, nil +} + +// MustFromURLQuery generates a new Obj by parsing the specified +// query. +// +// For queries with multiple values, the first value is selected. +// +// Panics if it encounters an error +func MustFromURLQuery(query string) Map { + o, err := FromURLQuery(query) + if err != nil { + panic("objx: MustFromURLQuery failed with error: " + err.Error()) + } + return o +} diff --git a/vendor/github.com/stretchr/objx/mutations.go b/vendor/github.com/stretchr/objx/mutations.go new file mode 100644 index 000000000..c3400a3f7 --- /dev/null +++ b/vendor/github.com/stretchr/objx/mutations.go @@ -0,0 +1,77 @@ +package objx + +// Exclude returns a new Map with the keys in the specified []string +// excluded. +func (m Map) Exclude(exclude []string) Map { + excluded := make(Map) + for k, v := range m { + if !contains(exclude, k) { + excluded[k] = v + } + } + return excluded +} + +// Copy creates a shallow copy of the Obj. +func (m Map) Copy() Map { + copied := Map{} + for k, v := range m { + copied[k] = v + } + return copied +} + +// Merge blends the specified map with a copy of this map and returns the result. +// +// Keys that appear in both will be selected from the specified map. +// This method requires that the wrapped object be a map[string]interface{} +func (m Map) Merge(merge Map) Map { + return m.Copy().MergeHere(merge) +} + +// MergeHere blends the specified map with this map and returns the current map. +// +// Keys that appear in both will be selected from the specified map. The original map +// will be modified. This method requires that +// the wrapped object be a map[string]interface{} +func (m Map) MergeHere(merge Map) Map { + for k, v := range merge { + m[k] = v + } + return m +} + +// Transform builds a new Obj giving the transformer a chance +// to change the keys and values as it goes. This method requires that +// the wrapped object be a map[string]interface{} +func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map { + newMap := Map{} + for k, v := range m { + modifiedKey, modifiedVal := transformer(k, v) + newMap[modifiedKey] = modifiedVal + } + return newMap +} + +// TransformKeys builds a new map using the specified key mapping. +// +// Unspecified keys will be unaltered. +// This method requires that the wrapped object be a map[string]interface{} +func (m Map) TransformKeys(mapping map[string]string) Map { + return m.Transform(func(key string, value interface{}) (string, interface{}) { + if newKey, ok := mapping[key]; ok { + return newKey, value + } + return key, value + }) +} + +// Checks if a string slice contains a string +func contains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} diff --git a/vendor/github.com/stretchr/objx/security.go b/vendor/github.com/stretchr/objx/security.go new file mode 100644 index 000000000..692be8e2a --- /dev/null +++ b/vendor/github.com/stretchr/objx/security.go @@ -0,0 +1,12 @@ +package objx + +import ( + "crypto/sha1" + "encoding/hex" +) + +// HashWithKey hashes the specified string using the security key +func HashWithKey(data, key string) string { + d := sha1.Sum([]byte(data + ":" + key)) + return hex.EncodeToString(d[:]) +} diff --git a/vendor/github.com/stretchr/objx/tests.go b/vendor/github.com/stretchr/objx/tests.go new file mode 100644 index 000000000..d9e0b479a --- /dev/null +++ b/vendor/github.com/stretchr/objx/tests.go @@ -0,0 +1,17 @@ +package objx + +// Has gets whether there is something at the specified selector +// or not. +// +// If m is nil, Has will always return false. +func (m Map) Has(selector string) bool { + if m == nil { + return false + } + return !m.Get(selector).IsNil() +} + +// IsNil gets whether the data is nil or not. +func (v *Value) IsNil() bool { + return v == nil || v.data == nil +} diff --git a/vendor/github.com/stretchr/objx/type_specific_codegen.go b/vendor/github.com/stretchr/objx/type_specific_codegen.go new file mode 100644 index 000000000..202a91f8c --- /dev/null +++ b/vendor/github.com/stretchr/objx/type_specific_codegen.go @@ -0,0 +1,2501 @@ +package objx + +/* + Inter (interface{} and []interface{}) +*/ + +// Inter gets the value as a interface{}, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Inter(optionalDefault ...interface{}) interface{} { + if s, ok := v.data.(interface{}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInter gets the value as a interface{}. +// +// Panics if the object is not a interface{}. +func (v *Value) MustInter() interface{} { + return v.data.(interface{}) +} + +// InterSlice gets the value as a []interface{}, returns the optionalDefault +// value or nil if the value is not a []interface{}. +func (v *Value) InterSlice(optionalDefault ...[]interface{}) []interface{} { + if s, ok := v.data.([]interface{}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInterSlice gets the value as a []interface{}. +// +// Panics if the object is not a []interface{}. +func (v *Value) MustInterSlice() []interface{} { + return v.data.([]interface{}) +} + +// IsInter gets whether the object contained is a interface{} or not. +func (v *Value) IsInter() bool { + _, ok := v.data.(interface{}) + return ok +} + +// IsInterSlice gets whether the object contained is a []interface{} or not. +func (v *Value) IsInterSlice() bool { + _, ok := v.data.([]interface{}) + return ok +} + +// EachInter calls the specified callback for each object +// in the []interface{}. +// +// Panics if the object is the wrong type. +func (v *Value) EachInter(callback func(int, interface{}) bool) *Value { + for index, val := range v.MustInterSlice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereInter uses the specified decider function to select items +// from the []interface{}. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInter(decider func(int, interface{}) bool) *Value { + var selected []interface{} + v.EachInter(func(index int, val interface{}) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupInter uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]interface{}. +func (v *Value) GroupInter(grouper func(int, interface{}) string) *Value { + groups := make(map[string][]interface{}) + v.EachInter(func(index int, val interface{}) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]interface{}, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceInter uses the specified function to replace each interface{}s +// by iterating each item. The data in the returned result will be a +// []interface{} containing the replaced items. +func (v *Value) ReplaceInter(replacer func(int, interface{}) interface{}) *Value { + arr := v.MustInterSlice() + replaced := make([]interface{}, len(arr)) + v.EachInter(func(index int, val interface{}) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectInter uses the specified collector function to collect a value +// for each of the interface{}s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInter(collector func(int, interface{}) interface{}) *Value { + arr := v.MustInterSlice() + collected := make([]interface{}, len(arr)) + v.EachInter(func(index int, val interface{}) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + MSI (map[string]interface{} and []map[string]interface{}) +*/ + +// MSI gets the value as a map[string]interface{}, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) MSI(optionalDefault ...map[string]interface{}) map[string]interface{} { + if s, ok := v.data.(map[string]interface{}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustMSI gets the value as a map[string]interface{}. +// +// Panics if the object is not a map[string]interface{}. +func (v *Value) MustMSI() map[string]interface{} { + return v.data.(map[string]interface{}) +} + +// MSISlice gets the value as a []map[string]interface{}, returns the optionalDefault +// value or nil if the value is not a []map[string]interface{}. +func (v *Value) MSISlice(optionalDefault ...[]map[string]interface{}) []map[string]interface{} { + if s, ok := v.data.([]map[string]interface{}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustMSISlice gets the value as a []map[string]interface{}. +// +// Panics if the object is not a []map[string]interface{}. +func (v *Value) MustMSISlice() []map[string]interface{} { + return v.data.([]map[string]interface{}) +} + +// IsMSI gets whether the object contained is a map[string]interface{} or not. +func (v *Value) IsMSI() bool { + _, ok := v.data.(map[string]interface{}) + return ok +} + +// IsMSISlice gets whether the object contained is a []map[string]interface{} or not. +func (v *Value) IsMSISlice() bool { + _, ok := v.data.([]map[string]interface{}) + return ok +} + +// EachMSI calls the specified callback for each object +// in the []map[string]interface{}. +// +// Panics if the object is the wrong type. +func (v *Value) EachMSI(callback func(int, map[string]interface{}) bool) *Value { + for index, val := range v.MustMSISlice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereMSI uses the specified decider function to select items +// from the []map[string]interface{}. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereMSI(decider func(int, map[string]interface{}) bool) *Value { + var selected []map[string]interface{} + v.EachMSI(func(index int, val map[string]interface{}) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupMSI uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]map[string]interface{}. +func (v *Value) GroupMSI(grouper func(int, map[string]interface{}) string) *Value { + groups := make(map[string][]map[string]interface{}) + v.EachMSI(func(index int, val map[string]interface{}) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]map[string]interface{}, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceMSI uses the specified function to replace each map[string]interface{}s +// by iterating each item. The data in the returned result will be a +// []map[string]interface{} containing the replaced items. +func (v *Value) ReplaceMSI(replacer func(int, map[string]interface{}) map[string]interface{}) *Value { + arr := v.MustMSISlice() + replaced := make([]map[string]interface{}, len(arr)) + v.EachMSI(func(index int, val map[string]interface{}) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectMSI uses the specified collector function to collect a value +// for each of the map[string]interface{}s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectMSI(collector func(int, map[string]interface{}) interface{}) *Value { + arr := v.MustMSISlice() + collected := make([]interface{}, len(arr)) + v.EachMSI(func(index int, val map[string]interface{}) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + ObjxMap ((Map) and [](Map)) +*/ + +// ObjxMap gets the value as a (Map), returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) ObjxMap(optionalDefault ...(Map)) Map { + if s, ok := v.data.((Map)); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return New(nil) +} + +// MustObjxMap gets the value as a (Map). +// +// Panics if the object is not a (Map). +func (v *Value) MustObjxMap() Map { + return v.data.((Map)) +} + +// ObjxMapSlice gets the value as a [](Map), returns the optionalDefault +// value or nil if the value is not a [](Map). +func (v *Value) ObjxMapSlice(optionalDefault ...[](Map)) [](Map) { + if s, ok := v.data.([](Map)); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustObjxMapSlice gets the value as a [](Map). +// +// Panics if the object is not a [](Map). +func (v *Value) MustObjxMapSlice() [](Map) { + return v.data.([](Map)) +} + +// IsObjxMap gets whether the object contained is a (Map) or not. +func (v *Value) IsObjxMap() bool { + _, ok := v.data.((Map)) + return ok +} + +// IsObjxMapSlice gets whether the object contained is a [](Map) or not. +func (v *Value) IsObjxMapSlice() bool { + _, ok := v.data.([](Map)) + return ok +} + +// EachObjxMap calls the specified callback for each object +// in the [](Map). +// +// Panics if the object is the wrong type. +func (v *Value) EachObjxMap(callback func(int, Map) bool) *Value { + for index, val := range v.MustObjxMapSlice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereObjxMap uses the specified decider function to select items +// from the [](Map). The object contained in the result will contain +// only the selected items. +func (v *Value) WhereObjxMap(decider func(int, Map) bool) *Value { + var selected [](Map) + v.EachObjxMap(func(index int, val Map) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupObjxMap uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][](Map). +func (v *Value) GroupObjxMap(grouper func(int, Map) string) *Value { + groups := make(map[string][](Map)) + v.EachObjxMap(func(index int, val Map) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([](Map), 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceObjxMap uses the specified function to replace each (Map)s +// by iterating each item. The data in the returned result will be a +// [](Map) containing the replaced items. +func (v *Value) ReplaceObjxMap(replacer func(int, Map) Map) *Value { + arr := v.MustObjxMapSlice() + replaced := make([](Map), len(arr)) + v.EachObjxMap(func(index int, val Map) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectObjxMap uses the specified collector function to collect a value +// for each of the (Map)s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectObjxMap(collector func(int, Map) interface{}) *Value { + arr := v.MustObjxMapSlice() + collected := make([]interface{}, len(arr)) + v.EachObjxMap(func(index int, val Map) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Bool (bool and []bool) +*/ + +// Bool gets the value as a bool, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Bool(optionalDefault ...bool) bool { + if s, ok := v.data.(bool); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return false +} + +// MustBool gets the value as a bool. +// +// Panics if the object is not a bool. +func (v *Value) MustBool() bool { + return v.data.(bool) +} + +// BoolSlice gets the value as a []bool, returns the optionalDefault +// value or nil if the value is not a []bool. +func (v *Value) BoolSlice(optionalDefault ...[]bool) []bool { + if s, ok := v.data.([]bool); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustBoolSlice gets the value as a []bool. +// +// Panics if the object is not a []bool. +func (v *Value) MustBoolSlice() []bool { + return v.data.([]bool) +} + +// IsBool gets whether the object contained is a bool or not. +func (v *Value) IsBool() bool { + _, ok := v.data.(bool) + return ok +} + +// IsBoolSlice gets whether the object contained is a []bool or not. +func (v *Value) IsBoolSlice() bool { + _, ok := v.data.([]bool) + return ok +} + +// EachBool calls the specified callback for each object +// in the []bool. +// +// Panics if the object is the wrong type. +func (v *Value) EachBool(callback func(int, bool) bool) *Value { + for index, val := range v.MustBoolSlice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereBool uses the specified decider function to select items +// from the []bool. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereBool(decider func(int, bool) bool) *Value { + var selected []bool + v.EachBool(func(index int, val bool) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupBool uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]bool. +func (v *Value) GroupBool(grouper func(int, bool) string) *Value { + groups := make(map[string][]bool) + v.EachBool(func(index int, val bool) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]bool, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceBool uses the specified function to replace each bools +// by iterating each item. The data in the returned result will be a +// []bool containing the replaced items. +func (v *Value) ReplaceBool(replacer func(int, bool) bool) *Value { + arr := v.MustBoolSlice() + replaced := make([]bool, len(arr)) + v.EachBool(func(index int, val bool) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectBool uses the specified collector function to collect a value +// for each of the bools in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectBool(collector func(int, bool) interface{}) *Value { + arr := v.MustBoolSlice() + collected := make([]interface{}, len(arr)) + v.EachBool(func(index int, val bool) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Str (string and []string) +*/ + +// Str gets the value as a string, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Str(optionalDefault ...string) string { + if s, ok := v.data.(string); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return "" +} + +// MustStr gets the value as a string. +// +// Panics if the object is not a string. +func (v *Value) MustStr() string { + return v.data.(string) +} + +// StrSlice gets the value as a []string, returns the optionalDefault +// value or nil if the value is not a []string. +func (v *Value) StrSlice(optionalDefault ...[]string) []string { + if s, ok := v.data.([]string); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustStrSlice gets the value as a []string. +// +// Panics if the object is not a []string. +func (v *Value) MustStrSlice() []string { + return v.data.([]string) +} + +// IsStr gets whether the object contained is a string or not. +func (v *Value) IsStr() bool { + _, ok := v.data.(string) + return ok +} + +// IsStrSlice gets whether the object contained is a []string or not. +func (v *Value) IsStrSlice() bool { + _, ok := v.data.([]string) + return ok +} + +// EachStr calls the specified callback for each object +// in the []string. +// +// Panics if the object is the wrong type. +func (v *Value) EachStr(callback func(int, string) bool) *Value { + for index, val := range v.MustStrSlice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereStr uses the specified decider function to select items +// from the []string. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereStr(decider func(int, string) bool) *Value { + var selected []string + v.EachStr(func(index int, val string) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupStr uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]string. +func (v *Value) GroupStr(grouper func(int, string) string) *Value { + groups := make(map[string][]string) + v.EachStr(func(index int, val string) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]string, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceStr uses the specified function to replace each strings +// by iterating each item. The data in the returned result will be a +// []string containing the replaced items. +func (v *Value) ReplaceStr(replacer func(int, string) string) *Value { + arr := v.MustStrSlice() + replaced := make([]string, len(arr)) + v.EachStr(func(index int, val string) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectStr uses the specified collector function to collect a value +// for each of the strings in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectStr(collector func(int, string) interface{}) *Value { + arr := v.MustStrSlice() + collected := make([]interface{}, len(arr)) + v.EachStr(func(index int, val string) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Int (int and []int) +*/ + +// Int gets the value as a int, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int(optionalDefault ...int) int { + if s, ok := v.data.(int); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt gets the value as a int. +// +// Panics if the object is not a int. +func (v *Value) MustInt() int { + return v.data.(int) +} + +// IntSlice gets the value as a []int, returns the optionalDefault +// value or nil if the value is not a []int. +func (v *Value) IntSlice(optionalDefault ...[]int) []int { + if s, ok := v.data.([]int); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustIntSlice gets the value as a []int. +// +// Panics if the object is not a []int. +func (v *Value) MustIntSlice() []int { + return v.data.([]int) +} + +// IsInt gets whether the object contained is a int or not. +func (v *Value) IsInt() bool { + _, ok := v.data.(int) + return ok +} + +// IsIntSlice gets whether the object contained is a []int or not. +func (v *Value) IsIntSlice() bool { + _, ok := v.data.([]int) + return ok +} + +// EachInt calls the specified callback for each object +// in the []int. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt(callback func(int, int) bool) *Value { + for index, val := range v.MustIntSlice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereInt uses the specified decider function to select items +// from the []int. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt(decider func(int, int) bool) *Value { + var selected []int + v.EachInt(func(index int, val int) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupInt uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int. +func (v *Value) GroupInt(grouper func(int, int) string) *Value { + groups := make(map[string][]int) + v.EachInt(func(index int, val int) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceInt uses the specified function to replace each ints +// by iterating each item. The data in the returned result will be a +// []int containing the replaced items. +func (v *Value) ReplaceInt(replacer func(int, int) int) *Value { + arr := v.MustIntSlice() + replaced := make([]int, len(arr)) + v.EachInt(func(index int, val int) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectInt uses the specified collector function to collect a value +// for each of the ints in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt(collector func(int, int) interface{}) *Value { + arr := v.MustIntSlice() + collected := make([]interface{}, len(arr)) + v.EachInt(func(index int, val int) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Int8 (int8 and []int8) +*/ + +// Int8 gets the value as a int8, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int8(optionalDefault ...int8) int8 { + if s, ok := v.data.(int8); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt8 gets the value as a int8. +// +// Panics if the object is not a int8. +func (v *Value) MustInt8() int8 { + return v.data.(int8) +} + +// Int8Slice gets the value as a []int8, returns the optionalDefault +// value or nil if the value is not a []int8. +func (v *Value) Int8Slice(optionalDefault ...[]int8) []int8 { + if s, ok := v.data.([]int8); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInt8Slice gets the value as a []int8. +// +// Panics if the object is not a []int8. +func (v *Value) MustInt8Slice() []int8 { + return v.data.([]int8) +} + +// IsInt8 gets whether the object contained is a int8 or not. +func (v *Value) IsInt8() bool { + _, ok := v.data.(int8) + return ok +} + +// IsInt8Slice gets whether the object contained is a []int8 or not. +func (v *Value) IsInt8Slice() bool { + _, ok := v.data.([]int8) + return ok +} + +// EachInt8 calls the specified callback for each object +// in the []int8. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt8(callback func(int, int8) bool) *Value { + for index, val := range v.MustInt8Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereInt8 uses the specified decider function to select items +// from the []int8. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt8(decider func(int, int8) bool) *Value { + var selected []int8 + v.EachInt8(func(index int, val int8) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupInt8 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int8. +func (v *Value) GroupInt8(grouper func(int, int8) string) *Value { + groups := make(map[string][]int8) + v.EachInt8(func(index int, val int8) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int8, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceInt8 uses the specified function to replace each int8s +// by iterating each item. The data in the returned result will be a +// []int8 containing the replaced items. +func (v *Value) ReplaceInt8(replacer func(int, int8) int8) *Value { + arr := v.MustInt8Slice() + replaced := make([]int8, len(arr)) + v.EachInt8(func(index int, val int8) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectInt8 uses the specified collector function to collect a value +// for each of the int8s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt8(collector func(int, int8) interface{}) *Value { + arr := v.MustInt8Slice() + collected := make([]interface{}, len(arr)) + v.EachInt8(func(index int, val int8) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Int16 (int16 and []int16) +*/ + +// Int16 gets the value as a int16, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int16(optionalDefault ...int16) int16 { + if s, ok := v.data.(int16); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt16 gets the value as a int16. +// +// Panics if the object is not a int16. +func (v *Value) MustInt16() int16 { + return v.data.(int16) +} + +// Int16Slice gets the value as a []int16, returns the optionalDefault +// value or nil if the value is not a []int16. +func (v *Value) Int16Slice(optionalDefault ...[]int16) []int16 { + if s, ok := v.data.([]int16); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInt16Slice gets the value as a []int16. +// +// Panics if the object is not a []int16. +func (v *Value) MustInt16Slice() []int16 { + return v.data.([]int16) +} + +// IsInt16 gets whether the object contained is a int16 or not. +func (v *Value) IsInt16() bool { + _, ok := v.data.(int16) + return ok +} + +// IsInt16Slice gets whether the object contained is a []int16 or not. +func (v *Value) IsInt16Slice() bool { + _, ok := v.data.([]int16) + return ok +} + +// EachInt16 calls the specified callback for each object +// in the []int16. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt16(callback func(int, int16) bool) *Value { + for index, val := range v.MustInt16Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereInt16 uses the specified decider function to select items +// from the []int16. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt16(decider func(int, int16) bool) *Value { + var selected []int16 + v.EachInt16(func(index int, val int16) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupInt16 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int16. +func (v *Value) GroupInt16(grouper func(int, int16) string) *Value { + groups := make(map[string][]int16) + v.EachInt16(func(index int, val int16) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int16, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceInt16 uses the specified function to replace each int16s +// by iterating each item. The data in the returned result will be a +// []int16 containing the replaced items. +func (v *Value) ReplaceInt16(replacer func(int, int16) int16) *Value { + arr := v.MustInt16Slice() + replaced := make([]int16, len(arr)) + v.EachInt16(func(index int, val int16) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectInt16 uses the specified collector function to collect a value +// for each of the int16s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt16(collector func(int, int16) interface{}) *Value { + arr := v.MustInt16Slice() + collected := make([]interface{}, len(arr)) + v.EachInt16(func(index int, val int16) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Int32 (int32 and []int32) +*/ + +// Int32 gets the value as a int32, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int32(optionalDefault ...int32) int32 { + if s, ok := v.data.(int32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt32 gets the value as a int32. +// +// Panics if the object is not a int32. +func (v *Value) MustInt32() int32 { + return v.data.(int32) +} + +// Int32Slice gets the value as a []int32, returns the optionalDefault +// value or nil if the value is not a []int32. +func (v *Value) Int32Slice(optionalDefault ...[]int32) []int32 { + if s, ok := v.data.([]int32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInt32Slice gets the value as a []int32. +// +// Panics if the object is not a []int32. +func (v *Value) MustInt32Slice() []int32 { + return v.data.([]int32) +} + +// IsInt32 gets whether the object contained is a int32 or not. +func (v *Value) IsInt32() bool { + _, ok := v.data.(int32) + return ok +} + +// IsInt32Slice gets whether the object contained is a []int32 or not. +func (v *Value) IsInt32Slice() bool { + _, ok := v.data.([]int32) + return ok +} + +// EachInt32 calls the specified callback for each object +// in the []int32. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt32(callback func(int, int32) bool) *Value { + for index, val := range v.MustInt32Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereInt32 uses the specified decider function to select items +// from the []int32. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt32(decider func(int, int32) bool) *Value { + var selected []int32 + v.EachInt32(func(index int, val int32) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupInt32 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int32. +func (v *Value) GroupInt32(grouper func(int, int32) string) *Value { + groups := make(map[string][]int32) + v.EachInt32(func(index int, val int32) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int32, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceInt32 uses the specified function to replace each int32s +// by iterating each item. The data in the returned result will be a +// []int32 containing the replaced items. +func (v *Value) ReplaceInt32(replacer func(int, int32) int32) *Value { + arr := v.MustInt32Slice() + replaced := make([]int32, len(arr)) + v.EachInt32(func(index int, val int32) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectInt32 uses the specified collector function to collect a value +// for each of the int32s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt32(collector func(int, int32) interface{}) *Value { + arr := v.MustInt32Slice() + collected := make([]interface{}, len(arr)) + v.EachInt32(func(index int, val int32) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Int64 (int64 and []int64) +*/ + +// Int64 gets the value as a int64, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int64(optionalDefault ...int64) int64 { + if s, ok := v.data.(int64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt64 gets the value as a int64. +// +// Panics if the object is not a int64. +func (v *Value) MustInt64() int64 { + return v.data.(int64) +} + +// Int64Slice gets the value as a []int64, returns the optionalDefault +// value or nil if the value is not a []int64. +func (v *Value) Int64Slice(optionalDefault ...[]int64) []int64 { + if s, ok := v.data.([]int64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInt64Slice gets the value as a []int64. +// +// Panics if the object is not a []int64. +func (v *Value) MustInt64Slice() []int64 { + return v.data.([]int64) +} + +// IsInt64 gets whether the object contained is a int64 or not. +func (v *Value) IsInt64() bool { + _, ok := v.data.(int64) + return ok +} + +// IsInt64Slice gets whether the object contained is a []int64 or not. +func (v *Value) IsInt64Slice() bool { + _, ok := v.data.([]int64) + return ok +} + +// EachInt64 calls the specified callback for each object +// in the []int64. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt64(callback func(int, int64) bool) *Value { + for index, val := range v.MustInt64Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereInt64 uses the specified decider function to select items +// from the []int64. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt64(decider func(int, int64) bool) *Value { + var selected []int64 + v.EachInt64(func(index int, val int64) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupInt64 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int64. +func (v *Value) GroupInt64(grouper func(int, int64) string) *Value { + groups := make(map[string][]int64) + v.EachInt64(func(index int, val int64) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int64, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceInt64 uses the specified function to replace each int64s +// by iterating each item. The data in the returned result will be a +// []int64 containing the replaced items. +func (v *Value) ReplaceInt64(replacer func(int, int64) int64) *Value { + arr := v.MustInt64Slice() + replaced := make([]int64, len(arr)) + v.EachInt64(func(index int, val int64) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectInt64 uses the specified collector function to collect a value +// for each of the int64s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt64(collector func(int, int64) interface{}) *Value { + arr := v.MustInt64Slice() + collected := make([]interface{}, len(arr)) + v.EachInt64(func(index int, val int64) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Uint (uint and []uint) +*/ + +// Uint gets the value as a uint, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint(optionalDefault ...uint) uint { + if s, ok := v.data.(uint); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint gets the value as a uint. +// +// Panics if the object is not a uint. +func (v *Value) MustUint() uint { + return v.data.(uint) +} + +// UintSlice gets the value as a []uint, returns the optionalDefault +// value or nil if the value is not a []uint. +func (v *Value) UintSlice(optionalDefault ...[]uint) []uint { + if s, ok := v.data.([]uint); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUintSlice gets the value as a []uint. +// +// Panics if the object is not a []uint. +func (v *Value) MustUintSlice() []uint { + return v.data.([]uint) +} + +// IsUint gets whether the object contained is a uint or not. +func (v *Value) IsUint() bool { + _, ok := v.data.(uint) + return ok +} + +// IsUintSlice gets whether the object contained is a []uint or not. +func (v *Value) IsUintSlice() bool { + _, ok := v.data.([]uint) + return ok +} + +// EachUint calls the specified callback for each object +// in the []uint. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint(callback func(int, uint) bool) *Value { + for index, val := range v.MustUintSlice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereUint uses the specified decider function to select items +// from the []uint. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint(decider func(int, uint) bool) *Value { + var selected []uint + v.EachUint(func(index int, val uint) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupUint uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint. +func (v *Value) GroupUint(grouper func(int, uint) string) *Value { + groups := make(map[string][]uint) + v.EachUint(func(index int, val uint) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceUint uses the specified function to replace each uints +// by iterating each item. The data in the returned result will be a +// []uint containing the replaced items. +func (v *Value) ReplaceUint(replacer func(int, uint) uint) *Value { + arr := v.MustUintSlice() + replaced := make([]uint, len(arr)) + v.EachUint(func(index int, val uint) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectUint uses the specified collector function to collect a value +// for each of the uints in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint(collector func(int, uint) interface{}) *Value { + arr := v.MustUintSlice() + collected := make([]interface{}, len(arr)) + v.EachUint(func(index int, val uint) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Uint8 (uint8 and []uint8) +*/ + +// Uint8 gets the value as a uint8, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint8(optionalDefault ...uint8) uint8 { + if s, ok := v.data.(uint8); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint8 gets the value as a uint8. +// +// Panics if the object is not a uint8. +func (v *Value) MustUint8() uint8 { + return v.data.(uint8) +} + +// Uint8Slice gets the value as a []uint8, returns the optionalDefault +// value or nil if the value is not a []uint8. +func (v *Value) Uint8Slice(optionalDefault ...[]uint8) []uint8 { + if s, ok := v.data.([]uint8); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUint8Slice gets the value as a []uint8. +// +// Panics if the object is not a []uint8. +func (v *Value) MustUint8Slice() []uint8 { + return v.data.([]uint8) +} + +// IsUint8 gets whether the object contained is a uint8 or not. +func (v *Value) IsUint8() bool { + _, ok := v.data.(uint8) + return ok +} + +// IsUint8Slice gets whether the object contained is a []uint8 or not. +func (v *Value) IsUint8Slice() bool { + _, ok := v.data.([]uint8) + return ok +} + +// EachUint8 calls the specified callback for each object +// in the []uint8. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint8(callback func(int, uint8) bool) *Value { + for index, val := range v.MustUint8Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereUint8 uses the specified decider function to select items +// from the []uint8. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint8(decider func(int, uint8) bool) *Value { + var selected []uint8 + v.EachUint8(func(index int, val uint8) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupUint8 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint8. +func (v *Value) GroupUint8(grouper func(int, uint8) string) *Value { + groups := make(map[string][]uint8) + v.EachUint8(func(index int, val uint8) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint8, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceUint8 uses the specified function to replace each uint8s +// by iterating each item. The data in the returned result will be a +// []uint8 containing the replaced items. +func (v *Value) ReplaceUint8(replacer func(int, uint8) uint8) *Value { + arr := v.MustUint8Slice() + replaced := make([]uint8, len(arr)) + v.EachUint8(func(index int, val uint8) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectUint8 uses the specified collector function to collect a value +// for each of the uint8s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint8(collector func(int, uint8) interface{}) *Value { + arr := v.MustUint8Slice() + collected := make([]interface{}, len(arr)) + v.EachUint8(func(index int, val uint8) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Uint16 (uint16 and []uint16) +*/ + +// Uint16 gets the value as a uint16, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint16(optionalDefault ...uint16) uint16 { + if s, ok := v.data.(uint16); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint16 gets the value as a uint16. +// +// Panics if the object is not a uint16. +func (v *Value) MustUint16() uint16 { + return v.data.(uint16) +} + +// Uint16Slice gets the value as a []uint16, returns the optionalDefault +// value or nil if the value is not a []uint16. +func (v *Value) Uint16Slice(optionalDefault ...[]uint16) []uint16 { + if s, ok := v.data.([]uint16); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUint16Slice gets the value as a []uint16. +// +// Panics if the object is not a []uint16. +func (v *Value) MustUint16Slice() []uint16 { + return v.data.([]uint16) +} + +// IsUint16 gets whether the object contained is a uint16 or not. +func (v *Value) IsUint16() bool { + _, ok := v.data.(uint16) + return ok +} + +// IsUint16Slice gets whether the object contained is a []uint16 or not. +func (v *Value) IsUint16Slice() bool { + _, ok := v.data.([]uint16) + return ok +} + +// EachUint16 calls the specified callback for each object +// in the []uint16. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint16(callback func(int, uint16) bool) *Value { + for index, val := range v.MustUint16Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereUint16 uses the specified decider function to select items +// from the []uint16. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint16(decider func(int, uint16) bool) *Value { + var selected []uint16 + v.EachUint16(func(index int, val uint16) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupUint16 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint16. +func (v *Value) GroupUint16(grouper func(int, uint16) string) *Value { + groups := make(map[string][]uint16) + v.EachUint16(func(index int, val uint16) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint16, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceUint16 uses the specified function to replace each uint16s +// by iterating each item. The data in the returned result will be a +// []uint16 containing the replaced items. +func (v *Value) ReplaceUint16(replacer func(int, uint16) uint16) *Value { + arr := v.MustUint16Slice() + replaced := make([]uint16, len(arr)) + v.EachUint16(func(index int, val uint16) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectUint16 uses the specified collector function to collect a value +// for each of the uint16s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint16(collector func(int, uint16) interface{}) *Value { + arr := v.MustUint16Slice() + collected := make([]interface{}, len(arr)) + v.EachUint16(func(index int, val uint16) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Uint32 (uint32 and []uint32) +*/ + +// Uint32 gets the value as a uint32, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint32(optionalDefault ...uint32) uint32 { + if s, ok := v.data.(uint32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint32 gets the value as a uint32. +// +// Panics if the object is not a uint32. +func (v *Value) MustUint32() uint32 { + return v.data.(uint32) +} + +// Uint32Slice gets the value as a []uint32, returns the optionalDefault +// value or nil if the value is not a []uint32. +func (v *Value) Uint32Slice(optionalDefault ...[]uint32) []uint32 { + if s, ok := v.data.([]uint32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUint32Slice gets the value as a []uint32. +// +// Panics if the object is not a []uint32. +func (v *Value) MustUint32Slice() []uint32 { + return v.data.([]uint32) +} + +// IsUint32 gets whether the object contained is a uint32 or not. +func (v *Value) IsUint32() bool { + _, ok := v.data.(uint32) + return ok +} + +// IsUint32Slice gets whether the object contained is a []uint32 or not. +func (v *Value) IsUint32Slice() bool { + _, ok := v.data.([]uint32) + return ok +} + +// EachUint32 calls the specified callback for each object +// in the []uint32. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint32(callback func(int, uint32) bool) *Value { + for index, val := range v.MustUint32Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereUint32 uses the specified decider function to select items +// from the []uint32. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint32(decider func(int, uint32) bool) *Value { + var selected []uint32 + v.EachUint32(func(index int, val uint32) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupUint32 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint32. +func (v *Value) GroupUint32(grouper func(int, uint32) string) *Value { + groups := make(map[string][]uint32) + v.EachUint32(func(index int, val uint32) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint32, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceUint32 uses the specified function to replace each uint32s +// by iterating each item. The data in the returned result will be a +// []uint32 containing the replaced items. +func (v *Value) ReplaceUint32(replacer func(int, uint32) uint32) *Value { + arr := v.MustUint32Slice() + replaced := make([]uint32, len(arr)) + v.EachUint32(func(index int, val uint32) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectUint32 uses the specified collector function to collect a value +// for each of the uint32s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint32(collector func(int, uint32) interface{}) *Value { + arr := v.MustUint32Slice() + collected := make([]interface{}, len(arr)) + v.EachUint32(func(index int, val uint32) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Uint64 (uint64 and []uint64) +*/ + +// Uint64 gets the value as a uint64, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint64(optionalDefault ...uint64) uint64 { + if s, ok := v.data.(uint64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint64 gets the value as a uint64. +// +// Panics if the object is not a uint64. +func (v *Value) MustUint64() uint64 { + return v.data.(uint64) +} + +// Uint64Slice gets the value as a []uint64, returns the optionalDefault +// value or nil if the value is not a []uint64. +func (v *Value) Uint64Slice(optionalDefault ...[]uint64) []uint64 { + if s, ok := v.data.([]uint64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUint64Slice gets the value as a []uint64. +// +// Panics if the object is not a []uint64. +func (v *Value) MustUint64Slice() []uint64 { + return v.data.([]uint64) +} + +// IsUint64 gets whether the object contained is a uint64 or not. +func (v *Value) IsUint64() bool { + _, ok := v.data.(uint64) + return ok +} + +// IsUint64Slice gets whether the object contained is a []uint64 or not. +func (v *Value) IsUint64Slice() bool { + _, ok := v.data.([]uint64) + return ok +} + +// EachUint64 calls the specified callback for each object +// in the []uint64. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint64(callback func(int, uint64) bool) *Value { + for index, val := range v.MustUint64Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereUint64 uses the specified decider function to select items +// from the []uint64. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint64(decider func(int, uint64) bool) *Value { + var selected []uint64 + v.EachUint64(func(index int, val uint64) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupUint64 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint64. +func (v *Value) GroupUint64(grouper func(int, uint64) string) *Value { + groups := make(map[string][]uint64) + v.EachUint64(func(index int, val uint64) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint64, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceUint64 uses the specified function to replace each uint64s +// by iterating each item. The data in the returned result will be a +// []uint64 containing the replaced items. +func (v *Value) ReplaceUint64(replacer func(int, uint64) uint64) *Value { + arr := v.MustUint64Slice() + replaced := make([]uint64, len(arr)) + v.EachUint64(func(index int, val uint64) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectUint64 uses the specified collector function to collect a value +// for each of the uint64s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint64(collector func(int, uint64) interface{}) *Value { + arr := v.MustUint64Slice() + collected := make([]interface{}, len(arr)) + v.EachUint64(func(index int, val uint64) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Uintptr (uintptr and []uintptr) +*/ + +// Uintptr gets the value as a uintptr, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uintptr(optionalDefault ...uintptr) uintptr { + if s, ok := v.data.(uintptr); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUintptr gets the value as a uintptr. +// +// Panics if the object is not a uintptr. +func (v *Value) MustUintptr() uintptr { + return v.data.(uintptr) +} + +// UintptrSlice gets the value as a []uintptr, returns the optionalDefault +// value or nil if the value is not a []uintptr. +func (v *Value) UintptrSlice(optionalDefault ...[]uintptr) []uintptr { + if s, ok := v.data.([]uintptr); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUintptrSlice gets the value as a []uintptr. +// +// Panics if the object is not a []uintptr. +func (v *Value) MustUintptrSlice() []uintptr { + return v.data.([]uintptr) +} + +// IsUintptr gets whether the object contained is a uintptr or not. +func (v *Value) IsUintptr() bool { + _, ok := v.data.(uintptr) + return ok +} + +// IsUintptrSlice gets whether the object contained is a []uintptr or not. +func (v *Value) IsUintptrSlice() bool { + _, ok := v.data.([]uintptr) + return ok +} + +// EachUintptr calls the specified callback for each object +// in the []uintptr. +// +// Panics if the object is the wrong type. +func (v *Value) EachUintptr(callback func(int, uintptr) bool) *Value { + for index, val := range v.MustUintptrSlice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereUintptr uses the specified decider function to select items +// from the []uintptr. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUintptr(decider func(int, uintptr) bool) *Value { + var selected []uintptr + v.EachUintptr(func(index int, val uintptr) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupUintptr uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uintptr. +func (v *Value) GroupUintptr(grouper func(int, uintptr) string) *Value { + groups := make(map[string][]uintptr) + v.EachUintptr(func(index int, val uintptr) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uintptr, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceUintptr uses the specified function to replace each uintptrs +// by iterating each item. The data in the returned result will be a +// []uintptr containing the replaced items. +func (v *Value) ReplaceUintptr(replacer func(int, uintptr) uintptr) *Value { + arr := v.MustUintptrSlice() + replaced := make([]uintptr, len(arr)) + v.EachUintptr(func(index int, val uintptr) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectUintptr uses the specified collector function to collect a value +// for each of the uintptrs in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUintptr(collector func(int, uintptr) interface{}) *Value { + arr := v.MustUintptrSlice() + collected := make([]interface{}, len(arr)) + v.EachUintptr(func(index int, val uintptr) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Float32 (float32 and []float32) +*/ + +// Float32 gets the value as a float32, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Float32(optionalDefault ...float32) float32 { + if s, ok := v.data.(float32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustFloat32 gets the value as a float32. +// +// Panics if the object is not a float32. +func (v *Value) MustFloat32() float32 { + return v.data.(float32) +} + +// Float32Slice gets the value as a []float32, returns the optionalDefault +// value or nil if the value is not a []float32. +func (v *Value) Float32Slice(optionalDefault ...[]float32) []float32 { + if s, ok := v.data.([]float32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustFloat32Slice gets the value as a []float32. +// +// Panics if the object is not a []float32. +func (v *Value) MustFloat32Slice() []float32 { + return v.data.([]float32) +} + +// IsFloat32 gets whether the object contained is a float32 or not. +func (v *Value) IsFloat32() bool { + _, ok := v.data.(float32) + return ok +} + +// IsFloat32Slice gets whether the object contained is a []float32 or not. +func (v *Value) IsFloat32Slice() bool { + _, ok := v.data.([]float32) + return ok +} + +// EachFloat32 calls the specified callback for each object +// in the []float32. +// +// Panics if the object is the wrong type. +func (v *Value) EachFloat32(callback func(int, float32) bool) *Value { + for index, val := range v.MustFloat32Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereFloat32 uses the specified decider function to select items +// from the []float32. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereFloat32(decider func(int, float32) bool) *Value { + var selected []float32 + v.EachFloat32(func(index int, val float32) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupFloat32 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]float32. +func (v *Value) GroupFloat32(grouper func(int, float32) string) *Value { + groups := make(map[string][]float32) + v.EachFloat32(func(index int, val float32) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]float32, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceFloat32 uses the specified function to replace each float32s +// by iterating each item. The data in the returned result will be a +// []float32 containing the replaced items. +func (v *Value) ReplaceFloat32(replacer func(int, float32) float32) *Value { + arr := v.MustFloat32Slice() + replaced := make([]float32, len(arr)) + v.EachFloat32(func(index int, val float32) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectFloat32 uses the specified collector function to collect a value +// for each of the float32s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectFloat32(collector func(int, float32) interface{}) *Value { + arr := v.MustFloat32Slice() + collected := make([]interface{}, len(arr)) + v.EachFloat32(func(index int, val float32) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Float64 (float64 and []float64) +*/ + +// Float64 gets the value as a float64, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Float64(optionalDefault ...float64) float64 { + if s, ok := v.data.(float64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustFloat64 gets the value as a float64. +// +// Panics if the object is not a float64. +func (v *Value) MustFloat64() float64 { + return v.data.(float64) +} + +// Float64Slice gets the value as a []float64, returns the optionalDefault +// value or nil if the value is not a []float64. +func (v *Value) Float64Slice(optionalDefault ...[]float64) []float64 { + if s, ok := v.data.([]float64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustFloat64Slice gets the value as a []float64. +// +// Panics if the object is not a []float64. +func (v *Value) MustFloat64Slice() []float64 { + return v.data.([]float64) +} + +// IsFloat64 gets whether the object contained is a float64 or not. +func (v *Value) IsFloat64() bool { + _, ok := v.data.(float64) + return ok +} + +// IsFloat64Slice gets whether the object contained is a []float64 or not. +func (v *Value) IsFloat64Slice() bool { + _, ok := v.data.([]float64) + return ok +} + +// EachFloat64 calls the specified callback for each object +// in the []float64. +// +// Panics if the object is the wrong type. +func (v *Value) EachFloat64(callback func(int, float64) bool) *Value { + for index, val := range v.MustFloat64Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereFloat64 uses the specified decider function to select items +// from the []float64. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereFloat64(decider func(int, float64) bool) *Value { + var selected []float64 + v.EachFloat64(func(index int, val float64) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupFloat64 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]float64. +func (v *Value) GroupFloat64(grouper func(int, float64) string) *Value { + groups := make(map[string][]float64) + v.EachFloat64(func(index int, val float64) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]float64, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceFloat64 uses the specified function to replace each float64s +// by iterating each item. The data in the returned result will be a +// []float64 containing the replaced items. +func (v *Value) ReplaceFloat64(replacer func(int, float64) float64) *Value { + arr := v.MustFloat64Slice() + replaced := make([]float64, len(arr)) + v.EachFloat64(func(index int, val float64) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectFloat64 uses the specified collector function to collect a value +// for each of the float64s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectFloat64(collector func(int, float64) interface{}) *Value { + arr := v.MustFloat64Slice() + collected := make([]interface{}, len(arr)) + v.EachFloat64(func(index int, val float64) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Complex64 (complex64 and []complex64) +*/ + +// Complex64 gets the value as a complex64, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Complex64(optionalDefault ...complex64) complex64 { + if s, ok := v.data.(complex64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustComplex64 gets the value as a complex64. +// +// Panics if the object is not a complex64. +func (v *Value) MustComplex64() complex64 { + return v.data.(complex64) +} + +// Complex64Slice gets the value as a []complex64, returns the optionalDefault +// value or nil if the value is not a []complex64. +func (v *Value) Complex64Slice(optionalDefault ...[]complex64) []complex64 { + if s, ok := v.data.([]complex64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustComplex64Slice gets the value as a []complex64. +// +// Panics if the object is not a []complex64. +func (v *Value) MustComplex64Slice() []complex64 { + return v.data.([]complex64) +} + +// IsComplex64 gets whether the object contained is a complex64 or not. +func (v *Value) IsComplex64() bool { + _, ok := v.data.(complex64) + return ok +} + +// IsComplex64Slice gets whether the object contained is a []complex64 or not. +func (v *Value) IsComplex64Slice() bool { + _, ok := v.data.([]complex64) + return ok +} + +// EachComplex64 calls the specified callback for each object +// in the []complex64. +// +// Panics if the object is the wrong type. +func (v *Value) EachComplex64(callback func(int, complex64) bool) *Value { + for index, val := range v.MustComplex64Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereComplex64 uses the specified decider function to select items +// from the []complex64. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereComplex64(decider func(int, complex64) bool) *Value { + var selected []complex64 + v.EachComplex64(func(index int, val complex64) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupComplex64 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]complex64. +func (v *Value) GroupComplex64(grouper func(int, complex64) string) *Value { + groups := make(map[string][]complex64) + v.EachComplex64(func(index int, val complex64) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]complex64, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceComplex64 uses the specified function to replace each complex64s +// by iterating each item. The data in the returned result will be a +// []complex64 containing the replaced items. +func (v *Value) ReplaceComplex64(replacer func(int, complex64) complex64) *Value { + arr := v.MustComplex64Slice() + replaced := make([]complex64, len(arr)) + v.EachComplex64(func(index int, val complex64) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectComplex64 uses the specified collector function to collect a value +// for each of the complex64s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectComplex64(collector func(int, complex64) interface{}) *Value { + arr := v.MustComplex64Slice() + collected := make([]interface{}, len(arr)) + v.EachComplex64(func(index int, val complex64) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} + +/* + Complex128 (complex128 and []complex128) +*/ + +// Complex128 gets the value as a complex128, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Complex128(optionalDefault ...complex128) complex128 { + if s, ok := v.data.(complex128); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustComplex128 gets the value as a complex128. +// +// Panics if the object is not a complex128. +func (v *Value) MustComplex128() complex128 { + return v.data.(complex128) +} + +// Complex128Slice gets the value as a []complex128, returns the optionalDefault +// value or nil if the value is not a []complex128. +func (v *Value) Complex128Slice(optionalDefault ...[]complex128) []complex128 { + if s, ok := v.data.([]complex128); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustComplex128Slice gets the value as a []complex128. +// +// Panics if the object is not a []complex128. +func (v *Value) MustComplex128Slice() []complex128 { + return v.data.([]complex128) +} + +// IsComplex128 gets whether the object contained is a complex128 or not. +func (v *Value) IsComplex128() bool { + _, ok := v.data.(complex128) + return ok +} + +// IsComplex128Slice gets whether the object contained is a []complex128 or not. +func (v *Value) IsComplex128Slice() bool { + _, ok := v.data.([]complex128) + return ok +} + +// EachComplex128 calls the specified callback for each object +// in the []complex128. +// +// Panics if the object is the wrong type. +func (v *Value) EachComplex128(callback func(int, complex128) bool) *Value { + for index, val := range v.MustComplex128Slice() { + carryon := callback(index, val) + if !carryon { + break + } + } + return v +} + +// WhereComplex128 uses the specified decider function to select items +// from the []complex128. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereComplex128(decider func(int, complex128) bool) *Value { + var selected []complex128 + v.EachComplex128(func(index int, val complex128) bool { + shouldSelect := decider(index, val) + if !shouldSelect { + selected = append(selected, val) + } + return true + }) + return &Value{data: selected} +} + +// GroupComplex128 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]complex128. +func (v *Value) GroupComplex128(grouper func(int, complex128) string) *Value { + groups := make(map[string][]complex128) + v.EachComplex128(func(index int, val complex128) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]complex128, 0) + } + groups[group] = append(groups[group], val) + return true + }) + return &Value{data: groups} +} + +// ReplaceComplex128 uses the specified function to replace each complex128s +// by iterating each item. The data in the returned result will be a +// []complex128 containing the replaced items. +func (v *Value) ReplaceComplex128(replacer func(int, complex128) complex128) *Value { + arr := v.MustComplex128Slice() + replaced := make([]complex128, len(arr)) + v.EachComplex128(func(index int, val complex128) bool { + replaced[index] = replacer(index, val) + return true + }) + return &Value{data: replaced} +} + +// CollectComplex128 uses the specified collector function to collect a value +// for each of the complex128s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectComplex128(collector func(int, complex128) interface{}) *Value { + arr := v.MustComplex128Slice() + collected := make([]interface{}, len(arr)) + v.EachComplex128(func(index int, val complex128) bool { + collected[index] = collector(index, val) + return true + }) + return &Value{data: collected} +} diff --git a/vendor/github.com/stretchr/objx/value.go b/vendor/github.com/stretchr/objx/value.go new file mode 100644 index 000000000..e4b4a1433 --- /dev/null +++ b/vendor/github.com/stretchr/objx/value.go @@ -0,0 +1,53 @@ +package objx + +import ( + "fmt" + "strconv" +) + +// Value provides methods for extracting interface{} data in various +// types. +type Value struct { + // data contains the raw data being managed by this Value + data interface{} +} + +// Data returns the raw data contained by this Value +func (v *Value) Data() interface{} { + return v.data +} + +// String returns the value always as a string +func (v *Value) String() string { + switch { + case v.IsStr(): + return v.Str() + case v.IsBool(): + return strconv.FormatBool(v.Bool()) + case v.IsFloat32(): + return strconv.FormatFloat(float64(v.Float32()), 'f', -1, 32) + case v.IsFloat64(): + return strconv.FormatFloat(v.Float64(), 'f', -1, 64) + case v.IsInt(): + return strconv.FormatInt(int64(v.Int()), 10) + case v.IsInt8(): + return strconv.FormatInt(int64(v.Int8()), 10) + case v.IsInt16(): + return strconv.FormatInt(int64(v.Int16()), 10) + case v.IsInt32(): + return strconv.FormatInt(int64(v.Int32()), 10) + case v.IsInt64(): + return strconv.FormatInt(v.Int64(), 10) + case v.IsUint(): + return strconv.FormatUint(uint64(v.Uint()), 10) + case v.IsUint8(): + return strconv.FormatUint(uint64(v.Uint8()), 10) + case v.IsUint16(): + return strconv.FormatUint(uint64(v.Uint16()), 10) + case v.IsUint32(): + return strconv.FormatUint(uint64(v.Uint32()), 10) + case v.IsUint64(): + return strconv.FormatUint(v.Uint64(), 10) + } + return fmt.Sprintf("%#v", v.Data()) +} diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE new file mode 100644 index 000000000..f38ec5956 --- /dev/null +++ b/vendor/github.com/stretchr/testify/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go new file mode 100644 index 000000000..bf89ecd21 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -0,0 +1,622 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package assert + +import ( + http "net/http" + url "net/url" + time "time" +) + +// Conditionf uses a Comparison to assert a complex condition. +func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Condition(t, comp, append([]interface{}{msg}, args...)...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") +// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") +// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") +func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Contains(t, s, contains, append([]interface{}{msg}, args...)...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails +// if the path is a file rather a directory or there is an error checking whether it exists. +func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return DirExists(t, path, append([]interface{}{msg}, args...)...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Emptyf(t, obj, "error message %s", "formatted") +func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Empty(t, object, append([]interface{}{msg}, args...)...) +} + +// Equalf asserts that two objects are equal. +// +// assert.Equalf(t, 123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") +func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) +func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Errorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Error(t, err, append([]interface{}{msg}, args...)...) +} + +// Eventuallyf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) +func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Failf reports a failure through +func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) +} + +// FailNowf fails test +func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) +} + +// Falsef asserts that the specified value is false. +// +// assert.Falsef(t, myBool, "error message %s", "formatted") +func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return False(t, value, append([]interface{}{msg}, args...)...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if +// the path points to a directory or there is an error when trying to check the file. +func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return FileExists(t, path, append([]interface{}{msg}, args...)...) +} + +// Greaterf asserts that the first element is greater than the second +// +// assert.Greaterf(t, 2, 1, "error message %s", "formatted") +// assert.Greaterf(t, float64(2, "error message %s", "formatted"), float64(1)) +// assert.Greaterf(t, "b", "a", "error message %s", "formatted") +func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Greater(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// GreaterOrEqualf asserts that the first element is greater than or equal to the second +// +// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") +func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") +func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) +} + +// IsTypef asserts that the specified objects are of the same type. +func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") +func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Len(t, object, length, append([]interface{}{msg}, args...)...) +} + +// Lessf asserts that the first element is less than the second +// +// assert.Lessf(t, 1, 2, "error message %s", "formatted") +// assert.Lessf(t, float64(1, "error message %s", "formatted"), float64(2)) +// assert.Lessf(t, "a", "b", "error message %s", "formatted") +func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Less(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// LessOrEqualf asserts that the first element is less than or equal to the second +// +// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") +// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") +func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// Neverf asserts that the given condition doesn't satisfy in waitFor time, +// periodically checking the target function each tick. +// +// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Never(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) +} + +// Nilf asserts that the specified object is nil. +// +// assert.Nilf(t, err, "error message %s", "formatted") +func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Nil(t, object, append([]interface{}{msg}, args...)...) +} + +// NoDirExistsf checks whether a directory does not exist in the given path. +// It fails if the path points to an existing _directory_ only. +func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NoDirExists(t, path, append([]interface{}{msg}, args...)...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoErrorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NoError(t, err, append([]interface{}{msg}, args...)...) +} + +// NoFileExistsf checks whether a file does not exist in a given path. It fails +// if the path points to an existing _file_ only. +func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NoFileExists(t, path, append([]interface{}{msg}, args...)...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") +func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotEmpty(t, object, append([]interface{}{msg}, args...)...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// NotNilf asserts that the specified object is not nil. +// +// assert.NotNilf(t, err, "error message %s", "formatted") +func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotNil(t, object, append([]interface{}{msg}, args...)...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") +func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotPanics(t, f, append([]interface{}{msg}, args...)...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") +func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) +} + +// NotSamef asserts that two pointers do not reference the same object. +// +// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) +} + +// NotZerof asserts that i is not the zero value for its type. +func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotZero(t, i, append([]interface{}{msg}, args...)...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") +func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Panics(t, f, append([]interface{}{msg}, args...)...) +} + +// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc +// panics, and that the recovered panic value is an error that satisfies the +// EqualError comparison. +// +// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return PanicsWithError(t, errString, f, append([]interface{}{msg}, args...)...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") +func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) +} + +// Samef asserts that two pointers reference the same object. +// +// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Same(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Subset(t, list, subset, append([]interface{}{msg}, args...)...) +} + +// Truef asserts that the specified value is true. +// +// assert.Truef(t, myBool, "error message %s", "formatted") +func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return True(t, value, append([]interface{}{msg}, args...)...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Zerof asserts that i is the zero value for its type. +func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Zero(t, i, append([]interface{}{msg}, args...)...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl new file mode 100644 index 000000000..d2bb0b817 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl @@ -0,0 +1,5 @@ +{{.CommentFormat}} +func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { + if h, ok := t.(tHelper); ok { h.Helper() } + return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go new file mode 100644 index 000000000..75ecdcaa2 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -0,0 +1,1232 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package assert + +import ( + http "net/http" + url "net/url" + time "time" +) + +// Condition uses a Comparison to assert a complex condition. +func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Condition(a.t, comp, msgAndArgs...) +} + +// Conditionf uses a Comparison to assert a complex condition. +func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Conditionf(a.t, comp, msg, args...) +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Contains("Hello World", "World") +// a.Contains(["Hello", "World"], "World") +// a.Contains({"Hello": "World"}, "Hello") +func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Contains(a.t, s, contains, msgAndArgs...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Containsf("Hello World", "World", "error message %s", "formatted") +// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") +// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") +func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Containsf(a.t, s, contains, msg, args...) +} + +// DirExists checks whether a directory exists in the given path. It also fails +// if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return DirExists(a.t, path, msgAndArgs...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails +// if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return DirExistsf(a.t, path, msg, args...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) +func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ElementsMatch(a.t, listA, listB, msgAndArgs...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ElementsMatchf(a.t, listA, listB, msg, args...) +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Empty(obj) +func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Empty(a.t, object, msgAndArgs...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Emptyf(obj, "error message %s", "formatted") +func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Emptyf(a.t, object, msg, args...) +} + +// Equal asserts that two objects are equal. +// +// a.Equal(123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Equal(a.t, expected, actual, msgAndArgs...) +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualError(err, expectedErrorString) +func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualError(a.t, theError, errString, msgAndArgs...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") +func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualErrorf(a.t, theError, errString, msg, args...) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValues(uint32(123), int32(123)) +func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualValues(a.t, expected, actual, msgAndArgs...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) +func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualValuesf(a.t, expected, actual, msg, args...) +} + +// Equalf asserts that two objects are equal. +// +// a.Equalf(123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Equalf(a.t, expected, actual, msg, args...) +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Error(err) { +// assert.Equal(t, expectedError, err) +// } +func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Error(a.t, err, msgAndArgs...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Errorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Errorf(a.t, err, msg, args...) +} + +// Eventually asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) +func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) +} + +// Eventuallyf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Eventuallyf(a.t, condition, waitFor, tick, msg, args...) +} + +// Exactly asserts that two objects are equal in value and type. +// +// a.Exactly(int32(123), int64(123)) +func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Exactly(a.t, expected, actual, msgAndArgs...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) +func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Exactlyf(a.t, expected, actual, msg, args...) +} + +// Fail reports a failure through +func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Fail(a.t, failureMessage, msgAndArgs...) +} + +// FailNow fails test +func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FailNow(a.t, failureMessage, msgAndArgs...) +} + +// FailNowf fails test +func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FailNowf(a.t, failureMessage, msg, args...) +} + +// Failf reports a failure through +func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Failf(a.t, failureMessage, msg, args...) +} + +// False asserts that the specified value is false. +// +// a.False(myBool) +func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return False(a.t, value, msgAndArgs...) +} + +// Falsef asserts that the specified value is false. +// +// a.Falsef(myBool, "error message %s", "formatted") +func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Falsef(a.t, value, msg, args...) +} + +// FileExists checks whether a file exists in the given path. It also fails if +// the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FileExists(a.t, path, msgAndArgs...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if +// the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FileExistsf(a.t, path, msg, args...) +} + +// Greater asserts that the first element is greater than the second +// +// a.Greater(2, 1) +// a.Greater(float64(2), float64(1)) +// a.Greater("b", "a") +func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Greater(a.t, e1, e2, msgAndArgs...) +} + +// GreaterOrEqual asserts that the first element is greater than or equal to the second +// +// a.GreaterOrEqual(2, 1) +// a.GreaterOrEqual(2, 2) +// a.GreaterOrEqual("b", "a") +// a.GreaterOrEqual("b", "b") +func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return GreaterOrEqual(a.t, e1, e2, msgAndArgs...) +} + +// GreaterOrEqualf asserts that the first element is greater than or equal to the second +// +// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") +// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") +// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") +// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") +func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return GreaterOrEqualf(a.t, e1, e2, msg, args...) +} + +// Greaterf asserts that the first element is greater than the second +// +// a.Greaterf(2, 1, "error message %s", "formatted") +// a.Greaterf(float64(2, "error message %s", "formatted"), float64(1)) +// a.Greaterf("b", "a", "error message %s", "formatted") +func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Greaterf(a.t, e1, e2, msg, args...) +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPError(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPErrorf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) +} + +// Implements asserts that an object is implemented by the specified interface. +// +// a.Implements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Implements(a.t, interfaceObject, object, msgAndArgs...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Implementsf(a.t, interfaceObject, object, msg, args...) +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// a.InDelta(math.Pi, 22/7.0, 0.01) +func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDelta(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") +func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaf(a.t, expected, actual, delta, msg, args...) +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) +} + +// IsType asserts that the specified objects are of the same type. +func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsType(a.t, expectedType, object, msgAndArgs...) +} + +// IsTypef asserts that the specified objects are of the same type. +func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsTypef(a.t, expectedType, object, msg, args...) +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return JSONEq(a.t, expected, actual, msgAndArgs...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return JSONEqf(a.t, expected, actual, msg, args...) +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// a.Len(mySlice, 3) +func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Len(a.t, object, length, msgAndArgs...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// a.Lenf(mySlice, 3, "error message %s", "formatted") +func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Lenf(a.t, object, length, msg, args...) +} + +// Less asserts that the first element is less than the second +// +// a.Less(1, 2) +// a.Less(float64(1), float64(2)) +// a.Less("a", "b") +func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Less(a.t, e1, e2, msgAndArgs...) +} + +// LessOrEqual asserts that the first element is less than or equal to the second +// +// a.LessOrEqual(1, 2) +// a.LessOrEqual(2, 2) +// a.LessOrEqual("a", "b") +// a.LessOrEqual("b", "b") +func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return LessOrEqual(a.t, e1, e2, msgAndArgs...) +} + +// LessOrEqualf asserts that the first element is less than or equal to the second +// +// a.LessOrEqualf(1, 2, "error message %s", "formatted") +// a.LessOrEqualf(2, 2, "error message %s", "formatted") +// a.LessOrEqualf("a", "b", "error message %s", "formatted") +// a.LessOrEqualf("b", "b", "error message %s", "formatted") +func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return LessOrEqualf(a.t, e1, e2, msg, args...) +} + +// Lessf asserts that the first element is less than the second +// +// a.Lessf(1, 2, "error message %s", "formatted") +// a.Lessf(float64(1, "error message %s", "formatted"), float64(2)) +// a.Lessf("a", "b", "error message %s", "formatted") +func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Lessf(a.t, e1, e2, msg, args...) +} + +// Never asserts that the given condition doesn't satisfy in waitFor time, +// periodically checking the target function each tick. +// +// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) +func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Never(a.t, condition, waitFor, tick, msgAndArgs...) +} + +// Neverf asserts that the given condition doesn't satisfy in waitFor time, +// periodically checking the target function each tick. +// +// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Neverf(a.t, condition, waitFor, tick, msg, args...) +} + +// Nil asserts that the specified object is nil. +// +// a.Nil(err) +func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Nil(a.t, object, msgAndArgs...) +} + +// Nilf asserts that the specified object is nil. +// +// a.Nilf(err, "error message %s", "formatted") +func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Nilf(a.t, object, msg, args...) +} + +// NoDirExists checks whether a directory does not exist in the given path. +// It fails if the path points to an existing _directory_ only. +func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoDirExists(a.t, path, msgAndArgs...) +} + +// NoDirExistsf checks whether a directory does not exist in the given path. +// It fails if the path points to an existing _directory_ only. +func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoDirExistsf(a.t, path, msg, args...) +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoError(err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoError(a.t, err, msgAndArgs...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoErrorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoErrorf(a.t, err, msg, args...) +} + +// NoFileExists checks whether a file does not exist in a given path. It fails +// if the path points to an existing _file_ only. +func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoFileExists(a.t, path, msgAndArgs...) +} + +// NoFileExistsf checks whether a file does not exist in a given path. It fails +// if the path points to an existing _file_ only. +func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoFileExistsf(a.t, path, msg, args...) +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContains("Hello World", "Earth") +// a.NotContains(["Hello", "World"], "Earth") +// a.NotContains({"Hello": "World"}, "Earth") +func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotContains(a.t, s, contains, msgAndArgs...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") +// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") +// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") +func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotContainsf(a.t, s, contains, msg, args...) +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmpty(obj) { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEmpty(a.t, object, msgAndArgs...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmptyf(obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEmptyf(a.t, object, msg, args...) +} + +// NotEqual asserts that the specified values are NOT equal. +// +// a.NotEqual(obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEqual(a.t, expected, actual, msgAndArgs...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// a.NotEqualf(obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEqualf(a.t, expected, actual, msg, args...) +} + +// NotNil asserts that the specified object is not nil. +// +// a.NotNil(err) +func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotNil(a.t, object, msgAndArgs...) +} + +// NotNilf asserts that the specified object is not nil. +// +// a.NotNilf(err, "error message %s", "formatted") +func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotNilf(a.t, object, msg, args...) +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanics(func(){ RemainCalm() }) +func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotPanics(a.t, f, msgAndArgs...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") +func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotPanicsf(a.t, f, msg, args...) +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") +// a.NotRegexp("^start", "it's not starting") +func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotRegexp(a.t, rx, str, msgAndArgs...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") +func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotRegexpf(a.t, rx, str, msg, args...) +} + +// NotSame asserts that two pointers do not reference the same object. +// +// a.NotSame(ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSame(a.t, expected, actual, msgAndArgs...) +} + +// NotSamef asserts that two pointers do not reference the same object. +// +// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSamef(a.t, expected, actual, msg, args...) +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSubset(a.t, list, subset, msgAndArgs...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSubsetf(a.t, list, subset, msg, args...) +} + +// NotZero asserts that i is not the zero value for its type. +func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotZero(a.t, i, msgAndArgs...) +} + +// NotZerof asserts that i is not the zero value for its type. +func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotZerof(a.t, i, msg, args...) +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panics(func(){ GoCrazy() }) +func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Panics(a.t, f, msgAndArgs...) +} + +// PanicsWithError asserts that the code inside the specified PanicTestFunc +// panics, and that the recovered panic value is an error that satisfies the +// EqualError comparison. +// +// a.PanicsWithError("crazy error", func(){ GoCrazy() }) +func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithError(a.t, errString, f, msgAndArgs...) +} + +// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc +// panics, and that the recovered panic value is an error that satisfies the +// EqualError comparison. +// +// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithErrorf(a.t, errString, f, msg, args...) +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) +func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithValue(a.t, expected, f, msgAndArgs...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithValuef(a.t, expected, f, msg, args...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Panicsf(a.t, f, msg, args...) +} + +// Regexp asserts that a specified regexp matches a string. +// +// a.Regexp(regexp.MustCompile("start"), "it's starting") +// a.Regexp("start...$", "it's not starting") +func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Regexp(a.t, rx, str, msgAndArgs...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") +func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Regexpf(a.t, rx, str, msg, args...) +} + +// Same asserts that two pointers reference the same object. +// +// a.Same(ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Same(a.t, expected, actual, msgAndArgs...) +} + +// Samef asserts that two pointers reference the same object. +// +// a.Samef(ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Samef(a.t, expected, actual, msg, args...) +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Subset(a.t, list, subset, msgAndArgs...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Subsetf(a.t, list, subset, msg, args...) +} + +// True asserts that the specified value is true. +// +// a.True(myBool) +func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return True(a.t, value, msgAndArgs...) +} + +// Truef asserts that the specified value is true. +// +// a.Truef(myBool, "error message %s", "formatted") +func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Truef(a.t, value, msg, args...) +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) +func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return WithinDurationf(a.t, expected, actual, delta, msg, args...) +} + +// YAMLEq asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return YAMLEq(a.t, expected, actual, msgAndArgs...) +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return YAMLEqf(a.t, expected, actual, msg, args...) +} + +// Zero asserts that i is the zero value for its type. +func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Zero(a.t, i, msgAndArgs...) +} + +// Zerof asserts that i is the zero value for its type. +func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Zerof(a.t, i, msg, args...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl new file mode 100644 index 000000000..188bb9e17 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl @@ -0,0 +1,5 @@ +{{.CommentWithoutT "a"}} +func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { + if h, ok := a.t.(tHelper); ok { h.Helper() } + return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go new file mode 100644 index 000000000..15a486ca6 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go @@ -0,0 +1,309 @@ +package assert + +import ( + "fmt" + "reflect" +) + +func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) { + switch kind { + case reflect.Int: + { + intobj1 := obj1.(int) + intobj2 := obj2.(int) + if intobj1 > intobj2 { + return -1, true + } + if intobj1 == intobj2 { + return 0, true + } + if intobj1 < intobj2 { + return 1, true + } + } + case reflect.Int8: + { + int8obj1 := obj1.(int8) + int8obj2 := obj2.(int8) + if int8obj1 > int8obj2 { + return -1, true + } + if int8obj1 == int8obj2 { + return 0, true + } + if int8obj1 < int8obj2 { + return 1, true + } + } + case reflect.Int16: + { + int16obj1 := obj1.(int16) + int16obj2 := obj2.(int16) + if int16obj1 > int16obj2 { + return -1, true + } + if int16obj1 == int16obj2 { + return 0, true + } + if int16obj1 < int16obj2 { + return 1, true + } + } + case reflect.Int32: + { + int32obj1 := obj1.(int32) + int32obj2 := obj2.(int32) + if int32obj1 > int32obj2 { + return -1, true + } + if int32obj1 == int32obj2 { + return 0, true + } + if int32obj1 < int32obj2 { + return 1, true + } + } + case reflect.Int64: + { + int64obj1 := obj1.(int64) + int64obj2 := obj2.(int64) + if int64obj1 > int64obj2 { + return -1, true + } + if int64obj1 == int64obj2 { + return 0, true + } + if int64obj1 < int64obj2 { + return 1, true + } + } + case reflect.Uint: + { + uintobj1 := obj1.(uint) + uintobj2 := obj2.(uint) + if uintobj1 > uintobj2 { + return -1, true + } + if uintobj1 == uintobj2 { + return 0, true + } + if uintobj1 < uintobj2 { + return 1, true + } + } + case reflect.Uint8: + { + uint8obj1 := obj1.(uint8) + uint8obj2 := obj2.(uint8) + if uint8obj1 > uint8obj2 { + return -1, true + } + if uint8obj1 == uint8obj2 { + return 0, true + } + if uint8obj1 < uint8obj2 { + return 1, true + } + } + case reflect.Uint16: + { + uint16obj1 := obj1.(uint16) + uint16obj2 := obj2.(uint16) + if uint16obj1 > uint16obj2 { + return -1, true + } + if uint16obj1 == uint16obj2 { + return 0, true + } + if uint16obj1 < uint16obj2 { + return 1, true + } + } + case reflect.Uint32: + { + uint32obj1 := obj1.(uint32) + uint32obj2 := obj2.(uint32) + if uint32obj1 > uint32obj2 { + return -1, true + } + if uint32obj1 == uint32obj2 { + return 0, true + } + if uint32obj1 < uint32obj2 { + return 1, true + } + } + case reflect.Uint64: + { + uint64obj1 := obj1.(uint64) + uint64obj2 := obj2.(uint64) + if uint64obj1 > uint64obj2 { + return -1, true + } + if uint64obj1 == uint64obj2 { + return 0, true + } + if uint64obj1 < uint64obj2 { + return 1, true + } + } + case reflect.Float32: + { + float32obj1 := obj1.(float32) + float32obj2 := obj2.(float32) + if float32obj1 > float32obj2 { + return -1, true + } + if float32obj1 == float32obj2 { + return 0, true + } + if float32obj1 < float32obj2 { + return 1, true + } + } + case reflect.Float64: + { + float64obj1 := obj1.(float64) + float64obj2 := obj2.(float64) + if float64obj1 > float64obj2 { + return -1, true + } + if float64obj1 == float64obj2 { + return 0, true + } + if float64obj1 < float64obj2 { + return 1, true + } + } + case reflect.String: + { + stringobj1 := obj1.(string) + stringobj2 := obj2.(string) + if stringobj1 > stringobj2 { + return -1, true + } + if stringobj1 == stringobj2 { + return 0, true + } + if stringobj1 < stringobj2 { + return 1, true + } + } + } + + return 0, false +} + +// Greater asserts that the first element is greater than the second +// +// assert.Greater(t, 2, 1) +// assert.Greater(t, float64(2), float64(1)) +// assert.Greater(t, "b", "a") +func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != -1 { + return Fail(t, fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} + +// GreaterOrEqual asserts that the first element is greater than or equal to the second +// +// assert.GreaterOrEqual(t, 2, 1) +// assert.GreaterOrEqual(t, 2, 2) +// assert.GreaterOrEqual(t, "b", "a") +// assert.GreaterOrEqual(t, "b", "b") +func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != -1 && res != 0 { + return Fail(t, fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} + +// Less asserts that the first element is less than the second +// +// assert.Less(t, 1, 2) +// assert.Less(t, float64(1), float64(2)) +// assert.Less(t, "a", "b") +func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != 1 { + return Fail(t, fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} + +// LessOrEqual asserts that the first element is less than or equal to the second +// +// assert.LessOrEqual(t, 1, 2) +// assert.LessOrEqual(t, 2, 2) +// assert.LessOrEqual(t, "a", "b") +// assert.LessOrEqual(t, "b", "b") +func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != 1 && res != 0 { + return Fail(t, fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go new file mode 100644 index 000000000..bdd81389a --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -0,0 +1,1626 @@ +package assert + +import ( + "bufio" + "bytes" + "encoding/json" + "errors" + "fmt" + "math" + "os" + "reflect" + "regexp" + "runtime" + "runtime/debug" + "strings" + "time" + "unicode" + "unicode/utf8" + + "github.com/davecgh/go-spew/spew" + "github.com/pmezard/go-difflib/difflib" + yaml "gopkg.in/yaml.v2" +) + +//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Errorf(format string, args ...interface{}) +} + +// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful +// for table driven tests. +type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool + +// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful +// for table driven tests. +type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool + +// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful +// for table driven tests. +type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool + +// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful +// for table driven tests. +type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool + +// Comparison a custom function that returns true on success and false on failure +type Comparison func() (success bool) + +/* + Helper functions +*/ + +// ObjectsAreEqual determines if two objects are considered equal. +// +// This function does no assertion of any kind. +func ObjectsAreEqual(expected, actual interface{}) bool { + if expected == nil || actual == nil { + return expected == actual + } + + exp, ok := expected.([]byte) + if !ok { + return reflect.DeepEqual(expected, actual) + } + + act, ok := actual.([]byte) + if !ok { + return false + } + if exp == nil || act == nil { + return exp == nil && act == nil + } + return bytes.Equal(exp, act) +} + +// ObjectsAreEqualValues gets whether two objects are equal, or if their +// values are equal. +func ObjectsAreEqualValues(expected, actual interface{}) bool { + if ObjectsAreEqual(expected, actual) { + return true + } + + actualType := reflect.TypeOf(actual) + if actualType == nil { + return false + } + expectedValue := reflect.ValueOf(expected) + if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { + // Attempt comparison after type conversion + return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + } + + return false +} + +/* CallerInfo is necessary because the assert functions use the testing object +internally, causing it to print the file:line of the assert method, rather than where +the problem actually occurred in calling code.*/ + +// CallerInfo returns an array of strings containing the file and line number +// of each stack frame leading from the current test to the assert call that +// failed. +func CallerInfo() []string { + + pc := uintptr(0) + file := "" + line := 0 + ok := false + name := "" + + callers := []string{} + for i := 0; ; i++ { + pc, file, line, ok = runtime.Caller(i) + if !ok { + // The breaks below failed to terminate the loop, and we ran off the + // end of the call stack. + break + } + + // This is a huge edge case, but it will panic if this is the case, see #180 + if file == "" { + break + } + + f := runtime.FuncForPC(pc) + if f == nil { + break + } + name = f.Name() + + // testing.tRunner is the standard library function that calls + // tests. Subtests are called directly by tRunner, without going through + // the Test/Benchmark/Example function that contains the t.Run calls, so + // with subtests we should break when we hit tRunner, without adding it + // to the list of callers. + if name == "testing.tRunner" { + break + } + + parts := strings.Split(file, "/") + file = parts[len(parts)-1] + if len(parts) > 1 { + dir := parts[len(parts)-2] + if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { + callers = append(callers, fmt.Sprintf("%s:%d", file, line)) + } + } + + // Drop the package + segments := strings.Split(name, ".") + name = segments[len(segments)-1] + if isTest(name, "Test") || + isTest(name, "Benchmark") || + isTest(name, "Example") { + break + } + } + + return callers +} + +// Stolen from the `go test` tool. +// isTest tells whether name looks like a test (or benchmark, according to prefix). +// It is a Test (say) if there is a character after Test that is not a lower-case letter. +// We don't want TesticularCancer. +func isTest(name, prefix string) bool { + if !strings.HasPrefix(name, prefix) { + return false + } + if len(name) == len(prefix) { // "Test" is ok + return true + } + rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(rune) +} + +func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { + if len(msgAndArgs) == 0 || msgAndArgs == nil { + return "" + } + if len(msgAndArgs) == 1 { + msg := msgAndArgs[0] + if msgAsStr, ok := msg.(string); ok { + return msgAsStr + } + return fmt.Sprintf("%+v", msg) + } + if len(msgAndArgs) > 1 { + return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) + } + return "" +} + +// Aligns the provided message so that all lines after the first line start at the same location as the first line. +// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). +// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// basis on which the alignment occurs). +func indentMessageLines(message string, longestLabelLen int) string { + outBuf := new(bytes.Buffer) + + for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { + // no need to align first line because it starts at the correct location (after the label) + if i != 0 { + // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab + outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") + } + outBuf.WriteString(scanner.Text()) + } + + return outBuf.String() +} + +type failNower interface { + FailNow() +} + +// FailNow fails test +func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + Fail(t, failureMessage, msgAndArgs...) + + // We cannot extend TestingT with FailNow() and + // maintain backwards compatibility, so we fallback + // to panicking when FailNow is not available in + // TestingT. + // See issue #263 + + if t, ok := t.(failNower); ok { + t.FailNow() + } else { + panic("test failed and t is missing `FailNow()`") + } + return false +} + +// Fail reports a failure through +func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + content := []labeledContent{ + {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, + {"Error", failureMessage}, + } + + // Add test name if the Go version supports it + if n, ok := t.(interface { + Name() string + }); ok { + content = append(content, labeledContent{"Test", n.Name()}) + } + + message := messageFromMsgAndArgs(msgAndArgs...) + if len(message) > 0 { + content = append(content, labeledContent{"Messages", message}) + } + + t.Errorf("\n%s", ""+labeledOutput(content...)) + + return false +} + +type labeledContent struct { + label string + content string +} + +// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: +// +// \t{{label}}:{{align_spaces}}\t{{content}}\n +// +// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. +// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this +// alignment is achieved, "\t{{content}}\n" is added for the output. +// +// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. +func labeledOutput(content ...labeledContent) string { + longestLabel := 0 + for _, v := range content { + if len(v.label) > longestLabel { + longestLabel = len(v.label) + } + } + var output string + for _, v := range content { + output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" + } + return output +} + +// Implements asserts that an object is implemented by the specified interface. +// +// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) +func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if object == nil { + return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) + } + if !reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) + } + + return true +} + +// IsType asserts that the specified objects are of the same type. +func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { + return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) + } + + return true +} + +// Equal asserts that two objects are equal. +// +// assert.Equal(t, 123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if err := validateEqualArgs(expected, actual); err != nil { + return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", + expected, actual, err), msgAndArgs...) + } + + if !ObjectsAreEqual(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "actual : %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// validateEqualArgs checks whether provided arguments can be safely used in the +// Equal/NotEqual functions. +func validateEqualArgs(expected, actual interface{}) error { + if expected == nil && actual == nil { + return nil + } + + if isFunction(expected) || isFunction(actual) { + return errors.New("cannot take func type as argument") + } + return nil +} + +// Same asserts that two pointers reference the same object. +// +// assert.Same(t, ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if !samePointers(expected, actual) { + return Fail(t, fmt.Sprintf("Not same: \n"+ + "expected: %p %#v\n"+ + "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...) + } + + return true +} + +// NotSame asserts that two pointers do not reference the same object. +// +// assert.NotSame(t, ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if samePointers(expected, actual) { + return Fail(t, fmt.Sprintf( + "Expected and actual point to the same object: %p %#v", + expected, expected), msgAndArgs...) + } + return true +} + +// samePointers compares two generic interface objects and returns whether +// they point to the same object +func samePointers(first, second interface{}) bool { + firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second) + if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr { + return false + } + + firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second) + if firstType != secondType { + return false + } + + // compare pointer addresses + return first == second +} + +// formatUnequalValues takes two values of arbitrary types and returns string +// representations appropriate to be presented to the user. +// +// If the values are not of like type, the returned strings will be prefixed +// with the type name, and the value will be enclosed in parenthesis similar +// to a type conversion in the Go grammar. +func formatUnequalValues(expected, actual interface{}) (e string, a string) { + if reflect.TypeOf(expected) != reflect.TypeOf(actual) { + return fmt.Sprintf("%T(%#v)", expected, expected), + fmt.Sprintf("%T(%#v)", actual, actual) + } + switch expected.(type) { + case time.Duration: + return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual) + } + return fmt.Sprintf("%#v", expected), fmt.Sprintf("%#v", actual) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValues(t, uint32(123), int32(123)) +func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if !ObjectsAreEqualValues(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "actual : %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// Exactly asserts that two objects are equal in value and type. +// +// assert.Exactly(t, int32(123), int64(123)) +func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + aType := reflect.TypeOf(expected) + bType := reflect.TypeOf(actual) + + if aType != bType { + return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) + } + + return Equal(t, expected, actual, msgAndArgs...) + +} + +// NotNil asserts that the specified object is not nil. +// +// assert.NotNil(t, err) +func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !isNil(object) { + return true + } + return Fail(t, "Expected value not to be nil.", msgAndArgs...) +} + +// containsKind checks if a specified kind in the slice of kinds. +func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { + for i := 0; i < len(kinds); i++ { + if kind == kinds[i] { + return true + } + } + + return false +} + +// isNil checks if a specified object is nil or not, without Failing. +func isNil(object interface{}) bool { + if object == nil { + return true + } + + value := reflect.ValueOf(object) + kind := value.Kind() + isNilableKind := containsKind( + []reflect.Kind{ + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice}, + kind) + + if isNilableKind && value.IsNil() { + return true + } + + return false +} + +// Nil asserts that the specified object is nil. +// +// assert.Nil(t, err) +func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if isNil(object) { + return true + } + return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) +} + +// isEmpty gets whether the specified object is considered empty or not. +func isEmpty(object interface{}) bool { + + // get nil case out of the way + if object == nil { + return true + } + + objValue := reflect.ValueOf(object) + + switch objValue.Kind() { + // collection types are empty when they have no element + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + return objValue.Len() == 0 + // pointers are empty if nil or if the value they point to is empty + case reflect.Ptr: + if objValue.IsNil() { + return true + } + deref := objValue.Elem().Interface() + return isEmpty(deref) + // for all other types, compare against the zero value + default: + zero := reflect.Zero(objValue.Type()) + return reflect.DeepEqual(object, zero.Interface()) + } +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Empty(t, obj) +func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + pass := isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + pass := !isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// getLen try to get length of object. +// return (false, 0) if impossible. +func getLen(x interface{}) (ok bool, length int) { + v := reflect.ValueOf(x) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + return true, v.Len() +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// assert.Len(t, mySlice, 3) +func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + ok, l := getLen(object) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + } + + if l != length { + return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + } + return true +} + +// True asserts that the specified value is true. +// +// assert.True(t, myBool) +func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if h, ok := t.(interface { + Helper() + }); ok { + h.Helper() + } + + if value != true { + return Fail(t, "Should be true", msgAndArgs...) + } + + return true + +} + +// False asserts that the specified value is false. +// +// assert.False(t, myBool) +func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if value != false { + return Fail(t, "Should be false", msgAndArgs...) + } + + return true + +} + +// NotEqual asserts that the specified values are NOT equal. +// +// assert.NotEqual(t, obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if err := validateEqualArgs(expected, actual); err != nil { + return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", + expected, actual, err), msgAndArgs...) + } + + if ObjectsAreEqual(expected, actual) { + return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) + } + + return true + +} + +// containsElement try loop over the list check if the list includes the element. +// return (false, false) if impossible. +// return (true, false) if element was not found. +// return (true, true) if element was found. +func includeElement(list interface{}, element interface{}) (ok, found bool) { + + listValue := reflect.ValueOf(list) + listKind := reflect.TypeOf(list).Kind() + defer func() { + if e := recover(); e != nil { + ok = false + found = false + } + }() + + if listKind == reflect.String { + elementValue := reflect.ValueOf(element) + return true, strings.Contains(listValue.String(), elementValue.String()) + } + + if listKind == reflect.Map { + mapKeys := listValue.MapKeys() + for i := 0; i < len(mapKeys); i++ { + if ObjectsAreEqual(mapKeys[i].Interface(), element) { + return true, true + } + } + return true, false + } + + for i := 0; i < listValue.Len(); i++ { + if ObjectsAreEqual(listValue.Index(i).Interface(), element) { + return true, true + } + } + return true, false + +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Contains(t, "Hello World", "World") +// assert.Contains(t, ["Hello", "World"], "World") +// assert.Contains(t, {"Hello": "World"}, "Hello") +func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContains(t, "Hello World", "Earth") +// assert.NotContains(t, ["Hello", "World"], "Earth") +// assert.NotContains(t, {"Hello": "World"}, "Earth") +func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if found { + return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if subset == nil { + return true // we consider nil to be equal to the nil set + } + + subsetValue := reflect.ValueOf(subset) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + + listKind := reflect.TypeOf(list).Kind() + subsetKind := reflect.TypeOf(subset).Kind() + + if listKind != reflect.Array && listKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) + } + + if subsetKind != reflect.Array && subsetKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) + } + + for i := 0; i < subsetValue.Len(); i++ { + element := subsetValue.Index(i).Interface() + ok, found := includeElement(list, element) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...) + } + } + + return true +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if subset == nil { + return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) + } + + subsetValue := reflect.ValueOf(subset) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + + listKind := reflect.TypeOf(list).Kind() + subsetKind := reflect.TypeOf(subset).Kind() + + if listKind != reflect.Array && listKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) + } + + if subsetKind != reflect.Array && subsetKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) + } + + for i := 0; i < subsetValue.Len(); i++ { + element := subsetValue.Index(i).Interface() + ok, found := includeElement(list, element) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + } + if !found { + return true + } + } + + return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) +func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if isEmpty(listA) && isEmpty(listB) { + return true + } + + aKind := reflect.TypeOf(listA).Kind() + bKind := reflect.TypeOf(listB).Kind() + + if aKind != reflect.Array && aKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...) + } + + if bKind != reflect.Array && bKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...) + } + + aValue := reflect.ValueOf(listA) + bValue := reflect.ValueOf(listB) + + aLen := aValue.Len() + bLen := bValue.Len() + + if aLen != bLen { + return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...) + } + + // Mark indexes in bValue that we already used + visited := make([]bool, bLen) + for i := 0; i < aLen; i++ { + element := aValue.Index(i).Interface() + found := false + for j := 0; j < bLen; j++ { + if visited[j] { + continue + } + if ObjectsAreEqual(bValue.Index(j).Interface(), element) { + visited[j] = true + found = true + break + } + } + if !found { + return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...) + } + } + + return true +} + +// Condition uses a Comparison to assert a complex condition. +func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + result := comp() + if !result { + Fail(t, "Condition failed!", msgAndArgs...) + } + return result +} + +// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics +// methods, and represents a simple func that takes no arguments, and returns nothing. +type PanicTestFunc func() + +// didPanic returns true if the function passed to it panics. Otherwise, it returns false. +func didPanic(f PanicTestFunc) (bool, interface{}, string) { + + didPanic := false + var message interface{} + var stack string + func() { + + defer func() { + if message = recover(); message != nil { + didPanic = true + stack = string(debug.Stack()) + } + }() + + // call the target function + f() + + }() + + return didPanic, message, stack + +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panics(t, func(){ GoCrazy() }) +func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) + } + + return true +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) +func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + funcDidPanic, panicValue, panickedStack := didPanic(f) + if !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) + } + if panicValue != expected { + return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...) + } + + return true +} + +// PanicsWithError asserts that the code inside the specified PanicTestFunc +// panics, and that the recovered panic value is an error that satisfies the +// EqualError comparison. +// +// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) +func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + funcDidPanic, panicValue, panickedStack := didPanic(f) + if !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) + } + panicErr, ok := panicValue.(error) + if !ok || panicErr.Error() != errString { + return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...) + } + + return true +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanics(t, func(){ RemainCalm() }) +func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...) + } + + return true +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) +func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + dt := expected.Sub(actual) + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +func toFloat(x interface{}) (float64, bool) { + var xf float64 + xok := true + + switch xn := x.(type) { + case uint8: + xf = float64(xn) + case uint16: + xf = float64(xn) + case uint32: + xf = float64(xn) + case uint64: + xf = float64(xn) + case int: + xf = float64(xn) + case int8: + xf = float64(xn) + case int16: + xf = float64(xn) + case int32: + xf = float64(xn) + case int64: + xf = float64(xn) + case float32: + xf = float64(xn) + case float64: + xf = float64(xn) + case time.Duration: + xf = float64(xn) + default: + xok = false + } + + return xf, xok +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// assert.InDelta(t, math.Pi, 22/7.0, 0.01) +func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + af, aok := toFloat(expected) + bf, bok := toFloat(actual) + + if !aok || !bok { + return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) + } + + if math.IsNaN(af) { + return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...) + } + + if math.IsNaN(bf) { + return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) + } + + dt := af - bf + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) + if !result { + return result + } + } + + return true +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Map || + reflect.TypeOf(expected).Kind() != reflect.Map { + return Fail(t, "Arguments must be maps", msgAndArgs...) + } + + expectedMap := reflect.ValueOf(expected) + actualMap := reflect.ValueOf(actual) + + if expectedMap.Len() != actualMap.Len() { + return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) + } + + for _, k := range expectedMap.MapKeys() { + ev := expectedMap.MapIndex(k) + av := actualMap.MapIndex(k) + + if !ev.IsValid() { + return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) + } + + if !av.IsValid() { + return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) + } + + if !InDelta( + t, + ev.Interface(), + av.Interface(), + delta, + msgAndArgs..., + ) { + return false + } + } + + return true +} + +func calcRelativeError(expected, actual interface{}) (float64, error) { + af, aok := toFloat(expected) + if !aok { + return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) + } + if af == 0 { + return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") + } + bf, bok := toFloat(actual) + if !bok { + return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) + } + + return math.Abs(af-bf) / math.Abs(af), nil +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + actualEpsilon, err := calcRelativeError(expected, actual) + if err != nil { + return Fail(t, err.Error(), msgAndArgs...) + } + if actualEpsilon > epsilon { + return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ + " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) + } + + return true +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) + if !result { + return result + } + } + + return true +} + +/* + Errors +*/ + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if err != nil { + return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) + } + + return true +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Error(t, err) { +// assert.Equal(t, expectedError, err) +// } +func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if err == nil { + return Fail(t, "An error is expected but got nil.", msgAndArgs...) + } + + return true +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualError(t, err, expectedErrorString) +func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !Error(t, theError, msgAndArgs...) { + return false + } + expected := errString + actual := theError.Error() + // don't need to use deep equals here, we know they are both strings + if expected != actual { + return Fail(t, fmt.Sprintf("Error message not equal:\n"+ + "expected: %q\n"+ + "actual : %q", expected, actual), msgAndArgs...) + } + return true +} + +// matchRegexp return true if a specified regexp matches a string. +func matchRegexp(rx interface{}, str interface{}) bool { + + var r *regexp.Regexp + if rr, ok := rx.(*regexp.Regexp); ok { + r = rr + } else { + r = regexp.MustCompile(fmt.Sprint(rx)) + } + + return (r.FindStringIndex(fmt.Sprint(str)) != nil) + +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + match := matchRegexp(rx, str) + + if !match { + Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) + } + + return match +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + match := matchRegexp(rx, str) + + if match { + Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) + } + + return !match + +} + +// Zero asserts that i is the zero value for its type. +func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// NotZero asserts that i is not the zero value for its type. +func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// FileExists checks whether a file exists in the given path. It also fails if +// the path points to a directory or there is an error when trying to check the file. +func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) + } + return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) + } + if info.IsDir() { + return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) + } + return true +} + +// NoFileExists checks whether a file does not exist in a given path. It fails +// if the path points to an existing _file_ only. +func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + return true + } + if info.IsDir() { + return true + } + return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...) +} + +// DirExists checks whether a directory exists in the given path. It also fails +// if the path is a file rather a directory or there is an error checking whether it exists. +func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) + } + return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) + } + if !info.IsDir() { + return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) + } + return true +} + +// NoDirExists checks whether a directory does not exist in the given path. +// It fails if the path points to an existing _directory_ only. +func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return true + } + return true + } + if !info.IsDir() { + return true + } + return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...) +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + var expectedJSONAsInterface, actualJSONAsInterface interface{} + + if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) + } + + if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) + } + + return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) +} + +// YAMLEq asserts that two YAML strings are equivalent. +func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + var expectedYAMLAsInterface, actualYAMLAsInterface interface{} + + if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) + } + + if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) + } + + return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...) +} + +func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { + t := reflect.TypeOf(v) + k := t.Kind() + + if k == reflect.Ptr { + t = t.Elem() + k = t.Kind() + } + return t, k +} + +// diff returns a diff of both values as long as both are of the same type and +// are a struct, map, slice, array or string. Otherwise it returns an empty string. +func diff(expected interface{}, actual interface{}) string { + if expected == nil || actual == nil { + return "" + } + + et, ek := typeAndKind(expected) + at, _ := typeAndKind(actual) + + if et != at { + return "" + } + + if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { + return "" + } + + var e, a string + if et != reflect.TypeOf("") { + e = spewConfig.Sdump(expected) + a = spewConfig.Sdump(actual) + } else { + e = reflect.ValueOf(expected).String() + a = reflect.ValueOf(actual).String() + } + + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(e), + B: difflib.SplitLines(a), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + + return "\n\nDiff:\n" + diff +} + +func isFunction(arg interface{}) bool { + if arg == nil { + return false + } + return reflect.TypeOf(arg).Kind() == reflect.Func +} + +var spewConfig = spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, +} + +type tHelper interface { + Helper() +} + +// Eventually asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) +func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ch := make(chan bool, 1) + + timer := time.NewTimer(waitFor) + defer timer.Stop() + + ticker := time.NewTicker(tick) + defer ticker.Stop() + + for tick := ticker.C; ; { + select { + case <-timer.C: + return Fail(t, "Condition never satisfied", msgAndArgs...) + case <-tick: + tick = nil + go func() { ch <- condition() }() + case v := <-ch: + if v { + return true + } + tick = ticker.C + } + } +} + +// Never asserts that the given condition doesn't satisfy in waitFor time, +// periodically checking the target function each tick. +// +// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) +func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ch := make(chan bool, 1) + + timer := time.NewTimer(waitFor) + defer timer.Stop() + + ticker := time.NewTicker(tick) + defer ticker.Stop() + + for tick := ticker.C; ; { + select { + case <-timer.C: + return true + case <-tick: + tick = nil + go func() { ch <- condition() }() + case v := <-ch: + if v { + return Fail(t, "Condition satisfied", msgAndArgs...) + } + tick = ticker.C + } + } +} diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go new file mode 100644 index 000000000..c9dccc4d6 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/doc.go @@ -0,0 +1,45 @@ +// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. +// +// Example Usage +// +// The following is a complete example using assert in a standard test function: +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(t, a, b, "The two words should be the same.") +// +// } +// +// if you assert many times, use the format below: +// +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// assert := assert.New(t) +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(a, b, "The two words should be the same.") +// } +// +// Assertions +// +// Assertions allow you to easily write test code, and are global funcs in the `assert` package. +// All assertion functions take, as the first argument, the `*testing.T` object provided by the +// testing framework. This allows the assertion funcs to write the failings and other details to +// the correct place. +// +// Every assertion function also takes an optional string message as the final argument, +// allowing custom error messages to be appended to the message the assertion method outputs. +package assert diff --git a/vendor/github.com/stretchr/testify/assert/errors.go b/vendor/github.com/stretchr/testify/assert/errors.go new file mode 100644 index 000000000..ac9dc9d1d --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/errors.go @@ -0,0 +1,10 @@ +package assert + +import ( + "errors" +) + +// AnError is an error instance useful for testing. If the code does not care +// about error specifics, and only needs to return the error for example, this +// error should be used to make the test code more readable. +var AnError = errors.New("assert.AnError general error for testing") diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go new file mode 100644 index 000000000..df189d234 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go @@ -0,0 +1,16 @@ +package assert + +// Assertions provides assertion methods around the +// TestingT interface. +type Assertions struct { + t TestingT +} + +// New makes a new Assertions object for the specified TestingT. +func New(t TestingT) *Assertions { + return &Assertions{ + t: t, + } +} + +//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs" diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go new file mode 100644 index 000000000..df46fa777 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -0,0 +1,143 @@ +package assert + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "strings" +) + +// httpCode is a helper that returns HTTP code of the response. It returns -1 and +// an error if building a new request fails. +func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url, nil) + if err != nil { + return -1, err + } + req.URL.RawQuery = values.Encode() + handler(w, req) + return w.Code, nil +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent + if !isSuccessCode { + Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isSuccessCode +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect + if !isRedirectCode { + Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isRedirectCode +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isErrorCode := code >= http.StatusBadRequest + if !isErrorCode { + Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isErrorCode +} + +// HTTPBody is a helper that returns HTTP body of the response. It returns +// empty string if building a new request fails. +func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if err != nil { + return "" + } + handler(w, req) + return w.Body.String() +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if !contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return contains +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return !contains +} diff --git a/vendor/github.com/stretchr/testify/mock/doc.go b/vendor/github.com/stretchr/testify/mock/doc.go new file mode 100644 index 000000000..7324128ef --- /dev/null +++ b/vendor/github.com/stretchr/testify/mock/doc.go @@ -0,0 +1,44 @@ +// Package mock provides a system by which it is possible to mock your objects +// and verify calls are happening as expected. +// +// Example Usage +// +// The mock package provides an object, Mock, that tracks activity on another object. It is usually +// embedded into a test object as shown below: +// +// type MyTestObject struct { +// // add a Mock object instance +// mock.Mock +// +// // other fields go here as normal +// } +// +// When implementing the methods of an interface, you wire your functions up +// to call the Mock.Called(args...) method, and return the appropriate values. +// +// For example, to mock a method that saves the name and age of a person and returns +// the year of their birth or an error, you might write this: +// +// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) { +// args := o.Called(firstname, lastname, age) +// return args.Int(0), args.Error(1) +// } +// +// The Int, Error and Bool methods are examples of strongly typed getters that take the argument +// index position. Given this argument list: +// +// (12, true, "Something") +// +// You could read them out strongly typed like this: +// +// args.Int(0) +// args.Bool(1) +// args.String(2) +// +// For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion: +// +// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine) +// +// This may cause a panic if the object you are getting is nil (the type assertion will fail), in those +// cases you should check for nil first. +package mock diff --git a/vendor/github.com/stretchr/testify/mock/mock.go b/vendor/github.com/stretchr/testify/mock/mock.go new file mode 100644 index 000000000..58e0798da --- /dev/null +++ b/vendor/github.com/stretchr/testify/mock/mock.go @@ -0,0 +1,917 @@ +package mock + +import ( + "errors" + "fmt" + "reflect" + "regexp" + "runtime" + "strings" + "sync" + "time" + + "github.com/davecgh/go-spew/spew" + "github.com/pmezard/go-difflib/difflib" + "github.com/stretchr/objx" + "github.com/stretchr/testify/assert" +) + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Logf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) + FailNow() +} + +/* + Call +*/ + +// Call represents a method call and is used for setting expectations, +// as well as recording activity. +type Call struct { + Parent *Mock + + // The name of the method that was or will be called. + Method string + + // Holds the arguments of the method. + Arguments Arguments + + // Holds the arguments that should be returned when + // this method is called. + ReturnArguments Arguments + + // Holds the caller info for the On() call + callerInfo []string + + // The number of times to return the return arguments when setting + // expectations. 0 means to always return the value. + Repeatability int + + // Amount of times this call has been called + totalCalls int + + // Call to this method can be optional + optional bool + + // Holds a channel that will be used to block the Return until it either + // receives a message or is closed. nil means it returns immediately. + WaitFor <-chan time.Time + + waitTime time.Duration + + // Holds a handler used to manipulate arguments content that are passed by + // reference. It's useful when mocking methods such as unmarshalers or + // decoders. + RunFn func(Arguments) +} + +func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call { + return &Call{ + Parent: parent, + Method: methodName, + Arguments: methodArguments, + ReturnArguments: make([]interface{}, 0), + callerInfo: callerInfo, + Repeatability: 0, + WaitFor: nil, + RunFn: nil, + } +} + +func (c *Call) lock() { + c.Parent.mutex.Lock() +} + +func (c *Call) unlock() { + c.Parent.mutex.Unlock() +} + +// Return specifies the return arguments for the expectation. +// +// Mock.On("DoSomething").Return(errors.New("failed")) +func (c *Call) Return(returnArguments ...interface{}) *Call { + c.lock() + defer c.unlock() + + c.ReturnArguments = returnArguments + + return c +} + +// Once indicates that that the mock should only return the value once. +// +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once() +func (c *Call) Once() *Call { + return c.Times(1) +} + +// Twice indicates that that the mock should only return the value twice. +// +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice() +func (c *Call) Twice() *Call { + return c.Times(2) +} + +// Times indicates that that the mock should only return the indicated number +// of times. +// +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5) +func (c *Call) Times(i int) *Call { + c.lock() + defer c.unlock() + c.Repeatability = i + return c +} + +// WaitUntil sets the channel that will block the mock's return until its closed +// or a message is received. +// +// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second)) +func (c *Call) WaitUntil(w <-chan time.Time) *Call { + c.lock() + defer c.unlock() + c.WaitFor = w + return c +} + +// After sets how long to block until the call returns +// +// Mock.On("MyMethod", arg1, arg2).After(time.Second) +func (c *Call) After(d time.Duration) *Call { + c.lock() + defer c.unlock() + c.waitTime = d + return c +} + +// Run sets a handler to be called before returning. It can be used when +// mocking a method (such as an unmarshaler) that takes a pointer to a struct and +// sets properties in such struct +// +// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(func(args Arguments) { +// arg := args.Get(0).(*map[string]interface{}) +// arg["foo"] = "bar" +// }) +func (c *Call) Run(fn func(args Arguments)) *Call { + c.lock() + defer c.unlock() + c.RunFn = fn + return c +} + +// Maybe allows the method call to be optional. Not calling an optional method +// will not cause an error while asserting expectations +func (c *Call) Maybe() *Call { + c.lock() + defer c.unlock() + c.optional = true + return c +} + +// On chains a new expectation description onto the mocked interface. This +// allows syntax like. +// +// Mock. +// On("MyMethod", 1).Return(nil). +// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error")) +//go:noinline +func (c *Call) On(methodName string, arguments ...interface{}) *Call { + return c.Parent.On(methodName, arguments...) +} + +// Mock is the workhorse used to track activity on another object. +// For an example of its usage, refer to the "Example Usage" section at the top +// of this document. +type Mock struct { + // Represents the calls that are expected of + // an object. + ExpectedCalls []*Call + + // Holds the calls that were made to this mocked object. + Calls []Call + + // test is An optional variable that holds the test struct, to be used when an + // invalid mock call was made. + test TestingT + + // TestData holds any data that might be useful for testing. Testify ignores + // this data completely allowing you to do whatever you like with it. + testData objx.Map + + mutex sync.Mutex +} + +// TestData holds any data that might be useful for testing. Testify ignores +// this data completely allowing you to do whatever you like with it. +func (m *Mock) TestData() objx.Map { + + if m.testData == nil { + m.testData = make(objx.Map) + } + + return m.testData +} + +/* + Setting expectations +*/ + +// Test sets the test struct variable of the mock object +func (m *Mock) Test(t TestingT) { + m.mutex.Lock() + defer m.mutex.Unlock() + m.test = t +} + +// fail fails the current test with the given formatted format and args. +// In case that a test was defined, it uses the test APIs for failing a test, +// otherwise it uses panic. +func (m *Mock) fail(format string, args ...interface{}) { + m.mutex.Lock() + defer m.mutex.Unlock() + + if m.test == nil { + panic(fmt.Sprintf(format, args...)) + } + m.test.Errorf(format, args...) + m.test.FailNow() +} + +// On starts a description of an expectation of the specified method +// being called. +// +// Mock.On("MyMethod", arg1, arg2) +func (m *Mock) On(methodName string, arguments ...interface{}) *Call { + for _, arg := range arguments { + if v := reflect.ValueOf(arg); v.Kind() == reflect.Func { + panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg)) + } + } + + m.mutex.Lock() + defer m.mutex.Unlock() + c := newCall(m, methodName, assert.CallerInfo(), arguments...) + m.ExpectedCalls = append(m.ExpectedCalls, c) + return c +} + +// /* +// Recording and responding to activity +// */ + +func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) { + var expectedCall *Call + + for i, call := range m.ExpectedCalls { + if call.Method == method { + _, diffCount := call.Arguments.Diff(arguments) + if diffCount == 0 { + expectedCall = call + if call.Repeatability > -1 { + return i, call + } + } + } + } + + return -1, expectedCall +} + +func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) { + var diffCount int + var closestCall *Call + var err string + + for _, call := range m.expectedCalls() { + if call.Method == method { + + errInfo, tempDiffCount := call.Arguments.Diff(arguments) + if tempDiffCount < diffCount || diffCount == 0 { + diffCount = tempDiffCount + closestCall = call + err = errInfo + } + + } + } + + return closestCall, err +} + +func callString(method string, arguments Arguments, includeArgumentValues bool) string { + + var argValsString string + if includeArgumentValues { + var argVals []string + for argIndex, arg := range arguments { + argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg)) + } + argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t")) + } + + return fmt.Sprintf("%s(%s)%s", method, arguments.String(), argValsString) +} + +// Called tells the mock object that a method has been called, and gets an array +// of arguments to return. Panics if the call is unexpected (i.e. not preceded by +// appropriate .On .Return() calls) +// If Call.WaitFor is set, blocks until the channel is closed or receives a message. +func (m *Mock) Called(arguments ...interface{}) Arguments { + // get the calling function's name + pc, _, _, ok := runtime.Caller(1) + if !ok { + panic("Couldn't get the caller information") + } + functionPath := runtime.FuncForPC(pc).Name() + //Next four lines are required to use GCCGO function naming conventions. + //For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock + //uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree + //With GCCGO we need to remove interface information starting from pN

. + re := regexp.MustCompile("\\.pN\\d+_") + if re.MatchString(functionPath) { + functionPath = re.Split(functionPath, -1)[0] + } + parts := strings.Split(functionPath, ".") + functionName := parts[len(parts)-1] + return m.MethodCalled(functionName, arguments...) +} + +// MethodCalled tells the mock object that the given method has been called, and gets +// an array of arguments to return. Panics if the call is unexpected (i.e. not preceded +// by appropriate .On .Return() calls) +// If Call.WaitFor is set, blocks until the channel is closed or receives a message. +func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments { + m.mutex.Lock() + //TODO: could combine expected and closes in single loop + found, call := m.findExpectedCall(methodName, arguments...) + + if found < 0 { + // expected call found but it has already been called with repeatable times + if call != nil { + m.mutex.Unlock() + m.fail("\nassert: mock: The method has been called over %d times.\n\tEither do one more Mock.On(\"%s\").Return(...), or remove extra call.\n\tThis call was unexpected:\n\t\t%s\n\tat: %s", call.totalCalls, methodName, callString(methodName, arguments, true), assert.CallerInfo()) + } + // we have to fail here - because we don't know what to do + // as the return arguments. This is because: + // + // a) this is a totally unexpected call to this method, + // b) the arguments are not what was expected, or + // c) the developer has forgotten to add an accompanying On...Return pair. + closestCall, mismatch := m.findClosestCall(methodName, arguments...) + m.mutex.Unlock() + + if closestCall != nil { + m.fail("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s", + callString(methodName, arguments, true), + callString(methodName, closestCall.Arguments, true), + diffArguments(closestCall.Arguments, arguments), + strings.TrimSpace(mismatch), + ) + } else { + m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo()) + } + } + + if call.Repeatability == 1 { + call.Repeatability = -1 + } else if call.Repeatability > 1 { + call.Repeatability-- + } + call.totalCalls++ + + // add the call + m.Calls = append(m.Calls, *newCall(m, methodName, assert.CallerInfo(), arguments...)) + m.mutex.Unlock() + + // block if specified + if call.WaitFor != nil { + <-call.WaitFor + } else { + time.Sleep(call.waitTime) + } + + m.mutex.Lock() + runFn := call.RunFn + m.mutex.Unlock() + + if runFn != nil { + runFn(arguments) + } + + m.mutex.Lock() + returnArgs := call.ReturnArguments + m.mutex.Unlock() + + return returnArgs +} + +/* + Assertions +*/ + +type assertExpectationser interface { + AssertExpectations(TestingT) bool +} + +// AssertExpectationsForObjects asserts that everything specified with On and Return +// of the specified objects was in fact called as expected. +// +// Calls may have occurred in any order. +func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + for _, obj := range testObjects { + if m, ok := obj.(Mock); ok { + t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)") + obj = &m + } + m := obj.(assertExpectationser) + if !m.AssertExpectations(t) { + t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m)) + return false + } + } + return true +} + +// AssertExpectations asserts that everything specified with On and Return was +// in fact called as expected. Calls may have occurred in any order. +func (m *Mock) AssertExpectations(t TestingT) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + m.mutex.Lock() + defer m.mutex.Unlock() + var somethingMissing bool + var failedExpectations int + + // iterate through each expectation + expectedCalls := m.expectedCalls() + for _, expectedCall := range expectedCalls { + if !expectedCall.optional && !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 { + somethingMissing = true + failedExpectations++ + t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo) + } else { + if expectedCall.Repeatability > 0 { + somethingMissing = true + failedExpectations++ + t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo) + } else { + t.Logf("PASS:\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String()) + } + } + } + + if somethingMissing { + t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo()) + } + + return !somethingMissing +} + +// AssertNumberOfCalls asserts that the method was called expectedCalls times. +func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + m.mutex.Lock() + defer m.mutex.Unlock() + var actualCalls int + for _, call := range m.calls() { + if call.Method == methodName { + actualCalls++ + } + } + return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls)) +} + +// AssertCalled asserts that the method was called. +// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method. +func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + m.mutex.Lock() + defer m.mutex.Unlock() + if !m.methodWasCalled(methodName, arguments) { + var calledWithArgs []string + for _, call := range m.calls() { + calledWithArgs = append(calledWithArgs, fmt.Sprintf("%v", call.Arguments)) + } + if len(calledWithArgs) == 0 { + return assert.Fail(t, "Should have called with given arguments", + fmt.Sprintf("Expected %q to have been called with:\n%v\nbut no actual calls happened", methodName, arguments)) + } + return assert.Fail(t, "Should have called with given arguments", + fmt.Sprintf("Expected %q to have been called with:\n%v\nbut actual calls were:\n %v", methodName, arguments, strings.Join(calledWithArgs, "\n"))) + } + return true +} + +// AssertNotCalled asserts that the method was not called. +// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method. +func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + m.mutex.Lock() + defer m.mutex.Unlock() + if m.methodWasCalled(methodName, arguments) { + return assert.Fail(t, "Should not have called with given arguments", + fmt.Sprintf("Expected %q to not have been called with:\n%v\nbut actually it was.", methodName, arguments)) + } + return true +} + +func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool { + for _, call := range m.calls() { + if call.Method == methodName { + + _, differences := Arguments(expected).Diff(call.Arguments) + + if differences == 0 { + // found the expected call + return true + } + + } + } + // we didn't find the expected call + return false +} + +func (m *Mock) expectedCalls() []*Call { + return append([]*Call{}, m.ExpectedCalls...) +} + +func (m *Mock) calls() []Call { + return append([]Call{}, m.Calls...) +} + +/* + Arguments +*/ + +// Arguments holds an array of method arguments or return values. +type Arguments []interface{} + +const ( + // Anything is used in Diff and Assert when the argument being tested + // shouldn't be taken into consideration. + Anything = "mock.Anything" +) + +// AnythingOfTypeArgument is a string that contains the type of an argument +// for use when type checking. Used in Diff and Assert. +type AnythingOfTypeArgument string + +// AnythingOfType returns an AnythingOfTypeArgument object containing the +// name of the type to check for. Used in Diff and Assert. +// +// For example: +// Assert(t, AnythingOfType("string"), AnythingOfType("int")) +func AnythingOfType(t string) AnythingOfTypeArgument { + return AnythingOfTypeArgument(t) +} + +// IsTypeArgument is a struct that contains the type of an argument +// for use when type checking. This is an alternative to AnythingOfType. +// Used in Diff and Assert. +type IsTypeArgument struct { + t interface{} +} + +// IsType returns an IsTypeArgument object containing the type to check for. +// You can provide a zero-value of the type to check. This is an +// alternative to AnythingOfType. Used in Diff and Assert. +// +// For example: +// Assert(t, IsType(""), IsType(0)) +func IsType(t interface{}) *IsTypeArgument { + return &IsTypeArgument{t: t} +} + +// argumentMatcher performs custom argument matching, returning whether or +// not the argument is matched by the expectation fixture function. +type argumentMatcher struct { + // fn is a function which accepts one argument, and returns a bool. + fn reflect.Value +} + +func (f argumentMatcher) Matches(argument interface{}) bool { + expectType := f.fn.Type().In(0) + expectTypeNilSupported := false + switch expectType.Kind() { + case reflect.Interface, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Ptr: + expectTypeNilSupported = true + } + + argType := reflect.TypeOf(argument) + var arg reflect.Value + if argType == nil { + arg = reflect.New(expectType).Elem() + } else { + arg = reflect.ValueOf(argument) + } + + if argType == nil && !expectTypeNilSupported { + panic(errors.New("attempting to call matcher with nil for non-nil expected type")) + } + if argType == nil || argType.AssignableTo(expectType) { + result := f.fn.Call([]reflect.Value{arg}) + return result[0].Bool() + } + return false +} + +func (f argumentMatcher) String() string { + return fmt.Sprintf("func(%s) bool", f.fn.Type().In(0).Name()) +} + +// MatchedBy can be used to match a mock call based on only certain properties +// from a complex struct or some calculation. It takes a function that will be +// evaluated with the called argument and will return true when there's a match +// and false otherwise. +// +// Example: +// m.On("Do", MatchedBy(func(req *http.Request) bool { return req.Host == "example.com" })) +// +// |fn|, must be a function accepting a single argument (of the expected type) +// which returns a bool. If |fn| doesn't match the required signature, +// MatchedBy() panics. +func MatchedBy(fn interface{}) argumentMatcher { + fnType := reflect.TypeOf(fn) + + if fnType.Kind() != reflect.Func { + panic(fmt.Sprintf("assert: arguments: %s is not a func", fn)) + } + if fnType.NumIn() != 1 { + panic(fmt.Sprintf("assert: arguments: %s does not take exactly one argument", fn)) + } + if fnType.NumOut() != 1 || fnType.Out(0).Kind() != reflect.Bool { + panic(fmt.Sprintf("assert: arguments: %s does not return a bool", fn)) + } + + return argumentMatcher{fn: reflect.ValueOf(fn)} +} + +// Get Returns the argument at the specified index. +func (args Arguments) Get(index int) interface{} { + if index+1 > len(args) { + panic(fmt.Sprintf("assert: arguments: Cannot call Get(%d) because there are %d argument(s).", index, len(args))) + } + return args[index] +} + +// Is gets whether the objects match the arguments specified. +func (args Arguments) Is(objects ...interface{}) bool { + for i, obj := range args { + if obj != objects[i] { + return false + } + } + return true +} + +// Diff gets a string describing the differences between the arguments +// and the specified objects. +// +// Returns the diff string and number of differences found. +func (args Arguments) Diff(objects []interface{}) (string, int) { + //TODO: could return string as error and nil for No difference + + var output = "\n" + var differences int + + var maxArgCount = len(args) + if len(objects) > maxArgCount { + maxArgCount = len(objects) + } + + for i := 0; i < maxArgCount; i++ { + var actual, expected interface{} + var actualFmt, expectedFmt string + + if len(objects) <= i { + actual = "(Missing)" + actualFmt = "(Missing)" + } else { + actual = objects[i] + actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual) + } + + if len(args) <= i { + expected = "(Missing)" + expectedFmt = "(Missing)" + } else { + expected = args[i] + expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected) + } + + if matcher, ok := expected.(argumentMatcher); ok { + if matcher.Matches(actual) { + output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher) + } else { + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher) + } + } else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() { + + // type checking + if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt) + } + + } else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) { + t := expected.(*IsTypeArgument).t + if reflect.TypeOf(t) != reflect.TypeOf(actual) { + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, reflect.TypeOf(t).Name(), reflect.TypeOf(actual).Name(), actualFmt) + } + } else { + + // normal checking + + if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { + // match + output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt) + } else { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt) + } + } + + } + + if differences == 0 { + return "No differences.", differences + } + + return output, differences + +} + +// Assert compares the arguments with the specified objects and fails if +// they do not exactly match. +func (args Arguments) Assert(t TestingT, objects ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + // get the differences + diff, diffCount := args.Diff(objects) + + if diffCount == 0 { + return true + } + + // there are differences... report them... + t.Logf(diff) + t.Errorf("%sArguments do not match.", assert.CallerInfo()) + + return false + +} + +// String gets the argument at the specified index. Panics if there is no argument, or +// if the argument is of the wrong type. +// +// If no index is provided, String() returns a complete string representation +// of the arguments. +func (args Arguments) String(indexOrNil ...int) string { + + if len(indexOrNil) == 0 { + // normal String() method - return a string representation of the args + var argsStr []string + for _, arg := range args { + argsStr = append(argsStr, fmt.Sprintf("%s", reflect.TypeOf(arg))) + } + return strings.Join(argsStr, ",") + } else if len(indexOrNil) == 1 { + // Index has been specified - get the argument at that index + var index = indexOrNil[0] + var s string + var ok bool + if s, ok = args.Get(index).(string); !ok { + panic(fmt.Sprintf("assert: arguments: String(%d) failed because object wasn't correct type: %s", index, args.Get(index))) + } + return s + } + + panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil))) + +} + +// Int gets the argument at the specified index. Panics if there is no argument, or +// if the argument is of the wrong type. +func (args Arguments) Int(index int) int { + var s int + var ok bool + if s, ok = args.Get(index).(int); !ok { + panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index))) + } + return s +} + +// Error gets the argument at the specified index. Panics if there is no argument, or +// if the argument is of the wrong type. +func (args Arguments) Error(index int) error { + obj := args.Get(index) + var s error + var ok bool + if obj == nil { + return nil + } + if s, ok = obj.(error); !ok { + panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index))) + } + return s +} + +// Bool gets the argument at the specified index. Panics if there is no argument, or +// if the argument is of the wrong type. +func (args Arguments) Bool(index int) bool { + var s bool + var ok bool + if s, ok = args.Get(index).(bool); !ok { + panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index))) + } + return s +} + +func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { + t := reflect.TypeOf(v) + k := t.Kind() + + if k == reflect.Ptr { + t = t.Elem() + k = t.Kind() + } + return t, k +} + +func diffArguments(expected Arguments, actual Arguments) string { + if len(expected) != len(actual) { + return fmt.Sprintf("Provided %v arguments, mocked for %v arguments", len(expected), len(actual)) + } + + for x := range expected { + if diffString := diff(expected[x], actual[x]); diffString != "" { + return fmt.Sprintf("Difference found in argument %v:\n\n%s", x, diffString) + } + } + + return "" +} + +// diff returns a diff of both values as long as both are of the same type and +// are a struct, map, slice or array. Otherwise it returns an empty string. +func diff(expected interface{}, actual interface{}) string { + if expected == nil || actual == nil { + return "" + } + + et, ek := typeAndKind(expected) + at, _ := typeAndKind(actual) + + if et != at { + return "" + } + + if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array { + return "" + } + + e := spewConfig.Sdump(expected) + a := spewConfig.Sdump(actual) + + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(e), + B: difflib.SplitLines(a), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + + return diff +} + +var spewConfig = spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, +} + +type tHelper interface { + Helper() +} diff --git a/vendor/github.com/subosito/gotenv/.env b/vendor/github.com/subosito/gotenv/.env new file mode 100644 index 000000000..6405eca71 --- /dev/null +++ b/vendor/github.com/subosito/gotenv/.env @@ -0,0 +1 @@ +HELLO=world diff --git a/vendor/github.com/subosito/gotenv/.env.invalid b/vendor/github.com/subosito/gotenv/.env.invalid new file mode 100644 index 000000000..016d5e0ce --- /dev/null +++ b/vendor/github.com/subosito/gotenv/.env.invalid @@ -0,0 +1 @@ +lol$wut diff --git a/vendor/github.com/subosito/gotenv/.gitignore b/vendor/github.com/subosito/gotenv/.gitignore new file mode 100644 index 000000000..2b8d45610 --- /dev/null +++ b/vendor/github.com/subosito/gotenv/.gitignore @@ -0,0 +1,3 @@ +*.test +*.out +annotate.json diff --git a/vendor/github.com/subosito/gotenv/.travis.yml b/vendor/github.com/subosito/gotenv/.travis.yml new file mode 100644 index 000000000..3370d5f40 --- /dev/null +++ b/vendor/github.com/subosito/gotenv/.travis.yml @@ -0,0 +1,10 @@ +language: go +go: + - 1.x +os: + - linux + - osx +script: + - go test -test.v -coverprofile=coverage.out -covermode=count +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/subosito/gotenv/CHANGELOG.md b/vendor/github.com/subosito/gotenv/CHANGELOG.md new file mode 100644 index 000000000..67f687382 --- /dev/null +++ b/vendor/github.com/subosito/gotenv/CHANGELOG.md @@ -0,0 +1,47 @@ +# Changelog + +## [1.2.0] - 2019-08-03 + +### Added + +- Add `Must` helper to raise an error as panic. It can be used with `Load` and `OverLoad`. +- Add more tests to be 100% coverage. +- Add CHANGELOG +- Add more OS for the test: OSX and Windows + +### Changed + +- Reduce complexity and improve source code for having `A+` score in [goreportcard](https://goreportcard.com/report/github.com/subosito/gotenv). +- Updated README with mentions to all available functions + +### Removed + +- Remove `ErrFormat` +- Remove `MustLoad` and `MustOverload`, replaced with `Must` helper. + +## [1.1.1] - 2018-06-05 + +### Changed + +- Replace `os.Getenv` with `os.LookupEnv` to ensure that the environment variable is not set, by [radding](https://github.com/radding) + +## [1.1.0] - 2017-03-20 + +### Added + +- Supports carriage return in env +- Handle files with UTF-8 BOM + +### Changed + +- Whitespace handling + +### Fixed + +- Incorrect variable expansion +- Handling escaped '$' characters + +## [1.0.0] - 2014-10-05 + +First stable release. + diff --git a/vendor/github.com/subosito/gotenv/LICENSE b/vendor/github.com/subosito/gotenv/LICENSE new file mode 100644 index 000000000..f64ccaedc --- /dev/null +++ b/vendor/github.com/subosito/gotenv/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Alif Rachmawadi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/subosito/gotenv/README.md b/vendor/github.com/subosito/gotenv/README.md new file mode 100644 index 000000000..d610cdf0b --- /dev/null +++ b/vendor/github.com/subosito/gotenv/README.md @@ -0,0 +1,131 @@ +# gotenv + +[![Build Status](https://travis-ci.org/subosito/gotenv.svg?branch=master)](https://travis-ci.org/subosito/gotenv) +[![Build status](https://ci.appveyor.com/api/projects/status/wb2e075xkfl0m0v2/branch/master?svg=true)](https://ci.appveyor.com/project/subosito/gotenv/branch/master) +[![Coverage Status](https://badgen.net/codecov/c/github/subosito/gotenv)](https://codecov.io/gh/subosito/gotenv) +[![Go Report Card](https://goreportcard.com/badge/github.com/subosito/gotenv)](https://goreportcard.com/report/github.com/subosito/gotenv) +[![GoDoc](https://godoc.org/github.com/subosito/gotenv?status.svg)](https://godoc.org/github.com/subosito/gotenv) + +Load environment variables dynamically in Go. + +## Usage + +Put the gotenv package on your `import` statement: + +```go +import "github.com/subosito/gotenv" +``` + +To modify your app environment variables, `gotenv` expose 2 main functions: + +- `gotenv.Load` +- `gotenv.Apply` + +By default, `gotenv.Load` will look for a file called `.env` in the current working directory. + +Behind the scene, it will then load `.env` file and export the valid variables to the environment variables. Make sure you call the method as soon as possible to ensure it loads all variables, say, put it on `init()` function. + +Once loaded you can use `os.Getenv()` to get the value of the variable. + +Let's say you have `.env` file: + +``` +APP_ID=1234567 +APP_SECRET=abcdef +``` + +Here's the example of your app: + +```go +package main + +import ( + "github.com/subosito/gotenv" + "log" + "os" +) + +func init() { + gotenv.Load() +} + +func main() { + log.Println(os.Getenv("APP_ID")) // "1234567" + log.Println(os.Getenv("APP_SECRET")) // "abcdef" +} +``` + +You can also load other than `.env` file if you wish. Just supply filenames when calling `Load()`. It will load them in order and the first value set for a variable will win.: + +```go +gotenv.Load(".env.production", "credentials") +``` + +While `gotenv.Load` loads entries from `.env` file, `gotenv.Apply` allows you to use any `io.Reader`: + +```go +gotenv.Apply(strings.NewReader("APP_ID=1234567")) + +log.Println(os.Getenv("APP_ID")) +// Output: "1234567" +``` + +Both `gotenv.Load` and `gotenv.Apply` **DO NOT** overrides existing environment variables. If you want to override existing ones, you can see section below. + +### Environment Overrides + +Besides above functions, `gotenv` also provides another functions that overrides existing: + +- `gotenv.OverLoad` +- `gotenv.OverApply` + + +Here's the example of this overrides behavior: + +```go +os.Setenv("HELLO", "world") + +// NOTE: using Apply existing value will be reserved +gotenv.Apply(strings.NewReader("HELLO=universe")) +fmt.Println(os.Getenv("HELLO")) +// Output: "world" + +// NOTE: using OverApply existing value will be overridden +gotenv.OverApply(strings.NewReader("HELLO=universe")) +fmt.Println(os.Getenv("HELLO")) +// Output: "universe" +``` + +### Throw a Panic + +Both `gotenv.Load` and `gotenv.OverLoad` returns an error on something wrong occurred, like your env file is not exist, and so on. To make it easier to use, `gotenv` also provides `gotenv.Must` helper, to let it panic when an error returned. + +```go +err := gotenv.Load(".env-is-not-exist") +fmt.Println("error", err) +// error: open .env-is-not-exist: no such file or directory + +gotenv.Must(gotenv.Load, ".env-is-not-exist") +// it will throw a panic +// panic: open .env-is-not-exist: no such file or directory +``` + +### Another Scenario + +Just in case you want to parse environment variables from any `io.Reader`, gotenv keeps its `Parse` and `StrictParse` function as public API so you can use that. + +```go +// import "strings" + +pairs := gotenv.Parse(strings.NewReader("FOO=test\nBAR=$FOO")) +// gotenv.Env{"FOO": "test", "BAR": "test"} + +err, pairs = gotenv.StrictParse(strings.NewReader(`FOO="bar"`)) +// gotenv.Env{"FOO": "bar"} +``` + +`Parse` ignores invalid lines and returns `Env` of valid environment variables, while `StrictParse` returns an error for invalid lines. + +## Notes + +The gotenv package is a Go port of [`dotenv`](https://github.com/bkeepers/dotenv) project with some additions made for Go. For general features, it aims to be compatible as close as possible. diff --git a/vendor/github.com/subosito/gotenv/appveyor.yml b/vendor/github.com/subosito/gotenv/appveyor.yml new file mode 100644 index 000000000..33b4c4046 --- /dev/null +++ b/vendor/github.com/subosito/gotenv/appveyor.yml @@ -0,0 +1,9 @@ +build: off +clone_folder: c:\gopath\src\github.com\subosito\gotenv +environment: + GOPATH: c:\gopath +stack: go 1.10 +before_test: + - go get -t +test_script: + - go test -v -cover -race diff --git a/vendor/github.com/subosito/gotenv/gotenv.go b/vendor/github.com/subosito/gotenv/gotenv.go new file mode 100644 index 000000000..745a34489 --- /dev/null +++ b/vendor/github.com/subosito/gotenv/gotenv.go @@ -0,0 +1,265 @@ +// Package gotenv provides functionality to dynamically load the environment variables +package gotenv + +import ( + "bufio" + "fmt" + "io" + "os" + "regexp" + "strings" +) + +const ( + // Pattern for detecting valid line format + linePattern = `\A\s*(?:export\s+)?([\w\.]+)(?:\s*=\s*|:\s+?)('(?:\'|[^'])*'|"(?:\"|[^"])*"|[^#\n]+)?\s*(?:\s*\#.*)?\z` + + // Pattern for detecting valid variable within a value + variablePattern = `(\\)?(\$)(\{?([A-Z0-9_]+)?\}?)` +) + +// Env holds key/value pair of valid environment variable +type Env map[string]string + +/* +Load is a function to load a file or multiple files and then export the valid variables into environment variables if they do not exist. +When it's called with no argument, it will load `.env` file on the current path and set the environment variables. +Otherwise, it will loop over the filenames parameter and set the proper environment variables. +*/ +func Load(filenames ...string) error { + return loadenv(false, filenames...) +} + +/* +OverLoad is a function to load a file or multiple files and then export and override the valid variables into environment variables. +*/ +func OverLoad(filenames ...string) error { + return loadenv(true, filenames...) +} + +/* +Must is wrapper function that will panic when supplied function returns an error. +*/ +func Must(fn func(filenames ...string) error, filenames ...string) { + if err := fn(filenames...); err != nil { + panic(err.Error()) + } +} + +/* +Apply is a function to load an io Reader then export the valid variables into environment variables if they do not exist. +*/ +func Apply(r io.Reader) error { + return parset(r, false) +} + +/* +OverApply is a function to load an io Reader then export and override the valid variables into environment variables. +*/ +func OverApply(r io.Reader) error { + return parset(r, true) +} + +func loadenv(override bool, filenames ...string) error { + if len(filenames) == 0 { + filenames = []string{".env"} + } + + for _, filename := range filenames { + f, err := os.Open(filename) + if err != nil { + return err + } + + err = parset(f, override) + if err != nil { + return err + } + + f.Close() + } + + return nil +} + +// parse and set :) +func parset(r io.Reader, override bool) error { + env, err := StrictParse(r) + if err != nil { + return err + } + + for key, val := range env { + setenv(key, val, override) + } + + return nil +} + +func setenv(key, val string, override bool) { + if override { + os.Setenv(key, val) + } else { + if _, present := os.LookupEnv(key); !present { + os.Setenv(key, val) + } + } +} + +// Parse is a function to parse line by line any io.Reader supplied and returns the valid Env key/value pair of valid variables. +// It expands the value of a variable from the environment variable but does not set the value to the environment itself. +// This function is skipping any invalid lines and only processing the valid one. +func Parse(r io.Reader) Env { + env, _ := StrictParse(r) + return env +} + +// StrictParse is a function to parse line by line any io.Reader supplied and returns the valid Env key/value pair of valid variables. +// It expands the value of a variable from the environment variable but does not set the value to the environment itself. +// This function is returning an error if there are any invalid lines. +func StrictParse(r io.Reader) (Env, error) { + env := make(Env) + scanner := bufio.NewScanner(r) + + i := 1 + bom := string([]byte{239, 187, 191}) + + for scanner.Scan() { + line := scanner.Text() + + if i == 1 { + line = strings.TrimPrefix(line, bom) + } + + i++ + + err := parseLine(line, env) + if err != nil { + return env, err + } + } + + return env, nil +} + +func parseLine(s string, env Env) error { + rl := regexp.MustCompile(linePattern) + rm := rl.FindStringSubmatch(s) + + if len(rm) == 0 { + return checkFormat(s, env) + } + + key := rm[1] + val := rm[2] + + // determine if string has quote prefix + hdq := strings.HasPrefix(val, `"`) + + // determine if string has single quote prefix + hsq := strings.HasPrefix(val, `'`) + + // trim whitespace + val = strings.Trim(val, " ") + + // remove quotes '' or "" + rq := regexp.MustCompile(`\A(['"])(.*)(['"])\z`) + val = rq.ReplaceAllString(val, "$2") + + if hdq { + val = strings.Replace(val, `\n`, "\n", -1) + val = strings.Replace(val, `\r`, "\r", -1) + + // Unescape all characters except $ so variables can be escaped properly + re := regexp.MustCompile(`\\([^$])`) + val = re.ReplaceAllString(val, "$1") + } + + rv := regexp.MustCompile(variablePattern) + fv := func(s string) string { + return varReplacement(s, hsq, env) + } + + val = rv.ReplaceAllStringFunc(val, fv) + val = parseVal(val, env) + + env[key] = val + return nil +} + +func parseExport(st string, env Env) error { + if strings.HasPrefix(st, "export") { + vs := strings.SplitN(st, " ", 2) + + if len(vs) > 1 { + if _, ok := env[vs[1]]; !ok { + return fmt.Errorf("line `%s` has an unset variable", st) + } + } + } + + return nil +} + +func varReplacement(s string, hsq bool, env Env) string { + if strings.HasPrefix(s, "\\") { + return strings.TrimPrefix(s, "\\") + } + + if hsq { + return s + } + + sn := `(\$)(\{?([A-Z0-9_]+)\}?)` + rn := regexp.MustCompile(sn) + mn := rn.FindStringSubmatch(s) + + if len(mn) == 0 { + return s + } + + v := mn[3] + + replace, ok := env[v] + if !ok { + replace = os.Getenv(v) + } + + return replace +} + +func checkFormat(s string, env Env) error { + st := strings.TrimSpace(s) + + if (st == "") || strings.HasPrefix(st, "#") { + return nil + } + + if err := parseExport(st, env); err != nil { + return err + } + + return fmt.Errorf("line `%s` doesn't match format", s) +} + +func parseVal(val string, env Env) string { + if strings.Contains(val, "=") { + if !(val == "\n" || val == "\r") { + kv := strings.Split(val, "\n") + + if len(kv) == 1 { + kv = strings.Split(val, "\r") + } + + if len(kv) > 1 { + val = kv[0] + + for i := 1; i < len(kv); i++ { + parseLine(kv[i], env) + } + } + } + } + + return val +} diff --git a/vendor/github.com/tdakkota/asciicheck/.gitignore b/vendor/github.com/tdakkota/asciicheck/.gitignore new file mode 100644 index 000000000..cf875a711 --- /dev/null +++ b/vendor/github.com/tdakkota/asciicheck/.gitignore @@ -0,0 +1,33 @@ +# IntelliJ project files +.idea +*.iml +out +gen + +# Go template +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ +.idea/$CACHE_FILE$ +.idea/$PRODUCT_WORKSPACE_FILE$ +.idea/.gitignore +.idea/codeStyles +.idea/deployment.xml +.idea/inspectionProfiles/ +.idea/kotlinc.xml +.idea/misc.xml +.idea/modules.xml +asciicheck.iml +go.sum diff --git a/vendor/github.com/tdakkota/asciicheck/LICENSE b/vendor/github.com/tdakkota/asciicheck/LICENSE new file mode 100644 index 000000000..48a60cf1c --- /dev/null +++ b/vendor/github.com/tdakkota/asciicheck/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 tdakkota + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/tdakkota/asciicheck/README.md b/vendor/github.com/tdakkota/asciicheck/README.md new file mode 100644 index 000000000..fc62811be --- /dev/null +++ b/vendor/github.com/tdakkota/asciicheck/README.md @@ -0,0 +1,44 @@ +# asciicheck [![Go Report Card](https://goreportcard.com/badge/github.com/tdakkota/asciicheck)](https://goreportcard.com/report/github.com/tdakkota/asciicheck) [![codecov](https://codecov.io/gh/tdakkota/asciicheck/branch/master/graph/badge.svg)](https://codecov.io/gh/tdakkota/asciicheck) ![Go](https://github.com/tdakkota/asciicheck/workflows/Go/badge.svg) +Simple linter to check that your code does not contain non-ASCII identifiers + +# Install + +``` +go get -u github.com/tdakkota/asciicheck/cmd/asciicheck +``` + +# Usage +asciicheck uses [`singlechecker`](https://pkg.go.dev/golang.org/x/tools/go/analysis/singlechecker) package to run: + +``` +asciicheck: checks that all code identifiers does not have non-ASCII symbols in the name + +Usage: asciicheck [-flag] [package] + + +Flags: + -V print version and exit + -all + no effect (deprecated) + -c int + display offending line with this many lines of context (default -1) + -cpuprofile string + write CPU profile to this file + -debug string + debug flags, any subset of "fpstv" + -fix + apply all suggested fixes + -flags + print analyzer flags in JSON + -json + emit JSON output + -memprofile string + write memory profile to this file + -source + no effect (deprecated) + -tags string + no effect (deprecated) + -trace string + write trace log to this file + -v no effect (deprecated) +``` diff --git a/vendor/github.com/tdakkota/asciicheck/ascii.go b/vendor/github.com/tdakkota/asciicheck/ascii.go new file mode 100644 index 000000000..9e70c391d --- /dev/null +++ b/vendor/github.com/tdakkota/asciicheck/ascii.go @@ -0,0 +1,18 @@ +package asciicheck + +import "unicode" + +func isASCII(s string) (rune, bool) { + if len(s) == 1 { + return []rune(s)[0], s[0] <= unicode.MaxASCII + } + + r := []rune(s) + for i := 0; i < len(s); i++ { + if r[i] > unicode.MaxASCII { + return r[i], false + } + } + + return 0, true +} diff --git a/vendor/github.com/tdakkota/asciicheck/asciicheck.go b/vendor/github.com/tdakkota/asciicheck/asciicheck.go new file mode 100644 index 000000000..690728022 --- /dev/null +++ b/vendor/github.com/tdakkota/asciicheck/asciicheck.go @@ -0,0 +1,49 @@ +package asciicheck + +import ( + "fmt" + "go/ast" + "golang.org/x/tools/go/analysis" +) + +func NewAnalyzer() *analysis.Analyzer { + return &analysis.Analyzer{ + Name: "asciicheck", + Doc: "checks that all code identifiers does not have non-ASCII symbols in the name", + Run: run, + } +} + +func run(pass *analysis.Pass) (interface{}, error) { + for _, file := range pass.Files { + alreadyViewed := map[*ast.Object]struct{}{} + ast.Inspect( + file, func(node ast.Node) bool { + cb(pass, node, alreadyViewed) + return true + }, + ) + } + + return nil, nil +} + +func cb(pass *analysis.Pass, n ast.Node, m map[*ast.Object]struct{}) { + if v, ok := n.(*ast.Ident); ok { + if _, ok := m[v.Obj]; ok { + return + } else { + m[v.Obj] = struct{}{} + } + + ch, ascii := isASCII(v.Name) + if !ascii { + pass.Report( + analysis.Diagnostic{ + Pos: v.Pos(), + Message: fmt.Sprintf("identifier \"%s\" contain non-ASCII character: %#U", v.Name, ch), + }, + ) + } + } +} diff --git a/vendor/github.com/tdakkota/asciicheck/go.mod b/vendor/github.com/tdakkota/asciicheck/go.mod new file mode 100644 index 000000000..43aa5d806 --- /dev/null +++ b/vendor/github.com/tdakkota/asciicheck/go.mod @@ -0,0 +1,5 @@ +module github.com/tdakkota/asciicheck + +go 1.13 + +require golang.org/x/tools v0.0.0-20200414032229-332987a829c3 diff --git a/vendor/github.com/tetafro/godot/.gitignore b/vendor/github.com/tetafro/godot/.gitignore new file mode 100644 index 000000000..2b87e3915 --- /dev/null +++ b/vendor/github.com/tetafro/godot/.gitignore @@ -0,0 +1,2 @@ +/dist/ +/godot diff --git a/vendor/github.com/tetafro/godot/.goreleaser.yml b/vendor/github.com/tetafro/godot/.goreleaser.yml new file mode 100644 index 000000000..87a05a2a7 --- /dev/null +++ b/vendor/github.com/tetafro/godot/.goreleaser.yml @@ -0,0 +1,12 @@ +builds: + - dir: ./cmd/godot +checksum: + name_template: checksums.txt +snapshot: + name_template: "{{ .Tag }}" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' diff --git a/vendor/github.com/tetafro/godot/LICENSE b/vendor/github.com/tetafro/godot/LICENSE new file mode 100644 index 000000000..120c6d502 --- /dev/null +++ b/vendor/github.com/tetafro/godot/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Denis Krivak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/tetafro/godot/Makefile b/vendor/github.com/tetafro/godot/Makefile new file mode 100644 index 000000000..fee7693ae --- /dev/null +++ b/vendor/github.com/tetafro/godot/Makefile @@ -0,0 +1,11 @@ +.PHONY: test +test: + go test ./... + +.PHONY: build +build: + go build -o godot ./cmd/godot + +.PHONY: release +release: + goreleaser release --rm-dist diff --git a/vendor/github.com/tetafro/godot/README.md b/vendor/github.com/tetafro/godot/README.md new file mode 100644 index 000000000..e2d2f6b0d --- /dev/null +++ b/vendor/github.com/tetafro/godot/README.md @@ -0,0 +1,54 @@ +# godot + +[![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/tetafro/godot/master/LICENSE) +[![Github CI](https://img.shields.io/github/workflow/status/tetafro/godot/Test)](https://github.com/tetafro/godot/actions?query=workflow%3ATest) +[![Go Report](https://goreportcard.com/badge/github.com/tetafro/godot)](https://goreportcard.com/report/github.com/tetafro/godot) +[![Codecov](https://codecov.io/gh/tetafro/godot/branch/master/graph/badge.svg)](https://codecov.io/gh/tetafro/godot) + +Linter that checks if all top-level comments contain a period at the +end of the last sentence if needed. + +[CodeReviewComments](https://github.com/golang/go/wiki/CodeReviewComments#comment-sentences) quote: + +> Comments should begin with the name of the thing being described +> and end in a period + +## Install and run + +*NOTE: Godot is available as a part of [GolangCI Lint](https://github.com/golangci/golangci-lint) +(disabled by default).* + +Build from source +```sh +go get -u github.com/tetafro/godot/cmd/godot +``` + +or download binary from [releases page](https://github.com/tetafro/godot/releases). + +Run +```sh +godot ./myproject +``` + +## Examples + +Code + +```go +package math + +// Sum sums two integers +func Sum(a, b int) int { + return a + b // result +} +``` + +Output + +```sh +Top level comment should end in a period: math/math.go:3:1 +``` + +See more examples in test files: +- [for default mode](testdata/example_default.go) +- [for using --all flag](testdata/example_checkall.go) diff --git a/vendor/github.com/tetafro/godot/go.mod b/vendor/github.com/tetafro/godot/go.mod new file mode 100644 index 000000000..d86531c42 --- /dev/null +++ b/vendor/github.com/tetafro/godot/go.mod @@ -0,0 +1,3 @@ +module github.com/tetafro/godot + +go 1.14 diff --git a/vendor/github.com/tetafro/godot/godot.go b/vendor/github.com/tetafro/godot/godot.go new file mode 100644 index 000000000..5eec83579 --- /dev/null +++ b/vendor/github.com/tetafro/godot/godot.go @@ -0,0 +1,151 @@ +// Package godot checks if all top-level comments contain a period at the +// end of the last sentence if needed. +package godot + +import ( + "go/ast" + "go/token" + "regexp" + "strings" +) + +const noPeriodMessage = "Top level comment should end in a period" + +// Message contains a message of linting error. +type Message struct { + Pos token.Position + Message string +} + +// Settings contains linter settings. +type Settings struct { + // Check all top-level comments, not only declarations + CheckAll bool +} + +var ( + // List of valid last characters. + lastChars = []string{".", "?", "!"} + + // Special tags in comments like "nolint" or "build". + tags = regexp.MustCompile("^[a-z]+:") + + // Special hashtags in comments like "#nosec". + hashtags = regexp.MustCompile("^#[a-z]+ ") + + // URL at the end of the line. + endURL = regexp.MustCompile(`[a-z]+://[^\s]+$`) +) + +// Run runs this linter on the provided code. +func Run(file *ast.File, fset *token.FileSet, settings Settings) []Message { + msgs := []Message{} + + // Check all top-level comments + if settings.CheckAll { + for _, group := range file.Comments { + if ok, msg := check(fset, group); !ok { + msgs = append(msgs, msg) + } + } + return msgs + } + + // Check only declaration comments + for _, decl := range file.Decls { + switch d := decl.(type) { + case *ast.GenDecl: + if ok, msg := check(fset, d.Doc); !ok { + msgs = append(msgs, msg) + } + case *ast.FuncDecl: + if ok, msg := check(fset, d.Doc); !ok { + msgs = append(msgs, msg) + } + } + } + return msgs +} + +func check(fset *token.FileSet, group *ast.CommentGroup) (ok bool, msg Message) { + if group == nil || len(group.List) == 0 { + return true, Message{} + } + + // Check only top-level comments + if fset.Position(group.Pos()).Column > 1 { + return true, Message{} + } + + // Get last element from comment group - it can be either + // last (or single) line for "//"-comment, or multiline string + // for "/*"-comment + last := group.List[len(group.List)-1] + + line, ok := checkComment(last.Text) + if ok { + return true, Message{} + } + pos := fset.Position(last.Slash) + pos.Line += line + return false, Message{ + Pos: pos, + Message: noPeriodMessage, + } +} + +func checkComment(comment string) (line int, ok bool) { + // Check last line of "//"-comment + if strings.HasPrefix(comment, "//") { + comment = strings.TrimPrefix(comment, "//") + return 0, checkLastChar(comment) + } + + // Skip cgo code blocks + // TODO: Find a better way to detect cgo code. + if strings.Contains(comment, "#include") || strings.Contains(comment, "#define") { + return 0, true + } + + // Check last non-empty line in multiline "/*"-comment block + lines := strings.Split(comment, "\n") + var i int + for i = len(lines) - 1; i >= 0; i-- { + if s := strings.TrimSpace(lines[i]); s == "*/" || s == "" { + continue + } + break + } + comment = strings.TrimPrefix(lines[i], "/*") + comment = strings.TrimSuffix(comment, "*/") + return i, checkLastChar(comment) +} + +func checkLastChar(s string) bool { + // Don't check comments starting with space indentation - they may + // contain code examples, which shouldn't end with period + if strings.HasPrefix(s, " ") || strings.HasPrefix(s, " \t") || strings.HasPrefix(s, "\t") { + return true + } + // Skip cgo export tags: https://golang.org/cmd/cgo/#hdr-C_references_to_Go + if strings.HasPrefix(s, "export") { + return true + } + s = strings.TrimSpace(s) + if tags.MatchString(s) || + hashtags.MatchString(s) || + endURL.MatchString(s) || + strings.HasPrefix(s, "+build") { + return true + } + // Don't check empty lines + if s == "" { + return true + } + for _, ch := range lastChars { + if string(s[len(s)-1]) == ch { + return true + } + } + return false +} diff --git a/vendor/github.com/timakin/bodyclose/LICENSE b/vendor/github.com/timakin/bodyclose/LICENSE new file mode 100644 index 000000000..6957f1889 --- /dev/null +++ b/vendor/github.com/timakin/bodyclose/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Seiji Takahashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go b/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go new file mode 100644 index 000000000..3c702ab5b --- /dev/null +++ b/vendor/github.com/timakin/bodyclose/passes/bodyclose/bodyclose.go @@ -0,0 +1,354 @@ +package bodyclose + +import ( + "fmt" + "go/ast" + "go/types" + "strconv" + "strings" + + "github.com/gostaticanalysis/analysisutil" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/buildssa" + "golang.org/x/tools/go/ssa" +) + +var Analyzer = &analysis.Analyzer{ + Name: "bodyclose", + Doc: Doc, + Run: new(runner).run, + Requires: []*analysis.Analyzer{ + buildssa.Analyzer, + }, +} + +const ( + Doc = "bodyclose checks whether HTTP response body is closed successfully" + + nethttpPath = "net/http" + closeMethod = "Close" +) + +type runner struct { + pass *analysis.Pass + resObj types.Object + resTyp *types.Pointer + bodyObj types.Object + closeMthd *types.Func + skipFile map[*ast.File]bool +} + +// run executes an analysis for the pass. The receiver is passed +// by value because this func is called in parallel for different passes. +func (r runner) run(pass *analysis.Pass) (interface{}, error) { + r.pass = pass + funcs := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA).SrcFuncs + + r.resObj = analysisutil.LookupFromImports(pass.Pkg.Imports(), nethttpPath, "Response") + if r.resObj == nil { + // skip checking + return nil, nil + } + + resNamed, ok := r.resObj.Type().(*types.Named) + if !ok { + return nil, fmt.Errorf("cannot find http.Response") + } + r.resTyp = types.NewPointer(resNamed) + + resStruct, ok := r.resObj.Type().Underlying().(*types.Struct) + if !ok { + return nil, fmt.Errorf("cannot find http.Response") + } + for i := 0; i < resStruct.NumFields(); i++ { + field := resStruct.Field(i) + if field.Id() == "Body" { + r.bodyObj = field + } + } + if r.bodyObj == nil { + return nil, fmt.Errorf("cannot find the object http.Response.Body") + } + bodyNamed := r.bodyObj.Type().(*types.Named) + bodyItrf := bodyNamed.Underlying().(*types.Interface) + for i := 0; i < bodyItrf.NumMethods(); i++ { + bmthd := bodyItrf.Method(i) + if bmthd.Id() == closeMethod { + r.closeMthd = bmthd + } + } + + r.skipFile = map[*ast.File]bool{} + for _, f := range funcs { + if r.noImportedNetHTTP(f) { + // skip this + continue + } + + // skip if the function is just referenced + var isreffunc bool + for i := 0; i < f.Signature.Results().Len(); i++ { + if f.Signature.Results().At(i).Type().String() == r.resTyp.String() { + isreffunc = true + } + } + if isreffunc { + continue + } + + for _, b := range f.Blocks { + for i := range b.Instrs { + pos := b.Instrs[i].Pos() + if r.isopen(b, i) { + pass.Reportf(pos, "response body must be closed") + } + } + } + } + + return nil, nil +} + +func (r *runner) isopen(b *ssa.BasicBlock, i int) bool { + call, ok := r.getReqCall(b.Instrs[i]) + if !ok { + return false + } + + if len(*call.Referrers()) == 0 { + return true + } + cRefs := *call.Referrers() + for _, cRef := range cRefs { + val, ok := r.getResVal(cRef) + if !ok { + continue + } + + if len(*val.Referrers()) == 0 { + return true + } + resRefs := *val.Referrers() + for _, resRef := range resRefs { + switch resRef := resRef.(type) { + case *ssa.Store: // Call in Closure function + if len(*resRef.Addr.Referrers()) == 0 { + return true + } + + for _, aref := range *resRef.Addr.Referrers() { + if c, ok := aref.(*ssa.MakeClosure); ok { + f := c.Fn.(*ssa.Function) + if r.noImportedNetHTTP(f) { + // skip this + return false + } + called := r.isClosureCalled(c) + + return r.calledInFunc(f, called) + } + + } + case *ssa.Call: // Indirect function call + if f, ok := resRef.Call.Value.(*ssa.Function); ok { + for _, b := range f.Blocks { + for i := range b.Instrs { + return r.isopen(b, i) + } + } + } + case *ssa.FieldAddr: // Normal reference to response entity + if resRef.Referrers() == nil { + return true + } + + bRefs := *resRef.Referrers() + + for _, bRef := range bRefs { + bOp, ok := r.getBodyOp(bRef) + if !ok { + continue + } + if len(*bOp.Referrers()) == 0 { + return true + } + ccalls := *bOp.Referrers() + for _, ccall := range ccalls { + if r.isCloseCall(ccall) { + return false + } + } + } + } + } + } + + return true +} + +func (r *runner) getReqCall(instr ssa.Instruction) (*ssa.Call, bool) { + call, ok := instr.(*ssa.Call) + if !ok { + return nil, false + } + if !strings.Contains(call.Type().String(), r.resTyp.String()) { + return nil, false + } + return call, true +} + +func (r *runner) getResVal(instr ssa.Instruction) (ssa.Value, bool) { + switch instr := instr.(type) { + case *ssa.FieldAddr: + if instr.X.Type().String() == r.resTyp.String() { + return instr.X.(ssa.Value), true + } + case ssa.Value: + if instr.Type().String() == r.resTyp.String() { + return instr, true + } + } + return nil, false +} + +func (r *runner) getBodyOp(instr ssa.Instruction) (*ssa.UnOp, bool) { + op, ok := instr.(*ssa.UnOp) + if !ok { + return nil, false + } + if op.Type() != r.bodyObj.Type() { + return nil, false + } + return op, true +} + +func (r *runner) isCloseCall(ccall ssa.Instruction) bool { + switch ccall := ccall.(type) { + case *ssa.Defer: + if ccall.Call.Method != nil && ccall.Call.Method.Name() == r.closeMthd.Name() { + return true + } + case *ssa.Call: + if ccall.Call.Method != nil && ccall.Call.Method.Name() == r.closeMthd.Name() { + return true + } + case *ssa.ChangeInterface: + if ccall.Type().String() == "io.Closer" { + closeMtd := ccall.Type().Underlying().(*types.Interface).Method(0) + crs := *ccall.Referrers() + for _, cs := range crs { + if cs, ok := cs.(*ssa.Defer); ok { + if val, ok := cs.Common().Value.(*ssa.Function); ok { + for _, b := range val.Blocks { + for _, instr := range b.Instrs { + if c, ok := instr.(*ssa.Call); ok { + if c.Call.Method == closeMtd { + return true + } + } + } + } + } + } + } + } + } + return false +} + +func (r *runner) isClosureCalled(c *ssa.MakeClosure) bool { + refs := *c.Referrers() + if len(refs) == 0 { + return false + } + for _, ref := range refs { + switch ref.(type) { + case *ssa.Call, *ssa.Defer: + return true + } + } + return false +} + +func (r *runner) noImportedNetHTTP(f *ssa.Function) (ret bool) { + obj := f.Object() + if obj == nil { + return false + } + + file := analysisutil.File(r.pass, obj.Pos()) + if file == nil { + return false + } + + if skip, has := r.skipFile[file]; has { + return skip + } + defer func() { + r.skipFile[file] = ret + }() + + for _, impt := range file.Imports { + path, err := strconv.Unquote(impt.Path.Value) + if err != nil { + continue + } + path = analysisutil.RemoveVendor(path) + if path == nethttpPath { + return false + } + } + + return true +} + +func (r *runner) calledInFunc(f *ssa.Function, called bool) bool { + for _, b := range f.Blocks { + for i, instr := range b.Instrs { + switch instr := instr.(type) { + case *ssa.UnOp: + refs := *instr.Referrers() + if len(refs) == 0 { + return true + } + for _, r := range refs { + if v, ok := r.(ssa.Value); ok { + if ptr, ok := v.Type().(*types.Pointer); !ok || !isNamedType(ptr.Elem(), "io", "ReadCloser") { + continue + } + vrefs := *v.Referrers() + for _, vref := range vrefs { + if vref, ok := vref.(*ssa.UnOp); ok { + vrefs := *vref.Referrers() + if len(vrefs) == 0 { + return true + } + for _, vref := range vrefs { + if c, ok := vref.(*ssa.Call); ok { + if c.Call.Method != nil && c.Call.Method.Name() == closeMethod { + return !called + } + } + } + } + } + } + + } + default: + return r.isopen(b, i) || !called + } + } + } + return false +} + +// isNamedType reports whether t is the named type path.name. +func isNamedType(t types.Type, path, name string) bool { + n, ok := t.(*types.Named) + if !ok { + return false + } + obj := n.Obj() + return obj.Name() == name && obj.Pkg() != nil && obj.Pkg().Path() == path +} diff --git a/vendor/github.com/tommy-muehle/go-mnd/.editorconfig b/vendor/github.com/tommy-muehle/go-mnd/.editorconfig new file mode 100644 index 000000000..316b8cae0 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/vendor/github.com/tommy-muehle/go-mnd/.gitignore b/vendor/github.com/tommy-muehle/go-mnd/.gitignore new file mode 100644 index 000000000..edd9d60a7 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/.gitignore @@ -0,0 +1,2 @@ +build/ +dist/ diff --git a/vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml b/vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml new file mode 100644 index 000000000..0986ff2f0 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml @@ -0,0 +1,30 @@ +builds: + - + main: ./cmd/mnd/main.go + binary: mnd + goos: + - windows + - darwin + - linux + goarch: + - amd64 + ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.buildTime={{.Date}}`. + +archives: + - + format: tar.gz + format_overrides: + - goos: windows + format: zip + +brews: + - + name: mnd + github: + owner: tommy-muehle + name: homebrew-tap + folder: Formula + homepage: https://github.com/tommy-muehle/go-mnd + description: Magic number detector for Go + test: | + system "#{bin}/mnd --version" diff --git a/vendor/github.com/tommy-muehle/go-mnd/.travis.yml b/vendor/github.com/tommy-muehle/go-mnd/.travis.yml new file mode 100644 index 000000000..fd76a2fc6 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/.travis.yml @@ -0,0 +1,12 @@ +language: go + +go: + - 1.13.x + - 1.12.x + - tip + +script: + - go test -v ./... + +notifications: + email: false diff --git a/vendor/github.com/tommy-muehle/go-mnd/LICENSE b/vendor/github.com/tommy-muehle/go-mnd/LICENSE new file mode 100644 index 000000000..8825fad20 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 Tommy Muehle + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/tommy-muehle/go-mnd/README.md b/vendor/github.com/tommy-muehle/go-mnd/README.md new file mode 100644 index 000000000..a85ed780c --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/README.md @@ -0,0 +1,111 @@ +# go-mnd - Magic number detector for Golang + +A vet analyzer to detect magic numbers. + +> **What is a magic number?** +> A magic number is a numeric literal that is not defined as a constant, but which may change, and therefore can be hard to update. It's considered a bad programming practice to use numbers directly in any source code without an explanation. It makes programs harder to read, understand, and maintain. + +## Project status + +[![Build Status](https://travis-ci.org/tommy-muehle/go-mnd.svg?branch=master)](https://travis-ci.org/tommy-muehle/go-mnd) +[![Go Report Card](https://goreportcard.com/badge/github.com/tommy-muehle/go-mnd)](https://goreportcard.com/report/github.com/tommy-muehle/go-mnd) + +## Install + +This analyzer requires Golang in version >= 1.12 because it's depends on the **go/analysis** API. + +``` +go get github.com/tommy-muehle/go-mnd/cmd/mnd +``` + +To install with [Homebrew](https://brew.sh/), run: + +``` +brew tap tommy-muehle/tap && brew install tommy-muehle/tap/mnd +``` + +On Windows download the [latest release](https://github.com/tommy-muehle/go-mnd/releases). + +## Usage + +[![asciicast](https://asciinema.org/a/231021.svg)](https://asciinema.org/a/231021) + +``` +go vet -vettool $(which mnd) ./... +``` + +or directly + +``` +mnd ./... +``` + +The ```-checks``` option let's you define a comma separated list of checks. + +The ```-ignored-numbers``` option let's you define a comma separated list of numbers to ignore. + +The ```-excludes``` option let's you define a comma separated list of regexp patterns to exclude. + +## Checks + +By default this detector analyses arguments, assigns, cases, conditions, operations and return statements. + +* argument + +``` +t := http.StatusText(200) +``` + +* assign + +``` +c := &http.Client{ + Timeout: 5 * time.Second, +} +``` + +* case + +``` +switch x { + case 3: +} +``` + +* condition + +``` +if x > 7 { +} +``` + +* operation + +``` +var x, y int +y = 10 * x +``` + +* return + +``` +return 3 +``` + +## Excludes + +By default the numbers 0 and 1 as well as test files are excluded! + +### Further known excludes + +The function "Date" in the "Time" package. + +``` +t := time.Date(2017, time.September, 26, 12, 13, 14, 0, time.UTC) +``` + +Additional custom excludes can be defined via option flag. + +## License + +The MIT License (MIT). Please see [LICENSE](LICENSE) for more information. diff --git a/vendor/github.com/tommy-muehle/go-mnd/analyzer.go b/vendor/github.com/tommy-muehle/go-mnd/analyzer.go new file mode 100644 index 000000000..9930170f2 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/analyzer.go @@ -0,0 +1,91 @@ +package magic_numbers + +import ( + "flag" + "go/ast" + + "github.com/tommy-muehle/go-mnd/checks" + "github.com/tommy-muehle/go-mnd/config" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +const Doc = `magic number detector` + +var Analyzer = &analysis.Analyzer{ + Name: "mnd", + Doc: Doc, + Run: run, + Flags: options(), + Requires: []*analysis.Analyzer{inspect.Analyzer}, + RunDespiteErrors: true, +} + +type Checker interface { + NodeFilter() []ast.Node + Check(n ast.Node) +} + +func options() flag.FlagSet { + options := flag.NewFlagSet("", flag.ExitOnError) + options.String("excludes", "", "comma separated list of patterns to exclude from analysis") + options.String("ignored-numbers", "", "comma separated list of numbers excluded from analysis") + options.String( + "checks", + checks.ArgumentCheck+","+ + checks.CaseCheck+","+ + checks.ConditionCheck+","+ + checks.OperationCheck+","+ + checks.ReturnCheck+","+ + checks.AssignCheck, + "comma separated list of checks", + ) + + return *options +} + +func run(pass *analysis.Pass) (interface{}, error) { + conf := config.WithOptions( + config.WithCustomChecks(pass.Analyzer.Flags.Lookup("checks").Value.String()), + config.WithExcludes(pass.Analyzer.Flags.Lookup("excludes").Value.String()), + config.WithIgnoredNumbers(pass.Analyzer.Flags.Lookup("ignored-numbers").Value.String()), + ) + + var checker []Checker + if conf.IsCheckEnabled(checks.ArgumentCheck) { + checker = append(checker, checks.NewArgumentAnalyzer(pass, conf)) + } + if conf.IsCheckEnabled(checks.CaseCheck) { + checker = append(checker, checks.NewCaseAnalyzer(pass, conf)) + } + if conf.IsCheckEnabled(checks.ConditionCheck) { + checker = append(checker, checks.NewConditionAnalyzer(pass, conf)) + } + if conf.IsCheckEnabled(checks.OperationCheck) { + checker = append(checker, checks.NewOperationAnalyzer(pass, conf)) + } + if conf.IsCheckEnabled(checks.ReturnCheck) { + checker = append(checker, checks.NewReturnAnalyzer(pass, conf)) + } + if conf.IsCheckEnabled(checks.AssignCheck) { + checker = append(checker, checks.NewAssignAnalyzer(pass, conf)) + } + + i := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + for _, c := range checker { + i.Preorder(c.NodeFilter(), func(node ast.Node) { + for _, exclude := range conf.Excludes { + if exclude.MatchString(pass.Fset.Position(node.Pos()).Filename) { + return + } + } + + c.Check(node) + }) + } + + return nil, nil +} diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/argument.go b/vendor/github.com/tommy-muehle/go-mnd/checks/argument.go new file mode 100644 index 000000000..34cc1d09f --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/checks/argument.go @@ -0,0 +1,107 @@ +package checks + +import ( + "go/ast" + "go/token" + + "golang.org/x/tools/go/analysis" + + config "github.com/tommy-muehle/go-mnd/config" +) + +const ArgumentCheck = "argument" + +// Known excludes for the argument check. +var argumentExcludes = map[string]string{ + // package: function + "time": "Date", // https://golang.org/pkg/time/#Date +} + +type ArgumentAnalyzer struct { + config *config.Config + pass *analysis.Pass +} + +func NewArgumentAnalyzer(pass *analysis.Pass, config *config.Config) *ArgumentAnalyzer { + return &ArgumentAnalyzer{ + pass: pass, + config: config, + } +} + +func (a *ArgumentAnalyzer) NodeFilter() []ast.Node { + return []ast.Node{ + (*ast.CallExpr)(nil), + } +} + +func (a *ArgumentAnalyzer) Check(n ast.Node) { + expr, ok := n.(*ast.CallExpr) + if !ok { + return + } + + // Don't check if package and function combination is excluded + if s, ok := expr.Fun.(*ast.SelectorExpr); ok && a.isExcluded(s) { + return + } + + for i, arg := range expr.Args { + switch x := arg.(type) { + case *ast.BasicLit: + if !a.isMagicNumber(x) { + continue + } + // If it's a magic number and has no previous element, report it + if i == 0 { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, ArgumentCheck) + } else { + // Otherwise check the previous element type + switch expr.Args[i-1].(type) { + case *ast.ChanType: + // When it's not a simple buffered channel, report it + if a.isMagicNumber(x) { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, ArgumentCheck) + } + } + } + case *ast.BinaryExpr: + a.checkBinaryExpr(x) + } + } +} + +func (a *ArgumentAnalyzer) isExcluded(expr *ast.SelectorExpr) bool { + var p string + + switch x := expr.X.(type) { + case *ast.Ident: + p = x.Name + } + + if v, ok := argumentExcludes[p]; ok && v == expr.Sel.Name { + return true + } + + return false +} + +func (a *ArgumentAnalyzer) checkBinaryExpr(expr *ast.BinaryExpr) { + switch x := expr.X.(type) { + case *ast.BasicLit: + if a.isMagicNumber(x) { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, ArgumentCheck) + } + } + + switch y := expr.Y.(type) { + case *ast.BasicLit: + if a.isMagicNumber(y) { + a.pass.Reportf(y.Pos(), reportMsg, y.Value, ArgumentCheck) + } + } +} + +func (a *ArgumentAnalyzer) isMagicNumber(l *ast.BasicLit) bool { + return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value) +} diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/assign.go b/vendor/github.com/tommy-muehle/go-mnd/checks/assign.go new file mode 100644 index 000000000..8699ce17f --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/checks/assign.go @@ -0,0 +1,66 @@ +package checks + +import ( + "go/ast" + "go/token" + + "golang.org/x/tools/go/analysis" + + config "github.com/tommy-muehle/go-mnd/config" +) + +const AssignCheck = "assign" + +type AssignAnalyzer struct { + pass *analysis.Pass + config *config.Config +} + +func NewAssignAnalyzer(pass *analysis.Pass, config *config.Config) *AssignAnalyzer { + return &AssignAnalyzer{ + pass: pass, + config: config, + } +} + +func (a *AssignAnalyzer) NodeFilter() []ast.Node { + return []ast.Node{ + (*ast.KeyValueExpr)(nil), + } +} + +func (a *AssignAnalyzer) Check(n ast.Node) { + expr, ok := n.(*ast.KeyValueExpr) + if !ok { + return + } + + switch x := expr.Value.(type) { + case *ast.BasicLit: + if a.isMagicNumber(x) { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, AssignCheck) + } + case *ast.BinaryExpr: + a.checkBinaryExpr(x) + } +} + +func (a *AssignAnalyzer) checkBinaryExpr(expr *ast.BinaryExpr) { + switch x := expr.X.(type) { + case *ast.BasicLit: + if a.isMagicNumber(x) { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, AssignCheck) + } + } + + switch y := expr.Y.(type) { + case *ast.BasicLit: + if a.isMagicNumber(y) { + a.pass.Reportf(y.Pos(), reportMsg, y.Value, AssignCheck) + } + } +} + +func (a *AssignAnalyzer) isMagicNumber(l *ast.BasicLit) bool { + return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value) +} diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/case.go b/vendor/github.com/tommy-muehle/go-mnd/checks/case.go new file mode 100644 index 000000000..d7993ede0 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/checks/case.go @@ -0,0 +1,68 @@ +package checks + +import ( + "go/ast" + "go/token" + + "golang.org/x/tools/go/analysis" + + config "github.com/tommy-muehle/go-mnd/config" +) + +const CaseCheck = "case" + +type CaseAnalyzer struct { + pass *analysis.Pass + config *config.Config +} + +func NewCaseAnalyzer(pass *analysis.Pass, config *config.Config) *CaseAnalyzer { + return &CaseAnalyzer{ + pass: pass, + config: config, + } +} + +func (a *CaseAnalyzer) NodeFilter() []ast.Node { + return []ast.Node{ + (*ast.CaseClause)(nil), + } +} + +func (a *CaseAnalyzer) Check(n ast.Node) { + caseClause, ok := n.(*ast.CaseClause) + if !ok { + return + } + + for _, c := range caseClause.List { + switch x := c.(type) { + case *ast.BasicLit: + if a.isMagicNumber(x) { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, CaseCheck) + } + case *ast.BinaryExpr: + a.checkBinaryExpr(x) + } + } +} + +func (a *CaseAnalyzer) checkBinaryExpr(expr *ast.BinaryExpr) { + switch x := expr.X.(type) { + case *ast.BasicLit: + if a.isMagicNumber(x) { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, CaseCheck) + } + } + + switch y := expr.Y.(type) { + case *ast.BasicLit: + if a.isMagicNumber(y) { + a.pass.Reportf(y.Pos(), reportMsg, y.Value, CaseCheck) + } + } +} + +func (a *CaseAnalyzer) isMagicNumber(l *ast.BasicLit) bool { + return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value) +} diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/checks.go b/vendor/github.com/tommy-muehle/go-mnd/checks/checks.go new file mode 100644 index 000000000..deff0c7bf --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/checks/checks.go @@ -0,0 +1,3 @@ +package checks + +const reportMsg = "Magic number: %v, in <%s> detected" diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/condition.go b/vendor/github.com/tommy-muehle/go-mnd/checks/condition.go new file mode 100644 index 000000000..b61bc0de9 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/checks/condition.go @@ -0,0 +1,55 @@ +package checks + +import ( + "go/ast" + "go/token" + + "golang.org/x/tools/go/analysis" + + config "github.com/tommy-muehle/go-mnd/config" +) + +const ConditionCheck = "condition" + +type ConditionAnalyzer struct { + pass *analysis.Pass + config *config.Config +} + +func NewConditionAnalyzer(pass *analysis.Pass, config *config.Config) *ConditionAnalyzer { + return &ConditionAnalyzer{ + pass: pass, + config: config, + } +} + +func (a *ConditionAnalyzer) NodeFilter() []ast.Node { + return []ast.Node{ + (*ast.IfStmt)(nil), + } +} + +func (a *ConditionAnalyzer) Check(n ast.Node) { + expr, ok := n.(*ast.IfStmt).Cond.(*ast.BinaryExpr) + if !ok { + return + } + + switch x := expr.X.(type) { + case *ast.BasicLit: + if a.isMagicNumber(x) { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, ConditionCheck) + } + } + + switch y := expr.Y.(type) { + case *ast.BasicLit: + if a.isMagicNumber(y) { + a.pass.Reportf(y.Pos(), reportMsg, y.Value, ConditionCheck) + } + } +} + +func (a *ConditionAnalyzer) isMagicNumber(l *ast.BasicLit) bool { + return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value) +} diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/operation.go b/vendor/github.com/tommy-muehle/go-mnd/checks/operation.go new file mode 100644 index 000000000..f1f8cf445 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/checks/operation.go @@ -0,0 +1,73 @@ +package checks + +import ( + "go/ast" + "go/token" + + "golang.org/x/tools/go/analysis" + + config "github.com/tommy-muehle/go-mnd/config" +) + +const OperationCheck = "operation" + +type OperationAnalyzer struct { + pass *analysis.Pass + config *config.Config +} + +func NewOperationAnalyzer(pass *analysis.Pass, config *config.Config) *OperationAnalyzer { + return &OperationAnalyzer{ + pass: pass, + config: config, + } +} + +func (a *OperationAnalyzer) NodeFilter() []ast.Node { + return []ast.Node{ + (*ast.AssignStmt)(nil), + } +} + +func (a *OperationAnalyzer) Check(n ast.Node) { + stmt, ok := n.(*ast.AssignStmt) + if !ok { + return + } + + for _, expr := range stmt.Rhs { + switch x := expr.(type) { + case *ast.BinaryExpr: + switch xExpr := x.X.(type) { + case *ast.BinaryExpr: + a.checkBinaryExpr(xExpr) + } + switch yExpr := x.Y.(type) { + case *ast.BinaryExpr: + a.checkBinaryExpr(yExpr) + } + + a.checkBinaryExpr(x) + } + } +} + +func (a *OperationAnalyzer) checkBinaryExpr(expr *ast.BinaryExpr) { + switch x := expr.X.(type) { + case *ast.BasicLit: + if a.isMagicNumber(x) { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, OperationCheck) + } + } + + switch y := expr.Y.(type) { + case *ast.BasicLit: + if a.isMagicNumber(y) { + a.pass.Reportf(y.Pos(), reportMsg, y.Value, OperationCheck) + } + } +} + +func (a *OperationAnalyzer) isMagicNumber(l *ast.BasicLit) bool { + return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value) +} diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/return.go b/vendor/github.com/tommy-muehle/go-mnd/checks/return.go new file mode 100644 index 000000000..be7f54697 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/checks/return.go @@ -0,0 +1,50 @@ +package checks + +import ( + "go/ast" + "go/token" + + "golang.org/x/tools/go/analysis" + + config "github.com/tommy-muehle/go-mnd/config" +) + +const ReturnCheck = "return" + +type ReturnAnalyzer struct { + pass *analysis.Pass + config *config.Config +} + +func NewReturnAnalyzer(pass *analysis.Pass, config *config.Config) *ReturnAnalyzer { + return &ReturnAnalyzer{ + pass: pass, + config: config, + } +} + +func (a *ReturnAnalyzer) NodeFilter() []ast.Node { + return []ast.Node{ + (*ast.ReturnStmt)(nil), + } +} + +func (a *ReturnAnalyzer) Check(n ast.Node) { + stmt, ok := n.(*ast.ReturnStmt) + if !ok { + return + } + + for _, expr := range stmt.Results { + switch x := expr.(type) { + case *ast.BasicLit: + if a.isMagicNumber(x) { + a.pass.Reportf(x.Pos(), reportMsg, x.Value, ReturnCheck) + } + } + } +} + +func (a *ReturnAnalyzer) isMagicNumber(l *ast.BasicLit) bool { + return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value) +} diff --git a/vendor/github.com/tommy-muehle/go-mnd/config/config.go b/vendor/github.com/tommy-muehle/go-mnd/config/config.go new file mode 100644 index 000000000..35c82eaf2 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/config/config.go @@ -0,0 +1,84 @@ +package config + +import ( + "regexp" + "strings" +) + +type Config struct { + Checks map[string]bool + IgnoredNumbers map[string]struct{} + Excludes []*regexp.Regexp +} + +type Option func(config *Config) + +func DefaultConfig() *Config { + return &Config{ + Checks: map[string]bool{}, + IgnoredNumbers: map[string]struct{}{ + "0": {}, + "1": {}, + }, + Excludes: []*regexp.Regexp{ + regexp.MustCompile(`_test.go`), + }, + } +} + +func WithOptions(options ...Option) *Config { + c := DefaultConfig() + for _, option := range options { + option(c) + } + return c +} + +func WithExcludes(excludes string) Option { + return func(config *Config) { + if excludes == "" { + return + } + + for _, exclude := range strings.Split(excludes, ",") { + config.Excludes = append(config.Excludes, regexp.MustCompile(exclude)) + } + } +} + +func WithIgnoredNumbers(numbers string) Option { + return func(config *Config) { + if numbers == "" { + return + } + + for _, number := range strings.Split(numbers, ",") { + config.IgnoredNumbers[number] = struct{}{} + } + } +} + +func WithCustomChecks(checks string) Option { + return func(config *Config) { + if checks == "" { + return + } + + for name, _ := range config.Checks { + config.Checks[name] = false + } + + for _, name := range strings.Split(checks, ",") { + config.Checks[name] = true + } + } +} + +func (c *Config) IsCheckEnabled(name string) bool { + return c.Checks[name] +} + +func (c *Config) IsIgnoredNumber(number string) bool { + _, ok := c.IgnoredNumbers[number] + return ok +} diff --git a/vendor/github.com/tommy-muehle/go-mnd/go.mod b/vendor/github.com/tommy-muehle/go-mnd/go.mod new file mode 100644 index 000000000..5119a7cc1 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/go.mod @@ -0,0 +1,11 @@ +module github.com/tommy-muehle/go-mnd + +go 1.12 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/stretchr/objx v0.1.1 // indirect + github.com/stretchr/testify v1.3.0 + golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect + golang.org/x/tools v0.0.0-20190221204921-83362c3779f5 +) diff --git a/vendor/github.com/tommy-muehle/go-mnd/go.sum b/vendor/github.com/tommy-muehle/go-mnd/go.sum new file mode 100644 index 000000000..bdc021ab2 --- /dev/null +++ b/vendor/github.com/tommy-muehle/go-mnd/go.sum @@ -0,0 +1,18 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190221204921-83362c3779f5 h1:ev5exjGDsOo0NPTB0qdCcE53BfWl1IICJlhgXgfT9fM= +golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/vendor/github.com/ultraware/funlen/LICENSE b/vendor/github.com/ultraware/funlen/LICENSE new file mode 100644 index 000000000..dca75556d --- /dev/null +++ b/vendor/github.com/ultraware/funlen/LICENSE @@ -0,0 +1,7 @@ +Copyright 2018 Ultraware Consultancy and Development B.V. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/ultraware/funlen/README.md b/vendor/github.com/ultraware/funlen/README.md new file mode 100644 index 000000000..ca7e9a0f7 --- /dev/null +++ b/vendor/github.com/ultraware/funlen/README.md @@ -0,0 +1,69 @@ +# Funlen linter + +Funlen is a linter that checks for long functions. It can checks both on the number of lines and the number of statements. + +The default limits are 50 lines and 35 statements. You can configure these with the `-l` and `-s` flags. + +Example code: + +```go +package main + +import "fmt" + +func fiveStatements() { + fmt.Println(1) + fmt.Println(2) + fmt.Println(3) + fmt.Println(4) + fmt.Println(5) +} + +func sevenLines() { + fmt.Println(1) + + fmt.Println(2) + + fmt.Println(3) + + fmt.Println(4) +} +``` + +Reults in: + +``` +$ funlen -l=6 -s=4 . +main.go:5:6:Function 'fiveStatements' has too many statements (5 > 4) +main.go:13:6:Function 'sevenLines' is too long (7 > 6) +``` + +## Installation guide + +```bash +go get git.ultraware.nl/NiseVoid/funlen +``` + +### Gometalinter + +You can add funlen to gometalinter and enable it. + +`.gometalinter.json`: + +```json +{ + "Linters": { + "funlen": "funlen -l=50 -s=35:PATH:LINE:COL:MESSAGE" + }, + + "Enable": [ + "funlen" + ] +} +``` + +commandline: + +```bash +gometalinter --linter "funlen:funlen -l=50 -s=35:PATH:LINE:COL:MESSAGE" --enable "funlen" +``` diff --git a/vendor/github.com/ultraware/funlen/main.go b/vendor/github.com/ultraware/funlen/main.go new file mode 100644 index 000000000..19e48e2ff --- /dev/null +++ b/vendor/github.com/ultraware/funlen/main.go @@ -0,0 +1,98 @@ +package funlen + +import ( + "fmt" + "go/ast" + "go/token" + "reflect" +) + +const defaultLineLimit = 60 +const defaultStmtLimit = 40 + +// Run runs this linter on the provided code +func Run(file *ast.File, fset *token.FileSet, lineLimit, stmtLimit int) []Message { + if lineLimit == 0 { + lineLimit = defaultLineLimit + } + if stmtLimit == 0 { + stmtLimit = defaultStmtLimit + } + + var msgs []Message + for _, f := range file.Decls { + decl, ok := f.(*ast.FuncDecl) + if !ok || decl.Body == nil { // decl.Body can be nil for e.g. cgo + continue + } + + if stmts := parseStmts(decl.Body.List); stmts > stmtLimit { + msgs = append(msgs, makeStmtMessage(fset, decl.Name, stmts, stmtLimit)) + continue + } + + if lines := getLines(fset, decl); lines > lineLimit { + msgs = append(msgs, makeLineMessage(fset, decl.Name, lines, lineLimit)) + } + } + + return msgs +} + +// Message contains a message +type Message struct { + Pos token.Position + Message string +} + +func makeLineMessage(fset *token.FileSet, funcInfo *ast.Ident, lines, lineLimit int) Message { + return Message{ + fset.Position(funcInfo.Pos()), + fmt.Sprintf("Function '%s' is too long (%d > %d)\n", funcInfo.Name, lines, lineLimit), + } +} + +func makeStmtMessage(fset *token.FileSet, funcInfo *ast.Ident, stmts, stmtLimit int) Message { + return Message{ + fset.Position(funcInfo.Pos()), + fmt.Sprintf("Function '%s' has too many statements (%d > %d)\n", funcInfo.Name, stmts, stmtLimit), + } +} + +func getLines(fset *token.FileSet, f *ast.FuncDecl) int { // nolint: interfacer + return fset.Position(f.End()).Line - fset.Position(f.Pos()).Line - 1 +} + +func parseStmts(s []ast.Stmt) (total int) { + for _, v := range s { + total++ + switch stmt := v.(type) { + case *ast.BlockStmt: + total += parseStmts(stmt.List) - 1 + case *ast.ForStmt, *ast.RangeStmt, *ast.IfStmt, + *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt: + total += parseBodyListStmts(stmt) + case *ast.CaseClause: + total += parseStmts(stmt.Body) + case *ast.AssignStmt: + total += checkInlineFunc(stmt.Rhs[0]) + case *ast.GoStmt: + total += checkInlineFunc(stmt.Call.Fun) + case *ast.DeferStmt: + total += checkInlineFunc(stmt.Call.Fun) + } + } + return +} + +func checkInlineFunc(stmt ast.Expr) int { + if block, ok := stmt.(*ast.FuncLit); ok { + return parseStmts(block.Body.List) + } + return 0 +} + +func parseBodyListStmts(t interface{}) int { + i := reflect.ValueOf(t).Elem().FieldByName(`Body`).Elem().FieldByName(`List`).Interface() + return parseStmts(i.([]ast.Stmt)) +} diff --git a/vendor/github.com/ultraware/whitespace/LICENSE b/vendor/github.com/ultraware/whitespace/LICENSE new file mode 100644 index 000000000..dca75556d --- /dev/null +++ b/vendor/github.com/ultraware/whitespace/LICENSE @@ -0,0 +1,7 @@ +Copyright 2018 Ultraware Consultancy and Development B.V. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/ultraware/whitespace/README.md b/vendor/github.com/ultraware/whitespace/README.md new file mode 100644 index 000000000..aed9a485f --- /dev/null +++ b/vendor/github.com/ultraware/whitespace/README.md @@ -0,0 +1,7 @@ +# Whitespace linter + +Whitespace is a linter that checks for unnecessary newlines at the start and end of functions, if, for, etc. + +## Installation guide + +Whitespace is included in [https://github.com/golangci/golangci-lint/](golangci-lint). Install it and enable whitespace. diff --git a/vendor/github.com/ultraware/whitespace/main.go b/vendor/github.com/ultraware/whitespace/main.go new file mode 100644 index 000000000..c36086c0e --- /dev/null +++ b/vendor/github.com/ultraware/whitespace/main.go @@ -0,0 +1,158 @@ +package whitespace + +import ( + "go/ast" + "go/token" +) + +// Message contains a message +type Message struct { + Pos token.Position + Type MessageType + Message string +} + +// MessageType describes what should happen to fix the warning +type MessageType uint8 + +// List of MessageTypes +const ( + MessageTypeLeading MessageType = iota + 1 + MessageTypeTrailing + MessageTypeAddAfter +) + +// Settings contains settings for edge-cases +type Settings struct { + MultiIf bool + MultiFunc bool +} + +// Run runs this linter on the provided code +func Run(file *ast.File, fset *token.FileSet, settings Settings) []Message { + var messages []Message + + for _, f := range file.Decls { + decl, ok := f.(*ast.FuncDecl) + if !ok || decl.Body == nil { // decl.Body can be nil for e.g. cgo + continue + } + + vis := visitor{file.Comments, fset, nil, make(map[*ast.BlockStmt]bool), settings} + ast.Walk(&vis, decl) + + messages = append(messages, vis.messages...) + } + + return messages +} + +type visitor struct { + comments []*ast.CommentGroup + fset *token.FileSet + messages []Message + wantNewline map[*ast.BlockStmt]bool + settings Settings +} + +func (v *visitor) Visit(node ast.Node) ast.Visitor { + if node == nil { + return v + } + + if stmt, ok := node.(*ast.IfStmt); ok && v.settings.MultiIf { + checkMultiLine(v, stmt.Body, stmt.Cond) + } + + if stmt, ok := node.(*ast.FuncDecl); ok && v.settings.MultiFunc { + checkMultiLine(v, stmt.Body, stmt.Type) + } + + if stmt, ok := node.(*ast.BlockStmt); ok { + wantNewline := v.wantNewline[stmt] + + comments := v.comments + if wantNewline { + comments = nil // Comments also count as a newline if we want a newline + } + first, last := firstAndLast(comments, v.fset, stmt.Pos(), stmt.End(), stmt.List) + + startMsg := checkStart(v.fset, stmt.Lbrace, first) + + if wantNewline && startMsg == nil { + v.messages = append(v.messages, Message{v.fset.Position(stmt.Pos()), MessageTypeAddAfter, `multi-line statement should be followed by a newline`}) + } else if !wantNewline && startMsg != nil { + v.messages = append(v.messages, *startMsg) + } + + if msg := checkEnd(v.fset, stmt.Rbrace, last); msg != nil { + v.messages = append(v.messages, *msg) + } + } + + return v +} + +func checkMultiLine(v *visitor, body *ast.BlockStmt, stmtStart ast.Node) { + start, end := posLine(v.fset, stmtStart.Pos()), posLine(v.fset, stmtStart.End()) + + if end > start { // Check only multi line conditions + v.wantNewline[body] = true + } +} + +func posLine(fset *token.FileSet, pos token.Pos) int { + return fset.Position(pos).Line +} + +func firstAndLast(comments []*ast.CommentGroup, fset *token.FileSet, start, end token.Pos, stmts []ast.Stmt) (ast.Node, ast.Node) { + if len(stmts) == 0 { + return nil, nil + } + + first, last := ast.Node(stmts[0]), ast.Node(stmts[len(stmts)-1]) + + for _, c := range comments { + if posLine(fset, c.Pos()) == posLine(fset, start) || posLine(fset, c.End()) == posLine(fset, end) { + continue + } + + if c.Pos() < start || c.End() > end { + continue + } + if c.Pos() < first.Pos() { + first = c + } + if c.End() > last.End() { + last = c + } + } + + return first, last +} + +func checkStart(fset *token.FileSet, start token.Pos, first ast.Node) *Message { + if first == nil { + return nil + } + + if posLine(fset, start)+1 < posLine(fset, first.Pos()) { + pos := fset.Position(start) + return &Message{pos, MessageTypeLeading, `unnecessary leading newline`} + } + + return nil +} + +func checkEnd(fset *token.FileSet, end token.Pos, last ast.Node) *Message { + if last == nil { + return nil + } + + if posLine(fset, end)-1 > posLine(fset, last.End()) { + pos := fset.Position(end) + return &Message{pos, MessageTypeTrailing, `unnecessary trailing newline`} + } + + return nil +} diff --git a/vendor/github.com/uudashr/gocognit/LICENSE b/vendor/github.com/uudashr/gocognit/LICENSE new file mode 100644 index 000000000..75d4b9c98 --- /dev/null +++ b/vendor/github.com/uudashr/gocognit/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Nuruddin Ashr + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/uudashr/gocognit/README.md b/vendor/github.com/uudashr/gocognit/README.md new file mode 100644 index 000000000..4a8846907 --- /dev/null +++ b/vendor/github.com/uudashr/gocognit/README.md @@ -0,0 +1,185 @@ +[![GoDoc](https://godoc.org/github.com/uudashr/gocognit?status.svg)](https://godoc.org/github.com/uudashr/gocognit) +# Gocognit +Gocognit calculates cognitive complexities of functions in Go source code. A measurement of how hard does the code is intuitively to understand. + +## Understanding the complexity + +Given code using `if` statement, +```go +func GetWords(number int) string { + if number == 1 { // +1 + return "one" + } else if number == 2 { // +1 + return "a couple" + } else if number == 3 { // +1 + return "a few" + } else { // +1 + return "lots" + } +} // Cognitive complexity = 4 +``` + +Above code can be refactored using `switch` statement, +```go +func GetWords(number int) string { + switch number { // +1 + case 1: + return "one" + case 2: + return "a couple" + case 3: + return "a few" + default: + return "lots" + } +} // Cognitive complexity = 1 +``` + +As you see above codes are the same, but the second code are easier to understand, that is why the cognitive complexity score are lower compare to the first one. + +## Comparison with cyclometic complexity + +### Example 1 +#### Cyclometic complexity +```go +func GetWords(number int) string { // +1 + switch number { + case 1: // +1 + return "one" + case 2: // +1 + return "a couple" + case 3: // +1 + return "a few" + default: + return "lots" + } +} // Cyclomatic complexity = 4 +``` + +#### Cognitive complexity +```go +func GetWords(number int) string { + switch number { // +1 + case 1: + return "one" + case 2: + return "a couple" + case 3: + return "a few" + default: + return "lots" + } +} // Cognitive complexity = 1 +``` + +Cognitive complexity give lower score compare to cyclomatic complexity. + +### Example 2 +#### Cyclomatic complexity +```go +func SumOfPrimes(max int) int { // +1 + var total int + +OUT: + for i := 1; i < max; i++ { // +1 + for j := 2; j < i; j++ { // +1 + if i%j == 0 { // +1 + continue OUT + } + } + total += i + } + + return total +} // Cyclomatic complexity = 4 +``` + +#### Cognitive complexity +```go +func SumOfPrimes(max int) int { + var total int + +OUT: + for i := 1; i < max; i++ { // +1 + for j := 2; j < i; j++ { // +2 (nesting = 1) + if i%j == 0 { // +3 (nesting = 2) + continue OUT // +1 + } + } + total += i + } + + return total +} // Cognitive complexity = 7 +``` + +Cognitive complexity give higher score compare to cyclomatic complexity. + +## Rules + +The cognitive complexity of a function is calculated according to the +following rules: +> Note: these rules are specific for Go, please see the [original whitepaper](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) for more complete reference. + +### Increments +There is an increment for each of the following: +1. `if`, `else if`, `else` +2. `switch`, `select` +3. `for` +4. `goto` LABEL, `break` LABEL, `continue` LABEL +5. sequence of binary logical operators +6. each method in a recursion cycle + +### Nesting level +The following structures increment the nesting level: +1. `if`, `else if`, `else` +2. `switch`, `select` +3. `for` +4. function literal or lambda + +### Nesting increments +The following structures receive a nesting increment commensurate with their nested depth inside nesting structures: +1. `if` +2. `switch`, `select` +3. `for` + +## Installation +``` +$ go get github.com/uudashr/gocognit/cmd/gocognit +``` + +## Usage + +``` +$ gocognit +Calculate cognitive complexities of Go functions. +Usage: + gocognit [flags] ... +Flags: + -over N show functions with complexity > N only and + return exit code 1 if the set is non-empty + -top N show the top N most complex functions only + -avg show the average complexity over all functions, + not depending on whether -over or -top are set +The output fields for each line are: + +``` + +Examples: + +``` +$ gocognit . +$ gocognit main.go +$ gocognit -top 10 src/ +$ gocognit -over 25 docker +$ gocognit -avg . +``` + +The output fields for each line are: +``` + +``` + +## Related project +- [Gocyclo](https://github.com/fzipp/gocyclo) where the code are based on. +- [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) white paper by G. Ann Campbell. \ No newline at end of file diff --git a/vendor/github.com/uudashr/gocognit/go.mod b/vendor/github.com/uudashr/gocognit/go.mod new file mode 100644 index 000000000..1a68d3880 --- /dev/null +++ b/vendor/github.com/uudashr/gocognit/go.mod @@ -0,0 +1,3 @@ +module github.com/uudashr/gocognit + +go 1.13 diff --git a/vendor/github.com/uudashr/gocognit/go.sum b/vendor/github.com/uudashr/gocognit/go.sum new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/github.com/uudashr/gocognit/gocognit.go b/vendor/github.com/uudashr/gocognit/gocognit.go new file mode 100644 index 000000000..11d5ee527 --- /dev/null +++ b/vendor/github.com/uudashr/gocognit/gocognit.go @@ -0,0 +1,313 @@ +package gocognit + +import ( + "fmt" + "go/ast" + "go/token" +) + +// Stat is statistic of the complexity. +type Stat struct { + PkgName string + FuncName string + Complexity int + Pos token.Position +} + +func (s Stat) String() string { + return fmt.Sprintf("%d %s %s %s", s.Complexity, s.PkgName, s.FuncName, s.Pos) +} + +// ComplexityStats builds the complexity statistics. +func ComplexityStats(f *ast.File, fset *token.FileSet, stats []Stat) []Stat { + for _, decl := range f.Decls { + if fn, ok := decl.(*ast.FuncDecl); ok { + stats = append(stats, Stat{ + PkgName: f.Name.Name, + FuncName: funcName(fn), + Complexity: Complexity(fn), + Pos: fset.Position(fn.Pos()), + }) + } + } + return stats +} + +// funcName returns the name representation of a function or method: +// "(Type).Name" for methods or simply "Name" for functions. +func funcName(fn *ast.FuncDecl) string { + if fn.Recv != nil { + if fn.Recv.NumFields() > 0 { + typ := fn.Recv.List[0].Type + return fmt.Sprintf("(%s).%s", recvString(typ), fn.Name) + } + } + return fn.Name.Name +} + +// recvString returns a string representation of recv of the +// form "T", "*T", or "BADRECV" (if not a proper receiver type). +func recvString(recv ast.Expr) string { + switch t := recv.(type) { + case *ast.Ident: + return t.Name + case *ast.StarExpr: + return "*" + recvString(t.X) + } + return "BADRECV" +} + +// Complexity calculates the cognitive complexity of a function. +func Complexity(fn *ast.FuncDecl) int { + v := complexityVisitor{ + name: fn.Name, + } + ast.Walk(&v, fn) + return v.complexity +} + +type complexityVisitor struct { + name *ast.Ident + complexity int + nesting int + elseNodes map[ast.Node]bool + calculatedExprs map[ast.Expr]bool +} + +func (v *complexityVisitor) incNesting() { + v.nesting++ +} + +func (v *complexityVisitor) decNesting() { + v.nesting-- +} + +func (v *complexityVisitor) incComplexity() { + v.complexity++ +} + +func (v *complexityVisitor) nestIncComplexity() { + v.complexity += (v.nesting + 1) +} + +func (v *complexityVisitor) markAsElseNode(n ast.Node) { + if v.elseNodes == nil { + v.elseNodes = make(map[ast.Node]bool) + } + + v.elseNodes[n] = true +} + +func (v *complexityVisitor) markedAsElseNode(n ast.Node) bool { + if v.elseNodes == nil { + return false + } + + return v.elseNodes[n] +} + +func (v *complexityVisitor) markCalculated(e ast.Expr) { + if v.calculatedExprs == nil { + v.calculatedExprs = make(map[ast.Expr]bool) + } + + v.calculatedExprs[e] = true +} + +func (v *complexityVisitor) isCalculated(e ast.Expr) bool { + if v.calculatedExprs == nil { + return false + } + + return v.calculatedExprs[e] +} + +// Visit implements the ast.Visitor interface. +func (v *complexityVisitor) Visit(n ast.Node) ast.Visitor { + switch n := n.(type) { + case *ast.IfStmt: + return v.visitIfStmt(n) + case *ast.SwitchStmt: + return v.visitSwitchStmt(n) + case *ast.SelectStmt: + return v.visitSelectStmt(n) + case *ast.ForStmt: + return v.visitForStmt(n) + case *ast.RangeStmt: + return v.visitRangeStmt(n) + case *ast.FuncLit: + return v.visitFuncLit(n) + case *ast.BranchStmt: + return v.visitBranchStmt(n) + case *ast.BinaryExpr: + return v.visitBinaryExpr(n) + case *ast.CallExpr: + return v.visitCallExpr(n) + } + return v +} + +func (v *complexityVisitor) visitIfStmt(n *ast.IfStmt) ast.Visitor { + v.incIfComplexity(n) + + if n.Init != nil { + ast.Walk(v, n.Init) + } + + ast.Walk(v, n.Cond) + + v.incNesting() + ast.Walk(v, n.Body) + v.decNesting() + + if _, ok := n.Else.(*ast.BlockStmt); ok { + v.incComplexity() + + v.incNesting() + ast.Walk(v, n.Else) + v.decNesting() + } else if _, ok := n.Else.(*ast.IfStmt); ok { + v.markAsElseNode(n.Else) + ast.Walk(v, n.Else) + } + return nil +} + +func (v *complexityVisitor) visitSwitchStmt(n *ast.SwitchStmt) ast.Visitor { + v.nestIncComplexity() + + if n.Init != nil { + ast.Walk(v, n.Init) + } + + if n.Tag != nil { + ast.Walk(v, n.Tag) + } + + v.incNesting() + ast.Walk(v, n.Body) + v.decNesting() + return nil +} + +func (v *complexityVisitor) visitSelectStmt(n *ast.SelectStmt) ast.Visitor { + v.nestIncComplexity() + + v.incNesting() + ast.Walk(v, n.Body) + v.decNesting() + return nil +} + +func (v *complexityVisitor) visitForStmt(n *ast.ForStmt) ast.Visitor { + v.nestIncComplexity() + + if n.Init != nil { + ast.Walk(v, n.Init) + } + + if n.Cond != nil { + ast.Walk(v, n.Cond) + } + + if n.Post != nil { + ast.Walk(v, n.Post) + } + + v.incNesting() + ast.Walk(v, n.Body) + v.decNesting() + return nil +} + +func (v *complexityVisitor) visitRangeStmt(n *ast.RangeStmt) ast.Visitor { + v.nestIncComplexity() + + if n.Key != nil { + ast.Walk(v, n.Key) + } + + if n.Value != nil { + ast.Walk(v, n.Value) + } + + ast.Walk(v, n.X) + + v.incNesting() + ast.Walk(v, n.Body) + v.decNesting() + return nil +} + +func (v *complexityVisitor) visitFuncLit(n *ast.FuncLit) ast.Visitor { + ast.Walk(v, n.Type) + + v.incNesting() + ast.Walk(v, n.Body) + v.decNesting() + return nil +} + +func (v *complexityVisitor) visitBranchStmt(n *ast.BranchStmt) ast.Visitor { + if n.Label != nil { + v.incComplexity() + } + return v +} + +func (v *complexityVisitor) visitBinaryExpr(n *ast.BinaryExpr) ast.Visitor { + if (n.Op == token.LAND || n.Op == token.LOR) && !v.isCalculated(n) { + ops := v.collectBinaryOps(n) + + var lastOp token.Token + for _, op := range ops { + if lastOp != op { + v.incComplexity() + lastOp = op + } + } + } + return v +} + +func (v *complexityVisitor) visitCallExpr(n *ast.CallExpr) ast.Visitor { + if name, ok := n.Fun.(*ast.Ident); ok { + if name.Obj == v.name.Obj && name.Name == v.name.Name { + v.incComplexity() + } + } + return v +} + +func (v *complexityVisitor) collectBinaryOps(exp ast.Expr) []token.Token { + v.markCalculated(exp) + switch exp := exp.(type) { + case *ast.BinaryExpr: + return mergeBinaryOps(v.collectBinaryOps(exp.X), exp.Op, v.collectBinaryOps(exp.Y)) + case *ast.ParenExpr: + // interest only on what inside paranthese + return v.collectBinaryOps(exp.X) + default: + return []token.Token{} + } +} + +func (v *complexityVisitor) incIfComplexity(n *ast.IfStmt) { + if v.markedAsElseNode(n) { + v.incComplexity() + } else { + v.nestIncComplexity() + } +} + +func mergeBinaryOps(x []token.Token, op token.Token, y []token.Token) []token.Token { + var out []token.Token + if len(x) != 0 { + out = append(out, x...) + } + out = append(out, op) + if len(y) != 0 { + out = append(out, y...) + } + return out +} -- cgit mrf-deployment