From 762906a735536e8e21c7846681c4c78f4ec9476e Mon Sep 17 00:00:00 2001 From: Matthias Luedtke Date: Mon, 23 Nov 2015 19:25:45 +0100 Subject: [PATCH] besticon v2.0: now with fallback icon rendering This is a major new release, with new features and a new URI structure. (Old URIs will be redirected) There is one known regression: missing caching for now --- Godeps/Godeps.json | 34 +- .../github.com/golang/freetype/raster/geom.go | 245 ++ .../golang/freetype/raster/paint.go | 287 ++ .../golang/freetype/raster/raster.go | 601 ++++ .../golang/freetype/raster/stroke.go | 483 +++ .../golang/freetype/truetype/face.go | 495 +++ .../golang/freetype/truetype/face_test.go | 48 + .../golang/freetype/truetype/glyph.go | 517 ++++ .../golang/freetype/truetype/hint.go | 1763 +++++++++++ .../golang/freetype/truetype/hint_test.go | 675 ++++ .../golang/freetype/truetype/opcodes.go | 289 ++ .../golang/freetype/truetype/truetype.go | 639 ++++ .../golang/freetype/truetype/truetype_test.go | 400 +++ .../github.com/golang/groupcache/.gitignore | 1 - .../src/github.com/golang/groupcache/LICENSE | 191 -- .../github.com/golang/groupcache/README.md | 73 - .../github.com/golang/groupcache/byteview.go | 160 - .../golang/groupcache/byteview_test.go | 142 - .../consistenthash/consistenthash.go | 81 - .../consistenthash/consistenthash_test.go | 110 - .../golang/groupcache/groupcache.go | 455 --- .../golang/groupcache/groupcache_test.go | 367 --- .../groupcache/groupcachepb/groupcache.pb.go | 65 - .../groupcache/groupcachepb/groupcache.proto | 32 - .../src/github.com/golang/groupcache/http.go | 229 -- .../github.com/golang/groupcache/http_test.go | 166 - .../github.com/golang/groupcache/lru/lru.go | 121 - .../golang/groupcache/lru/lru_test.go | 73 - .../src/github.com/golang/groupcache/peers.go | 71 - .../groupcache/singleflight/singleflight.go | 64 - .../singleflight/singleflight_test.go | 85 - .../src/github.com/golang/groupcache/sinks.go | 322 -- .../golang/groupcache/testpb/test.pb.go | 235 -- .../golang/groupcache/testpb/test.proto | 61 - .../github.com/golang/protobuf/proto/Makefile | 43 - .../golang/protobuf/proto/all_test.go | 2104 ------------- .../github.com/golang/protobuf/proto/clone.go | 212 -- .../golang/protobuf/proto/clone_test.go | 245 -- .../golang/protobuf/proto/decode.go | 827 ----- .../golang/protobuf/proto/encode.go | 1293 -------- .../github.com/golang/protobuf/proto/equal.go | 256 -- .../golang/protobuf/proto/equal_test.go | 191 -- .../golang/protobuf/proto/extensions.go | 400 --- .../golang/protobuf/proto/extensions_test.go | 292 -- .../github.com/golang/protobuf/proto/lib.go | 841 ----- .../golang/protobuf/proto/message_set.go | 287 -- .../golang/protobuf/proto/message_set_test.go | 66 - .../golang/protobuf/proto/pointer_reflect.go | 479 --- .../golang/protobuf/proto/pointer_unsafe.go | 266 -- .../golang/protobuf/proto/properties.go | 742 ----- .../protobuf/proto/proto3_proto/proto3.pb.go | 122 - .../protobuf/proto/proto3_proto/proto3.proto | 68 - .../golang/protobuf/proto/proto3_test.go | 125 - .../golang/protobuf/proto/size2_test.go | 63 - .../golang/protobuf/proto/size_test.go | 142 - .../golang/protobuf/proto/testdata/Makefile | 50 - .../protobuf/proto/testdata/golden_test.go | 86 - .../golang/protobuf/proto/testdata/test.pb.go | 2746 ----------------- .../golang/protobuf/proto/testdata/test.proto | 480 --- .../github.com/golang/protobuf/proto/text.go | 769 ----- .../golang/protobuf/proto/text_parser.go | 772 ----- .../golang/protobuf/proto/text_parser_test.go | 511 --- .../golang/protobuf/proto/text_test.go | 450 --- .../src/golang.org/x/image/bmp/reader.go | 199 -- .../src/golang.org/x/image/bmp/reader_test.go | 75 - .../src/golang.org/x/image/bmp/writer.go | 166 - .../src/golang.org/x/image/bmp/writer_test.go | 91 - .../src/golang.org/x/image/font/font.go | 202 ++ .../x/image/font/plan9font/example_test.go | 93 + .../x/image/font/plan9font/plan9font.go | 556 ++++ .../x/image/font/testdata/fixed/7x13.0000 | Bin 0 -> 3136 bytes .../x/image/font/testdata/fixed/7x13.0100 | Bin 0 -> 3908 bytes .../x/image/font/testdata/fixed/7x13.0200 | Bin 0 -> 3095 bytes .../x/image/font/testdata/fixed/7x13.0300 | Bin 0 -> 2631 bytes .../x/image/font/testdata/fixed/7x13.0400 | Bin 0 -> 3623 bytes .../x/image/font/testdata/fixed/7x13.0500 | Bin 0 -> 2492 bytes .../x/image/font/testdata/fixed/7x13.0E00 | Bin 0 -> 1235 bytes .../x/image/font/testdata/fixed/7x13.1000 | Bin 0 -> 2354 bytes .../x/image/font/testdata/fixed/7x13.1600 | Bin 0 -> 1825 bytes .../x/image/font/testdata/fixed/7x13.1E00 | Bin 0 -> 3713 bytes .../x/image/font/testdata/fixed/7x13.1F00 | Bin 0 -> 3012 bytes .../x/image/font/testdata/fixed/7x13.2000 | Bin 0 -> 2310 bytes .../x/image/font/testdata/fixed/7x13.2100 | Bin 0 -> 3206 bytes .../x/image/font/testdata/fixed/7x13.2200 | Bin 0 -> 3532 bytes .../x/image/font/testdata/fixed/7x13.2300 | Bin 0 -> 1613 bytes .../x/image/font/testdata/fixed/7x13.2400 | Bin 0 -> 1013 bytes .../x/image/font/testdata/fixed/7x13.2500 | Bin 0 -> 2747 bytes .../x/image/font/testdata/fixed/7x13.2600 | Bin 0 -> 1765 bytes .../x/image/font/testdata/fixed/7x13.2700 | Bin 0 -> 1762 bytes .../x/image/font/testdata/fixed/7x13.2800 | Bin 0 -> 1918 bytes .../x/image/font/testdata/fixed/7x13.2A00 | Bin 0 -> 620 bytes .../x/image/font/testdata/fixed/7x13.3000 | Bin 0 -> 569 bytes .../x/image/font/testdata/fixed/7x13.FB00 | Bin 0 -> 912 bytes .../x/image/font/testdata/fixed/7x13.FE00 | Bin 0 -> 387 bytes .../x/image/font/testdata/fixed/7x13.FF00 | Bin 0 -> 1687 bytes .../x/image/font/testdata/fixed/README | 9 + .../font/testdata/fixed/unicode.7x13.font | 68 + .../golang.org/x/image/math/fixed/fixed.go | 172 ++ .../x/image/math/fixed/fixed_test.go | 25 + .../golang.org/x/image/riff/example_test.go | 113 - .../src/golang.org/x/image/riff/riff.go | 179 -- .../src/golang.org/x/image/tiff/buffer.go | 69 - .../golang.org/x/image/tiff/buffer_test.go | 36 - .../src/golang.org/x/image/tiff/compress.go | 58 - .../src/golang.org/x/image/tiff/consts.go | 133 - .../src/golang.org/x/image/tiff/lzw/reader.go | 277 -- .../src/golang.org/x/image/tiff/reader.go | 681 ---- .../golang.org/x/image/tiff/reader_test.go | 377 --- .../src/golang.org/x/image/tiff/writer.go | 438 --- .../golang.org/x/image/tiff/writer_test.go | 95 - .../src/golang.org/x/image/vp8/decode.go | 403 --- .../src/golang.org/x/image/vp8/filter.go | 273 -- .../src/golang.org/x/image/vp8/idct.go | 98 - .../src/golang.org/x/image/vp8/partition.go | 129 - .../src/golang.org/x/image/vp8/pred.go | 201 -- .../src/golang.org/x/image/vp8/predfunc.go | 553 ---- .../src/golang.org/x/image/vp8/quant.go | 98 - .../src/golang.org/x/image/vp8/reconstruct.go | 442 --- .../src/golang.org/x/image/vp8/token.go | 381 --- .../src/golang.org/x/image/vp8l/decode.go | 603 ---- .../src/golang.org/x/image/vp8l/huffman.go | 245 -- .../src/golang.org/x/image/vp8l/transform.go | 299 -- .../src/golang.org/x/image/webp/decode.go | 275 -- .../golang.org/x/image/webp/decode_test.go | 296 -- .../x/image/webp/nycbcra/nycbcra.go | 186 -- Makefile | 8 +- Readme.markdown | 103 +- besticon/besticon.go | 163 +- besticon/besticon/cmd.go | 2 +- besticon/besticon_test.go | 8 +- besticon/caching.go | 83 - besticon/example_test.go | 2 +- besticon/iconserver/assets/assets.go | 78 +- besticon/iconserver/assets/icons.html | 23 +- besticon/iconserver/assets/index.html | 81 +- besticon/iconserver/assets/popular.html | 86 + .../iconserver/assets/test-lettericons.html | 110 + besticon/iconserver/server.go | 180 +- besticon/iconserver/server_test.go | 20 +- besticon/popular_sites.go | 117 + besticon/sorting.go | 9 +- colorfinder/colorfinder.go | 198 ++ colorfinder/colorfinder_test.go | 151 + colorfinder/testdata/black1x1.png | Bin 0 -> 1049 bytes colorfinder/testdata/icon01.png.gz | Bin 0 -> 29267 bytes colorfinder/testdata/icon02.png.gz | Bin 0 -> 11275 bytes colorfinder/testdata/icon03.png.gz | Bin 0 -> 3096 bytes colorfinder/testdata/icon04.png.gz | Bin 0 -> 882 bytes colorfinder/testdata/icon05.png.gz | Bin 0 -> 1036 bytes colorfinder/testdata/icon06.png.gz | Bin 0 -> 374 bytes colorfinder/testdata/icon07.png.gz | Bin 0 -> 3173 bytes colorfinder/testdata/white1x1.gif | Bin 0 -> 3221 bytes colorfinder/testdata/white1x1.jpg | Bin 0 -> 3349 bytes colorfinder/testdata/white1x1.png | Bin 0 -> 1049 bytes ico/ico.go | 112 +- ico/ico_test.go | 8 +- ico/icoparser/icoparser.go | 4 +- lettericon/fonts/LICENSE.txt | 202 ++ lettericon/fonts/open_sans.ttf | Bin 0 -> 24140 bytes lettericon/fonts/open_sans_light.go | 22 + lettericon/fonts/open_sans_light.ttf | Bin 0 -> 24120 bytes lettericon/lettericon.go | 277 ++ lettericon/lettericon/cmd.go | 39 + lettericon/lettericon_test.go | 153 + lettericon/testdata/A-16-123456.png | Bin 0 -> 222 bytes lettericon/testdata/X-32-dfdfdf.png | Bin 0 -> 418 bytes 166 files changed, 9493 insertions(+), 25848 deletions(-) create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/raster/geom.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/raster/paint.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/raster/raster.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/raster/stroke.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/truetype/face.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/truetype/face_test.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/truetype/glyph.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/truetype/hint.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/truetype/hint_test.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/truetype/opcodes.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/truetype/truetype.go create mode 100644 Godeps/_workspace/src/github.com/golang/freetype/truetype/truetype_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/.gitignore delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/LICENSE delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/README.md delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/byteview.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/byteview_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/consistenthash/consistenthash.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/consistenthash/consistenthash_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/groupcache.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/groupcache_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/groupcachepb/groupcache.pb.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/groupcachepb/groupcache.proto delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/http.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/http_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/lru/lru.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/lru/lru_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/peers.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/singleflight/singleflight.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/singleflight/singleflight_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/sinks.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/testpb/test.pb.go delete mode 100644 Godeps/_workspace/src/github.com/golang/groupcache/testpb/test.proto delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/Makefile delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/all_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/clone.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/clone_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/decode.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/equal.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/equal_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_reflect.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_unsafe.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/size2_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/size_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/Makefile delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/golden_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.pb.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.proto delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/text.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser_test.go delete mode 100644 Godeps/_workspace/src/github.com/golang/protobuf/proto/text_test.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/bmp/reader.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/bmp/reader_test.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/bmp/writer.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/bmp/writer_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/font.go create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/plan9font/example_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0000 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0100 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0200 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0300 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0400 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0500 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0E00 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1000 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1600 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1E00 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1F00 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2000 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2100 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2200 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2300 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2400 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2500 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2600 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2700 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2800 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2A00 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.3000 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.FB00 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.FE00 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.FF00 create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/README create mode 100644 Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/unicode.7x13.font create mode 100644 Godeps/_workspace/src/golang.org/x/image/math/fixed/fixed.go create mode 100644 Godeps/_workspace/src/golang.org/x/image/math/fixed/fixed_test.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/riff/example_test.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/riff/riff.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/buffer.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/buffer_test.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/compress.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/consts.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/lzw/reader.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/reader.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/reader_test.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/writer.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/writer_test.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8/decode.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8/filter.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8/idct.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8/partition.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8/pred.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8/predfunc.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8/quant.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8/reconstruct.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8/token.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8l/decode.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8l/huffman.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/vp8l/transform.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/webp/decode.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/webp/decode_test.go delete mode 100644 Godeps/_workspace/src/golang.org/x/image/webp/nycbcra/nycbcra.go delete mode 100644 besticon/caching.go create mode 100644 besticon/iconserver/assets/popular.html create mode 100644 besticon/iconserver/assets/test-lettericons.html create mode 100644 besticon/popular_sites.go create mode 100644 colorfinder/colorfinder.go create mode 100644 colorfinder/colorfinder_test.go create mode 100644 colorfinder/testdata/black1x1.png create mode 100644 colorfinder/testdata/icon01.png.gz create mode 100644 colorfinder/testdata/icon02.png.gz create mode 100644 colorfinder/testdata/icon03.png.gz create mode 100644 colorfinder/testdata/icon04.png.gz create mode 100644 colorfinder/testdata/icon05.png.gz create mode 100644 colorfinder/testdata/icon06.png.gz create mode 100644 colorfinder/testdata/icon07.png.gz create mode 100644 colorfinder/testdata/white1x1.gif create mode 100644 colorfinder/testdata/white1x1.jpg create mode 100644 colorfinder/testdata/white1x1.png create mode 100644 lettericon/fonts/LICENSE.txt create mode 100644 lettericon/fonts/open_sans.ttf create mode 100644 lettericon/fonts/open_sans_light.go create mode 100644 lettericon/fonts/open_sans_light.ttf create mode 100644 lettericon/lettericon.go create mode 100644 lettericon/lettericon/cmd.go create mode 100644 lettericon/lettericon_test.go create mode 100644 lettericon/testdata/A-16-123456.png create mode 100644 lettericon/testdata/X-32-dfdfdf.png diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 597c8f5f..b9f8d20e 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -19,36 +19,22 @@ "Rev": "3ad29d1ad1c4f2023e355603324348cf1f4b2d48" }, { - "ImportPath": "github.com/golang/groupcache", - "Rev": "604ed5785183e59ae2789449d89e73f3a2a77987" + "ImportPath": "github.com/golang/freetype/raster", + "Comment": "release-120-gf29eb11", + "Rev": "f29eb116deb328d02ee5c573f02d442ca67d5532" }, { - "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "73aaaa9eb61d74fbf7e256ca586a3a565b308eea" + "ImportPath": "github.com/golang/freetype/truetype", + "Comment": "release-120-gf29eb11", + "Rev": "f29eb116deb328d02ee5c573f02d442ca67d5532" }, { - "ImportPath": "golang.org/x/image/bmp", - "Rev": "d9c0088098f91b3d6e080f260217cdddc270052e" + "ImportPath": "golang.org/x/image/font", + "Rev": "2dc9880a10bbd310009571a348cc0d2e0b5bc4b2" }, { - "ImportPath": "golang.org/x/image/riff", - "Rev": "d9c0088098f91b3d6e080f260217cdddc270052e" - }, - { - "ImportPath": "golang.org/x/image/tiff", - "Rev": "d9c0088098f91b3d6e080f260217cdddc270052e" - }, - { - "ImportPath": "golang.org/x/image/vp8", - "Rev": "d9c0088098f91b3d6e080f260217cdddc270052e" - }, - { - "ImportPath": "golang.org/x/image/vp8l", - "Rev": "d9c0088098f91b3d6e080f260217cdddc270052e" - }, - { - "ImportPath": "golang.org/x/image/webp", - "Rev": "d9c0088098f91b3d6e080f260217cdddc270052e" + "ImportPath": "golang.org/x/image/math/fixed", + "Rev": "2dc9880a10bbd310009571a348cc0d2e0b5bc4b2" }, { "ImportPath": "golang.org/x/net/html", diff --git a/Godeps/_workspace/src/github.com/golang/freetype/raster/geom.go b/Godeps/_workspace/src/github.com/golang/freetype/raster/geom.go new file mode 100644 index 00000000..f3696ea9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/raster/geom.go @@ -0,0 +1,245 @@ +// Copyright 2010 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package raster + +import ( + "fmt" + "math" + + "golang.org/x/image/math/fixed" +) + +// maxAbs returns the maximum of abs(a) and abs(b). +func maxAbs(a, b fixed.Int26_6) fixed.Int26_6 { + if a < 0 { + a = -a + } + if b < 0 { + b = -b + } + if a < b { + return b + } + return a +} + +// pNeg returns the vector -p, or equivalently p rotated by 180 degrees. +func pNeg(p fixed.Point26_6) fixed.Point26_6 { + return fixed.Point26_6{-p.X, -p.Y} +} + +// pDot returns the dot product p·q. +func pDot(p fixed.Point26_6, q fixed.Point26_6) fixed.Int52_12 { + px, py := int64(p.X), int64(p.Y) + qx, qy := int64(q.X), int64(q.Y) + return fixed.Int52_12(px*qx + py*qy) +} + +// pLen returns the length of the vector p. +func pLen(p fixed.Point26_6) fixed.Int26_6 { + // TODO(nigeltao): use fixed point math. + x := float64(p.X) + y := float64(p.Y) + return fixed.Int26_6(math.Sqrt(x*x + y*y)) +} + +// pNorm returns the vector p normalized to the given length, or zero if p is +// degenerate. +func pNorm(p fixed.Point26_6, length fixed.Int26_6) fixed.Point26_6 { + d := pLen(p) + if d == 0 { + return fixed.Point26_6{} + } + s, t := int64(length), int64(d) + x := int64(p.X) * s / t + y := int64(p.Y) * s / t + return fixed.Point26_6{fixed.Int26_6(x), fixed.Int26_6(y)} +} + +// pRot45CW returns the vector p rotated clockwise by 45 degrees. +// +// Note that the Y-axis grows downwards, so {1, 0}.Rot45CW is {1/√2, 1/√2}. +func pRot45CW(p fixed.Point26_6) fixed.Point26_6 { + // 181/256 is approximately 1/√2, or sin(π/4). + px, py := int64(p.X), int64(p.Y) + qx := (+px - py) * 181 / 256 + qy := (+px + py) * 181 / 256 + return fixed.Point26_6{fixed.Int26_6(qx), fixed.Int26_6(qy)} +} + +// pRot90CW returns the vector p rotated clockwise by 90 degrees. +// +// Note that the Y-axis grows downwards, so {1, 0}.Rot90CW is {0, 1}. +func pRot90CW(p fixed.Point26_6) fixed.Point26_6 { + return fixed.Point26_6{-p.Y, p.X} +} + +// pRot135CW returns the vector p rotated clockwise by 135 degrees. +// +// Note that the Y-axis grows downwards, so {1, 0}.Rot135CW is {-1/√2, 1/√2}. +func pRot135CW(p fixed.Point26_6) fixed.Point26_6 { + // 181/256 is approximately 1/√2, or sin(π/4). + px, py := int64(p.X), int64(p.Y) + qx := (-px - py) * 181 / 256 + qy := (+px - py) * 181 / 256 + return fixed.Point26_6{fixed.Int26_6(qx), fixed.Int26_6(qy)} +} + +// pRot45CCW returns the vector p rotated counter-clockwise by 45 degrees. +// +// Note that the Y-axis grows downwards, so {1, 0}.Rot45CCW is {1/√2, -1/√2}. +func pRot45CCW(p fixed.Point26_6) fixed.Point26_6 { + // 181/256 is approximately 1/√2, or sin(π/4). + px, py := int64(p.X), int64(p.Y) + qx := (+px + py) * 181 / 256 + qy := (-px + py) * 181 / 256 + return fixed.Point26_6{fixed.Int26_6(qx), fixed.Int26_6(qy)} +} + +// pRot90CCW returns the vector p rotated counter-clockwise by 90 degrees. +// +// Note that the Y-axis grows downwards, so {1, 0}.Rot90CCW is {0, -1}. +func pRot90CCW(p fixed.Point26_6) fixed.Point26_6 { + return fixed.Point26_6{p.Y, -p.X} +} + +// pRot135CCW returns the vector p rotated counter-clockwise by 135 degrees. +// +// Note that the Y-axis grows downwards, so {1, 0}.Rot135CCW is {-1/√2, -1/√2}. +func pRot135CCW(p fixed.Point26_6) fixed.Point26_6 { + // 181/256 is approximately 1/√2, or sin(π/4). + px, py := int64(p.X), int64(p.Y) + qx := (-px + py) * 181 / 256 + qy := (-px - py) * 181 / 256 + return fixed.Point26_6{fixed.Int26_6(qx), fixed.Int26_6(qy)} +} + +// An Adder accumulates points on a curve. +type Adder interface { + // Start starts a new curve at the given point. + Start(a fixed.Point26_6) + // Add1 adds a linear segment to the current curve. + Add1(b fixed.Point26_6) + // Add2 adds a quadratic segment to the current curve. + Add2(b, c fixed.Point26_6) + // Add3 adds a cubic segment to the current curve. + Add3(b, c, d fixed.Point26_6) +} + +// A Path is a sequence of curves, and a curve is a start point followed by a +// sequence of linear, quadratic or cubic segments. +type Path []fixed.Int26_6 + +// String returns a human-readable representation of a Path. +func (p Path) String() string { + s := "" + for i := 0; i < len(p); { + if i != 0 { + s += " " + } + switch p[i] { + case 0: + s += "S0" + fmt.Sprint([]fixed.Int26_6(p[i+1:i+3])) + i += 4 + case 1: + s += "A1" + fmt.Sprint([]fixed.Int26_6(p[i+1:i+3])) + i += 4 + case 2: + s += "A2" + fmt.Sprint([]fixed.Int26_6(p[i+1:i+5])) + i += 6 + case 3: + s += "A3" + fmt.Sprint([]fixed.Int26_6(p[i+1:i+7])) + i += 8 + default: + panic("freetype/raster: bad path") + } + } + return s +} + +// Clear cancels any previous calls to p.Start or p.AddXxx. +func (p *Path) Clear() { + *p = (*p)[:0] +} + +// Start starts a new curve at the given point. +func (p *Path) Start(a fixed.Point26_6) { + *p = append(*p, 0, a.X, a.Y, 0) +} + +// Add1 adds a linear segment to the current curve. +func (p *Path) Add1(b fixed.Point26_6) { + *p = append(*p, 1, b.X, b.Y, 1) +} + +// Add2 adds a quadratic segment to the current curve. +func (p *Path) Add2(b, c fixed.Point26_6) { + *p = append(*p, 2, b.X, b.Y, c.X, c.Y, 2) +} + +// Add3 adds a cubic segment to the current curve. +func (p *Path) Add3(b, c, d fixed.Point26_6) { + *p = append(*p, 3, b.X, b.Y, c.X, c.Y, d.X, d.Y, 3) +} + +// AddPath adds the Path q to p. +func (p *Path) AddPath(q Path) { + *p = append(*p, q...) +} + +// AddStroke adds a stroked Path. +func (p *Path) AddStroke(q Path, width fixed.Int26_6, cr Capper, jr Joiner) { + Stroke(p, q, width, cr, jr) +} + +// firstPoint returns the first point in a non-empty Path. +func (p Path) firstPoint() fixed.Point26_6 { + return fixed.Point26_6{p[1], p[2]} +} + +// lastPoint returns the last point in a non-empty Path. +func (p Path) lastPoint() fixed.Point26_6 { + return fixed.Point26_6{p[len(p)-3], p[len(p)-2]} +} + +// addPathReversed adds q reversed to p. +// For example, if q consists of a linear segment from A to B followed by a +// quadratic segment from B to C to D, then the values of q looks like: +// index: 01234567890123 +// value: 0AA01BB12CCDD2 +// So, when adding q backwards to p, we want to Add2(C, B) followed by Add1(A). +func addPathReversed(p Adder, q Path) { + if len(q) == 0 { + return + } + i := len(q) - 1 + for { + switch q[i] { + case 0: + return + case 1: + i -= 4 + p.Add1( + fixed.Point26_6{q[i-2], q[i-1]}, + ) + case 2: + i -= 6 + p.Add2( + fixed.Point26_6{q[i+2], q[i+3]}, + fixed.Point26_6{q[i-2], q[i-1]}, + ) + case 3: + i -= 8 + p.Add3( + fixed.Point26_6{q[i+4], q[i+5]}, + fixed.Point26_6{q[i+2], q[i+3]}, + fixed.Point26_6{q[i-2], q[i-1]}, + ) + default: + panic("freetype/raster: bad path") + } + } +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/raster/paint.go b/Godeps/_workspace/src/github.com/golang/freetype/raster/paint.go new file mode 100644 index 00000000..185d36a8 --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/raster/paint.go @@ -0,0 +1,287 @@ +// Copyright 2010 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package raster + +import ( + "image" + "image/color" + "image/draw" + "math" +) + +// A Span is a horizontal segment of pixels with constant alpha. X0 is an +// inclusive bound and X1 is exclusive, the same as for slices. A fully opaque +// Span has Alpha == 0xffff. +type Span struct { + Y, X0, X1 int + Alpha uint32 +} + +// A Painter knows how to paint a batch of Spans. Rasterization may involve +// Painting multiple batches, and done will be true for the final batch. The +// Spans' Y values are monotonically increasing during a rasterization. Paint +// may use all of ss as scratch space during the call. +type Painter interface { + Paint(ss []Span, done bool) +} + +// The PainterFunc type adapts an ordinary function to the Painter interface. +type PainterFunc func(ss []Span, done bool) + +// Paint just delegates the call to f. +func (f PainterFunc) Paint(ss []Span, done bool) { f(ss, done) } + +// An AlphaOverPainter is a Painter that paints Spans onto a *image.Alpha using +// the Over Porter-Duff composition operator. +type AlphaOverPainter struct { + Image *image.Alpha +} + +// Paint satisfies the Painter interface. +func (r AlphaOverPainter) Paint(ss []Span, done bool) { + b := r.Image.Bounds() + for _, s := range ss { + if s.Y < b.Min.Y { + continue + } + if s.Y >= b.Max.Y { + return + } + if s.X0 < b.Min.X { + s.X0 = b.Min.X + } + if s.X1 > b.Max.X { + s.X1 = b.Max.X + } + if s.X0 >= s.X1 { + continue + } + base := (s.Y-r.Image.Rect.Min.Y)*r.Image.Stride - r.Image.Rect.Min.X + p := r.Image.Pix[base+s.X0 : base+s.X1] + a := int(s.Alpha >> 8) + for i, c := range p { + v := int(c) + p[i] = uint8((v*255 + (255-v)*a) / 255) + } + } +} + +// NewAlphaOverPainter creates a new AlphaOverPainter for the given image. +func NewAlphaOverPainter(m *image.Alpha) AlphaOverPainter { + return AlphaOverPainter{m} +} + +// An AlphaSrcPainter is a Painter that paints Spans onto a *image.Alpha using +// the Src Porter-Duff composition operator. +type AlphaSrcPainter struct { + Image *image.Alpha +} + +// Paint satisfies the Painter interface. +func (r AlphaSrcPainter) Paint(ss []Span, done bool) { + b := r.Image.Bounds() + for _, s := range ss { + if s.Y < b.Min.Y { + continue + } + if s.Y >= b.Max.Y { + return + } + if s.X0 < b.Min.X { + s.X0 = b.Min.X + } + if s.X1 > b.Max.X { + s.X1 = b.Max.X + } + if s.X0 >= s.X1 { + continue + } + base := (s.Y-r.Image.Rect.Min.Y)*r.Image.Stride - r.Image.Rect.Min.X + p := r.Image.Pix[base+s.X0 : base+s.X1] + color := uint8(s.Alpha >> 8) + for i := range p { + p[i] = color + } + } +} + +// NewAlphaSrcPainter creates a new AlphaSrcPainter for the given image. +func NewAlphaSrcPainter(m *image.Alpha) AlphaSrcPainter { + return AlphaSrcPainter{m} +} + +// An RGBAPainter is a Painter that paints Spans onto a *image.RGBA. +type RGBAPainter struct { + // Image is the image to compose onto. + Image *image.RGBA + // Op is the Porter-Duff composition operator. + Op draw.Op + // cr, cg, cb and ca are the 16-bit color to paint the spans. + cr, cg, cb, ca uint32 +} + +// Paint satisfies the Painter interface. +func (r *RGBAPainter) Paint(ss []Span, done bool) { + b := r.Image.Bounds() + for _, s := range ss { + if s.Y < b.Min.Y { + continue + } + if s.Y >= b.Max.Y { + return + } + if s.X0 < b.Min.X { + s.X0 = b.Min.X + } + if s.X1 > b.Max.X { + s.X1 = b.Max.X + } + if s.X0 >= s.X1 { + continue + } + // This code mimics drawGlyphOver in $GOROOT/src/image/draw/draw.go. + ma := s.Alpha + const m = 1<<16 - 1 + i0 := (s.Y-r.Image.Rect.Min.Y)*r.Image.Stride + (s.X0-r.Image.Rect.Min.X)*4 + i1 := i0 + (s.X1-s.X0)*4 + if r.Op == draw.Over { + for i := i0; i < i1; i += 4 { + dr := uint32(r.Image.Pix[i+0]) + dg := uint32(r.Image.Pix[i+1]) + db := uint32(r.Image.Pix[i+2]) + da := uint32(r.Image.Pix[i+3]) + a := (m - (r.ca * ma / m)) * 0x101 + r.Image.Pix[i+0] = uint8((dr*a + r.cr*ma) / m >> 8) + r.Image.Pix[i+1] = uint8((dg*a + r.cg*ma) / m >> 8) + r.Image.Pix[i+2] = uint8((db*a + r.cb*ma) / m >> 8) + r.Image.Pix[i+3] = uint8((da*a + r.ca*ma) / m >> 8) + } + } else { + for i := i0; i < i1; i += 4 { + r.Image.Pix[i+0] = uint8(r.cr * ma / m >> 8) + r.Image.Pix[i+1] = uint8(r.cg * ma / m >> 8) + r.Image.Pix[i+2] = uint8(r.cb * ma / m >> 8) + r.Image.Pix[i+3] = uint8(r.ca * ma / m >> 8) + } + } + } +} + +// SetColor sets the color to paint the spans. +func (r *RGBAPainter) SetColor(c color.Color) { + r.cr, r.cg, r.cb, r.ca = c.RGBA() +} + +// NewRGBAPainter creates a new RGBAPainter for the given image. +func NewRGBAPainter(m *image.RGBA) *RGBAPainter { + return &RGBAPainter{Image: m} +} + +// A MonochromePainter wraps another Painter, quantizing each Span's alpha to +// be either fully opaque or fully transparent. +type MonochromePainter struct { + Painter Painter + y, x0, x1 int +} + +// Paint delegates to the wrapped Painter after quantizing each Span's alpha +// value and merging adjacent fully opaque Spans. +func (m *MonochromePainter) Paint(ss []Span, done bool) { + // We compact the ss slice, discarding any Spans whose alpha quantizes to zero. + j := 0 + for _, s := range ss { + if s.Alpha >= 0x8000 { + if m.y == s.Y && m.x1 == s.X0 { + m.x1 = s.X1 + } else { + ss[j] = Span{m.y, m.x0, m.x1, 1<<32 - 1} + j++ + m.y, m.x0, m.x1 = s.Y, s.X0, s.X1 + } + } + } + if done { + // Flush the accumulated Span. + finalSpan := Span{m.y, m.x0, m.x1, 1<<32 - 1} + if j < len(ss) { + ss[j] = finalSpan + j++ + m.Painter.Paint(ss[:j], true) + } else if j == len(ss) { + m.Painter.Paint(ss, false) + if cap(ss) > 0 { + ss = ss[:1] + } else { + ss = make([]Span, 1) + } + ss[0] = finalSpan + m.Painter.Paint(ss, true) + } else { + panic("unreachable") + } + // Reset the accumulator, so that this Painter can be re-used. + m.y, m.x0, m.x1 = 0, 0, 0 + } else { + m.Painter.Paint(ss[:j], false) + } +} + +// NewMonochromePainter creates a new MonochromePainter that wraps the given +// Painter. +func NewMonochromePainter(p Painter) *MonochromePainter { + return &MonochromePainter{Painter: p} +} + +// A GammaCorrectionPainter wraps another Painter, performing gamma-correction +// on each Span's alpha value. +type GammaCorrectionPainter struct { + // Painter is the wrapped Painter. + Painter Painter + // a is the precomputed alpha values for linear interpolation, with fully + // opaque == 0xffff. + a [256]uint16 + // gammaIsOne is whether gamma correction is a no-op. + gammaIsOne bool +} + +// Paint delegates to the wrapped Painter after performing gamma-correction on +// each Span. +func (g *GammaCorrectionPainter) Paint(ss []Span, done bool) { + if !g.gammaIsOne { + const n = 0x101 + for i, s := range ss { + if s.Alpha == 0 || s.Alpha == 0xffff { + continue + } + p, q := s.Alpha/n, s.Alpha%n + // The resultant alpha is a linear interpolation of g.a[p] and g.a[p+1]. + a := uint32(g.a[p])*(n-q) + uint32(g.a[p+1])*q + ss[i].Alpha = (a + n/2) / n + } + } + g.Painter.Paint(ss, done) +} + +// SetGamma sets the gamma value. +func (g *GammaCorrectionPainter) SetGamma(gamma float64) { + g.gammaIsOne = gamma == 1 + if g.gammaIsOne { + return + } + for i := 0; i < 256; i++ { + a := float64(i) / 0xff + a = math.Pow(a, gamma) + g.a[i] = uint16(0xffff * a) + } +} + +// NewGammaCorrectionPainter creates a new GammaCorrectionPainter that wraps +// the given Painter. +func NewGammaCorrectionPainter(p Painter, gamma float64) *GammaCorrectionPainter { + g := &GammaCorrectionPainter{Painter: p} + g.SetGamma(gamma) + return g +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/raster/raster.go b/Godeps/_workspace/src/github.com/golang/freetype/raster/raster.go new file mode 100644 index 00000000..7e6cd4e2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/raster/raster.go @@ -0,0 +1,601 @@ +// Copyright 2010 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +// Package raster provides an anti-aliasing 2-D rasterizer. +// +// It is part of the larger Freetype suite of font-related packages, but the +// raster package is not specific to font rasterization, and can be used +// standalone without any other Freetype package. +// +// Rasterization is done by the same area/coverage accumulation algorithm as +// the Freetype "smooth" module, and the Anti-Grain Geometry library. A +// description of the area/coverage algorithm is at +// http://projects.tuxee.net/cl-vectors/section-the-cl-aa-algorithm +package raster // import "github.com/golang/freetype/raster" + +import ( + "strconv" + + "golang.org/x/image/math/fixed" +) + +// A cell is part of a linked list (for a given yi co-ordinate) of accumulated +// area/coverage for the pixel at (xi, yi). +type cell struct { + xi int + area, cover int + next int +} + +type Rasterizer struct { + // If false, the default behavior is to use the even-odd winding fill + // rule during Rasterize. + UseNonZeroWinding bool + // An offset (in pixels) to the painted spans. + Dx, Dy int + + // The width of the Rasterizer. The height is implicit in len(cellIndex). + width int + // splitScaleN is the scaling factor used to determine how many times + // to decompose a quadratic or cubic segment into a linear approximation. + splitScale2, splitScale3 int + + // The current pen position. + a fixed.Point26_6 + // The current cell and its area/coverage being accumulated. + xi, yi int + area, cover int + + // Saved cells. + cell []cell + // Linked list of cells, one per row. + cellIndex []int + // Buffers. + cellBuf [256]cell + cellIndexBuf [64]int + spanBuf [64]Span +} + +// findCell returns the index in r.cell for the cell corresponding to +// (r.xi, r.yi). The cell is created if necessary. +func (r *Rasterizer) findCell() int { + if r.yi < 0 || r.yi >= len(r.cellIndex) { + return -1 + } + xi := r.xi + if xi < 0 { + xi = -1 + } else if xi > r.width { + xi = r.width + } + i, prev := r.cellIndex[r.yi], -1 + for i != -1 && r.cell[i].xi <= xi { + if r.cell[i].xi == xi { + return i + } + i, prev = r.cell[i].next, i + } + c := len(r.cell) + if c == cap(r.cell) { + buf := make([]cell, c, 4*c) + copy(buf, r.cell) + r.cell = buf[0 : c+1] + } else { + r.cell = r.cell[0 : c+1] + } + r.cell[c] = cell{xi, 0, 0, i} + if prev == -1 { + r.cellIndex[r.yi] = c + } else { + r.cell[prev].next = c + } + return c +} + +// saveCell saves any accumulated r.area/r.cover for (r.xi, r.yi). +func (r *Rasterizer) saveCell() { + if r.area != 0 || r.cover != 0 { + i := r.findCell() + if i != -1 { + r.cell[i].area += r.area + r.cell[i].cover += r.cover + } + r.area = 0 + r.cover = 0 + } +} + +// setCell sets the (xi, yi) cell that r is accumulating area/coverage for. +func (r *Rasterizer) setCell(xi, yi int) { + if r.xi != xi || r.yi != yi { + r.saveCell() + r.xi, r.yi = xi, yi + } +} + +// scan accumulates area/coverage for the yi'th scanline, going from +// x0 to x1 in the horizontal direction (in 26.6 fixed point co-ordinates) +// and from y0f to y1f fractional vertical units within that scanline. +func (r *Rasterizer) scan(yi int, x0, y0f, x1, y1f fixed.Int26_6) { + // Break the 26.6 fixed point X co-ordinates into integral and fractional parts. + x0i := int(x0) / 64 + x0f := x0 - fixed.Int26_6(64*x0i) + x1i := int(x1) / 64 + x1f := x1 - fixed.Int26_6(64*x1i) + + // A perfectly horizontal scan. + if y0f == y1f { + r.setCell(x1i, yi) + return + } + dx, dy := x1-x0, y1f-y0f + // A single cell scan. + if x0i == x1i { + r.area += int((x0f + x1f) * dy) + r.cover += int(dy) + return + } + // There are at least two cells. Apart from the first and last cells, + // all intermediate cells go through the full width of the cell, + // or 64 units in 26.6 fixed point format. + var ( + p, q, edge0, edge1 fixed.Int26_6 + xiDelta int + ) + if dx > 0 { + p, q = (64-x0f)*dy, dx + edge0, edge1, xiDelta = 0, 64, 1 + } else { + p, q = x0f*dy, -dx + edge0, edge1, xiDelta = 64, 0, -1 + } + yDelta, yRem := p/q, p%q + if yRem < 0 { + yDelta -= 1 + yRem += q + } + // Do the first cell. + xi, y := x0i, y0f + r.area += int((x0f + edge1) * yDelta) + r.cover += int(yDelta) + xi, y = xi+xiDelta, y+yDelta + r.setCell(xi, yi) + if xi != x1i { + // Do all the intermediate cells. + p = 64 * (y1f - y + yDelta) + fullDelta, fullRem := p/q, p%q + if fullRem < 0 { + fullDelta -= 1 + fullRem += q + } + yRem -= q + for xi != x1i { + yDelta = fullDelta + yRem += fullRem + if yRem >= 0 { + yDelta += 1 + yRem -= q + } + r.area += int(64 * yDelta) + r.cover += int(yDelta) + xi, y = xi+xiDelta, y+yDelta + r.setCell(xi, yi) + } + } + // Do the last cell. + yDelta = y1f - y + r.area += int((edge0 + x1f) * yDelta) + r.cover += int(yDelta) +} + +// Start starts a new curve at the given point. +func (r *Rasterizer) Start(a fixed.Point26_6) { + r.setCell(int(a.X/64), int(a.Y/64)) + r.a = a +} + +// Add1 adds a linear segment to the current curve. +func (r *Rasterizer) Add1(b fixed.Point26_6) { + x0, y0 := r.a.X, r.a.Y + x1, y1 := b.X, b.Y + dx, dy := x1-x0, y1-y0 + // Break the 26.6 fixed point Y co-ordinates into integral and fractional + // parts. + y0i := int(y0) / 64 + y0f := y0 - fixed.Int26_6(64*y0i) + y1i := int(y1) / 64 + y1f := y1 - fixed.Int26_6(64*y1i) + + if y0i == y1i { + // There is only one scanline. + r.scan(y0i, x0, y0f, x1, y1f) + + } else if dx == 0 { + // This is a vertical line segment. We avoid calling r.scan and instead + // manipulate r.area and r.cover directly. + var ( + edge0, edge1 fixed.Int26_6 + yiDelta int + ) + if dy > 0 { + edge0, edge1, yiDelta = 0, 64, 1 + } else { + edge0, edge1, yiDelta = 64, 0, -1 + } + x0i, yi := int(x0)/64, y0i + x0fTimes2 := (int(x0) - (64 * x0i)) * 2 + // Do the first pixel. + dcover := int(edge1 - y0f) + darea := int(x0fTimes2 * dcover) + r.area += darea + r.cover += dcover + yi += yiDelta + r.setCell(x0i, yi) + // Do all the intermediate pixels. + dcover = int(edge1 - edge0) + darea = int(x0fTimes2 * dcover) + for yi != y1i { + r.area += darea + r.cover += dcover + yi += yiDelta + r.setCell(x0i, yi) + } + // Do the last pixel. + dcover = int(y1f - edge0) + darea = int(x0fTimes2 * dcover) + r.area += darea + r.cover += dcover + + } else { + // There are at least two scanlines. Apart from the first and last + // scanlines, all intermediate scanlines go through the full height of + // the row, or 64 units in 26.6 fixed point format. + var ( + p, q, edge0, edge1 fixed.Int26_6 + yiDelta int + ) + if dy > 0 { + p, q = (64-y0f)*dx, dy + edge0, edge1, yiDelta = 0, 64, 1 + } else { + p, q = y0f*dx, -dy + edge0, edge1, yiDelta = 64, 0, -1 + } + xDelta, xRem := p/q, p%q + if xRem < 0 { + xDelta -= 1 + xRem += q + } + // Do the first scanline. + x, yi := x0, y0i + r.scan(yi, x, y0f, x+xDelta, edge1) + x, yi = x+xDelta, yi+yiDelta + r.setCell(int(x)/64, yi) + if yi != y1i { + // Do all the intermediate scanlines. + p = 64 * dx + fullDelta, fullRem := p/q, p%q + if fullRem < 0 { + fullDelta -= 1 + fullRem += q + } + xRem -= q + for yi != y1i { + xDelta = fullDelta + xRem += fullRem + if xRem >= 0 { + xDelta += 1 + xRem -= q + } + r.scan(yi, x, edge0, x+xDelta, edge1) + x, yi = x+xDelta, yi+yiDelta + r.setCell(int(x)/64, yi) + } + } + // Do the last scanline. + r.scan(yi, x, edge0, x1, y1f) + } + // The next lineTo starts from b. + r.a = b +} + +// Add2 adds a quadratic segment to the current curve. +func (r *Rasterizer) Add2(b, c fixed.Point26_6) { + // Calculate nSplit (the number of recursive decompositions) based on how + // 'curvy' it is. Specifically, how much the middle point b deviates from + // (a+c)/2. + dev := maxAbs(r.a.X-2*b.X+c.X, r.a.Y-2*b.Y+c.Y) / fixed.Int26_6(r.splitScale2) + nsplit := 0 + for dev > 0 { + dev /= 4 + nsplit++ + } + // dev is 32-bit, and nsplit++ every time we shift off 2 bits, so maxNsplit + // is 16. + const maxNsplit = 16 + if nsplit > maxNsplit { + panic("freetype/raster: Add2 nsplit too large: " + strconv.Itoa(nsplit)) + } + // Recursively decompose the curve nSplit levels deep. + var ( + pStack [2*maxNsplit + 3]fixed.Point26_6 + sStack [maxNsplit + 1]int + i int + ) + sStack[0] = nsplit + pStack[0] = c + pStack[1] = b + pStack[2] = r.a + for i >= 0 { + s := sStack[i] + p := pStack[2*i:] + if s > 0 { + // Split the quadratic curve p[:3] into an equivalent set of two + // shorter curves: p[:3] and p[2:5]. The new p[4] is the old p[2], + // and p[0] is unchanged. + mx := p[1].X + p[4].X = p[2].X + p[3].X = (p[4].X + mx) / 2 + p[1].X = (p[0].X + mx) / 2 + p[2].X = (p[1].X + p[3].X) / 2 + my := p[1].Y + p[4].Y = p[2].Y + p[3].Y = (p[4].Y + my) / 2 + p[1].Y = (p[0].Y + my) / 2 + p[2].Y = (p[1].Y + p[3].Y) / 2 + // The two shorter curves have one less split to do. + sStack[i] = s - 1 + sStack[i+1] = s - 1 + i++ + } else { + // Replace the level-0 quadratic with a two-linear-piece + // approximation. + midx := (p[0].X + 2*p[1].X + p[2].X) / 4 + midy := (p[0].Y + 2*p[1].Y + p[2].Y) / 4 + r.Add1(fixed.Point26_6{midx, midy}) + r.Add1(p[0]) + i-- + } + } +} + +// Add3 adds a cubic segment to the current curve. +func (r *Rasterizer) Add3(b, c, d fixed.Point26_6) { + // Calculate nSplit (the number of recursive decompositions) based on how + // 'curvy' it is. + dev2 := maxAbs(r.a.X-3*(b.X+c.X)+d.X, r.a.Y-3*(b.Y+c.Y)+d.Y) / fixed.Int26_6(r.splitScale2) + dev3 := maxAbs(r.a.X-2*b.X+d.X, r.a.Y-2*b.Y+d.Y) / fixed.Int26_6(r.splitScale3) + nsplit := 0 + for dev2 > 0 || dev3 > 0 { + dev2 /= 8 + dev3 /= 4 + nsplit++ + } + // devN is 32-bit, and nsplit++ every time we shift off 2 bits, so + // maxNsplit is 16. + const maxNsplit = 16 + if nsplit > maxNsplit { + panic("freetype/raster: Add3 nsplit too large: " + strconv.Itoa(nsplit)) + } + // Recursively decompose the curve nSplit levels deep. + var ( + pStack [3*maxNsplit + 4]fixed.Point26_6 + sStack [maxNsplit + 1]int + i int + ) + sStack[0] = nsplit + pStack[0] = d + pStack[1] = c + pStack[2] = b + pStack[3] = r.a + for i >= 0 { + s := sStack[i] + p := pStack[3*i:] + if s > 0 { + // Split the cubic curve p[:4] into an equivalent set of two + // shorter curves: p[:4] and p[3:7]. The new p[6] is the old p[3], + // and p[0] is unchanged. + m01x := (p[0].X + p[1].X) / 2 + m12x := (p[1].X + p[2].X) / 2 + m23x := (p[2].X + p[3].X) / 2 + p[6].X = p[3].X + p[5].X = m23x + p[1].X = m01x + p[2].X = (m01x + m12x) / 2 + p[4].X = (m12x + m23x) / 2 + p[3].X = (p[2].X + p[4].X) / 2 + m01y := (p[0].Y + p[1].Y) / 2 + m12y := (p[1].Y + p[2].Y) / 2 + m23y := (p[2].Y + p[3].Y) / 2 + p[6].Y = p[3].Y + p[5].Y = m23y + p[1].Y = m01y + p[2].Y = (m01y + m12y) / 2 + p[4].Y = (m12y + m23y) / 2 + p[3].Y = (p[2].Y + p[4].Y) / 2 + // The two shorter curves have one less split to do. + sStack[i] = s - 1 + sStack[i+1] = s - 1 + i++ + } else { + // Replace the level-0 cubic with a two-linear-piece approximation. + midx := (p[0].X + 3*(p[1].X+p[2].X) + p[3].X) / 8 + midy := (p[0].Y + 3*(p[1].Y+p[2].Y) + p[3].Y) / 8 + r.Add1(fixed.Point26_6{midx, midy}) + r.Add1(p[0]) + i-- + } + } +} + +// AddPath adds the given Path. +func (r *Rasterizer) AddPath(p Path) { + for i := 0; i < len(p); { + switch p[i] { + case 0: + r.Start( + fixed.Point26_6{p[i+1], p[i+2]}, + ) + i += 4 + case 1: + r.Add1( + fixed.Point26_6{p[i+1], p[i+2]}, + ) + i += 4 + case 2: + r.Add2( + fixed.Point26_6{p[i+1], p[i+2]}, + fixed.Point26_6{p[i+3], p[i+4]}, + ) + i += 6 + case 3: + r.Add3( + fixed.Point26_6{p[i+1], p[i+2]}, + fixed.Point26_6{p[i+3], p[i+4]}, + fixed.Point26_6{p[i+5], p[i+6]}, + ) + i += 8 + default: + panic("freetype/raster: bad path") + } + } +} + +// AddStroke adds a stroked Path. +func (r *Rasterizer) AddStroke(q Path, width fixed.Int26_6, cr Capper, jr Joiner) { + Stroke(r, q, width, cr, jr) +} + +// areaToAlpha converts an area value to a uint32 alpha value. A completely +// filled pixel corresponds to an area of 64*64*2, and an alpha of 0xffff. The +// conversion of area values greater than this depends on the winding rule: +// even-odd or non-zero. +func (r *Rasterizer) areaToAlpha(area int) uint32 { + // The C Freetype implementation (version 2.3.12) does "alpha := area>>1" + // without the +1. Round-to-nearest gives a more symmetric result than + // round-down. The C implementation also returns 8-bit alpha, not 16-bit + // alpha. + a := (area + 1) >> 1 + if a < 0 { + a = -a + } + alpha := uint32(a) + if r.UseNonZeroWinding { + if alpha > 0x0fff { + alpha = 0x0fff + } + } else { + alpha &= 0x1fff + if alpha > 0x1000 { + alpha = 0x2000 - alpha + } else if alpha == 0x1000 { + alpha = 0x0fff + } + } + // alpha is now in the range [0x0000, 0x0fff]. Convert that 12-bit alpha to + // 16-bit alpha. + return alpha<<4 | alpha>>8 +} + +// Rasterize converts r's accumulated curves into Spans for p. The Spans passed +// to p are non-overlapping, and sorted by Y and then X. They all have non-zero +// width (and 0 <= X0 < X1 <= r.width) and non-zero A, except for the final +// Span, which has Y, X0, X1 and A all equal to zero. +func (r *Rasterizer) Rasterize(p Painter) { + r.saveCell() + s := 0 + for yi := 0; yi < len(r.cellIndex); yi++ { + xi, cover := 0, 0 + for c := r.cellIndex[yi]; c != -1; c = r.cell[c].next { + if cover != 0 && r.cell[c].xi > xi { + alpha := r.areaToAlpha(cover * 64 * 2) + if alpha != 0 { + xi0, xi1 := xi, r.cell[c].xi + if xi0 < 0 { + xi0 = 0 + } + if xi1 >= r.width { + xi1 = r.width + } + if xi0 < xi1 { + r.spanBuf[s] = Span{yi + r.Dy, xi0 + r.Dx, xi1 + r.Dx, alpha} + s++ + } + } + } + cover += r.cell[c].cover + alpha := r.areaToAlpha(cover*64*2 - r.cell[c].area) + xi = r.cell[c].xi + 1 + if alpha != 0 { + xi0, xi1 := r.cell[c].xi, xi + if xi0 < 0 { + xi0 = 0 + } + if xi1 >= r.width { + xi1 = r.width + } + if xi0 < xi1 { + r.spanBuf[s] = Span{yi + r.Dy, xi0 + r.Dx, xi1 + r.Dx, alpha} + s++ + } + } + if s > len(r.spanBuf)-2 { + p.Paint(r.spanBuf[:s], false) + s = 0 + } + } + } + p.Paint(r.spanBuf[:s], true) +} + +// Clear cancels any previous calls to r.Start or r.AddXxx. +func (r *Rasterizer) Clear() { + r.a = fixed.Point26_6{} + r.xi = 0 + r.yi = 0 + r.area = 0 + r.cover = 0 + r.cell = r.cell[:0] + for i := 0; i < len(r.cellIndex); i++ { + r.cellIndex[i] = -1 + } +} + +// SetBounds sets the maximum width and height of the rasterized image and +// calls Clear. The width and height are in pixels, not fixed.Int26_6 units. +func (r *Rasterizer) SetBounds(width, height int) { + if width < 0 { + width = 0 + } + if height < 0 { + height = 0 + } + // Use the same ssN heuristic as the C Freetype (version 2.4.0) + // implementation. + ss2, ss3 := 32, 16 + if width > 24 || height > 24 { + ss2, ss3 = 2*ss2, 2*ss3 + if width > 120 || height > 120 { + ss2, ss3 = 2*ss2, 2*ss3 + } + } + r.width = width + r.splitScale2 = ss2 + r.splitScale3 = ss3 + r.cell = r.cellBuf[:0] + if height > len(r.cellIndexBuf) { + r.cellIndex = make([]int, height) + } else { + r.cellIndex = r.cellIndexBuf[:height] + } + r.Clear() +} + +// NewRasterizer creates a new Rasterizer with the given bounds. +func NewRasterizer(width, height int) *Rasterizer { + r := new(Rasterizer) + r.SetBounds(width, height) + return r +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/raster/stroke.go b/Godeps/_workspace/src/github.com/golang/freetype/raster/stroke.go new file mode 100644 index 00000000..8d437975 --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/raster/stroke.go @@ -0,0 +1,483 @@ +// Copyright 2010 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package raster + +import ( + "golang.org/x/image/math/fixed" +) + +// Two points are considered practically equal if the square of the distance +// between them is less than one quarter (i.e. 1024 / 4096). +const epsilon = fixed.Int52_12(1024) + +// A Capper signifies how to begin or end a stroked path. +type Capper interface { + // Cap adds a cap to p given a pivot point and the normal vector of a + // terminal segment. The normal's length is half of the stroke width. + Cap(p Adder, halfWidth fixed.Int26_6, pivot, n1 fixed.Point26_6) +} + +// The CapperFunc type adapts an ordinary function to be a Capper. +type CapperFunc func(Adder, fixed.Int26_6, fixed.Point26_6, fixed.Point26_6) + +func (f CapperFunc) Cap(p Adder, halfWidth fixed.Int26_6, pivot, n1 fixed.Point26_6) { + f(p, halfWidth, pivot, n1) +} + +// A Joiner signifies how to join interior nodes of a stroked path. +type Joiner interface { + // Join adds a join to the two sides of a stroked path given a pivot + // point and the normal vectors of the trailing and leading segments. + // Both normals have length equal to half of the stroke width. + Join(lhs, rhs Adder, halfWidth fixed.Int26_6, pivot, n0, n1 fixed.Point26_6) +} + +// The JoinerFunc type adapts an ordinary function to be a Joiner. +type JoinerFunc func(lhs, rhs Adder, halfWidth fixed.Int26_6, pivot, n0, n1 fixed.Point26_6) + +func (f JoinerFunc) Join(lhs, rhs Adder, halfWidth fixed.Int26_6, pivot, n0, n1 fixed.Point26_6) { + f(lhs, rhs, halfWidth, pivot, n0, n1) +} + +// RoundCapper adds round caps to a stroked path. +var RoundCapper Capper = CapperFunc(roundCapper) + +func roundCapper(p Adder, halfWidth fixed.Int26_6, pivot, n1 fixed.Point26_6) { + // The cubic Bézier approximation to a circle involves the magic number + // (√2 - 1) * 4/3, which is approximately 141/256. + const k = 141 + e := pRot90CCW(n1) + side := pivot.Add(e) + start, end := pivot.Sub(n1), pivot.Add(n1) + d, e := n1.Mul(k), e.Mul(k) + p.Add3(start.Add(e), side.Sub(d), side) + p.Add3(side.Add(d), end.Add(e), end) +} + +// ButtCapper adds butt caps to a stroked path. +var ButtCapper Capper = CapperFunc(buttCapper) + +func buttCapper(p Adder, halfWidth fixed.Int26_6, pivot, n1 fixed.Point26_6) { + p.Add1(pivot.Add(n1)) +} + +// SquareCapper adds square caps to a stroked path. +var SquareCapper Capper = CapperFunc(squareCapper) + +func squareCapper(p Adder, halfWidth fixed.Int26_6, pivot, n1 fixed.Point26_6) { + e := pRot90CCW(n1) + side := pivot.Add(e) + p.Add1(side.Sub(n1)) + p.Add1(side.Add(n1)) + p.Add1(pivot.Add(n1)) +} + +// RoundJoiner adds round joins to a stroked path. +var RoundJoiner Joiner = JoinerFunc(roundJoiner) + +func roundJoiner(lhs, rhs Adder, haflWidth fixed.Int26_6, pivot, n0, n1 fixed.Point26_6) { + dot := pDot(pRot90CW(n0), n1) + if dot >= 0 { + addArc(lhs, pivot, n0, n1) + rhs.Add1(pivot.Sub(n1)) + } else { + lhs.Add1(pivot.Add(n1)) + addArc(rhs, pivot, pNeg(n0), pNeg(n1)) + } +} + +// BevelJoiner adds bevel joins to a stroked path. +var BevelJoiner Joiner = JoinerFunc(bevelJoiner) + +func bevelJoiner(lhs, rhs Adder, haflWidth fixed.Int26_6, pivot, n0, n1 fixed.Point26_6) { + lhs.Add1(pivot.Add(n1)) + rhs.Add1(pivot.Sub(n1)) +} + +// addArc adds a circular arc from pivot+n0 to pivot+n1 to p. The shorter of +// the two possible arcs is taken, i.e. the one spanning <= 180 degrees. The +// two vectors n0 and n1 must be of equal length. +func addArc(p Adder, pivot, n0, n1 fixed.Point26_6) { + // r2 is the square of the length of n0. + r2 := pDot(n0, n0) + if r2 < epsilon { + // The arc radius is so small that we collapse to a straight line. + p.Add1(pivot.Add(n1)) + return + } + // We approximate the arc by 0, 1, 2 or 3 45-degree quadratic segments plus + // a final quadratic segment from s to n1. Each 45-degree segment has + // control points {1, 0}, {1, tan(π/8)} and {1/√2, 1/√2} suitably scaled, + // rotated and translated. tan(π/8) is approximately 106/256. + const tpo8 = 106 + var s fixed.Point26_6 + // We determine which octant the angle between n0 and n1 is in via three + // dot products. m0, m1 and m2 are n0 rotated clockwise by 45, 90 and 135 + // degrees. + m0 := pRot45CW(n0) + m1 := pRot90CW(n0) + m2 := pRot90CW(m0) + if pDot(m1, n1) >= 0 { + if pDot(n0, n1) >= 0 { + if pDot(m2, n1) <= 0 { + // n1 is between 0 and 45 degrees clockwise of n0. + s = n0 + } else { + // n1 is between 45 and 90 degrees clockwise of n0. + p.Add2(pivot.Add(n0).Add(m1.Mul(tpo8)), pivot.Add(m0)) + s = m0 + } + } else { + pm1, n0t := pivot.Add(m1), n0.Mul(tpo8) + p.Add2(pivot.Add(n0).Add(m1.Mul(tpo8)), pivot.Add(m0)) + p.Add2(pm1.Add(n0t), pm1) + if pDot(m0, n1) >= 0 { + // n1 is between 90 and 135 degrees clockwise of n0. + s = m1 + } else { + // n1 is between 135 and 180 degrees clockwise of n0. + p.Add2(pm1.Sub(n0t), pivot.Add(m2)) + s = m2 + } + } + } else { + if pDot(n0, n1) >= 0 { + if pDot(m0, n1) >= 0 { + // n1 is between 0 and 45 degrees counter-clockwise of n0. + s = n0 + } else { + // n1 is between 45 and 90 degrees counter-clockwise of n0. + p.Add2(pivot.Add(n0).Sub(m1.Mul(tpo8)), pivot.Sub(m2)) + s = pNeg(m2) + } + } else { + pm1, n0t := pivot.Sub(m1), n0.Mul(tpo8) + p.Add2(pivot.Add(n0).Sub(m1.Mul(tpo8)), pivot.Sub(m2)) + p.Add2(pm1.Add(n0t), pm1) + if pDot(m2, n1) <= 0 { + // n1 is between 90 and 135 degrees counter-clockwise of n0. + s = pNeg(m1) + } else { + // n1 is between 135 and 180 degrees counter-clockwise of n0. + p.Add2(pm1.Sub(n0t), pivot.Sub(m0)) + s = pNeg(m0) + } + } + } + // The final quadratic segment has two endpoints s and n1 and the middle + // control point is a multiple of s.Add(n1), i.e. it is on the angle + // bisector of those two points. The multiple ranges between 128/256 and + // 150/256 as the angle between s and n1 ranges between 0 and 45 degrees. + // + // When the angle is 0 degrees (i.e. s and n1 are coincident) then + // s.Add(n1) is twice s and so the middle control point of the degenerate + // quadratic segment should be half s.Add(n1), and half = 128/256. + // + // When the angle is 45 degrees then 150/256 is the ratio of the lengths of + // the two vectors {1, tan(π/8)} and {1 + 1/√2, 1/√2}. + // + // d is the normalized dot product between s and n1. Since the angle ranges + // between 0 and 45 degrees then d ranges between 256/256 and 181/256. + d := 256 * pDot(s, n1) / r2 + multiple := fixed.Int26_6(150-(150-128)*(d-181)/(256-181)) >> 2 + p.Add2(pivot.Add(s.Add(n1).Mul(multiple)), pivot.Add(n1)) +} + +// midpoint returns the midpoint of two Points. +func midpoint(a, b fixed.Point26_6) fixed.Point26_6 { + return fixed.Point26_6{(a.X + b.X) / 2, (a.Y + b.Y) / 2} +} + +// angleGreaterThan45 returns whether the angle between two vectors is more +// than 45 degrees. +func angleGreaterThan45(v0, v1 fixed.Point26_6) bool { + v := pRot45CCW(v0) + return pDot(v, v1) < 0 || pDot(pRot90CW(v), v1) < 0 +} + +// interpolate returns the point (1-t)*a + t*b. +func interpolate(a, b fixed.Point26_6, t fixed.Int52_12) fixed.Point26_6 { + s := 1<<12 - t + x := s*fixed.Int52_12(a.X) + t*fixed.Int52_12(b.X) + y := s*fixed.Int52_12(a.Y) + t*fixed.Int52_12(b.Y) + return fixed.Point26_6{fixed.Int26_6(x >> 12), fixed.Int26_6(y >> 12)} +} + +// curviest2 returns the value of t for which the quadratic parametric curve +// (1-t)²*a + 2*t*(1-t).b + t²*c has maximum curvature. +// +// The curvature of the parametric curve f(t) = (x(t), y(t)) is +// |x′y″-y′x″| / (x′²+y′²)^(3/2). +// +// Let d = b-a and e = c-2*b+a, so that f′(t) = 2*d+2*e*t and f″(t) = 2*e. +// The curvature's numerator is (2*dx+2*ex*t)*(2*ey)-(2*dy+2*ey*t)*(2*ex), +// which simplifies to 4*dx*ey-4*dy*ex, which is constant with respect to t. +// +// Thus, curvature is extreme where the denominator is extreme, i.e. where +// (x′²+y′²) is extreme. The first order condition is that +// 2*x′*x″+2*y′*y″ = 0, or (dx+ex*t)*ex + (dy+ey*t)*ey = 0. +// Solving for t gives t = -(dx*ex+dy*ey) / (ex*ex+ey*ey). +func curviest2(a, b, c fixed.Point26_6) fixed.Int52_12 { + dx := int64(b.X - a.X) + dy := int64(b.Y - a.Y) + ex := int64(c.X - 2*b.X + a.X) + ey := int64(c.Y - 2*b.Y + a.Y) + if ex == 0 && ey == 0 { + return 2048 + } + return fixed.Int52_12(-4096 * (dx*ex + dy*ey) / (ex*ex + ey*ey)) +} + +// A stroker holds state for stroking a path. +type stroker struct { + // p is the destination that records the stroked path. + p Adder + // u is the half-width of the stroke. + u fixed.Int26_6 + // cr and jr specify how to end and connect path segments. + cr Capper + jr Joiner + // r is the reverse path. Stroking a path involves constructing two + // parallel paths 2*u apart. The first path is added immediately to p, + // the second path is accumulated in r and eventually added in reverse. + r Path + // a is the most recent segment point. anorm is the segment normal of + // length u at that point. + a, anorm fixed.Point26_6 +} + +// addNonCurvy2 adds a quadratic segment to the stroker, where the segment +// defined by (k.a, b, c) achieves maximum curvature at either k.a or c. +func (k *stroker) addNonCurvy2(b, c fixed.Point26_6) { + // We repeatedly divide the segment at its middle until it is straight + // enough to approximate the stroke by just translating the control points. + // ds and ps are stacks of depths and points. t is the top of the stack. + const maxDepth = 5 + var ( + ds [maxDepth + 1]int + ps [2*maxDepth + 3]fixed.Point26_6 + t int + ) + // Initially the ps stack has one quadratic segment of depth zero. + ds[0] = 0 + ps[2] = k.a + ps[1] = b + ps[0] = c + anorm := k.anorm + var cnorm fixed.Point26_6 + + for { + depth := ds[t] + a := ps[2*t+2] + b := ps[2*t+1] + c := ps[2*t+0] + ab := b.Sub(a) + bc := c.Sub(b) + abIsSmall := pDot(ab, ab) < fixed.Int52_12(1<<12) + bcIsSmall := pDot(bc, bc) < fixed.Int52_12(1<<12) + if abIsSmall && bcIsSmall { + // Approximate the segment by a circular arc. + cnorm = pRot90CCW(pNorm(bc, k.u)) + mac := midpoint(a, c) + addArc(k.p, mac, anorm, cnorm) + addArc(&k.r, mac, pNeg(anorm), pNeg(cnorm)) + } else if depth < maxDepth && angleGreaterThan45(ab, bc) { + // Divide the segment in two and push both halves on the stack. + mab := midpoint(a, b) + mbc := midpoint(b, c) + t++ + ds[t+0] = depth + 1 + ds[t-1] = depth + 1 + ps[2*t+2] = a + ps[2*t+1] = mab + ps[2*t+0] = midpoint(mab, mbc) + ps[2*t-1] = mbc + continue + } else { + // Translate the control points. + bnorm := pRot90CCW(pNorm(c.Sub(a), k.u)) + cnorm = pRot90CCW(pNorm(bc, k.u)) + k.p.Add2(b.Add(bnorm), c.Add(cnorm)) + k.r.Add2(b.Sub(bnorm), c.Sub(cnorm)) + } + if t == 0 { + k.a, k.anorm = c, cnorm + return + } + t-- + anorm = cnorm + } + panic("unreachable") +} + +// Add1 adds a linear segment to the stroker. +func (k *stroker) Add1(b fixed.Point26_6) { + bnorm := pRot90CCW(pNorm(b.Sub(k.a), k.u)) + if len(k.r) == 0 { + k.p.Start(k.a.Add(bnorm)) + k.r.Start(k.a.Sub(bnorm)) + } else { + k.jr.Join(k.p, &k.r, k.u, k.a, k.anorm, bnorm) + } + k.p.Add1(b.Add(bnorm)) + k.r.Add1(b.Sub(bnorm)) + k.a, k.anorm = b, bnorm +} + +// Add2 adds a quadratic segment to the stroker. +func (k *stroker) Add2(b, c fixed.Point26_6) { + ab := b.Sub(k.a) + bc := c.Sub(b) + abnorm := pRot90CCW(pNorm(ab, k.u)) + if len(k.r) == 0 { + k.p.Start(k.a.Add(abnorm)) + k.r.Start(k.a.Sub(abnorm)) + } else { + k.jr.Join(k.p, &k.r, k.u, k.a, k.anorm, abnorm) + } + + // Approximate nearly-degenerate quadratics by linear segments. + abIsSmall := pDot(ab, ab) < epsilon + bcIsSmall := pDot(bc, bc) < epsilon + if abIsSmall || bcIsSmall { + acnorm := pRot90CCW(pNorm(c.Sub(k.a), k.u)) + k.p.Add1(c.Add(acnorm)) + k.r.Add1(c.Sub(acnorm)) + k.a, k.anorm = c, acnorm + return + } + + // The quadratic segment (k.a, b, c) has a point of maximum curvature. + // If this occurs at an end point, we process the segment as a whole. + t := curviest2(k.a, b, c) + if t <= 0 || 4096 <= t { + k.addNonCurvy2(b, c) + return + } + + // Otherwise, we perform a de Casteljau decomposition at the point of + // maximum curvature and process the two straighter parts. + mab := interpolate(k.a, b, t) + mbc := interpolate(b, c, t) + mabc := interpolate(mab, mbc, t) + + // If the vectors ab and bc are close to being in opposite directions, + // then the decomposition can become unstable, so we approximate the + // quadratic segment by two linear segments joined by an arc. + bcnorm := pRot90CCW(pNorm(bc, k.u)) + if pDot(abnorm, bcnorm) < -fixed.Int52_12(k.u)*fixed.Int52_12(k.u)*2047/2048 { + pArc := pDot(abnorm, bc) < 0 + + k.p.Add1(mabc.Add(abnorm)) + if pArc { + z := pRot90CW(abnorm) + addArc(k.p, mabc, abnorm, z) + addArc(k.p, mabc, z, bcnorm) + } + k.p.Add1(mabc.Add(bcnorm)) + k.p.Add1(c.Add(bcnorm)) + + k.r.Add1(mabc.Sub(abnorm)) + if !pArc { + z := pRot90CW(abnorm) + addArc(&k.r, mabc, pNeg(abnorm), z) + addArc(&k.r, mabc, z, pNeg(bcnorm)) + } + k.r.Add1(mabc.Sub(bcnorm)) + k.r.Add1(c.Sub(bcnorm)) + + k.a, k.anorm = c, bcnorm + return + } + + // Process the decomposed parts. + k.addNonCurvy2(mab, mabc) + k.addNonCurvy2(mbc, c) +} + +// Add3 adds a cubic segment to the stroker. +func (k *stroker) Add3(b, c, d fixed.Point26_6) { + panic("freetype/raster: stroke unimplemented for cubic segments") +} + +// stroke adds the stroked Path q to p, where q consists of exactly one curve. +func (k *stroker) stroke(q Path) { + // Stroking is implemented by deriving two paths each k.u apart from q. + // The left-hand-side path is added immediately to k.p; the right-hand-side + // path is accumulated in k.r. Once we've finished adding the LHS to k.p, + // we add the RHS in reverse order. + k.r = make(Path, 0, len(q)) + k.a = fixed.Point26_6{q[1], q[2]} + for i := 4; i < len(q); { + switch q[i] { + case 1: + k.Add1( + fixed.Point26_6{q[i+1], q[i+2]}, + ) + i += 4 + case 2: + k.Add2( + fixed.Point26_6{q[i+1], q[i+2]}, + fixed.Point26_6{q[i+3], q[i+4]}, + ) + i += 6 + case 3: + k.Add3( + fixed.Point26_6{q[i+1], q[i+2]}, + fixed.Point26_6{q[i+3], q[i+4]}, + fixed.Point26_6{q[i+5], q[i+6]}, + ) + i += 8 + default: + panic("freetype/raster: bad path") + } + } + if len(k.r) == 0 { + return + } + // TODO(nigeltao): if q is a closed curve then we should join the first and + // last segments instead of capping them. + k.cr.Cap(k.p, k.u, q.lastPoint(), pNeg(k.anorm)) + addPathReversed(k.p, k.r) + pivot := q.firstPoint() + k.cr.Cap(k.p, k.u, pivot, pivot.Sub(fixed.Point26_6{k.r[1], k.r[2]})) +} + +// Stroke adds q stroked with the given width to p. The result is typically +// self-intersecting and should be rasterized with UseNonZeroWinding. +// cr and jr may be nil, which defaults to a RoundCapper or RoundJoiner. +func Stroke(p Adder, q Path, width fixed.Int26_6, cr Capper, jr Joiner) { + if len(q) == 0 { + return + } + if cr == nil { + cr = RoundCapper + } + if jr == nil { + jr = RoundJoiner + } + if q[0] != 0 { + panic("freetype/raster: bad path") + } + s := stroker{p: p, u: width / 2, cr: cr, jr: jr} + i := 0 + for j := 4; j < len(q); { + switch q[j] { + case 0: + s.stroke(q[i:j]) + i, j = j, j+4 + case 1: + j += 4 + case 2: + j += 6 + case 3: + j += 8 + default: + panic("freetype/raster: bad path") + } + } + s.stroke(q[i:]) +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/truetype/face.go b/Godeps/_workspace/src/github.com/golang/freetype/truetype/face.go new file mode 100644 index 00000000..d64a014c --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/truetype/face.go @@ -0,0 +1,495 @@ +// Copyright 2015 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package truetype + +import ( + "image" + + "github.com/golang/freetype/raster" + "golang.org/x/image/font" + "golang.org/x/image/math/fixed" +) + +func powerOf2(i int) bool { + return i != 0 && (i&(i-1)) == 0 +} + +// Options are optional arguments to NewFace. +type Options struct { + // Size is the font size in points, as in "a 10 point font size". + // + // A zero value means to use a 12 point font size. + Size float64 + + // DPI is the dots-per-inch resolution. + // + // A zero value means to use 72 DPI. + DPI float64 + + // Hinting is how to quantize the glyph nodes. + // + // A zero value means to use no hinting. + Hinting font.Hinting + + // GlyphCacheEntries is the number of entries in the glyph mask image + // cache. + // + // If non-zero, it must be a power of 2. + // + // A zero value means to use 512 entries. + GlyphCacheEntries int + + // SubPixelsX is the number of sub-pixel locations a glyph's dot is + // quantized to, in the horizontal direction. For example, a value of 8 + // means that the dot is quantized to 1/8th of a pixel. This quantization + // only affects the glyph mask image, not its bounding box or advance + // width. A higher value gives a more faithful glyph image, but reduces the + // effectiveness of the glyph cache. + // + // If non-zero, it must be a power of 2, and be between 1 and 64 inclusive. + // + // A zero value means to use 4 sub-pixel locations. + SubPixelsX int + + // SubPixelsY is the number of sub-pixel locations a glyph's dot is + // quantized to, in the vertical direction. For example, a value of 8 + // means that the dot is quantized to 1/8th of a pixel. This quantization + // only affects the glyph mask image, not its bounding box or advance + // width. A higher value gives a more faithful glyph image, but reduces the + // effectiveness of the glyph cache. + // + // If non-zero, it must be a power of 2, and be between 1 and 64 inclusive. + // + // A zero value means to use 1 sub-pixel location. + SubPixelsY int +} + +func (o *Options) size() float64 { + if o != nil && o.Size > 0 { + return o.Size + } + return 12 +} + +func (o *Options) dpi() float64 { + if o != nil && o.DPI > 0 { + return o.DPI + } + return 72 +} + +func (o *Options) hinting() font.Hinting { + if o != nil { + switch o.Hinting { + case font.HintingVertical, font.HintingFull: + // TODO: support vertical hinting. + return font.HintingFull + } + } + return font.HintingNone +} + +func (o *Options) glyphCacheEntries() int { + if o != nil && powerOf2(o.GlyphCacheEntries) { + return o.GlyphCacheEntries + } + // 512 is 128 * 4 * 1, which lets us cache 128 glyphs at 4 * 1 subpixel + // locations in the X and Y direction. + return 512 +} + +func (o *Options) subPixelsX() (value uint32, halfQuantum, mask fixed.Int26_6) { + if o != nil { + switch o.SubPixelsX { + case 1, 2, 4, 8, 16, 32, 64: + return subPixels(o.SubPixelsX) + } + } + // This default value of 4 isn't based on anything scientific, merely as + // small a number as possible that looks almost as good as no quantization, + // or returning subPixels(64). + return subPixels(4) +} + +func (o *Options) subPixelsY() (value uint32, halfQuantum, mask fixed.Int26_6) { + if o != nil { + switch o.SubPixelsX { + case 1, 2, 4, 8, 16, 32, 64: + return subPixels(o.SubPixelsX) + } + } + // This default value of 1 isn't based on anything scientific, merely that + // vertical sub-pixel glyph rendering is pretty rare. Baseline locations + // can usually afford to snap to the pixel grid, so the vertical direction + // doesn't have the deal with the horizontal's fractional advance widths. + return subPixels(1) +} + +// subPixels returns q and the bias and mask that leads to q quantized +// sub-pixel locations per full pixel. +// +// For example, q == 4 leads to a bias of 8 and a mask of 0xfffffff0, or -16, +// because we want to round fractions of fixed.Int26_6 as: +// - 0 to 7 rounds to 0. +// - 8 to 23 rounds to 16. +// - 24 to 39 rounds to 32. +// - 40 to 55 rounds to 48. +// - 56 to 63 rounds to 64. +// which means to add 8 and then bitwise-and with -16, in two's complement +// representation. +// +// When q == 1, we want bias == 32 and mask == -64. +// When q == 2, we want bias == 16 and mask == -32. +// When q == 4, we want bias == 8 and mask == -16. +// ... +// When q == 64, we want bias == 0 and mask == -1. (The no-op case). +// The pattern is clear. +func subPixels(q int) (value uint32, bias, mask fixed.Int26_6) { + return uint32(q), 32 / fixed.Int26_6(q), -64 / fixed.Int26_6(q) +} + +// glyphCacheEntry caches the arguments and return values of rasterize. +type glyphCacheEntry struct { + key glyphCacheKey + val glyphCacheVal +} + +type glyphCacheKey struct { + index Index + fx, fy uint8 +} + +type glyphCacheVal struct { + advanceWidth fixed.Int26_6 + offset image.Point + gw int + gh int +} + +type indexCacheEntry struct { + rune rune + index Index +} + +// NewFace returns a new font.Face for the given Font. +func NewFace(f *Font, opts *Options) font.Face { + a := &face{ + f: f, + hinting: opts.hinting(), + scale: fixed.Int26_6(0.5 + (opts.size() * opts.dpi() * 64 / 72)), + glyphCache: make([]glyphCacheEntry, opts.glyphCacheEntries()), + } + a.subPixelX, a.subPixelBiasX, a.subPixelMaskX = opts.subPixelsX() + a.subPixelY, a.subPixelBiasY, a.subPixelMaskY = opts.subPixelsY() + + // Fill the cache with invalid entries. Valid glyph cache entries have fx + // and fy in the range [0, 64). Valid index cache entries have rune >= 0. + for i := range a.glyphCache { + a.glyphCache[i].key.fy = 0xff + } + for i := range a.indexCache { + a.indexCache[i].rune = -1 + } + + // Set the rasterizer's bounds to be big enough to handle the largest glyph. + b := f.Bounds(a.scale) + xmin := +int(b.Min.X) >> 6 + ymin := -int(b.Max.Y) >> 6 + xmax := +int(b.Max.X+63) >> 6 + ymax := -int(b.Min.Y-63) >> 6 + a.maxw = xmax - xmin + a.maxh = ymax - ymin + a.masks = image.NewAlpha(image.Rect(0, 0, a.maxw, a.maxh*len(a.glyphCache))) + a.r.SetBounds(a.maxw, a.maxh) + a.p = facePainter{a} + + return a +} + +type face struct { + f *Font + hinting font.Hinting + scale fixed.Int26_6 + subPixelX uint32 + subPixelBiasX fixed.Int26_6 + subPixelMaskX fixed.Int26_6 + subPixelY uint32 + subPixelBiasY fixed.Int26_6 + subPixelMaskY fixed.Int26_6 + masks *image.Alpha + glyphCache []glyphCacheEntry + r raster.Rasterizer + p raster.Painter + paintOffset int + maxw int + maxh int + glyphBuf GlyphBuf + indexCache [indexCacheLen]indexCacheEntry + + // TODO: clip rectangle? +} + +const indexCacheLen = 256 + +func (a *face) index(r rune) Index { + const mask = indexCacheLen - 1 + c := &a.indexCache[r&mask] + if c.rune == r { + return c.index + } + i := a.f.Index(r) + c.rune = r + c.index = i + return i +} + +// Close satisfies the font.Face interface. +func (a *face) Close() error { return nil } + +// Kern satisfies the font.Face interface. +func (a *face) Kern(r0, r1 rune) fixed.Int26_6 { + i0 := a.index(r0) + i1 := a.index(r1) + kern := a.f.Kern(a.scale, i0, i1) + if a.hinting != font.HintingNone { + kern = (kern + 32) &^ 63 + } + return kern +} + +// Glyph satisfies the font.Face interface. +func (a *face) Glyph(dot fixed.Point26_6, r rune) ( + dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) { + + // Quantize to the sub-pixel granularity. + dotX := (dot.X + a.subPixelBiasX) & a.subPixelMaskX + dotY := (dot.Y + a.subPixelBiasY) & a.subPixelMaskY + + // Split the coordinates into their integer and fractional parts. + ix, fx := int(dotX>>6), dotX&0x3f + iy, fy := int(dotY>>6), dotY&0x3f + + index := a.index(r) + cIndex := uint32(index) + cIndex = cIndex*a.subPixelX - uint32(fx/a.subPixelMaskX) + cIndex = cIndex*a.subPixelY - uint32(fy/a.subPixelMaskY) + cIndex &= uint32(len(a.glyphCache) - 1) + a.paintOffset = a.maxh * int(cIndex) + k := glyphCacheKey{ + index: index, + fx: uint8(fx), + fy: uint8(fy), + } + var v glyphCacheVal + if a.glyphCache[cIndex].key != k { + var ok bool + v, ok = a.rasterize(index, fx, fy) + if !ok { + return image.Rectangle{}, nil, image.Point{}, 0, false + } + a.glyphCache[cIndex] = glyphCacheEntry{k, v} + } else { + v = a.glyphCache[cIndex].val + } + + dr.Min = image.Point{ + X: ix + v.offset.X, + Y: iy + v.offset.Y, + } + dr.Max = image.Point{ + X: dr.Min.X + v.gw, + Y: dr.Min.Y + v.gh, + } + return dr, a.masks, image.Point{Y: a.paintOffset}, v.advanceWidth, true +} + +func (a *face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) { + if err := a.glyphBuf.Load(a.f, a.scale, a.index(r), a.hinting); err != nil { + return fixed.Rectangle26_6{}, 0, false + } + xmin := +a.glyphBuf.Bounds.Min.X + ymin := -a.glyphBuf.Bounds.Max.Y + xmax := +a.glyphBuf.Bounds.Max.X + ymax := -a.glyphBuf.Bounds.Min.Y + if xmin > xmax || ymin > ymax { + return fixed.Rectangle26_6{}, 0, false + } + return fixed.Rectangle26_6{ + Min: fixed.Point26_6{ + X: xmin, + Y: ymin, + }, + Max: fixed.Point26_6{ + X: xmax, + Y: ymax, + }, + }, a.glyphBuf.AdvanceWidth, true +} + +func (a *face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) { + if err := a.glyphBuf.Load(a.f, a.scale, a.index(r), a.hinting); err != nil { + return 0, false + } + return a.glyphBuf.AdvanceWidth, true +} + +// rasterize returns the advance width, integer-pixel offset to render at, and +// the width and height of the given glyph at the given sub-pixel offsets. +// +// The 26.6 fixed point arguments fx and fy must be in the range [0, 1). +func (a *face) rasterize(index Index, fx, fy fixed.Int26_6) (v glyphCacheVal, ok bool) { + if err := a.glyphBuf.Load(a.f, a.scale, index, a.hinting); err != nil { + return glyphCacheVal{}, false + } + // Calculate the integer-pixel bounds for the glyph. + xmin := int(fx+a.glyphBuf.Bounds.Min.X) >> 6 + ymin := int(fy-a.glyphBuf.Bounds.Max.Y) >> 6 + xmax := int(fx+a.glyphBuf.Bounds.Max.X+0x3f) >> 6 + ymax := int(fy-a.glyphBuf.Bounds.Min.Y+0x3f) >> 6 + if xmin > xmax || ymin > ymax { + return glyphCacheVal{}, false + } + // A TrueType's glyph's nodes can have negative co-ordinates, but the + // rasterizer clips anything left of x=0 or above y=0. xmin and ymin are + // the pixel offsets, based on the font's FUnit metrics, that let a + // negative co-ordinate in TrueType space be non-negative in rasterizer + // space. xmin and ymin are typically <= 0. + fx -= fixed.Int26_6(xmin << 6) + fy -= fixed.Int26_6(ymin << 6) + // Rasterize the glyph's vectors. + a.r.Clear() + pixOffset := a.paintOffset * a.maxw + clear(a.masks.Pix[pixOffset : pixOffset+a.maxw*a.maxh]) + e0 := 0 + for _, e1 := range a.glyphBuf.Ends { + a.drawContour(a.glyphBuf.Points[e0:e1], fx, fy) + e0 = e1 + } + a.r.Rasterize(a.p) + return glyphCacheVal{ + a.glyphBuf.AdvanceWidth, + image.Point{xmin, ymin}, + xmax - xmin, + ymax - ymin, + }, true +} + +func clear(pix []byte) { + for i := range pix { + pix[i] = 0 + } +} + +// drawContour draws the given closed contour with the given offset. +func (a *face) drawContour(ps []Point, dx, dy fixed.Int26_6) { + if len(ps) == 0 { + return + } + + // The low bit of each point's Flags value is whether the point is on the + // curve. Truetype fonts only have quadratic Bézier curves, not cubics. + // Thus, two consecutive off-curve points imply an on-curve point in the + // middle of those two. + // + // See http://chanae.walon.org/pub/ttf/ttf_glyphs.htm for more details. + + // ps[0] is a truetype.Point measured in FUnits and positive Y going + // upwards. start is the same thing measured in fixed point units and + // positive Y going downwards, and offset by (dx, dy). + start := fixed.Point26_6{ + X: dx + ps[0].X, + Y: dy - ps[0].Y, + } + var others []Point + if ps[0].Flags&0x01 != 0 { + others = ps[1:] + } else { + last := fixed.Point26_6{ + X: dx + ps[len(ps)-1].X, + Y: dy - ps[len(ps)-1].Y, + } + if ps[len(ps)-1].Flags&0x01 != 0 { + start = last + others = ps[:len(ps)-1] + } else { + start = fixed.Point26_6{ + X: (start.X + last.X) / 2, + Y: (start.Y + last.Y) / 2, + } + others = ps + } + } + a.r.Start(start) + q0, on0 := start, true + for _, p := range others { + q := fixed.Point26_6{ + X: dx + p.X, + Y: dy - p.Y, + } + on := p.Flags&0x01 != 0 + if on { + if on0 { + a.r.Add1(q) + } else { + a.r.Add2(q0, q) + } + } else { + if on0 { + // No-op. + } else { + mid := fixed.Point26_6{ + X: (q0.X + q.X) / 2, + Y: (q0.Y + q.Y) / 2, + } + a.r.Add2(q0, mid) + } + } + q0, on0 = q, on + } + // Close the curve. + if on0 { + a.r.Add1(start) + } else { + a.r.Add2(q0, start) + } +} + +// facePainter is like a raster.AlphaSrcPainter, with an additional Y offset +// (face.paintOffset) to the painted spans. +type facePainter struct { + a *face +} + +func (p facePainter) Paint(ss []raster.Span, done bool) { + m := p.a.masks + b := m.Bounds() + b.Min.Y = p.a.paintOffset + b.Max.Y = p.a.paintOffset + p.a.maxh + for _, s := range ss { + s.Y += p.a.paintOffset + if s.Y < b.Min.Y { + continue + } + if s.Y >= b.Max.Y { + return + } + if s.X0 < b.Min.X { + s.X0 = b.Min.X + } + if s.X1 > b.Max.X { + s.X1 = b.Max.X + } + if s.X0 >= s.X1 { + continue + } + base := (s.Y-m.Rect.Min.Y)*m.Stride - m.Rect.Min.X + p := m.Pix[base+s.X0 : base+s.X1] + color := uint8(s.Alpha >> 8) + for i := range p { + p[i] = color + } + } +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/truetype/face_test.go b/Godeps/_workspace/src/github.com/golang/freetype/truetype/face_test.go new file mode 100644 index 00000000..856581df --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/truetype/face_test.go @@ -0,0 +1,48 @@ +// Copyright 2015 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package truetype + +import ( + "image" + "image/draw" + "io/ioutil" + "strings" + "testing" + + "golang.org/x/image/font" + "golang.org/x/image/math/fixed" +) + +func BenchmarkDrawString(b *testing.B) { + data, err := ioutil.ReadFile("../licenses/gpl.txt") + if err != nil { + b.Fatal(err) + } + lines := strings.Split(string(data), "\n") + data, err = ioutil.ReadFile("../testdata/luxisr.ttf") + if err != nil { + b.Fatal(err) + } + f, err := Parse(data) + if err != nil { + b.Fatal(err) + } + dst := image.NewRGBA(image.Rect(0, 0, 800, 600)) + draw.Draw(dst, dst.Bounds(), image.White, image.ZP, draw.Src) + d := &font.Drawer{ + Dst: dst, + Src: image.Black, + Face: NewFace(f, nil), + } + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + for j, line := range lines { + d.Dot = fixed.P(0, (j*16)%600) + d.DrawString(line) + } + } +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/truetype/glyph.go b/Godeps/_workspace/src/github.com/golang/freetype/truetype/glyph.go new file mode 100644 index 00000000..c2935a58 --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/truetype/glyph.go @@ -0,0 +1,517 @@ +// Copyright 2010 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package truetype + +import ( + "golang.org/x/image/font" + "golang.org/x/image/math/fixed" +) + +// TODO: implement VerticalHinting. + +// A Point is a co-ordinate pair plus whether it is 'on' a contour or an 'off' +// control point. +type Point struct { + X, Y fixed.Int26_6 + // The Flags' LSB means whether or not this Point is 'on' the contour. + // Other bits are reserved for internal use. + Flags uint32 +} + +// A GlyphBuf holds a glyph's contours. A GlyphBuf can be re-used to load a +// series of glyphs from a Font. +type GlyphBuf struct { + // AdvanceWidth is the glyph's advance width. + AdvanceWidth fixed.Int26_6 + // Bounds is the glyph's bounding box. + Bounds fixed.Rectangle26_6 + // Points contains all Points from all contours of the glyph. If hinting + // was used to load a glyph then Unhinted contains those Points before they + // were hinted, and InFontUnits contains those Points before they were + // hinted and scaled. + Points, Unhinted, InFontUnits []Point + // Ends is the point indexes of the end point of each contour. The length + // of Ends is the number of contours in the glyph. The i'th contour + // consists of points Points[Ends[i-1]:Ends[i]], where Ends[-1] is + // interpreted to mean zero. + Ends []int + + font *Font + scale fixed.Int26_6 + hinting font.Hinting + hinter hinter + // phantomPoints are the co-ordinates of the synthetic phantom points + // used for hinting and bounding box calculations. + phantomPoints [4]Point + // pp1x is the X co-ordinate of the first phantom point. The '1' is + // using 1-based indexing; pp1x is almost always phantomPoints[0].X. + // TODO: eliminate this and consistently use phantomPoints[0].X. + pp1x fixed.Int26_6 + // metricsSet is whether the glyph's metrics have been set yet. For a + // compound glyph, a sub-glyph may override the outer glyph's metrics. + metricsSet bool + // tmp is a scratch buffer. + tmp []Point +} + +// Flags for decoding a glyph's contours. These flags are documented at +// http://developer.apple.com/fonts/TTRefMan/RM06/Chap6glyf.html. +const ( + flagOnCurve = 1 << iota + flagXShortVector + flagYShortVector + flagRepeat + flagPositiveXShortVector + flagPositiveYShortVector + + // The remaining flags are for internal use. + flagTouchedX + flagTouchedY +) + +// The same flag bits (0x10 and 0x20) are overloaded to have two meanings, +// dependent on the value of the flag{X,Y}ShortVector bits. +const ( + flagThisXIsSame = flagPositiveXShortVector + flagThisYIsSame = flagPositiveYShortVector +) + +// Load loads a glyph's contours from a Font, overwriting any previously loaded +// contours for this GlyphBuf. scale is the number of 26.6 fixed point units in +// 1 em, i is the glyph index, and h is the hinting policy. +func (g *GlyphBuf) Load(f *Font, scale fixed.Int26_6, i Index, h font.Hinting) error { + g.Points = g.Points[:0] + g.Unhinted = g.Unhinted[:0] + g.InFontUnits = g.InFontUnits[:0] + g.Ends = g.Ends[:0] + g.font = f + g.hinting = h + g.scale = scale + g.pp1x = 0 + g.phantomPoints = [4]Point{} + g.metricsSet = false + + if h != font.HintingNone { + if err := g.hinter.init(f, scale); err != nil { + return err + } + } + if err := g.load(0, i, true); err != nil { + return err + } + // TODO: this selection of either g.pp1x or g.phantomPoints[0].X isn't ideal, + // and should be cleaned up once we have all the testScaling tests passing, + // plus additional tests for Freetype-Go's bounding boxes matching C Freetype's. + pp1x := g.pp1x + if h != font.HintingNone { + pp1x = g.phantomPoints[0].X + } + if pp1x != 0 { + for i := range g.Points { + g.Points[i].X -= pp1x + } + } + + advanceWidth := g.phantomPoints[1].X - g.phantomPoints[0].X + if h != font.HintingNone { + if len(f.hdmx) >= 8 { + if n := u32(f.hdmx, 4); n > 3+uint32(i) { + for hdmx := f.hdmx[8:]; uint32(len(hdmx)) >= n; hdmx = hdmx[n:] { + if fixed.Int26_6(hdmx[0]) == scale>>6 { + advanceWidth = fixed.Int26_6(hdmx[2+i]) << 6 + break + } + } + } + } + advanceWidth = (advanceWidth + 32) &^ 63 + } + g.AdvanceWidth = advanceWidth + + // Set g.Bounds to the 'control box', which is the bounding box of the + // Bézier curves' control points. This is easier to calculate, no smaller + // than and often equal to the tightest possible bounding box of the curves + // themselves. This approach is what C Freetype does. We can't just scale + // the nominal bounding box in the glyf data as the hinting process and + // phantom point adjustment may move points outside of that box. + if len(g.Points) == 0 { + g.Bounds = fixed.Rectangle26_6{} + } else { + p := g.Points[0] + g.Bounds.Min.X = p.X + g.Bounds.Max.X = p.X + g.Bounds.Min.Y = p.Y + g.Bounds.Max.Y = p.Y + for _, p := range g.Points[1:] { + if g.Bounds.Min.X > p.X { + g.Bounds.Min.X = p.X + } else if g.Bounds.Max.X < p.X { + g.Bounds.Max.X = p.X + } + if g.Bounds.Min.Y > p.Y { + g.Bounds.Min.Y = p.Y + } else if g.Bounds.Max.Y < p.Y { + g.Bounds.Max.Y = p.Y + } + } + // Snap the box to the grid, if hinting is on. + if h != font.HintingNone { + g.Bounds.Min.X &^= 63 + g.Bounds.Min.Y &^= 63 + g.Bounds.Max.X += 63 + g.Bounds.Max.X &^= 63 + g.Bounds.Max.Y += 63 + g.Bounds.Max.Y &^= 63 + } + } + return nil +} + +func (g *GlyphBuf) load(recursion uint32, i Index, useMyMetrics bool) (err error) { + // The recursion limit here is arbitrary, but defends against malformed glyphs. + if recursion >= 32 { + return UnsupportedError("excessive compound glyph recursion") + } + // Find the relevant slice of g.font.glyf. + var g0, g1 uint32 + if g.font.locaOffsetFormat == locaOffsetFormatShort { + g0 = 2 * uint32(u16(g.font.loca, 2*int(i))) + g1 = 2 * uint32(u16(g.font.loca, 2*int(i)+2)) + } else { + g0 = u32(g.font.loca, 4*int(i)) + g1 = u32(g.font.loca, 4*int(i)+4) + } + + // Decode the contour count and nominal bounding box, from the first + // 10 bytes of the glyf data. boundsYMin and boundsXMax, at offsets 4 + // and 6, are unused. + glyf, ne, boundsXMin, boundsYMax := []byte(nil), 0, fixed.Int26_6(0), fixed.Int26_6(0) + if g0+10 <= g1 { + glyf = g.font.glyf[g0:g1] + ne = int(int16(u16(glyf, 0))) + boundsXMin = fixed.Int26_6(int16(u16(glyf, 2))) + boundsYMax = fixed.Int26_6(int16(u16(glyf, 8))) + } + + // Create the phantom points. + uhm, pp1x := g.font.unscaledHMetric(i), fixed.Int26_6(0) + uvm := g.font.unscaledVMetric(i, boundsYMax) + g.phantomPoints = [4]Point{ + {X: boundsXMin - uhm.LeftSideBearing}, + {X: boundsXMin - uhm.LeftSideBearing + uhm.AdvanceWidth}, + {X: uhm.AdvanceWidth / 2, Y: boundsYMax + uvm.TopSideBearing}, + {X: uhm.AdvanceWidth / 2, Y: boundsYMax + uvm.TopSideBearing - uvm.AdvanceHeight}, + } + if len(glyf) == 0 { + g.addPhantomsAndScale(len(g.Points), len(g.Points), true, true) + copy(g.phantomPoints[:], g.Points[len(g.Points)-4:]) + g.Points = g.Points[:len(g.Points)-4] + return nil + } + + // Load and hint the contours. + if ne < 0 { + if ne != -1 { + // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6glyf.html says that + // "the values -2, -3, and so forth, are reserved for future use." + return UnsupportedError("negative number of contours") + } + pp1x = g.font.scale(g.scale * (boundsXMin - uhm.LeftSideBearing)) + if err := g.loadCompound(recursion, uhm, i, glyf, useMyMetrics); err != nil { + return err + } + } else { + np0, ne0 := len(g.Points), len(g.Ends) + program := g.loadSimple(glyf, ne) + g.addPhantomsAndScale(np0, np0, true, true) + pp1x = g.Points[len(g.Points)-4].X + if g.hinting != font.HintingNone { + if len(program) != 0 { + err := g.hinter.run( + program, + g.Points[np0:], + g.Unhinted[np0:], + g.InFontUnits[np0:], + g.Ends[ne0:], + ) + if err != nil { + return err + } + } + // Drop the four phantom points. + g.InFontUnits = g.InFontUnits[:len(g.InFontUnits)-4] + g.Unhinted = g.Unhinted[:len(g.Unhinted)-4] + } + if useMyMetrics { + copy(g.phantomPoints[:], g.Points[len(g.Points)-4:]) + } + g.Points = g.Points[:len(g.Points)-4] + if np0 != 0 { + // The hinting program expects the []Ends values to be indexed + // relative to the inner glyph, not the outer glyph, so we delay + // adding np0 until after the hinting program (if any) has run. + for i := ne0; i < len(g.Ends); i++ { + g.Ends[i] += np0 + } + } + } + if useMyMetrics && !g.metricsSet { + g.metricsSet = true + g.pp1x = pp1x + } + return nil +} + +// loadOffset is the initial offset for loadSimple and loadCompound. The first +// 10 bytes are the number of contours and the bounding box. +const loadOffset = 10 + +func (g *GlyphBuf) loadSimple(glyf []byte, ne int) (program []byte) { + offset := loadOffset + for i := 0; i < ne; i++ { + g.Ends = append(g.Ends, 1+int(u16(glyf, offset))) + offset += 2 + } + + // Note the TrueType hinting instructions. + instrLen := int(u16(glyf, offset)) + offset += 2 + program = glyf[offset : offset+instrLen] + offset += instrLen + + np0 := len(g.Points) + np1 := np0 + int(g.Ends[len(g.Ends)-1]) + + // Decode the flags. + for i := np0; i < np1; { + c := uint32(glyf[offset]) + offset++ + g.Points = append(g.Points, Point{Flags: c}) + i++ + if c&flagRepeat != 0 { + count := glyf[offset] + offset++ + for ; count > 0; count-- { + g.Points = append(g.Points, Point{Flags: c}) + i++ + } + } + } + + // Decode the co-ordinates. + var x int16 + for i := np0; i < np1; i++ { + f := g.Points[i].Flags + if f&flagXShortVector != 0 { + dx := int16(glyf[offset]) + offset++ + if f&flagPositiveXShortVector == 0 { + x -= dx + } else { + x += dx + } + } else if f&flagThisXIsSame == 0 { + x += int16(u16(glyf, offset)) + offset += 2 + } + g.Points[i].X = fixed.Int26_6(x) + } + var y int16 + for i := np0; i < np1; i++ { + f := g.Points[i].Flags + if f&flagYShortVector != 0 { + dy := int16(glyf[offset]) + offset++ + if f&flagPositiveYShortVector == 0 { + y -= dy + } else { + y += dy + } + } else if f&flagThisYIsSame == 0 { + y += int16(u16(glyf, offset)) + offset += 2 + } + g.Points[i].Y = fixed.Int26_6(y) + } + + return program +} + +func (g *GlyphBuf) loadCompound(recursion uint32, uhm HMetric, i Index, + glyf []byte, useMyMetrics bool) error { + + // Flags for decoding a compound glyph. These flags are documented at + // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6glyf.html. + const ( + flagArg1And2AreWords = 1 << iota + flagArgsAreXYValues + flagRoundXYToGrid + flagWeHaveAScale + flagUnused + flagMoreComponents + flagWeHaveAnXAndYScale + flagWeHaveATwoByTwo + flagWeHaveInstructions + flagUseMyMetrics + flagOverlapCompound + ) + np0, ne0 := len(g.Points), len(g.Ends) + offset := loadOffset + for { + flags := u16(glyf, offset) + component := Index(u16(glyf, offset+2)) + dx, dy, transform, hasTransform := fixed.Int26_6(0), fixed.Int26_6(0), [4]int16{}, false + if flags&flagArg1And2AreWords != 0 { + dx = fixed.Int26_6(int16(u16(glyf, offset+4))) + dy = fixed.Int26_6(int16(u16(glyf, offset+6))) + offset += 8 + } else { + dx = fixed.Int26_6(int16(int8(glyf[offset+4]))) + dy = fixed.Int26_6(int16(int8(glyf[offset+5]))) + offset += 6 + } + if flags&flagArgsAreXYValues == 0 { + return UnsupportedError("compound glyph transform vector") + } + if flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0 { + hasTransform = true + switch { + case flags&flagWeHaveAScale != 0: + transform[0] = int16(u16(glyf, offset+0)) + transform[3] = transform[0] + offset += 2 + case flags&flagWeHaveAnXAndYScale != 0: + transform[0] = int16(u16(glyf, offset+0)) + transform[3] = int16(u16(glyf, offset+2)) + offset += 4 + case flags&flagWeHaveATwoByTwo != 0: + transform[0] = int16(u16(glyf, offset+0)) + transform[1] = int16(u16(glyf, offset+2)) + transform[2] = int16(u16(glyf, offset+4)) + transform[3] = int16(u16(glyf, offset+6)) + offset += 8 + } + } + savedPP := g.phantomPoints + np0 := len(g.Points) + componentUMM := useMyMetrics && (flags&flagUseMyMetrics != 0) + if err := g.load(recursion+1, component, componentUMM); err != nil { + return err + } + if flags&flagUseMyMetrics == 0 { + g.phantomPoints = savedPP + } + if hasTransform { + for j := np0; j < len(g.Points); j++ { + p := &g.Points[j] + newX := 0 + + fixed.Int26_6((int64(p.X)*int64(transform[0])+1<<13)>>14) + + fixed.Int26_6((int64(p.Y)*int64(transform[2])+1<<13)>>14) + newY := 0 + + fixed.Int26_6((int64(p.X)*int64(transform[1])+1<<13)>>14) + + fixed.Int26_6((int64(p.Y)*int64(transform[3])+1<<13)>>14) + p.X, p.Y = newX, newY + } + } + dx = g.font.scale(g.scale * dx) + dy = g.font.scale(g.scale * dy) + if flags&flagRoundXYToGrid != 0 { + dx = (dx + 32) &^ 63 + dy = (dy + 32) &^ 63 + } + for j := np0; j < len(g.Points); j++ { + p := &g.Points[j] + p.X += dx + p.Y += dy + } + // TODO: also adjust g.InFontUnits and g.Unhinted? + if flags&flagMoreComponents == 0 { + break + } + } + + instrLen := 0 + if g.hinting != font.HintingNone && offset+2 <= len(glyf) { + instrLen = int(u16(glyf, offset)) + offset += 2 + } + + g.addPhantomsAndScale(np0, len(g.Points), false, instrLen > 0) + points, ends := g.Points[np0:], g.Ends[ne0:] + g.Points = g.Points[:len(g.Points)-4] + for j := range points { + points[j].Flags &^= flagTouchedX | flagTouchedY + } + + if instrLen == 0 { + if !g.metricsSet { + copy(g.phantomPoints[:], points[len(points)-4:]) + } + return nil + } + + // Hint the compound glyph. + program := glyf[offset : offset+instrLen] + // Temporarily adjust the ends to be relative to this compound glyph. + if np0 != 0 { + for i := range ends { + ends[i] -= np0 + } + } + // Hinting instructions of a composite glyph completely refer to the + // (already) hinted subglyphs. + g.tmp = append(g.tmp[:0], points...) + if err := g.hinter.run(program, points, g.tmp, g.tmp, ends); err != nil { + return err + } + if np0 != 0 { + for i := range ends { + ends[i] += np0 + } + } + if !g.metricsSet { + copy(g.phantomPoints[:], points[len(points)-4:]) + } + return nil +} + +func (g *GlyphBuf) addPhantomsAndScale(np0, np1 int, simple, adjust bool) { + // Add the four phantom points. + g.Points = append(g.Points, g.phantomPoints[:]...) + // Scale the points. + if simple && g.hinting != font.HintingNone { + g.InFontUnits = append(g.InFontUnits, g.Points[np1:]...) + } + for i := np1; i < len(g.Points); i++ { + p := &g.Points[i] + p.X = g.font.scale(g.scale * p.X) + p.Y = g.font.scale(g.scale * p.Y) + } + if g.hinting == font.HintingNone { + return + } + // Round the 1st phantom point to the grid, shifting all other points equally. + // Note that "all other points" starts from np0, not np1. + // TODO: delete this adjustment and the np0/np1 distinction, when + // we update the compatibility tests to C Freetype 2.5.3. + // See http://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=05c786d990390a7ca18e62962641dac740bacb06 + if adjust { + pp1x := g.Points[len(g.Points)-4].X + if dx := ((pp1x + 32) &^ 63) - pp1x; dx != 0 { + for i := np0; i < len(g.Points); i++ { + g.Points[i].X += dx + } + } + } + if simple { + g.Unhinted = append(g.Unhinted, g.Points[np1:]...) + } + // Round the 2nd and 4th phantom point to the grid. + p := &g.Points[len(g.Points)-3] + p.X = (p.X + 32) &^ 63 + p = &g.Points[len(g.Points)-1] + p.Y = (p.Y + 32) &^ 63 +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/truetype/hint.go b/Godeps/_workspace/src/github.com/golang/freetype/truetype/hint.go new file mode 100644 index 00000000..0315de51 --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/truetype/hint.go @@ -0,0 +1,1763 @@ +// Copyright 2012 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package truetype + +// This file implements a Truetype bytecode interpreter. +// The opcodes are described at https://developer.apple.com/fonts/TTRefMan/RM05/Chap5.html + +import ( + "errors" + "math" + + "golang.org/x/image/math/fixed" +) + +const ( + twilightZone = 0 + glyphZone = 1 + numZone = 2 +) + +type pointType uint32 + +const ( + current pointType = 0 + unhinted pointType = 1 + inFontUnits pointType = 2 + numPointType = 3 +) + +// callStackEntry is a bytecode call stack entry. +type callStackEntry struct { + program []byte + pc int + loopCount int32 +} + +// hinter implements bytecode hinting. A hinter can be re-used to hint a series +// of glyphs from a Font. +type hinter struct { + stack, store []int32 + + // functions is a map from function number to bytecode. + functions map[int32][]byte + + // font and scale are the font and scale last used for this hinter. + // Changing the font will require running the new font's fpgm bytecode. + // Changing either will require running the font's prep bytecode. + font *Font + scale fixed.Int26_6 + + // gs and defaultGS are the current and default graphics state. The + // default graphics state is the global default graphics state after + // the font's fpgm and prep programs have been run. + gs, defaultGS graphicsState + + // points and ends are the twilight zone's points, glyph's points + // and glyph's contour boundaries. + points [numZone][numPointType][]Point + ends []int + + // scaledCVT is the lazily initialized scaled Control Value Table. + scaledCVTInitialized bool + scaledCVT []fixed.Int26_6 +} + +// graphicsState is described at https://developer.apple.com/fonts/TTRefMan/RM04/Chap4.html +type graphicsState struct { + // Projection vector, freedom vector and dual projection vector. + pv, fv, dv [2]f2dot14 + // Reference points and zone pointers. + rp, zp [3]int32 + // Control Value / Single Width Cut-In. + controlValueCutIn, singleWidthCutIn, singleWidth fixed.Int26_6 + // Delta base / shift. + deltaBase, deltaShift int32 + // Minimum distance. + minDist fixed.Int26_6 + // Loop count. + loop int32 + // Rounding policy. + roundPeriod, roundPhase, roundThreshold fixed.Int26_6 + roundSuper45 bool + // Auto-flip. + autoFlip bool +} + +var globalDefaultGS = graphicsState{ + pv: [2]f2dot14{0x4000, 0}, // Unit vector along the X axis. + fv: [2]f2dot14{0x4000, 0}, + dv: [2]f2dot14{0x4000, 0}, + zp: [3]int32{1, 1, 1}, + controlValueCutIn: (17 << 6) / 16, // 17/16 as a fixed.Int26_6. + deltaBase: 9, + deltaShift: 3, + minDist: 1 << 6, // 1 as a fixed.Int26_6. + loop: 1, + roundPeriod: 1 << 6, // 1 as a fixed.Int26_6. + roundThreshold: 1 << 5, // 1/2 as a fixed.Int26_6. + roundSuper45: false, + autoFlip: true, +} + +func resetTwilightPoints(f *Font, p []Point) []Point { + if n := int(f.maxTwilightPoints) + 4; n <= cap(p) { + p = p[:n] + for i := range p { + p[i] = Point{} + } + } else { + p = make([]Point, n) + } + return p +} + +func (h *hinter) init(f *Font, scale fixed.Int26_6) error { + h.points[twilightZone][0] = resetTwilightPoints(f, h.points[twilightZone][0]) + h.points[twilightZone][1] = resetTwilightPoints(f, h.points[twilightZone][1]) + h.points[twilightZone][2] = resetTwilightPoints(f, h.points[twilightZone][2]) + + rescale := h.scale != scale + if h.font != f { + h.font, rescale = f, true + if h.functions == nil { + h.functions = make(map[int32][]byte) + } else { + for k := range h.functions { + delete(h.functions, k) + } + } + + if x := int(f.maxStackElements); x > len(h.stack) { + x += 255 + x &^= 255 + h.stack = make([]int32, x) + } + if x := int(f.maxStorage); x > len(h.store) { + x += 15 + x &^= 15 + h.store = make([]int32, x) + } + if len(f.fpgm) != 0 { + if err := h.run(f.fpgm, nil, nil, nil, nil); err != nil { + return err + } + } + } + + if rescale { + h.scale = scale + h.scaledCVTInitialized = false + + h.defaultGS = globalDefaultGS + + if len(f.prep) != 0 { + if err := h.run(f.prep, nil, nil, nil, nil); err != nil { + return err + } + h.defaultGS = h.gs + // The MS rasterizer doesn't allow the following graphics state + // variables to be modified by the CVT program. + h.defaultGS.pv = globalDefaultGS.pv + h.defaultGS.fv = globalDefaultGS.fv + h.defaultGS.dv = globalDefaultGS.dv + h.defaultGS.rp = globalDefaultGS.rp + h.defaultGS.zp = globalDefaultGS.zp + h.defaultGS.loop = globalDefaultGS.loop + } + } + return nil +} + +func (h *hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point, ends []int) error { + h.gs = h.defaultGS + h.points[glyphZone][current] = pCurrent + h.points[glyphZone][unhinted] = pUnhinted + h.points[glyphZone][inFontUnits] = pInFontUnits + h.ends = ends + + if len(program) > 50000 { + return errors.New("truetype: hinting: too many instructions") + } + var ( + steps, pc, top int + opcode uint8 + + callStack [32]callStackEntry + callStackTop int + ) + + for 0 <= pc && pc < len(program) { + steps++ + if steps == 100000 { + return errors.New("truetype: hinting: too many steps") + } + opcode = program[pc] + if top < int(popCount[opcode]) { + return errors.New("truetype: hinting: stack underflow") + } + switch opcode { + + case opSVTCA0: + h.gs.pv = [2]f2dot14{0, 0x4000} + h.gs.fv = [2]f2dot14{0, 0x4000} + h.gs.dv = [2]f2dot14{0, 0x4000} + + case opSVTCA1: + h.gs.pv = [2]f2dot14{0x4000, 0} + h.gs.fv = [2]f2dot14{0x4000, 0} + h.gs.dv = [2]f2dot14{0x4000, 0} + + case opSPVTCA0: + h.gs.pv = [2]f2dot14{0, 0x4000} + h.gs.dv = [2]f2dot14{0, 0x4000} + + case opSPVTCA1: + h.gs.pv = [2]f2dot14{0x4000, 0} + h.gs.dv = [2]f2dot14{0x4000, 0} + + case opSFVTCA0: + h.gs.fv = [2]f2dot14{0, 0x4000} + + case opSFVTCA1: + h.gs.fv = [2]f2dot14{0x4000, 0} + + case opSPVTL0, opSPVTL1, opSFVTL0, opSFVTL1: + top -= 2 + p1 := h.point(0, current, h.stack[top+0]) + p2 := h.point(0, current, h.stack[top+1]) + if p1 == nil || p2 == nil { + return errors.New("truetype: hinting: point out of range") + } + dx := f2dot14(p1.X - p2.X) + dy := f2dot14(p1.Y - p2.Y) + if dx == 0 && dy == 0 { + dx = 0x4000 + } else if opcode&1 != 0 { + // Counter-clockwise rotation. + dx, dy = -dy, dx + } + v := normalize(dx, dy) + if opcode < opSFVTL0 { + h.gs.pv = v + h.gs.dv = v + } else { + h.gs.fv = v + } + + case opSPVFS: + top -= 2 + h.gs.pv = normalize(f2dot14(h.stack[top]), f2dot14(h.stack[top+1])) + h.gs.dv = h.gs.pv + + case opSFVFS: + top -= 2 + h.gs.fv = normalize(f2dot14(h.stack[top]), f2dot14(h.stack[top+1])) + + case opGPV: + if top+1 >= len(h.stack) { + return errors.New("truetype: hinting: stack overflow") + } + h.stack[top+0] = int32(h.gs.pv[0]) + h.stack[top+1] = int32(h.gs.pv[1]) + top += 2 + + case opGFV: + if top+1 >= len(h.stack) { + return errors.New("truetype: hinting: stack overflow") + } + h.stack[top+0] = int32(h.gs.fv[0]) + h.stack[top+1] = int32(h.gs.fv[1]) + top += 2 + + case opSFVTPV: + h.gs.fv = h.gs.pv + + case opISECT: + top -= 5 + p := h.point(2, current, h.stack[top+0]) + a0 := h.point(1, current, h.stack[top+1]) + a1 := h.point(1, current, h.stack[top+2]) + b0 := h.point(0, current, h.stack[top+3]) + b1 := h.point(0, current, h.stack[top+4]) + if p == nil || a0 == nil || a1 == nil || b0 == nil || b1 == nil { + return errors.New("truetype: hinting: point out of range") + } + + dbx := b1.X - b0.X + dby := b1.Y - b0.Y + dax := a1.X - a0.X + day := a1.Y - a0.Y + dx := b0.X - a0.X + dy := b0.Y - a0.Y + discriminant := mulDiv(int64(dax), int64(-dby), 0x40) + + mulDiv(int64(day), int64(dbx), 0x40) + dotProduct := mulDiv(int64(dax), int64(dbx), 0x40) + + mulDiv(int64(day), int64(dby), 0x40) + // The discriminant above is actually a cross product of vectors + // da and db. Together with the dot product, they can be used as + // surrogates for sine and cosine of the angle between the vectors. + // Indeed, + // dotproduct = |da||db|cos(angle) + // discriminant = |da||db|sin(angle) + // We use these equations to reject grazing intersections by + // thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. + absDisc, absDotP := discriminant, dotProduct + if absDisc < 0 { + absDisc = -absDisc + } + if absDotP < 0 { + absDotP = -absDotP + } + if 19*absDisc > absDotP { + val := mulDiv(int64(dx), int64(-dby), 0x40) + + mulDiv(int64(dy), int64(dbx), 0x40) + rx := mulDiv(val, int64(dax), discriminant) + ry := mulDiv(val, int64(day), discriminant) + p.X = a0.X + fixed.Int26_6(rx) + p.Y = a0.Y + fixed.Int26_6(ry) + } else { + p.X = (a0.X + a1.X + b0.X + b1.X) / 4 + p.Y = (a0.Y + a1.Y + b0.Y + b1.Y) / 4 + } + p.Flags |= flagTouchedX | flagTouchedY + + case opSRP0, opSRP1, opSRP2: + top-- + h.gs.rp[opcode-opSRP0] = h.stack[top] + + case opSZP0, opSZP1, opSZP2: + top-- + h.gs.zp[opcode-opSZP0] = h.stack[top] + + case opSZPS: + top-- + h.gs.zp[0] = h.stack[top] + h.gs.zp[1] = h.stack[top] + h.gs.zp[2] = h.stack[top] + + case opSLOOP: + top-- + if h.stack[top] <= 0 { + return errors.New("truetype: hinting: invalid data") + } + h.gs.loop = h.stack[top] + + case opRTG: + h.gs.roundPeriod = 1 << 6 + h.gs.roundPhase = 0 + h.gs.roundThreshold = 1 << 5 + h.gs.roundSuper45 = false + + case opRTHG: + h.gs.roundPeriod = 1 << 6 + h.gs.roundPhase = 1 << 5 + h.gs.roundThreshold = 1 << 5 + h.gs.roundSuper45 = false + + case opSMD: + top-- + h.gs.minDist = fixed.Int26_6(h.stack[top]) + + case opELSE: + opcode = 1 + goto ifelse + + case opJMPR: + top-- + pc += int(h.stack[top]) + continue + + case opSCVTCI: + top-- + h.gs.controlValueCutIn = fixed.Int26_6(h.stack[top]) + + case opSSWCI: + top-- + h.gs.singleWidthCutIn = fixed.Int26_6(h.stack[top]) + + case opSSW: + top-- + h.gs.singleWidth = h.font.scale(h.scale * fixed.Int26_6(h.stack[top])) + + case opDUP: + if top >= len(h.stack) { + return errors.New("truetype: hinting: stack overflow") + } + h.stack[top] = h.stack[top-1] + top++ + + case opPOP: + top-- + + case opCLEAR: + top = 0 + + case opSWAP: + h.stack[top-1], h.stack[top-2] = h.stack[top-2], h.stack[top-1] + + case opDEPTH: + if top >= len(h.stack) { + return errors.New("truetype: hinting: stack overflow") + } + h.stack[top] = int32(top) + top++ + + case opCINDEX, opMINDEX: + x := int(h.stack[top-1]) + if x <= 0 || x >= top { + return errors.New("truetype: hinting: invalid data") + } + h.stack[top-1] = h.stack[top-1-x] + if opcode == opMINDEX { + copy(h.stack[top-1-x:top-1], h.stack[top-x:top]) + top-- + } + + case opALIGNPTS: + top -= 2 + p := h.point(1, current, h.stack[top]) + q := h.point(0, current, h.stack[top+1]) + if p == nil || q == nil { + return errors.New("truetype: hinting: point out of range") + } + d := dotProduct(fixed.Int26_6(q.X-p.X), fixed.Int26_6(q.Y-p.Y), h.gs.pv) / 2 + h.move(p, +d, true) + h.move(q, -d, true) + + case opUTP: + top-- + p := h.point(0, current, h.stack[top]) + if p == nil { + return errors.New("truetype: hinting: point out of range") + } + p.Flags &^= flagTouchedX | flagTouchedY + + case opLOOPCALL, opCALL: + if callStackTop >= len(callStack) { + return errors.New("truetype: hinting: call stack overflow") + } + top-- + f, ok := h.functions[h.stack[top]] + if !ok { + return errors.New("truetype: hinting: undefined function") + } + callStack[callStackTop] = callStackEntry{program, pc, 1} + if opcode == opLOOPCALL { + top-- + if h.stack[top] == 0 { + break + } + callStack[callStackTop].loopCount = h.stack[top] + } + callStackTop++ + program, pc = f, 0 + continue + + case opFDEF: + // Save all bytecode up until the next ENDF. + startPC := pc + 1 + fdefloop: + for { + pc++ + if pc >= len(program) { + return errors.New("truetype: hinting: unbalanced FDEF") + } + switch program[pc] { + case opFDEF: + return errors.New("truetype: hinting: nested FDEF") + case opENDF: + top-- + h.functions[h.stack[top]] = program[startPC : pc+1] + break fdefloop + default: + var ok bool + pc, ok = skipInstructionPayload(program, pc) + if !ok { + return errors.New("truetype: hinting: unbalanced FDEF") + } + } + } + + case opENDF: + if callStackTop == 0 { + return errors.New("truetype: hinting: call stack underflow") + } + callStackTop-- + callStack[callStackTop].loopCount-- + if callStack[callStackTop].loopCount != 0 { + callStackTop++ + pc = 0 + continue + } + program, pc = callStack[callStackTop].program, callStack[callStackTop].pc + + case opMDAP0, opMDAP1: + top-- + i := h.stack[top] + p := h.point(0, current, i) + if p == nil { + return errors.New("truetype: hinting: point out of range") + } + distance := fixed.Int26_6(0) + if opcode == opMDAP1 { + distance = dotProduct(p.X, p.Y, h.gs.pv) + // TODO: metrics compensation. + distance = h.round(distance) - distance + } + h.move(p, distance, true) + h.gs.rp[0] = i + h.gs.rp[1] = i + + case opIUP0, opIUP1: + iupY, mask := opcode == opIUP0, uint32(flagTouchedX) + if iupY { + mask = flagTouchedY + } + prevEnd := 0 + for _, end := range h.ends { + for i := prevEnd; i < end; i++ { + for i < end && h.points[glyphZone][current][i].Flags&mask == 0 { + i++ + } + if i == end { + break + } + firstTouched, curTouched := i, i + i++ + for ; i < end; i++ { + if h.points[glyphZone][current][i].Flags&mask != 0 { + h.iupInterp(iupY, curTouched+1, i-1, curTouched, i) + curTouched = i + } + } + if curTouched == firstTouched { + h.iupShift(iupY, prevEnd, end, curTouched) + } else { + h.iupInterp(iupY, curTouched+1, end-1, curTouched, firstTouched) + if firstTouched > 0 { + h.iupInterp(iupY, prevEnd, firstTouched-1, curTouched, firstTouched) + } + } + } + prevEnd = end + } + + case opSHP0, opSHP1: + if top < int(h.gs.loop) { + return errors.New("truetype: hinting: stack underflow") + } + _, _, d, ok := h.displacement(opcode&1 == 0) + if !ok { + return errors.New("truetype: hinting: point out of range") + } + for ; h.gs.loop != 0; h.gs.loop-- { + top-- + p := h.point(2, current, h.stack[top]) + if p == nil { + return errors.New("truetype: hinting: point out of range") + } + h.move(p, d, true) + } + h.gs.loop = 1 + + case opSHC0, opSHC1: + top-- + zonePointer, i, d, ok := h.displacement(opcode&1 == 0) + if !ok { + return errors.New("truetype: hinting: point out of range") + } + if h.gs.zp[2] == 0 { + // TODO: implement this when we have a glyph that does this. + return errors.New("hinting: unimplemented SHC instruction") + } + contour := h.stack[top] + if contour < 0 || len(ends) <= int(contour) { + return errors.New("truetype: hinting: contour out of range") + } + j0, j1 := int32(0), int32(h.ends[contour]) + if contour > 0 { + j0 = int32(h.ends[contour-1]) + } + move := h.gs.zp[zonePointer] != h.gs.zp[2] + for j := j0; j < j1; j++ { + if move || j != i { + h.move(h.point(2, current, j), d, true) + } + } + + case opSHZ0, opSHZ1: + top-- + zonePointer, i, d, ok := h.displacement(opcode&1 == 0) + if !ok { + return errors.New("truetype: hinting: point out of range") + } + + // As per C Freetype, SHZ doesn't move the phantom points, or mark + // the points as touched. + limit := int32(len(h.points[h.gs.zp[2]][current])) + if h.gs.zp[2] == glyphZone { + limit -= 4 + } + for j := int32(0); j < limit; j++ { + if i != j || h.gs.zp[zonePointer] != h.gs.zp[2] { + h.move(h.point(2, current, j), d, false) + } + } + + case opSHPIX: + top-- + d := fixed.Int26_6(h.stack[top]) + if top < int(h.gs.loop) { + return errors.New("truetype: hinting: stack underflow") + } + for ; h.gs.loop != 0; h.gs.loop-- { + top-- + p := h.point(2, current, h.stack[top]) + if p == nil { + return errors.New("truetype: hinting: point out of range") + } + h.move(p, d, true) + } + h.gs.loop = 1 + + case opIP: + if top < int(h.gs.loop) { + return errors.New("truetype: hinting: stack underflow") + } + pointType := inFontUnits + twilight := h.gs.zp[0] == 0 || h.gs.zp[1] == 0 || h.gs.zp[2] == 0 + if twilight { + pointType = unhinted + } + p := h.point(1, pointType, h.gs.rp[2]) + oldP := h.point(0, pointType, h.gs.rp[1]) + oldRange := dotProduct(p.X-oldP.X, p.Y-oldP.Y, h.gs.dv) + + p = h.point(1, current, h.gs.rp[2]) + curP := h.point(0, current, h.gs.rp[1]) + curRange := dotProduct(p.X-curP.X, p.Y-curP.Y, h.gs.pv) + for ; h.gs.loop != 0; h.gs.loop-- { + top-- + i := h.stack[top] + p = h.point(2, pointType, i) + oldDist := dotProduct(p.X-oldP.X, p.Y-oldP.Y, h.gs.dv) + p = h.point(2, current, i) + curDist := dotProduct(p.X-curP.X, p.Y-curP.Y, h.gs.pv) + newDist := fixed.Int26_6(0) + if oldDist != 0 { + if oldRange != 0 { + newDist = fixed.Int26_6(mulDiv(int64(oldDist), int64(curRange), int64(oldRange))) + } else { + newDist = -oldDist + } + } + h.move(p, newDist-curDist, true) + } + h.gs.loop = 1 + + case opMSIRP0, opMSIRP1: + top -= 2 + i := h.stack[top] + distance := fixed.Int26_6(h.stack[top+1]) + + // TODO: special case h.gs.zp[1] == 0 in C Freetype. + ref := h.point(0, current, h.gs.rp[0]) + p := h.point(1, current, i) + if ref == nil || p == nil { + return errors.New("truetype: hinting: point out of range") + } + curDist := dotProduct(p.X-ref.X, p.Y-ref.Y, h.gs.pv) + + // Set-RP0 bit. + if opcode == opMSIRP1 { + h.gs.rp[0] = i + } + h.gs.rp[1] = h.gs.rp[0] + h.gs.rp[2] = i + + // Move the point. + h.move(p, distance-curDist, true) + + case opALIGNRP: + if top < int(h.gs.loop) { + return errors.New("truetype: hinting: stack underflow") + } + ref := h.point(0, current, h.gs.rp[0]) + if ref == nil { + return errors.New("truetype: hinting: point out of range") + } + for ; h.gs.loop != 0; h.gs.loop-- { + top-- + p := h.point(1, current, h.stack[top]) + if p == nil { + return errors.New("truetype: hinting: point out of range") + } + h.move(p, -dotProduct(p.X-ref.X, p.Y-ref.Y, h.gs.pv), true) + } + h.gs.loop = 1 + + case opRTDG: + h.gs.roundPeriod = 1 << 5 + h.gs.roundPhase = 0 + h.gs.roundThreshold = 1 << 4 + h.gs.roundSuper45 = false + + case opMIAP0, opMIAP1: + top -= 2 + i := h.stack[top] + distance := h.getScaledCVT(h.stack[top+1]) + if h.gs.zp[0] == 0 { + p := h.point(0, unhinted, i) + q := h.point(0, current, i) + p.X = fixed.Int26_6((int64(distance) * int64(h.gs.fv[0])) >> 14) + p.Y = fixed.Int26_6((int64(distance) * int64(h.gs.fv[1])) >> 14) + *q = *p + } + p := h.point(0, current, i) + oldDist := dotProduct(p.X, p.Y, h.gs.pv) + if opcode == opMIAP1 { + if fabs(distance-oldDist) > h.gs.controlValueCutIn { + distance = oldDist + } + // TODO: metrics compensation. + distance = h.round(distance) + } + h.move(p, distance-oldDist, true) + h.gs.rp[0] = i + h.gs.rp[1] = i + + case opNPUSHB: + opcode = 0 + goto push + + case opNPUSHW: + opcode = 0x80 + goto push + + case opWS: + top -= 2 + i := int(h.stack[top]) + if i < 0 || len(h.store) <= i { + return errors.New("truetype: hinting: invalid data") + } + h.store[i] = h.stack[top+1] + + case opRS: + i := int(h.stack[top-1]) + if i < 0 || len(h.store) <= i { + return errors.New("truetype: hinting: invalid data") + } + h.stack[top-1] = h.store[i] + + case opWCVTP: + top -= 2 + h.setScaledCVT(h.stack[top], fixed.Int26_6(h.stack[top+1])) + + case opRCVT: + h.stack[top-1] = int32(h.getScaledCVT(h.stack[top-1])) + + case opGC0, opGC1: + i := h.stack[top-1] + if opcode == opGC0 { + p := h.point(2, current, i) + h.stack[top-1] = int32(dotProduct(p.X, p.Y, h.gs.pv)) + } else { + p := h.point(2, unhinted, i) + // Using dv as per C Freetype. + h.stack[top-1] = int32(dotProduct(p.X, p.Y, h.gs.dv)) + } + + case opSCFS: + top -= 2 + i := h.stack[top] + p := h.point(2, current, i) + if p == nil { + return errors.New("truetype: hinting: point out of range") + } + c := dotProduct(p.X, p.Y, h.gs.pv) + h.move(p, fixed.Int26_6(h.stack[top+1])-c, true) + if h.gs.zp[2] != 0 { + break + } + q := h.point(2, unhinted, i) + if q == nil { + return errors.New("truetype: hinting: point out of range") + } + q.X = p.X + q.Y = p.Y + + case opMD0, opMD1: + top-- + pt, v, scale := pointType(0), [2]f2dot14{}, false + if opcode == opMD0 { + pt = current + v = h.gs.pv + } else if h.gs.zp[0] == 0 || h.gs.zp[1] == 0 { + pt = unhinted + v = h.gs.dv + } else { + pt = inFontUnits + v = h.gs.dv + scale = true + } + p := h.point(0, pt, h.stack[top-1]) + q := h.point(1, pt, h.stack[top]) + if p == nil || q == nil { + return errors.New("truetype: hinting: point out of range") + } + d := int32(dotProduct(p.X-q.X, p.Y-q.Y, v)) + if scale { + d = int32(int64(d*int32(h.scale)) / int64(h.font.fUnitsPerEm)) + } + h.stack[top-1] = d + + case opMPPEM, opMPS: + if top >= len(h.stack) { + return errors.New("truetype: hinting: stack overflow") + } + // For MPS, point size should be irrelevant; we return the PPEM. + h.stack[top] = int32(h.scale) >> 6 + top++ + + case opFLIPON, opFLIPOFF: + h.gs.autoFlip = opcode == opFLIPON + + case opDEBUG: + // No-op. + + case opLT: + top-- + h.stack[top-1] = bool2int32(h.stack[top-1] < h.stack[top]) + + case opLTEQ: + top-- + h.stack[top-1] = bool2int32(h.stack[top-1] <= h.stack[top]) + + case opGT: + top-- + h.stack[top-1] = bool2int32(h.stack[top-1] > h.stack[top]) + + case opGTEQ: + top-- + h.stack[top-1] = bool2int32(h.stack[top-1] >= h.stack[top]) + + case opEQ: + top-- + h.stack[top-1] = bool2int32(h.stack[top-1] == h.stack[top]) + + case opNEQ: + top-- + h.stack[top-1] = bool2int32(h.stack[top-1] != h.stack[top]) + + case opODD, opEVEN: + i := h.round(fixed.Int26_6(h.stack[top-1])) >> 6 + h.stack[top-1] = int32(i&1) ^ int32(opcode-opODD) + + case opIF: + top-- + if h.stack[top] == 0 { + opcode = 0 + goto ifelse + } + + case opEIF: + // No-op. + + case opAND: + top-- + h.stack[top-1] = bool2int32(h.stack[top-1] != 0 && h.stack[top] != 0) + + case opOR: + top-- + h.stack[top-1] = bool2int32(h.stack[top-1]|h.stack[top] != 0) + + case opNOT: + h.stack[top-1] = bool2int32(h.stack[top-1] == 0) + + case opDELTAP1: + goto delta + + case opSDB: + top-- + h.gs.deltaBase = h.stack[top] + + case opSDS: + top-- + h.gs.deltaShift = h.stack[top] + + case opADD: + top-- + h.stack[top-1] += h.stack[top] + + case opSUB: + top-- + h.stack[top-1] -= h.stack[top] + + case opDIV: + top-- + if h.stack[top] == 0 { + return errors.New("truetype: hinting: division by zero") + } + h.stack[top-1] = int32(fdiv(fixed.Int26_6(h.stack[top-1]), fixed.Int26_6(h.stack[top]))) + + case opMUL: + top-- + h.stack[top-1] = int32(fmul(fixed.Int26_6(h.stack[top-1]), fixed.Int26_6(h.stack[top]))) + + case opABS: + if h.stack[top-1] < 0 { + h.stack[top-1] = -h.stack[top-1] + } + + case opNEG: + h.stack[top-1] = -h.stack[top-1] + + case opFLOOR: + h.stack[top-1] &^= 63 + + case opCEILING: + h.stack[top-1] += 63 + h.stack[top-1] &^= 63 + + case opROUND00, opROUND01, opROUND10, opROUND11: + // The four flavors of opROUND are equivalent. See the comment below on + // opNROUND for the rationale. + h.stack[top-1] = int32(h.round(fixed.Int26_6(h.stack[top-1]))) + + case opNROUND00, opNROUND01, opNROUND10, opNROUND11: + // No-op. The spec says to add one of four "compensations for the engine + // characteristics", to cater for things like "different dot-size printers". + // https://developer.apple.com/fonts/TTRefMan/RM02/Chap2.html#engine_compensation + // This code does not implement engine compensation, as we don't expect to + // be used to output on dot-matrix printers. + + case opWCVTF: + top -= 2 + h.setScaledCVT(h.stack[top], h.font.scale(h.scale*fixed.Int26_6(h.stack[top+1]))) + + case opDELTAP2, opDELTAP3, opDELTAC1, opDELTAC2, opDELTAC3: + goto delta + + case opSROUND, opS45ROUND: + top-- + switch (h.stack[top] >> 6) & 0x03 { + case 0: + h.gs.roundPeriod = 1 << 5 + case 1, 3: + h.gs.roundPeriod = 1 << 6 + case 2: + h.gs.roundPeriod = 1 << 7 + } + h.gs.roundSuper45 = opcode == opS45ROUND + if h.gs.roundSuper45 { + // The spec says to multiply by √2, but the C Freetype code says 1/√2. + // We go with 1/√2. + h.gs.roundPeriod *= 46341 + h.gs.roundPeriod /= 65536 + } + h.gs.roundPhase = h.gs.roundPeriod * fixed.Int26_6((h.stack[top]>>4)&0x03) / 4 + if x := h.stack[top] & 0x0f; x != 0 { + h.gs.roundThreshold = h.gs.roundPeriod * fixed.Int26_6(x-4) / 8 + } else { + h.gs.roundThreshold = h.gs.roundPeriod - 1 + } + + case opJROT: + top -= 2 + if h.stack[top+1] != 0 { + pc += int(h.stack[top]) + continue + } + + case opJROF: + top -= 2 + if h.stack[top+1] == 0 { + pc += int(h.stack[top]) + continue + } + + case opROFF: + h.gs.roundPeriod = 0 + h.gs.roundPhase = 0 + h.gs.roundThreshold = 0 + h.gs.roundSuper45 = false + + case opRUTG: + h.gs.roundPeriod = 1 << 6 + h.gs.roundPhase = 0 + h.gs.roundThreshold = 1<<6 - 1 + h.gs.roundSuper45 = false + + case opRDTG: + h.gs.roundPeriod = 1 << 6 + h.gs.roundPhase = 0 + h.gs.roundThreshold = 0 + h.gs.roundSuper45 = false + + case opSANGW, opAA: + // These ops are "anachronistic" and no longer used. + top-- + + case opFLIPPT: + if top < int(h.gs.loop) { + return errors.New("truetype: hinting: stack underflow") + } + points := h.points[glyphZone][current] + for ; h.gs.loop != 0; h.gs.loop-- { + top-- + i := h.stack[top] + if i < 0 || len(points) <= int(i) { + return errors.New("truetype: hinting: point out of range") + } + points[i].Flags ^= flagOnCurve + } + h.gs.loop = 1 + + case opFLIPRGON, opFLIPRGOFF: + top -= 2 + i, j, points := h.stack[top], h.stack[top+1], h.points[glyphZone][current] + if i < 0 || len(points) <= int(i) || j < 0 || len(points) <= int(j) { + return errors.New("truetype: hinting: point out of range") + } + for ; i <= j; i++ { + if opcode == opFLIPRGON { + points[i].Flags |= flagOnCurve + } else { + points[i].Flags &^= flagOnCurve + } + } + + case opSCANCTRL: + // We do not support dropout control, as we always rasterize grayscale glyphs. + top-- + + case opSDPVTL0, opSDPVTL1: + top -= 2 + for i := 0; i < 2; i++ { + pt := unhinted + if i != 0 { + pt = current + } + p := h.point(1, pt, h.stack[top]) + q := h.point(2, pt, h.stack[top+1]) + if p == nil || q == nil { + return errors.New("truetype: hinting: point out of range") + } + dx := f2dot14(p.X - q.X) + dy := f2dot14(p.Y - q.Y) + if dx == 0 && dy == 0 { + dx = 0x4000 + } else if opcode&1 != 0 { + // Counter-clockwise rotation. + dx, dy = -dy, dx + } + if i == 0 { + h.gs.dv = normalize(dx, dy) + } else { + h.gs.pv = normalize(dx, dy) + } + } + + case opGETINFO: + res := int32(0) + if h.stack[top-1]&(1<<0) != 0 { + // Set the engine version. We hard-code this to 35, the same as + // the C freetype code, which says that "Version~35 corresponds + // to MS rasterizer v.1.7 as used e.g. in Windows~98". + res |= 35 + } + if h.stack[top-1]&(1<<5) != 0 { + // Set that we support grayscale. + res |= 1 << 12 + } + // We set no other bits, as we do not support rotated or stretched glyphs. + h.stack[top-1] = res + + case opIDEF: + // IDEF is for ancient versions of the bytecode interpreter, and is no longer used. + return errors.New("truetype: hinting: unsupported IDEF instruction") + + case opROLL: + h.stack[top-1], h.stack[top-3], h.stack[top-2] = + h.stack[top-3], h.stack[top-2], h.stack[top-1] + + case opMAX: + top-- + if h.stack[top-1] < h.stack[top] { + h.stack[top-1] = h.stack[top] + } + + case opMIN: + top-- + if h.stack[top-1] > h.stack[top] { + h.stack[top-1] = h.stack[top] + } + + case opSCANTYPE: + // We do not support dropout control, as we always rasterize grayscale glyphs. + top-- + + case opINSTCTRL: + // TODO: support instruction execution control? It seems rare, and even when + // nominally used (e.g. Source Sans Pro), it seems conditional on extreme or + // unusual rasterization conditions. For example, the code snippet at + // https://developer.apple.com/fonts/TTRefMan/RM05/Chap5.html#INSTCTRL + // uses INSTCTRL when grid-fitting a rotated or stretched glyph, but + // freetype-go does not support rotated or stretched glyphs. + top -= 2 + + default: + if opcode < opPUSHB000 { + return errors.New("truetype: hinting: unrecognized instruction") + } + + if opcode < opMDRP00000 { + // PUSHxxxx opcode. + + if opcode < opPUSHW000 { + opcode -= opPUSHB000 - 1 + } else { + opcode -= opPUSHW000 - 1 - 0x80 + } + goto push + } + + if opcode < opMIRP00000 { + // MDRPxxxxx opcode. + + top-- + i := h.stack[top] + ref := h.point(0, current, h.gs.rp[0]) + p := h.point(1, current, i) + if ref == nil || p == nil { + return errors.New("truetype: hinting: point out of range") + } + + oldDist := fixed.Int26_6(0) + if h.gs.zp[0] == 0 || h.gs.zp[1] == 0 { + p0 := h.point(1, unhinted, i) + p1 := h.point(0, unhinted, h.gs.rp[0]) + oldDist = dotProduct(p0.X-p1.X, p0.Y-p1.Y, h.gs.dv) + } else { + p0 := h.point(1, inFontUnits, i) + p1 := h.point(0, inFontUnits, h.gs.rp[0]) + oldDist = dotProduct(p0.X-p1.X, p0.Y-p1.Y, h.gs.dv) + oldDist = h.font.scale(h.scale * oldDist) + } + + // Single-width cut-in test. + if x := fabs(oldDist - h.gs.singleWidth); x < h.gs.singleWidthCutIn { + if oldDist >= 0 { + oldDist = +h.gs.singleWidth + } else { + oldDist = -h.gs.singleWidth + } + } + + // Rounding bit. + // TODO: metrics compensation. + distance := oldDist + if opcode&0x04 != 0 { + distance = h.round(oldDist) + } + + // Minimum distance bit. + if opcode&0x08 != 0 { + if oldDist >= 0 { + if distance < h.gs.minDist { + distance = h.gs.minDist + } + } else { + if distance > -h.gs.minDist { + distance = -h.gs.minDist + } + } + } + + // Set-RP0 bit. + h.gs.rp[1] = h.gs.rp[0] + h.gs.rp[2] = i + if opcode&0x10 != 0 { + h.gs.rp[0] = i + } + + // Move the point. + oldDist = dotProduct(p.X-ref.X, p.Y-ref.Y, h.gs.pv) + h.move(p, distance-oldDist, true) + + } else { + // MIRPxxxxx opcode. + + top -= 2 + i := h.stack[top] + cvtDist := h.getScaledCVT(h.stack[top+1]) + if fabs(cvtDist-h.gs.singleWidth) < h.gs.singleWidthCutIn { + if cvtDist >= 0 { + cvtDist = +h.gs.singleWidth + } else { + cvtDist = -h.gs.singleWidth + } + } + + if h.gs.zp[1] == 0 { + // TODO: implement once we have a .ttf file that triggers + // this, so that we can step through C's freetype. + return errors.New("truetype: hinting: unimplemented twilight point adjustment") + } + + ref := h.point(0, unhinted, h.gs.rp[0]) + p := h.point(1, unhinted, i) + if ref == nil || p == nil { + return errors.New("truetype: hinting: point out of range") + } + oldDist := dotProduct(p.X-ref.X, p.Y-ref.Y, h.gs.dv) + + ref = h.point(0, current, h.gs.rp[0]) + p = h.point(1, current, i) + if ref == nil || p == nil { + return errors.New("truetype: hinting: point out of range") + } + curDist := dotProduct(p.X-ref.X, p.Y-ref.Y, h.gs.pv) + + if h.gs.autoFlip && oldDist^cvtDist < 0 { + cvtDist = -cvtDist + } + + // Rounding bit. + // TODO: metrics compensation. + distance := cvtDist + if opcode&0x04 != 0 { + // The CVT value is only used if close enough to oldDist. + if (h.gs.zp[0] == h.gs.zp[1]) && + (fabs(cvtDist-oldDist) > h.gs.controlValueCutIn) { + + distance = oldDist + } + distance = h.round(distance) + } + + // Minimum distance bit. + if opcode&0x08 != 0 { + if oldDist >= 0 { + if distance < h.gs.minDist { + distance = h.gs.minDist + } + } else { + if distance > -h.gs.minDist { + distance = -h.gs.minDist + } + } + } + + // Set-RP0 bit. + h.gs.rp[1] = h.gs.rp[0] + h.gs.rp[2] = i + if opcode&0x10 != 0 { + h.gs.rp[0] = i + } + + // Move the point. + h.move(p, distance-curDist, true) + } + } + pc++ + continue + + ifelse: + // Skip past bytecode until the next ELSE (if opcode == 0) or the + // next EIF (for all opcodes). Opcode == 0 means that we have come + // from an IF. Opcode == 1 means that we have come from an ELSE. + { + ifelseloop: + for depth := 0; ; { + pc++ + if pc >= len(program) { + return errors.New("truetype: hinting: unbalanced IF or ELSE") + } + switch program[pc] { + case opIF: + depth++ + case opELSE: + if depth == 0 && opcode == 0 { + break ifelseloop + } + case opEIF: + depth-- + if depth < 0 { + break ifelseloop + } + default: + var ok bool + pc, ok = skipInstructionPayload(program, pc) + if !ok { + return errors.New("truetype: hinting: unbalanced IF or ELSE") + } + } + } + pc++ + continue + } + + push: + // Push n elements from the program to the stack, where n is the low 7 bits of + // opcode. If the low 7 bits are zero, then n is the next byte from the program. + // The high bit being 0 means that the elements are zero-extended bytes. + // The high bit being 1 means that the elements are sign-extended words. + { + width := 1 + if opcode&0x80 != 0 { + opcode &^= 0x80 + width = 2 + } + if opcode == 0 { + pc++ + if pc >= len(program) { + return errors.New("truetype: hinting: insufficient data") + } + opcode = program[pc] + } + pc++ + if top+int(opcode) > len(h.stack) { + return errors.New("truetype: hinting: stack overflow") + } + if pc+width*int(opcode) > len(program) { + return errors.New("truetype: hinting: insufficient data") + } + for ; opcode > 0; opcode-- { + if width == 1 { + h.stack[top] = int32(program[pc]) + } else { + h.stack[top] = int32(int8(program[pc]))<<8 | int32(program[pc+1]) + } + top++ + pc += width + } + continue + } + + delta: + { + if opcode >= opDELTAC1 && !h.scaledCVTInitialized { + h.initializeScaledCVT() + } + top-- + n := h.stack[top] + if int32(top) < 2*n { + return errors.New("truetype: hinting: stack underflow") + } + for ; n > 0; n-- { + top -= 2 + b := h.stack[top] + c := (b & 0xf0) >> 4 + switch opcode { + case opDELTAP2, opDELTAC2: + c += 16 + case opDELTAP3, opDELTAC3: + c += 32 + } + c += h.gs.deltaBase + if ppem := (int32(h.scale) + 1<<5) >> 6; ppem != c { + continue + } + b = (b & 0x0f) - 8 + if b >= 0 { + b++ + } + b = b * 64 / (1 << uint32(h.gs.deltaShift)) + if opcode >= opDELTAC1 { + a := h.stack[top+1] + if a < 0 || len(h.scaledCVT) <= int(a) { + return errors.New("truetype: hinting: index out of range") + } + h.scaledCVT[a] += fixed.Int26_6(b) + } else { + p := h.point(0, current, h.stack[top+1]) + if p == nil { + return errors.New("truetype: hinting: point out of range") + } + h.move(p, fixed.Int26_6(b), true) + } + } + pc++ + continue + } + } + return nil +} + +func (h *hinter) initializeScaledCVT() { + h.scaledCVTInitialized = true + if n := len(h.font.cvt) / 2; n <= cap(h.scaledCVT) { + h.scaledCVT = h.scaledCVT[:n] + } else { + if n < 32 { + n = 32 + } + h.scaledCVT = make([]fixed.Int26_6, len(h.font.cvt)/2, n) + } + for i := range h.scaledCVT { + unscaled := uint16(h.font.cvt[2*i])<<8 | uint16(h.font.cvt[2*i+1]) + h.scaledCVT[i] = h.font.scale(h.scale * fixed.Int26_6(int16(unscaled))) + } +} + +// getScaledCVT returns the scaled value from the font's Control Value Table. +func (h *hinter) getScaledCVT(i int32) fixed.Int26_6 { + if !h.scaledCVTInitialized { + h.initializeScaledCVT() + } + if i < 0 || len(h.scaledCVT) <= int(i) { + return 0 + } + return h.scaledCVT[i] +} + +// setScaledCVT overrides the scaled value from the font's Control Value Table. +func (h *hinter) setScaledCVT(i int32, v fixed.Int26_6) { + if !h.scaledCVTInitialized { + h.initializeScaledCVT() + } + if i < 0 || len(h.scaledCVT) <= int(i) { + return + } + h.scaledCVT[i] = v +} + +func (h *hinter) point(zonePointer uint32, pt pointType, i int32) *Point { + points := h.points[h.gs.zp[zonePointer]][pt] + if i < 0 || len(points) <= int(i) { + return nil + } + return &points[i] +} + +func (h *hinter) move(p *Point, distance fixed.Int26_6, touch bool) { + fvx := int64(h.gs.fv[0]) + pvx := int64(h.gs.pv[0]) + if fvx == 0x4000 && pvx == 0x4000 { + p.X += fixed.Int26_6(distance) + if touch { + p.Flags |= flagTouchedX + } + return + } + + fvy := int64(h.gs.fv[1]) + pvy := int64(h.gs.pv[1]) + if fvy == 0x4000 && pvy == 0x4000 { + p.Y += fixed.Int26_6(distance) + if touch { + p.Flags |= flagTouchedY + } + return + } + + fvDotPv := (fvx*pvx + fvy*pvy) >> 14 + + if fvx != 0 { + p.X += fixed.Int26_6(mulDiv(fvx, int64(distance), fvDotPv)) + if touch { + p.Flags |= flagTouchedX + } + } + + if fvy != 0 { + p.Y += fixed.Int26_6(mulDiv(fvy, int64(distance), fvDotPv)) + if touch { + p.Flags |= flagTouchedY + } + } +} + +func (h *hinter) iupInterp(interpY bool, p1, p2, ref1, ref2 int) { + if p1 > p2 { + return + } + if ref1 >= len(h.points[glyphZone][current]) || + ref2 >= len(h.points[glyphZone][current]) { + return + } + + var ifu1, ifu2 fixed.Int26_6 + if interpY { + ifu1 = h.points[glyphZone][inFontUnits][ref1].Y + ifu2 = h.points[glyphZone][inFontUnits][ref2].Y + } else { + ifu1 = h.points[glyphZone][inFontUnits][ref1].X + ifu2 = h.points[glyphZone][inFontUnits][ref2].X + } + if ifu1 > ifu2 { + ifu1, ifu2 = ifu2, ifu1 + ref1, ref2 = ref2, ref1 + } + + var unh1, unh2, delta1, delta2 fixed.Int26_6 + if interpY { + unh1 = h.points[glyphZone][unhinted][ref1].Y + unh2 = h.points[glyphZone][unhinted][ref2].Y + delta1 = h.points[glyphZone][current][ref1].Y - unh1 + delta2 = h.points[glyphZone][current][ref2].Y - unh2 + } else { + unh1 = h.points[glyphZone][unhinted][ref1].X + unh2 = h.points[glyphZone][unhinted][ref2].X + delta1 = h.points[glyphZone][current][ref1].X - unh1 + delta2 = h.points[glyphZone][current][ref2].X - unh2 + } + + var xy, ifuXY fixed.Int26_6 + if ifu1 == ifu2 { + for i := p1; i <= p2; i++ { + if interpY { + xy = h.points[glyphZone][unhinted][i].Y + } else { + xy = h.points[glyphZone][unhinted][i].X + } + + if xy <= unh1 { + xy += delta1 + } else { + xy += delta2 + } + + if interpY { + h.points[glyphZone][current][i].Y = xy + } else { + h.points[glyphZone][current][i].X = xy + } + } + return + } + + scale, scaleOK := int64(0), false + for i := p1; i <= p2; i++ { + if interpY { + xy = h.points[glyphZone][unhinted][i].Y + ifuXY = h.points[glyphZone][inFontUnits][i].Y + } else { + xy = h.points[glyphZone][unhinted][i].X + ifuXY = h.points[glyphZone][inFontUnits][i].X + } + + if xy <= unh1 { + xy += delta1 + } else if xy >= unh2 { + xy += delta2 + } else { + if !scaleOK { + scaleOK = true + scale = mulDiv(int64(unh2+delta2-unh1-delta1), 0x10000, int64(ifu2-ifu1)) + } + numer := int64(ifuXY-ifu1) * scale + if numer >= 0 { + numer += 0x8000 + } else { + numer -= 0x8000 + } + xy = unh1 + delta1 + fixed.Int26_6(numer/0x10000) + } + + if interpY { + h.points[glyphZone][current][i].Y = xy + } else { + h.points[glyphZone][current][i].X = xy + } + } +} + +func (h *hinter) iupShift(interpY bool, p1, p2, p int) { + var delta fixed.Int26_6 + if interpY { + delta = h.points[glyphZone][current][p].Y - h.points[glyphZone][unhinted][p].Y + } else { + delta = h.points[glyphZone][current][p].X - h.points[glyphZone][unhinted][p].X + } + if delta == 0 { + return + } + for i := p1; i < p2; i++ { + if i == p { + continue + } + if interpY { + h.points[glyphZone][current][i].Y += delta + } else { + h.points[glyphZone][current][i].X += delta + } + } +} + +func (h *hinter) displacement(useZP1 bool) (zonePointer uint32, i int32, d fixed.Int26_6, ok bool) { + zonePointer, i = uint32(0), h.gs.rp[1] + if useZP1 { + zonePointer, i = 1, h.gs.rp[2] + } + p := h.point(zonePointer, current, i) + q := h.point(zonePointer, unhinted, i) + if p == nil || q == nil { + return 0, 0, 0, false + } + d = dotProduct(p.X-q.X, p.Y-q.Y, h.gs.pv) + return zonePointer, i, d, true +} + +// skipInstructionPayload increments pc by the extra data that follows a +// variable length PUSHB or PUSHW instruction. +func skipInstructionPayload(program []byte, pc int) (newPC int, ok bool) { + switch program[pc] { + case opNPUSHB: + pc++ + if pc >= len(program) { + return 0, false + } + pc += int(program[pc]) + case opNPUSHW: + pc++ + if pc >= len(program) { + return 0, false + } + pc += 2 * int(program[pc]) + case opPUSHB000, opPUSHB001, opPUSHB010, opPUSHB011, + opPUSHB100, opPUSHB101, opPUSHB110, opPUSHB111: + pc += int(program[pc] - (opPUSHB000 - 1)) + case opPUSHW000, opPUSHW001, opPUSHW010, opPUSHW011, + opPUSHW100, opPUSHW101, opPUSHW110, opPUSHW111: + pc += 2 * int(program[pc]-(opPUSHW000-1)) + } + return pc, true +} + +// f2dot14 is a 2.14 fixed point number. +type f2dot14 int16 + +func normalize(x, y f2dot14) [2]f2dot14 { + fx, fy := float64(x), float64(y) + l := 0x4000 / math.Hypot(fx, fy) + fx *= l + if fx >= 0 { + fx += 0.5 + } else { + fx -= 0.5 + } + fy *= l + if fy >= 0 { + fy += 0.5 + } else { + fy -= 0.5 + } + return [2]f2dot14{f2dot14(fx), f2dot14(fy)} +} + +// fabs returns abs(x) in 26.6 fixed point arithmetic. +func fabs(x fixed.Int26_6) fixed.Int26_6 { + if x < 0 { + return -x + } + return x +} + +// fdiv returns x/y in 26.6 fixed point arithmetic. +func fdiv(x, y fixed.Int26_6) fixed.Int26_6 { + return fixed.Int26_6((int64(x) << 6) / int64(y)) +} + +// fmul returns x*y in 26.6 fixed point arithmetic. +func fmul(x, y fixed.Int26_6) fixed.Int26_6 { + return fixed.Int26_6((int64(x)*int64(y) + 1<<5) >> 6) +} + +// dotProduct returns the dot product of [x, y] and q. It is almost the same as +// px := int64(x) +// py := int64(y) +// qx := int64(q[0]) +// qy := int64(q[1]) +// return fixed.Int26_6((px*qx + py*qy + 1<<13) >> 14) +// except that the computation is done with 32-bit integers to produce exactly +// the same rounding behavior as C Freetype. +func dotProduct(x, y fixed.Int26_6, q [2]f2dot14) fixed.Int26_6 { + // Compute x*q[0] as 64-bit value. + l := uint32((int32(x) & 0xFFFF) * int32(q[0])) + m := (int32(x) >> 16) * int32(q[0]) + + lo1 := l + (uint32(m) << 16) + hi1 := (m >> 16) + (int32(l) >> 31) + bool2int32(lo1 < l) + + // Compute y*q[1] as 64-bit value. + l = uint32((int32(y) & 0xFFFF) * int32(q[1])) + m = (int32(y) >> 16) * int32(q[1]) + + lo2 := l + (uint32(m) << 16) + hi2 := (m >> 16) + (int32(l) >> 31) + bool2int32(lo2 < l) + + // Add them. + lo := lo1 + lo2 + hi := hi1 + hi2 + bool2int32(lo < lo1) + + // Divide the result by 2^14 with rounding. + s := hi >> 31 + l = lo + uint32(s) + hi += s + bool2int32(l < lo) + lo = l + + l = lo + 0x2000 + hi += bool2int32(l < lo) + + return fixed.Int26_6((uint32(hi) << 18) | (l >> 14)) +} + +// mulDiv returns x*y/z, rounded to the nearest integer. +func mulDiv(x, y, z int64) int64 { + xy := x * y + if z < 0 { + xy, z = -xy, -z + } + if xy >= 0 { + xy += z / 2 + } else { + xy -= z / 2 + } + return xy / z +} + +// round rounds the given number. The rounding algorithm is described at +// https://developer.apple.com/fonts/TTRefMan/RM02/Chap2.html#rounding +func (h *hinter) round(x fixed.Int26_6) fixed.Int26_6 { + if h.gs.roundPeriod == 0 { + // Rounding is off. + return x + } + if x >= 0 { + ret := x - h.gs.roundPhase + h.gs.roundThreshold + if h.gs.roundSuper45 { + ret /= h.gs.roundPeriod + ret *= h.gs.roundPeriod + } else { + ret &= -h.gs.roundPeriod + } + if x != 0 && ret < 0 { + ret = 0 + } + return ret + h.gs.roundPhase + } + ret := -x - h.gs.roundPhase + h.gs.roundThreshold + if h.gs.roundSuper45 { + ret /= h.gs.roundPeriod + ret *= h.gs.roundPeriod + } else { + ret &= -h.gs.roundPeriod + } + if ret < 0 { + ret = 0 + } + return -ret - h.gs.roundPhase +} + +func bool2int32(b bool) int32 { + if b { + return 1 + } + return 0 +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/truetype/hint_test.go b/Godeps/_workspace/src/github.com/golang/freetype/truetype/hint_test.go new file mode 100644 index 00000000..7eb43dde --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/truetype/hint_test.go @@ -0,0 +1,675 @@ +// Copyright 2012 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package truetype + +import ( + "reflect" + "strings" + "testing" + + "golang.org/x/image/math/fixed" +) + +func TestBytecode(t *testing.T) { + testCases := []struct { + desc string + prog []byte + want []int32 + errStr string + }{ + { + "underflow", + []byte{ + opDUP, + }, + nil, + "underflow", + }, + { + "infinite loop", + []byte{ + opPUSHW000, // [-1] + 0xff, + 0xff, + opDUP, // [-1, -1] + opJMPR, // [-1] + }, + nil, + "too many steps", + }, + { + "unbalanced if/else", + []byte{ + opPUSHB000, // [0] + 0, + opIF, + }, + nil, + "unbalanced", + }, + { + "vector set/gets", + []byte{ + opSVTCA1, // [] + opGPV, // [0x4000, 0] + opSVTCA0, // [0x4000, 0] + opGFV, // [0x4000, 0, 0, 0x4000] + opNEG, // [0x4000, 0, 0, -0x4000] + opSPVFS, // [0x4000, 0] + opSFVTPV, // [0x4000, 0] + opPUSHB000, // [0x4000, 0, 1] + 1, + opGFV, // [0x4000, 0, 1, 0, -0x4000] + opPUSHB000, // [0x4000, 0, 1, 0, -0x4000, 2] + 2, + }, + []int32{0x4000, 0, 1, 0, -0x4000, 2}, + "", + }, + { + "jumps", + []byte{ + opPUSHB001, // [10, 2] + 10, + 2, + opJMPR, // [10] + opDUP, // not executed + opDUP, // [10, 10] + opPUSHB010, // [10, 10, 20, 2, 1] + 20, + 2, + 1, + opJROT, // [10, 10, 20] + opDUP, // not executed + opDUP, // [10, 10, 20, 20] + opPUSHB010, // [10, 10, 20, 20, 30, 2, 1] + 30, + 2, + 1, + opJROF, // [10, 10, 20, 20, 30] + opDUP, // [10, 10, 20, 20, 30, 30] + opDUP, // [10, 10, 20, 20, 30, 30, 30] + }, + []int32{10, 10, 20, 20, 30, 30, 30}, + "", + }, + { + "stack ops", + []byte{ + opPUSHB010, // [10, 20, 30] + 10, + 20, + 30, + opCLEAR, // [] + opPUSHB010, // [40, 50, 60] + 40, + 50, + 60, + opSWAP, // [40, 60, 50] + opDUP, // [40, 60, 50, 50] + opDUP, // [40, 60, 50, 50, 50] + opPOP, // [40, 60, 50, 50] + opDEPTH, // [40, 60, 50, 50, 4] + opCINDEX, // [40, 60, 50, 50, 40] + opPUSHB000, // [40, 60, 50, 50, 40, 4] + 4, + opMINDEX, // [40, 50, 50, 40, 60] + }, + []int32{40, 50, 50, 40, 60}, + "", + }, + { + "push ops", + []byte{ + opPUSHB000, // [255] + 255, + opPUSHW001, // [255, -2, 253] + 255, + 254, + 0, + 253, + opNPUSHB, // [1, -2, 253, 1, 2] + 2, + 1, + 2, + opNPUSHW, // [1, -2, 253, 1, 2, 0x0405, 0x0607, 0x0809] + 3, + 4, + 5, + 6, + 7, + 8, + 9, + }, + []int32{255, -2, 253, 1, 2, 0x0405, 0x0607, 0x0809}, + "", + }, + { + "store ops", + []byte{ + opPUSHB011, // [1, 22, 3, 44] + 1, + 22, + 3, + 44, + opWS, // [1, 22] + opWS, // [] + opPUSHB000, // [3] + 3, + opRS, // [44] + }, + []int32{44}, + "", + }, + { + "comparison ops", + []byte{ + opPUSHB001, // [10, 20] + 10, + 20, + opLT, // [1] + opPUSHB001, // [1, 10, 20] + 10, + 20, + opLTEQ, // [1, 1] + opPUSHB001, // [1, 1, 10, 20] + 10, + 20, + opGT, // [1, 1, 0] + opPUSHB001, // [1, 1, 0, 10, 20] + 10, + 20, + opGTEQ, // [1, 1, 0, 0] + opEQ, // [1, 1, 1] + opNEQ, // [1, 0] + }, + []int32{1, 0}, + "", + }, + { + "odd/even", + // Calculate odd(2+31/64), odd(2+32/64), even(2), even(1). + []byte{ + opPUSHB000, // [159] + 159, + opODD, // [0] + opPUSHB000, // [0, 160] + 160, + opODD, // [0, 1] + opPUSHB000, // [0, 1, 128] + 128, + opEVEN, // [0, 1, 1] + opPUSHB000, // [0, 1, 1, 64] + 64, + opEVEN, // [0, 1, 1, 0] + }, + []int32{0, 1, 1, 0}, + "", + }, + { + "if true", + []byte{ + opPUSHB001, // [255, 1] + 255, + 1, + opIF, + opPUSHB000, // [255, 2] + 2, + opEIF, + opPUSHB000, // [255, 2, 254] + 254, + }, + []int32{255, 2, 254}, + "", + }, + { + "if false", + []byte{ + opPUSHB001, // [255, 0] + 255, + 0, + opIF, + opPUSHB000, // [255] + 2, + opEIF, + opPUSHB000, // [255, 254] + 254, + }, + []int32{255, 254}, + "", + }, + { + "if/else true", + []byte{ + opPUSHB000, // [1] + 1, + opIF, + opPUSHB000, // [2] + 2, + opELSE, + opPUSHB000, // not executed + 3, + opEIF, + }, + []int32{2}, + "", + }, + { + "if/else false", + []byte{ + opPUSHB000, // [0] + 0, + opIF, + opPUSHB000, // not executed + 2, + opELSE, + opPUSHB000, // [3] + 3, + opEIF, + }, + []int32{3}, + "", + }, + { + "if/else true if/else false", + // 0x58 is the opcode for opIF. The literal 0x58s below are pushed data. + []byte{ + opPUSHB010, // [255, 0, 1] + 255, + 0, + 1, + opIF, + opIF, + opPUSHB001, // not executed + 0x58, + 0x58, + opELSE, + opPUSHW000, // [255, 0x5858] + 0x58, + 0x58, + opEIF, + opELSE, + opIF, + opNPUSHB, // not executed + 3, + 0x58, + 0x58, + 0x58, + opELSE, + opNPUSHW, // not executed + 2, + 0x58, + 0x58, + 0x58, + 0x58, + opEIF, + opEIF, + opPUSHB000, // [255, 0x5858, 254] + 254, + }, + []int32{255, 0x5858, 254}, + "", + }, + { + "if/else false if/else true", + // 0x58 is the opcode for opIF. The literal 0x58s below are pushed data. + []byte{ + opPUSHB010, // [255, 1, 0] + 255, + 1, + 0, + opIF, + opIF, + opPUSHB001, // not executed + 0x58, + 0x58, + opELSE, + opPUSHW000, // not executed + 0x58, + 0x58, + opEIF, + opELSE, + opIF, + opNPUSHB, // [255, 0x58, 0x58, 0x58] + 3, + 0x58, + 0x58, + 0x58, + opELSE, + opNPUSHW, // not executed + 2, + 0x58, + 0x58, + 0x58, + 0x58, + opEIF, + opEIF, + opPUSHB000, // [255, 0x58, 0x58, 0x58, 254] + 254, + }, + []int32{255, 0x58, 0x58, 0x58, 254}, + "", + }, + { + "logical ops", + []byte{ + opPUSHB010, // [0, 10, 20] + 0, + 10, + 20, + opAND, // [0, 1] + opOR, // [1] + opNOT, // [0] + }, + []int32{0}, + "", + }, + { + "arithmetic ops", + // Calculate abs((-(1 - (2*3)))/2 + 1/64). + // The answer is 5/2 + 1/64 in ideal numbers, or 161 in 26.6 fixed point math. + []byte{ + opPUSHB010, // [64, 128, 192] + 1 << 6, + 2 << 6, + 3 << 6, + opMUL, // [64, 384] + opSUB, // [-320] + opNEG, // [320] + opPUSHB000, // [320, 128] + 2 << 6, + opDIV, // [160] + opPUSHB000, // [160, 1] + 1, + opADD, // [161] + opABS, // [161] + }, + []int32{161}, + "", + }, + { + "floor, ceiling", + []byte{ + opPUSHB000, // [96] + 96, + opFLOOR, // [64] + opPUSHB000, // [64, 96] + 96, + opCEILING, // [64, 128] + }, + []int32{64, 128}, + "", + }, + { + "rounding", + // Round 1.40625 (which is 90/64) under various rounding policies. + // See figure 20 of https://developer.apple.com/fonts/TTRefMan/RM02/Chap2.html#rounding + []byte{ + opROFF, // [] + opPUSHB000, // [90] + 90, + opROUND00, // [90] + opRTG, // [90] + opPUSHB000, // [90, 90] + 90, + opROUND00, // [90, 64] + opRTHG, // [90, 64] + opPUSHB000, // [90, 64, 90] + 90, + opROUND00, // [90, 64, 96] + opRDTG, // [90, 64, 96] + opPUSHB000, // [90, 64, 96, 90] + 90, + opROUND00, // [90, 64, 96, 64] + opRUTG, // [90, 64, 96, 64] + opPUSHB000, // [90, 64, 96, 64, 90] + 90, + opROUND00, // [90, 64, 96, 64, 128] + opRTDG, // [90, 64, 96, 64, 128] + opPUSHB000, // [90, 64, 96, 64, 128, 90] + 90, + opROUND00, // [90, 64, 96, 64, 128, 96] + }, + []int32{90, 64, 96, 64, 128, 96}, + "", + }, + { + "super-rounding", + // See figure 20 of https://developer.apple.com/fonts/TTRefMan/RM02/Chap2.html#rounding + // and the sign preservation steps of the "Order of rounding operations" section. + []byte{ + opPUSHB000, // [0x58] + 0x58, + opSROUND, // [] + opPUSHW000, // [-81] + 0xff, + 0xaf, + opROUND00, // [-80] + opPUSHW000, // [-80, -80] + 0xff, + 0xb0, + opROUND00, // [-80, -80] + opPUSHW000, // [-80, -80, -17] + 0xff, + 0xef, + opROUND00, // [-80, -80, -16] + opPUSHW000, // [-80, -80, -16, -16] + 0xff, + 0xf0, + opROUND00, // [-80, -80, -16, -16] + opPUSHB000, // [-80, -80, -16, -16, 0] + 0, + opROUND00, // [-80, -80, -16, -16, 16] + opPUSHB000, // [-80, -80, -16, -16, 16, 16] + 16, + opROUND00, // [-80, -80, -16, -16, 16, 16] + opPUSHB000, // [-80, -80, -16, -16, 16, 16, 47] + 47, + opROUND00, // [-80, -80, -16, -16, 16, 16, 16] + opPUSHB000, // [-80, -80, -16, -16, 16, 16, 16, 48] + 48, + opROUND00, // [-80, -80, -16, -16, 16, 16, 16, 80] + }, + []int32{-80, -80, -16, -16, 16, 16, 16, 80}, + "", + }, + { + "roll", + []byte{ + opPUSHB010, // [1, 2, 3] + 1, + 2, + 3, + opROLL, // [2, 3, 1] + }, + []int32{2, 3, 1}, + "", + }, + { + "max/min", + []byte{ + opPUSHW001, // [-2, -3] + 0xff, + 0xfe, + 0xff, + 0xfd, + opMAX, // [-2] + opPUSHW001, // [-2, -4, -5] + 0xff, + 0xfc, + 0xff, + 0xfb, + opMIN, // [-2, -5] + }, + []int32{-2, -5}, + "", + }, + { + "functions", + []byte{ + opPUSHB011, // [3, 7, 0, 3] + 3, + 7, + 0, + 3, + + opFDEF, // Function #3 (not called) + opPUSHB000, + 98, + opENDF, + + opFDEF, // Function #0 + opDUP, + opADD, + opENDF, + + opFDEF, // Function #7 + opPUSHB001, + 10, + 0, + opCALL, + opDUP, + opENDF, + + opFDEF, // Function #3 (again) + opPUSHB000, + 99, + opENDF, + + opPUSHB001, // [2, 0] + 2, + 0, + opCALL, // [4] + opPUSHB000, // [4, 3] + 3, + opLOOPCALL, // [99, 99, 99, 99] + opPUSHB000, // [99, 99, 99, 99, 7] + 7, + opCALL, // [99, 99, 99, 99, 20, 20] + }, + []int32{99, 99, 99, 99, 20, 20}, + "", + }, + } + + for _, tc := range testCases { + h := &hinter{} + h.init(&Font{ + maxStorage: 32, + maxStackElements: 100, + }, 768) + err, errStr := h.run(tc.prog, nil, nil, nil, nil), "" + if err != nil { + errStr = err.Error() + } + if tc.errStr != "" { + if errStr == "" { + t.Errorf("%s: got no error, want %q", tc.desc, tc.errStr) + } else if !strings.Contains(errStr, tc.errStr) { + t.Errorf("%s: got error %q, want one containing %q", tc.desc, errStr, tc.errStr) + } + continue + } + if errStr != "" { + t.Errorf("%s: got error %q, want none", tc.desc, errStr) + continue + } + got := h.stack[:len(tc.want)] + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("%s: got %v, want %v", tc.desc, got, tc.want) + continue + } + } +} + +// TestMove tests that the hinter.move method matches the output of the C +// Freetype implementation. +func TestMove(t *testing.T) { + h, p := hinter{}, Point{} + testCases := []struct { + pvX, pvY, fvX, fvY f2dot14 + wantX, wantY fixed.Int26_6 + }{ + {+0x4000, +0x0000, +0x4000, +0x0000, +1000, +0}, + {+0x4000, +0x0000, -0x4000, +0x0000, +1000, +0}, + {-0x4000, +0x0000, +0x4000, +0x0000, -1000, +0}, + {-0x4000, +0x0000, -0x4000, +0x0000, -1000, +0}, + {+0x0000, +0x4000, +0x0000, +0x4000, +0, +1000}, + {+0x0000, +0x4000, +0x0000, -0x4000, +0, +1000}, + {+0x4000, +0x0000, +0x2d41, +0x2d41, +1000, +1000}, + {+0x4000, +0x0000, -0x2d41, +0x2d41, +1000, -1000}, + {+0x4000, +0x0000, +0x2d41, -0x2d41, +1000, -1000}, + {+0x4000, +0x0000, -0x2d41, -0x2d41, +1000, +1000}, + {-0x4000, +0x0000, +0x2d41, +0x2d41, -1000, -1000}, + {-0x4000, +0x0000, -0x2d41, +0x2d41, -1000, +1000}, + {-0x4000, +0x0000, +0x2d41, -0x2d41, -1000, +1000}, + {-0x4000, +0x0000, -0x2d41, -0x2d41, -1000, -1000}, + {+0x376d, +0x2000, +0x2d41, +0x2d41, +732, +732}, + {-0x376d, +0x2000, +0x2d41, +0x2d41, -2732, -2732}, + {+0x376d, +0x2000, +0x2d41, -0x2d41, +2732, -2732}, + {-0x376d, +0x2000, +0x2d41, -0x2d41, -732, +732}, + {-0x376d, -0x2000, +0x2d41, +0x2d41, -732, -732}, + {+0x376d, +0x2000, +0x4000, +0x0000, +1155, +0}, + {+0x376d, +0x2000, +0x0000, +0x4000, +0, +2000}, + } + for _, tc := range testCases { + p = Point{} + h.gs.pv = [2]f2dot14{tc.pvX, tc.pvY} + h.gs.fv = [2]f2dot14{tc.fvX, tc.fvY} + h.move(&p, 1000, true) + tx := p.Flags&flagTouchedX != 0 + ty := p.Flags&flagTouchedY != 0 + wantTX := tc.fvX != 0 + wantTY := tc.fvY != 0 + if p.X != tc.wantX || p.Y != tc.wantY || tx != wantTX || ty != wantTY { + t.Errorf("pv=%v, fv=%v\ngot %d, %d, %t, %t\nwant %d, %d, %t, %t", + h.gs.pv, h.gs.fv, p.X, p.Y, tx, ty, tc.wantX, tc.wantY, wantTX, wantTY) + continue + } + + // Check that p is aligned with the freedom vector. + a := int64(p.X) * int64(tc.fvY) + b := int64(p.Y) * int64(tc.fvX) + if a != b { + t.Errorf("pv=%v, fv=%v, p=%v not aligned with fv", h.gs.pv, h.gs.fv, p) + continue + } + + // Check that the projected p is 1000 away from the origin. + dotProd := (int64(p.X)*int64(tc.pvX) + int64(p.Y)*int64(tc.pvY) + 1<<13) >> 14 + if dotProd != 1000 { + t.Errorf("pv=%v, fv=%v, p=%v not 1000 from origin", h.gs.pv, h.gs.fv, p) + continue + } + } +} + +// TestNormalize tests that the normalize function matches the output of the C +// Freetype implementation. +func TestNormalize(t *testing.T) { + testCases := [][2]f2dot14{ + {-15895, 3974}, + {-15543, 5181}, + {-14654, 7327}, + {-11585, 11585}, + {0, 16384}, + {11585, 11585}, + {14654, 7327}, + {15543, 5181}, + {15895, 3974}, + {16066, 3213}, + {16161, 2694}, + {16219, 2317}, + {16257, 2032}, + {16284, 1809}, + } + for i, want := range testCases { + got := normalize(f2dot14(i)-4, 1) + if got != want { + t.Errorf("i=%d: got %v, want %v", i, got, want) + } + } +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/truetype/opcodes.go b/Godeps/_workspace/src/github.com/golang/freetype/truetype/opcodes.go new file mode 100644 index 00000000..1880e1e6 --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/truetype/opcodes.go @@ -0,0 +1,289 @@ +// Copyright 2012 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package truetype + +// The Truetype opcodes are summarized at +// https://developer.apple.com/fonts/TTRefMan/RM07/appendixA.html + +const ( + opSVTCA0 = 0x00 // Set freedom and projection Vectors To Coordinate Axis + opSVTCA1 = 0x01 // . + opSPVTCA0 = 0x02 // Set Projection Vector To Coordinate Axis + opSPVTCA1 = 0x03 // . + opSFVTCA0 = 0x04 // Set Freedom Vector to Coordinate Axis + opSFVTCA1 = 0x05 // . + opSPVTL0 = 0x06 // Set Projection Vector To Line + opSPVTL1 = 0x07 // . + opSFVTL0 = 0x08 // Set Freedom Vector To Line + opSFVTL1 = 0x09 // . + opSPVFS = 0x0a // Set Projection Vector From Stack + opSFVFS = 0x0b // Set Freedom Vector From Stack + opGPV = 0x0c // Get Projection Vector + opGFV = 0x0d // Get Freedom Vector + opSFVTPV = 0x0e // Set Freedom Vector To Projection Vector + opISECT = 0x0f // moves point p to the InterSECTion of two lines + opSRP0 = 0x10 // Set Reference Point 0 + opSRP1 = 0x11 // Set Reference Point 1 + opSRP2 = 0x12 // Set Reference Point 2 + opSZP0 = 0x13 // Set Zone Pointer 0 + opSZP1 = 0x14 // Set Zone Pointer 1 + opSZP2 = 0x15 // Set Zone Pointer 2 + opSZPS = 0x16 // Set Zone PointerS + opSLOOP = 0x17 // Set LOOP variable + opRTG = 0x18 // Round To Grid + opRTHG = 0x19 // Round To Half Grid + opSMD = 0x1a // Set Minimum Distance + opELSE = 0x1b // ELSE clause + opJMPR = 0x1c // JuMP Relative + opSCVTCI = 0x1d // Set Control Value Table Cut-In + opSSWCI = 0x1e // Set Single Width Cut-In + opSSW = 0x1f // Set Single Width + opDUP = 0x20 // DUPlicate top stack element + opPOP = 0x21 // POP top stack element + opCLEAR = 0x22 // CLEAR the stack + opSWAP = 0x23 // SWAP the top two elements on the stack + opDEPTH = 0x24 // DEPTH of the stack + opCINDEX = 0x25 // Copy the INDEXed element to the top of the stack + opMINDEX = 0x26 // Move the INDEXed element to the top of the stack + opALIGNPTS = 0x27 // ALIGN PoinTS + op_0x28 = 0x28 // deprecated + opUTP = 0x29 // UnTouch Point + opLOOPCALL = 0x2a // LOOP and CALL function + opCALL = 0x2b // CALL function + opFDEF = 0x2c // Function DEFinition + opENDF = 0x2d // END Function definition + opMDAP0 = 0x2e // Move Direct Absolute Point + opMDAP1 = 0x2f // . + opIUP0 = 0x30 // Interpolate Untouched Points through the outline + opIUP1 = 0x31 // . + opSHP0 = 0x32 // SHift Point using reference point + opSHP1 = 0x33 // . + opSHC0 = 0x34 // SHift Contour using reference point + opSHC1 = 0x35 // . + opSHZ0 = 0x36 // SHift Zone using reference point + opSHZ1 = 0x37 // . + opSHPIX = 0x38 // SHift point by a PIXel amount + opIP = 0x39 // Interpolate Point + opMSIRP0 = 0x3a // Move Stack Indirect Relative Point + opMSIRP1 = 0x3b // . + opALIGNRP = 0x3c // ALIGN to Reference Point + opRTDG = 0x3d // Round To Double Grid + opMIAP0 = 0x3e // Move Indirect Absolute Point + opMIAP1 = 0x3f // . + opNPUSHB = 0x40 // PUSH N Bytes + opNPUSHW = 0x41 // PUSH N Words + opWS = 0x42 // Write Store + opRS = 0x43 // Read Store + opWCVTP = 0x44 // Write Control Value Table in Pixel units + opRCVT = 0x45 // Read Control Value Table entry + opGC0 = 0x46 // Get Coordinate projected onto the projection vector + opGC1 = 0x47 // . + opSCFS = 0x48 // Sets Coordinate From the Stack using projection vector and freedom vector + opMD0 = 0x49 // Measure Distance + opMD1 = 0x4a // . + opMPPEM = 0x4b // Measure Pixels Per EM + opMPS = 0x4c // Measure Point Size + opFLIPON = 0x4d // set the auto FLIP Boolean to ON + opFLIPOFF = 0x4e // set the auto FLIP Boolean to OFF + opDEBUG = 0x4f // DEBUG call + opLT = 0x50 // Less Than + opLTEQ = 0x51 // Less Than or EQual + opGT = 0x52 // Greater Than + opGTEQ = 0x53 // Greater Than or EQual + opEQ = 0x54 // EQual + opNEQ = 0x55 // Not EQual + opODD = 0x56 // ODD + opEVEN = 0x57 // EVEN + opIF = 0x58 // IF test + opEIF = 0x59 // End IF + opAND = 0x5a // logical AND + opOR = 0x5b // logical OR + opNOT = 0x5c // logical NOT + opDELTAP1 = 0x5d // DELTA exception P1 + opSDB = 0x5e // Set Delta Base in the graphics state + opSDS = 0x5f // Set Delta Shift in the graphics state + opADD = 0x60 // ADD + opSUB = 0x61 // SUBtract + opDIV = 0x62 // DIVide + opMUL = 0x63 // MULtiply + opABS = 0x64 // ABSolute value + opNEG = 0x65 // NEGate + opFLOOR = 0x66 // FLOOR + opCEILING = 0x67 // CEILING + opROUND00 = 0x68 // ROUND value + opROUND01 = 0x69 // . + opROUND10 = 0x6a // . + opROUND11 = 0x6b // . + opNROUND00 = 0x6c // No ROUNDing of value + opNROUND01 = 0x6d // . + opNROUND10 = 0x6e // . + opNROUND11 = 0x6f // . + opWCVTF = 0x70 // Write Control Value Table in Funits + opDELTAP2 = 0x71 // DELTA exception P2 + opDELTAP3 = 0x72 // DELTA exception P3 + opDELTAC1 = 0x73 // DELTA exception C1 + opDELTAC2 = 0x74 // DELTA exception C2 + opDELTAC3 = 0x75 // DELTA exception C3 + opSROUND = 0x76 // Super ROUND + opS45ROUND = 0x77 // Super ROUND 45 degrees + opJROT = 0x78 // Jump Relative On True + opJROF = 0x79 // Jump Relative On False + opROFF = 0x7a // Round OFF + op_0x7b = 0x7b // deprecated + opRUTG = 0x7c // Round Up To Grid + opRDTG = 0x7d // Round Down To Grid + opSANGW = 0x7e // Set ANGle Weight + opAA = 0x7f // Adjust Angle + opFLIPPT = 0x80 // FLIP PoinT + opFLIPRGON = 0x81 // FLIP RanGe ON + opFLIPRGOFF = 0x82 // FLIP RanGe OFF + op_0x83 = 0x83 // deprecated + op_0x84 = 0x84 // deprecated + opSCANCTRL = 0x85 // SCAN conversion ConTRoL + opSDPVTL0 = 0x86 // Set Dual Projection Vector To Line + opSDPVTL1 = 0x87 // . + opGETINFO = 0x88 // GET INFOrmation + opIDEF = 0x89 // Instruction DEFinition + opROLL = 0x8a // ROLL the top three stack elements + opMAX = 0x8b // MAXimum of top two stack elements + opMIN = 0x8c // MINimum of top two stack elements + opSCANTYPE = 0x8d // SCANTYPE + opINSTCTRL = 0x8e // INSTRuction execution ConTRoL + op_0x8f = 0x8f + op_0x90 = 0x90 + op_0x91 = 0x91 + op_0x92 = 0x92 + op_0x93 = 0x93 + op_0x94 = 0x94 + op_0x95 = 0x95 + op_0x96 = 0x96 + op_0x97 = 0x97 + op_0x98 = 0x98 + op_0x99 = 0x99 + op_0x9a = 0x9a + op_0x9b = 0x9b + op_0x9c = 0x9c + op_0x9d = 0x9d + op_0x9e = 0x9e + op_0x9f = 0x9f + op_0xa0 = 0xa0 + op_0xa1 = 0xa1 + op_0xa2 = 0xa2 + op_0xa3 = 0xa3 + op_0xa4 = 0xa4 + op_0xa5 = 0xa5 + op_0xa6 = 0xa6 + op_0xa7 = 0xa7 + op_0xa8 = 0xa8 + op_0xa9 = 0xa9 + op_0xaa = 0xaa + op_0xab = 0xab + op_0xac = 0xac + op_0xad = 0xad + op_0xae = 0xae + op_0xaf = 0xaf + opPUSHB000 = 0xb0 // PUSH Bytes + opPUSHB001 = 0xb1 // . + opPUSHB010 = 0xb2 // . + opPUSHB011 = 0xb3 // . + opPUSHB100 = 0xb4 // . + opPUSHB101 = 0xb5 // . + opPUSHB110 = 0xb6 // . + opPUSHB111 = 0xb7 // . + opPUSHW000 = 0xb8 // PUSH Words + opPUSHW001 = 0xb9 // . + opPUSHW010 = 0xba // . + opPUSHW011 = 0xbb // . + opPUSHW100 = 0xbc // . + opPUSHW101 = 0xbd // . + opPUSHW110 = 0xbe // . + opPUSHW111 = 0xbf // . + opMDRP00000 = 0xc0 // Move Direct Relative Point + opMDRP00001 = 0xc1 // . + opMDRP00010 = 0xc2 // . + opMDRP00011 = 0xc3 // . + opMDRP00100 = 0xc4 // . + opMDRP00101 = 0xc5 // . + opMDRP00110 = 0xc6 // . + opMDRP00111 = 0xc7 // . + opMDRP01000 = 0xc8 // . + opMDRP01001 = 0xc9 // . + opMDRP01010 = 0xca // . + opMDRP01011 = 0xcb // . + opMDRP01100 = 0xcc // . + opMDRP01101 = 0xcd // . + opMDRP01110 = 0xce // . + opMDRP01111 = 0xcf // . + opMDRP10000 = 0xd0 // . + opMDRP10001 = 0xd1 // . + opMDRP10010 = 0xd2 // . + opMDRP10011 = 0xd3 // . + opMDRP10100 = 0xd4 // . + opMDRP10101 = 0xd5 // . + opMDRP10110 = 0xd6 // . + opMDRP10111 = 0xd7 // . + opMDRP11000 = 0xd8 // . + opMDRP11001 = 0xd9 // . + opMDRP11010 = 0xda // . + opMDRP11011 = 0xdb // . + opMDRP11100 = 0xdc // . + opMDRP11101 = 0xdd // . + opMDRP11110 = 0xde // . + opMDRP11111 = 0xdf // . + opMIRP00000 = 0xe0 // Move Indirect Relative Point + opMIRP00001 = 0xe1 // . + opMIRP00010 = 0xe2 // . + opMIRP00011 = 0xe3 // . + opMIRP00100 = 0xe4 // . + opMIRP00101 = 0xe5 // . + opMIRP00110 = 0xe6 // . + opMIRP00111 = 0xe7 // . + opMIRP01000 = 0xe8 // . + opMIRP01001 = 0xe9 // . + opMIRP01010 = 0xea // . + opMIRP01011 = 0xeb // . + opMIRP01100 = 0xec // . + opMIRP01101 = 0xed // . + opMIRP01110 = 0xee // . + opMIRP01111 = 0xef // . + opMIRP10000 = 0xf0 // . + opMIRP10001 = 0xf1 // . + opMIRP10010 = 0xf2 // . + opMIRP10011 = 0xf3 // . + opMIRP10100 = 0xf4 // . + opMIRP10101 = 0xf5 // . + opMIRP10110 = 0xf6 // . + opMIRP10111 = 0xf7 // . + opMIRP11000 = 0xf8 // . + opMIRP11001 = 0xf9 // . + opMIRP11010 = 0xfa // . + opMIRP11011 = 0xfb // . + opMIRP11100 = 0xfc // . + opMIRP11101 = 0xfd // . + opMIRP11110 = 0xfe // . + opMIRP11111 = 0xff // . +) + +// popCount is the number of stack elements that each opcode pops. +var popCount = [256]uint8{ + // 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 5, // 0x00 - 0x0f + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, // 0x10 - 0x1f + 1, 1, 0, 2, 0, 1, 1, 2, 0, 1, 2, 1, 1, 0, 1, 1, // 0x20 - 0x2f + 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 2, 2, 0, 0, 2, 2, // 0x30 - 0x3f + 0, 0, 2, 1, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, // 0x40 - 0x4f + 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 2, 2, 1, 1, 1, 1, // 0x50 - 0x5f + 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 0x6f + 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 1, 1, // 0x70 - 0x7f + 0, 2, 2, 0, 0, 1, 2, 2, 1, 1, 3, 2, 2, 1, 2, 0, // 0x80 - 0x8f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90 - 0x9f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0 - 0xaf + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0 - 0xbf + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xc0 - 0xcf + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xd0 - 0xdf + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xe0 - 0xef + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xf0 - 0xff +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/truetype/truetype.go b/Godeps/_workspace/src/github.com/golang/freetype/truetype/truetype.go new file mode 100644 index 00000000..75cb733b --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/truetype/truetype.go @@ -0,0 +1,639 @@ +// Copyright 2010 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +// Package truetype provides a parser for the TTF and TTC file formats. +// Those formats are documented at http://developer.apple.com/fonts/TTRefMan/ +// and http://www.microsoft.com/typography/otspec/ +// +// Some of a font's methods provide lengths or co-ordinates, e.g. bounds, font +// metrics and control points. All these methods take a scale parameter, which +// is the number of pixels in 1 em, expressed as a 26.6 fixed point value. For +// example, if 1 em is 10 pixels then scale is fixed.I(10), which is equal to +// fixed.Int26_6(10 << 6). +// +// To measure a TrueType font in ideal FUnit space, use scale equal to +// font.FUnitsPerEm(). +package truetype // import "github.com/golang/freetype/truetype" + +import ( + "fmt" + + "golang.org/x/image/math/fixed" +) + +// An Index is a Font's index of a rune. +type Index uint16 + +// A NameID identifies a name table entry. +// +// See https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html +type NameID uint16 + +const ( + NameIDCopyright NameID = 0 + NameIDFontFamily = 1 + NameIDFontSubfamily = 2 + NameIDUniqueSubfamilyID = 3 + NameIDFontFullName = 4 + NameIDNameTableVersion = 5 + NameIDPostscriptName = 6 + NameIDTrademarkNotice = 7 + NameIDManufacturerName = 8 + NameIDDesignerName = 9 + NameIDFontDescription = 10 + NameIDFontVendorURL = 11 + NameIDFontDesignerURL = 12 + NameIDFontLicense = 13 + NameIDFontLicenseURL = 14 + NameIDPreferredFamily = 16 + NameIDPreferredSubfamily = 17 + NameIDCompatibleName = 18 + NameIDSampleText = 19 +) + +const ( + // A 32-bit encoding consists of a most-significant 16-bit Platform ID and a + // least-significant 16-bit Platform Specific ID. The magic numbers are + // specified at https://www.microsoft.com/typography/otspec/name.htm + unicodeEncoding = 0x00000003 // PID = 0 (Unicode), PSID = 3 (Unicode 2.0) + microsoftSymbolEncoding = 0x00030000 // PID = 3 (Microsoft), PSID = 0 (Symbol) + microsoftUCS2Encoding = 0x00030001 // PID = 3 (Microsoft), PSID = 1 (UCS-2) + microsoftUCS4Encoding = 0x0003000a // PID = 3 (Microsoft), PSID = 10 (UCS-4) +) + +// An HMetric holds the horizontal metrics of a single glyph. +type HMetric struct { + AdvanceWidth, LeftSideBearing fixed.Int26_6 +} + +// A VMetric holds the vertical metrics of a single glyph. +type VMetric struct { + AdvanceHeight, TopSideBearing fixed.Int26_6 +} + +// A FormatError reports that the input is not a valid TrueType font. +type FormatError string + +func (e FormatError) Error() string { + return "freetype: invalid TrueType format: " + string(e) +} + +// An UnsupportedError reports that the input uses a valid but unimplemented +// TrueType feature. +type UnsupportedError string + +func (e UnsupportedError) Error() string { + return "freetype: unsupported TrueType feature: " + string(e) +} + +// u32 returns the big-endian uint32 at b[i:]. +func u32(b []byte, i int) uint32 { + return uint32(b[i])<<24 | uint32(b[i+1])<<16 | uint32(b[i+2])<<8 | uint32(b[i+3]) +} + +// u16 returns the big-endian uint16 at b[i:]. +func u16(b []byte, i int) uint16 { + return uint16(b[i])<<8 | uint16(b[i+1]) +} + +// readTable returns a slice of the TTF data given by a table's directory entry. +func readTable(ttf []byte, offsetLength []byte) ([]byte, error) { + offset := int(u32(offsetLength, 0)) + if offset < 0 { + return nil, FormatError(fmt.Sprintf("offset too large: %d", uint32(offset))) + } + length := int(u32(offsetLength, 4)) + if length < 0 { + return nil, FormatError(fmt.Sprintf("length too large: %d", uint32(length))) + } + end := offset + length + if end < 0 || end > len(ttf) { + return nil, FormatError(fmt.Sprintf("offset + length too large: %d", uint32(offset)+uint32(length))) + } + return ttf[offset:end], nil +} + +// parseSubtables returns the offset and platformID of the best subtable in +// table, where best favors a Unicode cmap encoding, and failing that, a +// Microsoft cmap encoding. offset is the offset of the first subtable in +// table, and size is the size of each subtable. +// +// If pred is non-nil, then only subtables that satisfy that predicate will be +// considered. +func parseSubtables(table []byte, name string, offset, size int, pred func([]byte) bool) ( + bestOffset int, bestPID uint32, retErr error) { + + if len(table) < 4 { + return 0, 0, FormatError(name + " too short") + } + nSubtables := int(u16(table, 2)) + if len(table) < size*nSubtables+offset { + return 0, 0, FormatError(name + " too short") + } + ok := false + for i := 0; i < nSubtables; i, offset = i+1, offset+size { + if pred != nil && !pred(table[offset:]) { + continue + } + // We read the 16-bit Platform ID and 16-bit Platform Specific ID as a single uint32. + // All values are big-endian. + pidPsid := u32(table, offset) + // We prefer the Unicode cmap encoding. Failing to find that, we fall + // back onto the Microsoft cmap encoding. + if pidPsid == unicodeEncoding { + bestOffset, bestPID, ok = offset, pidPsid>>16, true + break + + } else if pidPsid == microsoftSymbolEncoding || + pidPsid == microsoftUCS2Encoding || + pidPsid == microsoftUCS4Encoding { + + bestOffset, bestPID, ok = offset, pidPsid>>16, true + // We don't break out of the for loop, so that Unicode can override Microsoft. + } + } + if !ok { + return 0, 0, UnsupportedError(name + " encoding") + } + return bestOffset, bestPID, nil +} + +const ( + locaOffsetFormatUnknown int = iota + locaOffsetFormatShort + locaOffsetFormatLong +) + +// A cm holds a parsed cmap entry. +type cm struct { + start, end, delta, offset uint32 +} + +// A Font represents a Truetype font. +type Font struct { + // Tables sliced from the TTF data. The different tables are documented + // at http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html + cmap, cvt, fpgm, glyf, hdmx, head, hhea, hmtx, kern, loca, maxp, name, os2, prep, vmtx []byte + + cmapIndexes []byte + + // Cached values derived from the raw ttf data. + cm []cm + locaOffsetFormat int + nGlyph, nHMetric, nKern int + fUnitsPerEm int32 + bounds fixed.Rectangle26_6 + // Values from the maxp section. + maxTwilightPoints, maxStorage, maxFunctionDefs, maxStackElements uint16 +} + +func (f *Font) parseCmap() error { + const ( + cmapFormat4 = 4 + cmapFormat12 = 12 + languageIndependent = 0 + ) + + offset, _, err := parseSubtables(f.cmap, "cmap", 4, 8, nil) + if err != nil { + return err + } + offset = int(u32(f.cmap, offset+4)) + if offset <= 0 || offset > len(f.cmap) { + return FormatError("bad cmap offset") + } + + cmapFormat := u16(f.cmap, offset) + switch cmapFormat { + case cmapFormat4: + language := u16(f.cmap, offset+4) + if language != languageIndependent { + return UnsupportedError(fmt.Sprintf("language: %d", language)) + } + segCountX2 := int(u16(f.cmap, offset+6)) + if segCountX2%2 == 1 { + return FormatError(fmt.Sprintf("bad segCountX2: %d", segCountX2)) + } + segCount := segCountX2 / 2 + offset += 14 + f.cm = make([]cm, segCount) + for i := 0; i < segCount; i++ { + f.cm[i].end = uint32(u16(f.cmap, offset)) + offset += 2 + } + offset += 2 + for i := 0; i < segCount; i++ { + f.cm[i].start = uint32(u16(f.cmap, offset)) + offset += 2 + } + for i := 0; i < segCount; i++ { + f.cm[i].delta = uint32(u16(f.cmap, offset)) + offset += 2 + } + for i := 0; i < segCount; i++ { + f.cm[i].offset = uint32(u16(f.cmap, offset)) + offset += 2 + } + f.cmapIndexes = f.cmap[offset:] + return nil + + case cmapFormat12: + if u16(f.cmap, offset+2) != 0 { + return FormatError(fmt.Sprintf("cmap format: % x", f.cmap[offset:offset+4])) + } + length := u32(f.cmap, offset+4) + language := u32(f.cmap, offset+8) + if language != languageIndependent { + return UnsupportedError(fmt.Sprintf("language: %d", language)) + } + nGroups := u32(f.cmap, offset+12) + if length != 12*nGroups+16 { + return FormatError("inconsistent cmap length") + } + offset += 16 + f.cm = make([]cm, nGroups) + for i := uint32(0); i < nGroups; i++ { + f.cm[i].start = u32(f.cmap, offset+0) + f.cm[i].end = u32(f.cmap, offset+4) + f.cm[i].delta = u32(f.cmap, offset+8) - f.cm[i].start + offset += 12 + } + return nil + } + return UnsupportedError(fmt.Sprintf("cmap format: %d", cmapFormat)) +} + +func (f *Font) parseHead() error { + if len(f.head) != 54 { + return FormatError(fmt.Sprintf("bad head length: %d", len(f.head))) + } + f.fUnitsPerEm = int32(u16(f.head, 18)) + f.bounds.Min.X = fixed.Int26_6(int16(u16(f.head, 36))) + f.bounds.Min.Y = fixed.Int26_6(int16(u16(f.head, 38))) + f.bounds.Max.X = fixed.Int26_6(int16(u16(f.head, 40))) + f.bounds.Max.Y = fixed.Int26_6(int16(u16(f.head, 42))) + switch i := u16(f.head, 50); i { + case 0: + f.locaOffsetFormat = locaOffsetFormatShort + case 1: + f.locaOffsetFormat = locaOffsetFormatLong + default: + return FormatError(fmt.Sprintf("bad indexToLocFormat: %d", i)) + } + return nil +} + +func (f *Font) parseHhea() error { + if len(f.hhea) != 36 { + return FormatError(fmt.Sprintf("bad hhea length: %d", len(f.hhea))) + } + f.nHMetric = int(u16(f.hhea, 34)) + if 4*f.nHMetric+2*(f.nGlyph-f.nHMetric) != len(f.hmtx) { + return FormatError(fmt.Sprintf("bad hmtx length: %d", len(f.hmtx))) + } + return nil +} + +func (f *Font) parseKern() error { + // Apple's TrueType documentation (http://developer.apple.com/fonts/TTRefMan/RM06/Chap6kern.html) says: + // "Previous versions of the 'kern' table defined both the version and nTables fields in the header + // as UInt16 values and not UInt32 values. Use of the older format on the Mac OS is discouraged + // (although AAT can sense an old kerning table and still make correct use of it). Microsoft + // Windows still uses the older format for the 'kern' table and will not recognize the newer one. + // Fonts targeted for the Mac OS only should use the new format; fonts targeted for both the Mac OS + // and Windows should use the old format." + // Since we expect that almost all fonts aim to be Windows-compatible, we only parse the "older" format, + // just like the C Freetype implementation. + if len(f.kern) == 0 { + if f.nKern != 0 { + return FormatError("bad kern table length") + } + return nil + } + if len(f.kern) < 18 { + return FormatError("kern data too short") + } + version, offset := u16(f.kern, 0), 2 + if version != 0 { + return UnsupportedError(fmt.Sprintf("kern version: %d", version)) + } + n, offset := u16(f.kern, offset), offset+2 + if n != 1 { + return UnsupportedError(fmt.Sprintf("kern nTables: %d", n)) + } + offset += 2 + length, offset := int(u16(f.kern, offset)), offset+2 + coverage, offset := u16(f.kern, offset), offset+2 + if coverage != 0x0001 { + // We only support horizontal kerning. + return UnsupportedError(fmt.Sprintf("kern coverage: 0x%04x", coverage)) + } + f.nKern, offset = int(u16(f.kern, offset)), offset+2 + if 6*f.nKern != length-14 { + return FormatError("bad kern table length") + } + return nil +} + +func (f *Font) parseMaxp() error { + if len(f.maxp) != 32 { + return FormatError(fmt.Sprintf("bad maxp length: %d", len(f.maxp))) + } + f.nGlyph = int(u16(f.maxp, 4)) + f.maxTwilightPoints = u16(f.maxp, 16) + f.maxStorage = u16(f.maxp, 18) + f.maxFunctionDefs = u16(f.maxp, 20) + f.maxStackElements = u16(f.maxp, 24) + return nil +} + +// scale returns x divided by f.fUnitsPerEm, rounded to the nearest integer. +func (f *Font) scale(x fixed.Int26_6) fixed.Int26_6 { + if x >= 0 { + x += fixed.Int26_6(f.fUnitsPerEm) / 2 + } else { + x -= fixed.Int26_6(f.fUnitsPerEm) / 2 + } + return x / fixed.Int26_6(f.fUnitsPerEm) +} + +// Bounds returns the union of a Font's glyphs' bounds. +func (f *Font) Bounds(scale fixed.Int26_6) fixed.Rectangle26_6 { + b := f.bounds + b.Min.X = f.scale(scale * b.Min.X) + b.Min.Y = f.scale(scale * b.Min.Y) + b.Max.X = f.scale(scale * b.Max.X) + b.Max.Y = f.scale(scale * b.Max.Y) + return b +} + +// FUnitsPerEm returns the number of FUnits in a Font's em-square's side. +func (f *Font) FUnitsPerEm() int32 { + return f.fUnitsPerEm +} + +// Index returns a Font's index for the given rune. +func (f *Font) Index(x rune) Index { + c := uint32(x) + for i, j := 0, len(f.cm); i < j; { + h := i + (j-i)/2 + cm := &f.cm[h] + if c < cm.start { + j = h + } else if cm.end < c { + i = h + 1 + } else if cm.offset == 0 { + return Index(c + cm.delta) + } else { + offset := int(cm.offset) + 2*(h-len(f.cm)+int(c-cm.start)) + return Index(u16(f.cmapIndexes, offset)) + } + } + return 0 +} + +// Name returns the Font's name value for the given NameID. It returns "" if +// there was an error, or if that name was not found. +func (f *Font) Name(id NameID) string { + x, platformID, err := parseSubtables(f.name, "name", 6, 12, func(b []byte) bool { + return NameID(u16(b, 6)) == id + }) + if err != nil { + return "" + } + offset, length := u16(f.name, 4)+u16(f.name, x+10), u16(f.name, x+8) + // Return the ASCII value of the encoded string. + // The string is encoded as UTF-16 on non-Apple platformIDs; Apple is platformID 1. + src := f.name[offset : offset+length] + var dst []byte + if platformID != 1 { // UTF-16. + if len(src)&1 != 0 { + return "" + } + dst = make([]byte, len(src)/2) + for i := range dst { + dst[i] = printable(u16(src, 2*i)) + } + } else { // ASCII. + dst = make([]byte, len(src)) + for i, c := range src { + dst[i] = printable(uint16(c)) + } + } + return string(dst) +} + +func printable(r uint16) byte { + if 0x20 <= r && r < 0x7f { + return byte(r) + } + return '?' +} + +// unscaledHMetric returns the unscaled horizontal metrics for the glyph with +// the given index. +func (f *Font) unscaledHMetric(i Index) (h HMetric) { + j := int(i) + if j < 0 || f.nGlyph <= j { + return HMetric{} + } + if j >= f.nHMetric { + p := 4 * (f.nHMetric - 1) + return HMetric{ + AdvanceWidth: fixed.Int26_6(u16(f.hmtx, p)), + LeftSideBearing: fixed.Int26_6(int16(u16(f.hmtx, p+2*(j-f.nHMetric)+4))), + } + } + return HMetric{ + AdvanceWidth: fixed.Int26_6(u16(f.hmtx, 4*j)), + LeftSideBearing: fixed.Int26_6(int16(u16(f.hmtx, 4*j+2))), + } +} + +// HMetric returns the horizontal metrics for the glyph with the given index. +func (f *Font) HMetric(scale fixed.Int26_6, i Index) HMetric { + h := f.unscaledHMetric(i) + h.AdvanceWidth = f.scale(scale * h.AdvanceWidth) + h.LeftSideBearing = f.scale(scale * h.LeftSideBearing) + return h +} + +// unscaledVMetric returns the unscaled vertical metrics for the glyph with +// the given index. yMax is the top of the glyph's bounding box. +func (f *Font) unscaledVMetric(i Index, yMax fixed.Int26_6) (v VMetric) { + j := int(i) + if j < 0 || f.nGlyph <= j { + return VMetric{} + } + if 4*j+4 <= len(f.vmtx) { + return VMetric{ + AdvanceHeight: fixed.Int26_6(u16(f.vmtx, 4*j)), + TopSideBearing: fixed.Int26_6(int16(u16(f.vmtx, 4*j+2))), + } + } + // The OS/2 table has grown over time. + // https://developer.apple.com/fonts/TTRefMan/RM06/Chap6OS2.html + // says that it was originally 68 bytes. Optional fields, including + // the ascender and descender, are described at + // http://www.microsoft.com/typography/otspec/os2.htm + if len(f.os2) >= 72 { + sTypoAscender := fixed.Int26_6(int16(u16(f.os2, 68))) + sTypoDescender := fixed.Int26_6(int16(u16(f.os2, 70))) + return VMetric{ + AdvanceHeight: sTypoAscender - sTypoDescender, + TopSideBearing: sTypoAscender - yMax, + } + } + return VMetric{ + AdvanceHeight: fixed.Int26_6(f.fUnitsPerEm), + TopSideBearing: 0, + } +} + +// VMetric returns the vertical metrics for the glyph with the given index. +func (f *Font) VMetric(scale fixed.Int26_6, i Index) VMetric { + // TODO: should 0 be bounds.YMax? + v := f.unscaledVMetric(i, 0) + v.AdvanceHeight = f.scale(scale * v.AdvanceHeight) + v.TopSideBearing = f.scale(scale * v.TopSideBearing) + return v +} + +// Kern returns the horizontal adjustment for the given glyph pair. A positive +// kern means to move the glyphs further apart. +func (f *Font) Kern(scale fixed.Int26_6, i0, i1 Index) fixed.Int26_6 { + if f.nKern == 0 { + return 0 + } + g := uint32(i0)<<16 | uint32(i1) + lo, hi := 0, f.nKern + for lo < hi { + i := (lo + hi) / 2 + ig := u32(f.kern, 18+6*i) + if ig < g { + lo = i + 1 + } else if ig > g { + hi = i + } else { + return f.scale(scale * fixed.Int26_6(int16(u16(f.kern, 22+6*i)))) + } + } + return 0 +} + +// Parse returns a new Font for the given TTF or TTC data. +// +// For TrueType Collections, the first font in the collection is parsed. +func Parse(ttf []byte) (font *Font, err error) { + return parse(ttf, 0) +} + +func parse(ttf []byte, offset int) (font *Font, err error) { + if len(ttf)-offset < 12 { + err = FormatError("TTF data is too short") + return + } + originalOffset := offset + magic, offset := u32(ttf, offset), offset+4 + switch magic { + case 0x00010000: + // No-op. + case 0x74746366: // "ttcf" as a big-endian uint32. + if originalOffset != 0 { + err = FormatError("recursive TTC") + return + } + ttcVersion, offset := u32(ttf, offset), offset+4 + if ttcVersion != 0x00010000 { + // TODO: support TTC version 2.0, once I have such a .ttc file to test with. + err = FormatError("bad TTC version") + return + } + numFonts, offset := int(u32(ttf, offset)), offset+4 + if numFonts <= 0 { + err = FormatError("bad number of TTC fonts") + return + } + if len(ttf[offset:])/4 < numFonts { + err = FormatError("TTC offset table is too short") + return + } + // TODO: provide an API to select which font in a TrueType collection to return, + // not just the first one. This may require an API to parse a TTC's name tables, + // so users of this package can select the font in a TTC by name. + offset = int(u32(ttf, offset)) + if offset <= 0 || offset > len(ttf) { + err = FormatError("bad TTC offset") + return + } + return parse(ttf, offset) + default: + err = FormatError("bad TTF version") + return + } + n, offset := int(u16(ttf, offset)), offset+2 + if len(ttf) < 16*n+12 { + err = FormatError("TTF data is too short") + return + } + f := new(Font) + // Assign the table slices. + for i := 0; i < n; i++ { + x := 16*i + 12 + switch string(ttf[x : x+4]) { + case "cmap": + f.cmap, err = readTable(ttf, ttf[x+8:x+16]) + case "cvt ": + f.cvt, err = readTable(ttf, ttf[x+8:x+16]) + case "fpgm": + f.fpgm, err = readTable(ttf, ttf[x+8:x+16]) + case "glyf": + f.glyf, err = readTable(ttf, ttf[x+8:x+16]) + case "hdmx": + f.hdmx, err = readTable(ttf, ttf[x+8:x+16]) + case "head": + f.head, err = readTable(ttf, ttf[x+8:x+16]) + case "hhea": + f.hhea, err = readTable(ttf, ttf[x+8:x+16]) + case "hmtx": + f.hmtx, err = readTable(ttf, ttf[x+8:x+16]) + case "kern": + f.kern, err = readTable(ttf, ttf[x+8:x+16]) + case "loca": + f.loca, err = readTable(ttf, ttf[x+8:x+16]) + case "maxp": + f.maxp, err = readTable(ttf, ttf[x+8:x+16]) + case "name": + f.name, err = readTable(ttf, ttf[x+8:x+16]) + case "OS/2": + f.os2, err = readTable(ttf, ttf[x+8:x+16]) + case "prep": + f.prep, err = readTable(ttf, ttf[x+8:x+16]) + case "vmtx": + f.vmtx, err = readTable(ttf, ttf[x+8:x+16]) + } + if err != nil { + return + } + } + // Parse and sanity-check the TTF data. + if err = f.parseHead(); err != nil { + return + } + if err = f.parseMaxp(); err != nil { + return + } + if err = f.parseCmap(); err != nil { + return + } + if err = f.parseKern(); err != nil { + return + } + if err = f.parseHhea(); err != nil { + return + } + font = f + return +} diff --git a/Godeps/_workspace/src/github.com/golang/freetype/truetype/truetype_test.go b/Godeps/_workspace/src/github.com/golang/freetype/truetype/truetype_test.go new file mode 100644 index 00000000..bd62d1da --- /dev/null +++ b/Godeps/_workspace/src/github.com/golang/freetype/truetype/truetype_test.go @@ -0,0 +1,400 @@ +// Copyright 2012 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2 (or +// any later version), both of which can be found in the LICENSE file. + +package truetype + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "os" + "strconv" + "strings" + "testing" + + "golang.org/x/image/font" + "golang.org/x/image/math/fixed" +) + +func parseTestdataFont(name string) (f *Font, testdataIsOptional bool, err error) { + b, err := ioutil.ReadFile(fmt.Sprintf("../testdata/%s.ttf", name)) + if err != nil { + // The "x-foo" fonts are optional tests, as they are not checked + // in for copyright or file size reasons. + return nil, strings.HasPrefix(name, "x-"), fmt.Errorf("%s: ReadFile: %v", name, err) + } + f, err = Parse(b) + if err != nil { + return nil, true, fmt.Errorf("%s: Parse: %v", name, err) + } + return f, false, nil +} + +func mkBounds(minX, minY, maxX, maxY fixed.Int26_6) fixed.Rectangle26_6 { + return fixed.Rectangle26_6{ + Min: fixed.Point26_6{ + X: minX, + Y: minY, + }, + Max: fixed.Point26_6{ + X: maxX, + Y: maxY, + }, + } +} + +// TestParse tests that the luxisr.ttf metrics and glyphs are parsed correctly. +// The numerical values can be manually verified by examining luxisr.ttx. +func TestParse(t *testing.T) { + f, _, err := parseTestdataFont("luxisr") + if err != nil { + t.Fatal(err) + } + if got, want := f.FUnitsPerEm(), int32(2048); got != want { + t.Errorf("FUnitsPerEm: got %v, want %v", got, want) + } + fupe := fixed.Int26_6(f.FUnitsPerEm()) + if got, want := f.Bounds(fupe), mkBounds(-441, -432, 2024, 2033); got != want { + t.Errorf("Bounds: got %v, want %v", got, want) + } + + i0 := f.Index('A') + i1 := f.Index('V') + if i0 != 36 || i1 != 57 { + t.Fatalf("Index: i0, i1 = %d, %d, want 36, 57", i0, i1) + } + if got, want := f.HMetric(fupe, i0), (HMetric{1366, 19}); got != want { + t.Errorf("HMetric: got %v, want %v", got, want) + } + if got, want := f.VMetric(fupe, i0), (VMetric{2465, 553}); got != want { + t.Errorf("VMetric: got %v, want %v", got, want) + } + if got, want := f.Kern(fupe, i0, i1), fixed.Int26_6(-144); got != want { + t.Errorf("Kern: got %v, want %v", got, want) + } + + g := &GlyphBuf{} + err = g.Load(f, fupe, i0, font.HintingNone) + if err != nil { + t.Fatalf("Load: %v", err) + } + g0 := &GlyphBuf{ + Bounds: g.Bounds, + Points: g.Points, + Ends: g.Ends, + } + g1 := &GlyphBuf{ + Bounds: mkBounds(19, 0, 1342, 1480), + Points: []Point{ + {19, 0, 51}, + {581, 1480, 1}, + {789, 1480, 51}, + {1342, 0, 1}, + {1116, 0, 35}, + {962, 410, 3}, + {368, 410, 33}, + {214, 0, 3}, + {428, 566, 19}, + {904, 566, 33}, + {667, 1200, 3}, + }, + Ends: []int{8, 11}, + } + if got, want := fmt.Sprint(g0), fmt.Sprint(g1); got != want { + t.Errorf("GlyphBuf:\ngot %v\nwant %v", got, want) + } +} + +func TestIndex(t *testing.T) { + testCases := map[string]map[rune]Index{ + "luxisr": { + ' ': 3, + '!': 4, + 'A': 36, + 'V': 57, + 'É': 101, + 'fl': 193, + '\u22c5': 385, + '中': 0, + }, + + // The x-etc test cases use those versions of the .ttf files provided + // by Ubuntu 14.04. See testdata/make-other-hinting-txts.sh for details. + + "x-arial-bold": { + ' ': 3, + '+': 14, + '0': 19, + '_': 66, + 'w': 90, + '~': 97, + 'Ä': 98, + 'fl': 192, + '½': 242, + 'σ': 305, + 'λ': 540, + 'ỹ': 1275, + '\u04e9': 1319, + '中': 0, + }, + "x-deja-vu-sans-oblique": { + ' ': 3, + '*': 13, + 'Œ': 276, + 'ω': 861, + '‡': 2571, + '⊕': 3110, + 'fl': 4728, + '\ufb03': 4729, + '\ufffd': 4813, + // TODO: '\U0001f640': ???, + '中': 0, + }, + "x-droid-sans-japanese": { + ' ': 0, + '\u3000': 3, + '\u3041': 25, + '\u30fe': 201, + '\uff61': 202, + '\uff67': 208, + '\uff9e': 263, + '\uff9f': 264, + '\u4e00': 265, + '\u557e': 1000, + '\u61b6': 2024, + '\u6ede': 3177, + '\u7505': 3555, + '\u81e3': 4602, + '\u81e5': 4603, + '\u81e7': 4604, + '\u81e8': 4605, + '\u81ea': 4606, + '\u81ed': 4607, + '\u81f3': 4608, + '\u81f4': 4609, + '\u91c7': 5796, + '\u9fa0': 6620, + '\u203e': 12584, + }, + "x-times-new-roman": { + ' ': 3, + ':': 29, + 'fl': 192, + 'Ŀ': 273, + '♠': 388, + 'Ŗ': 451, + 'Σ': 520, + '\u200D': 745, + 'Ẽ': 1216, + '\u04e9': 1319, + '中': 0, + }, + } + for name, wants := range testCases { + f, testdataIsOptional, err := parseTestdataFont(name) + if err != nil { + if testdataIsOptional { + t.Log(err) + } else { + t.Fatal(err) + } + continue + } + for r, want := range wants { + if got := f.Index(r); got != want { + t.Errorf("%s: Index of %q, aka %U: got %d, want %d", name, r, r, got, want) + } + } + } +} + +func TestName(t *testing.T) { + testCases := map[string]string{ + "luximr": "Luxi Mono", + "luxirr": "Luxi Serif", + "luxisr": "Luxi Sans", + } + + for name, want := range testCases { + f, testdataIsOptional, err := parseTestdataFont(name) + if err != nil { + if testdataIsOptional { + t.Log(err) + } else { + t.Fatal(err) + } + continue + } + if got := f.Name(NameIDFontFamily); got != want { + t.Errorf("%s: got %q, want %q", name, got, want) + } + } +} + +type scalingTestData struct { + advanceWidth fixed.Int26_6 + bounds fixed.Rectangle26_6 + points []Point +} + +// scalingTestParse parses a line of points like +// 213 -22 -111 236 555;-22 -111 1, 178 555 1, 236 555 1, 36 -111 1 +// The line will not have a trailing "\n". +func scalingTestParse(line string) (ret scalingTestData) { + next := func(s string) (string, fixed.Int26_6) { + t, i := "", strings.Index(s, " ") + if i != -1 { + s, t = s[:i], s[i+1:] + } + x, _ := strconv.Atoi(s) + return t, fixed.Int26_6(x) + } + + i := strings.Index(line, ";") + prefix, line := line[:i], line[i+1:] + + prefix, ret.advanceWidth = next(prefix) + prefix, ret.bounds.Min.X = next(prefix) + prefix, ret.bounds.Min.Y = next(prefix) + prefix, ret.bounds.Max.X = next(prefix) + prefix, ret.bounds.Max.Y = next(prefix) + + ret.points = make([]Point, 0, 1+strings.Count(line, ",")) + for len(line) > 0 { + s := line + if i := strings.Index(line, ","); i != -1 { + s, line = line[:i], line[i+1:] + for len(line) > 0 && line[0] == ' ' { + line = line[1:] + } + } else { + line = "" + } + s, x := next(s) + s, y := next(s) + s, f := next(s) + ret.points = append(ret.points, Point{X: x, Y: y, Flags: uint32(f)}) + } + return ret +} + +// scalingTestEquals is equivalent to, but faster than, calling +// reflect.DeepEquals(a, b), and also returns the index of the first non-equal +// element. It also treats a nil []Point and an empty non-nil []Point as equal. +// a and b must have equal length. +func scalingTestEquals(a, b []Point) (index int, equals bool) { + for i, p := range a { + if p != b[i] { + return i, false + } + } + return 0, true +} + +var scalingTestCases = []struct { + name string + size int +}{ + {"luxisr", 12}, + {"x-arial-bold", 11}, + {"x-deja-vu-sans-oblique", 17}, + {"x-droid-sans-japanese", 9}, + {"x-times-new-roman", 13}, +} + +func testScaling(t *testing.T, h font.Hinting) { + for _, tc := range scalingTestCases { + f, testdataIsOptional, err := parseTestdataFont(tc.name) + if err != nil { + if testdataIsOptional { + t.Log(err) + } else { + t.Error(err) + } + continue + } + hintingStr := "sans" + if h != font.HintingNone { + hintingStr = "with" + } + testFile, err := os.Open(fmt.Sprintf( + "../testdata/%s-%dpt-%s-hinting.txt", tc.name, tc.size, hintingStr)) + if err != nil { + t.Errorf("%s: Open: %v", tc.name, err) + continue + } + defer testFile.Close() + + wants := []scalingTestData{} + scanner := bufio.NewScanner(testFile) + if scanner.Scan() { + major, minor, patch := 0, 0, 0 + _, err := fmt.Sscanf(scanner.Text(), "freetype version %d.%d.%d", &major, &minor, &patch) + if err != nil { + t.Errorf("%s: version information: %v", tc.name, err) + } + if (major < 2) || (major == 2 && minor < 5) || (major == 2 && minor == 5 && patch < 1) { + t.Errorf("%s: need freetype version >= 2.5.1.\n"+ + "Try setting LD_LIBRARY_PATH=/path/to/freetype_built_from_src/objs/.libs/\n"+ + "and re-running testdata/make-other-hinting-txts.sh", + tc.name) + continue + } + } else { + t.Errorf("%s: no version information", tc.name) + continue + } + for scanner.Scan() { + wants = append(wants, scalingTestParse(scanner.Text())) + } + if err := scanner.Err(); err != nil && err != io.EOF { + t.Errorf("%s: Scanner: %v", tc.name, err) + continue + } + + glyphBuf := &GlyphBuf{} + for i, want := range wants { + if err = glyphBuf.Load(f, fixed.I(tc.size), Index(i), h); err != nil { + t.Errorf("%s: glyph #%d: Load: %v", tc.name, i, err) + continue + } + got := scalingTestData{ + advanceWidth: glyphBuf.AdvanceWidth, + bounds: glyphBuf.Bounds, + points: glyphBuf.Points, + } + + if got.advanceWidth != want.advanceWidth { + t.Errorf("%s: glyph #%d advance width:\ngot %v\nwant %v", + tc.name, i, got.advanceWidth, want.advanceWidth) + continue + } + + if got.bounds != want.bounds { + t.Errorf("%s: glyph #%d bounds:\ngot %v\nwant %v", + tc.name, i, got.bounds, want.bounds) + continue + } + + for i := range got.points { + got.points[i].Flags &= 0x01 + } + if len(got.points) != len(want.points) { + t.Errorf("%s: glyph #%d:\ngot %v\nwant %v\ndifferent slice lengths: %d versus %d", + tc.name, i, got.points, want.points, len(got.points), len(want.points)) + continue + } + if j, equals := scalingTestEquals(got.points, want.points); !equals { + t.Errorf("%s: glyph #%d:\ngot %v\nwant %v\nat index %d: %v versus %v", + tc.name, i, got.points, want.points, j, got.points[j], want.points[j]) + continue + } + } + } +} + +func TestScalingHintingNone(t *testing.T) { testScaling(t, font.HintingNone) } +func TestScalingHintingFull(t *testing.T) { testScaling(t, font.HintingFull) } diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/.gitignore b/Godeps/_workspace/src/github.com/golang/groupcache/.gitignore deleted file mode 100644 index b25c15b8..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*~ diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/LICENSE b/Godeps/_workspace/src/github.com/golang/groupcache/LICENSE deleted file mode 100644 index 37ec93a1..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ -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 - -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/Godeps/_workspace/src/github.com/golang/groupcache/README.md b/Godeps/_workspace/src/github.com/golang/groupcache/README.md deleted file mode 100644 index 70c29da1..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# groupcache - -## Summary - -groupcache is a caching and cache-filling library, intended as a -replacement for memcached in many cases. - -For API docs and examples, see http://godoc.org/github.com/golang/groupcache - -## Comparison to memcached - -### **Like memcached**, groupcache: - - * shards by key to select which peer is responsible for that key - -### **Unlike memcached**, groupcache: - - * does not require running a separate set of servers, thus massively - reducing deployment/configuration pain. groupcache is a client - library as well as a server. It connects to its own peers. - - * comes with a cache filling mechanism. Whereas memcached just says - "Sorry, cache miss", often resulting in a thundering herd of - database (or whatever) loads from an unbounded number of clients - (which has resulted in several fun outages), groupcache coordinates - cache fills such that only one load in one process of an entire - replicated set of processes populates the cache, then multiplexes - the loaded value to all callers. - - * does not support versioned values. If key "foo" is value "bar", - key "foo" must always be "bar". There are neither cache expiration - times, nor explicit cache evictions. Thus there is also no CAS, - nor Increment/Decrement. This also means that groupcache.... - - * ... supports automatic mirroring of super-hot items to multiple - processes. This prevents memcached hot spotting where a machine's - CPU and/or NIC are overloaded by very popular keys/values. - - * is currently only available for Go. It's very unlikely that I - (bradfitz@) will port the code to any other language. - -## Loading process - -In a nutshell, a groupcache lookup of **Get("foo")** looks like: - -(On machine #5 of a set of N machines running the same code) - - 1. Is the value of "foo" in local memory because it's super hot? If so, use it. - - 2. Is the value of "foo" in local memory because peer #5 (the current - peer) is the owner of it? If so, use it. - - 3. Amongst all the peers in my set of N, am I the owner of the key - "foo"? (e.g. does it consistent hash to 5?) If so, load it. If - other callers come in, via the same process or via RPC requests - from peers, they block waiting for the load to finish and get the - same answer. If not, RPC to the peer that's the owner and get - the answer. If the RPC fails, just load it locally (still with - local dup suppression). - -## Users - -groupcache is in production use by dl.google.com (its original user), -parts of Blogger, parts of Google Code, parts of Google Fiber, parts -of Google production monitoring systems, etc. - -## Presentations - -See http://talks.golang.org/2013/oscon-dl.slide - -## Help - -Use the golang-nuts mailing list for any discussion or questions. diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/byteview.go b/Godeps/_workspace/src/github.com/golang/groupcache/byteview.go deleted file mode 100644 index 035a9ee4..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/byteview.go +++ /dev/null @@ -1,160 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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 groupcache - -import ( - "bytes" - "errors" - "io" - "strings" -) - -// A ByteView holds an immutable view of bytes. -// Internally it wraps either a []byte or a string, -// but that detail is invisible to callers. -// -// A ByteView is meant to be used as a value type, not -// a pointer (like a time.Time). -type ByteView struct { - // If b is non-nil, b is used, else s is used. - b []byte - s string -} - -// Len returns the view's length. -func (v ByteView) Len() int { - if v.b != nil { - return len(v.b) - } - return len(v.s) -} - -// ByteSlice returns a copy of the data as a byte slice. -func (v ByteView) ByteSlice() []byte { - if v.b != nil { - return cloneBytes(v.b) - } - return []byte(v.s) -} - -// String returns the data as a string, making a copy if necessary. -func (v ByteView) String() string { - if v.b != nil { - return string(v.b) - } - return v.s -} - -// At returns the byte at index i. -func (v ByteView) At(i int) byte { - if v.b != nil { - return v.b[i] - } - return v.s[i] -} - -// Slice slices the view between the provided from and to indices. -func (v ByteView) Slice(from, to int) ByteView { - if v.b != nil { - return ByteView{b: v.b[from:to]} - } - return ByteView{s: v.s[from:to]} -} - -// SliceFrom slices the view from the provided index until the end. -func (v ByteView) SliceFrom(from int) ByteView { - if v.b != nil { - return ByteView{b: v.b[from:]} - } - return ByteView{s: v.s[from:]} -} - -// Copy copies b into dest and returns the number of bytes copied. -func (v ByteView) Copy(dest []byte) int { - if v.b != nil { - return copy(dest, v.b) - } - return copy(dest, v.s) -} - -// Equal returns whether the bytes in b are the same as the bytes in -// b2. -func (v ByteView) Equal(b2 ByteView) bool { - if b2.b == nil { - return v.EqualString(b2.s) - } - return v.EqualBytes(b2.b) -} - -// EqualString returns whether the bytes in b are the same as the bytes -// in s. -func (v ByteView) EqualString(s string) bool { - if v.b == nil { - return v.s == s - } - l := v.Len() - if len(s) != l { - return false - } - for i, bi := range v.b { - if bi != s[i] { - return false - } - } - return true -} - -// EqualBytes returns whether the bytes in b are the same as the bytes -// in b2. -func (v ByteView) EqualBytes(b2 []byte) bool { - if v.b != nil { - return bytes.Equal(v.b, b2) - } - l := v.Len() - if len(b2) != l { - return false - } - for i, bi := range b2 { - if bi != v.s[i] { - return false - } - } - return true -} - -// Reader returns an io.ReadSeeker for the bytes in v. -func (v ByteView) Reader() io.ReadSeeker { - if v.b != nil { - return bytes.NewReader(v.b) - } - return strings.NewReader(v.s) -} - -// ReadAt implements io.ReaderAt on the bytes in v. -func (v ByteView) ReadAt(p []byte, off int64) (n int, err error) { - if off < 0 { - return 0, errors.New("view: invalid offset") - } - if off >= int64(v.Len()) { - return 0, io.EOF - } - n = v.SliceFrom(int(off)).Copy(p) - if n < len(p) { - err = io.EOF - } - return -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/byteview_test.go b/Godeps/_workspace/src/github.com/golang/groupcache/byteview_test.go deleted file mode 100644 index 9ece00f4..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/byteview_test.go +++ /dev/null @@ -1,142 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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 groupcache - -import ( - "fmt" - "io" - "io/ioutil" - "testing" -) - -func TestByteView(t *testing.T) { - for _, s := range []string{"", "x", "yy"} { - for _, v := range []ByteView{of([]byte(s)), of(s)} { - name := fmt.Sprintf("string %q, view %+v", s, v) - if v.Len() != len(s) { - t.Errorf("%s: Len = %d; want %d", name, v.Len(), len(s)) - } - if v.String() != s { - t.Errorf("%s: String = %q; want %q", name, v.String(), s) - } - var longDest [3]byte - if n := v.Copy(longDest[:]); n != len(s) { - t.Errorf("%s: long Copy = %d; want %d", name, n, len(s)) - } - var shortDest [1]byte - if n := v.Copy(shortDest[:]); n != min(len(s), 1) { - t.Errorf("%s: short Copy = %d; want %d", name, n, min(len(s), 1)) - } - if got, err := ioutil.ReadAll(v.Reader()); err != nil || string(got) != s { - t.Errorf("%s: Reader = %q, %v; want %q", name, got, err, s) - } - if got, err := ioutil.ReadAll(io.NewSectionReader(v, 0, int64(len(s)))); err != nil || string(got) != s { - t.Errorf("%s: SectionReader of ReaderAt = %q, %v; want %q", name, got, err, s) - } - } - } -} - -// of returns a byte view of the []byte or string in x. -func of(x interface{}) ByteView { - if bytes, ok := x.([]byte); ok { - return ByteView{b: bytes} - } - return ByteView{s: x.(string)} -} - -func TestByteViewEqual(t *testing.T) { - tests := []struct { - a interface{} // string or []byte - b interface{} // string or []byte - want bool - }{ - {"x", "x", true}, - {"x", "y", false}, - {"x", "yy", false}, - {[]byte("x"), []byte("x"), true}, - {[]byte("x"), []byte("y"), false}, - {[]byte("x"), []byte("yy"), false}, - {[]byte("x"), "x", true}, - {[]byte("x"), "y", false}, - {[]byte("x"), "yy", false}, - {"x", []byte("x"), true}, - {"x", []byte("y"), false}, - {"x", []byte("yy"), false}, - } - for i, tt := range tests { - va := of(tt.a) - if bytes, ok := tt.b.([]byte); ok { - if got := va.EqualBytes(bytes); got != tt.want { - t.Errorf("%d. EqualBytes = %v; want %v", i, got, tt.want) - } - } else { - if got := va.EqualString(tt.b.(string)); got != tt.want { - t.Errorf("%d. EqualString = %v; want %v", i, got, tt.want) - } - } - if got := va.Equal(of(tt.b)); got != tt.want { - t.Errorf("%d. Equal = %v; want %v", i, got, tt.want) - } - } -} - -func TestByteViewSlice(t *testing.T) { - tests := []struct { - in string - from int - to interface{} // nil to mean the end (SliceFrom); else int - want string - }{ - { - in: "abc", - from: 1, - to: 2, - want: "b", - }, - { - in: "abc", - from: 1, - want: "bc", - }, - { - in: "abc", - to: 2, - want: "ab", - }, - } - for i, tt := range tests { - for _, v := range []ByteView{of([]byte(tt.in)), of(tt.in)} { - name := fmt.Sprintf("test %d, view %+v", i, v) - if tt.to != nil { - v = v.Slice(tt.from, tt.to.(int)) - } else { - v = v.SliceFrom(tt.from) - } - if v.String() != tt.want { - t.Errorf("%s: got %q; want %q", name, v.String(), tt.want) - } - } - } -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/consistenthash/consistenthash.go b/Godeps/_workspace/src/github.com/golang/groupcache/consistenthash/consistenthash.go deleted file mode 100644 index a9c56f07..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/consistenthash/consistenthash.go +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2013 Google Inc. - -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 consistenthash provides an implementation of a ring hash. -package consistenthash - -import ( - "hash/crc32" - "sort" - "strconv" -) - -type Hash func(data []byte) uint32 - -type Map struct { - hash Hash - replicas int - keys []int // Sorted - hashMap map[int]string -} - -func New(replicas int, fn Hash) *Map { - m := &Map{ - replicas: replicas, - hash: fn, - hashMap: make(map[int]string), - } - if m.hash == nil { - m.hash = crc32.ChecksumIEEE - } - return m -} - -// Returns true if there are no items available. -func (m *Map) IsEmpty() bool { - return len(m.keys) == 0 -} - -// Adds some keys to the hash. -func (m *Map) Add(keys ...string) { - for _, key := range keys { - for i := 0; i < m.replicas; i++ { - hash := int(m.hash([]byte(strconv.Itoa(i) + key))) - m.keys = append(m.keys, hash) - m.hashMap[hash] = key - } - } - sort.Ints(m.keys) -} - -// Gets the closest item in the hash to the provided key. -func (m *Map) Get(key string) string { - if m.IsEmpty() { - return "" - } - - hash := int(m.hash([]byte(key))) - - // Binary search for appropriate replica. - idx := sort.Search(len(m.keys), func(i int) bool { return m.keys[i] >= hash }) - - // Means we have cycled back to the first replica. - if idx == len(m.keys) { - idx = 0 - } - - return m.hashMap[m.keys[idx]] -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/consistenthash/consistenthash_test.go b/Godeps/_workspace/src/github.com/golang/groupcache/consistenthash/consistenthash_test.go deleted file mode 100644 index 1a37fd7f..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/consistenthash/consistenthash_test.go +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright 2013 Google Inc. - -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 consistenthash - -import ( - "fmt" - "strconv" - "testing" -) - -func TestHashing(t *testing.T) { - - // Override the hash function to return easier to reason about values. Assumes - // the keys can be converted to an integer. - hash := New(3, func(key []byte) uint32 { - i, err := strconv.Atoi(string(key)) - if err != nil { - panic(err) - } - return uint32(i) - }) - - // Given the above hash function, this will give replicas with "hashes": - // 2, 4, 6, 12, 14, 16, 22, 24, 26 - hash.Add("6", "4", "2") - - testCases := map[string]string{ - "2": "2", - "11": "2", - "23": "4", - "27": "2", - } - - for k, v := range testCases { - if hash.Get(k) != v { - t.Errorf("Asking for %s, should have yielded %s", k, v) - } - } - - // Adds 8, 18, 28 - hash.Add("8") - - // 27 should now map to 8. - testCases["27"] = "8" - - for k, v := range testCases { - if hash.Get(k) != v { - t.Errorf("Asking for %s, should have yielded %s", k, v) - } - } - -} - -func TestConsistency(t *testing.T) { - hash1 := New(1, nil) - hash2 := New(1, nil) - - hash1.Add("Bill", "Bob", "Bonny") - hash2.Add("Bob", "Bonny", "Bill") - - if hash1.Get("Ben") != hash2.Get("Ben") { - t.Errorf("Fetching 'Ben' from both hashes should be the same") - } - - hash2.Add("Becky", "Ben", "Bobby") - - if hash1.Get("Ben") != hash2.Get("Ben") || - hash1.Get("Bob") != hash2.Get("Bob") || - hash1.Get("Bonny") != hash2.Get("Bonny") { - t.Errorf("Direct matches should always return the same entry") - } - -} - -func BenchmarkGet8(b *testing.B) { benchmarkGet(b, 8) } -func BenchmarkGet32(b *testing.B) { benchmarkGet(b, 32) } -func BenchmarkGet128(b *testing.B) { benchmarkGet(b, 128) } -func BenchmarkGet512(b *testing.B) { benchmarkGet(b, 512) } - -func benchmarkGet(b *testing.B, shards int) { - - hash := New(50, nil) - - var buckets []string - for i := 0; i < shards; i++ { - buckets = append(buckets, fmt.Sprintf("shard-%d", i)) - } - - hash.Add(buckets...) - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - hash.Get(buckets[i&(shards-1)]) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/groupcache.go b/Godeps/_workspace/src/github.com/golang/groupcache/groupcache.go deleted file mode 100644 index 637b0631..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/groupcache.go +++ /dev/null @@ -1,455 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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 groupcache provides a data loading mechanism with caching -// and de-duplication that works across a set of peer processes. -// -// Each data Get first consults its local cache, otherwise delegates -// to the requested key's canonical owner, which then checks its cache -// or finally gets the data. In the common case, many concurrent -// cache misses across a set of peers for the same key result in just -// one cache fill. -package groupcache - -import ( - "errors" - "math/rand" - "strconv" - "sync" - "sync/atomic" - - pb "github.com/golang/groupcache/groupcachepb" - "github.com/golang/groupcache/lru" - "github.com/golang/groupcache/singleflight" -) - -// A Getter loads data for a key. -type Getter interface { - // Get returns the value identified by key, populating dest. - // - // The returned data must be unversioned. That is, key must - // uniquely describe the loaded data, without an implicit - // current time, and without relying on cache expiration - // mechanisms. - Get(ctx Context, key string, dest Sink) error -} - -// A GetterFunc implements Getter with a function. -type GetterFunc func(ctx Context, key string, dest Sink) error - -func (f GetterFunc) Get(ctx Context, key string, dest Sink) error { - return f(ctx, key, dest) -} - -var ( - mu sync.RWMutex - groups = make(map[string]*Group) - - initPeerServerOnce sync.Once - initPeerServer func() -) - -// GetGroup returns the named group previously created with NewGroup, or -// nil if there's no such group. -func GetGroup(name string) *Group { - mu.RLock() - g := groups[name] - mu.RUnlock() - return g -} - -// NewGroup creates a coordinated group-aware Getter from a Getter. -// -// The returned Getter tries (but does not guarantee) to run only one -// Get call at once for a given key across an entire set of peer -// processes. Concurrent callers both in the local process and in -// other processes receive copies of the answer once the original Get -// completes. -// -// The group name must be unique for each getter. -func NewGroup(name string, cacheBytes int64, getter Getter) *Group { - return newGroup(name, cacheBytes, getter, nil) -} - -// If peers is nil, the peerPicker is called via a sync.Once to initialize it. -func newGroup(name string, cacheBytes int64, getter Getter, peers PeerPicker) *Group { - if getter == nil { - panic("nil Getter") - } - mu.Lock() - defer mu.Unlock() - initPeerServerOnce.Do(callInitPeerServer) - if _, dup := groups[name]; dup { - panic("duplicate registration of group " + name) - } - g := &Group{ - name: name, - getter: getter, - peers: peers, - cacheBytes: cacheBytes, - } - if fn := newGroupHook; fn != nil { - fn(g) - } - groups[name] = g - return g -} - -// newGroupHook, if non-nil, is called right after a new group is created. -var newGroupHook func(*Group) - -// RegisterNewGroupHook registers a hook that is run each time -// a group is created. -func RegisterNewGroupHook(fn func(*Group)) { - if newGroupHook != nil { - panic("RegisterNewGroupHook called more than once") - } - newGroupHook = fn -} - -// RegisterServerStart registers a hook that is run when the first -// group is created. -func RegisterServerStart(fn func()) { - if initPeerServer != nil { - panic("RegisterServerStart called more than once") - } - initPeerServer = fn -} - -func callInitPeerServer() { - if initPeerServer != nil { - initPeerServer() - } -} - -// A Group is a cache namespace and associated data loaded spread over -// a group of 1 or more machines. -type Group struct { - name string - getter Getter - peersOnce sync.Once - peers PeerPicker - cacheBytes int64 // limit for sum of mainCache and hotCache size - - // mainCache is a cache of the keys for which this process - // (amongst its peers) is authorative. That is, this cache - // contains keys which consistent hash on to this process's - // peer number. - mainCache cache - - // hotCache contains keys/values for which this peer is not - // authorative (otherwise they would be in mainCache), but - // are popular enough to warrant mirroring in this process to - // avoid going over the network to fetch from a peer. Having - // a hotCache avoids network hotspotting, where a peer's - // network card could become the bottleneck on a popular key. - // This cache is used sparingly to maximize the total number - // of key/value pairs that can be stored globally. - hotCache cache - - // loadGroup ensures that each key is only fetched once - // (either locally or remotely), regardless of the number of - // concurrent callers. - loadGroup singleflight.Group - - // Stats are statistics on the group. - Stats Stats -} - -// Stats are per-group statistics. -type Stats struct { - Gets AtomicInt // any Get request, including from peers - CacheHits AtomicInt // either cache was good - PeerLoads AtomicInt // either remote load or remote cache hit (not an error) - PeerErrors AtomicInt - Loads AtomicInt // (gets - cacheHits) - LoadsDeduped AtomicInt // after singleflight - LocalLoads AtomicInt // total good local loads - LocalLoadErrs AtomicInt // total bad local loads - ServerRequests AtomicInt // gets that came over the network from peers -} - -// Name returns the name of the group. -func (g *Group) Name() string { - return g.name -} - -func (g *Group) initPeers() { - if g.peers == nil { - g.peers = getPeers() - } -} - -func (g *Group) Get(ctx Context, key string, dest Sink) error { - g.peersOnce.Do(g.initPeers) - g.Stats.Gets.Add(1) - if dest == nil { - return errors.New("groupcache: nil dest Sink") - } - value, cacheHit := g.lookupCache(key) - - if cacheHit { - g.Stats.CacheHits.Add(1) - return setSinkView(dest, value) - } - - // Optimization to avoid double unmarshalling or copying: keep - // track of whether the dest was already populated. One caller - // (if local) will set this; the losers will not. The common - // case will likely be one caller. - destPopulated := false - value, destPopulated, err := g.load(ctx, key, dest) - if err != nil { - return err - } - if destPopulated { - return nil - } - return setSinkView(dest, value) -} - -// load loads key either by invoking the getter locally or by sending it to another machine. -func (g *Group) load(ctx Context, key string, dest Sink) (value ByteView, destPopulated bool, err error) { - g.Stats.Loads.Add(1) - viewi, err := g.loadGroup.Do(key, func() (interface{}, error) { - g.Stats.LoadsDeduped.Add(1) - var value ByteView - var err error - if peer, ok := g.peers.PickPeer(key); ok { - value, err = g.getFromPeer(ctx, peer, key) - if err == nil { - g.Stats.PeerLoads.Add(1) - return value, nil - } - g.Stats.PeerErrors.Add(1) - // TODO(bradfitz): log the peer's error? keep - // log of the past few for /groupcachez? It's - // probably boring (normal task movement), so not - // worth logging I imagine. - } - value, err = g.getLocally(ctx, key, dest) - if err != nil { - g.Stats.LocalLoadErrs.Add(1) - return nil, err - } - g.Stats.LocalLoads.Add(1) - destPopulated = true // only one caller of load gets this return value - g.populateCache(key, value, &g.mainCache) - return value, nil - }) - if err == nil { - value = viewi.(ByteView) - } - return -} - -func (g *Group) getLocally(ctx Context, key string, dest Sink) (ByteView, error) { - err := g.getter.Get(ctx, key, dest) - if err != nil { - return ByteView{}, err - } - return dest.view() -} - -func (g *Group) getFromPeer(ctx Context, peer ProtoGetter, key string) (ByteView, error) { - req := &pb.GetRequest{ - Group: &g.name, - Key: &key, - } - res := &pb.GetResponse{} - err := peer.Get(ctx, req, res) - if err != nil { - return ByteView{}, err - } - value := ByteView{b: res.Value} - // TODO(bradfitz): use res.MinuteQps or something smart to - // conditionally populate hotCache. For now just do it some - // percentage of the time. - if rand.Intn(10) == 0 { - g.populateCache(key, value, &g.hotCache) - } - return value, nil -} - -func (g *Group) lookupCache(key string) (value ByteView, ok bool) { - if g.cacheBytes <= 0 { - return - } - value, ok = g.mainCache.get(key) - if ok { - return - } - value, ok = g.hotCache.get(key) - return -} - -func (g *Group) populateCache(key string, value ByteView, cache *cache) { - if g.cacheBytes <= 0 { - return - } - cache.add(key, value) - - // Evict items from cache(s) if necessary. - for { - mainBytes := g.mainCache.bytes() - hotBytes := g.hotCache.bytes() - if mainBytes+hotBytes <= g.cacheBytes { - return - } - - // TODO(bradfitz): this is good-enough-for-now logic. - // It should be something based on measurements and/or - // respecting the costs of different resources. - victim := &g.mainCache - if hotBytes > mainBytes/8 { - victim = &g.hotCache - } - victim.removeOldest() - } -} - -// CacheType represents a type of cache. -type CacheType int - -const ( - // The MainCache is the cache for items that this peer is the - // owner for. - MainCache CacheType = iota + 1 - - // The HotCache is the cache for items that seem popular - // enough to replicate to this node, even though it's not the - // owner. - HotCache -) - -// CacheStats returns stats about the provided cache within the group. -func (g *Group) CacheStats(which CacheType) CacheStats { - switch which { - case MainCache: - return g.mainCache.stats() - case HotCache: - return g.hotCache.stats() - default: - return CacheStats{} - } -} - -// cache is a wrapper around an *lru.Cache that adds synchronization, -// makes values always be ByteView, and counts the size of all keys and -// values. -type cache struct { - mu sync.RWMutex - nbytes int64 // of all keys and values - lru *lru.Cache - nhit, nget int64 - nevict int64 // number of evictions -} - -func (c *cache) stats() CacheStats { - c.mu.RLock() - defer c.mu.RUnlock() - return CacheStats{ - Bytes: c.nbytes, - Items: c.itemsLocked(), - Gets: c.nget, - Hits: c.nhit, - Evictions: c.nevict, - } -} - -func (c *cache) add(key string, value ByteView) { - c.mu.Lock() - defer c.mu.Unlock() - if c.lru == nil { - c.lru = &lru.Cache{ - OnEvicted: func(key lru.Key, value interface{}) { - val := value.(ByteView) - c.nbytes -= int64(len(key.(string))) + int64(val.Len()) - c.nevict++ - }, - } - } - c.lru.Add(key, value) - c.nbytes += int64(len(key)) + int64(value.Len()) -} - -func (c *cache) get(key string) (value ByteView, ok bool) { - c.mu.Lock() - defer c.mu.Unlock() - c.nget++ - if c.lru == nil { - return - } - vi, ok := c.lru.Get(key) - if !ok { - return - } - c.nhit++ - return vi.(ByteView), true -} - -func (c *cache) removeOldest() { - c.mu.Lock() - defer c.mu.Unlock() - if c.lru != nil { - c.lru.RemoveOldest() - } -} - -func (c *cache) bytes() int64 { - c.mu.RLock() - defer c.mu.RUnlock() - return c.nbytes -} - -func (c *cache) items() int64 { - c.mu.RLock() - defer c.mu.RUnlock() - return c.itemsLocked() -} - -func (c *cache) itemsLocked() int64 { - if c.lru == nil { - return 0 - } - return int64(c.lru.Len()) -} - -// An AtomicInt is an int64 to be accessed atomically. -type AtomicInt int64 - -// Add atomically adds n to i. -func (i *AtomicInt) Add(n int64) { - atomic.AddInt64((*int64)(i), n) -} - -// Get atomically gets the value of i. -func (i *AtomicInt) Get() int64 { - return atomic.LoadInt64((*int64)(i)) -} - -func (i *AtomicInt) String() string { - return strconv.FormatInt(i.Get(), 10) -} - -// CacheStats are returned by stats accessors on Group. -type CacheStats struct { - Bytes int64 - Items int64 - Gets int64 - Hits int64 - Evictions int64 -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/groupcache_test.go b/Godeps/_workspace/src/github.com/golang/groupcache/groupcache_test.go deleted file mode 100644 index 0ecd6bdb..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/groupcache_test.go +++ /dev/null @@ -1,367 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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. -*/ - -// Tests for groupcache. - -package groupcache - -import ( - "errors" - "fmt" - "hash/crc32" - "math/rand" - "reflect" - "sync" - "testing" - "time" - - "github.com/golang/protobuf/proto" - - pb "github.com/golang/groupcache/groupcachepb" - testpb "github.com/golang/groupcache/testpb" -) - -var ( - once sync.Once - stringGroup, protoGroup Getter - - stringc = make(chan string) - - dummyCtx Context - - // cacheFills is the number of times stringGroup or - // protoGroup's Getter have been called. Read using the - // cacheFills function. - cacheFills AtomicInt -) - -const ( - stringGroupName = "string-group" - protoGroupName = "proto-group" - testMessageType = "google3/net/groupcache/go/test_proto.TestMessage" - fromChan = "from-chan" - cacheSize = 1 << 20 -) - -func testSetup() { - stringGroup = NewGroup(stringGroupName, cacheSize, GetterFunc(func(_ Context, key string, dest Sink) error { - if key == fromChan { - key = <-stringc - } - cacheFills.Add(1) - return dest.SetString("ECHO:" + key) - })) - - protoGroup = NewGroup(protoGroupName, cacheSize, GetterFunc(func(_ Context, key string, dest Sink) error { - if key == fromChan { - key = <-stringc - } - cacheFills.Add(1) - return dest.SetProto(&testpb.TestMessage{ - Name: proto.String("ECHO:" + key), - City: proto.String("SOME-CITY"), - }) - })) -} - -// tests that a Getter's Get method is only called once with two -// outstanding callers. This is the string variant. -func TestGetDupSuppressString(t *testing.T) { - once.Do(testSetup) - // Start two getters. The first should block (waiting reading - // from stringc) and the second should latch on to the first - // one. - resc := make(chan string, 2) - for i := 0; i < 2; i++ { - go func() { - var s string - if err := stringGroup.Get(dummyCtx, fromChan, StringSink(&s)); err != nil { - resc <- "ERROR:" + err.Error() - return - } - resc <- s - }() - } - - // Wait a bit so both goroutines get merged together via - // singleflight. - // TODO(bradfitz): decide whether there are any non-offensive - // debug/test hooks that could be added to singleflight to - // make a sleep here unnecessary. - time.Sleep(250 * time.Millisecond) - - // Unblock the first getter, which should unblock the second - // as well. - stringc <- "foo" - - for i := 0; i < 2; i++ { - select { - case v := <-resc: - if v != "ECHO:foo" { - t.Errorf("got %q; want %q", v, "ECHO:foo") - } - case <-time.After(5 * time.Second): - t.Errorf("timeout waiting on getter #%d of 2", i+1) - } - } -} - -// tests that a Getter's Get method is only called once with two -// outstanding callers. This is the proto variant. -func TestGetDupSuppressProto(t *testing.T) { - once.Do(testSetup) - // Start two getters. The first should block (waiting reading - // from stringc) and the second should latch on to the first - // one. - resc := make(chan *testpb.TestMessage, 2) - for i := 0; i < 2; i++ { - go func() { - tm := new(testpb.TestMessage) - if err := protoGroup.Get(dummyCtx, fromChan, ProtoSink(tm)); err != nil { - tm.Name = proto.String("ERROR:" + err.Error()) - } - resc <- tm - }() - } - - // Wait a bit so both goroutines get merged together via - // singleflight. - // TODO(bradfitz): decide whether there are any non-offensive - // debug/test hooks that could be added to singleflight to - // make a sleep here unnecessary. - time.Sleep(250 * time.Millisecond) - - // Unblock the first getter, which should unblock the second - // as well. - stringc <- "Fluffy" - want := &testpb.TestMessage{ - Name: proto.String("ECHO:Fluffy"), - City: proto.String("SOME-CITY"), - } - for i := 0; i < 2; i++ { - select { - case v := <-resc: - if !reflect.DeepEqual(v, want) { - t.Errorf(" Got: %v\nWant: %v", proto.CompactTextString(v), proto.CompactTextString(want)) - } - case <-time.After(5 * time.Second): - t.Errorf("timeout waiting on getter #%d of 2", i+1) - } - } -} - -func countFills(f func()) int64 { - fills0 := cacheFills.Get() - f() - return cacheFills.Get() - fills0 -} - -func TestCaching(t *testing.T) { - once.Do(testSetup) - fills := countFills(func() { - for i := 0; i < 10; i++ { - var s string - if err := stringGroup.Get(dummyCtx, "TestCaching-key", StringSink(&s)); err != nil { - t.Fatal(err) - } - } - }) - if fills != 1 { - t.Errorf("expected 1 cache fill; got %d", fills) - } -} - -func TestCacheEviction(t *testing.T) { - once.Do(testSetup) - testKey := "TestCacheEviction-key" - getTestKey := func() { - var res string - for i := 0; i < 10; i++ { - if err := stringGroup.Get(dummyCtx, testKey, StringSink(&res)); err != nil { - t.Fatal(err) - } - } - } - fills := countFills(getTestKey) - if fills != 1 { - t.Fatalf("expected 1 cache fill; got %d", fills) - } - - g := stringGroup.(*Group) - evict0 := g.mainCache.nevict - - // Trash the cache with other keys. - var bytesFlooded int64 - // cacheSize/len(testKey) is approximate - for bytesFlooded < cacheSize+1024 { - var res string - key := fmt.Sprintf("dummy-key-%d", bytesFlooded) - stringGroup.Get(dummyCtx, key, StringSink(&res)) - bytesFlooded += int64(len(key) + len(res)) - } - evicts := g.mainCache.nevict - evict0 - if evicts <= 0 { - t.Errorf("evicts = %v; want more than 0", evicts) - } - - // Test that the key is gone. - fills = countFills(getTestKey) - if fills != 1 { - t.Fatalf("expected 1 cache fill after cache trashing; got %d", fills) - } -} - -type fakePeer struct { - hits int - fail bool -} - -func (p *fakePeer) Get(_ Context, in *pb.GetRequest, out *pb.GetResponse) error { - p.hits++ - if p.fail { - return errors.New("simulated error from peer") - } - out.Value = []byte("got:" + in.GetKey()) - return nil -} - -type fakePeers []ProtoGetter - -func (p fakePeers) PickPeer(key string) (peer ProtoGetter, ok bool) { - if len(p) == 0 { - return - } - n := crc32.Checksum([]byte(key), crc32.IEEETable) % uint32(len(p)) - return p[n], p[n] != nil -} - -// tests that peers (virtual, in-process) are hit, and how much. -func TestPeers(t *testing.T) { - once.Do(testSetup) - rand.Seed(123) - peer0 := &fakePeer{} - peer1 := &fakePeer{} - peer2 := &fakePeer{} - peerList := fakePeers([]ProtoGetter{peer0, peer1, peer2, nil}) - const cacheSize = 0 // disabled - localHits := 0 - getter := func(_ Context, key string, dest Sink) error { - localHits++ - return dest.SetString("got:" + key) - } - testGroup := newGroup("TestPeers-group", cacheSize, GetterFunc(getter), peerList) - run := func(name string, n int, wantSummary string) { - // Reset counters - localHits = 0 - for _, p := range []*fakePeer{peer0, peer1, peer2} { - p.hits = 0 - } - - for i := 0; i < n; i++ { - key := fmt.Sprintf("key-%d", i) - want := "got:" + key - var got string - err := testGroup.Get(dummyCtx, key, StringSink(&got)) - if err != nil { - t.Errorf("%s: error on key %q: %v", name, key, err) - continue - } - if got != want { - t.Errorf("%s: for key %q, got %q; want %q", name, key, got, want) - } - } - summary := func() string { - return fmt.Sprintf("localHits = %d, peers = %d %d %d", localHits, peer0.hits, peer1.hits, peer2.hits) - } - if got := summary(); got != wantSummary { - t.Errorf("%s: got %q; want %q", name, got, wantSummary) - } - } - resetCacheSize := func(maxBytes int64) { - g := testGroup - g.cacheBytes = maxBytes - g.mainCache = cache{} - g.hotCache = cache{} - } - - // Base case; peers all up, with no problems. - resetCacheSize(1 << 20) - run("base", 200, "localHits = 49, peers = 51 49 51") - - // Verify cache was hit. All localHits are gone, and some of - // the peer hits (the ones randomly selected to be maybe hot) - run("cached_base", 200, "localHits = 0, peers = 49 47 48") - resetCacheSize(0) - - // With one of the peers being down. - // TODO(bradfitz): on a peer number being unavailable, the - // consistent hashing should maybe keep trying others to - // spread the load out. Currently it fails back to local - // execution if the first consistent-hash slot is unavailable. - peerList[0] = nil - run("one_peer_down", 200, "localHits = 100, peers = 0 49 51") - - // Failing peer - peerList[0] = peer0 - peer0.fail = true - run("peer0_failing", 200, "localHits = 100, peers = 51 49 51") -} - -func TestTruncatingByteSliceTarget(t *testing.T) { - var buf [100]byte - s := buf[:] - if err := stringGroup.Get(dummyCtx, "short", TruncatingByteSliceSink(&s)); err != nil { - t.Fatal(err) - } - if want := "ECHO:short"; string(s) != want { - t.Errorf("short key got %q; want %q", s, want) - } - - s = buf[:6] - if err := stringGroup.Get(dummyCtx, "truncated", TruncatingByteSliceSink(&s)); err != nil { - t.Fatal(err) - } - if want := "ECHO:t"; string(s) != want { - t.Errorf("truncated key got %q; want %q", s, want) - } -} - -func TestAllocatingByteSliceTarget(t *testing.T) { - var dst []byte - sink := AllocatingByteSliceSink(&dst) - - inBytes := []byte("some bytes") - sink.SetBytes(inBytes) - if want := "some bytes"; string(dst) != want { - t.Errorf("SetBytes resulted in %q; want %q", dst, want) - } - v, err := sink.view() - if err != nil { - t.Fatalf("view after SetBytes failed: %v", err) - } - if &inBytes[0] == &dst[0] { - t.Error("inBytes and dst share memory") - } - if &inBytes[0] == &v.b[0] { - t.Error("inBytes and view share memory") - } - if &dst[0] == &v.b[0] { - t.Error("dst and view share memory") - } -} - -// TODO(bradfitz): port the Google-internal full integration test into here, -// using HTTP requests instead of our RPC system. diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/groupcachepb/groupcache.pb.go b/Godeps/_workspace/src/github.com/golang/groupcache/groupcachepb/groupcache.pb.go deleted file mode 100644 index 520d1ee9..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/groupcachepb/groupcache.pb.go +++ /dev/null @@ -1,65 +0,0 @@ -// Code generated by protoc-gen-go. -// source: groupcache.proto -// DO NOT EDIT! - -package groupcachepb - -import proto "github.com/golang/protobuf/proto" -import json "encoding/json" -import math "math" - -// Reference proto, json, and math imports to suppress error if they are not otherwise used. -var _ = proto.Marshal -var _ = &json.SyntaxError{} -var _ = math.Inf - -type GetRequest struct { - Group *string `protobuf:"bytes,1,req,name=group" json:"group,omitempty"` - Key *string `protobuf:"bytes,2,req,name=key" json:"key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GetRequest) Reset() { *m = GetRequest{} } -func (m *GetRequest) String() string { return proto.CompactTextString(m) } -func (*GetRequest) ProtoMessage() {} - -func (m *GetRequest) GetGroup() string { - if m != nil && m.Group != nil { - return *m.Group - } - return "" -} - -func (m *GetRequest) GetKey() string { - if m != nil && m.Key != nil { - return *m.Key - } - return "" -} - -type GetResponse struct { - Value []byte `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` - MinuteQps *float64 `protobuf:"fixed64,2,opt,name=minute_qps" json:"minute_qps,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GetResponse) Reset() { *m = GetResponse{} } -func (m *GetResponse) String() string { return proto.CompactTextString(m) } -func (*GetResponse) ProtoMessage() {} - -func (m *GetResponse) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -func (m *GetResponse) GetMinuteQps() float64 { - if m != nil && m.MinuteQps != nil { - return *m.MinuteQps - } - return 0 -} - -func init() { -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/groupcachepb/groupcache.proto b/Godeps/_workspace/src/github.com/golang/groupcache/groupcachepb/groupcache.proto deleted file mode 100644 index 153e851b..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/groupcachepb/groupcache.proto +++ /dev/null @@ -1,32 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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 groupcachepb; - -message GetRequest { - required string group = 1; - required string key = 2; // not actually required/guaranteed to be UTF-8 -} - -message GetResponse { - optional bytes value = 1; - optional double minute_qps = 2; -} - -service GroupCache { - rpc Get(GetRequest) returns (GetResponse) { - }; -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/http.go b/Godeps/_workspace/src/github.com/golang/groupcache/http.go deleted file mode 100644 index 8f637d70..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/http.go +++ /dev/null @@ -1,229 +0,0 @@ -/* -Copyright 2013 Google Inc. - -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 groupcache - -import ( - "bytes" - "fmt" - "io" - "net/http" - "net/url" - "strings" - "sync" - - "github.com/golang/groupcache/consistenthash" - pb "github.com/golang/groupcache/groupcachepb" - "github.com/golang/protobuf/proto" -) - -const defaultBasePath = "/_groupcache/" - -const defaultReplicas = 50 - -// HTTPPool implements PeerPicker for a pool of HTTP peers. -type HTTPPool struct { - // Context optionally specifies a context for the server to use when it - // receives a request. - // If nil, the server uses a nil Context. - Context func(*http.Request) Context - - // Transport optionally specifies an http.RoundTripper for the client - // to use when it makes a request. - // If nil, the client uses http.DefaultTransport. - Transport func(Context) http.RoundTripper - - // base path including leading and trailing slash, e.g. "/_groupcache/" - basePath string - - // this peer's base URL, e.g. "https://example.net:8000" - self string - - mu sync.Mutex // guards peers and httpGetters - peers *consistenthash.Map - httpGetters map[string]*httpGetter // keyed by e.g. "http://10.0.0.2:8008" -} - -// HTTPPoolOptions are the configurations of a HTTPPool. -type HTTPPoolOptions struct { - // BasePath specifies the HTTP path that will serve groupcache requests. - // If blank, it defaults to "/_groupcache/". - BasePath string - - // Replicas specifies the number of key replicas on the consistent hash. - // If blank, it defaults to 50. - Replicas int - - // HashFn specifies the hash function of the consistent hash. - // If blank, it defaults to crc32.ChecksumIEEE. - HashFn consistenthash.Hash -} - -// NewHTTPPool initializes an HTTP pool of peers, and registers itself as a PeerPicker. -// For convenience, it also registers itself as an http.Handler with http.DefaultServeMux. -// The self argument be a valid base URL that points to the current server, -// for example "http://example.net:8000". -func NewHTTPPool(self string) *HTTPPool { - p := NewHTTPPoolOpts(self, nil) - http.Handle(p.basePath, p) - return p -} - -var httpPoolMade bool - -// NewHTTPPoolOpts initializes an HTTP pool of peers with the given options. -// Unlike NewHTTPPool, this function does not register the created pool as an HTTP handler. -// The returned *HTTPPool implements http.Handler and must be registered using http.Handle. -func NewHTTPPoolOpts(self string, o *HTTPPoolOptions) *HTTPPool { - if httpPoolMade { - panic("groupcache: NewHTTPPool must be called only once") - } - httpPoolMade = true - - opts := HTTPPoolOptions{} - if o != nil { - opts = *o - } - if opts.BasePath == "" { - opts.BasePath = defaultBasePath - } - if opts.Replicas == 0 { - opts.Replicas = defaultReplicas - } - - p := &HTTPPool{ - basePath: opts.BasePath, - self: self, - peers: consistenthash.New(opts.Replicas, opts.HashFn), - httpGetters: make(map[string]*httpGetter), - } - RegisterPeerPicker(func() PeerPicker { return p }) - return p -} - -// Set updates the pool's list of peers. -// Each peer value should be a valid base URL, -// for example "http://example.net:8000". -func (p *HTTPPool) Set(peers ...string) { - p.mu.Lock() - defer p.mu.Unlock() - p.peers = consistenthash.New(defaultReplicas, nil) - p.peers.Add(peers...) - p.httpGetters = make(map[string]*httpGetter, len(peers)) - for _, peer := range peers { - p.httpGetters[peer] = &httpGetter{transport: p.Transport, baseURL: peer + p.basePath} - } -} - -func (p *HTTPPool) PickPeer(key string) (ProtoGetter, bool) { - p.mu.Lock() - defer p.mu.Unlock() - if p.peers.IsEmpty() { - return nil, false - } - if peer := p.peers.Get(key); peer != p.self { - return p.httpGetters[peer], true - } - return nil, false -} - -func (p *HTTPPool) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // Parse request. - if !strings.HasPrefix(r.URL.Path, p.basePath) { - panic("HTTPPool serving unexpected path: " + r.URL.Path) - } - parts := strings.SplitN(r.URL.Path[len(p.basePath):], "/", 2) - if len(parts) != 2 { - http.Error(w, "bad request", http.StatusBadRequest) - return - } - groupName := parts[0] - key := parts[1] - - // Fetch the value for this group/key. - group := GetGroup(groupName) - if group == nil { - http.Error(w, "no such group: "+groupName, http.StatusNotFound) - return - } - var ctx Context - if p.Context != nil { - ctx = p.Context(r) - } - - group.Stats.ServerRequests.Add(1) - var value []byte - err := group.Get(ctx, key, AllocatingByteSliceSink(&value)) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // Write the value to the response body as a proto message. - body, err := proto.Marshal(&pb.GetResponse{Value: value}) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", "application/x-protobuf") - w.Write(body) -} - -type httpGetter struct { - transport func(Context) http.RoundTripper - baseURL string -} - -var bufferPool = sync.Pool{ - New: func() interface{} { return new(bytes.Buffer) }, -} - -func (h *httpGetter) Get(context Context, in *pb.GetRequest, out *pb.GetResponse) error { - u := fmt.Sprintf( - "%v%v/%v", - h.baseURL, - url.QueryEscape(in.GetGroup()), - url.QueryEscape(in.GetKey()), - ) - req, err := http.NewRequest("GET", u, nil) - if err != nil { - return err - } - tr := http.DefaultTransport - if h.transport != nil { - tr = h.transport(context) - } - res, err := tr.RoundTrip(req) - if err != nil { - return err - } - defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return fmt.Errorf("server returned: %v", res.Status) - } - b := bufferPool.Get().(*bytes.Buffer) - b.Reset() - defer bufferPool.Put(b) - _, err = io.Copy(b, res.Body) - if err != nil { - return fmt.Errorf("reading response body: %v", err) - } - err = proto.Unmarshal(b.Bytes(), out) - if err != nil { - return fmt.Errorf("decoding response body: %v", err) - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/http_test.go b/Godeps/_workspace/src/github.com/golang/groupcache/http_test.go deleted file mode 100644 index b42edd7f..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/http_test.go +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright 2013 Google Inc. - -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 groupcache - -import ( - "errors" - "flag" - "log" - "net" - "net/http" - "os" - "os/exec" - "strconv" - "strings" - "sync" - "testing" - "time" -) - -var ( - peerAddrs = flag.String("test_peer_addrs", "", "Comma-separated list of peer addresses; used by TestHTTPPool") - peerIndex = flag.Int("test_peer_index", -1, "Index of which peer this child is; used by TestHTTPPool") - peerChild = flag.Bool("test_peer_child", false, "True if running as a child process; used by TestHTTPPool") -) - -func TestHTTPPool(t *testing.T) { - if *peerChild { - beChildForTestHTTPPool() - os.Exit(0) - } - - const ( - nChild = 4 - nGets = 100 - ) - - var childAddr []string - for i := 0; i < nChild; i++ { - childAddr = append(childAddr, pickFreeAddr(t)) - } - - var cmds []*exec.Cmd - var wg sync.WaitGroup - for i := 0; i < nChild; i++ { - cmd := exec.Command(os.Args[0], - "--test.run=TestHTTPPool", - "--test_peer_child", - "--test_peer_addrs="+strings.Join(childAddr, ","), - "--test_peer_index="+strconv.Itoa(i), - ) - cmds = append(cmds, cmd) - wg.Add(1) - if err := cmd.Start(); err != nil { - t.Fatal("failed to start child process: ", err) - } - go awaitAddrReady(t, childAddr[i], &wg) - } - defer func() { - for i := 0; i < nChild; i++ { - if cmds[i].Process != nil { - cmds[i].Process.Kill() - } - } - }() - wg.Wait() - - // Use a dummy self address so that we don't handle gets in-process. - p := NewHTTPPool("should-be-ignored") - p.Set(addrToURL(childAddr)...) - - // Dummy getter function. Gets should go to children only. - // The only time this process will handle a get is when the - // children can't be contacted for some reason. - getter := GetterFunc(func(ctx Context, key string, dest Sink) error { - return errors.New("parent getter called; something's wrong") - }) - g := NewGroup("httpPoolTest", 1<<20, getter) - - for _, key := range testKeys(nGets) { - var value string - if err := g.Get(nil, key, StringSink(&value)); err != nil { - t.Fatal(err) - } - if suffix := ":" + key; !strings.HasSuffix(value, suffix) { - t.Errorf("Get(%q) = %q, want value ending in %q", key, value, suffix) - } - t.Logf("Get key=%q, value=%q (peer:key)", key, value) - } -} - -func testKeys(n int) (keys []string) { - keys = make([]string, n) - for i := range keys { - keys[i] = strconv.Itoa(i) - } - return -} - -func beChildForTestHTTPPool() { - addrs := strings.Split(*peerAddrs, ",") - - p := NewHTTPPool("http://" + addrs[*peerIndex]) - p.Set(addrToURL(addrs)...) - - getter := GetterFunc(func(ctx Context, key string, dest Sink) error { - dest.SetString(strconv.Itoa(*peerIndex) + ":" + key) - return nil - }) - NewGroup("httpPoolTest", 1<<20, getter) - - log.Fatal(http.ListenAndServe(addrs[*peerIndex], p)) -} - -// This is racy. Another process could swoop in and steal the port between the -// call to this function and the next listen call. Should be okay though. -// The proper way would be to pass the l.File() as ExtraFiles to the child -// process, and then close your copy once the child starts. -func pickFreeAddr(t *testing.T) string { - l, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - return l.Addr().String() -} - -func addrToURL(addr []string) []string { - url := make([]string, len(addr)) - for i := range addr { - url[i] = "http://" + addr[i] - } - return url -} - -func awaitAddrReady(t *testing.T, addr string, wg *sync.WaitGroup) { - defer wg.Done() - const max = 1 * time.Second - tries := 0 - for { - tries++ - c, err := net.Dial("tcp", addr) - if err == nil { - c.Close() - return - } - delay := time.Duration(tries) * 25 * time.Millisecond - if delay > max { - delay = max - } - time.Sleep(delay) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/lru/lru.go b/Godeps/_workspace/src/github.com/golang/groupcache/lru/lru.go deleted file mode 100644 index cdfe2991..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/lru/lru.go +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright 2013 Google Inc. - -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 lru implements an LRU cache. -package lru - -import "container/list" - -// Cache is an LRU cache. It is not safe for concurrent access. -type Cache struct { - // MaxEntries is the maximum number of cache entries before - // an item is evicted. Zero means no limit. - MaxEntries int - - // OnEvicted optionally specificies a callback function to be - // executed when an entry is purged from the cache. - OnEvicted func(key Key, value interface{}) - - ll *list.List - cache map[interface{}]*list.Element -} - -// A Key may be any value that is comparable. See http://golang.org/ref/spec#Comparison_operators -type Key interface{} - -type entry struct { - key Key - value interface{} -} - -// New creates a new Cache. -// If maxEntries is zero, the cache has no limit and it's assumed -// that eviction is done by the caller. -func New(maxEntries int) *Cache { - return &Cache{ - MaxEntries: maxEntries, - ll: list.New(), - cache: make(map[interface{}]*list.Element), - } -} - -// Add adds a value to the cache. -func (c *Cache) Add(key Key, value interface{}) { - if c.cache == nil { - c.cache = make(map[interface{}]*list.Element) - c.ll = list.New() - } - if ee, ok := c.cache[key]; ok { - c.ll.MoveToFront(ee) - ee.Value.(*entry).value = value - return - } - ele := c.ll.PushFront(&entry{key, value}) - c.cache[key] = ele - if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries { - c.RemoveOldest() - } -} - -// Get looks up a key's value from the cache. -func (c *Cache) Get(key Key) (value interface{}, ok bool) { - if c.cache == nil { - return - } - if ele, hit := c.cache[key]; hit { - c.ll.MoveToFront(ele) - return ele.Value.(*entry).value, true - } - return -} - -// Remove removes the provided key from the cache. -func (c *Cache) Remove(key Key) { - if c.cache == nil { - return - } - if ele, hit := c.cache[key]; hit { - c.removeElement(ele) - } -} - -// RemoveOldest removes the oldest item from the cache. -func (c *Cache) RemoveOldest() { - if c.cache == nil { - return - } - ele := c.ll.Back() - if ele != nil { - c.removeElement(ele) - } -} - -func (c *Cache) removeElement(e *list.Element) { - c.ll.Remove(e) - kv := e.Value.(*entry) - delete(c.cache, kv.key) - if c.OnEvicted != nil { - c.OnEvicted(kv.key, kv.value) - } -} - -// Len returns the number of items in the cache. -func (c *Cache) Len() int { - if c.cache == nil { - return 0 - } - return c.ll.Len() -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/lru/lru_test.go b/Godeps/_workspace/src/github.com/golang/groupcache/lru/lru_test.go deleted file mode 100644 index 98a2656e..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/lru/lru_test.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright 2013 Google Inc. - -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 lru - -import ( - "testing" -) - -type simpleStruct struct { - int - string -} - -type complexStruct struct { - int - simpleStruct -} - -var getTests = []struct { - name string - keyToAdd interface{} - keyToGet interface{} - expectedOk bool -}{ - {"string_hit", "myKey", "myKey", true}, - {"string_miss", "myKey", "nonsense", false}, - {"simple_struct_hit", simpleStruct{1, "two"}, simpleStruct{1, "two"}, true}, - {"simeple_struct_miss", simpleStruct{1, "two"}, simpleStruct{0, "noway"}, false}, - {"complex_struct_hit", complexStruct{1, simpleStruct{2, "three"}}, - complexStruct{1, simpleStruct{2, "three"}}, true}, -} - -func TestGet(t *testing.T) { - for _, tt := range getTests { - lru := New(0) - lru.Add(tt.keyToAdd, 1234) - val, ok := lru.Get(tt.keyToGet) - if ok != tt.expectedOk { - t.Fatalf("%s: cache hit = %v; want %v", tt.name, ok, !ok) - } else if ok && val != 1234 { - t.Fatalf("%s expected get to return 1234 but got %v", tt.name, val) - } - } -} - -func TestRemove(t *testing.T) { - lru := New(0) - lru.Add("myKey", 1234) - if val, ok := lru.Get("myKey"); !ok { - t.Fatal("TestRemove returned no match") - } else if val != 1234 { - t.Fatalf("TestRemove failed. Expected %d, got %v", 1234, val) - } - - lru.Remove("myKey") - if _, ok := lru.Get("myKey"); ok { - t.Fatal("TestRemove returned a removed entry") - } -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/peers.go b/Godeps/_workspace/src/github.com/golang/groupcache/peers.go deleted file mode 100644 index a74a79b8..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/peers.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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. -*/ - -// peers.go defines how processes find and communicate with their peers. - -package groupcache - -import ( - pb "github.com/golang/groupcache/groupcachepb" -) - -// Context is an opaque value passed through calls to the -// ProtoGetter. It may be nil if your ProtoGetter implementation does -// not require a context. -type Context interface{} - -// ProtoGetter is the interface that must be implemented by a peer. -type ProtoGetter interface { - Get(context Context, in *pb.GetRequest, out *pb.GetResponse) error -} - -// PeerPicker is the interface that must be implemented to locate -// the peer that owns a specific key. -type PeerPicker interface { - // PickPeer returns the peer that owns the specific key - // and true to indicate that a remote peer was nominated. - // It returns nil, false if the key owner is the current peer. - PickPeer(key string) (peer ProtoGetter, ok bool) -} - -// NoPeers is an implementation of PeerPicker that never finds a peer. -type NoPeers struct{} - -func (NoPeers) PickPeer(key string) (peer ProtoGetter, ok bool) { return } - -var ( - portPicker func() PeerPicker -) - -// RegisterPeerPicker registers the peer initialization function. -// It is called once, when the first group is created. -func RegisterPeerPicker(fn func() PeerPicker) { - if portPicker != nil { - panic("RegisterPeerPicker called more than once") - } - portPicker = fn -} - -func getPeers() PeerPicker { - if portPicker == nil { - return NoPeers{} - } - pk := portPicker() - if pk == nil { - pk = NoPeers{} - } - return pk -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/singleflight/singleflight.go b/Godeps/_workspace/src/github.com/golang/groupcache/singleflight/singleflight.go deleted file mode 100644 index ff2c2ee4..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/singleflight/singleflight.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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 singleflight provides a duplicate function call suppression -// mechanism. -package singleflight - -import "sync" - -// call is an in-flight or completed Do call -type call struct { - wg sync.WaitGroup - val interface{} - err error -} - -// Group represents a class of work and forms a namespace in which -// units of work can be executed with duplicate suppression. -type Group struct { - mu sync.Mutex // protects m - m map[string]*call // lazily initialized -} - -// Do executes and returns the results of the given function, making -// sure that only one execution is in-flight for a given key at a -// time. If a duplicate comes in, the duplicate caller waits for the -// original to complete and receives the same results. -func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) { - g.mu.Lock() - if g.m == nil { - g.m = make(map[string]*call) - } - if c, ok := g.m[key]; ok { - g.mu.Unlock() - c.wg.Wait() - return c.val, c.err - } - c := new(call) - c.wg.Add(1) - g.m[key] = c - g.mu.Unlock() - - c.val, c.err = fn() - c.wg.Done() - - g.mu.Lock() - delete(g.m, key) - g.mu.Unlock() - - return c.val, c.err -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/singleflight/singleflight_test.go b/Godeps/_workspace/src/github.com/golang/groupcache/singleflight/singleflight_test.go deleted file mode 100644 index 47b4d3dc..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/singleflight/singleflight_test.go +++ /dev/null @@ -1,85 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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 singleflight - -import ( - "errors" - "fmt" - "sync" - "sync/atomic" - "testing" - "time" -) - -func TestDo(t *testing.T) { - var g Group - v, err := g.Do("key", func() (interface{}, error) { - return "bar", nil - }) - if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want { - t.Errorf("Do = %v; want %v", got, want) - } - if err != nil { - t.Errorf("Do error = %v", err) - } -} - -func TestDoErr(t *testing.T) { - var g Group - someErr := errors.New("Some error") - v, err := g.Do("key", func() (interface{}, error) { - return nil, someErr - }) - if err != someErr { - t.Errorf("Do error = %v; want someErr", err) - } - if v != nil { - t.Errorf("unexpected non-nil value %#v", v) - } -} - -func TestDoDupSuppress(t *testing.T) { - var g Group - c := make(chan string) - var calls int32 - fn := func() (interface{}, error) { - atomic.AddInt32(&calls, 1) - return <-c, nil - } - - const n = 10 - var wg sync.WaitGroup - for i := 0; i < n; i++ { - wg.Add(1) - go func() { - v, err := g.Do("key", fn) - if err != nil { - t.Errorf("Do error: %v", err) - } - if v.(string) != "bar" { - t.Errorf("got %q; want %q", v, "bar") - } - wg.Done() - }() - } - time.Sleep(100 * time.Millisecond) // let goroutines above block - c <- "bar" - wg.Wait() - if got := atomic.LoadInt32(&calls); got != 1 { - t.Errorf("number of calls = %d; want 1", got) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/sinks.go b/Godeps/_workspace/src/github.com/golang/groupcache/sinks.go deleted file mode 100644 index cb42b41b..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/sinks.go +++ /dev/null @@ -1,322 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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 groupcache - -import ( - "errors" - - "github.com/golang/protobuf/proto" -) - -// A Sink receives data from a Get call. -// -// Implementation of Getter must call exactly one of the Set methods -// on success. -type Sink interface { - // SetString sets the value to s. - SetString(s string) error - - // SetBytes sets the value to the contents of v. - // The caller retains ownership of v. - SetBytes(v []byte) error - - // SetProto sets the value to the encoded version of m. - // The caller retains ownership of m. - SetProto(m proto.Message) error - - // view returns a frozen view of the bytes for caching. - view() (ByteView, error) -} - -func cloneBytes(b []byte) []byte { - c := make([]byte, len(b)) - copy(c, b) - return c -} - -func setSinkView(s Sink, v ByteView) error { - // A viewSetter is a Sink that can also receive its value from - // a ByteView. This is a fast path to minimize copies when the - // item was already cached locally in memory (where it's - // cached as a ByteView) - type viewSetter interface { - setView(v ByteView) error - } - if vs, ok := s.(viewSetter); ok { - return vs.setView(v) - } - if v.b != nil { - return s.SetBytes(v.b) - } - return s.SetString(v.s) -} - -// StringSink returns a Sink that populates the provided string pointer. -func StringSink(sp *string) Sink { - return &stringSink{sp: sp} -} - -type stringSink struct { - sp *string - v ByteView - // TODO(bradfitz): track whether any Sets were called. -} - -func (s *stringSink) view() (ByteView, error) { - // TODO(bradfitz): return an error if no Set was called - return s.v, nil -} - -func (s *stringSink) SetString(v string) error { - s.v.b = nil - s.v.s = v - *s.sp = v - return nil -} - -func (s *stringSink) SetBytes(v []byte) error { - return s.SetString(string(v)) -} - -func (s *stringSink) SetProto(m proto.Message) error { - b, err := proto.Marshal(m) - if err != nil { - return err - } - s.v.b = b - *s.sp = string(b) - return nil -} - -// ByteViewSink returns a Sink that populates a ByteView. -func ByteViewSink(dst *ByteView) Sink { - if dst == nil { - panic("nil dst") - } - return &byteViewSink{dst: dst} -} - -type byteViewSink struct { - dst *ByteView - - // if this code ever ends up tracking that at least one set* - // method was called, don't make it an error to call set - // methods multiple times. Lorry's payload.go does that, and - // it makes sense. The comment at the top of this file about - // "exactly one of the Set methods" is overly strict. We - // really care about at least once (in a handler), but if - // multiple handlers fail (or multiple functions in a program - // using a Sink), it's okay to re-use the same one. -} - -func (s *byteViewSink) setView(v ByteView) error { - *s.dst = v - return nil -} - -func (s *byteViewSink) view() (ByteView, error) { - return *s.dst, nil -} - -func (s *byteViewSink) SetProto(m proto.Message) error { - b, err := proto.Marshal(m) - if err != nil { - return err - } - *s.dst = ByteView{b: b} - return nil -} - -func (s *byteViewSink) SetBytes(b []byte) error { - *s.dst = ByteView{b: cloneBytes(b)} - return nil -} - -func (s *byteViewSink) SetString(v string) error { - *s.dst = ByteView{s: v} - return nil -} - -// ProtoSink returns a sink that unmarshals binary proto values into m. -func ProtoSink(m proto.Message) Sink { - return &protoSink{ - dst: m, - } -} - -type protoSink struct { - dst proto.Message // authorative value - typ string - - v ByteView // encoded -} - -func (s *protoSink) view() (ByteView, error) { - return s.v, nil -} - -func (s *protoSink) SetBytes(b []byte) error { - err := proto.Unmarshal(b, s.dst) - if err != nil { - return err - } - s.v.b = cloneBytes(b) - s.v.s = "" - return nil -} - -func (s *protoSink) SetString(v string) error { - b := []byte(v) - err := proto.Unmarshal(b, s.dst) - if err != nil { - return err - } - s.v.b = b - s.v.s = "" - return nil -} - -func (s *protoSink) SetProto(m proto.Message) error { - b, err := proto.Marshal(m) - if err != nil { - return err - } - // TODO(bradfitz): optimize for same-task case more and write - // right through? would need to document ownership rules at - // the same time. but then we could just assign *dst = *m - // here. This works for now: - err = proto.Unmarshal(b, s.dst) - if err != nil { - return err - } - s.v.b = b - s.v.s = "" - return nil -} - -// AllocatingByteSliceSink returns a Sink that allocates -// a byte slice to hold the received value and assigns -// it to *dst. The memory is not retained by groupcache. -func AllocatingByteSliceSink(dst *[]byte) Sink { - return &allocBytesSink{dst: dst} -} - -type allocBytesSink struct { - dst *[]byte - v ByteView -} - -func (s *allocBytesSink) view() (ByteView, error) { - return s.v, nil -} - -func (s *allocBytesSink) setView(v ByteView) error { - if v.b != nil { - *s.dst = cloneBytes(v.b) - } else { - *s.dst = []byte(v.s) - } - s.v = v - return nil -} - -func (s *allocBytesSink) SetProto(m proto.Message) error { - b, err := proto.Marshal(m) - if err != nil { - return err - } - return s.setBytesOwned(b) -} - -func (s *allocBytesSink) SetBytes(b []byte) error { - return s.setBytesOwned(cloneBytes(b)) -} - -func (s *allocBytesSink) setBytesOwned(b []byte) error { - if s.dst == nil { - return errors.New("nil AllocatingByteSliceSink *[]byte dst") - } - *s.dst = cloneBytes(b) // another copy, protecting the read-only s.v.b view - s.v.b = b - s.v.s = "" - return nil -} - -func (s *allocBytesSink) SetString(v string) error { - if s.dst == nil { - return errors.New("nil AllocatingByteSliceSink *[]byte dst") - } - *s.dst = []byte(v) - s.v.b = nil - s.v.s = v - return nil -} - -// TruncatingByteSliceSink returns a Sink that writes up to len(*dst) -// bytes to *dst. If more bytes are available, they're silently -// truncated. If fewer bytes are available than len(*dst), *dst -// is shrunk to fit the number of bytes available. -func TruncatingByteSliceSink(dst *[]byte) Sink { - return &truncBytesSink{dst: dst} -} - -type truncBytesSink struct { - dst *[]byte - v ByteView -} - -func (s *truncBytesSink) view() (ByteView, error) { - return s.v, nil -} - -func (s *truncBytesSink) SetProto(m proto.Message) error { - b, err := proto.Marshal(m) - if err != nil { - return err - } - return s.setBytesOwned(b) -} - -func (s *truncBytesSink) SetBytes(b []byte) error { - return s.setBytesOwned(cloneBytes(b)) -} - -func (s *truncBytesSink) setBytesOwned(b []byte) error { - if s.dst == nil { - return errors.New("nil TruncatingByteSliceSink *[]byte dst") - } - n := copy(*s.dst, b) - if n < len(*s.dst) { - *s.dst = (*s.dst)[:n] - } - s.v.b = b - s.v.s = "" - return nil -} - -func (s *truncBytesSink) SetString(v string) error { - if s.dst == nil { - return errors.New("nil TruncatingByteSliceSink *[]byte dst") - } - n := copy(*s.dst, v) - if n < len(*s.dst) { - *s.dst = (*s.dst)[:n] - } - s.v.b = nil - s.v.s = v - return nil -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/testpb/test.pb.go b/Godeps/_workspace/src/github.com/golang/groupcache/testpb/test.pb.go deleted file mode 100644 index 038040d1..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/testpb/test.pb.go +++ /dev/null @@ -1,235 +0,0 @@ -// Code generated by protoc-gen-go. -// source: test.proto -// DO NOT EDIT! - -package testpb - -import proto "github.com/golang/protobuf/proto" -import json "encoding/json" -import math "math" - -// Reference proto, json, and math imports to suppress error if they are not otherwise used. -var _ = proto.Marshal -var _ = &json.SyntaxError{} -var _ = math.Inf - -type TestMessage struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - City *string `protobuf:"bytes,2,opt,name=city" json:"city,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TestMessage) Reset() { *m = TestMessage{} } -func (m *TestMessage) String() string { return proto.CompactTextString(m) } -func (*TestMessage) ProtoMessage() {} - -func (m *TestMessage) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *TestMessage) GetCity() string { - if m != nil && m.City != nil { - return *m.City - } - return "" -} - -type TestRequest struct { - Lower *string `protobuf:"bytes,1,req,name=lower" json:"lower,omitempty"` - RepeatCount *int32 `protobuf:"varint,2,opt,name=repeat_count,def=1" json:"repeat_count,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TestRequest) Reset() { *m = TestRequest{} } -func (m *TestRequest) String() string { return proto.CompactTextString(m) } -func (*TestRequest) ProtoMessage() {} - -const Default_TestRequest_RepeatCount int32 = 1 - -func (m *TestRequest) GetLower() string { - if m != nil && m.Lower != nil { - return *m.Lower - } - return "" -} - -func (m *TestRequest) GetRepeatCount() int32 { - if m != nil && m.RepeatCount != nil { - return *m.RepeatCount - } - return Default_TestRequest_RepeatCount -} - -type TestResponse struct { - Value *string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TestResponse) Reset() { *m = TestResponse{} } -func (m *TestResponse) String() string { return proto.CompactTextString(m) } -func (*TestResponse) ProtoMessage() {} - -func (m *TestResponse) GetValue() string { - if m != nil && m.Value != nil { - return *m.Value - } - return "" -} - -type CacheStats struct { - Items *int64 `protobuf:"varint,1,opt,name=items" json:"items,omitempty"` - Bytes *int64 `protobuf:"varint,2,opt,name=bytes" json:"bytes,omitempty"` - Gets *int64 `protobuf:"varint,3,opt,name=gets" json:"gets,omitempty"` - Hits *int64 `protobuf:"varint,4,opt,name=hits" json:"hits,omitempty"` - Evicts *int64 `protobuf:"varint,5,opt,name=evicts" json:"evicts,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CacheStats) Reset() { *m = CacheStats{} } -func (m *CacheStats) String() string { return proto.CompactTextString(m) } -func (*CacheStats) ProtoMessage() {} - -func (m *CacheStats) GetItems() int64 { - if m != nil && m.Items != nil { - return *m.Items - } - return 0 -} - -func (m *CacheStats) GetBytes() int64 { - if m != nil && m.Bytes != nil { - return *m.Bytes - } - return 0 -} - -func (m *CacheStats) GetGets() int64 { - if m != nil && m.Gets != nil { - return *m.Gets - } - return 0 -} - -func (m *CacheStats) GetHits() int64 { - if m != nil && m.Hits != nil { - return *m.Hits - } - return 0 -} - -func (m *CacheStats) GetEvicts() int64 { - if m != nil && m.Evicts != nil { - return *m.Evicts - } - return 0 -} - -type StatsResponse struct { - Gets *int64 `protobuf:"varint,1,opt,name=gets" json:"gets,omitempty"` - CacheHits *int64 `protobuf:"varint,12,opt,name=cache_hits" json:"cache_hits,omitempty"` - Fills *int64 `protobuf:"varint,2,opt,name=fills" json:"fills,omitempty"` - TotalAlloc *uint64 `protobuf:"varint,3,opt,name=total_alloc" json:"total_alloc,omitempty"` - MainCache *CacheStats `protobuf:"bytes,4,opt,name=main_cache" json:"main_cache,omitempty"` - HotCache *CacheStats `protobuf:"bytes,5,opt,name=hot_cache" json:"hot_cache,omitempty"` - ServerIn *int64 `protobuf:"varint,6,opt,name=server_in" json:"server_in,omitempty"` - Loads *int64 `protobuf:"varint,8,opt,name=loads" json:"loads,omitempty"` - PeerLoads *int64 `protobuf:"varint,9,opt,name=peer_loads" json:"peer_loads,omitempty"` - PeerErrors *int64 `protobuf:"varint,10,opt,name=peer_errors" json:"peer_errors,omitempty"` - LocalLoads *int64 `protobuf:"varint,11,opt,name=local_loads" json:"local_loads,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *StatsResponse) Reset() { *m = StatsResponse{} } -func (m *StatsResponse) String() string { return proto.CompactTextString(m) } -func (*StatsResponse) ProtoMessage() {} - -func (m *StatsResponse) GetGets() int64 { - if m != nil && m.Gets != nil { - return *m.Gets - } - return 0 -} - -func (m *StatsResponse) GetCacheHits() int64 { - if m != nil && m.CacheHits != nil { - return *m.CacheHits - } - return 0 -} - -func (m *StatsResponse) GetFills() int64 { - if m != nil && m.Fills != nil { - return *m.Fills - } - return 0 -} - -func (m *StatsResponse) GetTotalAlloc() uint64 { - if m != nil && m.TotalAlloc != nil { - return *m.TotalAlloc - } - return 0 -} - -func (m *StatsResponse) GetMainCache() *CacheStats { - if m != nil { - return m.MainCache - } - return nil -} - -func (m *StatsResponse) GetHotCache() *CacheStats { - if m != nil { - return m.HotCache - } - return nil -} - -func (m *StatsResponse) GetServerIn() int64 { - if m != nil && m.ServerIn != nil { - return *m.ServerIn - } - return 0 -} - -func (m *StatsResponse) GetLoads() int64 { - if m != nil && m.Loads != nil { - return *m.Loads - } - return 0 -} - -func (m *StatsResponse) GetPeerLoads() int64 { - if m != nil && m.PeerLoads != nil { - return *m.PeerLoads - } - return 0 -} - -func (m *StatsResponse) GetPeerErrors() int64 { - if m != nil && m.PeerErrors != nil { - return *m.PeerErrors - } - return 0 -} - -func (m *StatsResponse) GetLocalLoads() int64 { - if m != nil && m.LocalLoads != nil { - return *m.LocalLoads - } - return 0 -} - -type Empty struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *Empty) Reset() { *m = Empty{} } -func (m *Empty) String() string { return proto.CompactTextString(m) } -func (*Empty) ProtoMessage() {} - -func init() { -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/testpb/test.proto b/Godeps/_workspace/src/github.com/golang/groupcache/testpb/test.proto deleted file mode 100644 index 7292dcea..00000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/testpb/test.proto +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2012 Google Inc. - -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 testpb; - -message TestMessage { - optional string name = 1; - optional string city = 2; -} - -message TestRequest { - required string lower = 1; // to be returned upper case - optional int32 repeat_count = 2 [default = 1]; // .. this many times -} - -message TestResponse { - optional string value = 1; -} - -message CacheStats { - optional int64 items = 1; - optional int64 bytes = 2; - optional int64 gets = 3; - optional int64 hits = 4; - optional int64 evicts = 5; -} - -message StatsResponse { - optional int64 gets = 1; - optional int64 cache_hits = 12; - optional int64 fills = 2; - optional uint64 total_alloc = 3; - optional CacheStats main_cache = 4; - optional CacheStats hot_cache = 5; - optional int64 server_in = 6; - optional int64 loads = 8; - optional int64 peer_loads = 9; - optional int64 peer_errors = 10; - optional int64 local_loads = 11; -} - -message Empty {} - -service GroupCacheTest { - rpc InitPeers(Empty) returns (Empty) {}; - rpc Get(TestRequest) returns (TestResponse) {}; - rpc GetStats(Empty) returns (StatsResponse) {}; -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/Makefile b/Godeps/_workspace/src/github.com/golang/protobuf/proto/Makefile deleted file mode 100644 index f1f06564..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# 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 testdata - protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata:. proto3_proto/proto3.proto - make diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/all_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/all_test.go deleted file mode 100644 index b787d58a..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/all_test.go +++ /dev/null @@ -1,2104 +0,0 @@ -// 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_test - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "math" - "math/rand" - "reflect" - "runtime/debug" - "strings" - "testing" - "time" - - . "github.com/golang/protobuf/proto" - . "github.com/golang/protobuf/proto/testdata" -) - -var globalO *Buffer - -func old() *Buffer { - if globalO == nil { - globalO = NewBuffer(nil) - } - globalO.Reset() - return globalO -} - -func equalbytes(b1, b2 []byte, t *testing.T) { - if len(b1) != len(b2) { - t.Errorf("wrong lengths: 2*%d != %d", len(b1), len(b2)) - return - } - for i := 0; i < len(b1); i++ { - if b1[i] != b2[i] { - t.Errorf("bad byte[%d]:%x %x: %s %s", i, b1[i], b2[i], b1, b2) - } - } -} - -func initGoTestField() *GoTestField { - f := new(GoTestField) - f.Label = String("label") - f.Type = String("type") - return f -} - -// These are all structurally equivalent but the tag numbers differ. -// (It's remarkable that required, optional, and repeated all have -// 8 letters.) -func initGoTest_RequiredGroup() *GoTest_RequiredGroup { - return &GoTest_RequiredGroup{ - RequiredField: String("required"), - } -} - -func initGoTest_OptionalGroup() *GoTest_OptionalGroup { - return &GoTest_OptionalGroup{ - RequiredField: String("optional"), - } -} - -func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup { - return &GoTest_RepeatedGroup{ - RequiredField: String("repeated"), - } -} - -func initGoTest(setdefaults bool) *GoTest { - pb := new(GoTest) - if setdefaults { - pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted) - pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted) - pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted) - pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted) - pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted) - pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted) - pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted) - pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted) - pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted) - pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted) - pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted - pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted) - pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted) - } - - pb.Kind = GoTest_TIME.Enum() - pb.RequiredField = initGoTestField() - pb.F_BoolRequired = Bool(true) - pb.F_Int32Required = Int32(3) - pb.F_Int64Required = Int64(6) - pb.F_Fixed32Required = Uint32(32) - pb.F_Fixed64Required = Uint64(64) - pb.F_Uint32Required = Uint32(3232) - pb.F_Uint64Required = Uint64(6464) - pb.F_FloatRequired = Float32(3232) - pb.F_DoubleRequired = Float64(6464) - pb.F_StringRequired = String("string") - pb.F_BytesRequired = []byte("bytes") - pb.F_Sint32Required = Int32(-32) - pb.F_Sint64Required = Int64(-64) - pb.Requiredgroup = initGoTest_RequiredGroup() - - return pb -} - -func fail(msg string, b *bytes.Buffer, s string, t *testing.T) { - data := b.Bytes() - ld := len(data) - ls := len(s) / 2 - - fmt.Printf("fail %s ld=%d ls=%d\n", msg, ld, ls) - - // find the interesting spot - n - n := ls - if ld < ls { - n = ld - } - j := 0 - for i := 0; i < n; i++ { - bs := hex(s[j])*16 + hex(s[j+1]) - j += 2 - if data[i] == bs { - continue - } - n = i - break - } - l := n - 10 - if l < 0 { - l = 0 - } - h := n + 10 - - // find the interesting spot - n - fmt.Printf("is[%d]:", l) - for i := l; i < h; i++ { - if i >= ld { - fmt.Printf(" --") - continue - } - fmt.Printf(" %.2x", data[i]) - } - fmt.Printf("\n") - - fmt.Printf("sb[%d]:", l) - for i := l; i < h; i++ { - if i >= ls { - fmt.Printf(" --") - continue - } - bs := hex(s[j])*16 + hex(s[j+1]) - j += 2 - fmt.Printf(" %.2x", bs) - } - fmt.Printf("\n") - - t.Fail() - - // t.Errorf("%s: \ngood: %s\nbad: %x", msg, s, b.Bytes()) - // Print the output in a partially-decoded format; can - // be helpful when updating the test. It produces the output - // that is pasted, with minor edits, into the argument to verify(). - // data := b.Bytes() - // nesting := 0 - // for b.Len() > 0 { - // start := len(data) - b.Len() - // var u uint64 - // u, err := DecodeVarint(b) - // if err != nil { - // fmt.Printf("decode error on varint:", err) - // return - // } - // wire := u & 0x7 - // tag := u >> 3 - // switch wire { - // case WireVarint: - // v, err := DecodeVarint(b) - // if err != nil { - // fmt.Printf("decode error on varint:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", - // data[start:len(data)-b.Len()], tag, wire, v) - // case WireFixed32: - // v, err := DecodeFixed32(b) - // if err != nil { - // fmt.Printf("decode error on fixed32:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", - // data[start:len(data)-b.Len()], tag, wire, v) - // case WireFixed64: - // v, err := DecodeFixed64(b) - // if err != nil { - // fmt.Printf("decode error on fixed64:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", - // data[start:len(data)-b.Len()], tag, wire, v) - // case WireBytes: - // nb, err := DecodeVarint(b) - // if err != nil { - // fmt.Printf("decode error on bytes:", err) - // return - // } - // after_tag := len(data) - b.Len() - // str := make([]byte, nb) - // _, err = b.Read(str) - // if err != nil { - // fmt.Printf("decode error on bytes:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" \"%x\" // field %d, encoding %d (FIELD)\n", - // data[start:after_tag], str, tag, wire) - // case WireStartGroup: - // nesting++ - // fmt.Printf("\t\t\"%x\"\t\t// start group field %d level %d\n", - // data[start:len(data)-b.Len()], tag, nesting) - // case WireEndGroup: - // fmt.Printf("\t\t\"%x\"\t\t// end group field %d level %d\n", - // data[start:len(data)-b.Len()], tag, nesting) - // nesting-- - // default: - // fmt.Printf("unrecognized wire type %d\n", wire) - // return - // } - // } -} - -func hex(c uint8) uint8 { - if '0' <= c && c <= '9' { - return c - '0' - } - if 'a' <= c && c <= 'f' { - return 10 + c - 'a' - } - if 'A' <= c && c <= 'F' { - return 10 + c - 'A' - } - return 0 -} - -func equal(b []byte, s string, t *testing.T) bool { - if 2*len(b) != len(s) { - // fail(fmt.Sprintf("wrong lengths: 2*%d != %d", len(b), len(s)), b, s, t) - fmt.Printf("wrong lengths: 2*%d != %d\n", len(b), len(s)) - return false - } - for i, j := 0, 0; i < len(b); i, j = i+1, j+2 { - x := hex(s[j])*16 + hex(s[j+1]) - if b[i] != x { - // fail(fmt.Sprintf("bad byte[%d]:%x %x", i, b[i], x), b, s, t) - fmt.Printf("bad byte[%d]:%x %x", i, b[i], x) - return false - } - } - return true -} - -func overify(t *testing.T, pb *GoTest, expected string) { - o := old() - err := o.Marshal(pb) - if err != nil { - fmt.Printf("overify marshal-1 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 1", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = o.Unmarshal(pbd) - if err != nil { - t.Fatalf("overify unmarshal err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - o.Reset() - err = o.Marshal(pbd) - if err != nil { - t.Errorf("overify marshal-2 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 2", o.Bytes()) - t.Fatalf("string = %s", expected) - } -} - -// Simple tests for numeric encode/decode primitives (varint, etc.) -func TestNumericPrimitives(t *testing.T) { - for i := uint64(0); i < 1e6; i += 111 { - o := old() - if o.EncodeVarint(i) != nil { - t.Error("EncodeVarint") - break - } - x, e := o.DecodeVarint() - if e != nil { - t.Fatal("DecodeVarint") - } - if x != i { - t.Fatal("varint decode fail:", i, x) - } - - o = old() - if o.EncodeFixed32(i) != nil { - t.Fatal("encFixed32") - } - x, e = o.DecodeFixed32() - if e != nil { - t.Fatal("decFixed32") - } - if x != i { - t.Fatal("fixed32 decode fail:", i, x) - } - - o = old() - if o.EncodeFixed64(i*1234567) != nil { - t.Error("encFixed64") - break - } - x, e = o.DecodeFixed64() - if e != nil { - t.Error("decFixed64") - break - } - if x != i*1234567 { - t.Error("fixed64 decode fail:", i*1234567, x) - break - } - - o = old() - i32 := int32(i - 12345) - if o.EncodeZigzag32(uint64(i32)) != nil { - t.Fatal("EncodeZigzag32") - } - x, e = o.DecodeZigzag32() - if e != nil { - t.Fatal("DecodeZigzag32") - } - if x != uint64(uint32(i32)) { - t.Fatal("zigzag32 decode fail:", i32, x) - } - - o = old() - i64 := int64(i - 12345) - if o.EncodeZigzag64(uint64(i64)) != nil { - t.Fatal("EncodeZigzag64") - } - x, e = o.DecodeZigzag64() - if e != nil { - t.Fatal("DecodeZigzag64") - } - if x != uint64(i64) { - t.Fatal("zigzag64 decode fail:", i64, x) - } - } -} - -// fakeMarshaler is a simple struct implementing Marshaler and Message interfaces. -type fakeMarshaler struct { - b []byte - err error -} - -func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err } -func (f *fakeMarshaler) String() string { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) } -func (f *fakeMarshaler) ProtoMessage() {} -func (f *fakeMarshaler) Reset() {} - -type msgWithFakeMarshaler struct { - M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"` -} - -func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) } -func (m *msgWithFakeMarshaler) ProtoMessage() {} -func (m *msgWithFakeMarshaler) Reset() {} - -// Simple tests for proto messages that implement the Marshaler interface. -func TestMarshalerEncoding(t *testing.T) { - tests := []struct { - name string - m Message - want []byte - wantErr error - }{ - { - name: "Marshaler that fails", - m: &fakeMarshaler{ - err: errors.New("some marshal err"), - b: []byte{5, 6, 7}, - }, - // Since there's an error, nothing should be written to buffer. - want: nil, - wantErr: errors.New("some marshal err"), - }, - { - name: "Marshaler that fails with RequiredNotSetError", - m: &msgWithFakeMarshaler{ - M: &fakeMarshaler{ - err: &RequiredNotSetError{}, - b: []byte{5, 6, 7}, - }, - }, - // Since there's an error that can be continued after, - // the buffer should be written. - want: []byte{ - 10, 3, // for &msgWithFakeMarshaler - 5, 6, 7, // for &fakeMarshaler - }, - wantErr: &RequiredNotSetError{}, - }, - { - name: "Marshaler that succeeds", - m: &fakeMarshaler{ - b: []byte{0, 1, 2, 3, 4, 127, 255}, - }, - want: []byte{0, 1, 2, 3, 4, 127, 255}, - wantErr: nil, - }, - } - for _, test := range tests { - b := NewBuffer(nil) - err := b.Marshal(test.m) - if _, ok := err.(*RequiredNotSetError); ok { - // We're not in package proto, so we can only assert the type in this case. - err = &RequiredNotSetError{} - } - if !reflect.DeepEqual(test.wantErr, err) { - t.Errorf("%s: got err %v wanted %v", test.name, err, test.wantErr) - } - if !reflect.DeepEqual(test.want, b.Bytes()) { - t.Errorf("%s: got bytes %v wanted %v", test.name, b.Bytes(), test.want) - } - } -} - -// Simple tests for bytes -func TestBytesPrimitives(t *testing.T) { - o := old() - bytes := []byte{'n', 'o', 'w', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 't', 'i', 'm', 'e'} - if o.EncodeRawBytes(bytes) != nil { - t.Error("EncodeRawBytes") - } - decb, e := o.DecodeRawBytes(false) - if e != nil { - t.Error("DecodeRawBytes") - } - equalbytes(bytes, decb, t) -} - -// Simple tests for strings -func TestStringPrimitives(t *testing.T) { - o := old() - s := "now is the time" - if o.EncodeStringBytes(s) != nil { - t.Error("enc_string") - } - decs, e := o.DecodeStringBytes() - if e != nil { - t.Error("dec_string") - } - if s != decs { - t.Error("string encode/decode fail:", s, decs) - } -} - -// Do we catch the "required bit not set" case? -func TestRequiredBit(t *testing.T) { - o := old() - pb := new(GoTest) - err := o.Marshal(pb) - if err == nil { - t.Error("did not catch missing required fields") - } else if strings.Index(err.Error(), "Kind") < 0 { - t.Error("wrong error type:", err) - } -} - -// Check that all fields are nil. -// Clearly silly, and a residue from a more interesting test with an earlier, -// different initialization property, but it once caught a compiler bug so -// it lives. -func checkInitialized(pb *GoTest, t *testing.T) { - if pb.F_BoolDefaulted != nil { - t.Error("New or Reset did not set boolean:", *pb.F_BoolDefaulted) - } - if pb.F_Int32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Int32Defaulted) - } - if pb.F_Int64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Int64Defaulted) - } - if pb.F_Fixed32Defaulted != nil { - t.Error("New or Reset did not set fixed32:", *pb.F_Fixed32Defaulted) - } - if pb.F_Fixed64Defaulted != nil { - t.Error("New or Reset did not set fixed64:", *pb.F_Fixed64Defaulted) - } - if pb.F_Uint32Defaulted != nil { - t.Error("New or Reset did not set uint32:", *pb.F_Uint32Defaulted) - } - if pb.F_Uint64Defaulted != nil { - t.Error("New or Reset did not set uint64:", *pb.F_Uint64Defaulted) - } - if pb.F_FloatDefaulted != nil { - t.Error("New or Reset did not set float:", *pb.F_FloatDefaulted) - } - if pb.F_DoubleDefaulted != nil { - t.Error("New or Reset did not set double:", *pb.F_DoubleDefaulted) - } - if pb.F_StringDefaulted != nil { - t.Error("New or Reset did not set string:", *pb.F_StringDefaulted) - } - if pb.F_BytesDefaulted != nil { - t.Error("New or Reset did not set bytes:", string(pb.F_BytesDefaulted)) - } - if pb.F_Sint32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Sint32Defaulted) - } - if pb.F_Sint64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Sint64Defaulted) - } -} - -// Does Reset() reset? -func TestReset(t *testing.T) { - pb := initGoTest(true) - // muck with some values - pb.F_BoolDefaulted = Bool(false) - pb.F_Int32Defaulted = Int32(237) - pb.F_Int64Defaulted = Int64(12346) - pb.F_Fixed32Defaulted = Uint32(32000) - pb.F_Fixed64Defaulted = Uint64(666) - pb.F_Uint32Defaulted = Uint32(323232) - pb.F_Uint64Defaulted = nil - pb.F_FloatDefaulted = nil - pb.F_DoubleDefaulted = Float64(0) - pb.F_StringDefaulted = String("gotcha") - pb.F_BytesDefaulted = []byte("asdfasdf") - pb.F_Sint32Defaulted = Int32(123) - pb.F_Sint64Defaulted = Int64(789) - pb.Reset() - checkInitialized(pb, t) -} - -// All required fields set, no defaults provided. -func TestEncodeDecode1(t *testing.T) { - pb := initGoTest(false) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 0x20 - "714000000000000000"+ // field 14, encoding 1, value 0x40 - "78a019"+ // field 15, encoding 0, value 0xca0 = 3232 - "8001c032"+ // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2, string "string" - "b304"+ // field 70, encoding 3, start group - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // field 70, encoding 4, end group - "aa0605"+"6279746573"+ // field 101, encoding 2, string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f") // field 103, encoding 0, 0x7f zigzag64 -} - -// All required fields set, defaults provided. -func TestEncodeDecode2(t *testing.T) { - pb := initGoTest(true) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All default fields set to their default value by hand -func TestEncodeDecode3(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolDefaulted = Bool(true) - pb.F_Int32Defaulted = Int32(32) - pb.F_Int64Defaulted = Int64(64) - pb.F_Fixed32Defaulted = Uint32(320) - pb.F_Fixed64Defaulted = Uint64(640) - pb.F_Uint32Defaulted = Uint32(3200) - pb.F_Uint64Defaulted = Uint64(6400) - pb.F_FloatDefaulted = Float32(314159) - pb.F_DoubleDefaulted = Float64(271828) - pb.F_StringDefaulted = String("hello, \"world!\"\n") - pb.F_BytesDefaulted = []byte("Bignose") - pb.F_Sint32Defaulted = Int32(-32) - pb.F_Sint64Defaulted = Int64(-64) - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All required fields set, defaults provided, all non-defaulted optional fields have values. -func TestEncodeDecode4(t *testing.T) { - pb := initGoTest(true) - pb.Table = String("hello") - pb.Param = Int32(7) - pb.OptionalField = initGoTestField() - pb.F_BoolOptional = Bool(true) - pb.F_Int32Optional = Int32(32) - pb.F_Int64Optional = Int64(64) - pb.F_Fixed32Optional = Uint32(3232) - pb.F_Fixed64Optional = Uint64(6464) - pb.F_Uint32Optional = Uint32(323232) - pb.F_Uint64Optional = Uint64(646464) - pb.F_FloatOptional = Float32(32.) - pb.F_DoubleOptional = Float64(64.) - pb.F_StringOptional = String("hello") - pb.F_BytesOptional = []byte("Bignose") - pb.F_Sint32Optional = Int32(-32) - pb.F_Sint64Optional = Int64(-64) - pb.Optionalgroup = initGoTest_OptionalGroup() - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "1205"+"68656c6c6f"+ // field 2, encoding 2, string "hello" - "1807"+ // field 3, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "320d"+"0a056c6162656c120474797065"+ // field 6, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "f00101"+ // field 30, encoding 0, value 1 - "f80120"+ // field 31, encoding 0, value 32 - "800240"+ // field 32, encoding 0, value 64 - "8d02a00c0000"+ // field 33, encoding 5, value 3232 - "91024019000000000000"+ // field 34, encoding 1, value 6464 - "9802a0dd13"+ // field 35, encoding 0, value 323232 - "a002c0ba27"+ // field 36, encoding 0, value 646464 - "ad0200000042"+ // field 37, encoding 5, value 32.0 - "b1020000000000005040"+ // field 38, encoding 1, value 64.0 - "ba0205"+"68656c6c6f"+ // field 39, encoding 2, string "hello" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "d305"+ // start group field 90 level 1 - "da0508"+"6f7074696f6e616c"+ // field 91, encoding 2, string "optional" - "d405"+ // end group field 90 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "ea1207"+"4269676e6f7365"+ // field 301, encoding 2, string "Bignose" - "f0123f"+ // field 302, encoding 0, value 63 - "f8127f"+ // field 303, encoding 0, value 127 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestEncodeDecode5(t *testing.T) { - pb := initGoTest(true) - pb.RepeatedField = []*GoTestField{initGoTestField(), initGoTestField()} - pb.F_BoolRepeated = []bool{false, true} - pb.F_Int32Repeated = []int32{32, 33} - pb.F_Int64Repeated = []int64{64, 65} - pb.F_Fixed32Repeated = []uint32{3232, 3333} - pb.F_Fixed64Repeated = []uint64{6464, 6565} - pb.F_Uint32Repeated = []uint32{323232, 333333} - pb.F_Uint64Repeated = []uint64{646464, 656565} - pb.F_FloatRepeated = []float32{32., 33.} - pb.F_DoubleRepeated = []float64{64., 65.} - pb.F_StringRepeated = []string{"hello", "sailor"} - pb.F_BytesRepeated = [][]byte{[]byte("big"), []byte("nose")} - pb.F_Sint32Repeated = []int32{32, -32} - pb.F_Sint64Repeated = []int64{64, -64} - pb.Repeatedgroup = []*GoTest_RepeatedGroup{initGoTest_RepeatedGroup(), initGoTest_RepeatedGroup()} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "a00100"+ // field 20, encoding 0, value 0 - "a00101"+ // field 20, encoding 0, value 1 - "a80120"+ // field 21, encoding 0, value 32 - "a80121"+ // field 21, encoding 0, value 33 - "b00140"+ // field 22, encoding 0, value 64 - "b00141"+ // field 22, encoding 0, value 65 - "bd01a00c0000"+ // field 23, encoding 5, value 3232 - "bd01050d0000"+ // field 23, encoding 5, value 3333 - "c1014019000000000000"+ // field 24, encoding 1, value 6464 - "c101a519000000000000"+ // field 24, encoding 1, value 6565 - "c801a0dd13"+ // field 25, encoding 0, value 323232 - "c80195ac14"+ // field 25, encoding 0, value 333333 - "d001c0ba27"+ // field 26, encoding 0, value 646464 - "d001b58928"+ // field 26, encoding 0, value 656565 - "dd0100000042"+ // field 27, encoding 5, value 32.0 - "dd0100000442"+ // field 27, encoding 5, value 33.0 - "e1010000000000005040"+ // field 28, encoding 1, value 64.0 - "e1010000000000405040"+ // field 28, encoding 1, value 65.0 - "ea0105"+"68656c6c6f"+ // field 29, encoding 2, string "hello" - "ea0106"+"7361696c6f72"+ // field 29, encoding 2, string "sailor" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "ca0c03"+"626967"+ // field 201, encoding 2, string "big" - "ca0c04"+"6e6f7365"+ // field 201, encoding 2, string "nose" - "d00c40"+ // field 202, encoding 0, value 32 - "d00c3f"+ // field 202, encoding 0, value -32 - "d80c8001"+ // field 203, encoding 0, value 64 - "d80c7f"+ // field 203, encoding 0, value -64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All required fields set, all packed repeated fields given two values. -func TestEncodeDecode6(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolRepeatedPacked = []bool{false, true} - pb.F_Int32RepeatedPacked = []int32{32, 33} - pb.F_Int64RepeatedPacked = []int64{64, 65} - pb.F_Fixed32RepeatedPacked = []uint32{3232, 3333} - pb.F_Fixed64RepeatedPacked = []uint64{6464, 6565} - pb.F_Uint32RepeatedPacked = []uint32{323232, 333333} - pb.F_Uint64RepeatedPacked = []uint64{646464, 656565} - pb.F_FloatRepeatedPacked = []float32{32., 33.} - pb.F_DoubleRepeatedPacked = []float64{64., 65.} - pb.F_Sint32RepeatedPacked = []int32{32, -32} - pb.F_Sint64RepeatedPacked = []int64{64, -64} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "9203020001"+ // field 50, encoding 2, 2 bytes, value 0, value 1 - "9a03022021"+ // field 51, encoding 2, 2 bytes, value 32, value 33 - "a203024041"+ // field 52, encoding 2, 2 bytes, value 64, value 65 - "aa0308"+ // field 53, encoding 2, 8 bytes - "a00c0000050d0000"+ // value 3232, value 3333 - "b20310"+ // field 54, encoding 2, 16 bytes - "4019000000000000a519000000000000"+ // value 6464, value 6565 - "ba0306"+ // field 55, encoding 2, 6 bytes - "a0dd1395ac14"+ // value 323232, value 333333 - "c20306"+ // field 56, encoding 2, 6 bytes - "c0ba27b58928"+ // value 646464, value 656565 - "ca0308"+ // field 57, encoding 2, 8 bytes - "0000004200000442"+ // value 32.0, value 33.0 - "d20310"+ // field 58, encoding 2, 16 bytes - "00000000000050400000000000405040"+ // value 64.0, value 65.0 - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "b21f02"+ // field 502, encoding 2, 2 bytes - "403f"+ // value 32, value -32 - "ba1f03"+ // field 503, encoding 2, 3 bytes - "80017f") // value 64, value -64 -} - -// Test that we can encode empty bytes fields. -func TestEncodeDecodeBytes1(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRequired = []byte{} - pb.F_BytesRepeated = [][]byte{{}} - pb.F_BytesOptional = []byte{} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if pbd.F_BytesRequired == nil || len(pbd.F_BytesRequired) != 0 { - t.Error("required empty bytes field is incorrect") - } - if pbd.F_BytesRepeated == nil || len(pbd.F_BytesRepeated) == 1 && pbd.F_BytesRepeated[0] == nil { - t.Error("repeated empty bytes field is incorrect") - } - if pbd.F_BytesOptional == nil || len(pbd.F_BytesOptional) != 0 { - t.Error("optional empty bytes field is incorrect") - } -} - -// Test that we encode nil-valued fields of a repeated bytes field correctly. -// Since entries in a repeated field cannot be nil, nil must mean empty value. -func TestEncodeDecodeBytes2(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRepeated = [][]byte{nil} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if len(pbd.F_BytesRepeated) != 1 || pbd.F_BytesRepeated[0] == nil { - t.Error("Unexpected value for repeated bytes field") - } -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestSkippingUnrecognizedFields(t *testing.T) { - o := old() - pb := initGoTestField() - - // Marshal it normally. - o.Marshal(pb) - - // Now new a GoSkipTest record. - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - // Marshal it into same buffer. - o.Marshal(skip) - - pbd := new(GoTestField) - o.Unmarshal(pbd) - - // The __unrecognized field should be a marshaling of GoSkipTest - skipd := new(GoSkipTest) - - o.SetBuf(pbd.XXX_unrecognized) - o.Unmarshal(skipd) - - if *skipd.SkipInt32 != *skip.SkipInt32 { - t.Error("skip int32", skipd.SkipInt32) - } - if *skipd.SkipFixed32 != *skip.SkipFixed32 { - t.Error("skip fixed32", skipd.SkipFixed32) - } - if *skipd.SkipFixed64 != *skip.SkipFixed64 { - t.Error("skip fixed64", skipd.SkipFixed64) - } - if *skipd.SkipString != *skip.SkipString { - t.Error("skip string", *skipd.SkipString) - } - if *skipd.Skipgroup.GroupInt32 != *skip.Skipgroup.GroupInt32 { - t.Error("skip group int32", skipd.Skipgroup.GroupInt32) - } - if *skipd.Skipgroup.GroupString != *skip.Skipgroup.GroupString { - t.Error("skip group string", *skipd.Skipgroup.GroupString) - } -} - -// Check that unrecognized fields of a submessage are preserved. -func TestSubmessageUnrecognizedFields(t *testing.T) { - nm := &NewMessage{ - Nested: &NewMessage_Nested{ - Name: String("Nigel"), - FoodGroup: String("carbs"), - }, - } - b, err := Marshal(nm) - if err != nil { - t.Fatalf("Marshal of NewMessage: %v", err) - } - - // Unmarshal into an OldMessage. - om := new(OldMessage) - if err := Unmarshal(b, om); err != nil { - t.Fatalf("Unmarshal to OldMessage: %v", err) - } - exp := &OldMessage{ - Nested: &OldMessage_Nested{ - Name: String("Nigel"), - // normal protocol buffer users should not do this - XXX_unrecognized: []byte("\x12\x05carbs"), - }, - } - if !Equal(om, exp) { - t.Errorf("om = %v, want %v", om, exp) - } - - // Clone the OldMessage. - om = Clone(om).(*OldMessage) - if !Equal(om, exp) { - t.Errorf("Clone(om) = %v, want %v", om, exp) - } - - // Marshal the OldMessage, then unmarshal it into an empty NewMessage. - if b, err = Marshal(om); err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - t.Logf("Marshal(%v) -> %q", om, b) - nm2 := new(NewMessage) - if err := Unmarshal(b, nm2); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - if !Equal(nm, nm2) { - t.Errorf("NewMessage round-trip: %v => %v", nm, nm2) - } -} - -// Check that an int32 field can be upgraded to an int64 field. -func TestNegativeInt32(t *testing.T) { - om := &OldMessage{ - Num: Int32(-1), - } - b, err := Marshal(om) - if err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - - // Check the size. It should be 11 bytes; - // 1 for the field/wire type, and 10 for the negative number. - if len(b) != 11 { - t.Errorf("%v marshaled as %q, wanted 11 bytes", om, b) - } - - // Unmarshal into a NewMessage. - nm := new(NewMessage) - if err := Unmarshal(b, nm); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - want := &NewMessage{ - Num: Int64(-1), - } - if !Equal(nm, want) { - t.Errorf("nm = %v, want %v", nm, want) - } -} - -// Check that we can grow an array (repeated field) to have many elements. -// This test doesn't depend only on our encoding; for variety, it makes sure -// we create, encode, and decode the correct contents explicitly. It's therefore -// a bit messier. -// This test also uses (and hence tests) the Marshal/Unmarshal functions -// instead of the methods. -func TestBigRepeated(t *testing.T) { - pb := initGoTest(true) - - // Create the arrays - const N = 50 // Internally the library starts much smaller. - pb.Repeatedgroup = make([]*GoTest_RepeatedGroup, N) - pb.F_Sint64Repeated = make([]int64, N) - pb.F_Sint32Repeated = make([]int32, N) - pb.F_BytesRepeated = make([][]byte, N) - pb.F_StringRepeated = make([]string, N) - pb.F_DoubleRepeated = make([]float64, N) - pb.F_FloatRepeated = make([]float32, N) - pb.F_Uint64Repeated = make([]uint64, N) - pb.F_Uint32Repeated = make([]uint32, N) - pb.F_Fixed64Repeated = make([]uint64, N) - pb.F_Fixed32Repeated = make([]uint32, N) - pb.F_Int64Repeated = make([]int64, N) - pb.F_Int32Repeated = make([]int32, N) - pb.F_BoolRepeated = make([]bool, N) - pb.RepeatedField = make([]*GoTestField, N) - - // Fill in the arrays with checkable values. - igtf := initGoTestField() - igtrg := initGoTest_RepeatedGroup() - for i := 0; i < N; i++ { - pb.Repeatedgroup[i] = igtrg - pb.F_Sint64Repeated[i] = int64(i) - pb.F_Sint32Repeated[i] = int32(i) - s := fmt.Sprint(i) - pb.F_BytesRepeated[i] = []byte(s) - pb.F_StringRepeated[i] = s - pb.F_DoubleRepeated[i] = float64(i) - pb.F_FloatRepeated[i] = float32(i) - pb.F_Uint64Repeated[i] = uint64(i) - pb.F_Uint32Repeated[i] = uint32(i) - pb.F_Fixed64Repeated[i] = uint64(i) - pb.F_Fixed32Repeated[i] = uint32(i) - pb.F_Int64Repeated[i] = int64(i) - pb.F_Int32Repeated[i] = int32(i) - pb.F_BoolRepeated[i] = i%2 == 0 - pb.RepeatedField[i] = igtf - } - - // Marshal. - buf, _ := Marshal(pb) - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - Unmarshal(buf, pbd) - - // Check the checkable values - for i := uint64(0); i < N; i++ { - if pbd.Repeatedgroup[i] == nil { // TODO: more checking? - t.Error("pbd.Repeatedgroup bad") - } - var x uint64 - x = uint64(pbd.F_Sint64Repeated[i]) - if x != i { - t.Error("pbd.F_Sint64Repeated bad", x, i) - } - x = uint64(pbd.F_Sint32Repeated[i]) - if x != i { - t.Error("pbd.F_Sint32Repeated bad", x, i) - } - s := fmt.Sprint(i) - equalbytes(pbd.F_BytesRepeated[i], []byte(s), t) - if pbd.F_StringRepeated[i] != s { - t.Error("pbd.F_Sint32Repeated bad", pbd.F_StringRepeated[i], i) - } - x = uint64(pbd.F_DoubleRepeated[i]) - if x != i { - t.Error("pbd.F_DoubleRepeated bad", x, i) - } - x = uint64(pbd.F_FloatRepeated[i]) - if x != i { - t.Error("pbd.F_FloatRepeated bad", x, i) - } - x = pbd.F_Uint64Repeated[i] - if x != i { - t.Error("pbd.F_Uint64Repeated bad", x, i) - } - x = uint64(pbd.F_Uint32Repeated[i]) - if x != i { - t.Error("pbd.F_Uint32Repeated bad", x, i) - } - x = pbd.F_Fixed64Repeated[i] - if x != i { - t.Error("pbd.F_Fixed64Repeated bad", x, i) - } - x = uint64(pbd.F_Fixed32Repeated[i]) - if x != i { - t.Error("pbd.F_Fixed32Repeated bad", x, i) - } - x = uint64(pbd.F_Int64Repeated[i]) - if x != i { - t.Error("pbd.F_Int64Repeated bad", x, i) - } - x = uint64(pbd.F_Int32Repeated[i]) - if x != i { - t.Error("pbd.F_Int32Repeated bad", x, i) - } - if pbd.F_BoolRepeated[i] != (i%2 == 0) { - t.Error("pbd.F_BoolRepeated bad", x, i) - } - if pbd.RepeatedField[i] == nil { // TODO: more checking? - t.Error("pbd.RepeatedField bad") - } - } -} - -// Verify we give a useful message when decoding to the wrong structure type. -func TestTypeMismatch(t *testing.T) { - pb1 := initGoTest(true) - - // Marshal - o := old() - o.Marshal(pb1) - - // Now Unmarshal it to the wrong type. - pb2 := initGoTestField() - err := o.Unmarshal(pb2) - if err == nil { - t.Error("expected error, got no error") - } else if !strings.Contains(err.Error(), "bad wiretype") { - t.Error("expected bad wiretype error, got", err) - } -} - -func encodeDecode(t *testing.T, in, out Message, msg string) { - buf, err := Marshal(in) - if err != nil { - t.Fatalf("failed marshaling %v: %v", msg, err) - } - if err := Unmarshal(buf, out); err != nil { - t.Fatalf("failed unmarshaling %v: %v", msg, err) - } -} - -func TestPackedNonPackedDecoderSwitching(t *testing.T) { - np, p := new(NonPackedTest), new(PackedTest) - - // non-packed -> packed - np.A = []int32{0, 1, 1, 2, 3, 5} - encodeDecode(t, np, p, "non-packed -> packed") - if !reflect.DeepEqual(np.A, p.B) { - t.Errorf("failed non-packed -> packed; np.A=%+v, p.B=%+v", np.A, p.B) - } - - // packed -> non-packed - np.Reset() - p.B = []int32{3, 1, 4, 1, 5, 9} - encodeDecode(t, p, np, "packed -> non-packed") - if !reflect.DeepEqual(p.B, np.A) { - t.Errorf("failed packed -> non-packed; p.B=%+v, np.A=%+v", p.B, np.A) - } -} - -func TestProto1RepeatedGroup(t *testing.T) { - pb := &MessageList{ - Message: []*MessageList_Message{ - { - Name: String("blah"), - Count: Int32(7), - }, - // NOTE: pb.Message[1] is a nil - nil, - }, - } - - o := old() - err := o.Marshal(pb) - if err == nil || !strings.Contains(err.Error(), "repeated field Message has nil") { - t.Fatalf("unexpected or no error when marshaling: %v", err) - } -} - -// Test that enums work. Checks for a bug introduced by making enums -// named types instead of int32: newInt32FromUint64 would crash with -// a type mismatch in reflect.PointTo. -func TestEnum(t *testing.T) { - pb := new(GoEnum) - pb.Foo = FOO_FOO1.Enum() - o := old() - if err := o.Marshal(pb); err != nil { - t.Fatal("error encoding enum:", err) - } - pb1 := new(GoEnum) - if err := o.Unmarshal(pb1); err != nil { - t.Fatal("error decoding enum:", err) - } - if *pb1.Foo != FOO_FOO1 { - t.Error("expected 7 but got ", *pb1.Foo) - } -} - -// Enum types have String methods. Check that enum fields can be printed. -// We don't care what the value actually is, just as long as it doesn't crash. -func TestPrintingNilEnumFields(t *testing.T) { - pb := new(GoEnum) - fmt.Sprintf("%+v", pb) -} - -// Verify that absent required fields cause Marshal/Unmarshal to return errors. -func TestRequiredFieldEnforcement(t *testing.T) { - pb := new(GoTestField) - _, err := Marshal(pb) - if err == nil { - t.Error("marshal: expected error, got nil") - } else if strings.Index(err.Error(), "Label") < 0 { - t.Errorf("marshal: bad error type: %v", err) - } - - // A slightly sneaky, yet valid, proto. It encodes the same required field twice, - // so simply counting the required fields is insufficient. - // field 1, encoding 2, value "hi" - buf := []byte("\x0A\x02hi\x0A\x02hi") - err = Unmarshal(buf, pb) - if err == nil { - t.Error("unmarshal: expected error, got nil") - } else if strings.Index(err.Error(), "{Unknown}") < 0 { - t.Errorf("unmarshal: bad error type: %v", err) - } -} - -func TestTypedNilMarshal(t *testing.T) { - // A typed nil should return ErrNil and not crash. - _, err := Marshal((*GoEnum)(nil)) - if err != ErrNil { - t.Errorf("Marshal: got err %v, want ErrNil", err) - } -} - -// A type that implements the Marshaler interface, but is not nillable. -type nonNillableInt uint64 - -func (nni nonNillableInt) Marshal() ([]byte, error) { - return EncodeVarint(uint64(nni)), nil -} - -type NNIMessage struct { - nni nonNillableInt -} - -func (*NNIMessage) Reset() {} -func (*NNIMessage) String() string { return "" } -func (*NNIMessage) ProtoMessage() {} - -// A type that implements the Marshaler interface and is nillable. -type nillableMessage struct { - x uint64 -} - -func (nm *nillableMessage) Marshal() ([]byte, error) { - return EncodeVarint(nm.x), nil -} - -type NMMessage struct { - nm *nillableMessage -} - -func (*NMMessage) Reset() {} -func (*NMMessage) String() string { return "" } -func (*NMMessage) ProtoMessage() {} - -// Verify a type that uses the Marshaler interface, but has a nil pointer. -func TestNilMarshaler(t *testing.T) { - // Try a struct with a Marshaler field that is nil. - // It should be directly marshable. - nmm := new(NMMessage) - if _, err := Marshal(nmm); err != nil { - t.Error("unexpected error marshaling nmm: ", err) - } - - // Try a struct with a Marshaler field that is not nillable. - nnim := new(NNIMessage) - nnim.nni = 7 - var _ Marshaler = nnim.nni // verify it is truly a Marshaler - if _, err := Marshal(nnim); err != nil { - t.Error("unexpected error marshaling nnim: ", err) - } -} - -func TestAllSetDefaults(t *testing.T) { - // Exercise SetDefaults with all scalar field types. - m := &Defaults{ - // NaN != NaN, so override that here. - F_Nan: Float32(1.7), - } - expected := &Defaults{ - F_Bool: Bool(true), - F_Int32: Int32(32), - F_Int64: Int64(64), - F_Fixed32: Uint32(320), - F_Fixed64: Uint64(640), - F_Uint32: Uint32(3200), - F_Uint64: Uint64(6400), - F_Float: Float32(314159), - F_Double: Float64(271828), - F_String: String(`hello, "world!"` + "\n"), - F_Bytes: []byte("Bignose"), - F_Sint32: Int32(-32), - F_Sint64: Int64(-64), - F_Enum: Defaults_GREEN.Enum(), - F_Pinf: Float32(float32(math.Inf(1))), - F_Ninf: Float32(float32(math.Inf(-1))), - F_Nan: Float32(1.7), - StrZero: String(""), - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("SetDefaults failed\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithSetField(t *testing.T) { - // Check that a set value is not overridden. - m := &Defaults{ - F_Int32: Int32(12), - } - SetDefaults(m) - if v := m.GetF_Int32(); v != 12 { - t.Errorf("m.FInt32 = %v, want 12", v) - } -} - -func TestSetDefaultsWithSubMessage(t *testing.T) { - m := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - }, - } - expected := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - Port: Int32(4000), - }, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithRepeatedSubMessage(t *testing.T) { - m := &MyMessage{ - RepInner: []*InnerMessage{{}}, - } - expected := &MyMessage{ - RepInner: []*InnerMessage{{ - Port: Int32(4000), - }}, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultWithRepeatedNonMessage(t *testing.T) { - m := &MyMessage{ - Pet: []string{"turtle", "wombat"}, - } - expected := Clone(m) - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestMaximumTagNumber(t *testing.T) { - m := &MaxTag{ - LastField: String("natural goat essence"), - } - buf, err := Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal failed: %v", err) - } - m2 := new(MaxTag) - if err := Unmarshal(buf, m2); err != nil { - t.Fatalf("proto.Unmarshal failed: %v", err) - } - if got, want := m2.GetLastField(), *m.LastField; got != want { - t.Errorf("got %q, want %q", got, want) - } -} - -func TestJSON(t *testing.T) { - m := &MyMessage{ - Count: Int32(4), - Pet: []string{"bunny", "kitty"}, - Inner: &InnerMessage{ - Host: String("cauchy"), - }, - Bikeshed: MyMessage_GREEN.Enum(), - } - const expected = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":1}` - - b, err := json.Marshal(m) - if err != nil { - t.Fatalf("json.Marshal failed: %v", err) - } - s := string(b) - if s != expected { - t.Errorf("got %s\nwant %s", s, expected) - } - - received := new(MyMessage) - if err := json.Unmarshal(b, received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } - - // Test unmarshalling of JSON with symbolic enum name. - const old = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":"GREEN"}` - received.Reset() - if err := json.Unmarshal([]byte(old), received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } -} - -func TestBadWireType(t *testing.T) { - b := []byte{7<<3 | 6} // field 7, wire type 6 - pb := new(OtherMessage) - if err := Unmarshal(b, pb); err == nil { - t.Errorf("Unmarshal did not fail") - } else if !strings.Contains(err.Error(), "unknown wire type") { - t.Errorf("wrong error: %v", err) - } -} - -func TestBytesWithInvalidLength(t *testing.T) { - // If a byte sequence has an invalid (negative) length, Unmarshal should not panic. - b := []byte{2<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0} - Unmarshal(b, new(MyMessage)) -} - -func TestLengthOverflow(t *testing.T) { - // Overflowing a length should not panic. - b := []byte{2<<3 | WireBytes, 1, 1, 3<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01} - Unmarshal(b, new(MyMessage)) -} - -func TestVarintOverflow(t *testing.T) { - // Overflowing a 64-bit length should not be allowed. - b := []byte{1<<3 | WireVarint, 0x01, 3<<3 | WireBytes, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01} - if err := Unmarshal(b, new(MyMessage)); err == nil { - t.Fatalf("Overflowed uint64 length without error") - } -} - -func TestUnmarshalFuzz(t *testing.T) { - const N = 1000 - seed := time.Now().UnixNano() - t.Logf("RNG seed is %d", seed) - rng := rand.New(rand.NewSource(seed)) - buf := make([]byte, 20) - for i := 0; i < N; i++ { - for j := range buf { - buf[j] = byte(rng.Intn(256)) - } - fuzzUnmarshal(t, buf) - } -} - -func TestMergeMessages(t *testing.T) { - pb := &MessageList{Message: []*MessageList_Message{{Name: String("x"), Count: Int32(1)}}} - data, err := Marshal(pb) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - pb1 := new(MessageList) - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("first Unmarshal: %v", err) - } - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("second Unmarshal: %v", err) - } - if len(pb1.Message) != 1 { - t.Errorf("two Unmarshals produced %d Messages, want 1", len(pb1.Message)) - } - - pb2 := new(MessageList) - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("first UnmarshalMerge: %v", err) - } - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("second UnmarshalMerge: %v", err) - } - if len(pb2.Message) != 2 { - t.Errorf("two UnmarshalMerges produced %d Messages, want 2", len(pb2.Message)) - } -} - -func TestExtensionMarshalOrder(t *testing.T) { - m := &MyMessage{Count: Int(123)} - if err := SetExtension(m, E_Ext_More, &Ext{Data: String("alpha")}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Text, String("aleph")); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Number, Int32(1)); err != nil { - t.Fatalf("SetExtension: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - var orig []byte - for i := 0; i < 100; i++ { - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if i == 0 { - orig = b - continue - } - if !bytes.Equal(b, orig) { - t.Errorf("Bytes differ on attempt #%d", i) - } - } -} - -// Many extensions, because small maps might not iterate differently on each iteration. -var exts = []*ExtensionDesc{ - E_X201, - E_X202, - E_X203, - E_X204, - E_X205, - E_X206, - E_X207, - E_X208, - E_X209, - E_X210, - E_X211, - E_X212, - E_X213, - E_X214, - E_X215, - E_X216, - E_X217, - E_X218, - E_X219, - E_X220, - E_X221, - E_X222, - E_X223, - E_X224, - E_X225, - E_X226, - E_X227, - E_X228, - E_X229, - E_X230, - E_X231, - E_X232, - E_X233, - E_X234, - E_X235, - E_X236, - E_X237, - E_X238, - E_X239, - E_X240, - E_X241, - E_X242, - E_X243, - E_X244, - E_X245, - E_X246, - E_X247, - E_X248, - E_X249, - E_X250, -} - -func TestMessageSetMarshalOrder(t *testing.T) { - m := &MyMessageSet{} - for _, x := range exts { - if err := SetExtension(m, x, &Empty{}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - } - - buf, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - for i := 0; i < 10; i++ { - b1, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if !bytes.Equal(b1, buf) { - t.Errorf("Bytes differ on re-Marshal #%d", i) - } - - m2 := &MyMessageSet{} - if err := Unmarshal(buf, m2); err != nil { - t.Errorf("Unmarshal: %v", err) - } - b2, err := Marshal(m2) - if err != nil { - t.Errorf("re-Marshal: %v", err) - } - if !bytes.Equal(b2, buf) { - t.Errorf("Bytes differ on round-trip #%d", i) - } - } -} - -func TestUnmarshalMergesMessages(t *testing.T) { - // If a nested message occurs twice in the input, - // the fields should be merged when decoding. - a := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("polhode"), - Port: Int32(1234), - }, - } - aData, err := Marshal(a) - if err != nil { - t.Fatalf("Marshal(a): %v", err) - } - b := &OtherMessage{ - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Connected: Bool(true), - }, - } - bData, err := Marshal(b) - if err != nil { - t.Fatalf("Marshal(b): %v", err) - } - want := &OtherMessage{ - Key: Int64(123), - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Port: Int32(1234), - Connected: Bool(true), - }, - } - got := new(OtherMessage) - if err := Unmarshal(append(aData, bData...), got); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !Equal(got, want) { - t.Errorf("\n got %v\nwant %v", got, want) - } -} - -func TestEncodingSizes(t *testing.T) { - tests := []struct { - m Message - n int - }{ - {&Defaults{F_Int32: Int32(math.MaxInt32)}, 6}, - {&Defaults{F_Int32: Int32(math.MinInt32)}, 11}, - {&Defaults{F_Uint32: Uint32(uint32(math.MaxInt32) + 1)}, 6}, - {&Defaults{F_Uint32: Uint32(math.MaxUint32)}, 6}, - } - for _, test := range tests { - b, err := Marshal(test.m) - if err != nil { - t.Errorf("Marshal(%v): %v", test.m, err) - continue - } - if len(b) != test.n { - t.Errorf("Marshal(%v) yielded %d bytes, want %d bytes", test.m, len(b), test.n) - } - } -} - -func TestRequiredNotSetError(t *testing.T) { - pb := initGoTest(false) - pb.RequiredField.Label = nil - pb.F_Int32Required = nil - pb.F_Int64Required = nil - - expected := "0807" + // field 1, encoding 0, value 7 - "2206" + "120474797065" + // field 4, encoding 2 (GoTestField) - "5001" + // field 10, encoding 0, value 1 - "6d20000000" + // field 13, encoding 5, value 0x20 - "714000000000000000" + // field 14, encoding 1, value 0x40 - "78a019" + // field 15, encoding 0, value 0xca0 = 3232 - "8001c032" + // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45" + // field 17, encoding 5, value 3232.0 - "9101000000000040b940" + // field 18, encoding 1, value 6464.0 - "9a0106" + "737472696e67" + // field 19, encoding 2, string "string" - "b304" + // field 70, encoding 3, start group - "ba0408" + "7265717569726564" + // field 71, encoding 2, string "required" - "b404" + // field 70, encoding 4, end group - "aa0605" + "6279746573" + // field 101, encoding 2, string "bytes" - "b0063f" + // field 102, encoding 0, 0x3f zigzag32 - "b8067f" // field 103, encoding 0, 0x7f zigzag64 - - o := old() - bytes, err := Marshal(pb) - if _, ok := err.(*RequiredNotSetError); !ok { - fmt.Printf("marshal-1 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("expected = %s", expected) - } - if strings.Index(err.Error(), "RequiredField.Label") < 0 { - t.Errorf("marshal-1 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 1", bytes) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = Unmarshal(bytes, pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Fatalf("unmarshal err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if strings.Index(err.Error(), "RequiredField.{Unknown}") < 0 { - t.Errorf("unmarshal wrong err msg: %v", err) - } - bytes, err = Marshal(pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Errorf("marshal-2 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if strings.Index(err.Error(), "RequiredField.Label") < 0 { - t.Errorf("marshal-2 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 2", bytes) - t.Fatalf("string = %s", expected) - } -} - -func fuzzUnmarshal(t *testing.T, data []byte) { - defer func() { - if e := recover(); e != nil { - t.Errorf("These bytes caused a panic: %+v", data) - t.Logf("Stack:\n%s", debug.Stack()) - t.FailNow() - } - }() - - pb := new(MyMessage) - Unmarshal(data, pb) -} - -func TestMapFieldMarshal(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // b should be the concatenation of these three byte sequences in some order. - parts := []string{ - "\n\a\b\x01\x12\x03Rob", - "\n\a\b\x04\x12\x03Ian", - "\n\b\b\x08\x12\x04Dave", - } - ok := false - for i := range parts { - for j := range parts { - if j == i { - continue - } - for k := range parts { - if k == i || k == j { - continue - } - try := parts[i] + parts[j] + parts[k] - if bytes.Equal(b, []byte(try)) { - ok = true - break - } - } - } - } - if !ok { - t.Fatalf("Incorrect Marshal output.\n got %q\nwant %q (or a permutation of that)", b, parts[0]+parts[1]+parts[2]) - } - t.Logf("FYI b: %q", b) - - (new(Buffer)).DebugPrint("Dump of b", b) -} - -func TestMapFieldRoundTrips(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - MsgMapping: map[int64]*FloatingPoint{ - 0x7001: &FloatingPoint{F: Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{ - false: []byte("that's not right!"), - true: []byte("aye, 'tis true!"), - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("FYI b: %q", b) - m2 := new(MessageWithMap) - if err := Unmarshal(b, m2); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - for _, pair := range [][2]interface{}{ - {m.NameMapping, m2.NameMapping}, - {m.MsgMapping, m2.MsgMapping}, - {m.ByteMapping, m2.ByteMapping}, - } { - if !reflect.DeepEqual(pair[0], pair[1]) { - t.Errorf("Map did not survive a round trip.\ninitial: %v\n final: %v", pair[0], pair[1]) - } - } -} - -func TestMapFieldWithNil(t *testing.T) { - m := &MessageWithMap{ - MsgMapping: map[int64]*FloatingPoint{ - 1: nil, - }, - } - b, err := Marshal(m) - if err == nil { - t.Fatalf("Marshal of bad map should have failed, got these bytes: %v", b) - } -} - -// Benchmarks - -func testMsg() *GoTest { - pb := initGoTest(true) - const N = 1000 // Internally the library starts much smaller. - pb.F_Int32Repeated = make([]int32, N) - pb.F_DoubleRepeated = make([]float64, N) - for i := 0; i < N; i++ { - pb.F_Int32Repeated[i] = int32(i) - pb.F_DoubleRepeated[i] = float64(i) - } - return pb -} - -func bytesMsg() *GoTest { - pb := initGoTest(true) - buf := make([]byte, 4000) - for i := range buf { - buf[i] = byte(i) - } - pb.F_BytesDefaulted = buf - return pb -} - -func benchmarkMarshal(b *testing.B, pb Message, marshal func(Message) ([]byte, error)) { - d, _ := marshal(pb) - b.SetBytes(int64(len(d))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - marshal(pb) - } -} - -func benchmarkBufferMarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - p.Reset() - err := p.Marshal(pb0) - return p.Bytes(), err - }) -} - -func benchmarkSize(b *testing.B, pb Message) { - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - Size(pb) - return nil, nil - }) -} - -func newOf(pb Message) Message { - in := reflect.ValueOf(pb) - if in.IsNil() { - return pb - } - return reflect.New(in.Type().Elem()).Interface().(Message) -} - -func benchmarkUnmarshal(b *testing.B, pb Message, unmarshal func([]byte, Message) error) { - d, _ := Marshal(pb) - b.SetBytes(int64(len(d))) - pbd := newOf(pb) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - unmarshal(d, pbd) - } -} - -func benchmarkBufferUnmarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkUnmarshal(b, pb, func(d []byte, pb0 Message) error { - p.SetBuf(d) - return p.Unmarshal(pb0) - }) -} - -// Benchmark{Marshal,BufferMarshal,Size,Unmarshal,BufferUnmarshal}{,Bytes} - -func BenchmarkMarshal(b *testing.B) { - benchmarkMarshal(b, testMsg(), Marshal) -} - -func BenchmarkBufferMarshal(b *testing.B) { - benchmarkBufferMarshal(b, testMsg()) -} - -func BenchmarkSize(b *testing.B) { - benchmarkSize(b, testMsg()) -} - -func BenchmarkUnmarshal(b *testing.B) { - benchmarkUnmarshal(b, testMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshal(b *testing.B) { - benchmarkBufferUnmarshal(b, testMsg()) -} - -func BenchmarkMarshalBytes(b *testing.B) { - benchmarkMarshal(b, bytesMsg(), Marshal) -} - -func BenchmarkBufferMarshalBytes(b *testing.B) { - benchmarkBufferMarshal(b, bytesMsg()) -} - -func BenchmarkSizeBytes(b *testing.B) { - benchmarkSize(b, bytesMsg()) -} - -func BenchmarkUnmarshalBytes(b *testing.B) { - benchmarkUnmarshal(b, bytesMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshalBytes(b *testing.B) { - benchmarkBufferUnmarshal(b, bytesMsg()) -} - -func BenchmarkUnmarshalUnrecognizedFields(b *testing.B) { - b.StopTimer() - pb := initGoTestField() - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - pbd := new(GoTestField) - p := NewBuffer(nil) - p.Marshal(pb) - p.Marshal(skip) - p2 := NewBuffer(nil) - - b.StartTimer() - for i := 0; i < b.N; i++ { - p2.SetBuf(p.Bytes()) - p2.Unmarshal(pbd) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/clone.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/clone.go deleted file mode 100644 index 915a68b8..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/clone.go +++ /dev/null @@ -1,212 +0,0 @@ -// 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: MessageSet and RawMessage. - -package proto - -import ( - "log" - "reflect" - "strings" -) - -// Clone returns a deep copy of a protocol buffer. -func Clone(pb Message) Message { - in := reflect.ValueOf(pb) - if in.IsNil() { - return pb - } - - out := reflect.New(in.Type().Elem()) - // out is empty so a merge is a deep copy. - mergeStruct(out.Elem(), in.Elem()) - return out.Interface().(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) { - in := reflect.ValueOf(src) - out := reflect.ValueOf(dst) - if out.IsNil() { - panic("proto: nil destination") - } - if in.Type() != out.Type() { - // Explicit test prior to mergeStruct so that mistyped nils will fail - panic("proto: type mismatch") - } - if in.IsNil() { - // Merging nil into non-nil is a quiet no-op - 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().(extendableProto); ok { - emOut := out.Addr().Interface().(extendableProto) - mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap()) - } - - 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.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/Godeps/_workspace/src/github.com/golang/protobuf/proto/clone_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/clone_test.go deleted file mode 100644 index a1c697bc..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/clone_test.go +++ /dev/null @@ -1,245 +0,0 @@ -// 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. - -package proto_test - -import ( - "testing" - - "github.com/golang/protobuf/proto" - - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -var cloneTestMessage = &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, -} - -func init() { - ext := &pb.Ext{ - Data: proto.String("extension"), - } - if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil { - panic("SetExtension: " + err.Error()) - } -} - -func TestClone(t *testing.T) { - m := proto.Clone(cloneTestMessage).(*pb.MyMessage) - if !proto.Equal(m, cloneTestMessage) { - t.Errorf("Clone(%v) = %v", cloneTestMessage, m) - } - - // Verify it was a deep copy. - *m.Inner.Port++ - if proto.Equal(m, cloneTestMessage) { - t.Error("Mutating clone changed the original") - } - // Byte fields and repeated fields should be copied. - if &m.Pet[0] == &cloneTestMessage.Pet[0] { - t.Error("Pet: repeated field not copied") - } - if &m.Others[0] == &cloneTestMessage.Others[0] { - t.Error("Others: repeated field not copied") - } - if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] { - t.Error("Others[0].Value: bytes field not copied") - } - if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] { - t.Error("RepBytes: repeated field not copied") - } - if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] { - t.Error("RepBytes[0]: bytes field not copied") - } -} - -func TestCloneNil(t *testing.T) { - var m *pb.MyMessage - if c := proto.Clone(m); !proto.Equal(m, c) { - t.Errorf("Clone(%v) = %v", m, c) - } -} - -var mergeTests = []struct { - src, dst, want proto.Message -}{ - { - src: &pb.MyMessage{ - Count: proto.Int32(42), - }, - dst: &pb.MyMessage{ - Name: proto.String("Dave"), - }, - want: &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - }, - }, - { - src: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - }, - Pet: []string{"horsey"}, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - }, - dst: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - { - // Explicitly test a src=nil field - Inner: nil, - }, - }, - }, - want: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty", "horsey"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - {}, - { - Value: []byte("some bytes"), - }, - }, - }, - }, - { - src: &pb.MyMessage{ - RepBytes: [][]byte{[]byte("wow")}, - }, - dst: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham")}, - }, - want: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, - }, - }, - // Check that a scalar bytes field replaces rather than appends. - { - src: &pb.OtherMessage{Value: []byte("foo")}, - dst: &pb.OtherMessage{Value: []byte("bar")}, - want: &pb.OtherMessage{Value: []byte("foo")}, - }, - { - src: &pb.MessageWithMap{ - NameMapping: map[int32]string{6: "Nigel"}, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - dst: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Bruce", // should be overwritten - 7: "Andrew", - }, - }, - want: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Nigel", - 7: "Andrew", - }, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - }, - // proto3 shouldn't merge zero values, - // in the same way that proto2 shouldn't merge nils. - { - src: &proto3pb.Message{ - Name: "Aaron", - Data: []byte(""), // zero value, but not nil - }, - dst: &proto3pb.Message{ - HeightInCm: 176, - Data: []byte("texas!"), - }, - want: &proto3pb.Message{ - Name: "Aaron", - HeightInCm: 176, - Data: []byte("texas!"), - }, - }, -} - -func TestMerge(t *testing.T) { - for _, m := range mergeTests { - got := proto.Clone(m.dst) - proto.Merge(got, m.src) - if !proto.Equal(got, m.want) { - t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/decode.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/decode.go deleted file mode 100644 index bf71dcad..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/decode.go +++ /dev/null @@ -1,827 +0,0 @@ -// 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" - "os" - "reflect" -) - -// errOverflow is returned when an integer is too large to be represented. -var errOverflow = errors.New("proto: integer overflow") - -// The fundamental decoders that interpret bytes on the wire. -// Those that take integer types all return uint64 and are -// therefore of type valueDecoder. - -// 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) { - // x, n already 0 - 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 -} - -// 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) { - // x, err already 0 - - 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 -} - -// 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 -} - -// These are not ValueDecoders: they produce an array of bytes or a string. -// bytes, embedded messages - -// 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 -} - -// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. -// If the protocol buffer has extensions, and the field matches, add it as an extension. -// Otherwise, if the XXX_unrecognized field exists, append the skipped data there. -func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error { - oi := o.index - - err := o.skip(t, tag, wire) - if err != nil { - return err - } - - if !unrecField.IsValid() { - return nil - } - - ptr := structPointer_Bytes(base, unrecField) - - // Add the skipped field to struct field - obuf := o.buf - - o.buf = *ptr - o.EncodeVarint(uint64(tag<<3 | wire)) - *ptr = append(o.buf, obuf[oi:o.index]...) - - o.buf = obuf - - return nil -} - -// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. -func (o *Buffer) skip(t reflect.Type, tag, wire int) error { - - var u uint64 - var err error - - switch wire { - case WireVarint: - _, err = o.DecodeVarint() - case WireFixed64: - _, err = o.DecodeFixed64() - case WireBytes: - _, err = o.DecodeRawBytes(false) - case WireFixed32: - _, err = o.DecodeFixed32() - case WireStartGroup: - for { - u, err = o.DecodeVarint() - if err != nil { - break - } - fwire := int(u & 0x7) - if fwire == WireEndGroup { - break - } - ftag := int(u >> 3) - err = o.skip(t, ftag, fwire) - if err != nil { - break - } - } - default: - err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t) - } - return err -} - -// Unmarshaler is the interface representing objects that can -// unmarshal themselves. The method should reset the receiver before -// decoding starts. The argument points to data that may be -// overwritten, so implementations should not keep references to the -// buffer. -type Unmarshaler interface { - 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() - return UnmarshalMerge(buf, 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 the object can unmarshal itself, let it. - if u, ok := pb.(Unmarshaler); ok { - return u.Unmarshal(buf) - } - return NewBuffer(buf).Unmarshal(pb) -} - -// 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. -func (p *Buffer) Unmarshal(pb Message) error { - // If the object can unmarshal itself, let it. - if u, ok := pb.(Unmarshaler); ok { - err := u.Unmarshal(p.buf[p.index:]) - p.index = len(p.buf) - return err - } - - typ, base, err := getbase(pb) - if err != nil { - return err - } - - err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base) - - if collectStats { - stats.Decode++ - } - - return err -} - -// unmarshalType does the work of unmarshaling a structure. -func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error { - var state errorState - required, reqFields := prop.reqCount, uint64(0) - - var err error - for err == nil && o.index < len(o.buf) { - oi := o.index - var u uint64 - u, err = o.DecodeVarint() - if err != nil { - break - } - wire := int(u & 0x7) - if wire == WireEndGroup { - if is_group { - return nil // input is satisfied - } - return fmt.Errorf("proto: %s: wiretype end group for non-group", st) - } - tag := int(u >> 3) - if tag <= 0 { - return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire) - } - fieldnum, ok := prop.decoderTags.get(tag) - if !ok { - // Maybe it's an extension? - if prop.extendable { - if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) { - if err = o.skip(st, tag, wire); err == nil { - ext := e.ExtensionMap()[int32(tag)] // may be missing - ext.enc = append(ext.enc, o.buf[oi:o.index]...) - e.ExtensionMap()[int32(tag)] = ext - } - continue - } - } - err = o.skipAndSave(st, tag, wire, base, prop.unrecField) - continue - } - p := prop.Prop[fieldnum] - - if p.dec == nil { - fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name) - continue - } - dec := p.dec - if wire != WireStartGroup && wire != p.WireType { - if wire == WireBytes && p.packedDec != nil { - // a packable field - dec = p.packedDec - } else { - err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType) - continue - } - } - decErr := dec(o, p, base) - if decErr != nil && !state.shouldContinue(decErr, p) { - err = decErr - } - if err == nil && p.Required { - // Successfully decoded a required field. - if tag <= 64 { - // use bitmap for fields 1-64 to catch field reuse. - var mask uint64 = 1 << uint64(tag-1) - if reqFields&mask == 0 { - // new required field - reqFields |= mask - required-- - } - } else { - // This is imprecise. It can be fooled by a required field - // with a tag > 64 that is encoded twice; that's very rare. - // A fully correct implementation would require allocating - // a data structure, which we would like to avoid. - required-- - } - } - } - if err == nil { - if is_group { - return io.ErrUnexpectedEOF - } - if state.err != nil { - return state.err - } - if required > 0 { - // Not enough information to determine the exact field. If we use extra - // CPU, we could determine the field only if the missing required field - // has a tag <= 64 and we check reqFields. - return &RequiredNotSetError{"{Unknown}"} - } - } - return err -} - -// Individual type decoders -// For each, -// u is the decoded value, -// v is a pointer to the field (pointer) in the struct - -// Sizes of the pools to allocate inside the Buffer. -// The goal is modest amortization and allocation -// on at least 16-byte boundaries. -const ( - boolPoolSize = 16 - uint32PoolSize = 8 - uint64PoolSize = 4 -) - -// Decode a bool. -func (o *Buffer) dec_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - if len(o.bools) == 0 { - o.bools = make([]bool, boolPoolSize) - } - o.bools[0] = u != 0 - *structPointer_Bool(base, p.field) = &o.bools[0] - o.bools = o.bools[1:] - return nil -} - -func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - *structPointer_BoolVal(base, p.field) = u != 0 - return nil -} - -// Decode an int32. -func (o *Buffer) dec_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word32_Set(structPointer_Word32(base, p.field), o, uint32(u)) - return nil -} - -func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u)) - return nil -} - -// Decode an int64. -func (o *Buffer) dec_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word64_Set(structPointer_Word64(base, p.field), o, u) - return nil -} - -func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - word64Val_Set(structPointer_Word64Val(base, p.field), o, u) - return nil -} - -// Decode a string. -func (o *Buffer) dec_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - *structPointer_String(base, p.field) = &s - return nil -} - -func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - *structPointer_StringVal(base, p.field) = s - return nil -} - -// Decode a slice of bytes ([]byte). -func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - *structPointer_Bytes(base, p.field) = b - return nil -} - -// Decode a slice of bools ([]bool). -func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - v := structPointer_BoolSlice(base, p.field) - *v = append(*v, u != 0) - return nil -} - -// Decode a slice of bools ([]bool) in packed format. -func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error { - v := structPointer_BoolSlice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded bools - - y := *v - for i := 0; i < nb; i++ { - u, err := p.valDec(o) - if err != nil { - return err - } - y = append(y, u != 0) - } - - *v = y - return nil -} - -// Decode a slice of int32s ([]int32). -func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - structPointer_Word32Slice(base, p.field).Append(uint32(u)) - return nil -} - -// Decode a slice of int32s ([]int32) in packed format. -func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error { - v := structPointer_Word32Slice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded int32s - - fin := o.index + nb - if fin < o.index { - return errOverflow - } - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - v.Append(uint32(u)) - } - return nil -} - -// Decode a slice of int64s ([]int64). -func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error { - u, err := p.valDec(o) - if err != nil { - return err - } - - structPointer_Word64Slice(base, p.field).Append(u) - return nil -} - -// Decode a slice of int64s ([]int64) in packed format. -func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error { - v := structPointer_Word64Slice(base, p.field) - - nn, err := o.DecodeVarint() - if err != nil { - return err - } - nb := int(nn) // number of bytes of encoded int64s - - fin := o.index + nb - if fin < o.index { - return errOverflow - } - for o.index < fin { - u, err := p.valDec(o) - if err != nil { - return err - } - v.Append(u) - } - return nil -} - -// Decode a slice of strings ([]string). -func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error { - s, err := o.DecodeStringBytes() - if err != nil { - return err - } - v := structPointer_StringSlice(base, p.field) - *v = append(*v, s) - return nil -} - -// Decode a slice of slice of bytes ([][]byte). -func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error { - b, err := o.DecodeRawBytes(true) - if err != nil { - return err - } - v := structPointer_BytesSlice(base, p.field) - *v = append(*v, b) - return nil -} - -// Decode a map field. -func (o *Buffer) dec_new_map(p *Properties, base structPointer) error { - raw, err := o.DecodeRawBytes(false) - if err != nil { - return err - } - oi := o.index // index at the end of this map entry - o.index -= len(raw) // move buffer back to start of map entry - - mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V - if mptr.Elem().IsNil() { - mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem())) - } - v := mptr.Elem() // map[K]V - - // Prepare addressable doubly-indirect placeholders for the key and value types. - // See enc_new_map for why. - keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K - keybase := toStructPointer(keyptr.Addr()) // **K - - var valbase structPointer - var valptr reflect.Value - switch p.mtype.Elem().Kind() { - case reflect.Slice: - // []byte - var dummy []byte - valptr = reflect.ValueOf(&dummy) // *[]byte - valbase = toStructPointer(valptr) // *[]byte - case reflect.Ptr: - // message; valptr is **Msg; need to allocate the intermediate pointer - valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V - valptr.Set(reflect.New(valptr.Type().Elem())) - valbase = toStructPointer(valptr) - default: - // everything else - valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V - valbase = toStructPointer(valptr.Addr()) // **V - } - - // Decode. - // This parses a restricted wire format, namely the encoding of a message - // with two fields. See enc_new_map for the format. - for o.index < oi { - // tagcode for key and value properties are always a single byte - // because they have tags 1 and 2. - tagcode := o.buf[o.index] - o.index++ - switch tagcode { - case p.mkeyprop.tagcode[0]: - if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil { - return err - } - case p.mvalprop.tagcode[0]: - if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil { - return err - } - default: - // TODO: Should we silently skip this instead? - return fmt.Errorf("proto: bad map data tag %d", raw[0]) - } - } - keyelem, valelem := keyptr.Elem(), valptr.Elem() - if !keyelem.IsValid() || !valelem.IsValid() { - // We did not decode the key or the value in the map entry. - // Either way, it's an invalid map entry. - return fmt.Errorf("proto: bad map data: missing key/val") - } - - v.SetMapIndex(keyelem, valelem) - return nil -} - -// Decode a group. -func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error { - bas := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(bas) { - // allocate new nested message - bas = toStructPointer(reflect.New(p.stype)) - structPointer_SetStructPointer(base, p.field, bas) - } - return o.unmarshalType(p.stype, p.sprop, true, bas) -} - -// Decode an embedded message. -func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) { - raw, e := o.DecodeRawBytes(false) - if e != nil { - return e - } - - bas := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(bas) { - // allocate new nested message - bas = toStructPointer(reflect.New(p.stype)) - structPointer_SetStructPointer(base, p.field, bas) - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - iv := structPointer_Interface(bas, p.stype) - return iv.(Unmarshaler).Unmarshal(raw) - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - err = o.unmarshalType(p.stype, p.sprop, false, bas) - o.buf = obuf - o.index = oi - - return err -} - -// Decode a slice of embedded messages. -func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error { - return o.dec_slice_struct(p, false, base) -} - -// Decode a slice of embedded groups. -func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error { - return o.dec_slice_struct(p, true, base) -} - -// Decode a slice of structs ([]*struct). -func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error { - v := reflect.New(p.stype) - bas := toStructPointer(v) - structPointer_StructPointerSlice(base, p.field).Append(bas) - - if is_group { - err := o.unmarshalType(p.stype, p.sprop, is_group, bas) - return err - } - - raw, err := o.DecodeRawBytes(false) - if err != nil { - return err - } - - // If the object can unmarshal itself, let it. - if p.isUnmarshaler { - iv := v.Interface() - return iv.(Unmarshaler).Unmarshal(raw) - } - - obuf := o.buf - oi := o.index - o.buf = raw - o.index = 0 - - err = o.unmarshalType(p.stype, p.sprop, is_group, bas) - - o.buf = obuf - o.index = oi - - return err -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go deleted file mode 100644 index 91f3f078..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go +++ /dev/null @@ -1,1293 +0,0 @@ -// 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" - "fmt" - "reflect" - "sort" -) - -// RequiredNotSetError is the error returned if Marshal is called with -// a protocol buffer struct whose required fields have not -// all been initialized. It is also the error returned if Unmarshal is -// called with an encoded protocol buffer that does not include all the -// required fields. -// -// When printed, RequiredNotSetError reports the first unset required field in a -// message. If the field cannot be precisely determined, it is reported as -// "{Unknown}". -type RequiredNotSetError struct { - field string -} - -func (e *RequiredNotSetError) Error() string { - return fmt.Sprintf("proto: required field %q not set", e.field) -} - -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") - - // ErrNil is the error returned if Marshal is called with nil. - ErrNil = errors.New("proto: Marshal called with nil") -) - -// 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 -} - -func sizeVarint(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} - -// 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 -} - -func sizeFixed64(x uint64) int { - return 8 -} - -// 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 -} - -func sizeFixed32(x uint64) int { - return 4 -} - -// 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)))) -} - -func sizeZigzag64(x uint64) int { - return sizeVarint(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)))) -} - -func sizeZigzag32(x uint64) int { - return sizeVarint(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 -} - -func sizeRawBytes(b []byte) int { - return sizeVarint(uint64(len(b))) + - len(b) -} - -// 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 -} - -func sizeStringBytes(s string) int { - return sizeVarint(uint64(len(s))) + - len(s) -} - -// Marshaler is the interface representing objects that can marshal themselves. -type Marshaler interface { - Marshal() ([]byte, error) -} - -// Marshal takes the protocol buffer -// and encodes it into the wire format, returning the data. -func Marshal(pb Message) ([]byte, error) { - // Can the object marshal itself? - if m, ok := pb.(Marshaler); ok { - return m.Marshal() - } - p := NewBuffer(nil) - err := p.Marshal(pb) - var state errorState - if err != nil && !state.shouldContinue(err, nil) { - return nil, err - } - if p.buf == nil && err == nil { - // Return a non-nil slice on success. - return []byte{}, nil - } - return p.buf, err -} - -// Marshal takes the protocol buffer -// and encodes it into the wire format, writing the result to the -// Buffer. -func (p *Buffer) Marshal(pb Message) error { - // Can the object marshal itself? - if m, ok := pb.(Marshaler); ok { - data, err := m.Marshal() - if err != nil { - return err - } - p.buf = append(p.buf, data...) - return nil - } - - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return ErrNil - } - if err == nil { - err = p.enc_struct(GetProperties(t.Elem()), base) - } - - if collectStats { - stats.Encode++ - } - - return err -} - -// Size returns the encoded size of a protocol buffer. -func Size(pb Message) (n int) { - // Can the object marshal itself? If so, Size is slow. - // TODO: add Size to Marshaler, or add a Sizer interface. - if m, ok := pb.(Marshaler); ok { - b, _ := m.Marshal() - return len(b) - } - - t, base, err := getbase(pb) - if structPointer_IsNil(base) { - return 0 - } - if err == nil { - n = size_struct(GetProperties(t.Elem()), base) - } - - if collectStats { - stats.Size++ - } - - return -} - -// Individual type encoders. - -// Encode a bool. -func (o *Buffer) enc_bool(p *Properties, base structPointer) error { - v := *structPointer_Bool(base, p.field) - if v == nil { - return ErrNil - } - x := 0 - if *v { - x = 1 - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error { - v := *structPointer_BoolVal(base, p.field) - if !v { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, 1) - return nil -} - -func size_bool(p *Properties, base structPointer) int { - v := *structPointer_Bool(base, p.field) - if v == nil { - return 0 - } - return len(p.tagcode) + 1 // each bool takes exactly one byte -} - -func size_proto3_bool(p *Properties, base structPointer) int { - v := *structPointer_BoolVal(base, p.field) - if !v { - return 0 - } - return len(p.tagcode) + 1 // each bool takes exactly one byte -} - -// Encode an int32. -func (o *Buffer) enc_int32(p *Properties, base structPointer) error { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return ErrNil - } - x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_int32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return 0 - } - x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -func size_proto3_int32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range - if x == 0 { - return 0 - } - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -// Encode a uint32. -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_uint32(p *Properties, base structPointer) error { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return ErrNil - } - x := word32_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, uint64(x)) - return nil -} - -func size_uint32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32(base, p.field) - if word32_IsNil(v) { - return 0 - } - x := word32_Get(v) - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -func size_proto3_uint32(p *Properties, base structPointer) (n int) { - v := structPointer_Word32Val(base, p.field) - x := word32Val_Get(v) - if x == 0 { - return 0 - } - n += len(p.tagcode) - n += p.valSize(uint64(x)) - return -} - -// Encode an int64. -func (o *Buffer) enc_int64(p *Properties, base structPointer) error { - v := structPointer_Word64(base, p.field) - if word64_IsNil(v) { - return ErrNil - } - x := word64_Get(v) - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, x) - return nil -} - -func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - if x == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, x) - return nil -} - -func size_int64(p *Properties, base structPointer) (n int) { - v := structPointer_Word64(base, p.field) - if word64_IsNil(v) { - return 0 - } - x := word64_Get(v) - n += len(p.tagcode) - n += p.valSize(x) - return -} - -func size_proto3_int64(p *Properties, base structPointer) (n int) { - v := structPointer_Word64Val(base, p.field) - x := word64Val_Get(v) - if x == 0 { - return 0 - } - n += len(p.tagcode) - n += p.valSize(x) - return -} - -// Encode a string. -func (o *Buffer) enc_string(p *Properties, base structPointer) error { - v := *structPointer_String(base, p.field) - if v == nil { - return ErrNil - } - x := *v - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(x) - return nil -} - -func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error { - v := *structPointer_StringVal(base, p.field) - if v == "" { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(v) - return nil -} - -func size_string(p *Properties, base structPointer) (n int) { - v := *structPointer_String(base, p.field) - if v == nil { - return 0 - } - x := *v - n += len(p.tagcode) - n += sizeStringBytes(x) - return -} - -func size_proto3_string(p *Properties, base structPointer) (n int) { - v := *structPointer_StringVal(base, p.field) - if v == "" { - return 0 - } - n += len(p.tagcode) - n += sizeStringBytes(v) - return -} - -// 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 -} - -// Encode a message struct. -func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error { - var state errorState - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return ErrNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - return state.err - } - - o.buf = append(o.buf, p.tagcode...) - return o.enc_len_struct(p.sprop, structp, &state) -} - -func size_struct_message(p *Properties, base structPointer) int { - structp := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(structp) { - return 0 - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n0 := len(p.tagcode) - n1 := sizeRawBytes(data) - return n0 + n1 - } - - n0 := len(p.tagcode) - n1 := size_struct(p.sprop, structp) - n2 := sizeVarint(uint64(n1)) // size of encoded length - return n0 + n1 + n2 -} - -// Encode a group struct. -func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error { - var state errorState - b := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(b) { - return ErrNil - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) - err := o.enc_struct(p.sprop, b) - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) - return state.err -} - -func size_struct_group(p *Properties, base structPointer) (n int) { - b := structPointer_GetStructPointer(base, p.field) - if structPointer_IsNil(b) { - return 0 - } - - n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup)) - n += size_struct(p.sprop, b) - n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup)) - return -} - -// Encode a slice of bools ([]bool). -func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return ErrNil - } - for _, x := range s { - o.buf = append(o.buf, p.tagcode...) - v := uint64(0) - if x { - v = 1 - } - p.valEnc(o, v) - } - return nil -} - -func size_slice_bool(p *Properties, base structPointer) int { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return 0 - } - return l * (len(p.tagcode) + 1) // each bool takes exactly one byte -} - -// Encode a slice of bools ([]bool) in packed format. -func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(l)) // each bool takes exactly one byte - for _, x := range s { - v := uint64(0) - if x { - v = 1 - } - p.valEnc(o, v) - } - return nil -} - -func size_slice_packed_bool(p *Properties, base structPointer) (n int) { - s := *structPointer_BoolSlice(base, p.field) - l := len(s) - if l == 0 { - return 0 - } - n += len(p.tagcode) - n += sizeVarint(uint64(l)) - n += l // each bool takes exactly one byte - return -} - -// Encode a slice of bytes ([]byte). -func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error { - s := *structPointer_Bytes(base, p.field) - if s == nil { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(s) - return nil -} - -func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error { - s := *structPointer_Bytes(base, p.field) - if len(s) == 0 { - return ErrNil - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(s) - return nil -} - -func size_slice_byte(p *Properties, base structPointer) (n int) { - s := *structPointer_Bytes(base, p.field) - if s == nil { - return 0 - } - n += len(p.tagcode) - n += sizeRawBytes(s) - return -} - -func size_proto3_slice_byte(p *Properties, base structPointer) (n int) { - s := *structPointer_Bytes(base, p.field) - if len(s) == 0 { - return 0 - } - n += len(p.tagcode) - n += sizeRawBytes(s) - return -} - -// Encode a slice of int32s ([]int32). -func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - p.valEnc(o, uint64(x)) - } - return nil -} - -func size_slice_int32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - n += p.valSize(uint64(x)) - } - return -} - -// Encode a slice of int32s ([]int32) in packed format. -func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - p.valEnc(buf, uint64(x)) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_int32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - x := int32(s.Index(i)) // permit sign extension to use full 64-bit range - bufSize += p.valSize(uint64(x)) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of uint32s ([]uint32). -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - x := s.Index(i) - p.valEnc(o, uint64(x)) - } - return nil -} - -func size_slice_uint32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - x := s.Index(i) - n += p.valSize(uint64(x)) - } - return -} - -// Encode a slice of uint32s ([]uint32) in packed format. -// Exactly the same as int32, except for no sign extension. -func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - p.valEnc(buf, uint64(s.Index(i))) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_uint32(p *Properties, base structPointer) (n int) { - s := structPointer_Word32Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - bufSize += p.valSize(uint64(s.Index(i))) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of int64s ([]int64). -func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - p.valEnc(o, s.Index(i)) - } - return nil -} - -func size_slice_int64(p *Properties, base structPointer) (n int) { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - for i := 0; i < l; i++ { - n += len(p.tagcode) - n += p.valSize(s.Index(i)) - } - return -} - -// Encode a slice of int64s ([]int64) in packed format. -func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return ErrNil - } - // TODO: Reuse a Buffer. - buf := NewBuffer(nil) - for i := 0; i < l; i++ { - p.valEnc(buf, s.Index(i)) - } - - o.buf = append(o.buf, p.tagcode...) - o.EncodeVarint(uint64(len(buf.buf))) - o.buf = append(o.buf, buf.buf...) - return nil -} - -func size_slice_packed_int64(p *Properties, base structPointer) (n int) { - s := structPointer_Word64Slice(base, p.field) - l := s.Len() - if l == 0 { - return 0 - } - var bufSize int - for i := 0; i < l; i++ { - bufSize += p.valSize(s.Index(i)) - } - - n += len(p.tagcode) - n += sizeVarint(uint64(bufSize)) - n += bufSize - return -} - -// Encode a slice of slice of bytes ([][]byte). -func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error { - ss := *structPointer_BytesSlice(base, p.field) - l := len(ss) - if l == 0 { - return ErrNil - } - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(ss[i]) - } - return nil -} - -func size_slice_slice_byte(p *Properties, base structPointer) (n int) { - ss := *structPointer_BytesSlice(base, p.field) - l := len(ss) - if l == 0 { - return 0 - } - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - n += sizeRawBytes(ss[i]) - } - return -} - -// Encode a slice of strings ([]string). -func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error { - ss := *structPointer_StringSlice(base, p.field) - l := len(ss) - for i := 0; i < l; i++ { - o.buf = append(o.buf, p.tagcode...) - o.EncodeStringBytes(ss[i]) - } - return nil -} - -func size_slice_string(p *Properties, base structPointer) (n int) { - ss := *structPointer_StringSlice(base, p.field) - l := len(ss) - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - n += sizeStringBytes(ss[i]) - } - return -} - -// Encode a slice of message structs ([]*struct). -func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error { - var state errorState - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - for i := 0; i < l; i++ { - structp := s.Index(i) - if structPointer_IsNil(structp) { - return errRepeatedHasNil - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, err := m.Marshal() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - o.buf = append(o.buf, p.tagcode...) - o.EncodeRawBytes(data) - continue - } - - o.buf = append(o.buf, p.tagcode...) - err := o.enc_len_struct(p.sprop, structp, &state) - if err != nil && !state.shouldContinue(err, nil) { - if err == ErrNil { - return errRepeatedHasNil - } - return err - } - } - return state.err -} - -func size_slice_struct_message(p *Properties, base structPointer) (n int) { - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - n += l * len(p.tagcode) - for i := 0; i < l; i++ { - structp := s.Index(i) - if structPointer_IsNil(structp) { - return // return the size up to this point - } - - // Can the object marshal itself? - if p.isMarshaler { - m := structPointer_Interface(structp, p.stype).(Marshaler) - data, _ := m.Marshal() - n += len(p.tagcode) - n += sizeRawBytes(data) - continue - } - - n0 := size_struct(p.sprop, structp) - n1 := sizeVarint(uint64(n0)) // size of encoded length - n += n0 + n1 - } - return -} - -// Encode a slice of group structs ([]*struct). -func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error { - var state errorState - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - for i := 0; i < l; i++ { - b := s.Index(i) - if structPointer_IsNil(b) { - return errRepeatedHasNil - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) - - err := o.enc_struct(p.sprop, b) - - if err != nil && !state.shouldContinue(err, nil) { - if err == ErrNil { - return errRepeatedHasNil - } - return err - } - - o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) - } - return state.err -} - -func size_slice_struct_group(p *Properties, base structPointer) (n int) { - s := structPointer_StructPointerSlice(base, p.field) - l := s.Len() - - n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup)) - n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup)) - for i := 0; i < l; i++ { - b := s.Index(i) - if structPointer_IsNil(b) { - return // return size up to this point - } - - n += size_struct(p.sprop, b) - } - return -} - -// Encode an extension map. -func (o *Buffer) enc_map(p *Properties, base structPointer) error { - v := *structPointer_ExtMap(base, p.field) - if err := encodeExtensionMap(v); err != nil { - return err - } - // Fast-path for common cases: zero or one extensions. - if len(v) <= 1 { - for _, e := range v { - o.buf = append(o.buf, e.enc...) - } - return nil - } - - // Sort keys to provide a deterministic encoding. - keys := make([]int, 0, len(v)) - for k := range v { - keys = append(keys, int(k)) - } - sort.Ints(keys) - - for _, k := range keys { - o.buf = append(o.buf, v[int32(k)].enc...) - } - return nil -} - -func size_map(p *Properties, base structPointer) int { - v := *structPointer_ExtMap(base, p.field) - return sizeExtensionMap(v) -} - -// Encode a map field. -func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { - var state errorState // XXX: or do we need to plumb this through? - - /* - A map defined as - map map_field = N; - is encoded in the same way as - message MapFieldEntry { - key_type key = 1; - value_type value = 2; - } - repeated MapFieldEntry map_field = N; - */ - - v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V - if v.Len() == 0 { - return nil - } - - keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) - - enc := func() error { - if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { - return err - } - if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil { - return err - } - return nil - } - - keys := v.MapKeys() - sort.Sort(mapKeys(keys)) - for _, key := range keys { - val := v.MapIndex(key) - - // The only illegal map entry values are nil message pointers. - if val.Kind() == reflect.Ptr && val.IsNil() { - return errors.New("proto: map has nil element") - } - - keycopy.Set(key) - valcopy.Set(val) - - o.buf = append(o.buf, p.tagcode...) - if err := o.enc_len_thing(enc, &state); err != nil { - return err - } - } - return nil -} - -func size_new_map(p *Properties, base structPointer) int { - v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V - - keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) - - n := 0 - for _, key := range v.MapKeys() { - val := v.MapIndex(key) - keycopy.Set(key) - valcopy.Set(val) - - // Tag codes for key and val are the responsibility of the sub-sizer. - keysize := p.mkeyprop.size(p.mkeyprop, keybase) - valsize := p.mvalprop.size(p.mvalprop, valbase) - entry := keysize + valsize - // Add on tag code and length of map entry itself. - n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry - } - return n -} - -// mapEncodeScratch returns a new reflect.Value matching the map's value type, -// and a structPointer suitable for passing to an encoder or sizer. -func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) { - // Prepare addressable doubly-indirect placeholders for the key and value types. - // This is needed because the element-type encoders expect **T, but the map iteration produces T. - - keycopy = reflect.New(mapType.Key()).Elem() // addressable K - keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K - keyptr.Set(keycopy.Addr()) // - keybase = toStructPointer(keyptr.Addr()) // **K - - // Value types are more varied and require special handling. - switch mapType.Elem().Kind() { - case reflect.Slice: - // []byte - var dummy []byte - valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte - valbase = toStructPointer(valcopy.Addr()) - case reflect.Ptr: - // message; the generated field type is map[K]*Msg (so V is *Msg), - // so we only need one level of indirection. - valcopy = reflect.New(mapType.Elem()).Elem() // addressable V - valbase = toStructPointer(valcopy.Addr()) - default: - // everything else - valcopy = reflect.New(mapType.Elem()).Elem() // addressable V - valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V - valptr.Set(valcopy.Addr()) // - valbase = toStructPointer(valptr.Addr()) // **V - } - return -} - -// Encode a struct. -func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { - var state errorState - // Encode fields in tag order so that decoders may use optimizations - // that depend on the ordering. - // https://developers.google.com/protocol-buffers/docs/encoding#order - for _, i := range prop.order { - p := prop.Prop[i] - if p.enc != nil { - err := p.enc(o, p, base) - if err != nil { - if err == ErrNil { - if p.Required && state.err == nil { - state.err = &RequiredNotSetError{p.Name} - } - } else if err == errRepeatedHasNil { - // Give more context to nil values in repeated fields. - return errors.New("repeated field " + p.OrigName + " has nil element") - } else if !state.shouldContinue(err, p) { - return err - } - } - } - } - - // Add unrecognized fields at the end. - if prop.unrecField.IsValid() { - v := *structPointer_Bytes(base, prop.unrecField) - if len(v) > 0 { - o.buf = append(o.buf, v...) - } - } - - return state.err -} - -func size_struct(prop *StructProperties, base structPointer) (n int) { - for _, i := range prop.order { - p := prop.Prop[i] - if p.size != nil { - n += p.size(p, base) - } - } - - // Add unrecognized fields at the end. - if prop.unrecField.IsValid() { - v := *structPointer_Bytes(base, prop.unrecField) - n += len(v) - } - - return -} - -var zeroes [20]byte // longer than any conceivable sizeVarint - -// Encode a struct, preceded by its encoded length (as a varint). -func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error { - return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state) -} - -// Encode something, preceded by its encoded length (as a varint). -func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error { - iLen := len(o.buf) - o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length - iMsg := len(o.buf) - err := enc() - if err != nil && !state.shouldContinue(err, nil) { - return err - } - lMsg := len(o.buf) - iMsg - lLen := sizeVarint(uint64(lMsg)) - switch x := lLen - (iMsg - iLen); { - case x > 0: // actual length is x bytes larger than the space we reserved - // Move msg x bytes right. - o.buf = append(o.buf, zeroes[:x]...) - copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) - case x < 0: // actual length is x bytes smaller than the space we reserved - // Move msg x bytes left. - copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) - o.buf = o.buf[:len(o.buf)+x] // x is negative - } - // Encode the length in the reserved space. - o.buf = o.buf[:iLen] - o.EncodeVarint(uint64(lMsg)) - o.buf = o.buf[:len(o.buf)+lMsg] - return state.err -} - -// errorState maintains the first error that occurs and updates that error -// with additional context. -type errorState struct { - err error -} - -// shouldContinue reports whether encoding should continue upon encountering the -// given error. If the error is RequiredNotSetError, shouldContinue returns true -// and, if this is the first appearance of that error, remembers it for future -// reporting. -// -// If prop is not nil, it may update any error with additional context about the -// field with the error. -func (s *errorState) shouldContinue(err error, prop *Properties) bool { - // Ignore unset required fields. - reqNotSet, ok := err.(*RequiredNotSetError) - if !ok { - return false - } - if s.err == nil { - if prop != nil { - err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field} - } - s.err = err - } - return true -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/equal.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/equal.go deleted file mode 100644 index d8673a3e..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/equal.go +++ /dev/null @@ -1,256 +0,0 @@ -// 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. -// TODO: MessageSet. - -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. - - Two repeated fields are equal iff their lengths are the same, - and their corresponding elements are equal (a "bytes" field, - although represented by []byte, is not a repeated field) - - 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. - - 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 { - 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 - } - b1, ok := f1.Interface().(raw) - if ok { - b2 := f2.Interface().(raw) - // RawMessage - if !bytes.Equal(b1.Bytes(), b2.Bytes()) { - return false - } - continue - } - f1, f2 = f1.Elem(), f2.Elem() - } - if !equalAny(f1, f2) { - return false - } - } - - if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { - em2 := v2.FieldByName("XXX_extensions") - if !equalExtensions(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() - if !bytes.Equal(u1, u2) { - return false - } - - return true -} - -// v1 and v2 are known to have the same type. -func equalAny(v1, v2 reflect.Value) 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.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) { - return false - } - } - return true - case reflect.Ptr: - return equalAny(v1.Elem(), v2.Elem()) - case reflect.Slice: - if v1.Type().Elem().Kind() == reflect.Uint8 { - // short circuit: []byte - 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)) { - 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. -// em1 and em2 are extension maps. -func equalExtensions(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 are unencoded. - if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2)) { - 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 { - log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) - continue - } - 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)) { - return false - } - } - - return true -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/equal_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/equal_test.go deleted file mode 100644 index b322f65a..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/equal_test.go +++ /dev/null @@ -1,191 +0,0 @@ -// 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. - -package proto_test - -import ( - "testing" - - . "github.com/golang/protobuf/proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -// Four identical base messages. -// The init function adds extensions to some of them. -var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)} -var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)} -var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)} -var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)} - -// Two messages with non-message extensions. -var messageWithInt32Extension1 = &pb.MyMessage{Count: Int32(8)} -var messageWithInt32Extension2 = &pb.MyMessage{Count: Int32(8)} - -func init() { - ext1 := &pb.Ext{Data: String("Kirk")} - ext2 := &pb.Ext{Data: String("Picard")} - - // messageWithExtension1a has ext1, but never marshals it. - if err := SetExtension(messageWithExtension1a, pb.E_Ext_More, ext1); err != nil { - panic("SetExtension on 1a failed: " + err.Error()) - } - - // messageWithExtension1b is the unmarshaled form of messageWithExtension1a. - if err := SetExtension(messageWithExtension1b, pb.E_Ext_More, ext1); err != nil { - panic("SetExtension on 1b failed: " + err.Error()) - } - buf, err := Marshal(messageWithExtension1b) - if err != nil { - panic("Marshal of 1b failed: " + err.Error()) - } - messageWithExtension1b.Reset() - if err := Unmarshal(buf, messageWithExtension1b); err != nil { - panic("Unmarshal of 1b failed: " + err.Error()) - } - - // messageWithExtension2 has ext2. - if err := SetExtension(messageWithExtension2, pb.E_Ext_More, ext2); err != nil { - panic("SetExtension on 2 failed: " + err.Error()) - } - - if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(23)); err != nil { - panic("SetExtension on Int32-1 failed: " + err.Error()) - } - if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(24)); err != nil { - panic("SetExtension on Int32-2 failed: " + err.Error()) - } -} - -var EqualTests = []struct { - desc string - a, b Message - exp bool -}{ - {"different types", &pb.GoEnum{}, &pb.GoTestField{}, false}, - {"equal empty", &pb.GoEnum{}, &pb.GoEnum{}, true}, - {"nil vs nil", nil, nil, true}, - {"typed nil vs typed nil", (*pb.GoEnum)(nil), (*pb.GoEnum)(nil), true}, - {"typed nil vs empty", (*pb.GoEnum)(nil), &pb.GoEnum{}, false}, - {"different typed nil", (*pb.GoEnum)(nil), (*pb.GoTestField)(nil), false}, - - {"one set field, one unset field", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{}, false}, - {"one set field zero, one unset field", &pb.GoTest{Param: Int32(0)}, &pb.GoTest{}, false}, - {"different set fields", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("bar")}, false}, - {"equal set", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("foo")}, true}, - - {"repeated, one set", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{}, false}, - {"repeated, different length", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{F_Int32Repeated: []int32{2}}, false}, - {"repeated, different value", &pb.GoTest{F_Int32Repeated: []int32{2}}, &pb.GoTest{F_Int32Repeated: []int32{3}}, false}, - {"repeated, equal", &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, true}, - {"repeated, nil equal nil", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: nil}, true}, - {"repeated, nil equal empty", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: []int32{}}, true}, - {"repeated, empty equal nil", &pb.GoTest{F_Int32Repeated: []int32{}}, &pb.GoTest{F_Int32Repeated: nil}, true}, - - { - "nested, different", - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("foo")}}, - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("bar")}}, - false, - }, - { - "nested, equal", - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, - true, - }, - - {"bytes", &pb.OtherMessage{Value: []byte("foo")}, &pb.OtherMessage{Value: []byte("foo")}, true}, - {"bytes, empty", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: []byte{}}, true}, - {"bytes, empty vs nil", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: nil}, false}, - { - "repeated bytes", - &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, - &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, - true, - }, - - {"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false}, - {"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true}, - {"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false}, - - {"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true}, - {"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false}, - - { - "message with group", - &pb.MyMessage{ - Count: Int32(1), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: Int32(5), - }, - }, - &pb.MyMessage{ - Count: Int32(1), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: Int32(5), - }, - }, - true, - }, - - { - "map same", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - true, - }, - { - "map different entry", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob"}}, - false, - }, - { - "map different key only", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{2: "Ken"}}, - false, - }, - { - "map different value only", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}}, - false, - }, -} - -func TestEqual(t *testing.T) { - for _, tc := range EqualTests { - if res := Equal(tc.a, tc.b); res != tc.exp { - t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions.go deleted file mode 100644 index e591ccef..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions.go +++ /dev/null @@ -1,400 +0,0 @@ -// 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" - "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 that may be extended. -type extendableProto interface { - Message - ExtensionRangeArray() []ExtensionRange - ExtensionMap() map[int32]Extension -} - -var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() - -// 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 -} - -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 extendableProto, id int32, b []byte) { - base.ExtensionMap()[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 { - // Check the extended type. - if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b { - return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String()) - } - // 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 -} - -// encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m. -func encodeExtensionMap(m map[int32]Extension) error { - for k, e := range m { - if e.value == nil || e.desc == nil { - // Extension is only in its encoded form. - 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. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - p := NewBuffer(nil) - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - if err := props.enc(p, props, toStructPointer(x)); err != nil { - return err - } - e.enc = p.buf - m[k] = e - } - return nil -} - -func sizeExtensionMap(m map[int32]Extension) (n int) { - 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. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - n += props.size(props, toStructPointer(x)) - } - return -} - -// HasExtension returns whether the given extension is present in pb. -func HasExtension(pb extendableProto, extension *ExtensionDesc) bool { - // TODO: Check types, field numbers, etc.? - _, ok := pb.ExtensionMap()[extension.Field] - return ok -} - -// ClearExtension removes the given extension from pb. -func ClearExtension(pb extendableProto, extension *ExtensionDesc) { - // TODO: Check types, field numbers, etc.? - delete(pb.ExtensionMap(), extension.Field) -} - -// GetExtension parses and returns the given extension of pb. -// If the extension is not present and has no default value it returns ErrMissingExtension. -func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) { - if err := checkExtensionTypes(pb, extension); err != nil { - return nil, err - } - - emap := pb.ExtensionMap() - 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 - } - - 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) { - 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) { - o := NewBuffer(b) - - t := reflect.TypeOf(extension.ExtensionType) - rep := extension.repeated() - - props := extensionProperties(extension) - - // t is a pointer to a struct, pointer to basic type or a slice. - // Allocate a "field" to store the pointer/slice itself; the - // pointer/slice will be stored here. We pass - // the address of this field to props.dec. - // This passes a zero field and a *t and lets props.dec - // interpret it as a *struct{ x t }. - value := reflect.New(t).Elem() - - for { - // Discard wire type and field number varint. It isn't needed. - if _, err := o.DecodeVarint(); err != nil { - return nil, err - } - - if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil { - return nil, err - } - - if !rep || o.index >= len(o.buf) { - 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, ok := pb.(extendableProto) - if !ok { - err = errors.New("proto: not an extendable proto") - return - } - 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 -} - -// SetExtension sets the specified extension of pb to the specified value. -func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error { - if err := checkExtensionTypes(pb, extension); err != nil { - return err - } - typ := reflect.TypeOf(extension.ExtensionType) - if typ != reflect.TypeOf(value) { - return errors.New("proto: bad extension value type") - } - // 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) - } - - pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value} - return nil -} - -// 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/Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions_test.go deleted file mode 100644 index 72552767..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions_test.go +++ /dev/null @@ -1,292 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 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_test - -import ( - "fmt" - "reflect" - "testing" - - "github.com/golang/protobuf/proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -func TestGetExtensionsWithMissingExtensions(t *testing.T) { - msg := &pb.MyMessage{} - ext1 := &pb.Ext{} - if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { - t.Fatalf("Could not set ext1: %s", ext1) - } - exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{ - pb.E_Ext_More, - pb.E_Ext_Text, - }) - if err != nil { - t.Fatalf("GetExtensions() failed: %s", err) - } - if exts[0] != ext1 { - t.Errorf("ext1 not in returned extensions: %T %v", exts[0], exts[0]) - } - if exts[1] != nil { - t.Errorf("ext2 in returned extensions: %T %v", exts[1], exts[1]) - } -} - -func TestGetExtensionStability(t *testing.T) { - check := func(m *pb.MyMessage) bool { - ext1, err := proto.GetExtension(m, pb.E_Ext_More) - if err != nil { - t.Fatalf("GetExtension() failed: %s", err) - } - ext2, err := proto.GetExtension(m, pb.E_Ext_More) - if err != nil { - t.Fatalf("GetExtension() failed: %s", err) - } - return ext1 == ext2 - } - msg := &pb.MyMessage{Count: proto.Int32(4)} - ext0 := &pb.Ext{} - if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil { - t.Fatalf("Could not set ext1: %s", ext0) - } - if !check(msg) { - t.Errorf("GetExtension() not stable before marshaling") - } - bb, err := proto.Marshal(msg) - if err != nil { - t.Fatalf("Marshal() failed: %s", err) - } - msg1 := &pb.MyMessage{} - err = proto.Unmarshal(bb, msg1) - if err != nil { - t.Fatalf("Unmarshal() failed: %s", err) - } - if !check(msg1) { - t.Errorf("GetExtension() not stable after unmarshaling") - } -} - -func TestGetExtensionDefaults(t *testing.T) { - var setFloat64 float64 = 1 - var setFloat32 float32 = 2 - var setInt32 int32 = 3 - var setInt64 int64 = 4 - var setUint32 uint32 = 5 - var setUint64 uint64 = 6 - var setBool = true - var setBool2 = false - var setString = "Goodnight string" - var setBytes = []byte("Goodnight bytes") - var setEnum = pb.DefaultsMessage_TWO - - type testcase struct { - ext *proto.ExtensionDesc // Extension we are testing. - want interface{} // Expected value of extension, or nil (meaning that GetExtension will fail). - def interface{} // Expected value of extension after ClearExtension(). - } - tests := []testcase{ - {pb.E_NoDefaultDouble, setFloat64, nil}, - {pb.E_NoDefaultFloat, setFloat32, nil}, - {pb.E_NoDefaultInt32, setInt32, nil}, - {pb.E_NoDefaultInt64, setInt64, nil}, - {pb.E_NoDefaultUint32, setUint32, nil}, - {pb.E_NoDefaultUint64, setUint64, nil}, - {pb.E_NoDefaultSint32, setInt32, nil}, - {pb.E_NoDefaultSint64, setInt64, nil}, - {pb.E_NoDefaultFixed32, setUint32, nil}, - {pb.E_NoDefaultFixed64, setUint64, nil}, - {pb.E_NoDefaultSfixed32, setInt32, nil}, - {pb.E_NoDefaultSfixed64, setInt64, nil}, - {pb.E_NoDefaultBool, setBool, nil}, - {pb.E_NoDefaultBool, setBool2, nil}, - {pb.E_NoDefaultString, setString, nil}, - {pb.E_NoDefaultBytes, setBytes, nil}, - {pb.E_NoDefaultEnum, setEnum, nil}, - {pb.E_DefaultDouble, setFloat64, float64(3.1415)}, - {pb.E_DefaultFloat, setFloat32, float32(3.14)}, - {pb.E_DefaultInt32, setInt32, int32(42)}, - {pb.E_DefaultInt64, setInt64, int64(43)}, - {pb.E_DefaultUint32, setUint32, uint32(44)}, - {pb.E_DefaultUint64, setUint64, uint64(45)}, - {pb.E_DefaultSint32, setInt32, int32(46)}, - {pb.E_DefaultSint64, setInt64, int64(47)}, - {pb.E_DefaultFixed32, setUint32, uint32(48)}, - {pb.E_DefaultFixed64, setUint64, uint64(49)}, - {pb.E_DefaultSfixed32, setInt32, int32(50)}, - {pb.E_DefaultSfixed64, setInt64, int64(51)}, - {pb.E_DefaultBool, setBool, true}, - {pb.E_DefaultBool, setBool2, true}, - {pb.E_DefaultString, setString, "Hello, string"}, - {pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")}, - {pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE}, - } - - checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error { - val, err := proto.GetExtension(msg, test.ext) - if err != nil { - if valWant != nil { - return fmt.Errorf("GetExtension(): %s", err) - } - if want := proto.ErrMissingExtension; err != want { - return fmt.Errorf("Unexpected error: got %v, want %v", err, want) - } - return nil - } - - // All proto2 extension values are either a pointer to a value or a slice of values. - ty := reflect.TypeOf(val) - tyWant := reflect.TypeOf(test.ext.ExtensionType) - if got, want := ty, tyWant; got != want { - return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want) - } - tye := ty.Elem() - tyeWant := tyWant.Elem() - if got, want := tye, tyeWant; got != want { - return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want) - } - - // Check the name of the type of the value. - // If it is an enum it will be type int32 with the name of the enum. - if got, want := tye.Name(), tye.Name(); got != want { - return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want) - } - - // Check that value is what we expect. - // If we have a pointer in val, get the value it points to. - valExp := val - if ty.Kind() == reflect.Ptr { - valExp = reflect.ValueOf(val).Elem().Interface() - } - if got, want := valExp, valWant; !reflect.DeepEqual(got, want) { - return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want) - } - - return nil - } - - setTo := func(test testcase) interface{} { - setTo := reflect.ValueOf(test.want) - if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr { - setTo = reflect.New(typ).Elem() - setTo.Set(reflect.New(setTo.Type().Elem())) - setTo.Elem().Set(reflect.ValueOf(test.want)) - } - return setTo.Interface() - } - - for _, test := range tests { - msg := &pb.DefaultsMessage{} - name := test.ext.Name - - // Check the initial value. - if err := checkVal(test, msg, test.def); err != nil { - t.Errorf("%s: %v", name, err) - } - - // Set the per-type value and check value. - name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want) - if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil { - t.Errorf("%s: SetExtension(): %v", name, err) - continue - } - if err := checkVal(test, msg, test.want); err != nil { - t.Errorf("%s: %v", name, err) - continue - } - - // Set and check the value. - name += " (cleared)" - proto.ClearExtension(msg, test.ext) - if err := checkVal(test, msg, test.def); err != nil { - t.Errorf("%s: %v", name, err) - } - } -} - -func TestExtensionsRoundTrip(t *testing.T) { - msg := &pb.MyMessage{} - ext1 := &pb.Ext{ - Data: proto.String("hi"), - } - ext2 := &pb.Ext{ - Data: proto.String("there"), - } - exists := proto.HasExtension(msg, pb.E_Ext_More) - if exists { - t.Error("Extension More present unexpectedly") - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { - t.Error(err) - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil { - t.Error(err) - } - e, err := proto.GetExtension(msg, pb.E_Ext_More) - if err != nil { - t.Error(err) - } - x, ok := e.(*pb.Ext) - if !ok { - t.Errorf("e has type %T, expected testdata.Ext", e) - } else if *x.Data != "there" { - t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x) - } - proto.ClearExtension(msg, pb.E_Ext_More) - if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension { - t.Errorf("got %v, expected ErrMissingExtension", e) - } - if _, err := proto.GetExtension(msg, pb.E_X215); err == nil { - t.Error("expected bad extension error, got nil") - } - if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil { - t.Error("expected extension err") - } - if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil { - t.Error("expected some sort of type mismatch error, got nil") - } -} - -func TestNilExtension(t *testing.T) { - msg := &pb.MyMessage{ - Count: proto.Int32(1), - } - if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil { - t.Fatal(err) - } - if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil { - t.Error("expected SetExtension to fail due to a nil extension") - } else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want { - t.Errorf("expected error %v, got %v", want, err) - } - // Note: if the behavior of Marshal is ever changed to ignore nil extensions, update - // this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal. -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go deleted file mode 100644 index 95f7975d..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go +++ /dev/null @@ -1,841 +0,0 @@ -// 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. - - Marshal and Unmarshal are functions to encode and decode the wire format. - -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; - } - } - -The resulting file, test.pb.go, is: - - package example - - import proto "github.com/golang/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"` - XXX_unrecognized []byte `json:"-"` - } - func (m *Test) Reset() { *m = Test{} } - func (m *Test) String() string { return proto.CompactTextString(m) } - func (*Test) ProtoMessage() {} - 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 init() { - proto.RegisterEnum("example.FOO", FOO_name, FOO_value) - } - -To create and play with a Test object: - -package main - - import ( - "log" - - "github.com/golang/protobuf/proto" - pb "./example.pb" - ) - - func main() { - test := &pb.Test{ - Label: proto.String("hello"), - Type: proto.Int32(17), - Optionalgroup: &pb.Test_OptionalGroup{ - RequiredField: proto.String("good bye"), - }, - } - 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()) - } - // etc. - } -*/ -package proto - -import ( - "encoding/json" - "fmt" - "log" - "reflect" - "sort" - "strconv" - "sync" -) - -// Message is implemented by generated protocol buffer messages. -type Message interface { - Reset() - String() string - ProtoMessage() -} - -// Stats records allocation details about the protocol buffer encoders -// and decoders. Useful for tuning the library itself. -type Stats struct { - Emalloc uint64 // mallocs in encode - Dmalloc uint64 // mallocs in decode - Encode uint64 // number of encodes - Decode uint64 // number of decodes - Chit uint64 // number of cache hits - Cmiss uint64 // number of cache misses - Size uint64 // number of sizes -} - -// Set to true to enable stats collection. -const collectStats = false - -var stats Stats - -// GetStats returns a copy of the global Stats structure. -func GetStats() Stats { return stats } - -// 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 // write point - - // pools of basic types to amortize allocation. - bools []bool - uint32s []uint32 - uint64s []uint64 - - // extra pools, only used with pointer_reflect.go - int32s []int32 - int64s []int64 - float32s []float32 - float64s []float64 -} - -// 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 } - -/* - * 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 - index := 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) - break - - 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: - if err != nil { - fmt.Printf("%3d: t=%3d start err %v\n", index, tag, err) - break out - } - fmt.Printf("%3d: t=%3d start\n", index, tag) - depth++ - - case WireEndGroup: - depth-- - if err != nil { - fmt.Printf("%3d: t=%3d end err %v\n", index, tag, err) - break out - } - 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 = index -} - -// 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 pointer to a struct. -func setDefaults(v reflect.Value, recur, zeros bool) { - 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 map[T]*T - switch f.Kind() { - 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.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.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: - 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 -} - -// Map fields may have key types of non-float scalars, strings and enums. -// The easiest way to sort them in some deterministic order is to use fmt. -// If this turns out to be inefficient we can always consider other options, -// such as doing a Schwartzian transform. - -func mapKeys(vs []reflect.Value) sort.Interface { - s := mapKeySorter{ - vs: vs, - // default Less function: textual comparison - less: func(a, b reflect.Value) bool { - return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface()) - }, - } - - // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps; - // numeric keys are sorted numerically. - 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() } - } - - 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 -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set.go deleted file mode 100644 index 9d912bce..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set.go +++ /dev/null @@ -1,287 +0,0 @@ -// 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 ( - "bytes" - "encoding/json" - "errors" - "fmt" - "reflect" - "sort" -) - -// 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. -// -// When a proto1 proto has a field that looks like: -// optional message info = 3; -// the protocol compiler produces a field in the generated struct that looks like: -// Info *_proto_.MessageSet `protobuf:"bytes,3,opt,name=info"` -// The package is automatically inserted so there is no need for that proto file to -// import 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 { - if ms.find(pb) != nil { - return true - } - return false -} - -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:] -} - -// MarshalMessageSet encodes the extension map represented by m in the message set wire format. -// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. -func MarshalMessageSet(m map[int32]Extension) ([]byte, error) { - if err := encodeExtensionMap(m); err != nil { - return nil, err - } - - // Sort extension IDs to provide a deterministic encoding. - // See also enc_map in encode.go. - ids := make([]int, 0, len(m)) - for id := range m { - ids = append(ids, int(id)) - } - sort.Ints(ids) - - ms := &MessageSet{Item: make([]*_MessageSet_Item, 0, len(m))} - for _, id := range ids { - e := m[int32(id)] - // Remove the wire type and field number varint, as well as the length varint. - msg := skipVarint(skipVarint(e.enc)) - - ms.Item = append(ms.Item, &_MessageSet_Item{ - TypeId: Int32(int32(id)), - Message: msg, - }) - } - return Marshal(ms) -} - -// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. -// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. -func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error { - 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 -} - -// MarshalMessageSetJSON encodes the extension map represented by m in JSON format. -// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. -func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) { - var b bytes.Buffer - b.WriteByte('{') - - // Process the map in key order for deterministic output. - ids := make([]int32, 0, len(m)) - for id := range m { - ids = append(ids, id) - } - sort.Sort(int32Slice(ids)) // int32Slice defined in text.go - - for i, id := range ids { - ext := m[id] - if i > 0 { - b.WriteByte(',') - } - - msd, ok := messageSetMap[id] - if !ok { - // Unknown type; we can't render it, so skip it. - continue - } - fmt.Fprintf(&b, `"[%s]":`, msd.name) - - x := ext.value - if x == nil { - x = reflect.New(msd.t.Elem()).Interface() - if err := Unmarshal(ext.enc, x.(Message)); err != nil { - return nil, err - } - } - d, err := json.Marshal(x) - if err != nil { - return nil, err - } - b.Write(d) - } - b.WriteByte('}') - return b.Bytes(), nil -} - -// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. -// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. -func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error { - // Common-case fast path. - if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { - return nil - } - - // This is fairly tricky, and it's not clear that it is needed. - return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented") -} - -// A global registry of types that can be used in a MessageSet. - -var messageSetMap = make(map[int32]messageSetDesc) - -type messageSetDesc struct { - t reflect.Type // pointer to struct - name string -} - -// RegisterMessageSetType is called from the generated code. -func RegisterMessageSetType(m Message, fieldNum int32, name string) { - messageSetMap[fieldNum] = messageSetDesc{ - t: reflect.TypeOf(m), - name: name, - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set_test.go deleted file mode 100644 index 7c29bccf..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 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 ( - "bytes" - "testing" -) - -func TestUnmarshalMessageSetWithDuplicate(t *testing.T) { - // Check that a repeated message set entry will be concatenated. - in := &MessageSet{ - Item: []*_MessageSet_Item{ - {TypeId: Int32(12345), Message: []byte("hoo")}, - {TypeId: Int32(12345), Message: []byte("hah")}, - }, - } - b, err := Marshal(in) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("Marshaled bytes: %q", b) - - m := make(map[int32]Extension) - if err := UnmarshalMessageSet(b, m); err != nil { - t.Fatalf("UnmarshalMessageSet: %v", err) - } - ext, ok := m[12345] - if !ok { - t.Fatalf("Didn't retrieve extension 12345; map is %v", m) - } - // Skip wire type/field number and length varints. - got := skipVarint(skipVarint(ext.enc)) - if want := []byte("hoohah"); !bytes.Equal(got, want) { - t.Errorf("Combined extension is %q, want %q", got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_reflect.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_reflect.go deleted file mode 100644 index 749919d2..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_reflect.go +++ /dev/null @@ -1,479 +0,0 @@ -// 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 appengine - -// 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 ( - "math" - "reflect" -) - -// A structPointer is a pointer to a struct. -type structPointer struct { - v reflect.Value -} - -// toStructPointer returns a structPointer equivalent to the given reflect value. -// The reflect value must itself be a pointer to a struct. -func toStructPointer(v reflect.Value) structPointer { - return structPointer{v} -} - -// IsNil reports whether p is nil. -func structPointer_IsNil(p structPointer) bool { - return p.v.IsNil() -} - -// Interface returns the struct pointer as an interface value. -func structPointer_Interface(p structPointer, _ reflect.Type) interface{} { - return p.v.Interface() -} - -// A field identifies a field in a struct, accessible from a structPointer. -// 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) - -// IsValid reports whether the field identifier is valid. -func (f field) IsValid() bool { return f != nil } - -// field returns the given field in the struct as a reflect value. -func structPointer_field(p structPointer, f field) reflect.Value { - // Special case: an extension map entry with a value of type T - // passes a *T to the struct-handling code with a zero field, - // expecting that it will be treated as equivalent to *struct{ X T }, - // which has the same memory layout. We have to handle that case - // specially, because reflect will panic if we call FieldByIndex on a - // non-struct. - if f == nil { - return p.v.Elem() - } - - return p.v.Elem().FieldByIndex(f) -} - -// ifield returns the given field in the struct as an interface value. -func structPointer_ifield(p structPointer, f field) interface{} { - return structPointer_field(p, f).Addr().Interface() -} - -// Bytes returns the address of a []byte field in the struct. -func structPointer_Bytes(p structPointer, f field) *[]byte { - return structPointer_ifield(p, f).(*[]byte) -} - -// BytesSlice returns the address of a [][]byte field in the struct. -func structPointer_BytesSlice(p structPointer, f field) *[][]byte { - return structPointer_ifield(p, f).(*[][]byte) -} - -// Bool returns the address of a *bool field in the struct. -func structPointer_Bool(p structPointer, f field) **bool { - return structPointer_ifield(p, f).(**bool) -} - -// BoolVal returns the address of a bool field in the struct. -func structPointer_BoolVal(p structPointer, f field) *bool { - return structPointer_ifield(p, f).(*bool) -} - -// BoolSlice returns the address of a []bool field in the struct. -func structPointer_BoolSlice(p structPointer, f field) *[]bool { - return structPointer_ifield(p, f).(*[]bool) -} - -// String returns the address of a *string field in the struct. -func structPointer_String(p structPointer, f field) **string { - return structPointer_ifield(p, f).(**string) -} - -// StringVal returns the address of a string field in the struct. -func structPointer_StringVal(p structPointer, f field) *string { - return structPointer_ifield(p, f).(*string) -} - -// StringSlice returns the address of a []string field in the struct. -func structPointer_StringSlice(p structPointer, f field) *[]string { - return structPointer_ifield(p, f).(*[]string) -} - -// ExtMap returns the address of an extension map field in the struct. -func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { - return structPointer_ifield(p, f).(*map[int32]Extension) -} - -// NewAt returns the reflect.Value for a pointer to a field in the struct. -func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { - return structPointer_field(p, f).Addr() -} - -// SetStructPointer writes a *struct field in the struct. -func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { - structPointer_field(p, f).Set(q.v) -} - -// GetStructPointer reads a *struct field in the struct. -func structPointer_GetStructPointer(p structPointer, f field) structPointer { - return structPointer{structPointer_field(p, f)} -} - -// StructPointerSlice the address of a []*struct field in the struct. -func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice { - return structPointerSlice{structPointer_field(p, f)} -} - -// A structPointerSlice represents the address of a slice of pointers to structs -// (themselves messages or groups). That is, v.Type() is *[]*struct{...}. -type structPointerSlice struct { - v reflect.Value -} - -func (p structPointerSlice) Len() int { return p.v.Len() } -func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } -func (p structPointerSlice) Append(q structPointer) { - p.v.Set(reflect.Append(p.v, q.v)) -} - -var ( - int32Type = reflect.TypeOf(int32(0)) - uint32Type = reflect.TypeOf(uint32(0)) - float32Type = reflect.TypeOf(float32(0)) - int64Type = reflect.TypeOf(int64(0)) - uint64Type = reflect.TypeOf(uint64(0)) - float64Type = reflect.TypeOf(float64(0)) -) - -// A word32 represents a field of type *int32, *uint32, *float32, or *enum. -// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable. -type word32 struct { - v reflect.Value -} - -// IsNil reports whether p is nil. -func word32_IsNil(p word32) bool { - return p.v.IsNil() -} - -// Set sets p to point at a newly allocated word with bits set to x. -func word32_Set(p word32, o *Buffer, x uint32) { - t := p.v.Type().Elem() - switch t { - case int32Type: - if len(o.int32s) == 0 { - o.int32s = make([]int32, uint32PoolSize) - } - o.int32s[0] = int32(x) - p.v.Set(reflect.ValueOf(&o.int32s[0])) - o.int32s = o.int32s[1:] - return - case uint32Type: - if len(o.uint32s) == 0 { - o.uint32s = make([]uint32, uint32PoolSize) - } - o.uint32s[0] = x - p.v.Set(reflect.ValueOf(&o.uint32s[0])) - o.uint32s = o.uint32s[1:] - return - case float32Type: - if len(o.float32s) == 0 { - o.float32s = make([]float32, uint32PoolSize) - } - o.float32s[0] = math.Float32frombits(x) - p.v.Set(reflect.ValueOf(&o.float32s[0])) - o.float32s = o.float32s[1:] - return - } - - // must be enum - p.v.Set(reflect.New(t)) - p.v.Elem().SetInt(int64(int32(x))) -} - -// Get gets the bits pointed at by p, as a uint32. -func word32_Get(p word32) uint32 { - elem := p.v.Elem() - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32(p structPointer, f field) word32 { - return word32{structPointer_field(p, f)} -} - -// A word32Val represents a field of type int32, uint32, float32, or enum. -// That is, v.Type() is int32, uint32, float32, or enum and v is assignable. -type word32Val struct { - v reflect.Value -} - -// Set sets *p to x. -func word32Val_Set(p word32Val, x uint32) { - switch p.v.Type() { - case int32Type: - p.v.SetInt(int64(x)) - return - case uint32Type: - p.v.SetUint(uint64(x)) - return - case float32Type: - p.v.SetFloat(float64(math.Float32frombits(x))) - return - } - - // must be enum - p.v.SetInt(int64(int32(x))) -} - -// Get gets the bits pointed at by p, as a uint32. -func word32Val_Get(p word32Val) uint32 { - elem := p.v - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct. -func structPointer_Word32Val(p structPointer, f field) word32Val { - return word32Val{structPointer_field(p, f)} -} - -// A word32Slice is a slice of 32-bit values. -// That is, v.Type() is []int32, []uint32, []float32, or []enum. -type word32Slice struct { - v reflect.Value -} - -func (p word32Slice) Append(x uint32) { - n, m := p.v.Len(), p.v.Cap() - if n < m { - p.v.SetLen(n + 1) - } else { - t := p.v.Type().Elem() - p.v.Set(reflect.Append(p.v, reflect.Zero(t))) - } - elem := p.v.Index(n) - switch elem.Kind() { - case reflect.Int32: - elem.SetInt(int64(int32(x))) - case reflect.Uint32: - elem.SetUint(uint64(x)) - case reflect.Float32: - elem.SetFloat(float64(math.Float32frombits(x))) - } -} - -func (p word32Slice) Len() int { - return p.v.Len() -} - -func (p word32Slice) Index(i int) uint32 { - elem := p.v.Index(i) - switch elem.Kind() { - case reflect.Int32: - return uint32(elem.Int()) - case reflect.Uint32: - return uint32(elem.Uint()) - case reflect.Float32: - return math.Float32bits(float32(elem.Float())) - } - panic("unreachable") -} - -// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct. -func structPointer_Word32Slice(p structPointer, f field) word32Slice { - return word32Slice{structPointer_field(p, f)} -} - -// word64 is like word32 but for 64-bit values. -type word64 struct { - v reflect.Value -} - -func word64_Set(p word64, o *Buffer, x uint64) { - t := p.v.Type().Elem() - switch t { - case int64Type: - if len(o.int64s) == 0 { - o.int64s = make([]int64, uint64PoolSize) - } - o.int64s[0] = int64(x) - p.v.Set(reflect.ValueOf(&o.int64s[0])) - o.int64s = o.int64s[1:] - return - case uint64Type: - if len(o.uint64s) == 0 { - o.uint64s = make([]uint64, uint64PoolSize) - } - o.uint64s[0] = x - p.v.Set(reflect.ValueOf(&o.uint64s[0])) - o.uint64s = o.uint64s[1:] - return - case float64Type: - if len(o.float64s) == 0 { - o.float64s = make([]float64, uint64PoolSize) - } - o.float64s[0] = math.Float64frombits(x) - p.v.Set(reflect.ValueOf(&o.float64s[0])) - o.float64s = o.float64s[1:] - return - } - panic("unreachable") -} - -func word64_IsNil(p word64) bool { - return p.v.IsNil() -} - -func word64_Get(p word64) uint64 { - elem := p.v.Elem() - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return elem.Uint() - case reflect.Float64: - return math.Float64bits(elem.Float()) - } - panic("unreachable") -} - -func structPointer_Word64(p structPointer, f field) word64 { - return word64{structPointer_field(p, f)} -} - -// word64Val is like word32Val but for 64-bit values. -type word64Val struct { - v reflect.Value -} - -func word64Val_Set(p word64Val, o *Buffer, x uint64) { - switch p.v.Type() { - case int64Type: - p.v.SetInt(int64(x)) - return - case uint64Type: - p.v.SetUint(x) - return - case float64Type: - p.v.SetFloat(math.Float64frombits(x)) - return - } - panic("unreachable") -} - -func word64Val_Get(p word64Val) uint64 { - elem := p.v - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return elem.Uint() - case reflect.Float64: - return math.Float64bits(elem.Float()) - } - panic("unreachable") -} - -func structPointer_Word64Val(p structPointer, f field) word64Val { - return word64Val{structPointer_field(p, f)} -} - -type word64Slice struct { - v reflect.Value -} - -func (p word64Slice) Append(x uint64) { - n, m := p.v.Len(), p.v.Cap() - if n < m { - p.v.SetLen(n + 1) - } else { - t := p.v.Type().Elem() - p.v.Set(reflect.Append(p.v, reflect.Zero(t))) - } - elem := p.v.Index(n) - switch elem.Kind() { - case reflect.Int64: - elem.SetInt(int64(int64(x))) - case reflect.Uint64: - elem.SetUint(uint64(x)) - case reflect.Float64: - elem.SetFloat(float64(math.Float64frombits(x))) - } -} - -func (p word64Slice) Len() int { - return p.v.Len() -} - -func (p word64Slice) Index(i int) uint64 { - elem := p.v.Index(i) - switch elem.Kind() { - case reflect.Int64: - return uint64(elem.Int()) - case reflect.Uint64: - return uint64(elem.Uint()) - case reflect.Float64: - return math.Float64bits(float64(elem.Float())) - } - panic("unreachable") -} - -func structPointer_Word64Slice(p structPointer, f field) word64Slice { - return word64Slice{structPointer_field(p, f)} -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_unsafe.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_unsafe.go deleted file mode 100644 index e9be0fe9..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_unsafe.go +++ /dev/null @@ -1,266 +0,0 @@ -// 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 !appengine - -// This file contains the implementation of the proto field accesses using package unsafe. - -package proto - -import ( - "reflect" - "unsafe" -) - -// NOTE: These type_Foo functions would more idiomatically be methods, -// but Go does not allow methods on pointer types, and we must preserve -// some pointer type for the garbage collector. We use these -// funcs with clunky names as our poor approximation to methods. -// -// An alternative would be -// type structPointer struct { p unsafe.Pointer } -// but that does not registerize as well. - -// A structPointer is a pointer to a struct. -type structPointer unsafe.Pointer - -// toStructPointer returns a structPointer equivalent to the given reflect value. -func toStructPointer(v reflect.Value) structPointer { - return structPointer(unsafe.Pointer(v.Pointer())) -} - -// IsNil reports whether p is nil. -func structPointer_IsNil(p structPointer) bool { - return p == nil -} - -// Interface returns the struct pointer, assumed to have element type t, -// as an interface value. -func structPointer_Interface(p structPointer, t reflect.Type) interface{} { - return reflect.NewAt(t, unsafe.Pointer(p)).Interface() -} - -// A field identifies a field in a struct, accessible from a structPointer. -// 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) - -// IsValid reports whether the field identifier is valid. -func (f field) IsValid() bool { - return f != ^field(0) -} - -// Bytes returns the address of a []byte field in the struct. -func structPointer_Bytes(p structPointer, f field) *[]byte { - return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BytesSlice returns the address of a [][]byte field in the struct. -func structPointer_BytesSlice(p structPointer, f field) *[][]byte { - return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// Bool returns the address of a *bool field in the struct. -func structPointer_Bool(p structPointer, f field) **bool { - return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BoolVal returns the address of a bool field in the struct. -func structPointer_BoolVal(p structPointer, f field) *bool { - return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// BoolSlice returns the address of a []bool field in the struct. -func structPointer_BoolSlice(p structPointer, f field) *[]bool { - return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// String returns the address of a *string field in the struct. -func structPointer_String(p structPointer, f field) **string { - return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StringVal returns the address of a string field in the struct. -func structPointer_StringVal(p structPointer, f field) *string { - return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StringSlice returns the address of a []string field in the struct. -func structPointer_StringSlice(p structPointer, f field) *[]string { - return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// ExtMap returns the address of an extension map field in the struct. -func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { - return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// NewAt returns the reflect.Value for a pointer to a field in the struct. -func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { - return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f))) -} - -// SetStructPointer writes a *struct field in the struct. -func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { - *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q -} - -// GetStructPointer reads a *struct field in the struct. -func structPointer_GetStructPointer(p structPointer, f field) structPointer { - return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// StructPointerSlice the address of a []*struct field in the struct. -func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice { - return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups). -type structPointerSlice []structPointer - -func (v *structPointerSlice) Len() int { return len(*v) } -func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] } -func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) } - -// A word32 is the address of a "pointer to 32-bit value" field. -type word32 **uint32 - -// IsNil reports whether *v is nil. -func word32_IsNil(p word32) bool { - return *p == nil -} - -// Set sets *v to point at a newly allocated word set to x. -func word32_Set(p word32, o *Buffer, x uint32) { - if len(o.uint32s) == 0 { - o.uint32s = make([]uint32, uint32PoolSize) - } - o.uint32s[0] = x - *p = &o.uint32s[0] - o.uint32s = o.uint32s[1:] -} - -// Get gets the value pointed at by *v. -func word32_Get(p word32) uint32 { - return **p -} - -// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32(p structPointer, f field) word32 { - return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// A word32Val is the address of a 32-bit value field. -type word32Val *uint32 - -// Set sets *p to x. -func word32Val_Set(p word32Val, x uint32) { - *p = x -} - -// Get gets the value pointed at by p. -func word32Val_Get(p word32Val) uint32 { - return *p -} - -// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct. -func structPointer_Word32Val(p structPointer, f field) word32Val { - return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// A word32Slice is a slice of 32-bit values. -type word32Slice []uint32 - -func (v *word32Slice) Append(x uint32) { *v = append(*v, x) } -func (v *word32Slice) Len() int { return len(*v) } -func (v *word32Slice) Index(i int) uint32 { return (*v)[i] } - -// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct. -func structPointer_Word32Slice(p structPointer, f field) *word32Slice { - return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} - -// word64 is like word32 but for 64-bit values. -type word64 **uint64 - -func word64_Set(p word64, o *Buffer, x uint64) { - if len(o.uint64s) == 0 { - o.uint64s = make([]uint64, uint64PoolSize) - } - o.uint64s[0] = x - *p = &o.uint64s[0] - o.uint64s = o.uint64s[1:] -} - -func word64_IsNil(p word64) bool { - return *p == nil -} - -func word64_Get(p word64) uint64 { - return **p -} - -func structPointer_Word64(p structPointer, f field) word64 { - return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// word64Val is like word32Val but for 64-bit values. -type word64Val *uint64 - -func word64Val_Set(p word64Val, o *Buffer, x uint64) { - *p = x -} - -func word64Val_Get(p word64Val) uint64 { - return *p -} - -func structPointer_Word64Val(p structPointer, f field) word64Val { - return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) -} - -// word64Slice is like word32Slice but for 64-bit values. -type word64Slice []uint64 - -func (v *word64Slice) Append(x uint64) { *v = append(*v, x) } -func (v *word64Slice) Len() int { return len(*v) } -func (v *word64Slice) Index(i int) uint64 { return (*v)[i] } - -func structPointer_Word64Slice(p structPointer, f field) *word64Slice { - return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go deleted file mode 100644 index d74844ab..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go +++ /dev/null @@ -1,742 +0,0 @@ -// 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" - "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 -) - -const startSize = 10 // initial slice/string sizes - -// Encoders are defined in encode.go -// An encoder outputs the full representation of a field, including its -// tag and encoder type. -type encoder func(p *Buffer, prop *Properties, base structPointer) error - -// A valueEncoder encodes a single integer in a particular encoding. -type valueEncoder func(o *Buffer, x uint64) error - -// Sizers are defined in encode.go -// A sizer returns the encoded size of a field, including its tag and encoder -// type. -type sizer func(prop *Properties, base structPointer) int - -// A valueSizer returns the encoded size of a single integer in a particular -// encoding. -type valueSizer func(x uint64) int - -// Decoders are defined in decode.go -// A decoder creates a value from its wire representation. -// Unrecognized subelements are saved in unrec. -type decoder func(p *Buffer, prop *Properties, base structPointer) error - -// A valueDecoder decodes a single integer in a particular encoding. -type valueDecoder func(o *Buffer) (x uint64, err error) - -// 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 - unrecField field // field id of the XXX_unrecognized []byte field - extendable bool // is this an extendable proto -} - -// 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) - 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; set for []byte only - - Default string // default value - HasDefault bool // whether an explicit default was provided - def_uint64 uint64 - - enc encoder - valEnc valueEncoder // set for bool and numeric types only - field field - tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType) - tagbuf [8]byte - stype reflect.Type // set for struct types only - sprop *StructProperties // set for struct types only - isMarshaler bool - isUnmarshaler bool - - mtype reflect.Type // set for map types only - mkeyprop *Properties // set for map types only - mvalprop *Properties // set for map types only - - size sizer - valSize valueSizer // set for bool and numeric types only - - dec decoder - valDec valueDecoder // set for bool and numeric types only - - // If this is a packable field, this will be the decoder for the packed version of the field. - packedDec decoder -} - -// 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" - } - if p.OrigName != p.Name { - s += ",name=" + p.OrigName - } - if p.proto3 { - s += ",proto3" - } - 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 - p.valEnc = (*Buffer).EncodeVarint - p.valDec = (*Buffer).DecodeVarint - p.valSize = sizeVarint - case "fixed32": - p.WireType = WireFixed32 - p.valEnc = (*Buffer).EncodeFixed32 - p.valDec = (*Buffer).DecodeFixed32 - p.valSize = sizeFixed32 - case "fixed64": - p.WireType = WireFixed64 - p.valEnc = (*Buffer).EncodeFixed64 - p.valDec = (*Buffer).DecodeFixed64 - p.valSize = sizeFixed64 - case "zigzag32": - p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeZigzag32 - p.valDec = (*Buffer).DecodeZigzag32 - p.valSize = sizeZigzag32 - case "zigzag64": - p.WireType = WireVarint - p.valEnc = (*Buffer).EncodeZigzag64 - p.valDec = (*Buffer).DecodeZigzag64 - p.valSize = sizeZigzag64 - 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 - } - - 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, "enum="): - p.Enum = f[5:] - case f == "proto3": - p.proto3 = 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 - } - } - } -} - -func logNoSliceEnc(t1, t2 reflect.Type) { - fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2) -} - -var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() - -// Initialize the fields for encoding and decoding. -func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { - p.enc = nil - p.dec = nil - p.size = nil - - switch t1 := typ; t1.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1) - - // proto3 scalar types - - case reflect.Bool: - p.enc = (*Buffer).enc_proto3_bool - p.dec = (*Buffer).dec_proto3_bool - p.size = size_proto3_bool - case reflect.Int32: - p.enc = (*Buffer).enc_proto3_int32 - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_proto3_int32 - case reflect.Uint32: - p.enc = (*Buffer).enc_proto3_uint32 - p.dec = (*Buffer).dec_proto3_int32 // can reuse - p.size = size_proto3_uint32 - case reflect.Int64, reflect.Uint64: - p.enc = (*Buffer).enc_proto3_int64 - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_proto3_int64 - case reflect.Float32: - p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int32 - p.size = size_proto3_uint32 - case reflect.Float64: - p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits - p.dec = (*Buffer).dec_proto3_int64 - p.size = size_proto3_int64 - case reflect.String: - p.enc = (*Buffer).enc_proto3_string - p.dec = (*Buffer).dec_proto3_string - p.size = size_proto3_string - - case reflect.Ptr: - switch t2 := t1.Elem(); t2.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2) - break - case reflect.Bool: - p.enc = (*Buffer).enc_bool - p.dec = (*Buffer).dec_bool - p.size = size_bool - case reflect.Int32: - p.enc = (*Buffer).enc_int32 - p.dec = (*Buffer).dec_int32 - p.size = size_int32 - case reflect.Uint32: - p.enc = (*Buffer).enc_uint32 - p.dec = (*Buffer).dec_int32 // can reuse - p.size = size_uint32 - case reflect.Int64, reflect.Uint64: - p.enc = (*Buffer).enc_int64 - p.dec = (*Buffer).dec_int64 - p.size = size_int64 - case reflect.Float32: - p.enc = (*Buffer).enc_uint32 // can just treat them as bits - p.dec = (*Buffer).dec_int32 - p.size = size_uint32 - case reflect.Float64: - p.enc = (*Buffer).enc_int64 // can just treat them as bits - p.dec = (*Buffer).dec_int64 - p.size = size_int64 - case reflect.String: - p.enc = (*Buffer).enc_string - p.dec = (*Buffer).dec_string - p.size = size_string - case reflect.Struct: - p.stype = t1.Elem() - p.isMarshaler = isMarshaler(t1) - p.isUnmarshaler = isUnmarshaler(t1) - if p.Wire == "bytes" { - p.enc = (*Buffer).enc_struct_message - p.dec = (*Buffer).dec_struct_message - p.size = size_struct_message - } else { - p.enc = (*Buffer).enc_struct_group - p.dec = (*Buffer).dec_struct_group - p.size = size_struct_group - } - } - - case reflect.Slice: - switch t2 := t1.Elem(); t2.Kind() { - default: - logNoSliceEnc(t1, t2) - break - case reflect.Bool: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_bool - p.size = size_slice_packed_bool - } else { - p.enc = (*Buffer).enc_slice_bool - p.size = size_slice_bool - } - p.dec = (*Buffer).dec_slice_bool - p.packedDec = (*Buffer).dec_slice_packed_bool - case reflect.Int32: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int32 - p.size = size_slice_packed_int32 - } else { - p.enc = (*Buffer).enc_slice_int32 - p.size = size_slice_int32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case reflect.Uint32: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_uint32 - p.size = size_slice_packed_uint32 - } else { - p.enc = (*Buffer).enc_slice_uint32 - p.size = size_slice_uint32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case reflect.Int64, reflect.Uint64: - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int64 - p.size = size_slice_packed_int64 - } else { - p.enc = (*Buffer).enc_slice_int64 - p.size = size_slice_int64 - } - p.dec = (*Buffer).dec_slice_int64 - p.packedDec = (*Buffer).dec_slice_packed_int64 - case reflect.Uint8: - p.enc = (*Buffer).enc_slice_byte - p.dec = (*Buffer).dec_slice_byte - p.size = size_slice_byte - // This is a []byte, which is either a bytes field, - // or the value of a map field. In the latter case, - // we always encode an empty []byte, so we should not - // use the proto3 enc/size funcs. - // f == nil iff this is the key/value of a map field. - if p.proto3 && f != nil { - p.enc = (*Buffer).enc_proto3_slice_byte - p.size = size_proto3_slice_byte - } - case reflect.Float32, reflect.Float64: - switch t2.Bits() { - case 32: - // can just treat them as bits - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_uint32 - p.size = size_slice_packed_uint32 - } else { - p.enc = (*Buffer).enc_slice_uint32 - p.size = size_slice_uint32 - } - p.dec = (*Buffer).dec_slice_int32 - p.packedDec = (*Buffer).dec_slice_packed_int32 - case 64: - // can just treat them as bits - if p.Packed { - p.enc = (*Buffer).enc_slice_packed_int64 - p.size = size_slice_packed_int64 - } else { - p.enc = (*Buffer).enc_slice_int64 - p.size = size_slice_int64 - } - p.dec = (*Buffer).dec_slice_int64 - p.packedDec = (*Buffer).dec_slice_packed_int64 - default: - logNoSliceEnc(t1, t2) - break - } - case reflect.String: - p.enc = (*Buffer).enc_slice_string - p.dec = (*Buffer).dec_slice_string - p.size = size_slice_string - case reflect.Ptr: - switch t3 := t2.Elem(); t3.Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3) - break - case reflect.Struct: - p.stype = t2.Elem() - p.isMarshaler = isMarshaler(t2) - p.isUnmarshaler = isUnmarshaler(t2) - if p.Wire == "bytes" { - p.enc = (*Buffer).enc_slice_struct_message - p.dec = (*Buffer).dec_slice_struct_message - p.size = size_slice_struct_message - } else { - p.enc = (*Buffer).enc_slice_struct_group - p.dec = (*Buffer).dec_slice_struct_group - p.size = size_slice_struct_group - } - } - case reflect.Slice: - switch t2.Elem().Kind() { - default: - fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem()) - break - case reflect.Uint8: - p.enc = (*Buffer).enc_slice_slice_byte - p.dec = (*Buffer).dec_slice_slice_byte - p.size = size_slice_slice_byte - } - } - - case reflect.Map: - p.enc = (*Buffer).enc_new_map - p.dec = (*Buffer).dec_new_map - p.size = size_new_map - - p.mtype = t1 - p.mkeyprop = &Properties{} - p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) - p.mvalprop = &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.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) - } - - // precalculate tag code - wire := p.WireType - if p.Packed { - wire = WireBytes - } - x := uint32(p.Tag)<<3 | uint32(wire) - i := 0 - for i = 0; x > 127; i++ { - p.tagbuf[i] = 0x80 | uint8(x&0x7F) - x >>= 7 - } - p.tagbuf[i] = uint8(x) - p.tagcode = p.tagbuf[0 : i+1] - - if p.stype != nil { - if lockGetProp { - p.sprop = GetProperties(p.stype) - } else { - p.sprop = getPropertiesLocked(p.stype) - } - } -} - -var ( - marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() - unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() -) - -// isMarshaler reports whether type t implements Marshaler. -func isMarshaler(t reflect.Type) bool { - // We're checking for (likely) pointer-receiver methods - // so if t is not a pointer, something is very wrong. - // The calls above only invoke isMarshaler on pointer types. - if t.Kind() != reflect.Ptr { - panic("proto: misuse of isMarshaler") - } - return t.Implements(marshalerType) -} - -// isUnmarshaler reports whether type t implements Unmarshaler. -func isUnmarshaler(t reflect.Type) bool { - // We're checking for (likely) pointer-receiver methods - // so if t is not a pointer, something is very wrong. - // The calls above only invoke isUnmarshaler on pointer types. - if t.Kind() != reflect.Ptr { - panic("proto: misuse of isUnmarshaler") - } - return t.Implements(unmarshalerType) -} - -// 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 f != nil { - p.field = toField(f) - } - if tag == "" { - return - } - p.Parse(tag) - p.setEncAndDec(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 { - if collectStats { - stats.Chit++ - } - 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 { - if collectStats { - stats.Chit++ - } - return prop - } - if collectStats { - stats.Cmiss++ - } - - prop := new(StructProperties) - // in case of recursive protos, fill this in now. - propertiesMap[t] = prop - - // build properties - prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) - prop.unrecField = invalidField - prop.Prop = make([]*Properties, t.NumField()) - prop.order = make([]int, t.NumField()) - - 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) - - if f.Name == "XXX_extensions" { // special case - p.enc = (*Buffer).enc_map - p.dec = nil // not needed - p.size = size_map - } - if f.Name == "XXX_unrecognized" { // special case - prop.unrecField = toField(&f) - } - 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") - } - if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") { - fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") - } - } - - // Re-order prop.order. - sort.Sort(prop) - - // 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 -} - -// Return the Properties object for the x[0]'th field of the structure. -func propByIndex(t reflect.Type, x []int) *Properties { - if len(x) != 1 { - fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t) - return nil - } - prop := GetProperties(t) - return prop.Prop[x[0]] -} - -// Get the address and type of a pointer to a struct from an interface. -func getbase(pb Message) (t reflect.Type, b structPointer, err error) { - if pb == nil { - err = ErrNil - return - } - // get the reflect type of the pointer to the struct. - t = reflect.TypeOf(pb) - // get the address of the struct. - value := reflect.ValueOf(pb) - b = toStructPointer(value) - return -} - -// 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) - -// 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 -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go deleted file mode 100644 index 37c77820..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go +++ /dev/null @@ -1,122 +0,0 @@ -// Code generated by protoc-gen-go. -// source: proto3_proto/proto3.proto -// DO NOT EDIT! - -/* -Package proto3_proto is a generated protocol buffer package. - -It is generated from these files: - proto3_proto/proto3.proto - -It has these top-level messages: - Message - Nested - MessageWithMap -*/ -package proto3_proto - -import proto "github.com/golang/protobuf/proto" -import testdata "github.com/golang/protobuf/proto/testdata" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal - -type Message_Humour int32 - -const ( - Message_UNKNOWN Message_Humour = 0 - Message_PUNS Message_Humour = 1 - Message_SLAPSTICK Message_Humour = 2 - Message_BILL_BAILEY Message_Humour = 3 -) - -var Message_Humour_name = map[int32]string{ - 0: "UNKNOWN", - 1: "PUNS", - 2: "SLAPSTICK", - 3: "BILL_BAILEY", -} -var Message_Humour_value = map[string]int32{ - "UNKNOWN": 0, - "PUNS": 1, - "SLAPSTICK": 2, - "BILL_BAILEY": 3, -} - -func (x Message_Humour) String() string { - return proto.EnumName(Message_Humour_name, int32(x)) -} - -type Message struct { - Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"` - HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm" json:"height_in_cm,omitempty"` - Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` - ResultCount int64 `protobuf:"varint,7,opt,name=result_count" json:"result_count,omitempty"` - TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman" json:"true_scotsman,omitempty"` - Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"` - Key []uint64 `protobuf:"varint,5,rep,name=key" json:"key,omitempty"` - Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"` - Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field" json:"proto2_field,omitempty"` - Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` -} - -func (m *Message) Reset() { *m = Message{} } -func (m *Message) String() string { return proto.CompactTextString(m) } -func (*Message) ProtoMessage() {} - -func (m *Message) GetNested() *Nested { - if m != nil { - return m.Nested - } - return nil -} - -func (m *Message) GetTerrain() map[string]*Nested { - if m != nil { - return m.Terrain - } - return nil -} - -func (m *Message) GetProto2Field() *testdata.SubDefaults { - if m != nil { - return m.Proto2Field - } - return nil -} - -func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults { - if m != nil { - return m.Proto2Value - } - return nil -} - -type Nested struct { - Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"` -} - -func (m *Nested) Reset() { *m = Nested{} } -func (m *Nested) String() string { return proto.CompactTextString(m) } -func (*Nested) ProtoMessage() {} - -type MessageWithMap struct { - ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } -func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } -func (*MessageWithMap) ProtoMessage() {} - -func (m *MessageWithMap) GetByteMapping() map[bool][]byte { - if m != nil { - return m.ByteMapping - } - return nil -} - -func init() { - proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value) -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto b/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto deleted file mode 100644 index e2311d92..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto +++ /dev/null @@ -1,68 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 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. - -syntax = "proto3"; - -import "testdata/test.proto"; - -package proto3_proto; - -message Message { - enum Humour { - UNKNOWN = 0; - PUNS = 1; - SLAPSTICK = 2; - BILL_BAILEY = 3; - } - - string name = 1; - Humour hilarity = 2; - uint32 height_in_cm = 3; - bytes data = 4; - int64 result_count = 7; - bool true_scotsman = 8; - float score = 9; - - repeated uint64 key = 5; - Nested nested = 6; - - map terrain = 10; - testdata.SubDefaults proto2_field = 11; - map proto2_value = 13; -} - -message Nested { - string bunny = 1; -} - -message MessageWithMap { - map byte_mapping = 1; -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_test.go deleted file mode 100644 index 462f8055..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 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_test - -import ( - "testing" - - "github.com/golang/protobuf/proto" - pb "github.com/golang/protobuf/proto/proto3_proto" - tpb "github.com/golang/protobuf/proto/testdata" -) - -func TestProto3ZeroValues(t *testing.T) { - tests := []struct { - desc string - m proto.Message - }{ - {"zero message", &pb.Message{}}, - {"empty bytes field", &pb.Message{Data: []byte{}}}, - } - for _, test := range tests { - b, err := proto.Marshal(test.m) - if err != nil { - t.Errorf("%s: proto.Marshal: %v", test.desc, err) - continue - } - if len(b) > 0 { - t.Errorf("%s: Encoding is non-empty: %q", test.desc, b) - } - } -} - -func TestRoundTripProto3(t *testing.T) { - m := &pb.Message{ - Name: "David", // (2 | 1<<3): 0x0a 0x05 "David" - Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01 - HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01 - Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto" - ResultCount: 47, // (0 | 7<<3): 0x38 0x2f - TrueScotsman: true, // (0 | 8<<3): 0x40 0x01 - Score: 8.1, // (5 | 9<<3): 0x4d <8.1> - - Key: []uint64{1, 0xdeadbeef}, - Nested: &pb.Nested{ - Bunny: "Monty", - }, - } - t.Logf(" m: %v", m) - - b, err := proto.Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal: %v", err) - } - t.Logf(" b: %q", b) - - m2 := new(pb.Message) - if err := proto.Unmarshal(b, m2); err != nil { - t.Fatalf("proto.Unmarshal: %v", err) - } - t.Logf("m2: %v", m2) - - if !proto.Equal(m, m2) { - t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2) - } -} - -func TestProto3SetDefaults(t *testing.T) { - in := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: new(tpb.SubDefaults), - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": new(tpb.SubDefaults), - }, - } - - got := proto.Clone(in).(*pb.Message) - proto.SetDefaults(got) - - // There are no defaults in proto3. Everything should be the zero value, but - // we need to remember to set defaults for nested proto2 messages. - want := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)}, - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": &tpb.SubDefaults{N: proto.Int64(7)}, - }, - } - - if !proto.Equal(got, want) { - t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/size2_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/size2_test.go deleted file mode 100644 index a2729c39..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/size2_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// 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. - -package proto - -import ( - "testing" -) - -// This is a separate file and package from size_test.go because that one uses -// generated messages and thus may not be in package proto without having a circular -// dependency, whereas this file tests unexported details of size.go. - -func TestVarintSize(t *testing.T) { - // Check the edge cases carefully. - testCases := []struct { - n uint64 - size int - }{ - {0, 1}, - {1, 1}, - {127, 1}, - {128, 2}, - {16383, 2}, - {16384, 3}, - {1<<63 - 1, 9}, - {1 << 63, 10}, - } - for _, tc := range testCases { - size := sizeVarint(tc.n) - if size != tc.size { - t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/size_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/size_test.go deleted file mode 100644 index db5614fd..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/size_test.go +++ /dev/null @@ -1,142 +0,0 @@ -// 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. - -package proto_test - -import ( - "log" - "strings" - "testing" - - . "github.com/golang/protobuf/proto" - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)} - -// messageWithExtension2 is in equal_test.go. -var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)} - -func init() { - if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - - // Force messageWithExtension3 to have the extension encoded. - Marshal(messageWithExtension3) - -} - -var SizeTests = []struct { - desc string - pb Message -}{ - {"empty", &pb.OtherMessage{}}, - // Basic types. - {"bool", &pb.Defaults{F_Bool: Bool(true)}}, - {"int32", &pb.Defaults{F_Int32: Int32(12)}}, - {"negative int32", &pb.Defaults{F_Int32: Int32(-1)}}, - {"small int64", &pb.Defaults{F_Int64: Int64(1)}}, - {"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}}, - {"negative int64", &pb.Defaults{F_Int64: Int64(-1)}}, - {"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}}, - {"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}}, - {"uint32", &pb.Defaults{F_Uint32: Uint32(123)}}, - {"uint64", &pb.Defaults{F_Uint64: Uint64(124)}}, - {"float", &pb.Defaults{F_Float: Float32(12.6)}}, - {"double", &pb.Defaults{F_Double: Float64(13.9)}}, - {"string", &pb.Defaults{F_String: String("niles")}}, - {"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}}, - {"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}}, - {"sint32", &pb.Defaults{F_Sint32: Int32(65)}}, - {"sint64", &pb.Defaults{F_Sint64: Int64(67)}}, - {"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}}, - // Repeated. - {"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}}, - {"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}}, - {"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}}, - {"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}}, - {"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}}, - {"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{ - // Need enough large numbers to verify that the header is counting the number of bytes - // for the field, not the number of elements. - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - }}}, - {"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}}, - {"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}}, - // Nested. - {"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}}, - {"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}}, - // Other things. - {"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}}, - {"extension (unencoded)", messageWithExtension1}, - {"extension (encoded)", messageWithExtension3}, - // proto3 message - {"proto3 empty", &proto3pb.Message{}}, - {"proto3 bool", &proto3pb.Message{TrueScotsman: true}}, - {"proto3 int64", &proto3pb.Message{ResultCount: 1}}, - {"proto3 uint32", &proto3pb.Message{HeightInCm: 123}}, - {"proto3 float", &proto3pb.Message{Score: 12.6}}, - {"proto3 string", &proto3pb.Message{Name: "Snezana"}}, - {"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}}, - {"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}}, - {"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, - {"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}}, - - {"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}}, - {"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: &pb.FloatingPoint{F: Float64(2.0)}}}}, - {"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}}, - {"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}}, - - {"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}}, - {"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}}, - {"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}}, -} - -func TestSize(t *testing.T) { - for _, tc := range SizeTests { - size := Size(tc.pb) - b, err := Marshal(tc.pb) - if err != nil { - t.Errorf("%v: Marshal failed: %v", tc.desc, err) - continue - } - if size != len(b) { - t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b)) - t.Logf("%v: bytes: %#v", tc.desc, b) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/Makefile b/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/Makefile deleted file mode 100644 index fc288628..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# 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. - - -include ../../Make.protobuf - -all: regenerate - -regenerate: - rm -f test.pb.go - make test.pb.go - -# The following rules are just aids to development. Not needed for typical testing. - -diff: regenerate - git diff test.pb.go - -restore: - cp test.pb.go.golden test.pb.go - -preserve: - cp test.pb.go test.pb.go.golden diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/golden_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/golden_test.go deleted file mode 100644 index 7172d0e9..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/golden_test.go +++ /dev/null @@ -1,86 +0,0 @@ -// 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. - -// Verify that the compiler output for test.proto is unchanged. - -package testdata - -import ( - "crypto/sha1" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "testing" -) - -// sum returns in string form (for easy comparison) the SHA-1 hash of the named file. -func sum(t *testing.T, name string) string { - data, err := ioutil.ReadFile(name) - if err != nil { - t.Fatal(err) - } - t.Logf("sum(%q): length is %d", name, len(data)) - hash := sha1.New() - _, err = hash.Write(data) - if err != nil { - t.Fatal(err) - } - return fmt.Sprintf("% x", hash.Sum(nil)) -} - -func run(t *testing.T, name string, args ...string) { - cmd := exec.Command(name, args...) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err := cmd.Run() - if err != nil { - t.Fatal(err) - } -} - -func TestGolden(t *testing.T) { - // Compute the original checksum. - goldenSum := sum(t, "test.pb.go") - // Run the proto compiler. - run(t, "protoc", "--go_out="+os.TempDir(), "test.proto") - newFile := filepath.Join(os.TempDir(), "test.pb.go") - defer os.Remove(newFile) - // Compute the new checksum. - newSum := sum(t, newFile) - // Verify - if newSum != goldenSum { - run(t, "diff", "-u", "test.pb.go", newFile) - t.Fatal("Code generated by protoc-gen-go has changed; update test.pb.go") - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.pb.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.pb.go deleted file mode 100644 index 13674a44..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.pb.go +++ /dev/null @@ -1,2746 +0,0 @@ -// Code generated by protoc-gen-go. -// source: test.proto -// DO NOT EDIT! - -/* -Package testdata is a generated protocol buffer package. - -It is generated from these files: - test.proto - -It has these top-level messages: - GoEnum - GoTestField - GoTest - GoSkipTest - NonPackedTest - PackedTest - MaxTag - OldMessage - NewMessage - InnerMessage - OtherMessage - MyMessage - Ext - DefaultsMessage - MyMessageSet - Empty - MessageList - Strings - Defaults - SubDefaults - RepeatedEnum - MoreRepeated - GroupOld - GroupNew - FloatingPoint - MessageWithMap -*/ -package testdata - -import proto "github.com/golang/protobuf/proto" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = math.Inf - -type FOO int32 - -const ( - FOO_FOO1 FOO = 1 -) - -var FOO_name = map[int32]string{ - 1: "FOO1", -} -var FOO_value = map[string]int32{ - "FOO1": 1, -} - -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, "FOO") - if err != nil { - return err - } - *x = FOO(value) - return nil -} - -// An enum, for completeness. -type GoTest_KIND int32 - -const ( - GoTest_VOID GoTest_KIND = 0 - // Basic types - GoTest_BOOL GoTest_KIND = 1 - GoTest_BYTES GoTest_KIND = 2 - GoTest_FINGERPRINT GoTest_KIND = 3 - GoTest_FLOAT GoTest_KIND = 4 - GoTest_INT GoTest_KIND = 5 - GoTest_STRING GoTest_KIND = 6 - GoTest_TIME GoTest_KIND = 7 - // Groupings - GoTest_TUPLE GoTest_KIND = 8 - GoTest_ARRAY GoTest_KIND = 9 - GoTest_MAP GoTest_KIND = 10 - // Table types - GoTest_TABLE GoTest_KIND = 11 - // Functions - GoTest_FUNCTION GoTest_KIND = 12 -) - -var GoTest_KIND_name = map[int32]string{ - 0: "VOID", - 1: "BOOL", - 2: "BYTES", - 3: "FINGERPRINT", - 4: "FLOAT", - 5: "INT", - 6: "STRING", - 7: "TIME", - 8: "TUPLE", - 9: "ARRAY", - 10: "MAP", - 11: "TABLE", - 12: "FUNCTION", -} -var GoTest_KIND_value = map[string]int32{ - "VOID": 0, - "BOOL": 1, - "BYTES": 2, - "FINGERPRINT": 3, - "FLOAT": 4, - "INT": 5, - "STRING": 6, - "TIME": 7, - "TUPLE": 8, - "ARRAY": 9, - "MAP": 10, - "TABLE": 11, - "FUNCTION": 12, -} - -func (x GoTest_KIND) Enum() *GoTest_KIND { - p := new(GoTest_KIND) - *p = x - return p -} -func (x GoTest_KIND) String() string { - return proto.EnumName(GoTest_KIND_name, int32(x)) -} -func (x *GoTest_KIND) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(GoTest_KIND_value, data, "GoTest_KIND") - if err != nil { - return err - } - *x = GoTest_KIND(value) - return nil -} - -type MyMessage_Color int32 - -const ( - MyMessage_RED MyMessage_Color = 0 - MyMessage_GREEN MyMessage_Color = 1 - MyMessage_BLUE MyMessage_Color = 2 -) - -var MyMessage_Color_name = map[int32]string{ - 0: "RED", - 1: "GREEN", - 2: "BLUE", -} -var MyMessage_Color_value = map[string]int32{ - "RED": 0, - "GREEN": 1, - "BLUE": 2, -} - -func (x MyMessage_Color) Enum() *MyMessage_Color { - p := new(MyMessage_Color) - *p = x - return p -} -func (x MyMessage_Color) String() string { - return proto.EnumName(MyMessage_Color_name, int32(x)) -} -func (x *MyMessage_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(MyMessage_Color_value, data, "MyMessage_Color") - if err != nil { - return err - } - *x = MyMessage_Color(value) - return nil -} - -type DefaultsMessage_DefaultsEnum int32 - -const ( - DefaultsMessage_ZERO DefaultsMessage_DefaultsEnum = 0 - DefaultsMessage_ONE DefaultsMessage_DefaultsEnum = 1 - DefaultsMessage_TWO DefaultsMessage_DefaultsEnum = 2 -) - -var DefaultsMessage_DefaultsEnum_name = map[int32]string{ - 0: "ZERO", - 1: "ONE", - 2: "TWO", -} -var DefaultsMessage_DefaultsEnum_value = map[string]int32{ - "ZERO": 0, - "ONE": 1, - "TWO": 2, -} - -func (x DefaultsMessage_DefaultsEnum) Enum() *DefaultsMessage_DefaultsEnum { - p := new(DefaultsMessage_DefaultsEnum) - *p = x - return p -} -func (x DefaultsMessage_DefaultsEnum) String() string { - return proto.EnumName(DefaultsMessage_DefaultsEnum_name, int32(x)) -} -func (x *DefaultsMessage_DefaultsEnum) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(DefaultsMessage_DefaultsEnum_value, data, "DefaultsMessage_DefaultsEnum") - if err != nil { - return err - } - *x = DefaultsMessage_DefaultsEnum(value) - return nil -} - -type Defaults_Color int32 - -const ( - Defaults_RED Defaults_Color = 0 - Defaults_GREEN Defaults_Color = 1 - Defaults_BLUE Defaults_Color = 2 -) - -var Defaults_Color_name = map[int32]string{ - 0: "RED", - 1: "GREEN", - 2: "BLUE", -} -var Defaults_Color_value = map[string]int32{ - "RED": 0, - "GREEN": 1, - "BLUE": 2, -} - -func (x Defaults_Color) Enum() *Defaults_Color { - p := new(Defaults_Color) - *p = x - return p -} -func (x Defaults_Color) String() string { - return proto.EnumName(Defaults_Color_name, int32(x)) -} -func (x *Defaults_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Defaults_Color_value, data, "Defaults_Color") - if err != nil { - return err - } - *x = Defaults_Color(value) - return nil -} - -type RepeatedEnum_Color int32 - -const ( - RepeatedEnum_RED RepeatedEnum_Color = 1 -) - -var RepeatedEnum_Color_name = map[int32]string{ - 1: "RED", -} -var RepeatedEnum_Color_value = map[string]int32{ - "RED": 1, -} - -func (x RepeatedEnum_Color) Enum() *RepeatedEnum_Color { - p := new(RepeatedEnum_Color) - *p = x - return p -} -func (x RepeatedEnum_Color) String() string { - return proto.EnumName(RepeatedEnum_Color_name, int32(x)) -} -func (x *RepeatedEnum_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(RepeatedEnum_Color_value, data, "RepeatedEnum_Color") - if err != nil { - return err - } - *x = RepeatedEnum_Color(value) - return nil -} - -type GoEnum struct { - Foo *FOO `protobuf:"varint,1,req,name=foo,enum=testdata.FOO" json:"foo,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoEnum) Reset() { *m = GoEnum{} } -func (m *GoEnum) String() string { return proto.CompactTextString(m) } -func (*GoEnum) ProtoMessage() {} - -func (m *GoEnum) GetFoo() FOO { - if m != nil && m.Foo != nil { - return *m.Foo - } - return FOO_FOO1 -} - -type GoTestField struct { - Label *string `protobuf:"bytes,1,req" json:"Label,omitempty"` - Type *string `protobuf:"bytes,2,req" json:"Type,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTestField) Reset() { *m = GoTestField{} } -func (m *GoTestField) String() string { return proto.CompactTextString(m) } -func (*GoTestField) ProtoMessage() {} - -func (m *GoTestField) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *GoTestField) GetType() string { - if m != nil && m.Type != nil { - return *m.Type - } - return "" -} - -type GoTest struct { - // Some typical parameters - Kind *GoTest_KIND `protobuf:"varint,1,req,enum=testdata.GoTest_KIND" json:"Kind,omitempty"` - Table *string `protobuf:"bytes,2,opt" json:"Table,omitempty"` - Param *int32 `protobuf:"varint,3,opt" json:"Param,omitempty"` - // Required, repeated and optional foreign fields. - RequiredField *GoTestField `protobuf:"bytes,4,req" json:"RequiredField,omitempty"` - RepeatedField []*GoTestField `protobuf:"bytes,5,rep" json:"RepeatedField,omitempty"` - OptionalField *GoTestField `protobuf:"bytes,6,opt" json:"OptionalField,omitempty"` - // Required fields of all basic types - F_BoolRequired *bool `protobuf:"varint,10,req,name=F_Bool_required" json:"F_Bool_required,omitempty"` - F_Int32Required *int32 `protobuf:"varint,11,req,name=F_Int32_required" json:"F_Int32_required,omitempty"` - F_Int64Required *int64 `protobuf:"varint,12,req,name=F_Int64_required" json:"F_Int64_required,omitempty"` - F_Fixed32Required *uint32 `protobuf:"fixed32,13,req,name=F_Fixed32_required" json:"F_Fixed32_required,omitempty"` - F_Fixed64Required *uint64 `protobuf:"fixed64,14,req,name=F_Fixed64_required" json:"F_Fixed64_required,omitempty"` - F_Uint32Required *uint32 `protobuf:"varint,15,req,name=F_Uint32_required" json:"F_Uint32_required,omitempty"` - F_Uint64Required *uint64 `protobuf:"varint,16,req,name=F_Uint64_required" json:"F_Uint64_required,omitempty"` - F_FloatRequired *float32 `protobuf:"fixed32,17,req,name=F_Float_required" json:"F_Float_required,omitempty"` - F_DoubleRequired *float64 `protobuf:"fixed64,18,req,name=F_Double_required" json:"F_Double_required,omitempty"` - F_StringRequired *string `protobuf:"bytes,19,req,name=F_String_required" json:"F_String_required,omitempty"` - F_BytesRequired []byte `protobuf:"bytes,101,req,name=F_Bytes_required" json:"F_Bytes_required,omitempty"` - F_Sint32Required *int32 `protobuf:"zigzag32,102,req,name=F_Sint32_required" json:"F_Sint32_required,omitempty"` - F_Sint64Required *int64 `protobuf:"zigzag64,103,req,name=F_Sint64_required" json:"F_Sint64_required,omitempty"` - // Repeated fields of all basic types - F_BoolRepeated []bool `protobuf:"varint,20,rep,name=F_Bool_repeated" json:"F_Bool_repeated,omitempty"` - F_Int32Repeated []int32 `protobuf:"varint,21,rep,name=F_Int32_repeated" json:"F_Int32_repeated,omitempty"` - F_Int64Repeated []int64 `protobuf:"varint,22,rep,name=F_Int64_repeated" json:"F_Int64_repeated,omitempty"` - F_Fixed32Repeated []uint32 `protobuf:"fixed32,23,rep,name=F_Fixed32_repeated" json:"F_Fixed32_repeated,omitempty"` - F_Fixed64Repeated []uint64 `protobuf:"fixed64,24,rep,name=F_Fixed64_repeated" json:"F_Fixed64_repeated,omitempty"` - F_Uint32Repeated []uint32 `protobuf:"varint,25,rep,name=F_Uint32_repeated" json:"F_Uint32_repeated,omitempty"` - F_Uint64Repeated []uint64 `protobuf:"varint,26,rep,name=F_Uint64_repeated" json:"F_Uint64_repeated,omitempty"` - F_FloatRepeated []float32 `protobuf:"fixed32,27,rep,name=F_Float_repeated" json:"F_Float_repeated,omitempty"` - F_DoubleRepeated []float64 `protobuf:"fixed64,28,rep,name=F_Double_repeated" json:"F_Double_repeated,omitempty"` - F_StringRepeated []string `protobuf:"bytes,29,rep,name=F_String_repeated" json:"F_String_repeated,omitempty"` - F_BytesRepeated [][]byte `protobuf:"bytes,201,rep,name=F_Bytes_repeated" json:"F_Bytes_repeated,omitempty"` - F_Sint32Repeated []int32 `protobuf:"zigzag32,202,rep,name=F_Sint32_repeated" json:"F_Sint32_repeated,omitempty"` - F_Sint64Repeated []int64 `protobuf:"zigzag64,203,rep,name=F_Sint64_repeated" json:"F_Sint64_repeated,omitempty"` - // Optional fields of all basic types - F_BoolOptional *bool `protobuf:"varint,30,opt,name=F_Bool_optional" json:"F_Bool_optional,omitempty"` - F_Int32Optional *int32 `protobuf:"varint,31,opt,name=F_Int32_optional" json:"F_Int32_optional,omitempty"` - F_Int64Optional *int64 `protobuf:"varint,32,opt,name=F_Int64_optional" json:"F_Int64_optional,omitempty"` - F_Fixed32Optional *uint32 `protobuf:"fixed32,33,opt,name=F_Fixed32_optional" json:"F_Fixed32_optional,omitempty"` - F_Fixed64Optional *uint64 `protobuf:"fixed64,34,opt,name=F_Fixed64_optional" json:"F_Fixed64_optional,omitempty"` - F_Uint32Optional *uint32 `protobuf:"varint,35,opt,name=F_Uint32_optional" json:"F_Uint32_optional,omitempty"` - F_Uint64Optional *uint64 `protobuf:"varint,36,opt,name=F_Uint64_optional" json:"F_Uint64_optional,omitempty"` - F_FloatOptional *float32 `protobuf:"fixed32,37,opt,name=F_Float_optional" json:"F_Float_optional,omitempty"` - F_DoubleOptional *float64 `protobuf:"fixed64,38,opt,name=F_Double_optional" json:"F_Double_optional,omitempty"` - F_StringOptional *string `protobuf:"bytes,39,opt,name=F_String_optional" json:"F_String_optional,omitempty"` - F_BytesOptional []byte `protobuf:"bytes,301,opt,name=F_Bytes_optional" json:"F_Bytes_optional,omitempty"` - F_Sint32Optional *int32 `protobuf:"zigzag32,302,opt,name=F_Sint32_optional" json:"F_Sint32_optional,omitempty"` - F_Sint64Optional *int64 `protobuf:"zigzag64,303,opt,name=F_Sint64_optional" json:"F_Sint64_optional,omitempty"` - // Default-valued fields of all basic types - F_BoolDefaulted *bool `protobuf:"varint,40,opt,name=F_Bool_defaulted,def=1" json:"F_Bool_defaulted,omitempty"` - F_Int32Defaulted *int32 `protobuf:"varint,41,opt,name=F_Int32_defaulted,def=32" json:"F_Int32_defaulted,omitempty"` - F_Int64Defaulted *int64 `protobuf:"varint,42,opt,name=F_Int64_defaulted,def=64" json:"F_Int64_defaulted,omitempty"` - F_Fixed32Defaulted *uint32 `protobuf:"fixed32,43,opt,name=F_Fixed32_defaulted,def=320" json:"F_Fixed32_defaulted,omitempty"` - F_Fixed64Defaulted *uint64 `protobuf:"fixed64,44,opt,name=F_Fixed64_defaulted,def=640" json:"F_Fixed64_defaulted,omitempty"` - F_Uint32Defaulted *uint32 `protobuf:"varint,45,opt,name=F_Uint32_defaulted,def=3200" json:"F_Uint32_defaulted,omitempty"` - F_Uint64Defaulted *uint64 `protobuf:"varint,46,opt,name=F_Uint64_defaulted,def=6400" json:"F_Uint64_defaulted,omitempty"` - F_FloatDefaulted *float32 `protobuf:"fixed32,47,opt,name=F_Float_defaulted,def=314159" json:"F_Float_defaulted,omitempty"` - F_DoubleDefaulted *float64 `protobuf:"fixed64,48,opt,name=F_Double_defaulted,def=271828" json:"F_Double_defaulted,omitempty"` - F_StringDefaulted *string `protobuf:"bytes,49,opt,name=F_String_defaulted,def=hello, \"world!\"\n" json:"F_String_defaulted,omitempty"` - F_BytesDefaulted []byte `protobuf:"bytes,401,opt,name=F_Bytes_defaulted,def=Bignose" json:"F_Bytes_defaulted,omitempty"` - F_Sint32Defaulted *int32 `protobuf:"zigzag32,402,opt,name=F_Sint32_defaulted,def=-32" json:"F_Sint32_defaulted,omitempty"` - F_Sint64Defaulted *int64 `protobuf:"zigzag64,403,opt,name=F_Sint64_defaulted,def=-64" json:"F_Sint64_defaulted,omitempty"` - // Packed repeated fields (no string or bytes). - F_BoolRepeatedPacked []bool `protobuf:"varint,50,rep,packed,name=F_Bool_repeated_packed" json:"F_Bool_repeated_packed,omitempty"` - F_Int32RepeatedPacked []int32 `protobuf:"varint,51,rep,packed,name=F_Int32_repeated_packed" json:"F_Int32_repeated_packed,omitempty"` - F_Int64RepeatedPacked []int64 `protobuf:"varint,52,rep,packed,name=F_Int64_repeated_packed" json:"F_Int64_repeated_packed,omitempty"` - F_Fixed32RepeatedPacked []uint32 `protobuf:"fixed32,53,rep,packed,name=F_Fixed32_repeated_packed" json:"F_Fixed32_repeated_packed,omitempty"` - F_Fixed64RepeatedPacked []uint64 `protobuf:"fixed64,54,rep,packed,name=F_Fixed64_repeated_packed" json:"F_Fixed64_repeated_packed,omitempty"` - F_Uint32RepeatedPacked []uint32 `protobuf:"varint,55,rep,packed,name=F_Uint32_repeated_packed" json:"F_Uint32_repeated_packed,omitempty"` - F_Uint64RepeatedPacked []uint64 `protobuf:"varint,56,rep,packed,name=F_Uint64_repeated_packed" json:"F_Uint64_repeated_packed,omitempty"` - F_FloatRepeatedPacked []float32 `protobuf:"fixed32,57,rep,packed,name=F_Float_repeated_packed" json:"F_Float_repeated_packed,omitempty"` - F_DoubleRepeatedPacked []float64 `protobuf:"fixed64,58,rep,packed,name=F_Double_repeated_packed" json:"F_Double_repeated_packed,omitempty"` - F_Sint32RepeatedPacked []int32 `protobuf:"zigzag32,502,rep,packed,name=F_Sint32_repeated_packed" json:"F_Sint32_repeated_packed,omitempty"` - F_Sint64RepeatedPacked []int64 `protobuf:"zigzag64,503,rep,packed,name=F_Sint64_repeated_packed" json:"F_Sint64_repeated_packed,omitempty"` - Requiredgroup *GoTest_RequiredGroup `protobuf:"group,70,req,name=RequiredGroup" json:"requiredgroup,omitempty"` - Repeatedgroup []*GoTest_RepeatedGroup `protobuf:"group,80,rep,name=RepeatedGroup" json:"repeatedgroup,omitempty"` - Optionalgroup *GoTest_OptionalGroup `protobuf:"group,90,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest) Reset() { *m = GoTest{} } -func (m *GoTest) String() string { return proto.CompactTextString(m) } -func (*GoTest) ProtoMessage() {} - -const Default_GoTest_F_BoolDefaulted bool = true -const Default_GoTest_F_Int32Defaulted int32 = 32 -const Default_GoTest_F_Int64Defaulted int64 = 64 -const Default_GoTest_F_Fixed32Defaulted uint32 = 320 -const Default_GoTest_F_Fixed64Defaulted uint64 = 640 -const Default_GoTest_F_Uint32Defaulted uint32 = 3200 -const Default_GoTest_F_Uint64Defaulted uint64 = 6400 -const Default_GoTest_F_FloatDefaulted float32 = 314159 -const Default_GoTest_F_DoubleDefaulted float64 = 271828 -const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n" - -var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose") - -const Default_GoTest_F_Sint32Defaulted int32 = -32 -const Default_GoTest_F_Sint64Defaulted int64 = -64 - -func (m *GoTest) GetKind() GoTest_KIND { - if m != nil && m.Kind != nil { - return *m.Kind - } - return GoTest_VOID -} - -func (m *GoTest) GetTable() string { - if m != nil && m.Table != nil { - return *m.Table - } - return "" -} - -func (m *GoTest) GetParam() int32 { - if m != nil && m.Param != nil { - return *m.Param - } - return 0 -} - -func (m *GoTest) GetRequiredField() *GoTestField { - if m != nil { - return m.RequiredField - } - return nil -} - -func (m *GoTest) GetRepeatedField() []*GoTestField { - if m != nil { - return m.RepeatedField - } - return nil -} - -func (m *GoTest) GetOptionalField() *GoTestField { - if m != nil { - return m.OptionalField - } - return nil -} - -func (m *GoTest) GetF_BoolRequired() bool { - if m != nil && m.F_BoolRequired != nil { - return *m.F_BoolRequired - } - return false -} - -func (m *GoTest) GetF_Int32Required() int32 { - if m != nil && m.F_Int32Required != nil { - return *m.F_Int32Required - } - return 0 -} - -func (m *GoTest) GetF_Int64Required() int64 { - if m != nil && m.F_Int64Required != nil { - return *m.F_Int64Required - } - return 0 -} - -func (m *GoTest) GetF_Fixed32Required() uint32 { - if m != nil && m.F_Fixed32Required != nil { - return *m.F_Fixed32Required - } - return 0 -} - -func (m *GoTest) GetF_Fixed64Required() uint64 { - if m != nil && m.F_Fixed64Required != nil { - return *m.F_Fixed64Required - } - return 0 -} - -func (m *GoTest) GetF_Uint32Required() uint32 { - if m != nil && m.F_Uint32Required != nil { - return *m.F_Uint32Required - } - return 0 -} - -func (m *GoTest) GetF_Uint64Required() uint64 { - if m != nil && m.F_Uint64Required != nil { - return *m.F_Uint64Required - } - return 0 -} - -func (m *GoTest) GetF_FloatRequired() float32 { - if m != nil && m.F_FloatRequired != nil { - return *m.F_FloatRequired - } - return 0 -} - -func (m *GoTest) GetF_DoubleRequired() float64 { - if m != nil && m.F_DoubleRequired != nil { - return *m.F_DoubleRequired - } - return 0 -} - -func (m *GoTest) GetF_StringRequired() string { - if m != nil && m.F_StringRequired != nil { - return *m.F_StringRequired - } - return "" -} - -func (m *GoTest) GetF_BytesRequired() []byte { - if m != nil { - return m.F_BytesRequired - } - return nil -} - -func (m *GoTest) GetF_Sint32Required() int32 { - if m != nil && m.F_Sint32Required != nil { - return *m.F_Sint32Required - } - return 0 -} - -func (m *GoTest) GetF_Sint64Required() int64 { - if m != nil && m.F_Sint64Required != nil { - return *m.F_Sint64Required - } - return 0 -} - -func (m *GoTest) GetF_BoolRepeated() []bool { - if m != nil { - return m.F_BoolRepeated - } - return nil -} - -func (m *GoTest) GetF_Int32Repeated() []int32 { - if m != nil { - return m.F_Int32Repeated - } - return nil -} - -func (m *GoTest) GetF_Int64Repeated() []int64 { - if m != nil { - return m.F_Int64Repeated - } - return nil -} - -func (m *GoTest) GetF_Fixed32Repeated() []uint32 { - if m != nil { - return m.F_Fixed32Repeated - } - return nil -} - -func (m *GoTest) GetF_Fixed64Repeated() []uint64 { - if m != nil { - return m.F_Fixed64Repeated - } - return nil -} - -func (m *GoTest) GetF_Uint32Repeated() []uint32 { - if m != nil { - return m.F_Uint32Repeated - } - return nil -} - -func (m *GoTest) GetF_Uint64Repeated() []uint64 { - if m != nil { - return m.F_Uint64Repeated - } - return nil -} - -func (m *GoTest) GetF_FloatRepeated() []float32 { - if m != nil { - return m.F_FloatRepeated - } - return nil -} - -func (m *GoTest) GetF_DoubleRepeated() []float64 { - if m != nil { - return m.F_DoubleRepeated - } - return nil -} - -func (m *GoTest) GetF_StringRepeated() []string { - if m != nil { - return m.F_StringRepeated - } - return nil -} - -func (m *GoTest) GetF_BytesRepeated() [][]byte { - if m != nil { - return m.F_BytesRepeated - } - return nil -} - -func (m *GoTest) GetF_Sint32Repeated() []int32 { - if m != nil { - return m.F_Sint32Repeated - } - return nil -} - -func (m *GoTest) GetF_Sint64Repeated() []int64 { - if m != nil { - return m.F_Sint64Repeated - } - return nil -} - -func (m *GoTest) GetF_BoolOptional() bool { - if m != nil && m.F_BoolOptional != nil { - return *m.F_BoolOptional - } - return false -} - -func (m *GoTest) GetF_Int32Optional() int32 { - if m != nil && m.F_Int32Optional != nil { - return *m.F_Int32Optional - } - return 0 -} - -func (m *GoTest) GetF_Int64Optional() int64 { - if m != nil && m.F_Int64Optional != nil { - return *m.F_Int64Optional - } - return 0 -} - -func (m *GoTest) GetF_Fixed32Optional() uint32 { - if m != nil && m.F_Fixed32Optional != nil { - return *m.F_Fixed32Optional - } - return 0 -} - -func (m *GoTest) GetF_Fixed64Optional() uint64 { - if m != nil && m.F_Fixed64Optional != nil { - return *m.F_Fixed64Optional - } - return 0 -} - -func (m *GoTest) GetF_Uint32Optional() uint32 { - if m != nil && m.F_Uint32Optional != nil { - return *m.F_Uint32Optional - } - return 0 -} - -func (m *GoTest) GetF_Uint64Optional() uint64 { - if m != nil && m.F_Uint64Optional != nil { - return *m.F_Uint64Optional - } - return 0 -} - -func (m *GoTest) GetF_FloatOptional() float32 { - if m != nil && m.F_FloatOptional != nil { - return *m.F_FloatOptional - } - return 0 -} - -func (m *GoTest) GetF_DoubleOptional() float64 { - if m != nil && m.F_DoubleOptional != nil { - return *m.F_DoubleOptional - } - return 0 -} - -func (m *GoTest) GetF_StringOptional() string { - if m != nil && m.F_StringOptional != nil { - return *m.F_StringOptional - } - return "" -} - -func (m *GoTest) GetF_BytesOptional() []byte { - if m != nil { - return m.F_BytesOptional - } - return nil -} - -func (m *GoTest) GetF_Sint32Optional() int32 { - if m != nil && m.F_Sint32Optional != nil { - return *m.F_Sint32Optional - } - return 0 -} - -func (m *GoTest) GetF_Sint64Optional() int64 { - if m != nil && m.F_Sint64Optional != nil { - return *m.F_Sint64Optional - } - return 0 -} - -func (m *GoTest) GetF_BoolDefaulted() bool { - if m != nil && m.F_BoolDefaulted != nil { - return *m.F_BoolDefaulted - } - return Default_GoTest_F_BoolDefaulted -} - -func (m *GoTest) GetF_Int32Defaulted() int32 { - if m != nil && m.F_Int32Defaulted != nil { - return *m.F_Int32Defaulted - } - return Default_GoTest_F_Int32Defaulted -} - -func (m *GoTest) GetF_Int64Defaulted() int64 { - if m != nil && m.F_Int64Defaulted != nil { - return *m.F_Int64Defaulted - } - return Default_GoTest_F_Int64Defaulted -} - -func (m *GoTest) GetF_Fixed32Defaulted() uint32 { - if m != nil && m.F_Fixed32Defaulted != nil { - return *m.F_Fixed32Defaulted - } - return Default_GoTest_F_Fixed32Defaulted -} - -func (m *GoTest) GetF_Fixed64Defaulted() uint64 { - if m != nil && m.F_Fixed64Defaulted != nil { - return *m.F_Fixed64Defaulted - } - return Default_GoTest_F_Fixed64Defaulted -} - -func (m *GoTest) GetF_Uint32Defaulted() uint32 { - if m != nil && m.F_Uint32Defaulted != nil { - return *m.F_Uint32Defaulted - } - return Default_GoTest_F_Uint32Defaulted -} - -func (m *GoTest) GetF_Uint64Defaulted() uint64 { - if m != nil && m.F_Uint64Defaulted != nil { - return *m.F_Uint64Defaulted - } - return Default_GoTest_F_Uint64Defaulted -} - -func (m *GoTest) GetF_FloatDefaulted() float32 { - if m != nil && m.F_FloatDefaulted != nil { - return *m.F_FloatDefaulted - } - return Default_GoTest_F_FloatDefaulted -} - -func (m *GoTest) GetF_DoubleDefaulted() float64 { - if m != nil && m.F_DoubleDefaulted != nil { - return *m.F_DoubleDefaulted - } - return Default_GoTest_F_DoubleDefaulted -} - -func (m *GoTest) GetF_StringDefaulted() string { - if m != nil && m.F_StringDefaulted != nil { - return *m.F_StringDefaulted - } - return Default_GoTest_F_StringDefaulted -} - -func (m *GoTest) GetF_BytesDefaulted() []byte { - if m != nil && m.F_BytesDefaulted != nil { - return m.F_BytesDefaulted - } - return append([]byte(nil), Default_GoTest_F_BytesDefaulted...) -} - -func (m *GoTest) GetF_Sint32Defaulted() int32 { - if m != nil && m.F_Sint32Defaulted != nil { - return *m.F_Sint32Defaulted - } - return Default_GoTest_F_Sint32Defaulted -} - -func (m *GoTest) GetF_Sint64Defaulted() int64 { - if m != nil && m.F_Sint64Defaulted != nil { - return *m.F_Sint64Defaulted - } - return Default_GoTest_F_Sint64Defaulted -} - -func (m *GoTest) GetF_BoolRepeatedPacked() []bool { - if m != nil { - return m.F_BoolRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Int32RepeatedPacked() []int32 { - if m != nil { - return m.F_Int32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Int64RepeatedPacked() []int64 { - if m != nil { - return m.F_Int64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Fixed32RepeatedPacked() []uint32 { - if m != nil { - return m.F_Fixed32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Fixed64RepeatedPacked() []uint64 { - if m != nil { - return m.F_Fixed64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Uint32RepeatedPacked() []uint32 { - if m != nil { - return m.F_Uint32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Uint64RepeatedPacked() []uint64 { - if m != nil { - return m.F_Uint64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_FloatRepeatedPacked() []float32 { - if m != nil { - return m.F_FloatRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_DoubleRepeatedPacked() []float64 { - if m != nil { - return m.F_DoubleRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Sint32RepeatedPacked() []int32 { - if m != nil { - return m.F_Sint32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Sint64RepeatedPacked() []int64 { - if m != nil { - return m.F_Sint64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetRequiredgroup() *GoTest_RequiredGroup { - if m != nil { - return m.Requiredgroup - } - return nil -} - -func (m *GoTest) GetRepeatedgroup() []*GoTest_RepeatedGroup { - if m != nil { - return m.Repeatedgroup - } - return nil -} - -func (m *GoTest) GetOptionalgroup() *GoTest_OptionalGroup { - if m != nil { - return m.Optionalgroup - } - return nil -} - -// Required, repeated, and optional groups. -type GoTest_RequiredGroup struct { - RequiredField *string `protobuf:"bytes,71,req" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_RequiredGroup) Reset() { *m = GoTest_RequiredGroup{} } -func (m *GoTest_RequiredGroup) String() string { return proto.CompactTextString(m) } -func (*GoTest_RequiredGroup) ProtoMessage() {} - -func (m *GoTest_RequiredGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -type GoTest_RepeatedGroup struct { - RequiredField *string `protobuf:"bytes,81,req" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_RepeatedGroup) Reset() { *m = GoTest_RepeatedGroup{} } -func (m *GoTest_RepeatedGroup) String() string { return proto.CompactTextString(m) } -func (*GoTest_RepeatedGroup) ProtoMessage() {} - -func (m *GoTest_RepeatedGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -type GoTest_OptionalGroup struct { - RequiredField *string `protobuf:"bytes,91,req" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_OptionalGroup) Reset() { *m = GoTest_OptionalGroup{} } -func (m *GoTest_OptionalGroup) String() string { return proto.CompactTextString(m) } -func (*GoTest_OptionalGroup) ProtoMessage() {} - -func (m *GoTest_OptionalGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -// For testing skipping of unrecognized fields. -// Numbers are all big, larger than tag numbers in GoTestField, -// the message used in the corresponding test. -type GoSkipTest struct { - SkipInt32 *int32 `protobuf:"varint,11,req,name=skip_int32" json:"skip_int32,omitempty"` - SkipFixed32 *uint32 `protobuf:"fixed32,12,req,name=skip_fixed32" json:"skip_fixed32,omitempty"` - SkipFixed64 *uint64 `protobuf:"fixed64,13,req,name=skip_fixed64" json:"skip_fixed64,omitempty"` - SkipString *string `protobuf:"bytes,14,req,name=skip_string" json:"skip_string,omitempty"` - Skipgroup *GoSkipTest_SkipGroup `protobuf:"group,15,req,name=SkipGroup" json:"skipgroup,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoSkipTest) Reset() { *m = GoSkipTest{} } -func (m *GoSkipTest) String() string { return proto.CompactTextString(m) } -func (*GoSkipTest) ProtoMessage() {} - -func (m *GoSkipTest) GetSkipInt32() int32 { - if m != nil && m.SkipInt32 != nil { - return *m.SkipInt32 - } - return 0 -} - -func (m *GoSkipTest) GetSkipFixed32() uint32 { - if m != nil && m.SkipFixed32 != nil { - return *m.SkipFixed32 - } - return 0 -} - -func (m *GoSkipTest) GetSkipFixed64() uint64 { - if m != nil && m.SkipFixed64 != nil { - return *m.SkipFixed64 - } - return 0 -} - -func (m *GoSkipTest) GetSkipString() string { - if m != nil && m.SkipString != nil { - return *m.SkipString - } - return "" -} - -func (m *GoSkipTest) GetSkipgroup() *GoSkipTest_SkipGroup { - if m != nil { - return m.Skipgroup - } - return nil -} - -type GoSkipTest_SkipGroup struct { - GroupInt32 *int32 `protobuf:"varint,16,req,name=group_int32" json:"group_int32,omitempty"` - GroupString *string `protobuf:"bytes,17,req,name=group_string" json:"group_string,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoSkipTest_SkipGroup) Reset() { *m = GoSkipTest_SkipGroup{} } -func (m *GoSkipTest_SkipGroup) String() string { return proto.CompactTextString(m) } -func (*GoSkipTest_SkipGroup) ProtoMessage() {} - -func (m *GoSkipTest_SkipGroup) GetGroupInt32() int32 { - if m != nil && m.GroupInt32 != nil { - return *m.GroupInt32 - } - return 0 -} - -func (m *GoSkipTest_SkipGroup) GetGroupString() string { - if m != nil && m.GroupString != nil { - return *m.GroupString - } - return "" -} - -// For testing packed/non-packed decoder switching. -// A serialized instance of one should be deserializable as the other. -type NonPackedTest struct { - A []int32 `protobuf:"varint,1,rep,name=a" json:"a,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NonPackedTest) Reset() { *m = NonPackedTest{} } -func (m *NonPackedTest) String() string { return proto.CompactTextString(m) } -func (*NonPackedTest) ProtoMessage() {} - -func (m *NonPackedTest) GetA() []int32 { - if m != nil { - return m.A - } - return nil -} - -type PackedTest struct { - B []int32 `protobuf:"varint,1,rep,packed,name=b" json:"b,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PackedTest) Reset() { *m = PackedTest{} } -func (m *PackedTest) String() string { return proto.CompactTextString(m) } -func (*PackedTest) ProtoMessage() {} - -func (m *PackedTest) GetB() []int32 { - if m != nil { - return m.B - } - return nil -} - -type MaxTag struct { - // Maximum possible tag number. - LastField *string `protobuf:"bytes,536870911,opt,name=last_field" json:"last_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MaxTag) Reset() { *m = MaxTag{} } -func (m *MaxTag) String() string { return proto.CompactTextString(m) } -func (*MaxTag) ProtoMessage() {} - -func (m *MaxTag) GetLastField() string { - if m != nil && m.LastField != nil { - return *m.LastField - } - return "" -} - -type OldMessage struct { - Nested *OldMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` - Num *int32 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OldMessage) Reset() { *m = OldMessage{} } -func (m *OldMessage) String() string { return proto.CompactTextString(m) } -func (*OldMessage) ProtoMessage() {} - -func (m *OldMessage) GetNested() *OldMessage_Nested { - if m != nil { - return m.Nested - } - return nil -} - -func (m *OldMessage) GetNum() int32 { - if m != nil && m.Num != nil { - return *m.Num - } - return 0 -} - -type OldMessage_Nested struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OldMessage_Nested) Reset() { *m = OldMessage_Nested{} } -func (m *OldMessage_Nested) String() string { return proto.CompactTextString(m) } -func (*OldMessage_Nested) ProtoMessage() {} - -func (m *OldMessage_Nested) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -// NewMessage is wire compatible with OldMessage; -// imagine it as a future version. -type NewMessage struct { - Nested *NewMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` - // This is an int32 in OldMessage. - Num *int64 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NewMessage) Reset() { *m = NewMessage{} } -func (m *NewMessage) String() string { return proto.CompactTextString(m) } -func (*NewMessage) ProtoMessage() {} - -func (m *NewMessage) GetNested() *NewMessage_Nested { - if m != nil { - return m.Nested - } - return nil -} - -func (m *NewMessage) GetNum() int64 { - if m != nil && m.Num != nil { - return *m.Num - } - return 0 -} - -type NewMessage_Nested struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - FoodGroup *string `protobuf:"bytes,2,opt,name=food_group" json:"food_group,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NewMessage_Nested) Reset() { *m = NewMessage_Nested{} } -func (m *NewMessage_Nested) String() string { return proto.CompactTextString(m) } -func (*NewMessage_Nested) ProtoMessage() {} - -func (m *NewMessage_Nested) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *NewMessage_Nested) GetFoodGroup() string { - if m != nil && m.FoodGroup != nil { - return *m.FoodGroup - } - return "" -} - -type InnerMessage struct { - Host *string `protobuf:"bytes,1,req,name=host" json:"host,omitempty"` - Port *int32 `protobuf:"varint,2,opt,name=port,def=4000" json:"port,omitempty"` - Connected *bool `protobuf:"varint,3,opt,name=connected" json:"connected,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *InnerMessage) Reset() { *m = InnerMessage{} } -func (m *InnerMessage) String() string { return proto.CompactTextString(m) } -func (*InnerMessage) ProtoMessage() {} - -const Default_InnerMessage_Port int32 = 4000 - -func (m *InnerMessage) GetHost() string { - if m != nil && m.Host != nil { - return *m.Host - } - return "" -} - -func (m *InnerMessage) GetPort() int32 { - if m != nil && m.Port != nil { - return *m.Port - } - return Default_InnerMessage_Port -} - -func (m *InnerMessage) GetConnected() bool { - if m != nil && m.Connected != nil { - return *m.Connected - } - return false -} - -type OtherMessage struct { - Key *int64 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` - Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - Weight *float32 `protobuf:"fixed32,3,opt,name=weight" json:"weight,omitempty"` - Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner" json:"inner,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OtherMessage) Reset() { *m = OtherMessage{} } -func (m *OtherMessage) String() string { return proto.CompactTextString(m) } -func (*OtherMessage) ProtoMessage() {} - -func (m *OtherMessage) GetKey() int64 { - if m != nil && m.Key != nil { - return *m.Key - } - return 0 -} - -func (m *OtherMessage) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -func (m *OtherMessage) GetWeight() float32 { - if m != nil && m.Weight != nil { - return *m.Weight - } - return 0 -} - -func (m *OtherMessage) GetInner() *InnerMessage { - if m != nil { - return m.Inner - } - return nil -} - -type MyMessage struct { - Count *int32 `protobuf:"varint,1,req,name=count" json:"count,omitempty"` - Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` - Quote *string `protobuf:"bytes,3,opt,name=quote" json:"quote,omitempty"` - Pet []string `protobuf:"bytes,4,rep,name=pet" json:"pet,omitempty"` - Inner *InnerMessage `protobuf:"bytes,5,opt,name=inner" json:"inner,omitempty"` - Others []*OtherMessage `protobuf:"bytes,6,rep,name=others" json:"others,omitempty"` - RepInner []*InnerMessage `protobuf:"bytes,12,rep,name=rep_inner" json:"rep_inner,omitempty"` - Bikeshed *MyMessage_Color `protobuf:"varint,7,opt,name=bikeshed,enum=testdata.MyMessage_Color" json:"bikeshed,omitempty"` - Somegroup *MyMessage_SomeGroup `protobuf:"group,8,opt,name=SomeGroup" json:"somegroup,omitempty"` - // This field becomes [][]byte in the generated code. - RepBytes [][]byte `protobuf:"bytes,10,rep,name=rep_bytes" json:"rep_bytes,omitempty"` - Bigfloat *float64 `protobuf:"fixed64,11,opt,name=bigfloat" json:"bigfloat,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessage) Reset() { *m = MyMessage{} } -func (m *MyMessage) String() string { return proto.CompactTextString(m) } -func (*MyMessage) ProtoMessage() {} - -var extRange_MyMessage = []proto.ExtensionRange{ - {100, 536870911}, -} - -func (*MyMessage) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_MyMessage -} -func (m *MyMessage) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -func (m *MyMessage) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -func (m *MyMessage) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *MyMessage) GetQuote() string { - if m != nil && m.Quote != nil { - return *m.Quote - } - return "" -} - -func (m *MyMessage) GetPet() []string { - if m != nil { - return m.Pet - } - return nil -} - -func (m *MyMessage) GetInner() *InnerMessage { - if m != nil { - return m.Inner - } - return nil -} - -func (m *MyMessage) GetOthers() []*OtherMessage { - if m != nil { - return m.Others - } - return nil -} - -func (m *MyMessage) GetRepInner() []*InnerMessage { - if m != nil { - return m.RepInner - } - return nil -} - -func (m *MyMessage) GetBikeshed() MyMessage_Color { - if m != nil && m.Bikeshed != nil { - return *m.Bikeshed - } - return MyMessage_RED -} - -func (m *MyMessage) GetSomegroup() *MyMessage_SomeGroup { - if m != nil { - return m.Somegroup - } - return nil -} - -func (m *MyMessage) GetRepBytes() [][]byte { - if m != nil { - return m.RepBytes - } - return nil -} - -func (m *MyMessage) GetBigfloat() float64 { - if m != nil && m.Bigfloat != nil { - return *m.Bigfloat - } - return 0 -} - -type MyMessage_SomeGroup struct { - GroupField *int32 `protobuf:"varint,9,opt,name=group_field" json:"group_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessage_SomeGroup) Reset() { *m = MyMessage_SomeGroup{} } -func (m *MyMessage_SomeGroup) String() string { return proto.CompactTextString(m) } -func (*MyMessage_SomeGroup) ProtoMessage() {} - -func (m *MyMessage_SomeGroup) GetGroupField() int32 { - if m != nil && m.GroupField != nil { - return *m.GroupField - } - return 0 -} - -type Ext struct { - Data *string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Ext) Reset() { *m = Ext{} } -func (m *Ext) String() string { return proto.CompactTextString(m) } -func (*Ext) ProtoMessage() {} - -func (m *Ext) GetData() string { - if m != nil && m.Data != nil { - return *m.Data - } - return "" -} - -var E_Ext_More = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*Ext)(nil), - Field: 103, - Name: "testdata.Ext.more", - Tag: "bytes,103,opt,name=more", -} - -var E_Ext_Text = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*string)(nil), - Field: 104, - Name: "testdata.Ext.text", - Tag: "bytes,104,opt,name=text", -} - -var E_Ext_Number = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 105, - Name: "testdata.Ext.number", - Tag: "varint,105,opt,name=number", -} - -type DefaultsMessage struct { - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DefaultsMessage) Reset() { *m = DefaultsMessage{} } -func (m *DefaultsMessage) String() string { return proto.CompactTextString(m) } -func (*DefaultsMessage) ProtoMessage() {} - -var extRange_DefaultsMessage = []proto.ExtensionRange{ - {100, 536870911}, -} - -func (*DefaultsMessage) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_DefaultsMessage -} -func (m *DefaultsMessage) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -type MyMessageSet struct { - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessageSet) Reset() { *m = MyMessageSet{} } -func (m *MyMessageSet) String() string { return proto.CompactTextString(m) } -func (*MyMessageSet) ProtoMessage() {} - -func (m *MyMessageSet) Marshal() ([]byte, error) { - return proto.MarshalMessageSet(m.ExtensionMap()) -} -func (m *MyMessageSet) Unmarshal(buf []byte) error { - return proto.UnmarshalMessageSet(buf, m.ExtensionMap()) -} -func (m *MyMessageSet) MarshalJSON() ([]byte, error) { - return proto.MarshalMessageSetJSON(m.XXX_extensions) -} -func (m *MyMessageSet) UnmarshalJSON(buf []byte) error { - return proto.UnmarshalMessageSetJSON(buf, m.XXX_extensions) -} - -// ensure MyMessageSet satisfies proto.Marshaler and proto.Unmarshaler -var _ proto.Marshaler = (*MyMessageSet)(nil) -var _ proto.Unmarshaler = (*MyMessageSet)(nil) - -var extRange_MyMessageSet = []proto.ExtensionRange{ - {100, 2147483646}, -} - -func (*MyMessageSet) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_MyMessageSet -} -func (m *MyMessageSet) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -type Empty struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *Empty) Reset() { *m = Empty{} } -func (m *Empty) String() string { return proto.CompactTextString(m) } -func (*Empty) ProtoMessage() {} - -type MessageList struct { - Message []*MessageList_Message `protobuf:"group,1,rep" json:"message,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageList) Reset() { *m = MessageList{} } -func (m *MessageList) String() string { return proto.CompactTextString(m) } -func (*MessageList) ProtoMessage() {} - -func (m *MessageList) GetMessage() []*MessageList_Message { - if m != nil { - return m.Message - } - return nil -} - -type MessageList_Message struct { - Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"` - Count *int32 `protobuf:"varint,3,req,name=count" json:"count,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageList_Message) Reset() { *m = MessageList_Message{} } -func (m *MessageList_Message) String() string { return proto.CompactTextString(m) } -func (*MessageList_Message) ProtoMessage() {} - -func (m *MessageList_Message) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *MessageList_Message) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -type Strings struct { - StringField *string `protobuf:"bytes,1,opt,name=string_field" json:"string_field,omitempty"` - BytesField []byte `protobuf:"bytes,2,opt,name=bytes_field" json:"bytes_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Strings) Reset() { *m = Strings{} } -func (m *Strings) String() string { return proto.CompactTextString(m) } -func (*Strings) ProtoMessage() {} - -func (m *Strings) GetStringField() string { - if m != nil && m.StringField != nil { - return *m.StringField - } - return "" -} - -func (m *Strings) GetBytesField() []byte { - if m != nil { - return m.BytesField - } - return nil -} - -type Defaults struct { - // Default-valued fields of all basic types. - // Same as GoTest, but copied here to make testing easier. - F_Bool *bool `protobuf:"varint,1,opt,def=1" json:"F_Bool,omitempty"` - F_Int32 *int32 `protobuf:"varint,2,opt,def=32" json:"F_Int32,omitempty"` - F_Int64 *int64 `protobuf:"varint,3,opt,def=64" json:"F_Int64,omitempty"` - F_Fixed32 *uint32 `protobuf:"fixed32,4,opt,def=320" json:"F_Fixed32,omitempty"` - F_Fixed64 *uint64 `protobuf:"fixed64,5,opt,def=640" json:"F_Fixed64,omitempty"` - F_Uint32 *uint32 `protobuf:"varint,6,opt,def=3200" json:"F_Uint32,omitempty"` - F_Uint64 *uint64 `protobuf:"varint,7,opt,def=6400" json:"F_Uint64,omitempty"` - F_Float *float32 `protobuf:"fixed32,8,opt,def=314159" json:"F_Float,omitempty"` - F_Double *float64 `protobuf:"fixed64,9,opt,def=271828" json:"F_Double,omitempty"` - F_String *string `protobuf:"bytes,10,opt,def=hello, \"world!\"\n" json:"F_String,omitempty"` - F_Bytes []byte `protobuf:"bytes,11,opt,def=Bignose" json:"F_Bytes,omitempty"` - F_Sint32 *int32 `protobuf:"zigzag32,12,opt,def=-32" json:"F_Sint32,omitempty"` - F_Sint64 *int64 `protobuf:"zigzag64,13,opt,def=-64" json:"F_Sint64,omitempty"` - F_Enum *Defaults_Color `protobuf:"varint,14,opt,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"` - // More fields with crazy defaults. - F_Pinf *float32 `protobuf:"fixed32,15,opt,def=inf" json:"F_Pinf,omitempty"` - F_Ninf *float32 `protobuf:"fixed32,16,opt,def=-inf" json:"F_Ninf,omitempty"` - F_Nan *float32 `protobuf:"fixed32,17,opt,def=nan" json:"F_Nan,omitempty"` - // Sub-message. - Sub *SubDefaults `protobuf:"bytes,18,opt,name=sub" json:"sub,omitempty"` - // Redundant but explicit defaults. - StrZero *string `protobuf:"bytes,19,opt,name=str_zero,def=" json:"str_zero,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Defaults) Reset() { *m = Defaults{} } -func (m *Defaults) String() string { return proto.CompactTextString(m) } -func (*Defaults) ProtoMessage() {} - -const Default_Defaults_F_Bool bool = true -const Default_Defaults_F_Int32 int32 = 32 -const Default_Defaults_F_Int64 int64 = 64 -const Default_Defaults_F_Fixed32 uint32 = 320 -const Default_Defaults_F_Fixed64 uint64 = 640 -const Default_Defaults_F_Uint32 uint32 = 3200 -const Default_Defaults_F_Uint64 uint64 = 6400 -const Default_Defaults_F_Float float32 = 314159 -const Default_Defaults_F_Double float64 = 271828 -const Default_Defaults_F_String string = "hello, \"world!\"\n" - -var Default_Defaults_F_Bytes []byte = []byte("Bignose") - -const Default_Defaults_F_Sint32 int32 = -32 -const Default_Defaults_F_Sint64 int64 = -64 -const Default_Defaults_F_Enum Defaults_Color = Defaults_GREEN - -var Default_Defaults_F_Pinf float32 = float32(math.Inf(1)) -var Default_Defaults_F_Ninf float32 = float32(math.Inf(-1)) -var Default_Defaults_F_Nan float32 = float32(math.NaN()) - -func (m *Defaults) GetF_Bool() bool { - if m != nil && m.F_Bool != nil { - return *m.F_Bool - } - return Default_Defaults_F_Bool -} - -func (m *Defaults) GetF_Int32() int32 { - if m != nil && m.F_Int32 != nil { - return *m.F_Int32 - } - return Default_Defaults_F_Int32 -} - -func (m *Defaults) GetF_Int64() int64 { - if m != nil && m.F_Int64 != nil { - return *m.F_Int64 - } - return Default_Defaults_F_Int64 -} - -func (m *Defaults) GetF_Fixed32() uint32 { - if m != nil && m.F_Fixed32 != nil { - return *m.F_Fixed32 - } - return Default_Defaults_F_Fixed32 -} - -func (m *Defaults) GetF_Fixed64() uint64 { - if m != nil && m.F_Fixed64 != nil { - return *m.F_Fixed64 - } - return Default_Defaults_F_Fixed64 -} - -func (m *Defaults) GetF_Uint32() uint32 { - if m != nil && m.F_Uint32 != nil { - return *m.F_Uint32 - } - return Default_Defaults_F_Uint32 -} - -func (m *Defaults) GetF_Uint64() uint64 { - if m != nil && m.F_Uint64 != nil { - return *m.F_Uint64 - } - return Default_Defaults_F_Uint64 -} - -func (m *Defaults) GetF_Float() float32 { - if m != nil && m.F_Float != nil { - return *m.F_Float - } - return Default_Defaults_F_Float -} - -func (m *Defaults) GetF_Double() float64 { - if m != nil && m.F_Double != nil { - return *m.F_Double - } - return Default_Defaults_F_Double -} - -func (m *Defaults) GetF_String() string { - if m != nil && m.F_String != nil { - return *m.F_String - } - return Default_Defaults_F_String -} - -func (m *Defaults) GetF_Bytes() []byte { - if m != nil && m.F_Bytes != nil { - return m.F_Bytes - } - return append([]byte(nil), Default_Defaults_F_Bytes...) -} - -func (m *Defaults) GetF_Sint32() int32 { - if m != nil && m.F_Sint32 != nil { - return *m.F_Sint32 - } - return Default_Defaults_F_Sint32 -} - -func (m *Defaults) GetF_Sint64() int64 { - if m != nil && m.F_Sint64 != nil { - return *m.F_Sint64 - } - return Default_Defaults_F_Sint64 -} - -func (m *Defaults) GetF_Enum() Defaults_Color { - if m != nil && m.F_Enum != nil { - return *m.F_Enum - } - return Default_Defaults_F_Enum -} - -func (m *Defaults) GetF_Pinf() float32 { - if m != nil && m.F_Pinf != nil { - return *m.F_Pinf - } - return Default_Defaults_F_Pinf -} - -func (m *Defaults) GetF_Ninf() float32 { - if m != nil && m.F_Ninf != nil { - return *m.F_Ninf - } - return Default_Defaults_F_Ninf -} - -func (m *Defaults) GetF_Nan() float32 { - if m != nil && m.F_Nan != nil { - return *m.F_Nan - } - return Default_Defaults_F_Nan -} - -func (m *Defaults) GetSub() *SubDefaults { - if m != nil { - return m.Sub - } - return nil -} - -func (m *Defaults) GetStrZero() string { - if m != nil && m.StrZero != nil { - return *m.StrZero - } - return "" -} - -type SubDefaults struct { - N *int64 `protobuf:"varint,1,opt,name=n,def=7" json:"n,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SubDefaults) Reset() { *m = SubDefaults{} } -func (m *SubDefaults) String() string { return proto.CompactTextString(m) } -func (*SubDefaults) ProtoMessage() {} - -const Default_SubDefaults_N int64 = 7 - -func (m *SubDefaults) GetN() int64 { - if m != nil && m.N != nil { - return *m.N - } - return Default_SubDefaults_N -} - -type RepeatedEnum struct { - Color []RepeatedEnum_Color `protobuf:"varint,1,rep,name=color,enum=testdata.RepeatedEnum_Color" json:"color,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RepeatedEnum) Reset() { *m = RepeatedEnum{} } -func (m *RepeatedEnum) String() string { return proto.CompactTextString(m) } -func (*RepeatedEnum) ProtoMessage() {} - -func (m *RepeatedEnum) GetColor() []RepeatedEnum_Color { - if m != nil { - return m.Color - } - return nil -} - -type MoreRepeated struct { - Bools []bool `protobuf:"varint,1,rep,name=bools" json:"bools,omitempty"` - BoolsPacked []bool `protobuf:"varint,2,rep,packed,name=bools_packed" json:"bools_packed,omitempty"` - Ints []int32 `protobuf:"varint,3,rep,name=ints" json:"ints,omitempty"` - IntsPacked []int32 `protobuf:"varint,4,rep,packed,name=ints_packed" json:"ints_packed,omitempty"` - Int64SPacked []int64 `protobuf:"varint,7,rep,packed,name=int64s_packed" json:"int64s_packed,omitempty"` - Strings []string `protobuf:"bytes,5,rep,name=strings" json:"strings,omitempty"` - Fixeds []uint32 `protobuf:"fixed32,6,rep,name=fixeds" json:"fixeds,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MoreRepeated) Reset() { *m = MoreRepeated{} } -func (m *MoreRepeated) String() string { return proto.CompactTextString(m) } -func (*MoreRepeated) ProtoMessage() {} - -func (m *MoreRepeated) GetBools() []bool { - if m != nil { - return m.Bools - } - return nil -} - -func (m *MoreRepeated) GetBoolsPacked() []bool { - if m != nil { - return m.BoolsPacked - } - return nil -} - -func (m *MoreRepeated) GetInts() []int32 { - if m != nil { - return m.Ints - } - return nil -} - -func (m *MoreRepeated) GetIntsPacked() []int32 { - if m != nil { - return m.IntsPacked - } - return nil -} - -func (m *MoreRepeated) GetInt64SPacked() []int64 { - if m != nil { - return m.Int64SPacked - } - return nil -} - -func (m *MoreRepeated) GetStrings() []string { - if m != nil { - return m.Strings - } - return nil -} - -func (m *MoreRepeated) GetFixeds() []uint32 { - if m != nil { - return m.Fixeds - } - return nil -} - -type GroupOld struct { - G *GroupOld_G `protobuf:"group,101,opt" json:"g,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupOld) Reset() { *m = GroupOld{} } -func (m *GroupOld) String() string { return proto.CompactTextString(m) } -func (*GroupOld) ProtoMessage() {} - -func (m *GroupOld) GetG() *GroupOld_G { - if m != nil { - return m.G - } - return nil -} - -type GroupOld_G struct { - X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupOld_G) Reset() { *m = GroupOld_G{} } -func (m *GroupOld_G) String() string { return proto.CompactTextString(m) } -func (*GroupOld_G) ProtoMessage() {} - -func (m *GroupOld_G) GetX() int32 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -type GroupNew struct { - G *GroupNew_G `protobuf:"group,101,opt" json:"g,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupNew) Reset() { *m = GroupNew{} } -func (m *GroupNew) String() string { return proto.CompactTextString(m) } -func (*GroupNew) ProtoMessage() {} - -func (m *GroupNew) GetG() *GroupNew_G { - if m != nil { - return m.G - } - return nil -} - -type GroupNew_G struct { - X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` - Y *int32 `protobuf:"varint,3,opt,name=y" json:"y,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupNew_G) Reset() { *m = GroupNew_G{} } -func (m *GroupNew_G) String() string { return proto.CompactTextString(m) } -func (*GroupNew_G) ProtoMessage() {} - -func (m *GroupNew_G) GetX() int32 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -func (m *GroupNew_G) GetY() int32 { - if m != nil && m.Y != nil { - return *m.Y - } - return 0 -} - -type FloatingPoint struct { - F *float64 `protobuf:"fixed64,1,req,name=f" json:"f,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *FloatingPoint) Reset() { *m = FloatingPoint{} } -func (m *FloatingPoint) String() string { return proto.CompactTextString(m) } -func (*FloatingPoint) ProtoMessage() {} - -func (m *FloatingPoint) GetF() float64 { - if m != nil && m.F != nil { - return *m.F - } - return 0 -} - -type MessageWithMap struct { - NameMapping map[int32]string `protobuf:"bytes,1,rep,name=name_mapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - MsgMapping map[int64]*FloatingPoint `protobuf:"bytes,2,rep,name=msg_mapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - ByteMapping map[bool][]byte `protobuf:"bytes,3,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - StrToStr map[string]string `protobuf:"bytes,4,rep,name=str_to_str" json:"str_to_str,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } -func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } -func (*MessageWithMap) ProtoMessage() {} - -func (m *MessageWithMap) GetNameMapping() map[int32]string { - if m != nil { - return m.NameMapping - } - return nil -} - -func (m *MessageWithMap) GetMsgMapping() map[int64]*FloatingPoint { - if m != nil { - return m.MsgMapping - } - return nil -} - -func (m *MessageWithMap) GetByteMapping() map[bool][]byte { - if m != nil { - return m.ByteMapping - } - return nil -} - -func (m *MessageWithMap) GetStrToStr() map[string]string { - if m != nil { - return m.StrToStr - } - return nil -} - -var E_Greeting = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: ([]string)(nil), - Field: 106, - Name: "testdata.greeting", - Tag: "bytes,106,rep,name=greeting", -} - -var E_NoDefaultDouble = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float64)(nil), - Field: 101, - Name: "testdata.no_default_double", - Tag: "fixed64,101,opt,name=no_default_double", -} - -var E_NoDefaultFloat = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float32)(nil), - Field: 102, - Name: "testdata.no_default_float", - Tag: "fixed32,102,opt,name=no_default_float", -} - -var E_NoDefaultInt32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 103, - Name: "testdata.no_default_int32", - Tag: "varint,103,opt,name=no_default_int32", -} - -var E_NoDefaultInt64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 104, - Name: "testdata.no_default_int64", - Tag: "varint,104,opt,name=no_default_int64", -} - -var E_NoDefaultUint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 105, - Name: "testdata.no_default_uint32", - Tag: "varint,105,opt,name=no_default_uint32", -} - -var E_NoDefaultUint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 106, - Name: "testdata.no_default_uint64", - Tag: "varint,106,opt,name=no_default_uint64", -} - -var E_NoDefaultSint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 107, - Name: "testdata.no_default_sint32", - Tag: "zigzag32,107,opt,name=no_default_sint32", -} - -var E_NoDefaultSint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 108, - Name: "testdata.no_default_sint64", - Tag: "zigzag64,108,opt,name=no_default_sint64", -} - -var E_NoDefaultFixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 109, - Name: "testdata.no_default_fixed32", - Tag: "fixed32,109,opt,name=no_default_fixed32", -} - -var E_NoDefaultFixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 110, - Name: "testdata.no_default_fixed64", - Tag: "fixed64,110,opt,name=no_default_fixed64", -} - -var E_NoDefaultSfixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 111, - Name: "testdata.no_default_sfixed32", - Tag: "fixed32,111,opt,name=no_default_sfixed32", -} - -var E_NoDefaultSfixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 112, - Name: "testdata.no_default_sfixed64", - Tag: "fixed64,112,opt,name=no_default_sfixed64", -} - -var E_NoDefaultBool = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*bool)(nil), - Field: 113, - Name: "testdata.no_default_bool", - Tag: "varint,113,opt,name=no_default_bool", -} - -var E_NoDefaultString = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*string)(nil), - Field: 114, - Name: "testdata.no_default_string", - Tag: "bytes,114,opt,name=no_default_string", -} - -var E_NoDefaultBytes = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: ([]byte)(nil), - Field: 115, - Name: "testdata.no_default_bytes", - Tag: "bytes,115,opt,name=no_default_bytes", -} - -var E_NoDefaultEnum = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), - Field: 116, - Name: "testdata.no_default_enum", - Tag: "varint,116,opt,name=no_default_enum,enum=testdata.DefaultsMessage_DefaultsEnum", -} - -var E_DefaultDouble = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float64)(nil), - Field: 201, - Name: "testdata.default_double", - Tag: "fixed64,201,opt,name=default_double,def=3.1415", -} - -var E_DefaultFloat = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float32)(nil), - Field: 202, - Name: "testdata.default_float", - Tag: "fixed32,202,opt,name=default_float,def=3.14", -} - -var E_DefaultInt32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 203, - Name: "testdata.default_int32", - Tag: "varint,203,opt,name=default_int32,def=42", -} - -var E_DefaultInt64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 204, - Name: "testdata.default_int64", - Tag: "varint,204,opt,name=default_int64,def=43", -} - -var E_DefaultUint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 205, - Name: "testdata.default_uint32", - Tag: "varint,205,opt,name=default_uint32,def=44", -} - -var E_DefaultUint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 206, - Name: "testdata.default_uint64", - Tag: "varint,206,opt,name=default_uint64,def=45", -} - -var E_DefaultSint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 207, - Name: "testdata.default_sint32", - Tag: "zigzag32,207,opt,name=default_sint32,def=46", -} - -var E_DefaultSint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 208, - Name: "testdata.default_sint64", - Tag: "zigzag64,208,opt,name=default_sint64,def=47", -} - -var E_DefaultFixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 209, - Name: "testdata.default_fixed32", - Tag: "fixed32,209,opt,name=default_fixed32,def=48", -} - -var E_DefaultFixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 210, - Name: "testdata.default_fixed64", - Tag: "fixed64,210,opt,name=default_fixed64,def=49", -} - -var E_DefaultSfixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 211, - Name: "testdata.default_sfixed32", - Tag: "fixed32,211,opt,name=default_sfixed32,def=50", -} - -var E_DefaultSfixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 212, - Name: "testdata.default_sfixed64", - Tag: "fixed64,212,opt,name=default_sfixed64,def=51", -} - -var E_DefaultBool = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*bool)(nil), - Field: 213, - Name: "testdata.default_bool", - Tag: "varint,213,opt,name=default_bool,def=1", -} - -var E_DefaultString = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*string)(nil), - Field: 214, - Name: "testdata.default_string", - Tag: "bytes,214,opt,name=default_string,def=Hello, string", -} - -var E_DefaultBytes = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: ([]byte)(nil), - Field: 215, - Name: "testdata.default_bytes", - Tag: "bytes,215,opt,name=default_bytes,def=Hello, bytes", -} - -var E_DefaultEnum = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), - Field: 216, - Name: "testdata.default_enum", - Tag: "varint,216,opt,name=default_enum,enum=testdata.DefaultsMessage_DefaultsEnum,def=1", -} - -var E_X201 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 201, - Name: "testdata.x201", - Tag: "bytes,201,opt,name=x201", -} - -var E_X202 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 202, - Name: "testdata.x202", - Tag: "bytes,202,opt,name=x202", -} - -var E_X203 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 203, - Name: "testdata.x203", - Tag: "bytes,203,opt,name=x203", -} - -var E_X204 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 204, - Name: "testdata.x204", - Tag: "bytes,204,opt,name=x204", -} - -var E_X205 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 205, - Name: "testdata.x205", - Tag: "bytes,205,opt,name=x205", -} - -var E_X206 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 206, - Name: "testdata.x206", - Tag: "bytes,206,opt,name=x206", -} - -var E_X207 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 207, - Name: "testdata.x207", - Tag: "bytes,207,opt,name=x207", -} - -var E_X208 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 208, - Name: "testdata.x208", - Tag: "bytes,208,opt,name=x208", -} - -var E_X209 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 209, - Name: "testdata.x209", - Tag: "bytes,209,opt,name=x209", -} - -var E_X210 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 210, - Name: "testdata.x210", - Tag: "bytes,210,opt,name=x210", -} - -var E_X211 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 211, - Name: "testdata.x211", - Tag: "bytes,211,opt,name=x211", -} - -var E_X212 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 212, - Name: "testdata.x212", - Tag: "bytes,212,opt,name=x212", -} - -var E_X213 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 213, - Name: "testdata.x213", - Tag: "bytes,213,opt,name=x213", -} - -var E_X214 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 214, - Name: "testdata.x214", - Tag: "bytes,214,opt,name=x214", -} - -var E_X215 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 215, - Name: "testdata.x215", - Tag: "bytes,215,opt,name=x215", -} - -var E_X216 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 216, - Name: "testdata.x216", - Tag: "bytes,216,opt,name=x216", -} - -var E_X217 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 217, - Name: "testdata.x217", - Tag: "bytes,217,opt,name=x217", -} - -var E_X218 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 218, - Name: "testdata.x218", - Tag: "bytes,218,opt,name=x218", -} - -var E_X219 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 219, - Name: "testdata.x219", - Tag: "bytes,219,opt,name=x219", -} - -var E_X220 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 220, - Name: "testdata.x220", - Tag: "bytes,220,opt,name=x220", -} - -var E_X221 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 221, - Name: "testdata.x221", - Tag: "bytes,221,opt,name=x221", -} - -var E_X222 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 222, - Name: "testdata.x222", - Tag: "bytes,222,opt,name=x222", -} - -var E_X223 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 223, - Name: "testdata.x223", - Tag: "bytes,223,opt,name=x223", -} - -var E_X224 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 224, - Name: "testdata.x224", - Tag: "bytes,224,opt,name=x224", -} - -var E_X225 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 225, - Name: "testdata.x225", - Tag: "bytes,225,opt,name=x225", -} - -var E_X226 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 226, - Name: "testdata.x226", - Tag: "bytes,226,opt,name=x226", -} - -var E_X227 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 227, - Name: "testdata.x227", - Tag: "bytes,227,opt,name=x227", -} - -var E_X228 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 228, - Name: "testdata.x228", - Tag: "bytes,228,opt,name=x228", -} - -var E_X229 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 229, - Name: "testdata.x229", - Tag: "bytes,229,opt,name=x229", -} - -var E_X230 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 230, - Name: "testdata.x230", - Tag: "bytes,230,opt,name=x230", -} - -var E_X231 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 231, - Name: "testdata.x231", - Tag: "bytes,231,opt,name=x231", -} - -var E_X232 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 232, - Name: "testdata.x232", - Tag: "bytes,232,opt,name=x232", -} - -var E_X233 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 233, - Name: "testdata.x233", - Tag: "bytes,233,opt,name=x233", -} - -var E_X234 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 234, - Name: "testdata.x234", - Tag: "bytes,234,opt,name=x234", -} - -var E_X235 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 235, - Name: "testdata.x235", - Tag: "bytes,235,opt,name=x235", -} - -var E_X236 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 236, - Name: "testdata.x236", - Tag: "bytes,236,opt,name=x236", -} - -var E_X237 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 237, - Name: "testdata.x237", - Tag: "bytes,237,opt,name=x237", -} - -var E_X238 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 238, - Name: "testdata.x238", - Tag: "bytes,238,opt,name=x238", -} - -var E_X239 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 239, - Name: "testdata.x239", - Tag: "bytes,239,opt,name=x239", -} - -var E_X240 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 240, - Name: "testdata.x240", - Tag: "bytes,240,opt,name=x240", -} - -var E_X241 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 241, - Name: "testdata.x241", - Tag: "bytes,241,opt,name=x241", -} - -var E_X242 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 242, - Name: "testdata.x242", - Tag: "bytes,242,opt,name=x242", -} - -var E_X243 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 243, - Name: "testdata.x243", - Tag: "bytes,243,opt,name=x243", -} - -var E_X244 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 244, - Name: "testdata.x244", - Tag: "bytes,244,opt,name=x244", -} - -var E_X245 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 245, - Name: "testdata.x245", - Tag: "bytes,245,opt,name=x245", -} - -var E_X246 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 246, - Name: "testdata.x246", - Tag: "bytes,246,opt,name=x246", -} - -var E_X247 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 247, - Name: "testdata.x247", - Tag: "bytes,247,opt,name=x247", -} - -var E_X248 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 248, - Name: "testdata.x248", - Tag: "bytes,248,opt,name=x248", -} - -var E_X249 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 249, - Name: "testdata.x249", - Tag: "bytes,249,opt,name=x249", -} - -var E_X250 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 250, - Name: "testdata.x250", - Tag: "bytes,250,opt,name=x250", -} - -func init() { - proto.RegisterEnum("testdata.FOO", FOO_name, FOO_value) - proto.RegisterEnum("testdata.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value) - proto.RegisterEnum("testdata.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value) - proto.RegisterEnum("testdata.DefaultsMessage_DefaultsEnum", DefaultsMessage_DefaultsEnum_name, DefaultsMessage_DefaultsEnum_value) - proto.RegisterEnum("testdata.Defaults_Color", Defaults_Color_name, Defaults_Color_value) - proto.RegisterEnum("testdata.RepeatedEnum_Color", RepeatedEnum_Color_name, RepeatedEnum_Color_value) - proto.RegisterExtension(E_Ext_More) - proto.RegisterExtension(E_Ext_Text) - proto.RegisterExtension(E_Ext_Number) - proto.RegisterExtension(E_Greeting) - proto.RegisterExtension(E_NoDefaultDouble) - proto.RegisterExtension(E_NoDefaultFloat) - proto.RegisterExtension(E_NoDefaultInt32) - proto.RegisterExtension(E_NoDefaultInt64) - proto.RegisterExtension(E_NoDefaultUint32) - proto.RegisterExtension(E_NoDefaultUint64) - proto.RegisterExtension(E_NoDefaultSint32) - proto.RegisterExtension(E_NoDefaultSint64) - proto.RegisterExtension(E_NoDefaultFixed32) - proto.RegisterExtension(E_NoDefaultFixed64) - proto.RegisterExtension(E_NoDefaultSfixed32) - proto.RegisterExtension(E_NoDefaultSfixed64) - proto.RegisterExtension(E_NoDefaultBool) - proto.RegisterExtension(E_NoDefaultString) - proto.RegisterExtension(E_NoDefaultBytes) - proto.RegisterExtension(E_NoDefaultEnum) - proto.RegisterExtension(E_DefaultDouble) - proto.RegisterExtension(E_DefaultFloat) - proto.RegisterExtension(E_DefaultInt32) - proto.RegisterExtension(E_DefaultInt64) - proto.RegisterExtension(E_DefaultUint32) - proto.RegisterExtension(E_DefaultUint64) - proto.RegisterExtension(E_DefaultSint32) - proto.RegisterExtension(E_DefaultSint64) - proto.RegisterExtension(E_DefaultFixed32) - proto.RegisterExtension(E_DefaultFixed64) - proto.RegisterExtension(E_DefaultSfixed32) - proto.RegisterExtension(E_DefaultSfixed64) - proto.RegisterExtension(E_DefaultBool) - proto.RegisterExtension(E_DefaultString) - proto.RegisterExtension(E_DefaultBytes) - proto.RegisterExtension(E_DefaultEnum) - proto.RegisterExtension(E_X201) - proto.RegisterExtension(E_X202) - proto.RegisterExtension(E_X203) - proto.RegisterExtension(E_X204) - proto.RegisterExtension(E_X205) - proto.RegisterExtension(E_X206) - proto.RegisterExtension(E_X207) - proto.RegisterExtension(E_X208) - proto.RegisterExtension(E_X209) - proto.RegisterExtension(E_X210) - proto.RegisterExtension(E_X211) - proto.RegisterExtension(E_X212) - proto.RegisterExtension(E_X213) - proto.RegisterExtension(E_X214) - proto.RegisterExtension(E_X215) - proto.RegisterExtension(E_X216) - proto.RegisterExtension(E_X217) - proto.RegisterExtension(E_X218) - proto.RegisterExtension(E_X219) - proto.RegisterExtension(E_X220) - proto.RegisterExtension(E_X221) - proto.RegisterExtension(E_X222) - proto.RegisterExtension(E_X223) - proto.RegisterExtension(E_X224) - proto.RegisterExtension(E_X225) - proto.RegisterExtension(E_X226) - proto.RegisterExtension(E_X227) - proto.RegisterExtension(E_X228) - proto.RegisterExtension(E_X229) - proto.RegisterExtension(E_X230) - proto.RegisterExtension(E_X231) - proto.RegisterExtension(E_X232) - proto.RegisterExtension(E_X233) - proto.RegisterExtension(E_X234) - proto.RegisterExtension(E_X235) - proto.RegisterExtension(E_X236) - proto.RegisterExtension(E_X237) - proto.RegisterExtension(E_X238) - proto.RegisterExtension(E_X239) - proto.RegisterExtension(E_X240) - proto.RegisterExtension(E_X241) - proto.RegisterExtension(E_X242) - proto.RegisterExtension(E_X243) - proto.RegisterExtension(E_X244) - proto.RegisterExtension(E_X245) - proto.RegisterExtension(E_X246) - proto.RegisterExtension(E_X247) - proto.RegisterExtension(E_X248) - proto.RegisterExtension(E_X249) - proto.RegisterExtension(E_X250) -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.proto b/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.proto deleted file mode 100644 index 440dba38..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.proto +++ /dev/null @@ -1,480 +0,0 @@ -// 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. - -// A feature-rich test file for the protocol compiler and libraries. - -syntax = "proto2"; - -package testdata; - -enum FOO { FOO1 = 1; }; - -message GoEnum { - required FOO foo = 1; -} - -message GoTestField { - required string Label = 1; - required string Type = 2; -} - -message GoTest { - // An enum, for completeness. - enum KIND { - VOID = 0; - - // Basic types - BOOL = 1; - BYTES = 2; - FINGERPRINT = 3; - FLOAT = 4; - INT = 5; - STRING = 6; - TIME = 7; - - // Groupings - TUPLE = 8; - ARRAY = 9; - MAP = 10; - - // Table types - TABLE = 11; - - // Functions - FUNCTION = 12; // last tag - }; - - // Some typical parameters - required KIND Kind = 1; - optional string Table = 2; - optional int32 Param = 3; - - // Required, repeated and optional foreign fields. - required GoTestField RequiredField = 4; - repeated GoTestField RepeatedField = 5; - optional GoTestField OptionalField = 6; - - // Required fields of all basic types - required bool F_Bool_required = 10; - required int32 F_Int32_required = 11; - required int64 F_Int64_required = 12; - required fixed32 F_Fixed32_required = 13; - required fixed64 F_Fixed64_required = 14; - required uint32 F_Uint32_required = 15; - required uint64 F_Uint64_required = 16; - required float F_Float_required = 17; - required double F_Double_required = 18; - required string F_String_required = 19; - required bytes F_Bytes_required = 101; - required sint32 F_Sint32_required = 102; - required sint64 F_Sint64_required = 103; - - // Repeated fields of all basic types - repeated bool F_Bool_repeated = 20; - repeated int32 F_Int32_repeated = 21; - repeated int64 F_Int64_repeated = 22; - repeated fixed32 F_Fixed32_repeated = 23; - repeated fixed64 F_Fixed64_repeated = 24; - repeated uint32 F_Uint32_repeated = 25; - repeated uint64 F_Uint64_repeated = 26; - repeated float F_Float_repeated = 27; - repeated double F_Double_repeated = 28; - repeated string F_String_repeated = 29; - repeated bytes F_Bytes_repeated = 201; - repeated sint32 F_Sint32_repeated = 202; - repeated sint64 F_Sint64_repeated = 203; - - // Optional fields of all basic types - optional bool F_Bool_optional = 30; - optional int32 F_Int32_optional = 31; - optional int64 F_Int64_optional = 32; - optional fixed32 F_Fixed32_optional = 33; - optional fixed64 F_Fixed64_optional = 34; - optional uint32 F_Uint32_optional = 35; - optional uint64 F_Uint64_optional = 36; - optional float F_Float_optional = 37; - optional double F_Double_optional = 38; - optional string F_String_optional = 39; - optional bytes F_Bytes_optional = 301; - optional sint32 F_Sint32_optional = 302; - optional sint64 F_Sint64_optional = 303; - - // Default-valued fields of all basic types - optional bool F_Bool_defaulted = 40 [default=true]; - optional int32 F_Int32_defaulted = 41 [default=32]; - optional int64 F_Int64_defaulted = 42 [default=64]; - optional fixed32 F_Fixed32_defaulted = 43 [default=320]; - optional fixed64 F_Fixed64_defaulted = 44 [default=640]; - optional uint32 F_Uint32_defaulted = 45 [default=3200]; - optional uint64 F_Uint64_defaulted = 46 [default=6400]; - optional float F_Float_defaulted = 47 [default=314159.]; - optional double F_Double_defaulted = 48 [default=271828.]; - optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"]; - optional bytes F_Bytes_defaulted = 401 [default="Bignose"]; - optional sint32 F_Sint32_defaulted = 402 [default = -32]; - optional sint64 F_Sint64_defaulted = 403 [default = -64]; - - // Packed repeated fields (no string or bytes). - repeated bool F_Bool_repeated_packed = 50 [packed=true]; - repeated int32 F_Int32_repeated_packed = 51 [packed=true]; - repeated int64 F_Int64_repeated_packed = 52 [packed=true]; - repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true]; - repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true]; - repeated uint32 F_Uint32_repeated_packed = 55 [packed=true]; - repeated uint64 F_Uint64_repeated_packed = 56 [packed=true]; - repeated float F_Float_repeated_packed = 57 [packed=true]; - repeated double F_Double_repeated_packed = 58 [packed=true]; - repeated sint32 F_Sint32_repeated_packed = 502 [packed=true]; - repeated sint64 F_Sint64_repeated_packed = 503 [packed=true]; - - // Required, repeated, and optional groups. - required group RequiredGroup = 70 { - required string RequiredField = 71; - }; - - repeated group RepeatedGroup = 80 { - required string RequiredField = 81; - }; - - optional group OptionalGroup = 90 { - required string RequiredField = 91; - }; -} - -// For testing skipping of unrecognized fields. -// Numbers are all big, larger than tag numbers in GoTestField, -// the message used in the corresponding test. -message GoSkipTest { - required int32 skip_int32 = 11; - required fixed32 skip_fixed32 = 12; - required fixed64 skip_fixed64 = 13; - required string skip_string = 14; - required group SkipGroup = 15 { - required int32 group_int32 = 16; - required string group_string = 17; - } -} - -// For testing packed/non-packed decoder switching. -// A serialized instance of one should be deserializable as the other. -message NonPackedTest { - repeated int32 a = 1; -} - -message PackedTest { - repeated int32 b = 1 [packed=true]; -} - -message MaxTag { - // Maximum possible tag number. - optional string last_field = 536870911; -} - -message OldMessage { - message Nested { - optional string name = 1; - } - optional Nested nested = 1; - - optional int32 num = 2; -} - -// NewMessage is wire compatible with OldMessage; -// imagine it as a future version. -message NewMessage { - message Nested { - optional string name = 1; - optional string food_group = 2; - } - optional Nested nested = 1; - - // This is an int32 in OldMessage. - optional int64 num = 2; -} - -// Smaller tests for ASCII formatting. - -message InnerMessage { - required string host = 1; - optional int32 port = 2 [default=4000]; - optional bool connected = 3; -} - -message OtherMessage { - optional int64 key = 1; - optional bytes value = 2; - optional float weight = 3; - optional InnerMessage inner = 4; -} - -message MyMessage { - required int32 count = 1; - optional string name = 2; - optional string quote = 3; - repeated string pet = 4; - optional InnerMessage inner = 5; - repeated OtherMessage others = 6; - repeated InnerMessage rep_inner = 12; - - enum Color { - RED = 0; - GREEN = 1; - BLUE = 2; - }; - optional Color bikeshed = 7; - - optional group SomeGroup = 8 { - optional int32 group_field = 9; - } - - // This field becomes [][]byte in the generated code. - repeated bytes rep_bytes = 10; - - optional double bigfloat = 11; - - extensions 100 to max; -} - -message Ext { - extend MyMessage { - optional Ext more = 103; - optional string text = 104; - optional int32 number = 105; - } - - optional string data = 1; -} - -extend MyMessage { - repeated string greeting = 106; -} - -message DefaultsMessage { - enum DefaultsEnum { - ZERO = 0; - ONE = 1; - TWO = 2; - }; - extensions 100 to max; -} - -extend DefaultsMessage { - optional double no_default_double = 101; - optional float no_default_float = 102; - optional int32 no_default_int32 = 103; - optional int64 no_default_int64 = 104; - optional uint32 no_default_uint32 = 105; - optional uint64 no_default_uint64 = 106; - optional sint32 no_default_sint32 = 107; - optional sint64 no_default_sint64 = 108; - optional fixed32 no_default_fixed32 = 109; - optional fixed64 no_default_fixed64 = 110; - optional sfixed32 no_default_sfixed32 = 111; - optional sfixed64 no_default_sfixed64 = 112; - optional bool no_default_bool = 113; - optional string no_default_string = 114; - optional bytes no_default_bytes = 115; - optional DefaultsMessage.DefaultsEnum no_default_enum = 116; - - optional double default_double = 201 [default = 3.1415]; - optional float default_float = 202 [default = 3.14]; - optional int32 default_int32 = 203 [default = 42]; - optional int64 default_int64 = 204 [default = 43]; - optional uint32 default_uint32 = 205 [default = 44]; - optional uint64 default_uint64 = 206 [default = 45]; - optional sint32 default_sint32 = 207 [default = 46]; - optional sint64 default_sint64 = 208 [default = 47]; - optional fixed32 default_fixed32 = 209 [default = 48]; - optional fixed64 default_fixed64 = 210 [default = 49]; - optional sfixed32 default_sfixed32 = 211 [default = 50]; - optional sfixed64 default_sfixed64 = 212 [default = 51]; - optional bool default_bool = 213 [default = true]; - optional string default_string = 214 [default = "Hello, string"]; - optional bytes default_bytes = 215 [default = "Hello, bytes"]; - optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE]; -} - -message MyMessageSet { - option message_set_wire_format = true; - extensions 100 to max; -} - -message Empty { -} - -extend MyMessageSet { - optional Empty x201 = 201; - optional Empty x202 = 202; - optional Empty x203 = 203; - optional Empty x204 = 204; - optional Empty x205 = 205; - optional Empty x206 = 206; - optional Empty x207 = 207; - optional Empty x208 = 208; - optional Empty x209 = 209; - optional Empty x210 = 210; - optional Empty x211 = 211; - optional Empty x212 = 212; - optional Empty x213 = 213; - optional Empty x214 = 214; - optional Empty x215 = 215; - optional Empty x216 = 216; - optional Empty x217 = 217; - optional Empty x218 = 218; - optional Empty x219 = 219; - optional Empty x220 = 220; - optional Empty x221 = 221; - optional Empty x222 = 222; - optional Empty x223 = 223; - optional Empty x224 = 224; - optional Empty x225 = 225; - optional Empty x226 = 226; - optional Empty x227 = 227; - optional Empty x228 = 228; - optional Empty x229 = 229; - optional Empty x230 = 230; - optional Empty x231 = 231; - optional Empty x232 = 232; - optional Empty x233 = 233; - optional Empty x234 = 234; - optional Empty x235 = 235; - optional Empty x236 = 236; - optional Empty x237 = 237; - optional Empty x238 = 238; - optional Empty x239 = 239; - optional Empty x240 = 240; - optional Empty x241 = 241; - optional Empty x242 = 242; - optional Empty x243 = 243; - optional Empty x244 = 244; - optional Empty x245 = 245; - optional Empty x246 = 246; - optional Empty x247 = 247; - optional Empty x248 = 248; - optional Empty x249 = 249; - optional Empty x250 = 250; -} - -message MessageList { - repeated group Message = 1 { - required string name = 2; - required int32 count = 3; - } -} - -message Strings { - optional string string_field = 1; - optional bytes bytes_field = 2; -} - -message Defaults { - enum Color { - RED = 0; - GREEN = 1; - BLUE = 2; - } - - // Default-valued fields of all basic types. - // Same as GoTest, but copied here to make testing easier. - optional bool F_Bool = 1 [default=true]; - optional int32 F_Int32 = 2 [default=32]; - optional int64 F_Int64 = 3 [default=64]; - optional fixed32 F_Fixed32 = 4 [default=320]; - optional fixed64 F_Fixed64 = 5 [default=640]; - optional uint32 F_Uint32 = 6 [default=3200]; - optional uint64 F_Uint64 = 7 [default=6400]; - optional float F_Float = 8 [default=314159.]; - optional double F_Double = 9 [default=271828.]; - optional string F_String = 10 [default="hello, \"world!\"\n"]; - optional bytes F_Bytes = 11 [default="Bignose"]; - optional sint32 F_Sint32 = 12 [default=-32]; - optional sint64 F_Sint64 = 13 [default=-64]; - optional Color F_Enum = 14 [default=GREEN]; - - // More fields with crazy defaults. - optional float F_Pinf = 15 [default=inf]; - optional float F_Ninf = 16 [default=-inf]; - optional float F_Nan = 17 [default=nan]; - - // Sub-message. - optional SubDefaults sub = 18; - - // Redundant but explicit defaults. - optional string str_zero = 19 [default=""]; -} - -message SubDefaults { - optional int64 n = 1 [default=7]; -} - -message RepeatedEnum { - enum Color { - RED = 1; - } - repeated Color color = 1; -} - -message MoreRepeated { - repeated bool bools = 1; - repeated bool bools_packed = 2 [packed=true]; - repeated int32 ints = 3; - repeated int32 ints_packed = 4 [packed=true]; - repeated int64 int64s_packed = 7 [packed=true]; - repeated string strings = 5; - repeated fixed32 fixeds = 6; -} - -// GroupOld and GroupNew have the same wire format. -// GroupNew has a new field inside a group. - -message GroupOld { - optional group G = 101 { - optional int32 x = 2; - } -} - -message GroupNew { - optional group G = 101 { - optional int32 x = 2; - optional int32 y = 3; - } -} - -message FloatingPoint { - required double f = 1; -} - -message MessageWithMap { - map name_mapping = 1; - map msg_mapping = 2; - map byte_mapping = 3; - map str_to_str = 4; -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/text.go deleted file mode 100644 index f3db2cf5..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text.go +++ /dev/null @@ -1,769 +0,0 @@ -// 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" - "fmt" - "io" - "log" - "math" - "reflect" - "sort" - "strings" -) - -var ( - newline = []byte("\n") - spaces = []byte(" ") - gtNewline = []byte(">\n") - 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.Printf("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 -} - -var ( - messageSetType = reflect.TypeOf((*MessageSet)(nil)).Elem() -) - -// raw is the interface satisfied by RawMessage. -type raw interface { - Bytes() []byte -} - -func writeStruct(w *textWriter, sv reflect.Value) error { - if sv.Type() == messageSetType { - return writeMessageSet(w, sv.Addr().Interface().(*MessageSet)) - } - - 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 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 err := 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 := writeAny(w, key, props.mkeyprop); 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 := writeAny(w, val, props.mvalprop); 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 fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice { - // proto3 non-repeated scalar field; skip if zero value - if isProto3Zero(fv) { - continue - } - } - - if err := writeName(w, props); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte(' '); err != nil { - return err - } - } - if b, ok := fv.Interface().(raw); ok { - if err := writeRaw(w, b.Bytes()); err != nil { - return err - } - continue - } - - // Enums have a String method, so writeAny will work fine. - if err := writeAny(w, fv, props); err != nil { - return err - } - - if err := w.WriteByte('\n'); err != nil { - return err - } - } - - // Extensions (the XXX_extensions field). - pv := sv.Addr() - if pv.Type().Implements(extendableProtoType) { - if err := writeExtensions(w, pv); err != nil { - return err - } - } - - return nil -} - -// writeRaw writes an uninterpreted raw message. -func writeRaw(w *textWriter, b []byte) error { - if err := w.WriteByte('<'); err != nil { - return err - } - if !w.compact { - if err := w.WriteByte('\n'); err != nil { - return err - } - } - w.indent() - if err := writeUnknownStruct(w, b); err != nil { - return err - } - w.unindent() - if err := w.WriteByte('>'); err != nil { - return err - } - return nil -} - -// writeAny writes an arbitrary field. -func writeAny(w *textWriter, v reflect.Value, props *Properties) error { - v = reflect.Indirect(v) - - // 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.Interface().([]byte))); 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 tm, ok := v.Interface().(encoding.TextMarshaler); ok { - text, err := tm.MarshalText() - if err != nil { - return err - } - if _, err = w.Write(text); err != nil { - return err - } - } else if err := 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 writeMessageSet(w *textWriter, ms *MessageSet) error { - for _, item := range ms.Item { - id := *item.TypeId - if msd, ok := messageSetMap[id]; ok { - // Known message set type. - if _, err := fmt.Fprintf(w, "[%s]: <\n", msd.name); err != nil { - return err - } - w.indent() - - pb := reflect.New(msd.t.Elem()) - if err := Unmarshal(item.Message, pb.Interface().(Message)); err != nil { - if _, err := fmt.Fprintf(w, "/* bad message: %v */\n", err); err != nil { - return err - } - } else { - if err := writeStruct(w, pb.Elem()); err != nil { - return err - } - } - } else { - // Unknown type. - if _, err := fmt.Fprintf(w, "[%d]: <\n", id); err != nil { - return err - } - w.indent() - if err := writeUnknownStruct(w, item.Message); err != nil { - return err - } - } - w.unindent() - if _, err := w.Write(gtNewline); err != nil { - return err - } - } - return nil -} - -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 { - _, err := fmt.Fprintf(w, "/* %v */\n", err) - return err - } - wire, tag := x&7, x>>3 - if wire == WireEndGroup { - w.unindent() - if _, err := w.Write(endBraceNewline); err != nil { - return err - } - continue - } - if _, err := fmt.Fprint(w, tag); err != nil { - return err - } - 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 writeExtensions(w *textWriter, pv reflect.Value) error { - emap := extensionMaps[pv.Type().Elem()] - ep := pv.Interface().(extendableProto) - - // Order the extensions by ID. - // This isn't strictly necessary, but it will give us - // canonical output, which will also make testing easier. - m := ep.ExtensionMap() - ids := make([]int32, 0, len(m)) - for id := range m { - ids = append(ids, id) - } - sort.Sort(int32Slice(ids)) - - 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(ep, desc) - if err != nil { - return fmt.Errorf("failed getting extension: %v", err) - } - - // Repeated extensions will appear as a slice. - if !desc.repeated() { - if err := writeExtension(w, desc.Name, pb); err != nil { - return err - } - } else { - v := reflect.ValueOf(pb) - for i := 0; i < v.Len(); i++ { - if err := writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { - return err - } - } - } - } - return nil -} - -func 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 := 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 -} - -func marshalText(w io.Writer, pb Message, compact bool) 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: compact, - } - - if tm, ok := pb.(encoding.TextMarshaler); ok { - text, err := tm.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 := writeStruct(aw, v); err != nil { - return err - } - if bw != nil { - return bw.Flush() - } - return nil -} - -// 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 marshalText(w, pb, false) -} - -// MarshalTextString is the same as MarshalText, but returns the string directly. -func MarshalTextString(pb Message) string { - var buf bytes.Buffer - marshalText(&buf, pb, false) - return buf.String() -} - -// CompactText writes a given protocol buffer in compact text format (one line). -func CompactText(w io.Writer, pb Message) error { return marshalText(w, pb, true) } - -// CompactTextString is the same as CompactText, but returns the string directly. -func CompactTextString(pb Message) string { - var buf bytes.Buffer - marshalText(&buf, pb, true) - return buf.String() -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser.go deleted file mode 100644 index 7d0c7571..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser.go +++ /dev/null @@ -1,772 +0,0 @@ -// 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" - "unicode/utf8" -) - -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 (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") - errBadHex = errors.New("proto: bad hexadecimal") -) - -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', 'x', 'X': - if len(s) < 2 { - return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) - } - base := 8 - ss := s[:2] - s = s[2:] - if r == 'x' || r == 'X' { - base = 16 - } else { - ss = string(r) + ss - } - i, err := strconv.ParseUint(ss, base, 8) - if err != nil { - return "", "", err - } - return string([]byte{byte(i)}), s, nil - case 'u', 'U': - n := 4 - if r == 'U' { - n = 8 - } - if len(s) < n { - return "", "", fmt.Errorf(`\%c requires %d digits`, r, n) - } - - bs := make([]byte, n/2) - for i := 0; i < n; i += 2 { - a, ok1 := unhex(s[i]) - b, ok2 := unhex(s[i+1]) - if !ok1 || !ok2 { - return "", "", errBadHex - } - bs[i/2] = a<<4 | b - } - s = s[n:] - return string(bs), s, nil - } - return "", "", fmt.Errorf(`unknown escape \%c`, r) -} - -// Adapted from src/pkg/strconv/quote.go. -func unhex(b byte) (v byte, ok bool) { - switch { - case '0' <= b && b <= '9': - return b - '0', true - case 'a' <= b && b <= 'f': - return b - 'a' + 10, true - case 'A' <= b && b <= 'F': - return b - 'A' + 10, true - } - return 0, false -} - -// 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 && p.cur.value[0] == '"' { - // Look for multiple quoted strings separated by whitespace, - // and concatenate them. - cat := p.cur - for { - p.skipWhitespace() - if p.done || 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(st reflect.Type, name string) (int, *Properties, bool) { - sprops := GetProperties(st) - 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() - reqCount := GetProperties(st).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]". - for { - tok := p.next() - if tok.err != nil { - return tok.err - } - if tok.value == terminator { - break - } - if tok.value == "[" { - // Looks like an extension. - // - // TODO: Check whether we need to handle - // namespace rooted names (e.g. ".something.Foo"). - tok = p.next() - if tok.err != nil { - return tok.err - } - 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 == tok.value { - desc = d - break - } - } - if desc == nil { - return p.errorf("unrecognized extension %q", tok.value) - } - // Check the extension terminator. - tok = p.next() - if tok.err != nil { - return tok.err - } - if tok.value != "]" { - return p.errorf("unrecognized extension terminator %q", tok.value) - } - - 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().(extendableProto) - 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()) - } - } else { - // This is a normal, non-extension field. - name := tok.value - fi, props, ok := structFieldByName(st, name) - if !ok { - return p.errorf("unknown field name %q in %v", name, st) - } - - dst := sv.Field(fi) - - 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 > - // Technically the "key" and "value" could come in any order, - // but in practice they won't. - - tok := p.next() - var terminator string - switch tok.value { - case "<": - terminator = ">" - case "{": - terminator = "}" - default: - return p.errorf("expected '{' or '<', found %q", tok.value) - } - if err := p.consumeToken("key"); err != nil { - return err - } - if err := p.consumeToken(":"); err != nil { - return err - } - if err := p.readAny(key, props.mkeyprop); err != nil { - return err - } - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - if err := p.consumeToken("value"); err != nil { - return err - } - if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { - return err - } - if err := p.readAny(val, props.mvalprop); err != nil { - return err - } - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - if err := p.consumeToken(terminator); err != nil { - return err - } - - 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, st.Field(fi).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 - } else if props.Required { - reqCount-- - } - } - - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - - } - - if reqCount > 0 { - return p.missingRequiredFieldError(sv) - } - return reqFieldErr -} - -// 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") - } - - 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. May already exist. - flen := fv.Len() - if flen == fv.Cap() { - nav := reflect.MakeSlice(at, 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) - case reflect.Bool: - // Either "true", "false", 1 or 0. - switch tok.value { - case "true", "1": - fv.SetBool(true) - return nil - case "false", "0": - 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.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.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 { - err := um.UnmarshalText([]byte(s)) - return err - } - pb.Reset() - v := reflect.ValueOf(pb) - if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil { - return pe - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser_test.go deleted file mode 100644 index 0754b262..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser_test.go +++ /dev/null @@ -1,511 +0,0 @@ -// 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_test - -import ( - "math" - "reflect" - "testing" - - . "github.com/golang/protobuf/proto" - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - . "github.com/golang/protobuf/proto/testdata" -) - -type UnmarshalTextTest struct { - in string - err string // if "", no error expected - out *MyMessage -} - -func buildExtStructTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_More, &Ext{ - Data: String("Hello, world!"), - }) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtDataTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_Text, String("Hello, world!")) - SetExtension(msg, E_Ext_Number, Int32(1729)) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtRepStringTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil { - panic(err) - } - return UnmarshalTextTest{in: text, out: msg} -} - -var unMarshalTextTests = []UnmarshalTextTest{ - // Basic - { - in: " count:42\n name:\"Dave\" ", - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - }, - }, - - // Empty quoted string - { - in: `count:42 name:""`, - out: &MyMessage{ - Count: Int32(42), - Name: String(""), - }, - }, - - // Quoted string concatenation - { - in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string with escaped apostrophe - { - in: `count:42 name: "HOLIDAY - New Year\'s Day"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("HOLIDAY - New Year's Day"), - }, - }, - - // Quoted string with single quote - { - in: `count:42 name: 'Roger "The Ramster" Ramjet'`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`Roger "The Ramster" Ramjet`), - }, - }, - - // Quoted string with all the accepted special characters from the C++ test - { - in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"", - out: &MyMessage{ - Count: Int32(42), - Name: String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces"), - }, - }, - - // Quoted string with quoted backslash - { - in: `count:42 name: "\\'xyz"`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`\'xyz`), - }, - }, - - // Quoted string with UTF-8 bytes. - { - in: "count:42 name: '\303\277\302\201\xAB'", - out: &MyMessage{ - Count: Int32(42), - Name: String("\303\277\302\201\xAB"), - }, - }, - - // Bad quoted string - { - in: `inner: < host: "\0" >` + "\n", - err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`, - }, - - // Number too large for int64 - { - in: "count: 1 others { key: 123456789012345678901 }", - err: "line 1.23: invalid int64: 123456789012345678901", - }, - - // Number too large for int32 - { - in: "count: 1234567890123", - err: "line 1.7: invalid int32: 1234567890123", - }, - - // Number in hexadecimal - { - in: "count: 0x2beef", - out: &MyMessage{ - Count: Int32(0x2beef), - }, - }, - - // Number in octal - { - in: "count: 024601", - out: &MyMessage{ - Count: Int32(024601), - }, - }, - - // Floating point number with "f" suffix - { - in: "count: 4 others:< weight: 17.0f >", - out: &MyMessage{ - Count: Int32(4), - Others: []*OtherMessage{ - { - Weight: Float32(17), - }, - }, - }, - }, - - // Floating point positive infinity - { - in: "count: 4 bigfloat: inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(1)), - }, - }, - - // Floating point negative infinity - { - in: "count: 4 bigfloat: -inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(-1)), - }, - }, - - // Number too large for float32 - { - in: "others:< weight: 12345678901234567890123456789012345678901234567890 >", - err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890", - }, - - // Number posing as a quoted string - { - in: `inner: < host: 12 >` + "\n", - err: `line 1.15: invalid string: 12`, - }, - - // Quoted string posing as int32 - { - in: `count: "12"`, - err: `line 1.7: invalid int32: "12"`, - }, - - // Quoted string posing a float32 - { - in: `others:< weight: "17.4" >`, - err: `line 1.17: invalid float32: "17.4"`, - }, - - // Enum - { - in: `count:42 bikeshed: BLUE`, - out: &MyMessage{ - Count: Int32(42), - Bikeshed: MyMessage_BLUE.Enum(), - }, - }, - - // Repeated field - { - in: `count:42 pet: "horsey" pet:"bunny"`, - out: &MyMessage{ - Count: Int32(42), - Pet: []string{"horsey", "bunny"}, - }, - }, - - // Repeated message with/without colon and <>/{} - { - in: `count:42 others:{} others{} others:<> others:{}`, - out: &MyMessage{ - Count: Int32(42), - Others: []*OtherMessage{ - {}, - {}, - {}, - {}, - }, - }, - }, - - // Missing colon for inner message - { - in: `count:42 inner < host: "cauchy.syd" >`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("cauchy.syd"), - }, - }, - }, - - // Missing colon for string field - { - in: `name "Dave"`, - err: `line 1.5: expected ':', found "\"Dave\""`, - }, - - // Missing colon for int32 field - { - in: `count 42`, - err: `line 1.6: expected ':', found "42"`, - }, - - // Missing required field - { - in: `name: "Pawel"`, - err: `proto: required field "testdata.MyMessage.count" not set`, - out: &MyMessage{ - Name: String("Pawel"), - }, - }, - - // Repeated non-repeated field - { - in: `name: "Rob" name: "Russ"`, - err: `line 1.12: non-repeated field "name" was repeated`, - }, - - // Group - { - in: `count: 17 SomeGroup { group_field: 12 }`, - out: &MyMessage{ - Count: Int32(17), - Somegroup: &MyMessage_SomeGroup{ - GroupField: Int32(12), - }, - }, - }, - - // Semicolon between fields - { - in: `count:3;name:"Calvin"`, - out: &MyMessage{ - Count: Int32(3), - Name: String("Calvin"), - }, - }, - // Comma between fields - { - in: `count:4,name:"Ezekiel"`, - out: &MyMessage{ - Count: Int32(4), - Name: String("Ezekiel"), - }, - }, - - // Extension - buildExtStructTest(`count: 42 [testdata.Ext.more]:`), - buildExtStructTest(`count: 42 [testdata.Ext.more] {data:"Hello, world!"}`), - buildExtDataTest(`count: 42 [testdata.Ext.text]:"Hello, world!" [testdata.Ext.number]:1729`), - buildExtRepStringTest(`count: 42 [testdata.greeting]:"bula" [testdata.greeting]:"hola"`), - - // Big all-in-one - { - in: "count:42 # Meaning\n" + - `name:"Dave" ` + - `quote:"\"I didn't want to go.\"" ` + - `pet:"bunny" ` + - `pet:"kitty" ` + - `pet:"horsey" ` + - `inner:<` + - ` host:"footrest.syd" ` + - ` port:7001 ` + - ` connected:true ` + - `> ` + - `others:<` + - ` key:3735928559 ` + - ` value:"\x01A\a\f" ` + - `> ` + - `others:<` + - " weight:58.9 # Atomic weight of Co\n" + - ` inner:<` + - ` host:"lesha.mtv" ` + - ` port:8002 ` + - ` >` + - `>`, - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - Quote: String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &InnerMessage{ - Host: String("footrest.syd"), - Port: Int32(7001), - Connected: Bool(true), - }, - Others: []*OtherMessage{ - { - Key: Int64(3735928559), - Value: []byte{0x1, 'A', '\a', '\f'}, - }, - { - Weight: Float32(58.9), - Inner: &InnerMessage{ - Host: String("lesha.mtv"), - Port: Int32(8002), - }, - }, - }, - }, - }, -} - -func TestUnmarshalText(t *testing.T) { - for i, test := range unMarshalTextTests { - pb := new(MyMessage) - err := UnmarshalText(test.in, pb) - if test.err == "" { - // We don't expect failure. - if err != nil { - t.Errorf("Test %d: Unexpected error: %v", i, err) - } else if !reflect.DeepEqual(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } else { - // We do expect failure. - if err == nil { - t.Errorf("Test %d: Didn't get expected error: %v", i, test.err) - } else if err.Error() != test.err { - t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v", - i, err.Error(), test.err) - } else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !reflect.DeepEqual(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } - } -} - -func TestUnmarshalTextCustomMessage(t *testing.T) { - msg := &textMessage{} - if err := UnmarshalText("custom", msg); err != nil { - t.Errorf("Unexpected error from custom unmarshal: %v", err) - } - if UnmarshalText("not custom", msg) == nil { - t.Errorf("Didn't get expected error from custom unmarshal") - } -} - -// Regression test; this caused a panic. -func TestRepeatedEnum(t *testing.T) { - pb := new(RepeatedEnum) - if err := UnmarshalText("color: RED", pb); err != nil { - t.Fatal(err) - } - exp := &RepeatedEnum{ - Color: []RepeatedEnum_Color{RepeatedEnum_RED}, - } - if !Equal(pb, exp) { - t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp) - } -} - -func TestProto3TextParsing(t *testing.T) { - m := new(proto3pb.Message) - const in = `name: "Wallace" true_scotsman: true` - want := &proto3pb.Message{ - Name: "Wallace", - TrueScotsman: true, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -func TestMapParsing(t *testing.T) { - m := new(MessageWithMap) - const in = `name_mapping: name_mapping:` + - `msg_mapping:,>` + // separating commas are okay - `msg_mapping>` + // no colon after "value" - `byte_mapping:` - want := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Beatles", - 1234: "Feist", - }, - MsgMapping: map[int64]*FloatingPoint{ - -4: {F: Float64(2.0)}, - -2: {F: Float64(4.0)}, - }, - ByteMapping: map[bool][]byte{ - true: []byte("so be it"), - }, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -var benchInput string - -func init() { - benchInput = "count: 4\n" - for i := 0; i < 1000; i++ { - benchInput += "pet: \"fido\"\n" - } - - // Check it is valid input. - pb := new(MyMessage) - err := UnmarshalText(benchInput, pb) - if err != nil { - panic("Bad benchmark input: " + err.Error()) - } -} - -func BenchmarkUnmarshalText(b *testing.B) { - pb := new(MyMessage) - for i := 0; i < b.N; i++ { - UnmarshalText(benchInput, pb) - } - b.SetBytes(int64(len(benchInput))) -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_test.go deleted file mode 100644 index 64579e94..00000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_test.go +++ /dev/null @@ -1,450 +0,0 @@ -// 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_test - -import ( - "bytes" - "errors" - "io/ioutil" - "math" - "strings" - "testing" - - "github.com/golang/protobuf/proto" - - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -// textMessage implements the methods that allow it to marshal and unmarshal -// itself as text. -type textMessage struct { -} - -func (*textMessage) MarshalText() ([]byte, error) { - return []byte("custom"), nil -} - -func (*textMessage) UnmarshalText(bytes []byte) error { - if string(bytes) != "custom" { - return errors.New("expected 'custom'") - } - return nil -} - -func (*textMessage) Reset() {} -func (*textMessage) String() string { return "" } -func (*textMessage) ProtoMessage() {} - -func newTestMessage() *pb.MyMessage { - msg := &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Quote: proto.String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("footrest.syd"), - Port: proto.Int32(7001), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(0xdeadbeef), - Value: []byte{1, 65, 7, 12}, - }, - { - Weight: proto.Float32(6.022), - Inner: &pb.InnerMessage{ - Host: proto.String("lesha.mtv"), - Port: proto.Int32(8002), - }, - }, - }, - Bikeshed: pb.MyMessage_BLUE.Enum(), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(8), - }, - // One normally wouldn't do this. - // This is an undeclared tag 13, as a varint (wire type 0) with value 4. - XXX_unrecognized: []byte{13<<3 | 0, 4}, - } - ext := &pb.Ext{ - Data: proto.String("Big gobs for big rats"), - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil { - panic(err) - } - greetings := []string{"adg", "easy", "cow"} - if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil { - panic(err) - } - - // Add an unknown extension. We marshal a pb.Ext, and fake the ID. - b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")}) - if err != nil { - panic(err) - } - b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...) - proto.SetRawExtension(msg, 201, b) - - // Extensions can be plain fields, too, so let's test that. - b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19) - proto.SetRawExtension(msg, 202, b) - - return msg -} - -const text = `count: 42 -name: "Dave" -quote: "\"I didn't want to go.\"" -pet: "bunny" -pet: "kitty" -pet: "horsey" -inner: < - host: "footrest.syd" - port: 7001 - connected: true -> -others: < - key: 3735928559 - value: "\001A\007\014" -> -others: < - weight: 6.022 - inner: < - host: "lesha.mtv" - port: 8002 - > -> -bikeshed: BLUE -SomeGroup { - group_field: 8 -} -/* 2 unknown bytes */ -13: 4 -[testdata.Ext.more]: < - data: "Big gobs for big rats" -> -[testdata.greeting]: "adg" -[testdata.greeting]: "easy" -[testdata.greeting]: "cow" -/* 13 unknown bytes */ -201: "\t3G skiing" -/* 3 unknown bytes */ -202: 19 -` - -func TestMarshalText(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, newTestMessage()); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != text { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text) - } -} - -func TestMarshalTextCustomMessage(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, &textMessage{}); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != "custom" { - t.Errorf("Got %q, expected %q", s, "custom") - } -} -func TestMarshalTextNil(t *testing.T) { - want := "" - tests := []proto.Message{nil, (*pb.MyMessage)(nil)} - for i, test := range tests { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, test); err != nil { - t.Fatal(err) - } - if got := buf.String(); got != want { - t.Errorf("%d: got %q want %q", i, got, want) - } - } -} - -func TestMarshalTextUnknownEnum(t *testing.T) { - // The Color enum only specifies values 0-2. - m := &pb.MyMessage{Bikeshed: pb.MyMessage_Color(3).Enum()} - got := m.String() - const want = `bikeshed:3 ` - if got != want { - t.Errorf("\n got %q\nwant %q", got, want) - } -} - -func BenchmarkMarshalTextBuffered(b *testing.B) { - buf := new(bytes.Buffer) - m := newTestMessage() - for i := 0; i < b.N; i++ { - buf.Reset() - proto.MarshalText(buf, m) - } -} - -func BenchmarkMarshalTextUnbuffered(b *testing.B) { - w := ioutil.Discard - m := newTestMessage() - for i := 0; i < b.N; i++ { - proto.MarshalText(w, m) - } -} - -func compact(src string) string { - // s/[ \n]+/ /g; s/ $//; - dst := make([]byte, len(src)) - space, comment := false, false - j := 0 - for i := 0; i < len(src); i++ { - if strings.HasPrefix(src[i:], "/*") { - comment = true - i++ - continue - } - if comment && strings.HasPrefix(src[i:], "*/") { - comment = false - i++ - continue - } - if comment { - continue - } - c := src[i] - if c == ' ' || c == '\n' { - space = true - continue - } - if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') { - space = false - } - if c == '{' { - space = false - } - if space { - dst[j] = ' ' - j++ - space = false - } - dst[j] = c - j++ - } - if space { - dst[j] = ' ' - j++ - } - return string(dst[0:j]) -} - -var compactText = compact(text) - -func TestCompactText(t *testing.T) { - s := proto.CompactTextString(newTestMessage()) - if s != compactText { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText) - } -} - -func TestStringEscaping(t *testing.T) { - testCases := []struct { - in *pb.Strings - out string - }{ - { - // Test data from C++ test (TextFormatTest.StringEscape). - // Single divergence: we don't escape apostrophes. - &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")}, - "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n", - }, - { - // Test data from the same C++ test. - &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")}, - "string_field: \"\\350\\260\\267\\346\\255\\214\"\n", - }, - { - // Some UTF-8. - &pb.Strings{StringField: proto.String("\x00\x01\xff\x81")}, - `string_field: "\000\001\377\201"` + "\n", - }, - } - - for i, tc := range testCases { - var buf bytes.Buffer - if err := proto.MarshalText(&buf, tc.in); err != nil { - t.Errorf("proto.MarsalText: %v", err) - continue - } - s := buf.String() - if s != tc.out { - t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out) - continue - } - - // Check round-trip. - pb := new(pb.Strings) - if err := proto.UnmarshalText(s, pb); err != nil { - t.Errorf("#%d: UnmarshalText: %v", i, err) - continue - } - if !proto.Equal(pb, tc.in) { - t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb) - } - } -} - -// A limitedWriter accepts some output before it fails. -// This is a proxy for something like a nearly-full or imminently-failing disk, -// or a network connection that is about to die. -type limitedWriter struct { - b bytes.Buffer - limit int -} - -var outOfSpace = errors.New("proto: insufficient space") - -func (w *limitedWriter) Write(p []byte) (n int, err error) { - var avail = w.limit - w.b.Len() - if avail <= 0 { - return 0, outOfSpace - } - if len(p) <= avail { - return w.b.Write(p) - } - n, _ = w.b.Write(p[:avail]) - return n, outOfSpace -} - -func TestMarshalTextFailing(t *testing.T) { - // Try lots of different sizes to exercise more error code-paths. - for lim := 0; lim < len(text); lim++ { - buf := new(limitedWriter) - buf.limit = lim - err := proto.MarshalText(buf, newTestMessage()) - // We expect a certain error, but also some partial results in the buffer. - if err != outOfSpace { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", err, outOfSpace) - } - s := buf.b.String() - x := text[:buf.limit] - if s != x { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, x) - } - } -} - -func TestFloats(t *testing.T) { - tests := []struct { - f float64 - want string - }{ - {0, "0"}, - {4.7, "4.7"}, - {math.Inf(1), "inf"}, - {math.Inf(-1), "-inf"}, - {math.NaN(), "nan"}, - } - for _, test := range tests { - msg := &pb.FloatingPoint{F: &test.f} - got := strings.TrimSpace(msg.String()) - want := `f:` + test.want - if got != want { - t.Errorf("f=%f: got %q, want %q", test.f, got, want) - } - } -} - -func TestRepeatedNilText(t *testing.T) { - m := &pb.MessageList{ - Message: []*pb.MessageList_Message{ - nil, - &pb.MessageList_Message{ - Name: proto.String("Horse"), - }, - nil, - }, - } - want := `Message -Message { - name: "Horse" -} -Message -` - if s := proto.MarshalTextString(m); s != want { - t.Errorf(" got: %s\nwant: %s", s, want) - } -} - -func TestProto3Text(t *testing.T) { - tests := []struct { - m proto.Message - want string - }{ - // zero message - {&proto3pb.Message{}, ``}, - // zero message except for an empty byte slice - {&proto3pb.Message{Data: []byte{}}, ``}, - // trivial case - {&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`}, - // empty map - {&pb.MessageWithMap{}, ``}, - // non-empty map; map format is the same as a repeated struct, - // and they are sorted by key (numerically for numeric keys). - { - &pb.MessageWithMap{NameMapping: map[int32]string{ - -1: "Negatory", - 7: "Lucky", - 1234: "Feist", - 6345789: "Otis", - }}, - `name_mapping: ` + - `name_mapping: ` + - `name_mapping: ` + - `name_mapping:`, - }, - // map with nil value; not well-defined, but we shouldn't crash - { - &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}}, - `msg_mapping:`, - }, - } - for _, test := range tests { - got := strings.TrimSpace(test.m.String()) - if got != test.want { - t.Errorf("\n got %s\nwant %s", got, test.want) - } - } -} diff --git a/Godeps/_workspace/src/golang.org/x/image/bmp/reader.go b/Godeps/_workspace/src/golang.org/x/image/bmp/reader.go deleted file mode 100644 index a0f2715c..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/bmp/reader.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package bmp implements a BMP image decoder and encoder. -// -// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html. -package bmp // import "golang.org/x/image/bmp" - -import ( - "errors" - "image" - "image/color" - "io" -) - -// ErrUnsupported means that the input BMP image uses a valid but unsupported -// feature. -var ErrUnsupported = errors.New("bmp: unsupported BMP image") - -func readUint16(b []byte) uint16 { - return uint16(b[0]) | uint16(b[1])<<8 -} - -func readUint32(b []byte) uint32 { - return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 -} - -// decodePaletted reads an 8 bit-per-pixel BMP image from r. -// If topDown is false, the image rows will be read bottom-up. -func decodePaletted(r io.Reader, c image.Config, topDown bool) (image.Image, error) { - paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette)) - if c.Width == 0 || c.Height == 0 { - return paletted, nil - } - var tmp [4]byte - y0, y1, yDelta := c.Height-1, -1, -1 - if topDown { - y0, y1, yDelta = 0, c.Height, +1 - } - for y := y0; y != y1; y += yDelta { - p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width] - if _, err := io.ReadFull(r, p); err != nil { - return nil, err - } - // Each row is 4-byte aligned. - if c.Width%4 != 0 { - _, err := io.ReadFull(r, tmp[:4-c.Width%4]) - if err != nil { - return nil, err - } - } - } - return paletted, nil -} - -// decodeRGB reads a 24 bit-per-pixel BMP image from r. -// If topDown is false, the image rows will be read bottom-up. -func decodeRGB(r io.Reader, c image.Config, topDown bool) (image.Image, error) { - rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height)) - if c.Width == 0 || c.Height == 0 { - return rgba, nil - } - // There are 3 bytes per pixel, and each row is 4-byte aligned. - b := make([]byte, (3*c.Width+3)&^3) - y0, y1, yDelta := c.Height-1, -1, -1 - if topDown { - y0, y1, yDelta = 0, c.Height, +1 - } - for y := y0; y != y1; y += yDelta { - if _, err := io.ReadFull(r, b); err != nil { - return nil, err - } - p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4] - for i, j := 0, 0; i < len(p); i, j = i+4, j+3 { - // BMP images are stored in BGR order rather than RGB order. - p[i+0] = b[j+2] - p[i+1] = b[j+1] - p[i+2] = b[j+0] - p[i+3] = 0xFF - } - } - return rgba, nil -} - -// decodeNRGBA reads a 32 bit-per-pixel BMP image from r. -// If topDown is false, the image rows will be read bottom-up. -func decodeNRGBA(r io.Reader, c image.Config, topDown bool) (image.Image, error) { - rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height)) - if c.Width == 0 || c.Height == 0 { - return rgba, nil - } - y0, y1, yDelta := c.Height-1, -1, -1 - if topDown { - y0, y1, yDelta = 0, c.Height, +1 - } - for y := y0; y != y1; y += yDelta { - p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4] - if _, err := io.ReadFull(r, p); err != nil { - return nil, err - } - for i := 0; i < len(p); i += 4 { - // BMP images are stored in BGRA order rather than RGBA order. - p[i+0], p[i+2] = p[i+2], p[i+0] - } - } - return rgba, nil -} - -// Decode reads a BMP image from r and returns it as an image.Image. -// Limitation: The file must be 8, 24 or 32 bits per pixel. -func Decode(r io.Reader) (image.Image, error) { - c, bpp, topDown, err := decodeConfig(r) - if err != nil { - return nil, err - } - switch bpp { - case 8: - return decodePaletted(r, c, topDown) - case 24: - return decodeRGB(r, c, topDown) - case 32: - return decodeNRGBA(r, c, topDown) - } - panic("unreachable") -} - -// DecodeConfig returns the color model and dimensions of a BMP image without -// decoding the entire image. -// Limitation: The file must be 8, 24 or 32 bits per pixel. -func DecodeConfig(r io.Reader) (image.Config, error) { - config, _, _, err := decodeConfig(r) - return config, err -} - -func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, err error) { - // We only support those BMP images that are a BITMAPFILEHEADER - // immediately followed by a BITMAPINFOHEADER. - const ( - fileHeaderLen = 14 - infoHeaderLen = 40 - ) - var b [1024]byte - if _, err := io.ReadFull(r, b[:fileHeaderLen+infoHeaderLen]); err != nil { - return image.Config{}, 0, false, err - } - if string(b[:2]) != "BM" { - return image.Config{}, 0, false, errors.New("bmp: invalid format") - } - offset := readUint32(b[10:14]) - if readUint32(b[14:18]) != infoHeaderLen { - return image.Config{}, 0, false, ErrUnsupported - } - width := int(int32(readUint32(b[18:22]))) - height := int(int32(readUint32(b[22:26]))) - if height < 0 { - height, topDown = -height, true - } - if width < 0 || height < 0 { - return image.Config{}, 0, false, ErrUnsupported - } - // We only support 1 plane, 8 or 24 bits per pixel and no compression. - planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34]) - if planes != 1 || compression != 0 { - return image.Config{}, 0, false, ErrUnsupported - } - switch bpp { - case 8: - if offset != fileHeaderLen+infoHeaderLen+256*4 { - return image.Config{}, 0, false, ErrUnsupported - } - _, err = io.ReadFull(r, b[:256*4]) - if err != nil { - return image.Config{}, 0, false, err - } - pcm := make(color.Palette, 256) - for i := range pcm { - // BMP images are stored in BGR order rather than RGB order. - // Every 4th byte is padding. - pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF} - } - return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, nil - case 24: - if offset != fileHeaderLen+infoHeaderLen { - return image.Config{}, 0, false, ErrUnsupported - } - return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, nil - case 32: - if offset != fileHeaderLen+infoHeaderLen { - return image.Config{}, 0, false, ErrUnsupported - } - return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, nil - } - return image.Config{}, 0, false, ErrUnsupported -} - -func init() { - image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig) -} diff --git a/Godeps/_workspace/src/golang.org/x/image/bmp/reader_test.go b/Godeps/_workspace/src/golang.org/x/image/bmp/reader_test.go deleted file mode 100644 index fd6ff64f..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/bmp/reader_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// 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. - -package bmp - -import ( - "fmt" - "image" - "os" - "testing" - - _ "image/png" -) - -const testdataDir = "../testdata/" - -func compare(t *testing.T, img0, img1 image.Image) error { - b := img1.Bounds() - if !b.Eq(img0.Bounds()) { - return fmt.Errorf("wrong image size: want %s, got %s", img0.Bounds(), b) - } - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - c0 := img0.At(x, y) - c1 := img1.At(x, y) - r0, g0, b0, a0 := c0.RGBA() - r1, g1, b1, a1 := c1.RGBA() - if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 { - return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) - } - } - } - return nil -} - -// TestDecode tests that decoding a PNG image and a BMP image result in the -// same pixel data. -func TestDecode(t *testing.T) { - testCases := []string{ - "video-001", - "yellow_rose-small", - } - - for _, tc := range testCases { - f0, err := os.Open(testdataDir + tc + ".png") - if err != nil { - t.Errorf("%s: Open PNG: %v", tc, err) - continue - } - defer f0.Close() - img0, _, err := image.Decode(f0) - if err != nil { - t.Errorf("%s: Decode PNG: %v", tc, err) - continue - } - - f1, err := os.Open(testdataDir + tc + ".bmp") - if err != nil { - t.Errorf("%s: Open BMP: %v", tc, err) - continue - } - defer f1.Close() - img1, _, err := image.Decode(f1) - if err != nil { - t.Errorf("%s: Decode BMP: %v", tc, err) - continue - } - - if err := compare(t, img0, img1); err != nil { - t.Errorf("%s: %v", tc, err) - continue - } - } -} diff --git a/Godeps/_workspace/src/golang.org/x/image/bmp/writer.go b/Godeps/_workspace/src/golang.org/x/image/bmp/writer.go deleted file mode 100644 index 6947968a..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/bmp/writer.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bmp - -import ( - "encoding/binary" - "errors" - "image" - "io" -) - -type header struct { - sigBM [2]byte - fileSize uint32 - resverved [2]uint16 - pixOffset uint32 - dibHeaderSize uint32 - width uint32 - height uint32 - colorPlane uint16 - bpp uint16 - compression uint32 - imageSize uint32 - xPixelsPerMeter uint32 - yPixelsPerMeter uint32 - colorUse uint32 - colorImportant uint32 -} - -func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error { - var padding []byte - if dx < step { - padding = make([]byte, step-dx) - } - for y := dy - 1; y >= 0; y-- { - min := y*stride + 0 - max := y*stride + dx - if _, err := w.Write(pix[min:max]); err != nil { - return err - } - if padding != nil { - if _, err := w.Write(padding); err != nil { - return err - } - } - } - return nil -} - -func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int) error { - buf := make([]byte, step) - for y := dy - 1; y >= 0; y-- { - min := y*stride + 0 - max := y*stride + dx*4 - off := 0 - for i := min; i < max; i += 4 { - buf[off+2] = pix[i+0] - buf[off+1] = pix[i+1] - buf[off+0] = pix[i+2] - off += 3 - } - if _, err := w.Write(buf); err != nil { - return err - } - } - return nil -} - -func encode(w io.Writer, m image.Image, step int) error { - b := m.Bounds() - buf := make([]byte, step) - for y := b.Max.Y - 1; y >= b.Min.Y; y-- { - off := 0 - for x := b.Min.X; x < b.Max.X; x++ { - r, g, b, _ := m.At(x, y).RGBA() - buf[off+2] = byte(r >> 8) - buf[off+1] = byte(g >> 8) - buf[off+0] = byte(b >> 8) - off += 3 - } - if _, err := w.Write(buf); err != nil { - return err - } - } - return nil -} - -// Encode writes the image m to w in BMP format. -func Encode(w io.Writer, m image.Image) error { - d := m.Bounds().Size() - if d.X < 0 || d.Y < 0 { - return errors.New("bmp: negative bounds") - } - h := &header{ - sigBM: [2]byte{'B', 'M'}, - fileSize: 14 + 40, - pixOffset: 14 + 40, - dibHeaderSize: 40, - width: uint32(d.X), - height: uint32(d.Y), - colorPlane: 1, - } - - var step int - var palette []byte - switch m := m.(type) { - case *image.Gray: - step = (d.X + 3) &^ 3 - palette = make([]byte, 1024) - for i := 0; i < 256; i++ { - palette[i*4+0] = uint8(i) - palette[i*4+1] = uint8(i) - palette[i*4+2] = uint8(i) - palette[i*4+3] = 0xFF - } - h.imageSize = uint32(d.Y * step) - h.fileSize += uint32(len(palette)) + h.imageSize - h.pixOffset += uint32(len(palette)) - h.bpp = 8 - - case *image.Paletted: - step = (d.X + 3) &^ 3 - palette = make([]byte, 1024) - for i := 0; i < len(m.Palette) && i < 256; i++ { - r, g, b, _ := m.Palette[i].RGBA() - palette[i*4+0] = uint8(b >> 8) - palette[i*4+1] = uint8(g >> 8) - palette[i*4+2] = uint8(r >> 8) - palette[i*4+3] = 0xFF - } - h.imageSize = uint32(d.Y * step) - h.fileSize += uint32(len(palette)) + h.imageSize - h.pixOffset += uint32(len(palette)) - h.bpp = 8 - default: - step = (3*d.X + 3) &^ 3 - h.imageSize = uint32(d.Y * step) - h.fileSize += h.imageSize - h.bpp = 24 - } - - if err := binary.Write(w, binary.LittleEndian, h); err != nil { - return err - } - if palette != nil { - if err := binary.Write(w, binary.LittleEndian, palette); err != nil { - return err - } - } - - if d.X == 0 || d.Y == 0 { - return nil - } - - switch m := m.(type) { - case *image.Gray: - return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step) - case *image.Paletted: - return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step) - case *image.RGBA: - return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step) - } - return encode(w, m, step) -} diff --git a/Godeps/_workspace/src/golang.org/x/image/bmp/writer_test.go b/Godeps/_workspace/src/golang.org/x/image/bmp/writer_test.go deleted file mode 100644 index 9e5a3274..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/bmp/writer_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bmp - -import ( - "bytes" - "fmt" - "image" - "io/ioutil" - "os" - "testing" - "time" -) - -func openImage(filename string) (image.Image, error) { - f, err := os.Open(testdataDir + filename) - if err != nil { - return nil, err - } - defer f.Close() - return Decode(f) -} - -func TestEncode(t *testing.T) { - img0, err := openImage("video-001.bmp") - if err != nil { - t.Fatal(err) - } - - buf := new(bytes.Buffer) - err = Encode(buf, img0) - if err != nil { - t.Fatal(err) - } - - img1, err := Decode(buf) - if err != nil { - t.Fatal(err) - } - - compare(t, img0, img1) -} - -// TestZeroWidthVeryLargeHeight tests that encoding and decoding a degenerate -// image with zero width but over one billion pixels in height is faster than -// naively calling an io.Reader or io.Writer method once per row. -func TestZeroWidthVeryLargeHeight(t *testing.T) { - c := make(chan error, 1) - go func() { - b := image.Rect(0, 0, 0, 0x3fffffff) - var buf bytes.Buffer - if err := Encode(&buf, image.NewRGBA(b)); err != nil { - c <- err - return - } - m, err := Decode(&buf) - if err != nil { - c <- err - return - } - if got := m.Bounds(); got != b { - c <- fmt.Errorf("bounds: got %v, want %v", got, b) - return - } - c <- nil - }() - select { - case err := <-c: - if err != nil { - t.Fatal(err) - } - case <-time.After(3 * time.Second): - t.Fatalf("timed out") - } -} - -// BenchmarkEncode benchmarks the encoding of an image. -func BenchmarkEncode(b *testing.B) { - img, err := openImage("video-001.bmp") - if err != nil { - b.Fatal(err) - } - s := img.Bounds().Size() - b.SetBytes(int64(s.X * s.Y * 4)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Encode(ioutil.Discard, img) - } -} diff --git a/Godeps/_workspace/src/golang.org/x/image/font/font.go b/Godeps/_workspace/src/golang.org/x/image/font/font.go new file mode 100644 index 00000000..9cf43ff2 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/font/font.go @@ -0,0 +1,202 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package font defines an interface for font faces, for drawing text on an +// image. +// +// Other packages provide font face implementations. For example, a truetype +// package would provide one based on .ttf font files. +package font // import "golang.org/x/image/font" + +import ( + "image" + "image/draw" + "io" + + "golang.org/x/image/math/fixed" +) + +// TODO: who is responsible for caches (glyph images, glyph indices, kerns)? +// The Drawer or the Face? + +// Face is a font face. Its glyphs are often derived from a font file, such as +// "Comic_Sans_MS.ttf", but a face has a specific size, style, weight and +// hinting. For example, the 12pt and 18pt versions of Comic Sans are two +// different faces, even if derived from the same font file. +// +// A Face is not safe for concurrent use by multiple goroutines, as its methods +// may re-use implementation-specific caches and mask image buffers. +// +// To create a Face, look to other packages that implement specific font file +// formats. +type Face interface { + io.Closer + + // Glyph returns the draw.DrawMask parameters (dr, mask, maskp) to draw r's + // glyph at the sub-pixel destination location dot, and that glyph's + // advance width. + // + // It returns !ok if the face does not contain a glyph for r. + // + // The contents of the mask image returned by one Glyph call may change + // after the next Glyph call. Callers that want to cache the mask must make + // a copy. + Glyph(dot fixed.Point26_6, r rune) ( + dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) + + // GlyphBounds returns the bounding box of r's glyph, drawn at a dot equal + // to the origin, and that glyph's advance width. + // + // It returns !ok if the face does not contain a glyph for r. + // + // The glyph's ascent and descent equal -bounds.Min.Y and +bounds.Max.Y. A + // visual depiction of what these metrics are is at + // https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/Art/glyph_metrics_2x.png + GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) + + // GlyphAdvance returns the advance width of r's glyph. + // + // It returns !ok if the face does not contain a glyph for r. + GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) + + // Kern returns the horizontal adjustment for the kerning pair (r0, r1). A + // positive kern means to move the glyphs further apart. + Kern(r0, r1 rune) fixed.Int26_6 + + // TODO: per-font Metrics. + // TODO: ColoredGlyph for various emoji? + // TODO: Ligatures? Shaping? +} + +// TODO: Drawer.Layout or Drawer.Measure methods to measure text without +// drawing? + +// Drawer draws text on a destination image. +// +// A Drawer is not safe for concurrent use by multiple goroutines, since its +// Face is not. +type Drawer struct { + // Dst is the destination image. + Dst draw.Image + // Src is the source image. + Src image.Image + // Face provides the glyph mask images. + Face Face + // Dot is the baseline location to draw the next glyph. The majority of the + // affected pixels will be above and to the right of the dot, but some may + // be below or to the left. For example, drawing a 'j' in an italic face + // may affect pixels below and to the left of the dot. + Dot fixed.Point26_6 + + // TODO: Clip image.Image? + // TODO: SrcP image.Point for Src images other than *image.Uniform? How + // does it get updated during DrawString? +} + +// TODO: should DrawString return the last rune drawn, so the next DrawString +// call can kern beforehand? Or should that be the responsibility of the caller +// if they really want to do that, since they have to explicitly shift d.Dot +// anyway? +// +// In general, we'd have a DrawBytes([]byte) and DrawRuneReader(io.RuneReader) +// and the last case can't assume that you can rewind the stream. +// +// TODO: how does this work with line breaking: drawing text up until a +// vertical line? Should DrawString return the number of runes drawn? + +// DrawString draws s at the dot and advances the dot's location. +func (d *Drawer) DrawString(s string) { + var prevC rune + for i, c := range s { + if i != 0 { + d.Dot.X += d.Face.Kern(prevC, c) + } + dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c) + if !ok { + // TODO: is falling back on the U+FFFD glyph the responsibility of + // the Drawer or the Face? + // TODO: set prevC = '\ufffd'? + continue + } + draw.DrawMask(d.Dst, dr, d.Src, image.Point{}, mask, maskp, draw.Over) + d.Dot.X += advance + prevC = c + } +} + +// MeasureString returns how far dot would advance by drawing s. +func (d *Drawer) MeasureString(s string) (advance fixed.Int26_6) { + var prevC rune + for i, c := range s { + if i != 0 { + advance += d.Face.Kern(prevC, c) + } + a, ok := d.Face.GlyphAdvance(c) + if !ok { + // TODO: is falling back on the U+FFFD glyph the responsibility of + // the Drawer or the Face? + // TODO: set prevC = '\ufffd'? + continue + } + advance += a + prevC = c + } + return advance +} + +// Hinting selects how to quantize a vector font's glyph nodes. +// +// Not all fonts support hinting. +type Hinting int + +const ( + HintingNone Hinting = iota + HintingVertical + HintingFull +) + +// Stretch selects a normal, condensed, or expanded face. +// +// Not all fonts support stretches. +type Stretch int + +const ( + StretchUltraCondensed Stretch = -4 + StretchExtraCondensed Stretch = -3 + StretchCondensed Stretch = -2 + StretchSemiCondensed Stretch = -1 + StretchNormal Stretch = +0 + StretchSemiExpanded Stretch = +1 + StretchExpanded Stretch = +2 + StretchExtraExpanded Stretch = +3 + StretchUltraExpanded Stretch = +4 +) + +// Style selects a normal, italic, or oblique face. +// +// Not all fonts support styles. +type Style int + +const ( + StyleNormal Style = iota + StyleItalic + StyleOblique +) + +// Weight selects a normal, light or bold face. +// +// Not all fonts support weights. +type Weight int + +const ( + WeightThin Weight = 100 + WeightExtraLight Weight = 200 + WeightLight Weight = 300 + WeightNormal Weight = 400 + WeightMedium Weight = 500 + WeightSemiBold Weight = 600 + WeightBold Weight = 700 + WeightExtraBold Weight = 800 + WeightBlack Weight = 900 +) diff --git a/Godeps/_workspace/src/golang.org/x/image/font/plan9font/example_test.go b/Godeps/_workspace/src/golang.org/x/image/font/plan9font/example_test.go new file mode 100644 index 00000000..c1eacb23 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/font/plan9font/example_test.go @@ -0,0 +1,93 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package plan9font_test + +import ( + "image" + "image/draw" + "io/ioutil" + "log" + "os" + "path" + "path/filepath" + + "golang.org/x/image/font" + "golang.org/x/image/font/plan9font" + "golang.org/x/image/math/fixed" +) + +func ExampleParseFont() { + readFile := func(name string) ([]byte, error) { + return ioutil.ReadFile(filepath.FromSlash(path.Join("../testdata/fixed", name))) + } + fontData, err := readFile("unicode.7x13.font") + if err != nil { + log.Fatal(err) + } + face, err := plan9font.ParseFont(fontData, readFile) + if err != nil { + log.Fatal(err) + } + // TODO: derive the ascent from the face's metrics. + const ascent = 11 + + dst := image.NewRGBA(image.Rect(0, 0, 4*7, 13)) + draw.Draw(dst, dst.Bounds(), image.Black, image.Point{}, draw.Src) + d := &font.Drawer{ + Dst: dst, + Src: image.White, + Face: face, + Dot: fixed.P(0, ascent), + } + // Draw: + // - U+0053 LATIN CAPITAL LETTER S + // - U+03A3 GREEK CAPITAL LETTER SIGMA + // - U+222B INTEGRAL + // - U+3055 HIRAGANA LETTER SA + // The testdata does not contain the CJK subfont files, so U+3055 HIRAGANA + // LETTER SA (さ) should be rendered as U+FFFD REPLACEMENT CHARACTER (�). + // + // The missing subfont file will trigger an "open + // ../testdata/shinonome/k12.3000: no such file or directory" log message. + // This is expected and can be ignored. + d.DrawString("SΣ∫さ") + + // Convert the dst image to ASCII art. + var out []byte + b := dst.Bounds() + for y := b.Min.Y; y < b.Max.Y; y++ { + out = append(out, '0'+byte(y%10), ' ') + for x := b.Min.X; x < b.Max.X; x++ { + if dst.RGBAAt(x, y).R > 0 { + out = append(out, 'X') + } else { + out = append(out, '.') + } + } + // Highlight the last row before the baseline. Glyphs like 'S' without + // descenders should not affect any pixels whose Y coordinate is >= the + // baseline. + if y == ascent-1 { + out = append(out, '_') + } + out = append(out, '\n') + } + os.Stdout.Write(out) + + // Output: + // 0 ..................X......... + // 1 .................X.X........ + // 2 .XXXX..XXXXXX....X.....XXX.. + // 3 X....X.X.........X....XX.XX. + // 4 X.......X........X....X.X.X. + // 5 X........X.......X....XXX.X. + // 6 .XXXX.....X......X....XX.XX. + // 7 .....X...X.......X....XX.XX. + // 8 .....X..X........X....XXXXX. + // 9 X....X.X.........X....XX.XX. + // 0 .XXXX..XXXXXX....X.....XXX.._ + // 1 ...............X.X.......... + // 2 ................X........... +} diff --git a/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go b/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go new file mode 100644 index 00000000..da56ee89 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go @@ -0,0 +1,556 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package plan9font implements font faces for the Plan 9 font and subfont file +// formats. These formats are described at +// http://plan9.bell-labs.com/magic/man2html/6/font +package plan9font // import "golang.org/x/image/font/plan9font" + +// TODO: have a subface use an *image.Alpha instead of plan9Image implementing +// the image.Image interface? The image/draw code has a fast path for +// *image.Alpha masks. + +import ( + "bytes" + "errors" + "fmt" + "image" + "image/color" + "log" + "strconv" + "strings" + + "golang.org/x/image/font" + "golang.org/x/image/math/fixed" +) + +// fontchar describes one character glyph in a subfont. +// +// For more detail, look for "struct Fontchar" in +// http://plan9.bell-labs.com/magic/man2html/2/cachechars +type fontchar struct { + x uint32 // X position in the image holding the glyphs. + top uint8 // First non-zero scan line. + bottom uint8 // Last non-zero scan line. + left int8 // Offset of baseline. + width uint8 // Width of baseline. +} + +func parseFontchars(p []byte) []fontchar { + fc := make([]fontchar, len(p)/6) + for i := range fc { + fc[i] = fontchar{ + x: uint32(p[0]) | uint32(p[1])<<8, + top: uint8(p[2]), + bottom: uint8(p[3]), + left: int8(p[4]), + width: uint8(p[5]), + } + p = p[6:] + } + return fc +} + +// subface implements font.Face for a Plan 9 subfont. +type subface struct { + firstRune rune // First rune in the subfont. + n int // Number of characters in the subfont. + height int // Inter-line spacing. + ascent int // Height above the baseline. + fontchars []fontchar // Character descriptions. + img *plan9Image // Image holding the glyphs. +} + +func (f *subface) Close() error { return nil } +func (f *subface) Kern(r0, r1 rune) fixed.Int26_6 { return 0 } + +func (f *subface) Glyph(dot fixed.Point26_6, r rune) ( + dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) { + + r -= f.firstRune + if r < 0 || f.n <= int(r) { + return image.Rectangle{}, nil, image.Point{}, 0, false + } + i := &f.fontchars[r+0] + j := &f.fontchars[r+1] + + minX := int(dot.X+32)>>6 + int(i.left) + minY := int(dot.Y+32)>>6 + int(i.top) - f.ascent + dr = image.Rectangle{ + Min: image.Point{ + X: minX, + Y: minY, + }, + Max: image.Point{ + X: minX + int(j.x-i.x), + Y: minY + int(i.bottom) - int(i.top), + }, + } + return dr, f.img, image.Point{int(i.x), int(i.top)}, fixed.Int26_6(i.width) << 6, true +} + +func (f *subface) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) { + r -= f.firstRune + if r < 0 || f.n <= int(r) { + return fixed.Rectangle26_6{}, 0, false + } + i := &f.fontchars[r+0] + j := &f.fontchars[r+1] + + bounds = fixed.R( + int(i.left), + int(i.top)-f.ascent, + int(i.left)+int(j.x-i.x), + int(i.bottom)-f.ascent, + ) + return bounds, fixed.Int26_6(i.width) << 6, true +} + +func (f *subface) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) { + r -= f.firstRune + if r < 0 || f.n <= int(r) { + return 0, false + } + return fixed.Int26_6(f.fontchars[r].width) << 6, true +} + +// runeRange maps a single rune range [lo, hi] to a lazily loaded subface. Both +// ends of the range are inclusive. +type runeRange struct { + lo, hi rune + offset rune // subfont index that the lo rune maps to. + relFilename string + subface *subface + bad bool +} + +// face implements font.Face for a Plan 9 font. +// +// It maps multiple rune ranges to *subface values. Rune ranges may overlap; +// the first match wins. +type face struct { + height int + ascent int + readFile func(relFilename string) ([]byte, error) + runeRanges []runeRange +} + +func (f *face) Close() error { return nil } +func (f *face) Kern(r0, r1 rune) fixed.Int26_6 { return 0 } + +func (f *face) Glyph(dot fixed.Point26_6, r rune) ( + dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) { + + if s, rr := f.subface(r); s != nil { + return s.Glyph(dot, rr) + } + return image.Rectangle{}, nil, image.Point{}, 0, false +} + +func (f *face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) { + if s, rr := f.subface(r); s != nil { + return s.GlyphBounds(rr) + } + return fixed.Rectangle26_6{}, 0, false +} + +func (f *face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) { + if s, rr := f.subface(r); s != nil { + return s.GlyphAdvance(rr) + } + return 0, false +} + +func (f *face) subface(r rune) (*subface, rune) { + // Fall back on U+FFFD if we can't find r. + for _, rr := range [2]rune{r, '\ufffd'} { + // We have to do linear, not binary search. plan9port's + // lucsans/unicode.8.font says: + // 0x2591 0x2593 ../luc/Altshades.7.0 + // 0x2500 0x25ee ../luc/FormBlock.7.0 + // and the rune ranges overlap. + for i := range f.runeRanges { + x := &f.runeRanges[i] + if rr < x.lo || x.hi < rr || x.bad { + continue + } + if x.subface == nil { + data, err := f.readFile(x.relFilename) + if err != nil { + log.Printf("plan9font: couldn't read subfont %q: %v", x.relFilename, err) + x.bad = true + continue + } + sub, err := ParseSubfont(data, x.lo-x.offset) + if err != nil { + log.Printf("plan9font: couldn't parse subfont %q: %v", x.relFilename, err) + x.bad = true + continue + } + x.subface = sub.(*subface) + } + return x.subface, rr + } + } + return nil, 0 +} + +// ParseFont parses a Plan 9 font file. data is the contents of that font file, +// which gives relative filenames for subfont files. readFile returns the +// contents of those subfont files. It is similar to io/ioutil's ReadFile +// function, except that it takes a relative filename instead of an absolute +// one. +func ParseFont(data []byte, readFile func(relFilename string) ([]byte, error)) (font.Face, error) { + f := &face{ + readFile: readFile, + } + // TODO: don't use strconv, to avoid the conversions from []byte to string? + for first := true; len(data) > 0; first = false { + i := bytes.IndexByte(data, '\n') + if i < 0 { + return nil, errors.New("plan9font: invalid font: no final newline") + } + row := string(data[:i]) + data = data[i+1:] + if first { + height, s, ok := nextInt32(row) + if !ok { + return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row) + } + ascent, s, ok := nextInt32(s) + if !ok { + return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row) + } + if height < 0 || 0xffff < height || ascent < 0 || 0xffff < ascent { + return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row) + } + f.height, f.ascent = int(height), int(ascent) + continue + } + lo, s, ok := nextInt32(row) + if !ok { + return nil, fmt.Errorf("plan9font: invalid font: invalid row %q", row) + } + hi, s, ok := nextInt32(s) + if !ok { + return nil, fmt.Errorf("plan9font: invalid font: invalid row %q", row) + } + offset, s, _ := nextInt32(s) + + f.runeRanges = append(f.runeRanges, runeRange{ + lo: lo, + hi: hi, + offset: offset, + relFilename: s, + }) + } + return f, nil +} + +func nextInt32(s string) (ret int32, remaining string, ok bool) { + i := 0 + for ; i < len(s) && s[i] <= ' '; i++ { + } + j := i + for ; j < len(s) && s[j] > ' '; j++ { + } + n, err := strconv.ParseInt(s[i:j], 0, 32) + if err != nil { + return 0, s, false + } + for ; j < len(s) && s[j] <= ' '; j++ { + } + return int32(n), s[j:], true +} + +// ParseSubfont parses a Plan 9 subfont file. +// +// firstRune is the first rune in the subfont file. For example, the +// Phonetic.6.0 subfont, containing glyphs in the range U+0250 to U+02E9, would +// set firstRune to '\u0250'. +func ParseSubfont(data []byte, firstRune rune) (font.Face, error) { + data, m, err := parseImage(data) + if err != nil { + return nil, err + } + if len(data) < 3*12 { + return nil, errors.New("plan9font: invalid subfont: header too short") + } + n := atoi(data[0*12:]) + height := atoi(data[1*12:]) + ascent := atoi(data[2*12:]) + data = data[3*12:] + if len(data) != 6*(n+1) { + return nil, errors.New("plan9font: invalid subfont: data length mismatch") + } + return &subface{ + firstRune: firstRune, + n: n, + height: height, + ascent: ascent, + fontchars: parseFontchars(data), + img: m, + }, nil +} + +// plan9Image implements that subset of the Plan 9 image feature set that is +// used by this font file format. +// +// Some features, such as the repl bit and a clip rectangle, are omitted for +// simplicity. +type plan9Image struct { + depth int // Depth of the pixels in bits. + width int // Width in bytes of a single scan line. + rect image.Rectangle // Extent of the image. + pix []byte // Pixel bits. +} + +func (m *plan9Image) byteoffset(x, y int) int { + a := y * m.width + if m.depth < 8 { + // We need to always round down, but Go rounds toward zero. + np := 8 / m.depth + if x < 0 { + return a + (x-np+1)/np + } + return a + x/np + } + return a + x*(m.depth/8) +} + +func (m *plan9Image) Bounds() image.Rectangle { return m.rect } +func (m *plan9Image) ColorModel() color.Model { return color.AlphaModel } + +func (m *plan9Image) At(x, y int) color.Color { + if (image.Point{x, y}).In(m.rect) { + b := m.pix[m.byteoffset(x, y)] + switch m.depth { + case 1: + // CGrey, 1. + mask := uint8(1 << uint8(7-x&7)) + if (b & mask) != 0 { + return color.Alpha{0xff} + } + return color.Alpha{0x00} + case 2: + // CGrey, 2. + shift := uint(x&3) << 1 + // Place pixel at top of word. + y := b << shift + y &= 0xc0 + // Replicate throughout. + y |= y >> 2 + y |= y >> 4 + return color.Alpha{y} + } + } + return color.Alpha{0x00} +} + +var compressed = []byte("compressed\n") + +func parseImage(data []byte) (remainingData []byte, m *plan9Image, retErr error) { + if !bytes.HasPrefix(data, compressed) { + return nil, nil, errors.New("plan9font: unsupported uncompressed format") + } + data = data[len(compressed):] + + const hdrSize = 5 * 12 + if len(data) < hdrSize { + return nil, nil, errors.New("plan9font: invalid image: header too short") + } + hdr, data := data[:hdrSize], data[hdrSize:] + + // Distinguish new channel descriptor from old ldepth. Channel descriptors + // have letters as well as numbers, while ldepths are a single digit + // formatted as %-11d. + new := false + for m := 0; m < 10; m++ { + if hdr[m] != ' ' { + new = true + break + } + } + if hdr[11] != ' ' { + return nil, nil, errors.New("plan9font: invalid image: bad header") + } + if !new { + return nil, nil, errors.New("plan9font: unsupported ldepth format") + } + + depth := 0 + switch s := strings.TrimSpace(string(hdr[:1*12])); s { + default: + return nil, nil, fmt.Errorf("plan9font: unsupported pixel format %q", s) + case "k1": + depth = 1 + case "k2": + depth = 2 + } + r := ator(hdr[1*12:]) + if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y { + return nil, nil, errors.New("plan9font: invalid image: bad rectangle") + } + + width := bytesPerLine(r, depth) + m = &plan9Image{ + depth: depth, + width: width, + rect: r, + pix: make([]byte, width*r.Dy()), + } + + miny := r.Min.Y + for miny != r.Max.Y { + if len(data) < 2*12 { + return nil, nil, errors.New("plan9font: invalid image: data band too short") + } + maxy := atoi(data[0*12:]) + nb := atoi(data[1*12:]) + data = data[2*12:] + + if len(data) < nb { + return nil, nil, errors.New("plan9font: invalid image: data band length mismatch") + } + buf := data[:nb] + data = data[nb:] + + if maxy <= miny || r.Max.Y < maxy { + return nil, nil, fmt.Errorf("plan9font: bad maxy %d", maxy) + } + // An old-format image would flip the bits here, but we don't support + // the old format. + rr := r + rr.Min.Y = miny + rr.Max.Y = maxy + if err := decompress(m, rr, buf); err != nil { + return nil, nil, err + } + miny = maxy + } + return data, m, nil +} + +// Compressed data are sequences of byte codes. If the first byte b has the +// 0x80 bit set, the next (b^0x80)+1 bytes are data. Otherwise, these two bytes +// specify a previous string to repeat. +const ( + compShortestMatch = 3 // shortest match possible. + compWindowSize = 1024 // window size. +) + +var ( + errDecompressBufferTooSmall = errors.New("plan9font: decompress: buffer too small") + errDecompressPhaseError = errors.New("plan9font: decompress: phase error") +) + +func decompress(m *plan9Image, r image.Rectangle, data []byte) error { + if !r.In(m.rect) { + return errors.New("plan9font: decompress: bad rectangle") + } + bpl := bytesPerLine(r, m.depth) + mem := make([]byte, compWindowSize) + memi := 0 + omemi := -1 + y := r.Min.Y + linei := m.byteoffset(r.Min.X, y) + eline := linei + bpl + datai := 0 + for { + if linei == eline { + y++ + if y == r.Max.Y { + break + } + linei = m.byteoffset(r.Min.X, y) + eline = linei + bpl + } + if datai == len(data) { + return errDecompressBufferTooSmall + } + c := data[datai] + datai++ + if c >= 128 { + for cnt := c - 128 + 1; cnt != 0; cnt-- { + if datai == len(data) { + return errDecompressBufferTooSmall + } + if linei == eline { + return errDecompressPhaseError + } + m.pix[linei] = data[datai] + linei++ + mem[memi] = data[datai] + memi++ + datai++ + if memi == len(mem) { + memi = 0 + } + } + } else { + if datai == len(data) { + return errDecompressBufferTooSmall + } + offs := int(data[datai]) + ((int(c) & 3) << 8) + 1 + datai++ + if memi < offs { + omemi = memi + (compWindowSize - offs) + } else { + omemi = memi - offs + } + for cnt := (c >> 2) + compShortestMatch; cnt != 0; cnt-- { + if linei == eline { + return errDecompressPhaseError + } + m.pix[linei] = mem[omemi] + linei++ + mem[memi] = mem[omemi] + memi++ + omemi++ + if omemi == len(mem) { + omemi = 0 + } + if memi == len(mem) { + memi = 0 + } + } + } + } + return nil +} + +func ator(b []byte) image.Rectangle { + return image.Rectangle{atop(b), atop(b[2*12:])} +} + +func atop(b []byte) image.Point { + return image.Pt(atoi(b), atoi(b[12:])) +} + +func atoi(b []byte) int { + i := 0 + for ; i < len(b) && b[i] == ' '; i++ { + } + n := 0 + for ; i < len(b) && '0' <= b[i] && b[i] <= '9'; i++ { + n = n*10 + int(b[i]) - '0' + } + return n +} + +func bytesPerLine(r image.Rectangle, depth int) int { + if depth <= 0 || 32 < depth { + panic("invalid depth") + } + var l int + if r.Min.X >= 0 { + l = (r.Max.X*depth + 7) / 8 + l -= (r.Min.X * depth) / 8 + } else { + // Make positive before divide. + t := (-r.Min.X*depth + 7) / 8 + l = t + (r.Max.X*depth+7)/8 + } + return l +} diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0000 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0000 new file mode 100644 index 0000000000000000000000000000000000000000..9509cdf97f478dc67f631cc67d25490eef825a10 GIT binary patch literal 3136 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 S@91gtL-Z2*84Bsr5Aa{3E_&qv literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0200 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0200 new file mode 100644 index 0000000000000000000000000000000000000000..e25247ecc749f4c6a9d76644593ead99e2b08db0 GIT binary patch literal 3095 zcmdVc|8o@O9S88w?mc(6mmImh%LWe;!rtWqN2(?PY)^WI&CWqinwle~72C8E`7%Od zHImVWPKvvGdzZVAkh>siZ7m5<5Vc|*ucK314-!OcD`Iu%x6uHlAfq)%Td*>1H}4tk zFZK`U{_xsoo|(@+pXc*D^E|umo^SVT-q72-VSS1G$Czkj+uyk4 zv)YX}EM6+7bKI1Rs)^ zET3E*i1u;Q9?k8K+h|92ImNl=7R^mDy3Q;k5`@sLnohQ)!`+}&dBqZg<3uqmIFe;m zVwZGpX2KLi61X8h6*P^m*L+;t_R&2Kw_lV4oG|JaDX{3>A=#BBAzb9m?Mx8uTl7jw zH{>SkUsv>=`1Gb_m-qa&I~Ci{n6FcspN=(mOv zjuDx>5tdE~E}=f@4T?GD)ELbf2*m_Z*~!P~wb8C3uk%tYA&-tTUJfS|BgNKhO2BRq z6etn!;2s7hJ0}mF;OQ zBzeK>b%$rYA=IRbWRgEb{koDT56@92L8oGi`xrYIDWQiE&k%ZW)+AP6e~&e489)L8|-{&s&RufEW8#OW9kpU;-BcqkCpLU8lPv}>h~-DFJ;5Y-+vN}5 z(PdFTH{c1nS8!t?&#tDAE}gcI>7wL6$`GM#H;^LSaWsOw1N)gQZvMw1%xRb{a# zX+ge!R=4ITyU*Tja^xgpqjaZOFmi?}6owj9Y6+-jmJEpHtw{~js(k5Wv*8iMEqpkUuZzoi%>XMHZ^n06W2`&(R(%Jz zFS&QHBFNhquXS}6LLMuwhYCcg)Ldz!I5sB{X{r^RvDUtZ3dY{JZtvD(aXv5-@$&2Q-e4xcClphNjXDBa6Mr(R z&knyG%eU`qt!RC!H0?a99S)wY=r#g}Cv8uRn-|It9$y~q|LD@Wk?N>v_?+8+w5)Hs z`It7Y_Vr#qf6I%d4^X8py6T5>Qwt5or(72YJiA0%^K59fZP*;2*stWQfkte@BOP9D zPnkDp)|{Jan-n51QyhXuEhc%=f ztcuAr<*qaQ&JpPbEg}?jhd_3BLkDSm&G=27pIioum;A3gqERNIS>&|#l%;hXTUNj- zSOe=|BaFc1a3%aQ?0{c~YvCr?1HS{e!W0~WJK&>m96k;Y!k@ukz)AQjd;|U-PFWKm z`cy0bbLjso{5!k~ZQRW4N}w0|;e5CNUI&-LFGB0Ou%d2;33wa)CO0$g|Akim8<6u| zuor$8>M#RG;6v~+xEDSNpM@{LB0L6PgKxn}p@NIY&z6USCe?rbalc4}Ta5kI= rL-2EOF}x8fum#=%zXChqI`}PkFYJR4z%(3&55gb7-SB{YW)=Pe>1k#m literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0300 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0300 new file mode 100644 index 0000000000000000000000000000000000000000..86eb33f42fb587cc7a9f356f8a344a775fd56dcb GIT binary patch literal 2631 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 E1dQH-2LJ#7 literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0E00 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.0E00 new file mode 100644 index 0000000000000000000000000000000000000000..7c51a1e511a5919063c2bc729f41ed9815e67342 GIT binary patch literal 1235 zcmZwFe`s4(6bJB=_d@%YzIBPFBh)ybuQ4QD#U%aVHnW=5q-5cWVa>Xd)q$P;qgu7B zf4Ge>^3o<**0C(vGS;zQ)kYGcv{fny4jlAX5L9G>ihoqXR_IVRwt>iCCSM3c==tMw z&$(PK=UndLk3JYVGB`Rq_^w8(#{2eaR$grz<{h@3PxtMu8|Lk89a5M=Z>y=A+?sns@xD0g(dXX$**c|U#5{MNS4 zytQd5>F6v@Y;6h7I~NnB<>WT!!h??GWUI;)UKRUebLwl&>SI5dSgf72QgD{ekKesz z?T>YB`gA()pK?7~pSJqvT_QW%wRlQz@lSOv)^%78-EgQjiQf_%R~psPoYpr{T25bb z9-ZsCd3BZw3zq!__a}`jXVY14%K4HtTj-k%c@uhzFEik&TWac4f`K8~%oHaHB8&5X zsw@2qy7+{C`~Ive?7LOV6)5K}W(wYPV^OEiucREF^=!eLl20b|d0$3$ugInqCD=c? z?=z-wea1?rEqh;z~%6H~P&lI@+LQTdKXOAU>9o0;d{`aHo5>;a})z%V~t%nWJ2%BItw8I_nb=VExgaLRE4!|Ke z0zZZ)U=*H)=intc1#@r)ehqKH1^7Mu8U6-W;TrrKK7x-Sud2+YfjVe_FF-SV8MeXK zU>DpA{qO)h1P9?T9EHcB0#Cvuyr8N)@rIVWx`H#)umHb=-@xzSGW-Gl0{?&|xDM~b jf8Y~X!&Ro<4E69iC_^i>!B=4?^gsrCU=Y5;Ri^k4X&(gZ literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1000 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1000 new file mode 100644 index 0000000000000000000000000000000000000000..019698c8d105992723c6ad0e43f181a62e703908 GIT binary patch literal 2354 zcmeIyacCP=90%~5NVr=;va5x45n`A^#?_S{^fr{ z-@)g;+&v!ezC7;O3(u!t932}QJua%70Vjz z)b{x&V%=<=(*??GXv z#XRFnS)paq-H7llyi zH>K@lD>?e-N+LVozSLV;b;@1V@8lgPV_1@u$gm8PfPP%=3$5DCD3d;FSuotdCIB+ z%_{||(iI^p7tHE*RG`cTI%m%6mah^%QZQ_xVs&eVDJY3)D31rnYKA|^3&)(pGi3P2 z4Grkxgs(2_?CiRmt7$@O$R>(5eac|#t9w{EWI0k8rVQ(PCFi_-@V3~Tal3xG=XIv4 zcV(?r1^gK!4PstkU^%DSO0XmA?u}$^PLw!+Nt%Okx$fDOIVgb08lWkceyY~LF)IPQ zY^^T?gUyq@zhnPqRMmeS_?QaYW4nRv2L8_tG(kfHfU6&EK|^R8x)+V152KxE4|*6K zM4v!M&}Yyz`U-jiwb5zx4Rju@q6_FE`XTxedIkLgy^4N^E~7u8zoIwM+o*@z_%6}? z;Q{<--4$e9Cy3sM?nduN51@~t2HJ}z(Z|sz(NXj{bPRnJ&7cliMCZ`A&n1Kjhc4>YrMkJbE^cn(>d!CaiJ^2C@`lg*@_FBTy!+jK{3v>|xU{r* zPnU!Bpgc&lyQk*L%uwTG<+5(m4Er7zT`$!-t3g+PVdYtU zT_&NgYmOhJ6Cb%)Suk}bSgku=;58;*_OhDo2PfyfUNPA9%q$bU6Bl@gUdc7h@)Lu9 z;F^0>&(*l#`#BLy+JCLA)lIGQCq?x4gW*)B=LS*Ae`Z#eY_vub7){`Rp1>r_Wbl3> z;+0uRA2;8*k&secS} O2C4HM-~Ir9qW>F8LVdab literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1E00 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1E00 new file mode 100644 index 0000000000000000000000000000000000000000..3bc5068cfbdcf5a47f9af710fee2b583184d9da6 GIT binary patch literal 3713 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 literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1F00 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.1F00 new file mode 100644 index 0000000000000000000000000000000000000000..43b320be121764eaa703e070c1514324f44573f5 GIT binary patch literal 3012 zcmZwJe{>Yp6$kLQlgaY3nF*6MV#rdMUBr0*53R}(EI*1623sTb*wnU`0tI{8N~+ctYVF&vhtNN| ze|+|yyLaBZcg{QS?2^a7-`vu)VntJzxDqY7tSgEpPItrn>9D%!s3$I zDkCB>y4SEoH2!q_SiE~`QSJVKY}CJ@$#SugepRCEEq6tf zu_;ckWQ!|G{n7NzJH;$*v|I6QadirG?8WcCxoys)R34nW?z8Kko)^SOv5Fw}Js(3Ok5q(($vB)`xul2g`pPCaD7Ur_)Wc#7r zGefL$NHqp0lgfqT)w@I@mMmX9vSB*aBdXIP5)y9;_T|=e+Nqq#4mFg;1VK@JKHt2W zf$F9}k0z=rV=UTZ_XicVTy(H9q8kI%iZ|MqA4*s>z1=B@RB;Lx-mJ=^qM|67yjd+! zAR9ivD!&@Me4dB}wd6#8P$bHJ!h|UW4P||9|N4T}*Rp0gh&PyNuh=xVJnAbydo(k@ zFKBlPgw`G)-f%)uGk3&?&h+M29crQJQMW#LJfhqdw^a=n4VnE)Zk%?yw2t1~w0D`n z8yhZCa>F&li*9ij=o*o9b}3`qQn|gs=?Zla)nZ#6SA9M1fFjcD*bGV)!=gM8p*^-N zMURsnmp?(2r&oS(?%Daz+@n?Y0Nis-{Cp*gfMB7v)tcF8;q4# z`1@(96b_O))-1{4pj{L1VjYSsk|>Hl&#mF z9v$>$^SriCH;wvZyx}6=?6uVXHd8aB&WN25%8Wgge6y{r!)F?uX`+>>ZKh%xBh|#k z(rn#dyn#M9t;|Erv{|G?(%W;Zc6eg+SUZ2W?gf0j#?yY21>_|xq>Rx#)J0`G<8FbG5NoA4pn1RsSf;2LPa4!8+E1)qUKa4$Rv55c4G6#RuHIq-zM^LLQ{ zExZ8#49DR=Q9mKC{~UR%kephESX50nflu_-pt+{1f~u{1{$`LQ1m3G^oJa;PjN_ zj1%&j+mSDT#qb_j1_ST`xCnj+Ho`|>3tSBuY=;|RAKVUi!{^}v_$vGvd;`7-e+A!z ze}o^vtMF6!ADAj8CzaqWFb6uJ8-4}OfnSAw_;pwfzXj{z_uymj2e1uB;Ck4@|7Z}x z<-0!(cfudTpTL*kYw$Q6fp5Wg;qT!k_!syQyoU9;e0@u5QVJ)-Dey~BgR@`}yc_!9 zeQ-Wp2p>#Mc0M6rc?t5%;S;bG{s_iV&*hcf@JYB0?t;T`KYRtg4o||f@ErUNJP)tH u58*%HXHc{z_e!@W`<#$x?8r}rDt_hi{2lO4I2(H4*I*@F0BhmHc=o?@0a_XW literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2000 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2000 new file mode 100644 index 0000000000000000000000000000000000000000..f9244e1cf9f08933d03d080bd3ddb875f53b8fa6 GIT binary patch literal 2310 zcmdVae{2(F7zgm@uJ6{P>$)43P;e=?GDv{|9h*?yaGey=MbI(kFN{XCGngSv-b4rT z<9)B|R$%NG&WM@P%_WS1Vn`G*kZr+*L=#aGBPJ$bh}IZ2Tf*WHGrfM3X-tSQ{$cd~ z_}rT}_dM_Oy!YNcwe8vZ?X{fOMjgh~RaZ1MvhIOfj_+Jn^2dBp@h!)}z#WF5UF0Td zo7gosL`{Ys%4%(AdUi~0w~q#WO)+v#-=e(j$%(V+H5Kzh&Mavc#N^mjEvs31L{;-V z^&y%rH6yS}_zRp(yCy=;^@Dq8YxBU-^6r&4ei{udj#nu*auyI5Qh!cH8r?kRA0>_K zFEQa;v%#uB*(fq~L+_~|m#!CvTN-Ypu8G{Tp#;rM9HBNd)M{g?ggVfl>kb0^q(-Y7uRyC8ZSNX#ST^;VR>zleo95@j~0+-pM>Jb6%$mF=RzE=Jp4O zcd#;j>?_~;Ifdg5ie2^SMulTl3E%&DG;8qeCj%#DI0YmOV43 zsg-^;`+!PihVX@}75{jHe}x&6cJIjk9o6wx$06g`ccdl1H_jY`$-aRT1rDc&%Y6Z>{$AoWTuQs^w0Pf{ zQZ8ycW2GV_*o)G?dugqi6sC9NVE#ZCyRXCOt8R%_vh6c2ih5g}nH-K14{*6*LMe|C zMaXs}u0{H3+5@vs$NdH~ST2RMRA7afl!}#P<=EF*Egi;t)i>WrG;Ue6NcM)U_|hzw zNz@*=O(?FX<&c9itm9f%9HXR};T;hQWw6z=zISU)_VVrq#X6v+*6|NjDfjBf7>|%y zao#FWyX5RE){J<4~)YWcnH10NTbTSZQ+@xpnq5EjF`Ubg literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2100 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2100 new file mode 100644 index 0000000000000000000000000000000000000000..c565abb7d261646173a5c30caa7f1a325b4c534c GIT binary patch literal 3206 zcmd7TeQ?wE83*u3ikv83USuKKTpK`k3>eBr0x5*T9N9C>xLxBIr$7fIgqP8!8wuP- z*aafVcH%f`NkZt#SRpn^d1-lD5x3sDl7wy@Y%8OqP22TGNGWu5-G!GPVGCr=cjI=w z>!15$(%nbDlXO2ldZg$1ty=&6sts#4Zd|k4EZ^HI3+|1Q$NVoF7Zg4`>%ZpCUZd zNF|20T)WZDtWuq#JB9WpJ#|wiR=gu&6mL&d^%F?^KqMCRk zqNZ8+Wb9Lt(Y@5=Yv~cnd$}6c-X6_0rI(hpcey6|TBio%f#9(~+-0?gSvl+@ipa^S zs#r743wP*jMvlYKh1Ru{narHtK+S4^jPQ2zV{#g;SF42MDnqBpsZl8X)n~cv3z{-0 zG?(0*Jcno{XVj;cvRM}`0`uF5X5u7zkDEw`L;adLOy(w+%QUy$;g2sQlG?j`T3$5?q8b?WI}`#~k*X%oHv&NoUKMG%^m30L2dDWFluf#F5BF0E*l zc~9J(sY_E9-?+|X56hNC1EQO6vG-adW}Bx`oU*4s@%*~CHB;sT$~lWGG>>kNVQdXxEJ_>Qr4b@R=eMn+E7`NdnW3t!VrELUW&9&>r|?s>f6dbI52 zrPUj@hkoL$C7JDFtnQpK?BpFYZB^HacHqs1eiuDE^niqkoqH>ge6bGPookm67G3V}n*#0txuA!XZz zFrV-5N$pE8W?znp+Vy}n=Xl-7$ekOXR?JdI?xuSunk7fI=$IXAHzox%lPT8Cxg~e7 z)y4~&uk6S+r?Vlc2Re<6+2Z$v@g&(enUrxJ7rEpR?2%qBp8{Ms#`GV zlpYYQoRMDHWK-juX!B38CETK^a#zI5*zJve)o<|#t=(6d3Ja-9vVM5QZyQ^=`{UxW zEsMp%nikd*Rl+Q@uw(4zlI3qnj*Tblo=CkF^TxE4SfDrRmRw}Sh4k)Nu(MQixBG%! zONeLAq={}${Kh9O`AS$39gQp*O|lY7&B)0wZ?$<;$uReEhGjEvuziPFZmMIy%gn~? zvd|KaHG1tf_ueooIsAzZfAQ9`LDeR=FD;mo={DKj3ac%q9)A|yjl`}MVm@-9cQ?jyI%B3n>2BW4WG&PMl zU1oZ|awNiZ`vtCu?pL+6kLr_+CpAZ@VJaKvMrD~$-Kl-`98cuxVJWkjlI5K>>*=Ar zPf2QfY{Aa{o^$cnNU>Lt@uFNUu4(UdYOYJ3U{`=LXj}Iy^J+wKdiMCDn$XRXjFU6? z+uc2;%4F*mt%9MiIP2sLDYIeQIL~N5Wa)NDma;S{5gCTcEdN}TkswDA^Zqlh1cK^9D%9Hf}*rcD8UDz4Nigia5i+p`S3Bg2tEl{ z!gX*x{1My&!>|dq!JV)J?t_P+0bhfs;2C%hz6USB%kVRJlO6qP{}Yor`6uRNQ%3WX z4h48W91kbLX>cZd1iGLXmcS?Aa=02+!VPdURAB>r7VdyQgL~mYcntmmo`k=Fe}L!V zpWy)fD;$Kk;9Y3qM&B+2j)4zAD|Eo=a2EVJ^uR}904{~)@VoE_@Q1J#hF}b~!sp>0 z_#!+6kHcTWUU(Y*5hgotGUmU)kKy0o4fqepm`3m6VK%%Ej)Qji5S#($Km~piJ`T&^ eGPnwU4_3n(SO@FjGq4@*f(dv49yN{rpZ@}k1G%{X literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2200 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2200 new file mode 100644 index 0000000000000000000000000000000000000000..a992d3521af0e7ef6bdc2571c9464ab4685208d1 GIT binary patch literal 3532 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 JL(-$4=s)CzBGUi> literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2300 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2300 new file mode 100644 index 0000000000000000000000000000000000000000..8ff099d19e02f6fad93292917f7803c5b6424aad GIT binary patch literal 1613 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 literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2600 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2600 new file mode 100644 index 0000000000000000000000000000000000000000..1b393c28ba2753ccfd5a68b0b683f35979da9d16 GIT binary patch literal 1765 zcmaLWeN0nV6aetk#{=4~mIt=32(gb+W@((E2+B4rr61brHbF{sI#+aJG-I>VxakD; z`tdBS4k$7weo=Fj_gUG?nvrGf&Qfj5ESauXSGRaPx9 z-~`}=nPQPA;Q<4gMRbG#zF>nuY;y^XTAL&fNL!L%&S91+1scEwpu5cg@q}C$KR7Y| zkURYoAgRUhvEJ$pr@)%+l6kvGV>{RSJ_URC(T0j>6+qER!UsU#yu2~2nGsr*2Qw*f zIRuhYo~jgF6bu>&l5~;_Sq9jQd>SsFBRP-Cj2@GoZgw2%>T_D7cdr~&*NlD6@7~t; z!~Ve@NVir#7Bx#7^|6FV1X4G!W7)@~r|LJxIL|R8jJUNL`$bV{dX=4NG20&IXi07Z zXGlXfX0jP7t%kHTrqPG{)rwejFn#WIQO9(FTA5Nkpe`hOL_GZC_Id#ja29rX5njcuh_h_A7(&8@OF*bN%5h<#z zg3vDRr`1cdE@(OpFmJB6(NwrK@ z!!yu@D^r|mN)@(A%!s{VPPgE^D!w>(^rrnupH_B*(Ky!tr|xoN3PI~IHZT< zryl!wmGs{e<9|K4MOy5mJpcqE9Bp~6GX%oJ) z0|&~0A*F6cxv~U+QGjQ?l!2+HR;dc6LYn?hf2(K!m=y~)K`V%^UM$lpO zKKclKf+ldDR>4P8Q3)zVUqD|(3(!|kEowr`&=u%gXf;}cZbd&rZD<49gziHRqXD!N zJ%gS@!|3>&}e97$=aE(X>Hkp|@kQwF6XAut*OqaiRF0<;VP zUIun{1_mI>2PQ?qqzsr;29sJ~+sPn-W*UM`umF?xVA2gt`hv+2Fc}RdlfYyqm@EL3 HDtpE`qy?4PvZ;9lNApp{|YHii#2jAPCqOB@`3v#O^Na1RE6<6AZxa zZn4-0SKu7(d+u-kGw00Q^UjCs8Q>on76+GvmUu_?C3j@SeHp*Q+rFpkA=oPslP0WQO}xCM9PL5#<I6tw8n~99o6WBjj%boVHfO;18^_~;7AO`i8vkS;9^{f8*n@B z#UpqU&to#CU^+g**Z2uD(a=cOml;}MDJ+LJSPSjY1)E?i?10^|FM6Rb2H_YC!^s$f z^KmJz!Oge}58!b;gGqQD@8AP`j_>d*{zemHU3UsBhNZCrR>QjJhz(JTZLu@UzxHZH;yxE{CR9z2XEFcGidElk75_zFMb4>T~*^;G~1V@WKFm9Zw;qBFW; zOKgwb&>cN-C=SQbI02(D8s}jwuEtHc6ZhjWJdGFe8s5hH_zd6T7yO0BlCHagSQM>L zg;lW*I$#5AhHbDD_Qd|^gZ>zT<1hlJ;w)T<%W)lU#W*~K33v`K<4wGWkMJda!0#xs Ie*HrH1wPyIyZ`_I literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2A00 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.2A00 new file mode 100644 index 0000000000000000000000000000000000000000..71791ace691545674d3417fe10dbcdc5b74d48b2 GIT binary patch literal 620 zcmYe!&n+lQEiO(?;ZlHsY(p3eNE={hn1f{i&qtGkqp?*@fTN{V zZSDFGEXvI-E4QxXFlBIOkZN*b{L@-d@c8(J{S1*33~;;6OyEofWM>!}DljlG@G`Ko ugGoLxDGDZKz@##m)B=-+K&1=}a1yA?0xUvj5@@eI*xq440{!9!_6q=D;Yn2h literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.3000 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.3000 new file mode 100644 index 0000000000000000000000000000000000000000..fb830f4fbf7ba957f62b83c140db986580d02159 GIT binary patch literal 569 zcmYe!&n+lQEiO(?;ZlHsY(p3eNE={h8=E4;4UMt0O)L}|7+4ruL>)grU}(`;=&=3( z154wY1C0TJKw*}~)eemdG#OYpI5~tlWI5D13^^F!2AP?_nF=W88!9kR26!3R*%=ss bBp=uus*^yIMZxCFfXyFfB+z%tV1EGsfPW_N literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.FB00 b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/7x13.FB00 new file mode 100644 index 0000000000000000000000000000000000000000..3a0b30a999c61c749a6c9717f8dcaa15a132f69c GIT binary patch literal 912 zcmd7OO=uHA6bJCxb+D7g)XlOLtHEs6nbs79Y-=GxsZH3*Hc?q5hf)uUwud5OwFe^< z*|v$c5HYD2?X8FSfd}!@o1Xjtdr<1hn;%GTeo#b%6`cN|nu8Z_F6?jqJl+hCck1k! zvGXJ2<0HeGweg*HHj+G(f6ZOVh90NuPftVc+}~{lWP%X+Q&Qr|W%t(R)V4t7TP77! z8XD-nH>weB$|f_OD6(kk94UHfb2dQ*8_efw-hg>Gv2*c|a$@=Pt z>DaEG>gto@<(`R))|Is%-#-0(XK*TR&hFrPUtfmWI@9fR#CAPhctuKQDl8WmOq7rX=M#SIITgW6CMp^+zsU&hiw3Ua$fnsjuWU86zzWBYrRKvO(R%tnoCHEL6O--;Fw!kRd4LhJCTM7BE zl#{10+X2k>Ps+OoarZFH!(;Fy9ED@>0=xuEune!mdANWXr1IrE@IG9G58-3V|t literal 0 HcmV?d00001 diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/README b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/README new file mode 100644 index 00000000..a39f8a5e --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/README @@ -0,0 +1,9 @@ +These font files were copied from the Plan 9 Port's font/fixed directory. The +README in that directory states that: "These fonts are converted from the BDFs +in the XFree86 distribution. They were all marked as public domain." + +The Plan 9 Port is at https://github.com/9fans/plan9port and the copy was made +from commit a78b1841 (2015-08-18). + +The unicode.7x13.font file also refers to a ../shinonome directory, but this +testdata does not include those subfont files. diff --git a/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/unicode.7x13.font b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/unicode.7x13.font new file mode 100644 index 00000000..337b4286 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/font/testdata/fixed/unicode.7x13.font @@ -0,0 +1,68 @@ +13 10 +0x0000 0x001F 7x13.2400 +0x0000 0x00FF 7x13.0000 +0x0100 0x01FF 7x13.0100 +0x0200 0x02FF 7x13.0200 +0x0300 0x03FF 7x13.0300 +0x0400 0x04FF 7x13.0400 +0x0500 0x05FF 7x13.0500 +0x0E00 0x0EFF 7x13.0E00 +0x1000 0x10FF 7x13.1000 +0x1600 0x16FF 7x13.1600 +0x1E00 0x1EFF 7x13.1E00 +0x1F00 0x1FFF 7x13.1F00 +0x2000 0x20FF 7x13.2000 +0x2100 0x21FF 7x13.2100 +0x2200 0x22FF 7x13.2200 +0x2300 0x23FF 7x13.2300 +0x2400 0x24FF 7x13.2400 +0x2500 0x25FF 7x13.2500 +0x2600 0x26FF 7x13.2600 +0x2700 0x27FF 7x13.2700 +0x2800 0x28FF 7x13.2800 +0x2A00 0x2AFF 7x13.2A00 +0x3000 0x30fe ../shinonome/k12.3000 +0x4e00 0x4ffe ../shinonome/k12.4e00 +0x5005 0x51fe ../shinonome/k12.5005 +0x5200 0x53fa ../shinonome/k12.5200 +0x5401 0x55fe ../shinonome/k12.5401 +0x5606 0x57fc ../shinonome/k12.5606 +0x5800 0x59ff ../shinonome/k12.5800 +0x5a01 0x5bff ../shinonome/k12.5a01 +0x5c01 0x5dfe ../shinonome/k12.5c01 +0x5e02 0x5fff ../shinonome/k12.5e02 +0x600e 0x61ff ../shinonome/k12.600e +0x6200 0x63fa ../shinonome/k12.6200 +0x6406 0x65fb ../shinonome/k12.6406 +0x6602 0x67ff ../shinonome/k12.6602 +0x6802 0x69ff ../shinonome/k12.6802 +0x6a02 0x6bf3 ../shinonome/k12.6a02 +0x6c08 0x6dfb ../shinonome/k12.6c08 +0x6e05 0x6ffe ../shinonome/k12.6e05 +0x7001 0x71ff ../shinonome/k12.7001 +0x7206 0x73fe ../shinonome/k12.7206 +0x7403 0x75ff ../shinonome/k12.7403 +0x7601 0x77fc ../shinonome/k12.7601 +0x7802 0x79fb ../shinonome/k12.7802 +0x7a00 0x7bf7 ../shinonome/k12.7a00 +0x7c00 0x7dfb ../shinonome/k12.7c00 +0x7e01 0x7ffc ../shinonome/k12.7e01 +0x8000 0x81fe ../shinonome/k12.8000 +0x8201 0x83fd ../shinonome/k12.8201 +0x8403 0x85fe ../shinonome/k12.8403 +0x8602 0x87fe ../shinonome/k12.8602 +0x8805 0x89f8 ../shinonome/k12.8805 +0x8a00 0x8b9a ../shinonome/k12.8a00 +0x8c37 0x8dff ../shinonome/k12.8c37 +0x8e08 0x8ffd ../shinonome/k12.8e08 +0x9000 0x91ff ../shinonome/k12.9000 +0x920d 0x93e8 ../shinonome/k12.920d +0x9403 0x95e5 ../shinonome/k12.9403 +0x961c 0x97ff ../shinonome/k12.961c +0x9801 0x99ff ../shinonome/k12.9801 +0x9a01 0x9bf5 ../shinonome/k12.9a01 +0x9c04 0x9dfd ../shinonome/k12.9c04 +0x9e1a 0x9fa0 ../shinonome/k12.9e1a +0xFB00 0xFBFF 7x13.FB00 +0xFE00 0xFEFF 7x13.FE00 +0xFF00 0xFFFF 7x13.FF00 diff --git a/Godeps/_workspace/src/golang.org/x/image/math/fixed/fixed.go b/Godeps/_workspace/src/golang.org/x/image/math/fixed/fixed.go new file mode 100644 index 00000000..2f25d0ef --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/math/fixed/fixed.go @@ -0,0 +1,172 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package fixed implements fixed-point integer types. +package fixed // import "golang.org/x/image/math/fixed" + +import ( + "fmt" +) + +// TODO: implement fmt.Formatter for %f and %g. + +// I returns the integer value i as an Int26_6. +// +// For example, passing the integer value 2 yields Int26_6(128). +func I(i int) Int26_6 { + return Int26_6(i << 6) +} + +// Int26_6 is a signed 26.6 fixed-point number. +// +// The integer part ranges from -33554432 to 33554431, inclusive. The +// fractional part has 6 bits of precision. +// +// For example, the number one-and-a-quarter is Int26_6(1<<6 + 1<<4). +type Int26_6 int32 + +// String returns a human-readable representation of a 26.6 fixed-point number. +// +// For example, the number one-and-a-quarter becomes "1:16". +func (x Int26_6) String() string { + const shift, mask = 6, 1<<6 - 1 + if x >= 0 { + return fmt.Sprintf("%d:%02d", int32(x>>shift), int32(x&mask)) + } + x = -x + if x >= 0 { + return fmt.Sprintf("-%d:%02d", int32(x>>shift), int32(x&mask)) + } + return "-33554432:00" // The minimum value is -(1<<25). +} + +// Int52_12 is a signed 52.12 fixed-point number. +// +// The integer part ranges from -2251799813685248 to 2251799813685247, +// inclusive. The fractional part has 12 bits of precision. +// +// For example, the number one-and-a-quarter is Int52_12(1<<12 + 1<<10). +type Int52_12 int64 + +// String returns a human-readable representation of a 52.12 fixed-point +// number. +// +// For example, the number one-and-a-quarter becomes "1:1024". +func (x Int52_12) String() string { + const shift, mask = 12, 1<<12 - 1 + if x >= 0 { + return fmt.Sprintf("%d:%04d", int64(x>>shift), int64(x&mask)) + } + x = -x + if x >= 0 { + return fmt.Sprintf("-%d:%04d", int64(x>>shift), int64(x&mask)) + } + return "-2251799813685248:0000" // The minimum value is -(1<<51). +} + +// P returns the integer values x and y as a Point26_6. +// +// For example, passing the integer values (2, -3) yields Point26_6{128, -192}. +func P(x, y int) Point26_6 { + return Point26_6{Int26_6(x << 6), Int26_6(y << 6)} +} + +// Point26_6 is a 26.6 fixed-point coordinate pair. +// +// It is analogous to the image.Point type in the standard library. +type Point26_6 struct { + X, Y Int26_6 +} + +// Add returns the vector p+q. +func (p Point26_6) Add(q Point26_6) Point26_6 { + return Point26_6{p.X + q.X, p.Y + q.Y} +} + +// Sub returns the vector p-q. +func (p Point26_6) Sub(q Point26_6) Point26_6 { + return Point26_6{p.X - q.X, p.Y - q.Y} +} + +// Mul returns the vector p*k. +func (p Point26_6) Mul(k Int26_6) Point26_6 { + return Point26_6{p.X * k / 64, p.Y * k / 64} +} + +// Div returns the vector p/k. +func (p Point26_6) Div(k Int26_6) Point26_6 { + return Point26_6{p.X * 64 / k, p.Y * 64 / k} +} + +// Point52_12 is a 52.12 fixed-point coordinate pair. +// +// It is analogous to the image.Point type in the standard library. +type Point52_12 struct { + X, Y Int52_12 +} + +// Add returns the vector p+q. +func (p Point52_12) Add(q Point52_12) Point52_12 { + return Point52_12{p.X + q.X, p.Y + q.Y} +} + +// Sub returns the vector p-q. +func (p Point52_12) Sub(q Point52_12) Point52_12 { + return Point52_12{p.X - q.X, p.Y - q.Y} +} + +// Mul returns the vector p*k. +func (p Point52_12) Mul(k Int52_12) Point52_12 { + return Point52_12{p.X * k / 4096, p.Y * k / 4096} +} + +// Div returns the vector p/k. +func (p Point52_12) Div(k Int52_12) Point52_12 { + return Point52_12{p.X * 4096 / k, p.Y * 4096 / k} +} + +// R returns the integer values minX, minY, maxX, maxY as a Rectangle26_6. +// +// For example, passing the integer values (0, 1, 2, 3) yields +// Rectangle26_6{Point26_6{0, 64}, Point26_6{128, 192}}. +// +// Like the image.Rect function in the standard library, the returned rectangle +// has minimum and maximum coordinates swapped if necessary so that it is +// well-formed. +func R(minX, minY, maxX, maxY int) Rectangle26_6 { + if minX > maxX { + minX, maxX = maxX, minX + } + if minY > maxY { + minY, maxY = maxY, minY + } + return Rectangle26_6{ + Point26_6{ + Int26_6(minX << 6), + Int26_6(minY << 6), + }, + Point26_6{ + Int26_6(maxX << 6), + Int26_6(maxY << 6), + }, + } +} + +// Rectangle26_6 is a 26.6 fixed-point coordinate rectangle. The Min bound is +// inclusive and the Max bound is exclusive. It is well-formed if Min.X <= +// Max.X and likewise for Y. +// +// It is analogous to the image.Rectangle type in the standard library. +type Rectangle26_6 struct { + Min, Max Point26_6 +} + +// Rectangle52_12 is a 52.12 fixed-point coordinate rectangle. The Min bound is +// inclusive and the Max bound is exclusive. It is well-formed if Min.X <= +// Max.X and likewise for Y. +// +// It is analogous to the image.Rectangle type in the standard library. +type Rectangle52_12 struct { + Min, Max Point52_12 +} diff --git a/Godeps/_workspace/src/golang.org/x/image/math/fixed/fixed_test.go b/Godeps/_workspace/src/golang.org/x/image/math/fixed/fixed_test.go new file mode 100644 index 00000000..e252de7c --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/math/fixed/fixed_test.go @@ -0,0 +1,25 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fixed + +import ( + "testing" +) + +func TestInt26_6(t *testing.T) { + got := Int26_6(1<<6 + 1<<4).String() + want := "1:16" + if got != want { + t.Fatalf("got %q, want %q", got, want) + } +} + +func TestInt52_12(t *testing.T) { + got := Int52_12(1<<12 + 1<<10).String() + want := "1:1024" + if got != want { + t.Fatalf("got %q, want %q", got, want) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/image/riff/example_test.go b/Godeps/_workspace/src/golang.org/x/image/riff/example_test.go deleted file mode 100644 index 93c72b09..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/riff/example_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package riff_test - -import ( - "fmt" - "io" - "io/ioutil" - "log" - "strings" - - "golang.org/x/image/riff" -) - -func ExampleReader() { - formType, r, err := riff.NewReader(strings.NewReader(data)) - if err != nil { - log.Fatal(err) - } - fmt.Printf("RIFF(%s)\n", formType) - if err := dump(r, ".\t"); err != nil { - log.Fatal(err) - } - // Output: - // RIFF(ROOT) - // . ZERO "" - // . ONE "a" - // . LIST(META) - // . . LIST(GOOD) - // . . . ONE "a" - // . . . FIVE "klmno" - // . . ZERO "" - // . . LIST(BAD ) - // . . . THRE "def" - // . TWO "bc" - // . LIST(UGLY) - // . . FOUR "ghij" - // . . SIX "pqrstu" -} - -func dump(r *riff.Reader, indent string) error { - for { - chunkID, chunkLen, chunkData, err := r.Next() - if err == io.EOF { - return nil - } - if err != nil { - return err - } - if chunkID == riff.LIST { - listType, list, err := riff.NewListReader(chunkLen, chunkData) - if err != nil { - return err - } - fmt.Printf("%sLIST(%s)\n", indent, listType) - if err := dump(list, indent+".\t"); err != nil { - return err - } - continue - } - b, err := ioutil.ReadAll(chunkData) - if err != nil { - return err - } - fmt.Printf("%s%s %q\n", indent, chunkID, b) - } -} - -func encodeU32(u uint32) string { - return string([]byte{ - byte(u >> 0), - byte(u >> 8), - byte(u >> 16), - byte(u >> 24), - }) -} - -func encode(chunkID, contents string) string { - n := len(contents) - if n&1 == 1 { - contents += "\x00" - } - return chunkID + encodeU32(uint32(n)) + contents -} - -func encodeMulti(typ0, typ1 string, chunks ...string) string { - n := 4 - for _, c := range chunks { - n += len(c) - } - s := typ0 + encodeU32(uint32(n)) + typ1 - for _, c := range chunks { - s += c - } - return s -} - -var ( - d0 = encode("ZERO", "") - d1 = encode("ONE ", "a") - d2 = encode("TWO ", "bc") - d3 = encode("THRE", "def") - d4 = encode("FOUR", "ghij") - d5 = encode("FIVE", "klmno") - d6 = encode("SIX ", "pqrstu") - l0 = encodeMulti("LIST", "GOOD", d1, d5) - l1 = encodeMulti("LIST", "BAD ", d3) - l2 = encodeMulti("LIST", "UGLY", d4, d6) - l01 = encodeMulti("LIST", "META", l0, d0, l1) - data = encodeMulti("RIFF", "ROOT", d0, d1, l01, d2, l2) -) diff --git a/Godeps/_workspace/src/golang.org/x/image/riff/riff.go b/Godeps/_workspace/src/golang.org/x/image/riff/riff.go deleted file mode 100644 index 9b9f71d8..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/riff/riff.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package riff implements the Resource Interchange File Format, used by media -// formats such as AVI, WAVE and WEBP. -// -// A RIFF stream contains a sequence of chunks. Each chunk consists of an 8-byte -// header (containing a 4-byte chunk type and a 4-byte chunk length), the chunk -// data (presented as an io.Reader), and some padding bytes. -// -// A detailed description of the format is at -// http://www.tactilemedia.com/info/MCI_Control_Info.html -package riff // import "golang.org/x/image/riff" - -import ( - "errors" - "io" - "io/ioutil" - "math" -) - -var ( - errMissingPaddingByte = errors.New("riff: missing padding byte") - errMissingRIFFChunkHeader = errors.New("riff: missing RIFF chunk header") - errShortChunkData = errors.New("riff: short chunk data") - errShortChunkHeader = errors.New("riff: short chunk header") - errStaleReader = errors.New("riff: stale reader") -) - -// u32 decodes the first four bytes of b as a little-endian integer. -func u32(b []byte) uint32 { - return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 -} - -const chunkHeaderSize = 8 - -// FourCC is a four character code. -type FourCC [4]byte - -// LIST is the "LIST" FourCC. -var LIST = FourCC{'L', 'I', 'S', 'T'} - -// NewReader returns the RIFF stream's form type, such as "AVI " or "WAVE", and -// its chunks as a *Reader. -func NewReader(r io.Reader) (formType FourCC, data *Reader, err error) { - var buf [chunkHeaderSize]byte - if _, err := io.ReadFull(r, buf[:]); err != nil { - if err == io.EOF || err == io.ErrUnexpectedEOF { - err = errMissingRIFFChunkHeader - } - return FourCC{}, nil, err - } - if buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F' { - return FourCC{}, nil, errMissingRIFFChunkHeader - } - return NewListReader(u32(buf[4:]), r) -} - -// NewListReader returns a LIST chunk's list type, such as "movi" or "wavl", -// and its chunks as a *Reader. -func NewListReader(chunkLen uint32, chunkData io.Reader) (listType FourCC, data *Reader, err error) { - if chunkLen < 4 { - return FourCC{}, nil, errShortChunkData - } - z := &Reader{r: chunkData} - if _, err := io.ReadFull(chunkData, z.buf[:4]); err != nil { - if err == io.EOF || err == io.ErrUnexpectedEOF { - err = errShortChunkData - } - return FourCC{}, nil, err - } - z.totalLen = chunkLen - 4 - return FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}, z, nil -} - -// Reader reads chunks from an underlying io.Reader. -type Reader struct { - r io.Reader - err error - - totalLen uint32 - chunkLen uint32 - - chunkReader *chunkReader - buf [chunkHeaderSize]byte - padded bool -} - -// Next returns the next chunk's ID, length and data. It returns io.EOF if there -// are no more chunks. The io.Reader returned becomes stale after the next Next -// call, and should no longer be used. -// -// It is valid to call Next even if all of the previous chunk's data has not -// been read. -func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, err error) { - if z.err != nil { - return FourCC{}, 0, nil, z.err - } - - // Drain the rest of the previous chunk. - if z.chunkLen != 0 { - _, z.err = io.Copy(ioutil.Discard, z.chunkReader) - if z.err != nil { - return FourCC{}, 0, nil, z.err - } - } - z.chunkReader = nil - if z.padded { - _, z.err = io.ReadFull(z.r, z.buf[:1]) - if z.err != nil { - if z.err == io.EOF { - z.err = errMissingPaddingByte - } - return FourCC{}, 0, nil, z.err - } - z.totalLen-- - } - - // We are done if we have no more data. - if z.totalLen == 0 { - z.err = io.EOF - return FourCC{}, 0, nil, z.err - } - - // Read the next chunk header. - if z.totalLen < chunkHeaderSize { - z.err = errShortChunkHeader - return FourCC{}, 0, nil, z.err - } - z.totalLen -= chunkHeaderSize - if _, err = io.ReadFull(z.r, z.buf[:chunkHeaderSize]); err != nil { - if z.err == io.EOF || z.err == io.ErrUnexpectedEOF { - z.err = errShortChunkHeader - } - return FourCC{}, 0, nil, z.err - } - chunkID = FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]} - z.chunkLen = u32(z.buf[4:]) - z.padded = z.chunkLen&1 == 1 - z.chunkReader = &chunkReader{z} - return chunkID, z.chunkLen, z.chunkReader, nil -} - -type chunkReader struct { - z *Reader -} - -func (c *chunkReader) Read(p []byte) (int, error) { - if c != c.z.chunkReader { - return 0, errStaleReader - } - z := c.z - if z.err != nil { - if z.err == io.EOF { - return 0, errStaleReader - } - return 0, z.err - } - - n := int(z.chunkLen) - if n == 0 { - return 0, io.EOF - } - if n < 0 { - // Converting uint32 to int overflowed. - n = math.MaxInt32 - } - if n > len(p) { - n = len(p) - } - n, err := z.r.Read(p[:n]) - z.totalLen -= uint32(n) - z.chunkLen -= uint32(n) - if err != io.EOF { - z.err = err - } - return n, err -} diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/buffer.go b/Godeps/_workspace/src/golang.org/x/image/tiff/buffer.go deleted file mode 100644 index d1801be4..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/buffer.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tiff - -import "io" - -// buffer buffers an io.Reader to satisfy io.ReaderAt. -type buffer struct { - r io.Reader - buf []byte -} - -// fill reads data from b.r until the buffer contains at least end bytes. -func (b *buffer) fill(end int) error { - m := len(b.buf) - if end > m { - if end > cap(b.buf) { - newcap := 1024 - for newcap < end { - newcap *= 2 - } - newbuf := make([]byte, end, newcap) - copy(newbuf, b.buf) - b.buf = newbuf - } else { - b.buf = b.buf[:end] - } - if n, err := io.ReadFull(b.r, b.buf[m:end]); err != nil { - end = m + n - b.buf = b.buf[:end] - return err - } - } - return nil -} - -func (b *buffer) ReadAt(p []byte, off int64) (int, error) { - o := int(off) - end := o + len(p) - if int64(end) != off+int64(len(p)) { - return 0, io.ErrUnexpectedEOF - } - - err := b.fill(end) - return copy(p, b.buf[o:end]), err -} - -// Slice returns a slice of the underlying buffer. The slice contains -// n bytes starting at offset off. -func (b *buffer) Slice(off, n int) ([]byte, error) { - end := off + n - if err := b.fill(end); err != nil { - return nil, err - } - return b.buf[off:end], nil -} - -// newReaderAt converts an io.Reader into an io.ReaderAt. -func newReaderAt(r io.Reader) io.ReaderAt { - if ra, ok := r.(io.ReaderAt); ok { - return ra - } - return &buffer{ - r: r, - buf: make([]byte, 0, 1024), - } -} diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/buffer_test.go b/Godeps/_workspace/src/golang.org/x/image/tiff/buffer_test.go deleted file mode 100644 index e13afb36..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/buffer_test.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tiff - -import ( - "io" - "strings" - "testing" -) - -var readAtTests = []struct { - n int - off int64 - s string - err error -}{ - {2, 0, "ab", nil}, - {6, 0, "abcdef", nil}, - {3, 3, "def", nil}, - {3, 5, "f", io.EOF}, - {3, 6, "", io.EOF}, -} - -func TestReadAt(t *testing.T) { - r := newReaderAt(strings.NewReader("abcdef")) - b := make([]byte, 10) - for _, test := range readAtTests { - n, err := r.ReadAt(b[:test.n], test.off) - s := string(b[:n]) - if s != test.s || err != test.err { - t.Errorf("buffer.ReadAt(<%v bytes>, %v): got %v, %q; want %v, %q", test.n, test.off, err, s, test.err, test.s) - } - } -} diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/compress.go b/Godeps/_workspace/src/golang.org/x/image/tiff/compress.go deleted file mode 100644 index 3f176f00..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/compress.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tiff - -import ( - "bufio" - "io" -) - -type byteReader interface { - io.Reader - io.ByteReader -} - -// unpackBits decodes the PackBits-compressed data in src and returns the -// uncompressed data. -// -// The PackBits compression format is described in section 9 (p. 42) -// of the TIFF spec. -func unpackBits(r io.Reader) ([]byte, error) { - buf := make([]byte, 128) - dst := make([]byte, 0, 1024) - br, ok := r.(byteReader) - if !ok { - br = bufio.NewReader(r) - } - - for { - b, err := br.ReadByte() - if err != nil { - if err == io.EOF { - return dst, nil - } - return nil, err - } - code := int(int8(b)) - switch { - case code >= 0: - n, err := io.ReadFull(br, buf[:code+1]) - if err != nil { - return nil, err - } - dst = append(dst, buf[:n]...) - case code == -128: - // No-op. - default: - if b, err = br.ReadByte(); err != nil { - return nil, err - } - for j := 0; j < 1-code; j++ { - buf[j] = b - } - dst = append(dst, buf[:1-code]...) - } - } -} diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/consts.go b/Godeps/_workspace/src/golang.org/x/image/tiff/consts.go deleted file mode 100644 index 3c51a70b..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/consts.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tiff - -// A tiff image file contains one or more images. The metadata -// of each image is contained in an Image File Directory (IFD), -// which contains entries of 12 bytes each and is described -// on page 14-16 of the specification. An IFD entry consists of -// -// - a tag, which describes the signification of the entry, -// - the data type and length of the entry, -// - the data itself or a pointer to it if it is more than 4 bytes. -// -// The presence of a length means that each IFD is effectively an array. - -const ( - leHeader = "II\x2A\x00" // Header for little-endian files. - beHeader = "MM\x00\x2A" // Header for big-endian files. - - ifdLen = 12 // Length of an IFD entry in bytes. -) - -// Data types (p. 14-16 of the spec). -const ( - dtByte = 1 - dtASCII = 2 - dtShort = 3 - dtLong = 4 - dtRational = 5 -) - -// The length of one instance of each data type in bytes. -var lengths = [...]uint32{0, 1, 1, 2, 4, 8} - -// Tags (see p. 28-41 of the spec). -const ( - tImageWidth = 256 - tImageLength = 257 - tBitsPerSample = 258 - tCompression = 259 - tPhotometricInterpretation = 262 - - tStripOffsets = 273 - tSamplesPerPixel = 277 - tRowsPerStrip = 278 - tStripByteCounts = 279 - - tTileWidth = 322 - tTileLength = 323 - tTileOffsets = 324 - tTileByteCounts = 325 - - tXResolution = 282 - tYResolution = 283 - tResolutionUnit = 296 - - tPredictor = 317 - tColorMap = 320 - tExtraSamples = 338 - tSampleFormat = 339 -) - -// Compression types (defined in various places in the spec and supplements). -const ( - cNone = 1 - cCCITT = 2 - cG3 = 3 // Group 3 Fax. - cG4 = 4 // Group 4 Fax. - cLZW = 5 - cJPEGOld = 6 // Superseded by cJPEG. - cJPEG = 7 - cDeflate = 8 // zlib compression. - cPackBits = 32773 - cDeflateOld = 32946 // Superseded by cDeflate. -) - -// Photometric interpretation values (see p. 37 of the spec). -const ( - pWhiteIsZero = 0 - pBlackIsZero = 1 - pRGB = 2 - pPaletted = 3 - pTransMask = 4 // transparency mask - pCMYK = 5 - pYCbCr = 6 - pCIELab = 8 -) - -// Values for the tPredictor tag (page 64-65 of the spec). -const ( - prNone = 1 - prHorizontal = 2 -) - -// Values for the tResolutionUnit tag (page 18). -const ( - resNone = 1 - resPerInch = 2 // Dots per inch. - resPerCM = 3 // Dots per centimeter. -) - -// imageMode represents the mode of the image. -type imageMode int - -const ( - mBilevel imageMode = iota - mPaletted - mGray - mGrayInvert - mRGB - mRGBA - mNRGBA -) - -// CompressionType describes the type of compression used in Options. -type CompressionType int - -const ( - Uncompressed CompressionType = iota - Deflate -) - -// specValue returns the compression type constant from the TIFF spec that -// is equivalent to c. -func (c CompressionType) specValue() uint32 { - switch c { - case Deflate: - return cDeflate - } - return cNone -} diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/lzw/reader.go b/Godeps/_workspace/src/golang.org/x/image/tiff/lzw/reader.go deleted file mode 100644 index ad35819f..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/lzw/reader.go +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package lzw implements the Lempel-Ziv-Welch compressed data format, -// described in T. A. Welch, ``A Technique for High-Performance Data -// Compression'', Computer, 17(6) (June 1984), pp 8-19. -// -// In particular, it implements LZW as used by the TIFF file format, including -// an "off by one" algorithmic difference when compared to standard LZW. -package lzw // import "golang.org/x/image/tiff/lzw" - -/* -This file was branched from src/pkg/compress/lzw/reader.go in the -standard library. Differences from the original are marked with "NOTE". - -The tif_lzw.c file in the libtiff C library has this comment: - ----- -The 5.0 spec describes a different algorithm than Aldus -implements. Specifically, Aldus does code length transitions -one code earlier than should be done (for real LZW). -Earlier versions of this library implemented the correct -LZW algorithm, but emitted codes in a bit order opposite -to the TIFF spec. Thus, to maintain compatibility w/ Aldus -we interpret MSB-LSB ordered codes to be images written w/ -old versions of this library, but otherwise adhere to the -Aldus "off by one" algorithm. ----- - -The Go code doesn't read (invalid) TIFF files written by old versions of -libtiff, but the LZW algorithm in this package still differs from the one in -Go's standard package library to accomodate this "off by one" in valid TIFFs. -*/ - -import ( - "bufio" - "errors" - "fmt" - "io" -) - -// Order specifies the bit ordering in an LZW data stream. -type Order int - -const ( - // LSB means Least Significant Bits first, as used in the GIF file format. - LSB Order = iota - // MSB means Most Significant Bits first, as used in the TIFF and PDF - // file formats. - MSB -) - -const ( - maxWidth = 12 - decoderInvalidCode = 0xffff - flushBuffer = 1 << maxWidth -) - -// decoder is the state from which the readXxx method converts a byte -// stream into a code stream. -type decoder struct { - r io.ByteReader - bits uint32 - nBits uint - width uint - read func(*decoder) (uint16, error) // readLSB or readMSB - litWidth int // width in bits of literal codes - err error - - // The first 1<= 1<>= d.width - d.nBits -= d.width - return code, nil -} - -// readMSB returns the next code for "Most Significant Bits first" data. -func (d *decoder) readMSB() (uint16, error) { - for d.nBits < d.width { - x, err := d.r.ReadByte() - if err != nil { - return 0, err - } - d.bits |= uint32(x) << (24 - d.nBits) - d.nBits += 8 - } - code := uint16(d.bits >> (32 - d.width)) - d.bits <<= d.width - d.nBits -= d.width - return code, nil -} - -func (d *decoder) Read(b []byte) (int, error) { - for { - if len(d.toRead) > 0 { - n := copy(b, d.toRead) - d.toRead = d.toRead[n:] - return n, nil - } - if d.err != nil { - return 0, d.err - } - d.decode() - } -} - -// decode decompresses bytes from r and leaves them in d.toRead. -// read specifies how to decode bytes into codes. -// litWidth is the width in bits of literal codes. -func (d *decoder) decode() { - // Loop over the code stream, converting codes into decompressed bytes. - for { - code, err := d.read(d) - if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - d.err = err - d.flush() - return - } - switch { - case code < d.clear: - // We have a literal code. - d.output[d.o] = uint8(code) - d.o++ - if d.last != decoderInvalidCode { - // Save what the hi code expands to. - d.suffix[d.hi] = uint8(code) - d.prefix[d.hi] = d.last - } - case code == d.clear: - d.width = 1 + uint(d.litWidth) - d.hi = d.eof - d.overflow = 1 << d.width - d.last = decoderInvalidCode - continue - case code == d.eof: - d.flush() - d.err = io.EOF - return - case code <= d.hi: - c, i := code, len(d.output)-1 - if code == d.hi { - // code == hi is a special case which expands to the last expansion - // followed by the head of the last expansion. To find the head, we walk - // the prefix chain until we find a literal code. - c = d.last - for c >= d.clear { - c = d.prefix[c] - } - d.output[i] = uint8(c) - i-- - c = d.last - } - // Copy the suffix chain into output and then write that to w. - for c >= d.clear { - d.output[i] = d.suffix[c] - i-- - c = d.prefix[c] - } - d.output[i] = uint8(c) - d.o += copy(d.output[d.o:], d.output[i:]) - if d.last != decoderInvalidCode { - // Save what the hi code expands to. - d.suffix[d.hi] = uint8(c) - d.prefix[d.hi] = d.last - } - default: - d.err = errors.New("lzw: invalid code") - d.flush() - return - } - d.last, d.hi = code, d.hi+1 - if d.hi+1 >= d.overflow { // NOTE: the "+1" is where TIFF's LZW differs from the standard algorithm. - if d.width == maxWidth { - d.last = decoderInvalidCode - } else { - d.width++ - d.overflow <<= 1 - } - } - if d.o >= flushBuffer { - d.flush() - return - } - } -} - -func (d *decoder) flush() { - d.toRead = d.output[:d.o] - d.o = 0 -} - -var errClosed = errors.New("lzw: reader/writer is closed") - -func (d *decoder) Close() error { - d.err = errClosed // in case any Reads come along - return nil -} - -// NewReader creates a new io.ReadCloser. -// Reads from the returned io.ReadCloser read and decompress data from r. -// If r does not also implement io.ByteReader, -// the decompressor may read more data than necessary from r. -// It is the caller's responsibility to call Close on the ReadCloser when -// finished reading. -// The number of bits to use for literal codes, litWidth, must be in the -// range [2,8] and is typically 8. It must equal the litWidth -// used during compression. -func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser { - d := new(decoder) - switch order { - case LSB: - d.read = (*decoder).readLSB - case MSB: - d.read = (*decoder).readMSB - default: - d.err = errors.New("lzw: unknown order") - return d - } - if litWidth < 2 || 8 < litWidth { - d.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth) - return d - } - if br, ok := r.(io.ByteReader); ok { - d.r = br - } else { - d.r = bufio.NewReader(r) - } - d.litWidth = litWidth - d.width = 1 + uint(litWidth) - d.clear = uint16(1) << uint(litWidth) - d.eof, d.hi = d.clear+1, d.clear+1 - d.overflow = uint16(1) << d.width - d.last = decoderInvalidCode - - return d -} diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/reader.go b/Godeps/_workspace/src/golang.org/x/image/tiff/reader.go deleted file mode 100644 index df39e828..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/reader.go +++ /dev/null @@ -1,681 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package tiff implements a TIFF image decoder and encoder. -// -// The TIFF specification is at http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf -package tiff // import "golang.org/x/image/tiff" - -import ( - "compress/zlib" - "encoding/binary" - "fmt" - "image" - "image/color" - "io" - "io/ioutil" - "math" - - "golang.org/x/image/tiff/lzw" -) - -// A FormatError reports that the input is not a valid TIFF image. -type FormatError string - -func (e FormatError) Error() string { - return "tiff: invalid format: " + string(e) -} - -// An UnsupportedError reports that the input uses a valid but -// unimplemented feature. -type UnsupportedError string - -func (e UnsupportedError) Error() string { - return "tiff: unsupported feature: " + string(e) -} - -// An InternalError reports that an internal error was encountered. -type InternalError string - -func (e InternalError) Error() string { - return "tiff: internal error: " + string(e) -} - -var errNoPixels = FormatError("not enough pixel data") - -type decoder struct { - r io.ReaderAt - byteOrder binary.ByteOrder - config image.Config - mode imageMode - bpp uint - features map[int][]uint - palette []color.Color - - buf []byte - off int // Current offset in buf. - v uint32 // Buffer value for reading with arbitrary bit depths. - nbits uint // Remaining number of bits in v. -} - -// firstVal returns the first uint of the features entry with the given tag, -// or 0 if the tag does not exist. -func (d *decoder) firstVal(tag int) uint { - f := d.features[tag] - if len(f) == 0 { - return 0 - } - return f[0] -} - -// ifdUint decodes the IFD entry in p, which must be of the Byte, Short -// or Long type, and returns the decoded uint values. -func (d *decoder) ifdUint(p []byte) (u []uint, err error) { - var raw []byte - if len(p) < ifdLen { - return nil, FormatError("bad IFD entry") - } - - datatype := d.byteOrder.Uint16(p[2:4]) - if dt := int(datatype); dt <= 0 || dt >= len(lengths) { - return nil, UnsupportedError("IFD entry datatype") - } - - count := d.byteOrder.Uint32(p[4:8]) - if count > math.MaxInt32/lengths[datatype] { - return nil, FormatError("IFD data too large") - } - if datalen := lengths[datatype] * count; datalen > 4 { - // The IFD contains a pointer to the real value. - raw = make([]byte, datalen) - _, err = d.r.ReadAt(raw, int64(d.byteOrder.Uint32(p[8:12]))) - } else { - raw = p[8 : 8+datalen] - } - if err != nil { - return nil, err - } - - u = make([]uint, count) - switch datatype { - case dtByte: - for i := uint32(0); i < count; i++ { - u[i] = uint(raw[i]) - } - case dtShort: - for i := uint32(0); i < count; i++ { - u[i] = uint(d.byteOrder.Uint16(raw[2*i : 2*(i+1)])) - } - case dtLong: - for i := uint32(0); i < count; i++ { - u[i] = uint(d.byteOrder.Uint32(raw[4*i : 4*(i+1)])) - } - default: - return nil, UnsupportedError("data type") - } - return u, nil -} - -// parseIFD decides whether the the IFD entry in p is "interesting" and -// stows away the data in the decoder. -func (d *decoder) parseIFD(p []byte) error { - tag := d.byteOrder.Uint16(p[0:2]) - switch tag { - case tBitsPerSample, - tExtraSamples, - tPhotometricInterpretation, - tCompression, - tPredictor, - tStripOffsets, - tStripByteCounts, - tRowsPerStrip, - tTileWidth, - tTileLength, - tTileOffsets, - tTileByteCounts, - tImageLength, - tImageWidth: - val, err := d.ifdUint(p) - if err != nil { - return err - } - d.features[int(tag)] = val - case tColorMap: - val, err := d.ifdUint(p) - if err != nil { - return err - } - numcolors := len(val) / 3 - if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 { - return FormatError("bad ColorMap length") - } - d.palette = make([]color.Color, numcolors) - for i := 0; i < numcolors; i++ { - d.palette[i] = color.RGBA64{ - uint16(val[i]), - uint16(val[i+numcolors]), - uint16(val[i+2*numcolors]), - 0xffff, - } - } - case tSampleFormat: - // Page 27 of the spec: If the SampleFormat is present and - // the value is not 1 [= unsigned integer data], a Baseline - // TIFF reader that cannot handle the SampleFormat value - // must terminate the import process gracefully. - val, err := d.ifdUint(p) - if err != nil { - return err - } - for _, v := range val { - if v != 1 { - return UnsupportedError("sample format") - } - } - } - return nil -} - -// readBits reads n bits from the internal buffer starting at the current offset. -func (d *decoder) readBits(n uint) (v uint32, ok bool) { - for d.nbits < n { - d.v <<= 8 - if d.off >= len(d.buf) { - return 0, false - } - d.v |= uint32(d.buf[d.off]) - d.off++ - d.nbits += 8 - } - d.nbits -= n - rv := d.v >> d.nbits - d.v &^= rv << d.nbits - return rv, true -} - -// flushBits discards the unread bits in the buffer used by readBits. -// It is used at the end of a line. -func (d *decoder) flushBits() { - d.v = 0 - d.nbits = 0 -} - -// minInt returns the smaller of x or y. -func minInt(a, b int) int { - if a <= b { - return a - } - return b -} - -// decode decodes the raw data of an image. -// It reads from d.buf and writes the strip or tile into dst. -func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error { - d.off = 0 - - // Apply horizontal predictor if necessary. - // In this case, p contains the color difference to the preceding pixel. - // See page 64-65 of the spec. - if d.firstVal(tPredictor) == prHorizontal { - switch d.bpp { - case 16: - var off int - n := 2 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel - for y := ymin; y < ymax; y++ { - off += n - for x := 0; x < (xmax-xmin-1)*n; x += 2 { - if off+2 > len(d.buf) { - return errNoPixels - } - v0 := d.byteOrder.Uint16(d.buf[off-n : off-n+2]) - v1 := d.byteOrder.Uint16(d.buf[off : off+2]) - d.byteOrder.PutUint16(d.buf[off:off+2], v1+v0) - off += 2 - } - } - case 8: - var off int - n := 1 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel - for y := ymin; y < ymax; y++ { - off += n - for x := 0; x < (xmax-xmin-1)*n; x++ { - if off >= len(d.buf) { - return errNoPixels - } - d.buf[off] += d.buf[off-n] - off++ - } - } - case 1: - return UnsupportedError("horizontal predictor with 1 BitsPerSample") - } - } - - rMaxX := minInt(xmax, dst.Bounds().Max.X) - rMaxY := minInt(ymax, dst.Bounds().Max.Y) - switch d.mode { - case mGray, mGrayInvert: - if d.bpp == 16 { - img := dst.(*image.Gray16) - for y := ymin; y < rMaxY; y++ { - for x := xmin; x < rMaxX; x++ { - if d.off+2 > len(d.buf) { - return errNoPixels - } - v := d.byteOrder.Uint16(d.buf[d.off : d.off+2]) - d.off += 2 - if d.mode == mGrayInvert { - v = 0xffff - v - } - img.SetGray16(x, y, color.Gray16{v}) - } - } - } else { - img := dst.(*image.Gray) - max := uint32((1 << d.bpp) - 1) - for y := ymin; y < rMaxY; y++ { - for x := xmin; x < rMaxX; x++ { - v, ok := d.readBits(d.bpp) - if !ok { - return errNoPixels - } - v = v * 0xff / max - if d.mode == mGrayInvert { - v = 0xff - v - } - img.SetGray(x, y, color.Gray{uint8(v)}) - } - d.flushBits() - } - } - case mPaletted: - img := dst.(*image.Paletted) - for y := ymin; y < rMaxY; y++ { - for x := xmin; x < rMaxX; x++ { - v, ok := d.readBits(d.bpp) - if !ok { - return errNoPixels - } - img.SetColorIndex(x, y, uint8(v)) - } - d.flushBits() - } - case mRGB: - if d.bpp == 16 { - img := dst.(*image.RGBA64) - for y := ymin; y < rMaxY; y++ { - for x := xmin; x < rMaxX; x++ { - if d.off+6 > len(d.buf) { - return errNoPixels - } - r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2]) - g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4]) - b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6]) - d.off += 6 - img.SetRGBA64(x, y, color.RGBA64{r, g, b, 0xffff}) - } - } - } else { - img := dst.(*image.RGBA) - for y := ymin; y < rMaxY; y++ { - min := img.PixOffset(xmin, y) - max := img.PixOffset(rMaxX, y) - off := (y - ymin) * (xmax - xmin) * 3 - for i := min; i < max; i += 4 { - if off+3 > len(d.buf) { - return errNoPixels - } - img.Pix[i+0] = d.buf[off+0] - img.Pix[i+1] = d.buf[off+1] - img.Pix[i+2] = d.buf[off+2] - img.Pix[i+3] = 0xff - off += 3 - } - } - } - case mNRGBA: - if d.bpp == 16 { - img := dst.(*image.NRGBA64) - for y := ymin; y < rMaxY; y++ { - for x := xmin; x < rMaxX; x++ { - if d.off+8 > len(d.buf) { - return errNoPixels - } - r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2]) - g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4]) - b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6]) - a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8]) - d.off += 8 - img.SetNRGBA64(x, y, color.NRGBA64{r, g, b, a}) - } - } - } else { - img := dst.(*image.NRGBA) - for y := ymin; y < rMaxY; y++ { - min := img.PixOffset(xmin, y) - max := img.PixOffset(rMaxX, y) - i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4 - if i1 > len(d.buf) { - return errNoPixels - } - copy(img.Pix[min:max], d.buf[i0:i1]) - } - } - case mRGBA: - if d.bpp == 16 { - img := dst.(*image.RGBA64) - for y := ymin; y < rMaxY; y++ { - for x := xmin; x < rMaxX; x++ { - if d.off+8 > len(d.buf) { - return errNoPixels - } - r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2]) - g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4]) - b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6]) - a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8]) - d.off += 8 - img.SetRGBA64(x, y, color.RGBA64{r, g, b, a}) - } - } - } else { - img := dst.(*image.RGBA) - for y := ymin; y < rMaxY; y++ { - min := img.PixOffset(xmin, y) - max := img.PixOffset(rMaxX, y) - i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4 - if i1 > len(d.buf) { - return errNoPixels - } - copy(img.Pix[min:max], d.buf[i0:i1]) - } - } - } - - return nil -} - -func newDecoder(r io.Reader) (*decoder, error) { - d := &decoder{ - r: newReaderAt(r), - features: make(map[int][]uint), - } - - p := make([]byte, 8) - if _, err := d.r.ReadAt(p, 0); err != nil { - return nil, err - } - switch string(p[0:4]) { - case leHeader: - d.byteOrder = binary.LittleEndian - case beHeader: - d.byteOrder = binary.BigEndian - default: - return nil, FormatError("malformed header") - } - - ifdOffset := int64(d.byteOrder.Uint32(p[4:8])) - - // The first two bytes contain the number of entries (12 bytes each). - if _, err := d.r.ReadAt(p[0:2], ifdOffset); err != nil { - return nil, err - } - numItems := int(d.byteOrder.Uint16(p[0:2])) - - // All IFD entries are read in one chunk. - p = make([]byte, ifdLen*numItems) - if _, err := d.r.ReadAt(p, ifdOffset+2); err != nil { - return nil, err - } - - for i := 0; i < len(p); i += ifdLen { - if err := d.parseIFD(p[i : i+ifdLen]); err != nil { - return nil, err - } - } - - d.config.Width = int(d.firstVal(tImageWidth)) - d.config.Height = int(d.firstVal(tImageLength)) - - if _, ok := d.features[tBitsPerSample]; !ok { - return nil, FormatError("BitsPerSample tag missing") - } - d.bpp = d.firstVal(tBitsPerSample) - switch d.bpp { - case 0: - return nil, FormatError("BitsPerSample must not be 0") - case 1, 8, 16: - // Nothing to do, these are accepted by this implementation. - default: - return nil, UnsupportedError(fmt.Sprintf("BitsPerSample of %v", d.bpp)) - } - - // Determine the image mode. - switch d.firstVal(tPhotometricInterpretation) { - case pRGB: - if d.bpp == 16 { - for _, b := range d.features[tBitsPerSample] { - if b != 16 { - return nil, FormatError("wrong number of samples for 16bit RGB") - } - } - } else { - for _, b := range d.features[tBitsPerSample] { - if b != 8 { - return nil, FormatError("wrong number of samples for 8bit RGB") - } - } - } - // RGB images normally have 3 samples per pixel. - // If there are more, ExtraSamples (p. 31-32 of the spec) - // gives their meaning (usually an alpha channel). - // - // This implementation does not support extra samples - // of an unspecified type. - switch len(d.features[tBitsPerSample]) { - case 3: - d.mode = mRGB - if d.bpp == 16 { - d.config.ColorModel = color.RGBA64Model - } else { - d.config.ColorModel = color.RGBAModel - } - case 4: - switch d.firstVal(tExtraSamples) { - case 1: - d.mode = mRGBA - if d.bpp == 16 { - d.config.ColorModel = color.RGBA64Model - } else { - d.config.ColorModel = color.RGBAModel - } - case 2: - d.mode = mNRGBA - if d.bpp == 16 { - d.config.ColorModel = color.NRGBA64Model - } else { - d.config.ColorModel = color.NRGBAModel - } - default: - return nil, FormatError("wrong number of samples for RGB") - } - default: - return nil, FormatError("wrong number of samples for RGB") - } - case pPaletted: - d.mode = mPaletted - d.config.ColorModel = color.Palette(d.palette) - case pWhiteIsZero: - d.mode = mGrayInvert - if d.bpp == 16 { - d.config.ColorModel = color.Gray16Model - } else { - d.config.ColorModel = color.GrayModel - } - case pBlackIsZero: - d.mode = mGray - if d.bpp == 16 { - d.config.ColorModel = color.Gray16Model - } else { - d.config.ColorModel = color.GrayModel - } - default: - return nil, UnsupportedError("color model") - } - - return d, nil -} - -// DecodeConfig returns the color model and dimensions of a TIFF image without -// decoding the entire image. -func DecodeConfig(r io.Reader) (image.Config, error) { - d, err := newDecoder(r) - if err != nil { - return image.Config{}, err - } - return d.config, nil -} - -// Decode reads a TIFF image from r and returns it as an image.Image. -// The type of Image returned depends on the contents of the TIFF. -func Decode(r io.Reader) (img image.Image, err error) { - d, err := newDecoder(r) - if err != nil { - return - } - - blockPadding := false - blockWidth := d.config.Width - blockHeight := d.config.Height - blocksAcross := 1 - blocksDown := 1 - - if d.config.Width == 0 { - blocksAcross = 0 - } - if d.config.Height == 0 { - blocksDown = 0 - } - - var blockOffsets, blockCounts []uint - - if int(d.firstVal(tTileWidth)) != 0 { - blockPadding = true - - blockWidth = int(d.firstVal(tTileWidth)) - blockHeight = int(d.firstVal(tTileLength)) - - if blockWidth != 0 { - blocksAcross = (d.config.Width + blockWidth - 1) / blockWidth - } - if blockHeight != 0 { - blocksDown = (d.config.Height + blockHeight - 1) / blockHeight - } - - blockCounts = d.features[tTileByteCounts] - blockOffsets = d.features[tTileOffsets] - - } else { - if int(d.firstVal(tRowsPerStrip)) != 0 { - blockHeight = int(d.firstVal(tRowsPerStrip)) - } - - if blockHeight != 0 { - blocksDown = (d.config.Height + blockHeight - 1) / blockHeight - } - - blockOffsets = d.features[tStripOffsets] - blockCounts = d.features[tStripByteCounts] - } - - // Check if we have the right number of strips/tiles, offsets and counts. - if n := blocksAcross * blocksDown; len(blockOffsets) < n || len(blockCounts) < n { - return nil, FormatError("inconsistent header") - } - - imgRect := image.Rect(0, 0, d.config.Width, d.config.Height) - switch d.mode { - case mGray, mGrayInvert: - if d.bpp == 16 { - img = image.NewGray16(imgRect) - } else { - img = image.NewGray(imgRect) - } - case mPaletted: - img = image.NewPaletted(imgRect, d.palette) - case mNRGBA: - if d.bpp == 16 { - img = image.NewNRGBA64(imgRect) - } else { - img = image.NewNRGBA(imgRect) - } - case mRGB, mRGBA: - if d.bpp == 16 { - img = image.NewRGBA64(imgRect) - } else { - img = image.NewRGBA(imgRect) - } - } - - for i := 0; i < blocksAcross; i++ { - blkW := blockWidth - if !blockPadding && i == blocksAcross-1 && d.config.Width%blockWidth != 0 { - blkW = d.config.Width % blockWidth - } - for j := 0; j < blocksDown; j++ { - blkH := blockHeight - if !blockPadding && j == blocksDown-1 && d.config.Height%blockHeight != 0 { - blkH = d.config.Height % blockHeight - } - offset := int64(blockOffsets[j*blocksAcross+i]) - n := int64(blockCounts[j*blocksAcross+i]) - switch d.firstVal(tCompression) { - - // According to the spec, Compression does not have a default value, - // but some tools interpret a missing Compression value as none so we do - // the same. - case cNone, 0: - if b, ok := d.r.(*buffer); ok { - d.buf, err = b.Slice(int(offset), int(n)) - } else { - d.buf = make([]byte, n) - _, err = d.r.ReadAt(d.buf, offset) - } - case cLZW: - r := lzw.NewReader(io.NewSectionReader(d.r, offset, n), lzw.MSB, 8) - d.buf, err = ioutil.ReadAll(r) - r.Close() - case cDeflate, cDeflateOld: - var r io.ReadCloser - r, err = zlib.NewReader(io.NewSectionReader(d.r, offset, n)) - if err != nil { - return nil, err - } - d.buf, err = ioutil.ReadAll(r) - r.Close() - case cPackBits: - d.buf, err = unpackBits(io.NewSectionReader(d.r, offset, n)) - default: - err = UnsupportedError(fmt.Sprintf("compression value %d", d.firstVal(tCompression))) - } - if err != nil { - return nil, err - } - - xmin := i * blockWidth - ymin := j * blockHeight - xmax := xmin + blkW - ymax := ymin + blkH - err = d.decode(img, xmin, ymin, xmax, ymax) - if err != nil { - return nil, err - } - } - } - return -} - -func init() { - image.RegisterFormat("tiff", leHeader, Decode, DecodeConfig) - image.RegisterFormat("tiff", beHeader, Decode, DecodeConfig) -} diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/reader_test.go b/Godeps/_workspace/src/golang.org/x/image/tiff/reader_test.go deleted file mode 100644 index f5c02e69..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/reader_test.go +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tiff - -import ( - "bytes" - "encoding/binary" - "encoding/hex" - "errors" - "image" - "io/ioutil" - "os" - "strings" - "testing" - - _ "image/png" -) - -const testdataDir = "../testdata/" - -// Read makes *buffer implements io.Reader, so that we can pass one to Decode. -func (*buffer) Read([]byte) (int, error) { - panic("unimplemented") -} - -func load(name string) (image.Image, error) { - f, err := os.Open(testdataDir + name) - if err != nil { - return nil, err - } - defer f.Close() - img, _, err := image.Decode(f) - if err != nil { - return nil, err - } - return img, nil -} - -// TestNoRPS tests decoding an image that has no RowsPerStrip tag. The tag is -// mandatory according to the spec but some software omits it in the case of a -// single strip. -func TestNoRPS(t *testing.T) { - _, err := load("no_rps.tiff") - if err != nil { - t.Fatal(err) - } -} - -// TestNoCompression tests decoding an image that has no Compression tag. This -// tag is mandatory, but most tools interpret a missing value as no -// compression. -func TestNoCompression(t *testing.T) { - _, err := load("no_compress.tiff") - if err != nil { - t.Fatal(err) - } -} - -// TestUnpackBits tests the decoding of PackBits-encoded data. -func TestUnpackBits(t *testing.T) { - var unpackBitsTests = []struct { - compressed string - uncompressed string - }{{ - // Example data from Wikipedia. - "\xfe\xaa\x02\x80\x00\x2a\xfd\xaa\x03\x80\x00\x2a\x22\xf7\xaa", - "\xaa\xaa\xaa\x80\x00\x2a\xaa\xaa\xaa\xaa\x80\x00\x2a\x22\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - }} - for _, u := range unpackBitsTests { - buf, err := unpackBits(strings.NewReader(u.compressed)) - if err != nil { - t.Fatal(err) - } - if string(buf) != u.uncompressed { - t.Fatalf("unpackBits: want %x, got %x", u.uncompressed, buf) - } - } -} - -func TestShortBlockData(t *testing.T) { - b, err := ioutil.ReadFile("../testdata/bw-uncompressed.tiff") - if err != nil { - t.Fatal(err) - } - // The bw-uncompressed.tiff image is a 153x55 bi-level image. This is 1 bit - // per pixel, or 20 bytes per row, times 55 rows, or 1100 bytes of pixel - // data. 1100 in hex is 0x44c, or "\x4c\x04" in little-endian. We replace - // that byte count (StripByteCounts-tagged data) by something less than - // that, so that there is not enough pixel data. - old := []byte{0x4c, 0x04} - new := []byte{0x01, 0x01} - i := bytes.Index(b, old) - if i < 0 { - t.Fatal(`could not find "\x4c\x04" byte count`) - } - if bytes.Contains(b[i+len(old):], old) { - t.Fatal(`too many occurrences of "\x4c\x04"`) - } - b[i+0] = new[0] - b[i+1] = new[1] - if _, err = Decode(bytes.NewReader(b)); err == nil { - t.Fatal("got nil error, want non-nil") - } -} - -func TestDecodeInvalidDataType(t *testing.T) { - b, err := ioutil.ReadFile("../testdata/bw-uncompressed.tiff") - if err != nil { - t.Fatal(err) - } - - // off is the offset of the ImageWidth tag. It is the offset of the overall - // IFD block (0x00000454), plus 2 for the uint16 number of IFD entries, plus 12 - // to skip the first entry. - const off = 0x00000454 + 2 + 12*1 - - if v := binary.LittleEndian.Uint16(b[off : off+2]); v != tImageWidth { - t.Fatal(`could not find ImageWidth tag`) - } - binary.LittleEndian.PutUint16(b[off+2:], uint16(len(lengths))) // invalid datatype - - if _, err = Decode(bytes.NewReader(b)); err == nil { - t.Fatal("got nil error, want non-nil") - } -} - -func compare(t *testing.T, img0, img1 image.Image) { - b0 := img0.Bounds() - b1 := img1.Bounds() - if b0.Dx() != b1.Dx() || b0.Dy() != b1.Dy() { - t.Fatalf("wrong image size: want %s, got %s", b0, b1) - } - x1 := b1.Min.X - b0.Min.X - y1 := b1.Min.Y - b0.Min.Y - for y := b0.Min.Y; y < b0.Max.Y; y++ { - for x := b0.Min.X; x < b0.Max.X; x++ { - c0 := img0.At(x, y) - c1 := img1.At(x+x1, y+y1) - r0, g0, b0, a0 := c0.RGBA() - r1, g1, b1, a1 := c1.RGBA() - if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 { - t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) - } - } - } -} - -// TestDecode tests that decoding a PNG image and a TIFF image result in the -// same pixel data. -func TestDecode(t *testing.T) { - img0, err := load("video-001.png") - if err != nil { - t.Fatal(err) - } - img1, err := load("video-001.tiff") - if err != nil { - t.Fatal(err) - } - img2, err := load("video-001-strip-64.tiff") - if err != nil { - t.Fatal(err) - } - img3, err := load("video-001-tile-64x64.tiff") - if err != nil { - t.Fatal(err) - } - img4, err := load("video-001-16bit.tiff") - if err != nil { - t.Fatal(err) - } - - compare(t, img0, img1) - compare(t, img0, img2) - compare(t, img0, img3) - compare(t, img0, img4) -} - -// TestDecodeLZW tests that decoding a PNG image and a LZW-compressed TIFF -// image result in the same pixel data. -func TestDecodeLZW(t *testing.T) { - img0, err := load("blue-purple-pink.png") - if err != nil { - t.Fatal(err) - } - img1, err := load("blue-purple-pink.lzwcompressed.tiff") - if err != nil { - t.Fatal(err) - } - - compare(t, img0, img1) -} - -// TestDecompress tests that decoding some TIFF images that use different -// compression formats result in the same pixel data. -func TestDecompress(t *testing.T) { - var decompressTests = []string{ - "bw-uncompressed.tiff", - "bw-deflate.tiff", - "bw-packbits.tiff", - } - var img0 image.Image - for _, name := range decompressTests { - img1, err := load(name) - if err != nil { - t.Fatalf("decoding %s: %v", name, err) - } - if img0 == nil { - img0 = img1 - continue - } - compare(t, img0, img1) - } -} - -func replace(src []byte, find, repl string) ([]byte, error) { - removeSpaces := func(r rune) rune { - if r != ' ' { - return r - } - return -1 - } - - f, err := hex.DecodeString(strings.Map(removeSpaces, find)) - if err != nil { - return nil, err - } - r, err := hex.DecodeString(strings.Map(removeSpaces, repl)) - if err != nil { - return nil, err - } - dst := bytes.Replace(src, f, r, 1) - if bytes.Equal(dst, src) { - return nil, errors.New("replacement failed") - } - return dst, nil -} - -// TestZeroBitsPerSample tests that an IFD with a bitsPerSample of 0 does not -// cause a crash. -// Issue 10711. -func TestZeroBitsPerSample(t *testing.T) { - b0, err := ioutil.ReadFile(testdataDir + "bw-deflate.tiff") - if err != nil { - t.Fatal(err) - } - - // Mutate the loaded image to have the problem. - // 02 01: tag number (tBitsPerSample) - // 03 00: data type (short, or uint16) - // 01 00 00 00: count - // ?? 00 00 00: value (1 -> 0) - b1, err := replace(b0, - "02 01 03 00 01 00 00 00 01 00 00 00", - "02 01 03 00 01 00 00 00 00 00 00 00", - ) - if err != nil { - t.Fatal(err) - } - - _, err = Decode(bytes.NewReader(b1)) - if err == nil { - t.Fatal("Decode with 0 bits per sample: got nil error, want non-nil") - } -} - -// TestTileTooBig tests that we do not panic when a tile is too big compared to -// the data available. -// Issue 10712 -func TestTileTooBig(t *testing.T) { - b0, err := ioutil.ReadFile(testdataDir + "video-001-tile-64x64.tiff") - if err != nil { - t.Fatal(err) - } - - // Mutate the loaded image to have the problem. - // - // 42 01: tag number (tTileWidth) - // 03 00: data type (short, or uint16) - // 01 00 00 00: count - // xx 00 00 00: value (0x40 -> 0x44: a wider tile consumes more data - // than is available) - b1, err := replace(b0, - "42 01 03 00 01 00 00 00 40 00 00 00", - "42 01 03 00 01 00 00 00 44 00 00 00", - ) - if err != nil { - t.Fatal(err) - } - - // Turn off the predictor, which makes it possible to hit the - // place with the defect. Without this patch to the image, we run - // out of data too early, and do not hit the part of the code where - // the original panic was. - // - // 3d 01: tag number (tPredictor) - // 03 00: data type (short, or uint16) - // 01 00 00 00: count - // xx 00 00 00: value (2 -> 1: 2 = horizontal, 1 = none) - b2, err := replace(b1, - "3d 01 03 00 01 00 00 00 02 00 00 00", - "3d 01 03 00 01 00 00 00 01 00 00 00", - ) - if err != nil { - t.Fatal(err) - } - - _, err = Decode(bytes.NewReader(b2)) - if err == nil { - t.Fatal("did not expect nil error") - } -} - -// TestZeroSizedImages tests that decoding does not panic when image dimensions -// are zero, and returns a zero-sized image instead. -// Issue 10393. -func TestZeroSizedImages(t *testing.T) { - testsizes := []struct { - w, h int - }{ - {0, 0}, - {1, 0}, - {0, 1}, - {1, 1}, - } - for _, r := range testsizes { - img := image.NewRGBA(image.Rect(0, 0, r.w, r.h)) - var buf bytes.Buffer - if err := Encode(&buf, img, nil); err != nil { - t.Errorf("encode w=%d h=%d: %v", r.w, r.h, err) - continue - } - if _, err := Decode(&buf); err != nil { - t.Errorf("decode w=%d h=%d: %v", r.w, r.h, err) - } - } -} - -// TestLargeIFDEntry tests that a large IFD entry does not cause Decode to -// panic. -// Issue 10596. -func TestLargeIFDEntry(t *testing.T) { - testdata := "II*\x00\x08\x00\x00\x00\f\x000000000000" + - "00000000000000000000" + - "00000000000000000000" + - "00000000000000000000" + - "00000000000000\x17\x01\x04\x00\x01\x00" + - "\x00\xc0000000000000000000" + - "00000000000000000000" + - "00000000000000000000" + - "000000" - _, err := Decode(strings.NewReader(testdata)) - if err == nil { - t.Fatal("Decode with large IFD entry: got nil error, want non-nil") - } -} - -// benchmarkDecode benchmarks the decoding of an image. -func benchmarkDecode(b *testing.B, filename string) { - b.StopTimer() - contents, err := ioutil.ReadFile(testdataDir + filename) - if err != nil { - b.Fatal(err) - } - r := &buffer{buf: contents} - b.StartTimer() - for i := 0; i < b.N; i++ { - _, err := Decode(r) - if err != nil { - b.Fatal("Decode:", err) - } - } -} - -func BenchmarkDecodeCompressed(b *testing.B) { benchmarkDecode(b, "video-001.tiff") } -func BenchmarkDecodeUncompressed(b *testing.B) { benchmarkDecode(b, "video-001-uncompressed.tiff") } diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/writer.go b/Godeps/_workspace/src/golang.org/x/image/tiff/writer.go deleted file mode 100644 index c8a01cea..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/writer.go +++ /dev/null @@ -1,438 +0,0 @@ -// 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. - -package tiff - -import ( - "bytes" - "compress/zlib" - "encoding/binary" - "image" - "io" - "sort" -) - -// The TIFF format allows to choose the order of the different elements freely. -// The basic structure of a TIFF file written by this package is: -// -// 1. Header (8 bytes). -// 2. Image data. -// 3. Image File Directory (IFD). -// 4. "Pointer area" for larger entries in the IFD. - -// We only write little-endian TIFF files. -var enc = binary.LittleEndian - -// An ifdEntry is a single entry in an Image File Directory. -// A value of type dtRational is composed of two 32-bit values, -// thus data contains two uints (numerator and denominator) for a single number. -type ifdEntry struct { - tag int - datatype int - data []uint32 -} - -func (e ifdEntry) putData(p []byte) { - for _, d := range e.data { - switch e.datatype { - case dtByte, dtASCII: - p[0] = byte(d) - p = p[1:] - case dtShort: - enc.PutUint16(p, uint16(d)) - p = p[2:] - case dtLong, dtRational: - enc.PutUint32(p, uint32(d)) - p = p[4:] - } - } -} - -type byTag []ifdEntry - -func (d byTag) Len() int { return len(d) } -func (d byTag) Less(i, j int) bool { return d[i].tag < d[j].tag } -func (d byTag) Swap(i, j int) { d[i], d[j] = d[j], d[i] } - -func encodeGray(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { - if !predictor { - return writePix(w, pix, dy, dx, stride) - } - buf := make([]byte, dx) - for y := 0; y < dy; y++ { - min := y*stride + 0 - max := y*stride + dx - off := 0 - var v0 uint8 - for i := min; i < max; i++ { - v1 := pix[i] - buf[off] = v1 - v0 - v0 = v1 - off++ - } - if _, err := w.Write(buf); err != nil { - return err - } - } - return nil -} - -func encodeGray16(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { - buf := make([]byte, dx*2) - for y := 0; y < dy; y++ { - min := y*stride + 0 - max := y*stride + dx*2 - off := 0 - var v0 uint16 - for i := min; i < max; i += 2 { - // An image.Gray16's Pix is in big-endian order. - v1 := uint16(pix[i])<<8 | uint16(pix[i+1]) - if predictor { - v0, v1 = v1, v1-v0 - } - // We only write little-endian TIFF files. - buf[off+0] = byte(v1) - buf[off+1] = byte(v1 >> 8) - off += 2 - } - if _, err := w.Write(buf); err != nil { - return err - } - } - return nil -} - -func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { - if !predictor { - return writePix(w, pix, dy, dx*4, stride) - } - buf := make([]byte, dx*4) - for y := 0; y < dy; y++ { - min := y*stride + 0 - max := y*stride + dx*4 - off := 0 - var r0, g0, b0, a0 uint8 - for i := min; i < max; i += 4 { - r1, g1, b1, a1 := pix[i+0], pix[i+1], pix[i+2], pix[i+3] - buf[off+0] = r1 - r0 - buf[off+1] = g1 - g0 - buf[off+2] = b1 - b0 - buf[off+3] = a1 - a0 - off += 4 - r0, g0, b0, a0 = r1, g1, b1, a1 - } - if _, err := w.Write(buf); err != nil { - return err - } - } - return nil -} - -func encodeRGBA64(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error { - buf := make([]byte, dx*8) - for y := 0; y < dy; y++ { - min := y*stride + 0 - max := y*stride + dx*8 - off := 0 - var r0, g0, b0, a0 uint16 - for i := min; i < max; i += 8 { - // An image.RGBA64's Pix is in big-endian order. - r1 := uint16(pix[i+0])<<8 | uint16(pix[i+1]) - g1 := uint16(pix[i+2])<<8 | uint16(pix[i+3]) - b1 := uint16(pix[i+4])<<8 | uint16(pix[i+5]) - a1 := uint16(pix[i+6])<<8 | uint16(pix[i+7]) - if predictor { - r0, r1 = r1, r1-r0 - g0, g1 = g1, g1-g0 - b0, b1 = b1, b1-b0 - a0, a1 = a1, a1-a0 - } - // We only write little-endian TIFF files. - buf[off+0] = byte(r1) - buf[off+1] = byte(r1 >> 8) - buf[off+2] = byte(g1) - buf[off+3] = byte(g1 >> 8) - buf[off+4] = byte(b1) - buf[off+5] = byte(b1 >> 8) - buf[off+6] = byte(a1) - buf[off+7] = byte(a1 >> 8) - off += 8 - } - if _, err := w.Write(buf); err != nil { - return err - } - } - return nil -} - -func encode(w io.Writer, m image.Image, predictor bool) error { - bounds := m.Bounds() - buf := make([]byte, 4*bounds.Dx()) - for y := bounds.Min.Y; y < bounds.Max.Y; y++ { - off := 0 - if predictor { - var r0, g0, b0, a0 uint8 - for x := bounds.Min.X; x < bounds.Max.X; x++ { - r, g, b, a := m.At(x, y).RGBA() - r1 := uint8(r >> 8) - g1 := uint8(g >> 8) - b1 := uint8(b >> 8) - a1 := uint8(a >> 8) - buf[off+0] = r1 - r0 - buf[off+1] = g1 - g0 - buf[off+2] = b1 - b0 - buf[off+3] = a1 - a0 - off += 4 - r0, g0, b0, a0 = r1, g1, b1, a1 - } - } else { - for x := bounds.Min.X; x < bounds.Max.X; x++ { - r, g, b, a := m.At(x, y).RGBA() - buf[off+0] = uint8(r >> 8) - buf[off+1] = uint8(g >> 8) - buf[off+2] = uint8(b >> 8) - buf[off+3] = uint8(a >> 8) - off += 4 - } - } - if _, err := w.Write(buf); err != nil { - return err - } - } - return nil -} - -// writePix writes the internal byte array of an image to w. It is less general -// but much faster then encode. writePix is used when pix directly -// corresponds to one of the TIFF image types. -func writePix(w io.Writer, pix []byte, nrows, length, stride int) error { - if length == stride { - _, err := w.Write(pix[:nrows*length]) - return err - } - for ; nrows > 0; nrows-- { - if _, err := w.Write(pix[:length]); err != nil { - return err - } - pix = pix[stride:] - } - return nil -} - -func writeIFD(w io.Writer, ifdOffset int, d []ifdEntry) error { - var buf [ifdLen]byte - // Make space for "pointer area" containing IFD entry data - // longer than 4 bytes. - parea := make([]byte, 1024) - pstart := ifdOffset + ifdLen*len(d) + 6 - var o int // Current offset in parea. - - // The IFD has to be written with the tags in ascending order. - sort.Sort(byTag(d)) - - // Write the number of entries in this IFD. - if err := binary.Write(w, enc, uint16(len(d))); err != nil { - return err - } - for _, ent := range d { - enc.PutUint16(buf[0:2], uint16(ent.tag)) - enc.PutUint16(buf[2:4], uint16(ent.datatype)) - count := uint32(len(ent.data)) - if ent.datatype == dtRational { - count /= 2 - } - enc.PutUint32(buf[4:8], count) - datalen := int(count * lengths[ent.datatype]) - if datalen <= 4 { - ent.putData(buf[8:12]) - } else { - if (o + datalen) > len(parea) { - newlen := len(parea) + 1024 - for (o + datalen) > newlen { - newlen += 1024 - } - newarea := make([]byte, newlen) - copy(newarea, parea) - parea = newarea - } - ent.putData(parea[o : o+datalen]) - enc.PutUint32(buf[8:12], uint32(pstart+o)) - o += datalen - } - if _, err := w.Write(buf[:]); err != nil { - return err - } - } - // The IFD ends with the offset of the next IFD in the file, - // or zero if it is the last one (page 14). - if err := binary.Write(w, enc, uint32(0)); err != nil { - return err - } - _, err := w.Write(parea[:o]) - return err -} - -// Options are the encoding parameters. -type Options struct { - // Compression is the type of compression used. - Compression CompressionType - // Predictor determines whether a differencing predictor is used; - // if true, instead of each pixel's color, the color difference to the - // preceding one is saved. This improves the compression for certain - // types of images and compressors. For example, it works well for - // photos with Deflate compression. - Predictor bool -} - -// Encode writes the image m to w. opt determines the options used for -// encoding, such as the compression type. If opt is nil, an uncompressed -// image is written. -func Encode(w io.Writer, m image.Image, opt *Options) error { - d := m.Bounds().Size() - - compression := uint32(cNone) - predictor := false - if opt != nil { - compression = opt.Compression.specValue() - // The predictor field is only used with LZW. See page 64 of the spec. - predictor = opt.Predictor && compression == cLZW - } - - _, err := io.WriteString(w, leHeader) - if err != nil { - return err - } - - // Compressed data is written into a buffer first, so that we - // know the compressed size. - var buf bytes.Buffer - // dst holds the destination for the pixel data of the image -- - // either w or a writer to buf. - var dst io.Writer - // imageLen is the length of the pixel data in bytes. - // The offset of the IFD is imageLen + 8 header bytes. - var imageLen int - - switch compression { - case cNone: - dst = w - // Write IFD offset before outputting pixel data. - switch m.(type) { - case *image.Paletted: - imageLen = d.X * d.Y * 1 - case *image.Gray: - imageLen = d.X * d.Y * 1 - case *image.Gray16: - imageLen = d.X * d.Y * 2 - case *image.RGBA64: - imageLen = d.X * d.Y * 8 - case *image.NRGBA64: - imageLen = d.X * d.Y * 8 - default: - imageLen = d.X * d.Y * 4 - } - err = binary.Write(w, enc, uint32(imageLen+8)) - if err != nil { - return err - } - case cDeflate: - dst = zlib.NewWriter(&buf) - } - - pr := uint32(prNone) - photometricInterpretation := uint32(pRGB) - samplesPerPixel := uint32(4) - bitsPerSample := []uint32{8, 8, 8, 8} - extraSamples := uint32(0) - colorMap := []uint32{} - - if predictor { - pr = prHorizontal - } - switch m := m.(type) { - case *image.Paletted: - photometricInterpretation = pPaletted - samplesPerPixel = 1 - bitsPerSample = []uint32{8} - colorMap = make([]uint32, 256*3) - for i := 0; i < 256 && i < len(m.Palette); i++ { - r, g, b, _ := m.Palette[i].RGBA() - colorMap[i+0*256] = uint32(r) - colorMap[i+1*256] = uint32(g) - colorMap[i+2*256] = uint32(b) - } - err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor) - case *image.Gray: - photometricInterpretation = pBlackIsZero - samplesPerPixel = 1 - bitsPerSample = []uint32{8} - err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor) - case *image.Gray16: - photometricInterpretation = pBlackIsZero - samplesPerPixel = 1 - bitsPerSample = []uint32{16} - err = encodeGray16(dst, m.Pix, d.X, d.Y, m.Stride, predictor) - case *image.NRGBA: - extraSamples = 2 // Unassociated alpha. - err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor) - case *image.NRGBA64: - extraSamples = 2 // Unassociated alpha. - bitsPerSample = []uint32{16, 16, 16, 16} - err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor) - case *image.RGBA: - extraSamples = 1 // Associated alpha. - err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor) - case *image.RGBA64: - extraSamples = 1 // Associated alpha. - bitsPerSample = []uint32{16, 16, 16, 16} - err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor) - default: - extraSamples = 1 // Associated alpha. - err = encode(dst, m, predictor) - } - if err != nil { - return err - } - - if compression != cNone { - if err = dst.(io.Closer).Close(); err != nil { - return err - } - imageLen = buf.Len() - if err = binary.Write(w, enc, uint32(imageLen+8)); err != nil { - return err - } - if _, err = buf.WriteTo(w); err != nil { - return err - } - } - - ifd := []ifdEntry{ - {tImageWidth, dtShort, []uint32{uint32(d.X)}}, - {tImageLength, dtShort, []uint32{uint32(d.Y)}}, - {tBitsPerSample, dtShort, bitsPerSample}, - {tCompression, dtShort, []uint32{compression}}, - {tPhotometricInterpretation, dtShort, []uint32{photometricInterpretation}}, - {tStripOffsets, dtLong, []uint32{8}}, - {tSamplesPerPixel, dtShort, []uint32{samplesPerPixel}}, - {tRowsPerStrip, dtShort, []uint32{uint32(d.Y)}}, - {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}}, - // There is currently no support for storing the image - // resolution, so give a bogus value of 72x72 dpi. - {tXResolution, dtRational, []uint32{72, 1}}, - {tYResolution, dtRational, []uint32{72, 1}}, - {tResolutionUnit, dtShort, []uint32{resPerInch}}, - } - if pr != prNone { - ifd = append(ifd, ifdEntry{tPredictor, dtShort, []uint32{pr}}) - } - if len(colorMap) != 0 { - ifd = append(ifd, ifdEntry{tColorMap, dtShort, colorMap}) - } - if extraSamples > 0 { - ifd = append(ifd, ifdEntry{tExtraSamples, dtShort, []uint32{extraSamples}}) - } - - return writeIFD(w, imageLen+8, ifd) -} diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/writer_test.go b/Godeps/_workspace/src/golang.org/x/image/tiff/writer_test.go deleted file mode 100644 index c8fb7bf3..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/writer_test.go +++ /dev/null @@ -1,95 +0,0 @@ -// 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. - -package tiff - -import ( - "bytes" - "image" - "io/ioutil" - "os" - "testing" -) - -var roundtripTests = []struct { - filename string - opts *Options -}{ - {"video-001.tiff", nil}, - {"video-001-16bit.tiff", nil}, - {"video-001-gray.tiff", nil}, - {"video-001-gray-16bit.tiff", nil}, - {"video-001-paletted.tiff", nil}, - {"bw-packbits.tiff", nil}, - {"video-001.tiff", &Options{Predictor: true}}, - {"video-001.tiff", &Options{Compression: Deflate}}, - {"video-001.tiff", &Options{Predictor: true, Compression: Deflate}}, -} - -func openImage(filename string) (image.Image, error) { - f, err := os.Open(testdataDir + filename) - if err != nil { - return nil, err - } - defer f.Close() - return Decode(f) -} - -func TestRoundtrip(t *testing.T) { - for _, rt := range roundtripTests { - img, err := openImage(rt.filename) - if err != nil { - t.Fatal(err) - } - out := new(bytes.Buffer) - err = Encode(out, img, rt.opts) - if err != nil { - t.Fatal(err) - } - - img2, err := Decode(&buffer{buf: out.Bytes()}) - if err != nil { - t.Fatal(err) - } - compare(t, img, img2) - } -} - -// TestRoundtrip2 tests that encoding and decoding an image whose -// origin is not (0, 0) gives the same thing. -func TestRoundtrip2(t *testing.T) { - m0 := image.NewRGBA(image.Rect(3, 4, 9, 8)) - for i := range m0.Pix { - m0.Pix[i] = byte(i) - } - out := new(bytes.Buffer) - if err := Encode(out, m0, nil); err != nil { - t.Fatal(err) - } - m1, err := Decode(&buffer{buf: out.Bytes()}) - if err != nil { - t.Fatal(err) - } - compare(t, m0, m1) -} - -func benchmarkEncode(b *testing.B, name string, pixelSize int) { - img, err := openImage(name) - if err != nil { - b.Fatal(err) - } - s := img.Bounds().Size() - b.SetBytes(int64(s.X * s.Y * pixelSize)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Encode(ioutil.Discard, img, nil) - } -} - -func BenchmarkEncode(b *testing.B) { benchmarkEncode(b, "video-001.tiff", 4) } -func BenchmarkEncodePaletted(b *testing.B) { benchmarkEncode(b, "video-001-paletted.tiff", 1) } -func BenchmarkEncodeGray(b *testing.B) { benchmarkEncode(b, "video-001-gray.tiff", 1) } -func BenchmarkEncodeGray16(b *testing.B) { benchmarkEncode(b, "video-001-gray-16bit.tiff", 2) } -func BenchmarkEncodeRGBA(b *testing.B) { benchmarkEncode(b, "video-001.tiff", 4) } -func BenchmarkEncodeRGBA64(b *testing.B) { benchmarkEncode(b, "video-001-16bit.tiff", 8) } diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8/decode.go b/Godeps/_workspace/src/golang.org/x/image/vp8/decode.go deleted file mode 100644 index 1bb50284..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8/decode.go +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package vp8 implements a decoder for the VP8 lossy image format. -// -// The VP8 specification is RFC 6386. -package vp8 // import "golang.org/x/image/vp8" - -// This file implements the top-level decoding algorithm. - -import ( - "errors" - "image" - "io" -) - -// limitReader wraps an io.Reader to read at most n bytes from it. -type limitReader struct { - r io.Reader - n int -} - -// ReadFull reads exactly len(p) bytes into p. -func (r *limitReader) ReadFull(p []byte) error { - if len(p) > r.n { - return io.ErrUnexpectedEOF - } - n, err := io.ReadFull(r.r, p) - r.n -= n - return err -} - -// FrameHeader is a frame header, as specified in section 9.1. -type FrameHeader struct { - KeyFrame bool - VersionNumber uint8 - ShowFrame bool - FirstPartitionLen uint32 - Width int - Height int - XScale uint8 - YScale uint8 -} - -const ( - nSegment = 4 - nSegmentProb = 3 -) - -// segmentHeader holds segment-related header information. -type segmentHeader struct { - useSegment bool - updateMap bool - relativeDelta bool - quantizer [nSegment]int8 - filterStrength [nSegment]int8 - prob [nSegmentProb]uint8 -} - -const ( - nRefLFDelta = 4 - nModeLFDelta = 4 -) - -// filterHeader holds filter-related header information. -type filterHeader struct { - simple bool - level int8 - sharpness uint8 - useLFDelta bool - refLFDelta [nRefLFDelta]int8 - modeLFDelta [nModeLFDelta]int8 - perSegmentLevel [nSegment]int8 -} - -// mb is the per-macroblock decode state. A decoder maintains mbw+1 of these -// as it is decoding macroblocks left-to-right and top-to-bottom: mbw for the -// macroblocks in the row above, and one for the macroblock to the left. -type mb struct { - // pred is the predictor mode for the 4 bottom or right 4x4 luma regions. - pred [4]uint8 - // nzMask is a mask of 8 bits: 4 for the bottom or right 4x4 luma regions, - // and 2 + 2 for the bottom or right 4x4 chroma regions. A 1 bit indicates - // that that region has non-zero coefficients. - nzMask uint8 - // nzY16 is a 0/1 value that is 1 if the macroblock used Y16 prediction and - // had non-zero coefficients. - nzY16 uint8 -} - -// Decoder decodes VP8 bitstreams into frames. Decoding one frame consists of -// calling Init, DecodeFrameHeader and then DecodeFrame in that order. -// A Decoder can be re-used to decode multiple frames. -type Decoder struct { - // r is the input bitsream. - r limitReader - // scratch is a scratch buffer. - scratch [8]byte - // img is the YCbCr image to decode into. - img *image.YCbCr - // mbw and mbh are the number of 16x16 macroblocks wide and high the image is. - mbw, mbh int - // frameHeader is the frame header. When decoding multiple frames, - // frames that aren't key frames will inherit the Width, Height, - // XScale and YScale of the most recent key frame. - frameHeader FrameHeader - // Other headers. - segmentHeader segmentHeader - filterHeader filterHeader - // The image data is divided into a number of independent partitions. - // There is 1 "first partition" and between 1 and 8 "other partitions" - // for coefficient data. - fp partition - op [8]partition - nOP int - // Quantization factors. - quant [nSegment]quant - // DCT/WHT coefficient decoding probabilities. - tokenProb [nPlane][nBand][nContext][nProb]uint8 - useSkipProb bool - skipProb uint8 - // Loop filter parameters. - filterParams [nSegment][2]filterParam - perMBFilterParams []filterParam - - // The eight fields below relate to the current macroblock being decoded. - // - // Segment-based adjustments. - segment int - // Per-macroblock state for the macroblock immediately left of and those - // macroblocks immediately above the current macroblock. - leftMB mb - upMB []mb - // Bitmasks for which 4x4 regions of coeff contain non-zero coefficients. - nzDCMask, nzACMask uint32 - // Predictor modes. - usePredY16 bool // The libwebp C code calls this !is_i4x4_. - predY16 uint8 - predC8 uint8 - predY4 [4][4]uint8 - - // The two fields below form a workspace for reconstructing a macroblock. - // Their specific sizes are documented in reconstruct.go. - coeff [1*16*16 + 2*8*8 + 1*4*4]int16 - ybr [1 + 16 + 1 + 8][32]uint8 -} - -// NewDecoder returns a new Decoder. -func NewDecoder() *Decoder { - return &Decoder{} -} - -// Init initializes the decoder to read at most n bytes from r. -func (d *Decoder) Init(r io.Reader, n int) { - d.r = limitReader{r, n} -} - -// DecodeFrameHeader decodes the frame header. -func (d *Decoder) DecodeFrameHeader() (fh FrameHeader, err error) { - // All frame headers are at least 3 bytes long. - b := d.scratch[:3] - if err = d.r.ReadFull(b); err != nil { - return - } - d.frameHeader.KeyFrame = (b[0] & 1) == 0 - d.frameHeader.VersionNumber = (b[0] >> 1) & 7 - d.frameHeader.ShowFrame = (b[0]>>4)&1 == 1 - d.frameHeader.FirstPartitionLen = uint32(b[0])>>5 | uint32(b[1])<<3 | uint32(b[2])<<11 - if !d.frameHeader.KeyFrame { - return d.frameHeader, nil - } - // Frame headers for key frames are an additional 7 bytes long. - b = d.scratch[:7] - if err = d.r.ReadFull(b); err != nil { - return - } - // Check the magic sync code. - if b[0] != 0x9d || b[1] != 0x01 || b[2] != 0x2a { - err = errors.New("vp8: invalid format") - return - } - d.frameHeader.Width = int(b[4]&0x3f)<<8 | int(b[3]) - d.frameHeader.Height = int(b[6]&0x3f)<<8 | int(b[5]) - d.frameHeader.XScale = b[4] >> 6 - d.frameHeader.YScale = b[6] >> 6 - d.mbw = (d.frameHeader.Width + 0x0f) >> 4 - d.mbh = (d.frameHeader.Height + 0x0f) >> 4 - d.segmentHeader = segmentHeader{ - prob: [3]uint8{0xff, 0xff, 0xff}, - } - d.tokenProb = defaultTokenProb - d.segment = 0 - return d.frameHeader, nil -} - -// ensureImg ensures that d.img is large enough to hold the decoded frame. -func (d *Decoder) ensureImg() { - if d.img != nil { - p0, p1 := d.img.Rect.Min, d.img.Rect.Max - if p0.X == 0 && p0.Y == 0 && p1.X >= 16*d.mbw && p1.Y >= 16*d.mbh { - return - } - } - m := image.NewYCbCr(image.Rect(0, 0, 16*d.mbw, 16*d.mbh), image.YCbCrSubsampleRatio420) - d.img = m.SubImage(image.Rect(0, 0, d.frameHeader.Width, d.frameHeader.Height)).(*image.YCbCr) - d.perMBFilterParams = make([]filterParam, d.mbw*d.mbh) - d.upMB = make([]mb, d.mbw) -} - -// parseSegmentHeader parses the segment header, as specified in section 9.3. -func (d *Decoder) parseSegmentHeader() { - d.segmentHeader.useSegment = d.fp.readBit(uniformProb) - if !d.segmentHeader.useSegment { - d.segmentHeader.updateMap = false - return - } - d.segmentHeader.updateMap = d.fp.readBit(uniformProb) - if d.fp.readBit(uniformProb) { - d.segmentHeader.relativeDelta = !d.fp.readBit(uniformProb) - for i := range d.segmentHeader.quantizer { - d.segmentHeader.quantizer[i] = int8(d.fp.readOptionalInt(uniformProb, 7)) - } - for i := range d.segmentHeader.filterStrength { - d.segmentHeader.filterStrength[i] = int8(d.fp.readOptionalInt(uniformProb, 6)) - } - } - if !d.segmentHeader.updateMap { - return - } - for i := range d.segmentHeader.prob { - if d.fp.readBit(uniformProb) { - d.segmentHeader.prob[i] = uint8(d.fp.readUint(uniformProb, 8)) - } else { - d.segmentHeader.prob[i] = 0xff - } - } -} - -// parseFilterHeader parses the filter header, as specified in section 9.4. -func (d *Decoder) parseFilterHeader() { - d.filterHeader.simple = d.fp.readBit(uniformProb) - d.filterHeader.level = int8(d.fp.readUint(uniformProb, 6)) - d.filterHeader.sharpness = uint8(d.fp.readUint(uniformProb, 3)) - d.filterHeader.useLFDelta = d.fp.readBit(uniformProb) - if d.filterHeader.useLFDelta && d.fp.readBit(uniformProb) { - for i := range d.filterHeader.refLFDelta { - d.filterHeader.refLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6)) - } - for i := range d.filterHeader.modeLFDelta { - d.filterHeader.modeLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6)) - } - } - if d.filterHeader.level == 0 { - return - } - if d.segmentHeader.useSegment { - for i := range d.filterHeader.perSegmentLevel { - strength := d.segmentHeader.filterStrength[i] - if d.segmentHeader.relativeDelta { - strength += d.filterHeader.level - } - d.filterHeader.perSegmentLevel[i] = strength - } - } else { - d.filterHeader.perSegmentLevel[0] = d.filterHeader.level - } - d.computeFilterParams() -} - -// parseOtherPartitions parses the other partitions, as specified in section 9.5. -func (d *Decoder) parseOtherPartitions() error { - const maxNOP = 1 << 3 - var partLens [maxNOP]int - d.nOP = 1 << d.fp.readUint(uniformProb, 2) - - // The final partition length is implied by the the remaining chunk data - // (d.r.n) and the other d.nOP-1 partition lengths. Those d.nOP-1 partition - // lengths are stored as 24-bit uints, i.e. up to 16 MiB per partition. - n := 3 * (d.nOP - 1) - partLens[d.nOP-1] = d.r.n - n - if partLens[d.nOP-1] < 0 { - return io.ErrUnexpectedEOF - } - if n > 0 { - buf := make([]byte, n) - if err := d.r.ReadFull(buf); err != nil { - return err - } - for i := 0; i < d.nOP-1; i++ { - pl := int(buf[3*i+0]) | int(buf[3*i+1])<<8 | int(buf[3*i+2])<<16 - if pl > partLens[d.nOP-1] { - return io.ErrUnexpectedEOF - } - partLens[i] = pl - partLens[d.nOP-1] -= pl - } - } - - // We check if the final partition length can also fit into a 24-bit uint. - // Strictly speaking, this isn't part of the spec, but it guards against a - // malicious WEBP image that is too large to ReadFull the encoded DCT - // coefficients into memory, whether that's because the actual WEBP file is - // too large, or whether its RIFF metadata lists too large a chunk. - if 1<<24 <= partLens[d.nOP-1] { - return errors.New("vp8: too much data to decode") - } - - buf := make([]byte, d.r.n) - if err := d.r.ReadFull(buf); err != nil { - return err - } - for i, pl := range partLens { - if i == d.nOP { - break - } - d.op[i].init(buf[:pl]) - buf = buf[pl:] - } - return nil -} - -// parseOtherHeaders parses header information other than the frame header. -func (d *Decoder) parseOtherHeaders() error { - // Initialize and parse the first partition. - firstPartition := make([]byte, d.frameHeader.FirstPartitionLen) - if err := d.r.ReadFull(firstPartition); err != nil { - return err - } - d.fp.init(firstPartition) - if d.frameHeader.KeyFrame { - // Read and ignore the color space and pixel clamp values. They are - // specified in section 9.2, but are unimplemented. - d.fp.readBit(uniformProb) - d.fp.readBit(uniformProb) - } - d.parseSegmentHeader() - d.parseFilterHeader() - if err := d.parseOtherPartitions(); err != nil { - return err - } - d.parseQuant() - if !d.frameHeader.KeyFrame { - // Golden and AltRef frames are specified in section 9.7. - // TODO(nigeltao): implement. Note that they are only used for video, not still images. - return errors.New("vp8: Golden / AltRef frames are not implemented") - } - // Read and ignore the refreshLastFrameBuffer bit, specified in section 9.8. - // It applies only to video, and not still images. - d.fp.readBit(uniformProb) - d.parseTokenProb() - d.useSkipProb = d.fp.readBit(uniformProb) - if d.useSkipProb { - d.skipProb = uint8(d.fp.readUint(uniformProb, 8)) - } - if d.fp.unexpectedEOF { - return io.ErrUnexpectedEOF - } - return nil -} - -// DecodeFrame decodes the frame and returns it as an YCbCr image. -// The image's contents are valid up until the next call to Decoder.Init. -func (d *Decoder) DecodeFrame() (*image.YCbCr, error) { - d.ensureImg() - if err := d.parseOtherHeaders(); err != nil { - return nil, err - } - // Reconstruct the rows. - for mbx := 0; mbx < d.mbw; mbx++ { - d.upMB[mbx] = mb{} - } - for mby := 0; mby < d.mbh; mby++ { - d.leftMB = mb{} - for mbx := 0; mbx < d.mbw; mbx++ { - skip := d.reconstruct(mbx, mby) - fs := d.filterParams[d.segment][btou(!d.usePredY16)] - fs.inner = fs.inner || !skip - d.perMBFilterParams[d.mbw*mby+mbx] = fs - } - } - if d.fp.unexpectedEOF { - return nil, io.ErrUnexpectedEOF - } - for i := 0; i < d.nOP; i++ { - if d.op[i].unexpectedEOF { - return nil, io.ErrUnexpectedEOF - } - } - // Apply the loop filter. - // - // Even if we are using per-segment levels, section 15 says that "loop - // filtering must be skipped entirely if loop_filter_level at either the - // frame header level or macroblock override level is 0". - if d.filterHeader.level != 0 { - if d.filterHeader.simple { - d.simpleFilter() - } else { - d.normalFilter() - } - } - return d.img, nil -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8/filter.go b/Godeps/_workspace/src/golang.org/x/image/vp8/filter.go deleted file mode 100644 index e34a811b..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8/filter.go +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8 - -// filter2 modifies a 2-pixel wide or 2-pixel high band along an edge. -func filter2(pix []byte, level, index, iStep, jStep int) { - for n := 16; n > 0; n, index = n-1, index+iStep { - p1 := int(pix[index-2*jStep]) - p0 := int(pix[index-1*jStep]) - q0 := int(pix[index+0*jStep]) - q1 := int(pix[index+1*jStep]) - if abs(p0-q0)<<1+abs(p1-q1)>>1 > level { - continue - } - a := 3*(q0-p0) + clamp127(p1-q1) - a1 := clamp15((a + 4) >> 3) - a2 := clamp15((a + 3) >> 3) - pix[index-1*jStep] = clamp255(p0 + a2) - pix[index+0*jStep] = clamp255(q0 - a1) - } -} - -// filter246 modifies a 2-, 4- or 6-pixel wide or high band along an edge. -func filter246(pix []byte, n, level, ilevel, hlevel, index, iStep, jStep int, fourNotSix bool) { - for ; n > 0; n, index = n-1, index+iStep { - p3 := int(pix[index-4*jStep]) - p2 := int(pix[index-3*jStep]) - p1 := int(pix[index-2*jStep]) - p0 := int(pix[index-1*jStep]) - q0 := int(pix[index+0*jStep]) - q1 := int(pix[index+1*jStep]) - q2 := int(pix[index+2*jStep]) - q3 := int(pix[index+3*jStep]) - if abs(p0-q0)<<1+abs(p1-q1)>>1 > level { - continue - } - if abs(p3-p2) > ilevel || - abs(p2-p1) > ilevel || - abs(p1-p0) > ilevel || - abs(q1-q0) > ilevel || - abs(q2-q1) > ilevel || - abs(q3-q2) > ilevel { - continue - } - if abs(p1-p0) > hlevel || abs(q1-q0) > hlevel { - // Filter 2 pixels. - a := 3*(q0-p0) + clamp127(p1-q1) - a1 := clamp15((a + 4) >> 3) - a2 := clamp15((a + 3) >> 3) - pix[index-1*jStep] = clamp255(p0 + a2) - pix[index+0*jStep] = clamp255(q0 - a1) - } else if fourNotSix { - // Filter 4 pixels. - a := 3 * (q0 - p0) - a1 := clamp15((a + 4) >> 3) - a2 := clamp15((a + 3) >> 3) - a3 := (a1 + 1) >> 1 - pix[index-2*jStep] = clamp255(p1 + a3) - pix[index-1*jStep] = clamp255(p0 + a2) - pix[index+0*jStep] = clamp255(q0 - a1) - pix[index+1*jStep] = clamp255(q1 - a3) - } else { - // Filter 6 pixels. - a := clamp127(3*(q0-p0) + clamp127(p1-q1)) - a1 := (27*a + 63) >> 7 - a2 := (18*a + 63) >> 7 - a3 := (9*a + 63) >> 7 - pix[index-3*jStep] = clamp255(p2 + a3) - pix[index-2*jStep] = clamp255(p1 + a2) - pix[index-1*jStep] = clamp255(p0 + a1) - pix[index+0*jStep] = clamp255(q0 - a1) - pix[index+1*jStep] = clamp255(q1 - a2) - pix[index+2*jStep] = clamp255(q2 - a3) - } - } -} - -// simpleFilter implements the simple filter, as specified in section 15.2. -func (d *Decoder) simpleFilter() { - for mby := 0; mby < d.mbh; mby++ { - for mbx := 0; mbx < d.mbw; mbx++ { - f := d.perMBFilterParams[d.mbw*mby+mbx] - if f.level == 0 { - continue - } - l := int(f.level) - yIndex := (mby*d.img.YStride + mbx) * 16 - if mbx > 0 { - filter2(d.img.Y, l+4, yIndex, d.img.YStride, 1) - } - if f.inner { - filter2(d.img.Y, l, yIndex+0x4, d.img.YStride, 1) - filter2(d.img.Y, l, yIndex+0x8, d.img.YStride, 1) - filter2(d.img.Y, l, yIndex+0xc, d.img.YStride, 1) - } - if mby > 0 { - filter2(d.img.Y, l+4, yIndex, 1, d.img.YStride) - } - if f.inner { - filter2(d.img.Y, l, yIndex+d.img.YStride*0x4, 1, d.img.YStride) - filter2(d.img.Y, l, yIndex+d.img.YStride*0x8, 1, d.img.YStride) - filter2(d.img.Y, l, yIndex+d.img.YStride*0xc, 1, d.img.YStride) - } - } - } -} - -// normalFilter implements the normal filter, as specified in section 15.3. -func (d *Decoder) normalFilter() { - for mby := 0; mby < d.mbh; mby++ { - for mbx := 0; mbx < d.mbw; mbx++ { - f := d.perMBFilterParams[d.mbw*mby+mbx] - if f.level == 0 { - continue - } - l, il, hl := int(f.level), int(f.ilevel), int(f.hlevel) - yIndex := (mby*d.img.YStride + mbx) * 16 - cIndex := (mby*d.img.CStride + mbx) * 8 - if mbx > 0 { - filter246(d.img.Y, 16, l+4, il, hl, yIndex, d.img.YStride, 1, false) - filter246(d.img.Cb, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false) - filter246(d.img.Cr, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false) - } - if f.inner { - filter246(d.img.Y, 16, l, il, hl, yIndex+0x4, d.img.YStride, 1, true) - filter246(d.img.Y, 16, l, il, hl, yIndex+0x8, d.img.YStride, 1, true) - filter246(d.img.Y, 16, l, il, hl, yIndex+0xc, d.img.YStride, 1, true) - filter246(d.img.Cb, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true) - filter246(d.img.Cr, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true) - } - if mby > 0 { - filter246(d.img.Y, 16, l+4, il, hl, yIndex, 1, d.img.YStride, false) - filter246(d.img.Cb, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false) - filter246(d.img.Cr, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false) - } - if f.inner { - filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x4, 1, d.img.YStride, true) - filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x8, 1, d.img.YStride, true) - filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0xc, 1, d.img.YStride, true) - filter246(d.img.Cb, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true) - filter246(d.img.Cr, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true) - } - } - } -} - -// filterParam holds the loop filter parameters for a macroblock. -type filterParam struct { - // The first three fields are thresholds used by the loop filter to smooth - // over the edges and interior of a macroblock. level is used by both the - // simple and normal filters. The inner level and high edge variance level - // are only used by the normal filter. - level, ilevel, hlevel uint8 - // inner is whether the inner loop filter cannot be optimized out as a - // no-op for this particular macroblock. - inner bool -} - -// computeFilterParams computes the loop filter parameters, as specified in -// section 15.4. -func (d *Decoder) computeFilterParams() { - for i := range d.filterParams { - baseLevel := d.filterHeader.level - if d.segmentHeader.useSegment { - baseLevel = d.segmentHeader.filterStrength[i] - if d.segmentHeader.relativeDelta { - baseLevel += d.filterHeader.level - } - } - - for j := range d.filterParams[i] { - p := &d.filterParams[i][j] - p.inner = j != 0 - level := baseLevel - if d.filterHeader.useLFDelta { - // The libwebp C code has a "TODO: only CURRENT is handled for now." - level += d.filterHeader.refLFDelta[0] - if j != 0 { - level += d.filterHeader.modeLFDelta[0] - } - } - if level <= 0 { - p.level = 0 - continue - } - if level > 63 { - level = 63 - } - ilevel := level - if d.filterHeader.sharpness > 0 { - if d.filterHeader.sharpness > 4 { - ilevel >>= 2 - } else { - ilevel >>= 1 - } - if x := int8(9 - d.filterHeader.sharpness); ilevel > x { - ilevel = x - } - } - if ilevel < 1 { - ilevel = 1 - } - p.ilevel = uint8(ilevel) - p.level = uint8(2*level + ilevel) - if d.frameHeader.KeyFrame { - if level < 15 { - p.hlevel = 0 - } else if level < 40 { - p.hlevel = 1 - } else { - p.hlevel = 2 - } - } else { - if level < 15 { - p.hlevel = 0 - } else if level < 20 { - p.hlevel = 1 - } else if level < 40 { - p.hlevel = 2 - } else { - p.hlevel = 3 - } - } - } - } -} - -// intSize is either 32 or 64. -const intSize = 32 << (^uint(0) >> 63) - -func abs(x int) int { - // m := -1 if x < 0. m := 0 otherwise. - m := x >> (intSize - 1) - - // In two's complement representation, the negative number - // of any number (except the smallest one) can be computed - // by flipping all the bits and add 1. This is faster than - // code with a branch. - // See Hacker's Delight, section 2-4. - return (x ^ m) - m -} - -func clamp15(x int) int { - if x < -16 { - return -16 - } - if x > 15 { - return 15 - } - return x -} - -func clamp127(x int) int { - if x < -128 { - return -128 - } - if x > 127 { - return 127 - } - return x -} - -func clamp255(x int) uint8 { - if x < 0 { - return 0 - } - if x > 255 { - return 255 - } - return uint8(x) -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8/idct.go b/Godeps/_workspace/src/golang.org/x/image/vp8/idct.go deleted file mode 100644 index 929af2cc..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8/idct.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8 - -// This file implements the inverse Discrete Cosine Transform and the inverse -// Walsh Hadamard Transform (WHT), as specified in sections 14.3 and 14.4. - -func clip8(i int32) uint8 { - if i < 0 { - return 0 - } - if i > 255 { - return 255 - } - return uint8(i) -} - -func (z *Decoder) inverseDCT4(y, x, coeffBase int) { - const ( - c1 = 85627 // 65536 * cos(pi/8) * sqrt(2). - c2 = 35468 // 65536 * sin(pi/8) * sqrt(2). - ) - var m [4][4]int32 - for i := 0; i < 4; i++ { - a := int32(z.coeff[coeffBase+0]) + int32(z.coeff[coeffBase+8]) - b := int32(z.coeff[coeffBase+0]) - int32(z.coeff[coeffBase+8]) - c := (int32(z.coeff[coeffBase+4])*c2)>>16 - (int32(z.coeff[coeffBase+12])*c1)>>16 - d := (int32(z.coeff[coeffBase+4])*c1)>>16 + (int32(z.coeff[coeffBase+12])*c2)>>16 - m[i][0] = a + d - m[i][1] = b + c - m[i][2] = b - c - m[i][3] = a - d - coeffBase++ - } - for j := 0; j < 4; j++ { - dc := m[0][j] + 4 - a := dc + m[2][j] - b := dc - m[2][j] - c := (m[1][j]*c2)>>16 - (m[3][j]*c1)>>16 - d := (m[1][j]*c1)>>16 + (m[3][j]*c2)>>16 - z.ybr[y+j][x+0] = clip8(int32(z.ybr[y+j][x+0]) + (a+d)>>3) - z.ybr[y+j][x+1] = clip8(int32(z.ybr[y+j][x+1]) + (b+c)>>3) - z.ybr[y+j][x+2] = clip8(int32(z.ybr[y+j][x+2]) + (b-c)>>3) - z.ybr[y+j][x+3] = clip8(int32(z.ybr[y+j][x+3]) + (a-d)>>3) - } -} - -func (z *Decoder) inverseDCT4DCOnly(y, x, coeffBase int) { - dc := (int32(z.coeff[coeffBase+0]) + 4) >> 3 - for j := 0; j < 4; j++ { - for i := 0; i < 4; i++ { - z.ybr[y+j][x+i] = clip8(int32(z.ybr[y+j][x+i]) + dc) - } - } -} - -func (z *Decoder) inverseDCT8(y, x, coeffBase int) { - z.inverseDCT4(y+0, x+0, coeffBase+0*16) - z.inverseDCT4(y+0, x+4, coeffBase+1*16) - z.inverseDCT4(y+4, x+0, coeffBase+2*16) - z.inverseDCT4(y+4, x+4, coeffBase+3*16) -} - -func (z *Decoder) inverseDCT8DCOnly(y, x, coeffBase int) { - z.inverseDCT4DCOnly(y+0, x+0, coeffBase+0*16) - z.inverseDCT4DCOnly(y+0, x+4, coeffBase+1*16) - z.inverseDCT4DCOnly(y+4, x+0, coeffBase+2*16) - z.inverseDCT4DCOnly(y+4, x+4, coeffBase+3*16) -} - -func (d *Decoder) inverseWHT16() { - var m [16]int32 - for i := 0; i < 4; i++ { - a0 := int32(d.coeff[384+0+i]) + int32(d.coeff[384+12+i]) - a1 := int32(d.coeff[384+4+i]) + int32(d.coeff[384+8+i]) - a2 := int32(d.coeff[384+4+i]) - int32(d.coeff[384+8+i]) - a3 := int32(d.coeff[384+0+i]) - int32(d.coeff[384+12+i]) - m[0+i] = a0 + a1 - m[8+i] = a0 - a1 - m[4+i] = a3 + a2 - m[12+i] = a3 - a2 - } - out := 0 - for i := 0; i < 4; i++ { - dc := m[0+i*4] + 3 - a0 := dc + m[3+i*4] - a1 := m[1+i*4] + m[2+i*4] - a2 := m[1+i*4] - m[2+i*4] - a3 := dc - m[3+i*4] - d.coeff[out+0] = int16((a0 + a1) >> 3) - d.coeff[out+16] = int16((a3 + a2) >> 3) - d.coeff[out+32] = int16((a0 - a1) >> 3) - d.coeff[out+48] = int16((a3 - a2) >> 3) - out += 64 - } -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8/partition.go b/Godeps/_workspace/src/golang.org/x/image/vp8/partition.go deleted file mode 100644 index 72288bde..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8/partition.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8 - -// Each VP8 frame consists of between 2 and 9 bitstream partitions. -// Each partition is byte-aligned and is independently arithmetic-encoded. -// -// This file implements decoding a partition's bitstream, as specified in -// chapter 7. The implementation follows libwebp's approach instead of the -// specification's reference C implementation. For example, we use a look-up -// table instead of a for loop to recalibrate the encoded range. - -var ( - lutShift = [127]uint8{ - 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - } - lutRangeM1 = [127]uint8{ - 127, - 127, 191, - 127, 159, 191, 223, - 127, 143, 159, 175, 191, 207, 223, 239, - 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, 247, - 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, 183, 187, - 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, - 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, - 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, - 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, - 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, - } -) - -// uniformProb represents a 50% probability that the next bit is 0. -const uniformProb = 128 - -// partition holds arithmetic-coded bits. -type partition struct { - // buf is the input bytes. - buf []byte - // r is how many of buf's bytes have been consumed. - r int - // rangeM1 is range minus 1, where range is in the arithmetic coding sense, - // not the Go language sense. - rangeM1 uint32 - // bits and nBits hold those bits shifted out of buf but not yet consumed. - bits uint32 - nBits uint8 - // unexpectedEOF tells whether we tried to read past buf. - unexpectedEOF bool -} - -// init initializes the partition. -func (p *partition) init(buf []byte) { - p.buf = buf - p.r = 0 - p.rangeM1 = 254 - p.bits = 0 - p.nBits = 0 - p.unexpectedEOF = false -} - -// readBit returns the next bit. -func (p *partition) readBit(prob uint8) bool { - if p.nBits < 8 { - if p.r >= len(p.buf) { - p.unexpectedEOF = true - return false - } - // Expression split for 386 compiler. - x := uint32(p.buf[p.r]) - p.bits |= x << (8 - p.nBits) - p.r++ - p.nBits += 8 - } - split := (p.rangeM1*uint32(prob))>>8 + 1 - bit := p.bits >= split<<8 - if bit { - p.rangeM1 -= split - p.bits -= split << 8 - } else { - p.rangeM1 = split - 1 - } - if p.rangeM1 < 127 { - shift := lutShift[p.rangeM1] - p.rangeM1 = uint32(lutRangeM1[p.rangeM1]) - p.bits <<= shift - p.nBits -= shift - } - return bit -} - -// readUint returns the next n-bit unsigned integer. -func (p *partition) readUint(prob, n uint8) uint32 { - var u uint32 - for n > 0 { - n-- - if p.readBit(prob) { - u |= 1 << n - } - } - return u -} - -// readInt returns the next n-bit signed integer. -func (p *partition) readInt(prob, n uint8) int32 { - u := p.readUint(prob, n) - b := p.readBit(prob) - if b { - return -int32(u) - } - return int32(u) -} - -// readOptionalInt returns the next n-bit signed integer in an encoding -// where the likely result is zero. -func (p *partition) readOptionalInt(prob, n uint8) int32 { - if !p.readBit(prob) { - return 0 - } - return p.readInt(prob, n) -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8/pred.go b/Godeps/_workspace/src/golang.org/x/image/vp8/pred.go deleted file mode 100644 index 58c2689e..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8/pred.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8 - -// This file implements parsing the predictor modes, as specified in chapter -// 11. - -func (d *Decoder) parsePredModeY16(mbx int) { - var p uint8 - if !d.fp.readBit(156) { - if !d.fp.readBit(163) { - p = predDC - } else { - p = predVE - } - } else if !d.fp.readBit(128) { - p = predHE - } else { - p = predTM - } - for i := 0; i < 4; i++ { - d.upMB[mbx].pred[i] = p - d.leftMB.pred[i] = p - } - d.predY16 = p -} - -func (d *Decoder) parsePredModeC8() { - if !d.fp.readBit(142) { - d.predC8 = predDC - } else if !d.fp.readBit(114) { - d.predC8 = predVE - } else if !d.fp.readBit(183) { - d.predC8 = predHE - } else { - d.predC8 = predTM - } -} - -func (d *Decoder) parsePredModeY4(mbx int) { - for j := 0; j < 4; j++ { - p := d.leftMB.pred[j] - for i := 0; i < 4; i++ { - prob := &predProb[d.upMB[mbx].pred[i]][p] - if !d.fp.readBit(prob[0]) { - p = predDC - } else if !d.fp.readBit(prob[1]) { - p = predTM - } else if !d.fp.readBit(prob[2]) { - p = predVE - } else if !d.fp.readBit(prob[3]) { - if !d.fp.readBit(prob[4]) { - p = predHE - } else if !d.fp.readBit(prob[5]) { - p = predRD - } else { - p = predVR - } - } else if !d.fp.readBit(prob[6]) { - p = predLD - } else if !d.fp.readBit(prob[7]) { - p = predVL - } else if !d.fp.readBit(prob[8]) { - p = predHD - } else { - p = predHU - } - d.predY4[j][i] = p - d.upMB[mbx].pred[i] = p - } - d.leftMB.pred[j] = p - } -} - -// predProb are the probabilities to decode a 4x4 region's predictor mode given -// the predictor modes of the regions above and left of it. -// These values are specified in section 11.5. -var predProb = [nPred][nPred][9]uint8{ - { - {231, 120, 48, 89, 115, 113, 120, 152, 112}, - {152, 179, 64, 126, 170, 118, 46, 70, 95}, - {175, 69, 143, 80, 85, 82, 72, 155, 103}, - {56, 58, 10, 171, 218, 189, 17, 13, 152}, - {114, 26, 17, 163, 44, 195, 21, 10, 173}, - {121, 24, 80, 195, 26, 62, 44, 64, 85}, - {144, 71, 10, 38, 171, 213, 144, 34, 26}, - {170, 46, 55, 19, 136, 160, 33, 206, 71}, - {63, 20, 8, 114, 114, 208, 12, 9, 226}, - {81, 40, 11, 96, 182, 84, 29, 16, 36}, - }, - { - {134, 183, 89, 137, 98, 101, 106, 165, 148}, - {72, 187, 100, 130, 157, 111, 32, 75, 80}, - {66, 102, 167, 99, 74, 62, 40, 234, 128}, - {41, 53, 9, 178, 241, 141, 26, 8, 107}, - {74, 43, 26, 146, 73, 166, 49, 23, 157}, - {65, 38, 105, 160, 51, 52, 31, 115, 128}, - {104, 79, 12, 27, 217, 255, 87, 17, 7}, - {87, 68, 71, 44, 114, 51, 15, 186, 23}, - {47, 41, 14, 110, 182, 183, 21, 17, 194}, - {66, 45, 25, 102, 197, 189, 23, 18, 22}, - }, - { - {88, 88, 147, 150, 42, 46, 45, 196, 205}, - {43, 97, 183, 117, 85, 38, 35, 179, 61}, - {39, 53, 200, 87, 26, 21, 43, 232, 171}, - {56, 34, 51, 104, 114, 102, 29, 93, 77}, - {39, 28, 85, 171, 58, 165, 90, 98, 64}, - {34, 22, 116, 206, 23, 34, 43, 166, 73}, - {107, 54, 32, 26, 51, 1, 81, 43, 31}, - {68, 25, 106, 22, 64, 171, 36, 225, 114}, - {34, 19, 21, 102, 132, 188, 16, 76, 124}, - {62, 18, 78, 95, 85, 57, 50, 48, 51}, - }, - { - {193, 101, 35, 159, 215, 111, 89, 46, 111}, - {60, 148, 31, 172, 219, 228, 21, 18, 111}, - {112, 113, 77, 85, 179, 255, 38, 120, 114}, - {40, 42, 1, 196, 245, 209, 10, 25, 109}, - {88, 43, 29, 140, 166, 213, 37, 43, 154}, - {61, 63, 30, 155, 67, 45, 68, 1, 209}, - {100, 80, 8, 43, 154, 1, 51, 26, 71}, - {142, 78, 78, 16, 255, 128, 34, 197, 171}, - {41, 40, 5, 102, 211, 183, 4, 1, 221}, - {51, 50, 17, 168, 209, 192, 23, 25, 82}, - }, - { - {138, 31, 36, 171, 27, 166, 38, 44, 229}, - {67, 87, 58, 169, 82, 115, 26, 59, 179}, - {63, 59, 90, 180, 59, 166, 93, 73, 154}, - {40, 40, 21, 116, 143, 209, 34, 39, 175}, - {47, 15, 16, 183, 34, 223, 49, 45, 183}, - {46, 17, 33, 183, 6, 98, 15, 32, 183}, - {57, 46, 22, 24, 128, 1, 54, 17, 37}, - {65, 32, 73, 115, 28, 128, 23, 128, 205}, - {40, 3, 9, 115, 51, 192, 18, 6, 223}, - {87, 37, 9, 115, 59, 77, 64, 21, 47}, - }, - { - {104, 55, 44, 218, 9, 54, 53, 130, 226}, - {64, 90, 70, 205, 40, 41, 23, 26, 57}, - {54, 57, 112, 184, 5, 41, 38, 166, 213}, - {30, 34, 26, 133, 152, 116, 10, 32, 134}, - {39, 19, 53, 221, 26, 114, 32, 73, 255}, - {31, 9, 65, 234, 2, 15, 1, 118, 73}, - {75, 32, 12, 51, 192, 255, 160, 43, 51}, - {88, 31, 35, 67, 102, 85, 55, 186, 85}, - {56, 21, 23, 111, 59, 205, 45, 37, 192}, - {55, 38, 70, 124, 73, 102, 1, 34, 98}, - }, - { - {125, 98, 42, 88, 104, 85, 117, 175, 82}, - {95, 84, 53, 89, 128, 100, 113, 101, 45}, - {75, 79, 123, 47, 51, 128, 81, 171, 1}, - {57, 17, 5, 71, 102, 57, 53, 41, 49}, - {38, 33, 13, 121, 57, 73, 26, 1, 85}, - {41, 10, 67, 138, 77, 110, 90, 47, 114}, - {115, 21, 2, 10, 102, 255, 166, 23, 6}, - {101, 29, 16, 10, 85, 128, 101, 196, 26}, - {57, 18, 10, 102, 102, 213, 34, 20, 43}, - {117, 20, 15, 36, 163, 128, 68, 1, 26}, - }, - { - {102, 61, 71, 37, 34, 53, 31, 243, 192}, - {69, 60, 71, 38, 73, 119, 28, 222, 37}, - {68, 45, 128, 34, 1, 47, 11, 245, 171}, - {62, 17, 19, 70, 146, 85, 55, 62, 70}, - {37, 43, 37, 154, 100, 163, 85, 160, 1}, - {63, 9, 92, 136, 28, 64, 32, 201, 85}, - {75, 15, 9, 9, 64, 255, 184, 119, 16}, - {86, 6, 28, 5, 64, 255, 25, 248, 1}, - {56, 8, 17, 132, 137, 255, 55, 116, 128}, - {58, 15, 20, 82, 135, 57, 26, 121, 40}, - }, - { - {164, 50, 31, 137, 154, 133, 25, 35, 218}, - {51, 103, 44, 131, 131, 123, 31, 6, 158}, - {86, 40, 64, 135, 148, 224, 45, 183, 128}, - {22, 26, 17, 131, 240, 154, 14, 1, 209}, - {45, 16, 21, 91, 64, 222, 7, 1, 197}, - {56, 21, 39, 155, 60, 138, 23, 102, 213}, - {83, 12, 13, 54, 192, 255, 68, 47, 28}, - {85, 26, 85, 85, 128, 128, 32, 146, 171}, - {18, 11, 7, 63, 144, 171, 4, 4, 246}, - {35, 27, 10, 146, 174, 171, 12, 26, 128}, - }, - { - {190, 80, 35, 99, 180, 80, 126, 54, 45}, - {85, 126, 47, 87, 176, 51, 41, 20, 32}, - {101, 75, 128, 139, 118, 146, 116, 128, 85}, - {56, 41, 15, 176, 236, 85, 37, 9, 62}, - {71, 30, 17, 119, 118, 255, 17, 18, 138}, - {101, 38, 60, 138, 55, 70, 43, 26, 142}, - {146, 36, 19, 30, 171, 255, 97, 27, 20}, - {138, 45, 61, 62, 219, 1, 81, 188, 64}, - {32, 41, 20, 117, 151, 142, 20, 21, 163}, - {112, 19, 12, 61, 195, 128, 48, 4, 24}, - }, -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8/predfunc.go b/Godeps/_workspace/src/golang.org/x/image/vp8/predfunc.go deleted file mode 100644 index f8999582..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8/predfunc.go +++ /dev/null @@ -1,553 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8 - -// This file implements the predicition functions, as specified in chapter 12. -// -// For each macroblock (of 1x16x16 luma and 2x8x8 chroma coefficients), the -// luma values are either predicted as one large 16x16 region or 16 separate -// 4x4 regions. The chroma values are always predicted as one 8x8 region. -// -// For 4x4 regions, the target block's predicted values (Xs) are a function of -// its previously-decoded top and left border values, as well as a number of -// pixels from the top-right: -// -// a b c d e f g h -// p X X X X -// q X X X X -// r X X X X -// s X X X X -// -// The predictor modes are: -// - DC: all Xs = (b + c + d + e + p + q + r + s + 4) / 8. -// - TM: the first X = (b + p - a), the second X = (c + p - a), and so on. -// - VE: each X = the weighted average of its column's top value and that -// value's neighbors, i.e. averages of abc, bcd, cde or def. -// - HE: similar to VE except rows instead of columns, and the final row is -// an average of r, s and s. -// - RD, VR, LD, VL, HD, HU: these diagonal modes ("Right Down", "Vertical -// Right", etc) are more complicated and are described in section 12.3. -// All Xs are clipped to the range [0, 255]. -// -// For 8x8 and 16x16 regions, the target block's predicted values are a -// function of the top and left border values without the top-right overhang, -// i.e. without the 8x8 or 16x16 equivalent of f, g and h. Furthermore: -// - There are no diagonal predictor modes, only DC, TM, VE and HE. -// - The DC mode has variants for macroblocks in the top row and/or left -// column, i.e. for macroblocks with mby == 0 || mbx == 0. -// - The VE and HE modes take only the column top or row left values; they do -// not smooth that top/left value with its neighbors. - -// nPred is the number of predictor modes, not including the Top/Left versions -// of the DC predictor mode. -const nPred = 10 - -const ( - predDC = iota - predTM - predVE - predHE - predRD - predVR - predLD - predVL - predHD - predHU - predDCTop - predDCLeft - predDCTopLeft -) - -func checkTopLeftPred(mbx, mby int, p uint8) uint8 { - if p != predDC { - return p - } - if mbx == 0 { - if mby == 0 { - return predDCTopLeft - } - return predDCLeft - } - if mby == 0 { - return predDCTop - } - return predDC -} - -var predFunc4 = [...]func(*Decoder, int, int){ - predFunc4DC, - predFunc4TM, - predFunc4VE, - predFunc4HE, - predFunc4RD, - predFunc4VR, - predFunc4LD, - predFunc4VL, - predFunc4HD, - predFunc4HU, - nil, - nil, - nil, -} - -var predFunc8 = [...]func(*Decoder, int, int){ - predFunc8DC, - predFunc8TM, - predFunc8VE, - predFunc8HE, - nil, - nil, - nil, - nil, - nil, - nil, - predFunc8DCTop, - predFunc8DCLeft, - predFunc8DCTopLeft, -} - -var predFunc16 = [...]func(*Decoder, int, int){ - predFunc16DC, - predFunc16TM, - predFunc16VE, - predFunc16HE, - nil, - nil, - nil, - nil, - nil, - nil, - predFunc16DCTop, - predFunc16DCLeft, - predFunc16DCTopLeft, -} - -func predFunc4DC(z *Decoder, y, x int) { - sum := uint32(4) - for i := 0; i < 4; i++ { - sum += uint32(z.ybr[y-1][x+i]) - } - for j := 0; j < 4; j++ { - sum += uint32(z.ybr[y+j][x-1]) - } - avg := uint8(sum / 8) - for j := 0; j < 4; j++ { - for i := 0; i < 4; i++ { - z.ybr[y+j][x+i] = avg - } - } -} - -func predFunc4TM(z *Decoder, y, x int) { - delta0 := -int32(z.ybr[y-1][x-1]) - for j := 0; j < 4; j++ { - delta1 := delta0 + int32(z.ybr[y+j][x-1]) - for i := 0; i < 4; i++ { - delta2 := delta1 + int32(z.ybr[y-1][x+i]) - z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255)) - } - } -} - -func predFunc4VE(z *Decoder, y, x int) { - a := int32(z.ybr[y-1][x-1]) - b := int32(z.ybr[y-1][x+0]) - c := int32(z.ybr[y-1][x+1]) - d := int32(z.ybr[y-1][x+2]) - e := int32(z.ybr[y-1][x+3]) - f := int32(z.ybr[y-1][x+4]) - abc := uint8((a + 2*b + c + 2) / 4) - bcd := uint8((b + 2*c + d + 2) / 4) - cde := uint8((c + 2*d + e + 2) / 4) - def := uint8((d + 2*e + f + 2) / 4) - for j := 0; j < 4; j++ { - z.ybr[y+j][x+0] = abc - z.ybr[y+j][x+1] = bcd - z.ybr[y+j][x+2] = cde - z.ybr[y+j][x+3] = def - } -} - -func predFunc4HE(z *Decoder, y, x int) { - s := int32(z.ybr[y+3][x-1]) - r := int32(z.ybr[y+2][x-1]) - q := int32(z.ybr[y+1][x-1]) - p := int32(z.ybr[y+0][x-1]) - a := int32(z.ybr[y-1][x-1]) - ssr := uint8((s + 2*s + r + 2) / 4) - srq := uint8((s + 2*r + q + 2) / 4) - rqp := uint8((r + 2*q + p + 2) / 4) - apq := uint8((a + 2*p + q + 2) / 4) - for i := 0; i < 4; i++ { - z.ybr[y+0][x+i] = apq - z.ybr[y+1][x+i] = rqp - z.ybr[y+2][x+i] = srq - z.ybr[y+3][x+i] = ssr - } -} - -func predFunc4RD(z *Decoder, y, x int) { - s := int32(z.ybr[y+3][x-1]) - r := int32(z.ybr[y+2][x-1]) - q := int32(z.ybr[y+1][x-1]) - p := int32(z.ybr[y+0][x-1]) - a := int32(z.ybr[y-1][x-1]) - b := int32(z.ybr[y-1][x+0]) - c := int32(z.ybr[y-1][x+1]) - d := int32(z.ybr[y-1][x+2]) - e := int32(z.ybr[y-1][x+3]) - srq := uint8((s + 2*r + q + 2) / 4) - rqp := uint8((r + 2*q + p + 2) / 4) - qpa := uint8((q + 2*p + a + 2) / 4) - pab := uint8((p + 2*a + b + 2) / 4) - abc := uint8((a + 2*b + c + 2) / 4) - bcd := uint8((b + 2*c + d + 2) / 4) - cde := uint8((c + 2*d + e + 2) / 4) - z.ybr[y+0][x+0] = pab - z.ybr[y+0][x+1] = abc - z.ybr[y+0][x+2] = bcd - z.ybr[y+0][x+3] = cde - z.ybr[y+1][x+0] = qpa - z.ybr[y+1][x+1] = pab - z.ybr[y+1][x+2] = abc - z.ybr[y+1][x+3] = bcd - z.ybr[y+2][x+0] = rqp - z.ybr[y+2][x+1] = qpa - z.ybr[y+2][x+2] = pab - z.ybr[y+2][x+3] = abc - z.ybr[y+3][x+0] = srq - z.ybr[y+3][x+1] = rqp - z.ybr[y+3][x+2] = qpa - z.ybr[y+3][x+3] = pab -} - -func predFunc4VR(z *Decoder, y, x int) { - r := int32(z.ybr[y+2][x-1]) - q := int32(z.ybr[y+1][x-1]) - p := int32(z.ybr[y+0][x-1]) - a := int32(z.ybr[y-1][x-1]) - b := int32(z.ybr[y-1][x+0]) - c := int32(z.ybr[y-1][x+1]) - d := int32(z.ybr[y-1][x+2]) - e := int32(z.ybr[y-1][x+3]) - ab := uint8((a + b + 1) / 2) - bc := uint8((b + c + 1) / 2) - cd := uint8((c + d + 1) / 2) - de := uint8((d + e + 1) / 2) - rqp := uint8((r + 2*q + p + 2) / 4) - qpa := uint8((q + 2*p + a + 2) / 4) - pab := uint8((p + 2*a + b + 2) / 4) - abc := uint8((a + 2*b + c + 2) / 4) - bcd := uint8((b + 2*c + d + 2) / 4) - cde := uint8((c + 2*d + e + 2) / 4) - z.ybr[y+0][x+0] = ab - z.ybr[y+0][x+1] = bc - z.ybr[y+0][x+2] = cd - z.ybr[y+0][x+3] = de - z.ybr[y+1][x+0] = pab - z.ybr[y+1][x+1] = abc - z.ybr[y+1][x+2] = bcd - z.ybr[y+1][x+3] = cde - z.ybr[y+2][x+0] = qpa - z.ybr[y+2][x+1] = ab - z.ybr[y+2][x+2] = bc - z.ybr[y+2][x+3] = cd - z.ybr[y+3][x+0] = rqp - z.ybr[y+3][x+1] = pab - z.ybr[y+3][x+2] = abc - z.ybr[y+3][x+3] = bcd -} - -func predFunc4LD(z *Decoder, y, x int) { - a := int32(z.ybr[y-1][x+0]) - b := int32(z.ybr[y-1][x+1]) - c := int32(z.ybr[y-1][x+2]) - d := int32(z.ybr[y-1][x+3]) - e := int32(z.ybr[y-1][x+4]) - f := int32(z.ybr[y-1][x+5]) - g := int32(z.ybr[y-1][x+6]) - h := int32(z.ybr[y-1][x+7]) - abc := uint8((a + 2*b + c + 2) / 4) - bcd := uint8((b + 2*c + d + 2) / 4) - cde := uint8((c + 2*d + e + 2) / 4) - def := uint8((d + 2*e + f + 2) / 4) - efg := uint8((e + 2*f + g + 2) / 4) - fgh := uint8((f + 2*g + h + 2) / 4) - ghh := uint8((g + 2*h + h + 2) / 4) - z.ybr[y+0][x+0] = abc - z.ybr[y+0][x+1] = bcd - z.ybr[y+0][x+2] = cde - z.ybr[y+0][x+3] = def - z.ybr[y+1][x+0] = bcd - z.ybr[y+1][x+1] = cde - z.ybr[y+1][x+2] = def - z.ybr[y+1][x+3] = efg - z.ybr[y+2][x+0] = cde - z.ybr[y+2][x+1] = def - z.ybr[y+2][x+2] = efg - z.ybr[y+2][x+3] = fgh - z.ybr[y+3][x+0] = def - z.ybr[y+3][x+1] = efg - z.ybr[y+3][x+2] = fgh - z.ybr[y+3][x+3] = ghh -} - -func predFunc4VL(z *Decoder, y, x int) { - a := int32(z.ybr[y-1][x+0]) - b := int32(z.ybr[y-1][x+1]) - c := int32(z.ybr[y-1][x+2]) - d := int32(z.ybr[y-1][x+3]) - e := int32(z.ybr[y-1][x+4]) - f := int32(z.ybr[y-1][x+5]) - g := int32(z.ybr[y-1][x+6]) - h := int32(z.ybr[y-1][x+7]) - ab := uint8((a + b + 1) / 2) - bc := uint8((b + c + 1) / 2) - cd := uint8((c + d + 1) / 2) - de := uint8((d + e + 1) / 2) - abc := uint8((a + 2*b + c + 2) / 4) - bcd := uint8((b + 2*c + d + 2) / 4) - cde := uint8((c + 2*d + e + 2) / 4) - def := uint8((d + 2*e + f + 2) / 4) - efg := uint8((e + 2*f + g + 2) / 4) - fgh := uint8((f + 2*g + h + 2) / 4) - z.ybr[y+0][x+0] = ab - z.ybr[y+0][x+1] = bc - z.ybr[y+0][x+2] = cd - z.ybr[y+0][x+3] = de - z.ybr[y+1][x+0] = abc - z.ybr[y+1][x+1] = bcd - z.ybr[y+1][x+2] = cde - z.ybr[y+1][x+3] = def - z.ybr[y+2][x+0] = bc - z.ybr[y+2][x+1] = cd - z.ybr[y+2][x+2] = de - z.ybr[y+2][x+3] = efg - z.ybr[y+3][x+0] = bcd - z.ybr[y+3][x+1] = cde - z.ybr[y+3][x+2] = def - z.ybr[y+3][x+3] = fgh -} - -func predFunc4HD(z *Decoder, y, x int) { - s := int32(z.ybr[y+3][x-1]) - r := int32(z.ybr[y+2][x-1]) - q := int32(z.ybr[y+1][x-1]) - p := int32(z.ybr[y+0][x-1]) - a := int32(z.ybr[y-1][x-1]) - b := int32(z.ybr[y-1][x+0]) - c := int32(z.ybr[y-1][x+1]) - d := int32(z.ybr[y-1][x+2]) - sr := uint8((s + r + 1) / 2) - rq := uint8((r + q + 1) / 2) - qp := uint8((q + p + 1) / 2) - pa := uint8((p + a + 1) / 2) - srq := uint8((s + 2*r + q + 2) / 4) - rqp := uint8((r + 2*q + p + 2) / 4) - qpa := uint8((q + 2*p + a + 2) / 4) - pab := uint8((p + 2*a + b + 2) / 4) - abc := uint8((a + 2*b + c + 2) / 4) - bcd := uint8((b + 2*c + d + 2) / 4) - z.ybr[y+0][x+0] = pa - z.ybr[y+0][x+1] = pab - z.ybr[y+0][x+2] = abc - z.ybr[y+0][x+3] = bcd - z.ybr[y+1][x+0] = qp - z.ybr[y+1][x+1] = qpa - z.ybr[y+1][x+2] = pa - z.ybr[y+1][x+3] = pab - z.ybr[y+2][x+0] = rq - z.ybr[y+2][x+1] = rqp - z.ybr[y+2][x+2] = qp - z.ybr[y+2][x+3] = qpa - z.ybr[y+3][x+0] = sr - z.ybr[y+3][x+1] = srq - z.ybr[y+3][x+2] = rq - z.ybr[y+3][x+3] = rqp -} - -func predFunc4HU(z *Decoder, y, x int) { - s := int32(z.ybr[y+3][x-1]) - r := int32(z.ybr[y+2][x-1]) - q := int32(z.ybr[y+1][x-1]) - p := int32(z.ybr[y+0][x-1]) - pq := uint8((p + q + 1) / 2) - qr := uint8((q + r + 1) / 2) - rs := uint8((r + s + 1) / 2) - pqr := uint8((p + 2*q + r + 2) / 4) - qrs := uint8((q + 2*r + s + 2) / 4) - rss := uint8((r + 2*s + s + 2) / 4) - sss := uint8(s) - z.ybr[y+0][x+0] = pq - z.ybr[y+0][x+1] = pqr - z.ybr[y+0][x+2] = qr - z.ybr[y+0][x+3] = qrs - z.ybr[y+1][x+0] = qr - z.ybr[y+1][x+1] = qrs - z.ybr[y+1][x+2] = rs - z.ybr[y+1][x+3] = rss - z.ybr[y+2][x+0] = rs - z.ybr[y+2][x+1] = rss - z.ybr[y+2][x+2] = sss - z.ybr[y+2][x+3] = sss - z.ybr[y+3][x+0] = sss - z.ybr[y+3][x+1] = sss - z.ybr[y+3][x+2] = sss - z.ybr[y+3][x+3] = sss -} - -func predFunc8DC(z *Decoder, y, x int) { - sum := uint32(8) - for i := 0; i < 8; i++ { - sum += uint32(z.ybr[y-1][x+i]) - } - for j := 0; j < 8; j++ { - sum += uint32(z.ybr[y+j][x-1]) - } - avg := uint8(sum / 16) - for j := 0; j < 8; j++ { - for i := 0; i < 8; i++ { - z.ybr[y+j][x+i] = avg - } - } -} - -func predFunc8TM(z *Decoder, y, x int) { - delta0 := -int32(z.ybr[y-1][x-1]) - for j := 0; j < 8; j++ { - delta1 := delta0 + int32(z.ybr[y+j][x-1]) - for i := 0; i < 8; i++ { - delta2 := delta1 + int32(z.ybr[y-1][x+i]) - z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255)) - } - } -} - -func predFunc8VE(z *Decoder, y, x int) { - for j := 0; j < 8; j++ { - for i := 0; i < 8; i++ { - z.ybr[y+j][x+i] = z.ybr[y-1][x+i] - } - } -} - -func predFunc8HE(z *Decoder, y, x int) { - for j := 0; j < 8; j++ { - for i := 0; i < 8; i++ { - z.ybr[y+j][x+i] = z.ybr[y+j][x-1] - } - } -} - -func predFunc8DCTop(z *Decoder, y, x int) { - sum := uint32(4) - for j := 0; j < 8; j++ { - sum += uint32(z.ybr[y+j][x-1]) - } - avg := uint8(sum / 8) - for j := 0; j < 8; j++ { - for i := 0; i < 8; i++ { - z.ybr[y+j][x+i] = avg - } - } -} - -func predFunc8DCLeft(z *Decoder, y, x int) { - sum := uint32(4) - for i := 0; i < 8; i++ { - sum += uint32(z.ybr[y-1][x+i]) - } - avg := uint8(sum / 8) - for j := 0; j < 8; j++ { - for i := 0; i < 8; i++ { - z.ybr[y+j][x+i] = avg - } - } -} - -func predFunc8DCTopLeft(z *Decoder, y, x int) { - for j := 0; j < 8; j++ { - for i := 0; i < 8; i++ { - z.ybr[y+j][x+i] = 0x80 - } - } -} - -func predFunc16DC(z *Decoder, y, x int) { - sum := uint32(16) - for i := 0; i < 16; i++ { - sum += uint32(z.ybr[y-1][x+i]) - } - for j := 0; j < 16; j++ { - sum += uint32(z.ybr[y+j][x-1]) - } - avg := uint8(sum / 32) - for j := 0; j < 16; j++ { - for i := 0; i < 16; i++ { - z.ybr[y+j][x+i] = avg - } - } -} - -func predFunc16TM(z *Decoder, y, x int) { - delta0 := -int32(z.ybr[y-1][x-1]) - for j := 0; j < 16; j++ { - delta1 := delta0 + int32(z.ybr[y+j][x-1]) - for i := 0; i < 16; i++ { - delta2 := delta1 + int32(z.ybr[y-1][x+i]) - z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255)) - } - } -} - -func predFunc16VE(z *Decoder, y, x int) { - for j := 0; j < 16; j++ { - for i := 0; i < 16; i++ { - z.ybr[y+j][x+i] = z.ybr[y-1][x+i] - } - } -} - -func predFunc16HE(z *Decoder, y, x int) { - for j := 0; j < 16; j++ { - for i := 0; i < 16; i++ { - z.ybr[y+j][x+i] = z.ybr[y+j][x-1] - } - } -} - -func predFunc16DCTop(z *Decoder, y, x int) { - sum := uint32(8) - for j := 0; j < 16; j++ { - sum += uint32(z.ybr[y+j][x-1]) - } - avg := uint8(sum / 16) - for j := 0; j < 16; j++ { - for i := 0; i < 16; i++ { - z.ybr[y+j][x+i] = avg - } - } -} - -func predFunc16DCLeft(z *Decoder, y, x int) { - sum := uint32(8) - for i := 0; i < 16; i++ { - sum += uint32(z.ybr[y-1][x+i]) - } - avg := uint8(sum / 16) - for j := 0; j < 16; j++ { - for i := 0; i < 16; i++ { - z.ybr[y+j][x+i] = avg - } - } -} - -func predFunc16DCTopLeft(z *Decoder, y, x int) { - for j := 0; j < 16; j++ { - for i := 0; i < 16; i++ { - z.ybr[y+j][x+i] = 0x80 - } - } -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8/quant.go b/Godeps/_workspace/src/golang.org/x/image/vp8/quant.go deleted file mode 100644 index da436160..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8/quant.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8 - -// This file implements parsing the quantization factors. - -// quant are DC/AC quantization factors. -type quant struct { - y1 [2]uint16 - y2 [2]uint16 - uv [2]uint16 -} - -// clip clips x to the range [min, max] inclusive. -func clip(x, min, max int32) int32 { - if x < min { - return min - } - if x > max { - return max - } - return x -} - -// parseQuant parses the quantization factors, as specified in section 9.6. -func (d *Decoder) parseQuant() { - baseQ0 := d.fp.readUint(uniformProb, 7) - dqy1DC := d.fp.readOptionalInt(uniformProb, 4) - const dqy1AC = 0 - dqy2DC := d.fp.readOptionalInt(uniformProb, 4) - dqy2AC := d.fp.readOptionalInt(uniformProb, 4) - dquvDC := d.fp.readOptionalInt(uniformProb, 4) - dquvAC := d.fp.readOptionalInt(uniformProb, 4) - for i := 0; i < nSegment; i++ { - q := int32(baseQ0) - if d.segmentHeader.useSegment { - if d.segmentHeader.relativeDelta { - q += int32(d.segmentHeader.quantizer[i]) - } else { - q = int32(d.segmentHeader.quantizer[i]) - } - } - d.quant[i].y1[0] = dequantTableDC[clip(q+dqy1DC, 0, 127)] - d.quant[i].y1[1] = dequantTableAC[clip(q+dqy1AC, 0, 127)] - d.quant[i].y2[0] = dequantTableDC[clip(q+dqy2DC, 0, 127)] * 2 - d.quant[i].y2[1] = dequantTableAC[clip(q+dqy2AC, 0, 127)] * 155 / 100 - if d.quant[i].y2[1] < 8 { - d.quant[i].y2[1] = 8 - } - // The 117 is not a typo. The dequant_init function in the spec's Reference - // Decoder Source Code (http://tools.ietf.org/html/rfc6386#section-9.6 Page 145) - // says to clamp the LHS value at 132, which is equal to dequantTableDC[117]. - d.quant[i].uv[0] = dequantTableDC[clip(q+dquvDC, 0, 117)] - d.quant[i].uv[1] = dequantTableAC[clip(q+dquvAC, 0, 127)] - } -} - -// The dequantization tables are specified in section 14.1. -var ( - dequantTableDC = [128]uint16{ - 4, 5, 6, 7, 8, 9, 10, 10, - 11, 12, 13, 14, 15, 16, 17, 17, - 18, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 25, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, - 37, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, - 91, 93, 95, 96, 98, 100, 101, 102, - 104, 106, 108, 110, 112, 114, 116, 118, - 122, 124, 126, 128, 130, 132, 134, 136, - 138, 140, 143, 145, 148, 151, 154, 157, - } - dequantTableAC = [128]uint16{ - 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 60, - 62, 64, 66, 68, 70, 72, 74, 76, - 78, 80, 82, 84, 86, 88, 90, 92, - 94, 96, 98, 100, 102, 104, 106, 108, - 110, 112, 114, 116, 119, 122, 125, 128, - 131, 134, 137, 140, 143, 146, 149, 152, - 155, 158, 161, 164, 167, 170, 173, 177, - 181, 185, 189, 193, 197, 201, 205, 209, - 213, 217, 221, 225, 229, 234, 239, 245, - 249, 254, 259, 264, 269, 274, 279, 284, - } -) diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8/reconstruct.go b/Godeps/_workspace/src/golang.org/x/image/vp8/reconstruct.go deleted file mode 100644 index c1cc4b53..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8/reconstruct.go +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8 - -// This file implements decoding DCT/WHT residual coefficients and -// reconstructing YCbCr data equal to predicted values plus residuals. -// -// There are 1*16*16 + 2*8*8 + 1*4*4 coefficients per macroblock: -// - 1*16*16 luma DCT coefficients, -// - 2*8*8 chroma DCT coefficients, and -// - 1*4*4 luma WHT coefficients. -// Coefficients are read in lots of 16, and the later coefficients in each lot -// are often zero. -// -// The YCbCr data consists of 1*16*16 luma values and 2*8*8 chroma values, -// plus previously decoded values along the top and left borders. The combined -// values are laid out as a [1+16+1+8][32]uint8 so that vertically adjacent -// samples are 32 bytes apart. In detail, the layout is: -// -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// . . . . . . . a b b b b b b b b b b b b b b b b c c c c . . . . 0 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 1 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 2 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 3 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 4 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 5 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 6 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 7 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 8 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 9 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 10 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 11 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 12 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 13 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 14 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 15 -// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 16 -// . . . . . . . e f f f f f f f f . . . . . . . g h h h h h h h h 17 -// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 18 -// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 19 -// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 20 -// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 21 -// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 22 -// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 23 -// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 24 -// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 25 -// -// Y, B and R are the reconstructed luma (Y) and chroma (B, R) values. -// The Y values are predicted (either as one 16x16 region or 16 4x4 regions) -// based on the row above's Y values (some combination of {abc} or {dYC}) and -// the column left's Y values (either {ad} or {bY}). Similarly, B and R values -// are predicted on the row above and column left of their respective 8x8 -// region: {efi} for B, {ghj} for R. -// -// For uppermost macroblocks (i.e. those with mby == 0), the {abcefgh} values -// are initialized to 0x81. Otherwise, they are copied from the bottom row of -// the macroblock above. The {c} values are then duplicated from row 0 to rows -// 4, 8 and 12 of the ybr workspace. -// Similarly, for leftmost macroblocks (i.e. those with mbx == 0), the {adeigj} -// values are initialized to 0x7f. Otherwise, they are copied from the right -// column of the macroblock to the left. -// For the top-left macroblock (with mby == 0 && mbx == 0), {aeg} is 0x81. -// -// When moving from one macroblock to the next horizontally, the {adeigj} -// values can simply be copied from the workspace to itself, shifted by 8 or -// 16 columns. When moving from one macroblock to the next vertically, -// filtering can occur and hence the row values have to be copied from the -// post-filtered image instead of the pre-filtered workspace. - -const ( - bCoeffBase = 1*16*16 + 0*8*8 - rCoeffBase = 1*16*16 + 1*8*8 - whtCoeffBase = 1*16*16 + 2*8*8 -) - -const ( - ybrYX = 8 - ybrYY = 1 - ybrBX = 8 - ybrBY = 18 - ybrRX = 24 - ybrRY = 18 -) - -// prepareYBR prepares the {abcdefghij} elements of ybr. -func (d *Decoder) prepareYBR(mbx, mby int) { - if mbx == 0 { - for y := 0; y < 17; y++ { - d.ybr[y][7] = 0x81 - } - for y := 17; y < 26; y++ { - d.ybr[y][7] = 0x81 - d.ybr[y][23] = 0x81 - } - } else { - for y := 0; y < 17; y++ { - d.ybr[y][7] = d.ybr[y][7+16] - } - for y := 17; y < 26; y++ { - d.ybr[y][7] = d.ybr[y][15] - d.ybr[y][23] = d.ybr[y][31] - } - } - if mby == 0 { - for x := 7; x < 28; x++ { - d.ybr[0][x] = 0x7f - } - for x := 7; x < 16; x++ { - d.ybr[17][x] = 0x7f - } - for x := 23; x < 32; x++ { - d.ybr[17][x] = 0x7f - } - } else { - for i := 0; i < 16; i++ { - d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i] - } - for i := 0; i < 8; i++ { - d.ybr[17][8+i] = d.img.Cb[(8*mby-1)*d.img.CStride+8*mbx+i] - } - for i := 0; i < 8; i++ { - d.ybr[17][24+i] = d.img.Cr[(8*mby-1)*d.img.CStride+8*mbx+i] - } - if mbx == d.mbw-1 { - for i := 16; i < 20; i++ { - d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+15] - } - } else { - for i := 16; i < 20; i++ { - d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i] - } - } - } - for y := 4; y < 16; y += 4 { - d.ybr[y][24] = d.ybr[0][24] - d.ybr[y][25] = d.ybr[0][25] - d.ybr[y][26] = d.ybr[0][26] - d.ybr[y][27] = d.ybr[0][27] - } -} - -// btou converts a bool to a 0/1 value. -func btou(b bool) uint8 { - if b { - return 1 - } - return 0 -} - -// pack packs four 0/1 values into four bits of a uint32. -func pack(x [4]uint8, shift int) uint32 { - u := uint32(x[0])<<0 | uint32(x[1])<<1 | uint32(x[2])<<2 | uint32(x[3])<<3 - return u << uint(shift) -} - -// unpack unpacks four 0/1 values from a four-bit value. -var unpack = [16][4]uint8{ - {0, 0, 0, 0}, - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {1, 1, 0, 0}, - {0, 0, 1, 0}, - {1, 0, 1, 0}, - {0, 1, 1, 0}, - {1, 1, 1, 0}, - {0, 0, 0, 1}, - {1, 0, 0, 1}, - {0, 1, 0, 1}, - {1, 1, 0, 1}, - {0, 0, 1, 1}, - {1, 0, 1, 1}, - {0, 1, 1, 1}, - {1, 1, 1, 1}, -} - -var ( - // The mapping from 4x4 region position to band is specified in section 13.3. - bands = [17]uint8{0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0} - // Category probabilties are specified in section 13.2. - // Decoding categories 1 and 2 are done inline. - cat3456 = [4][12]uint8{ - {173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0}, - {180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0}, - {254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0}, - } - // The zigzag order is: - // 0 1 5 6 - // 2 4 7 12 - // 3 8 11 13 - // 9 10 14 15 - zigzag = [16]uint8{0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15} -) - -// parseResiduals4 parses a 4x4 region of residual coefficients, as specified -// in section 13.3, and returns a 0/1 value indicating whether there was at -// least one non-zero coefficient. -// r is the partition to read bits from. -// plane and context describe which token probability table to use. context is -// either 0, 1 or 2, and equals how many of the macroblock left and macroblock -// above have non-zero coefficients. -// quant are the DC/AC quantization factors. -// skipFirstCoeff is whether the DC coefficient has already been parsed. -// coeffBase is the base index of d.coeff to write to. -func (d *Decoder) parseResiduals4(r *partition, plane int, context uint8, quant [2]uint16, skipFirstCoeff bool, coeffBase int) uint8 { - prob, n := &d.tokenProb[plane], 0 - if skipFirstCoeff { - n = 1 - } - p := prob[bands[n]][context] - if !r.readBit(p[0]) { - return 0 - } - for n != 16 { - n++ - if !r.readBit(p[1]) { - p = prob[bands[n]][0] - continue - } - var v uint32 - if !r.readBit(p[2]) { - v = 1 - p = prob[bands[n]][1] - } else { - if !r.readBit(p[3]) { - if !r.readBit(p[4]) { - v = 2 - } else { - v = 3 + r.readUint(p[5], 1) - } - } else if !r.readBit(p[6]) { - if !r.readBit(p[7]) { - // Category 1. - v = 5 + r.readUint(159, 1) - } else { - // Category 2. - v = 7 + 2*r.readUint(165, 1) + r.readUint(145, 1) - } - } else { - // Categories 3, 4, 5 or 6. - b1 := r.readUint(p[8], 1) - b0 := r.readUint(p[9+b1], 1) - cat := 2*b1 + b0 - tab := &cat3456[cat] - v = 0 - for i := 0; tab[i] != 0; i++ { - v *= 2 - v += r.readUint(tab[i], 1) - } - v += 3 + (8 << cat) - } - p = prob[bands[n]][2] - } - z := zigzag[n-1] - c := int32(v) * int32(quant[btou(z > 0)]) - if r.readBit(uniformProb) { - c = -c - } - d.coeff[coeffBase+int(z)] = int16(c) - if n == 16 || !r.readBit(p[0]) { - return 1 - } - } - return 1 -} - -// parseResiduals parses the residuals and returns whether inner loop filtering -// should be skipped for this macroblock. -func (d *Decoder) parseResiduals(mbx, mby int) (skip bool) { - partition := &d.op[mby&(d.nOP-1)] - plane := planeY1SansY2 - quant := &d.quant[d.segment] - - // Parse the DC coefficient of each 4x4 luma region. - if d.usePredY16 { - nz := d.parseResiduals4(partition, planeY2, d.leftMB.nzY16+d.upMB[mbx].nzY16, quant.y2, false, whtCoeffBase) - d.leftMB.nzY16 = nz - d.upMB[mbx].nzY16 = nz - d.inverseWHT16() - plane = planeY1WithY2 - } - - var ( - nzDC, nzAC [4]uint8 - nzDCMask, nzACMask uint32 - coeffBase int - ) - - // Parse the luma coefficients. - lnz := unpack[d.leftMB.nzMask&0x0f] - unz := unpack[d.upMB[mbx].nzMask&0x0f] - for y := 0; y < 4; y++ { - nz := lnz[y] - for x := 0; x < 4; x++ { - nz = d.parseResiduals4(partition, plane, nz+unz[x], quant.y1, d.usePredY16, coeffBase) - unz[x] = nz - nzAC[x] = nz - nzDC[x] = btou(d.coeff[coeffBase] != 0) - coeffBase += 16 - } - lnz[y] = nz - nzDCMask |= pack(nzDC, y*4) - nzACMask |= pack(nzAC, y*4) - } - lnzMask := pack(lnz, 0) - unzMask := pack(unz, 0) - - // Parse the chroma coefficients. - lnz = unpack[d.leftMB.nzMask>>4] - unz = unpack[d.upMB[mbx].nzMask>>4] - for c := 0; c < 4; c += 2 { - for y := 0; y < 2; y++ { - nz := lnz[y+c] - for x := 0; x < 2; x++ { - nz = d.parseResiduals4(partition, planeUV, nz+unz[x+c], quant.uv, false, coeffBase) - unz[x+c] = nz - nzAC[y*2+x] = nz - nzDC[y*2+x] = btou(d.coeff[coeffBase] != 0) - coeffBase += 16 - } - lnz[y+c] = nz - } - nzDCMask |= pack(nzDC, 16+c*2) - nzACMask |= pack(nzAC, 16+c*2) - } - lnzMask |= pack(lnz, 4) - unzMask |= pack(unz, 4) - - // Save decoder state. - d.leftMB.nzMask = uint8(lnzMask) - d.upMB[mbx].nzMask = uint8(unzMask) - d.nzDCMask = nzDCMask - d.nzACMask = nzACMask - - // Section 15.1 of the spec says that "Steps 2 and 4 [of the loop filter] - // are skipped... [if] there is no DCT coefficient coded for the whole - // macroblock." - return nzDCMask == 0 && nzACMask == 0 -} - -// reconstructMacroblock applies the predictor functions and adds the inverse- -// DCT transformed residuals to recover the YCbCr data. -func (d *Decoder) reconstructMacroblock(mbx, mby int) { - if d.usePredY16 { - p := checkTopLeftPred(mbx, mby, d.predY16) - predFunc16[p](d, 1, 8) - for j := 0; j < 4; j++ { - for i := 0; i < 4; i++ { - n := 4*j + i - y := 4*j + 1 - x := 4*i + 8 - mask := uint32(1) << uint(n) - if d.nzACMask&mask != 0 { - d.inverseDCT4(y, x, 16*n) - } else if d.nzDCMask&mask != 0 { - d.inverseDCT4DCOnly(y, x, 16*n) - } - } - } - } else { - for j := 0; j < 4; j++ { - for i := 0; i < 4; i++ { - n := 4*j + i - y := 4*j + 1 - x := 4*i + 8 - predFunc4[d.predY4[j][i]](d, y, x) - mask := uint32(1) << uint(n) - if d.nzACMask&mask != 0 { - d.inverseDCT4(y, x, 16*n) - } else if d.nzDCMask&mask != 0 { - d.inverseDCT4DCOnly(y, x, 16*n) - } - } - } - } - p := checkTopLeftPred(mbx, mby, d.predC8) - predFunc8[p](d, ybrBY, ybrBX) - if d.nzACMask&0x0f0000 != 0 { - d.inverseDCT8(ybrBY, ybrBX, bCoeffBase) - } else if d.nzDCMask&0x0f0000 != 0 { - d.inverseDCT8DCOnly(ybrBY, ybrBX, bCoeffBase) - } - predFunc8[p](d, ybrRY, ybrRX) - if d.nzACMask&0xf00000 != 0 { - d.inverseDCT8(ybrRY, ybrRX, rCoeffBase) - } else if d.nzDCMask&0xf00000 != 0 { - d.inverseDCT8DCOnly(ybrRY, ybrRX, rCoeffBase) - } -} - -// reconstruct reconstructs one macroblock and returns whether inner loop -// filtering should be skipped for it. -func (d *Decoder) reconstruct(mbx, mby int) (skip bool) { - if d.segmentHeader.updateMap { - if !d.fp.readBit(d.segmentHeader.prob[0]) { - d.segment = int(d.fp.readUint(d.segmentHeader.prob[1], 1)) - } else { - d.segment = int(d.fp.readUint(d.segmentHeader.prob[2], 1)) + 2 - } - } - if d.useSkipProb { - skip = d.fp.readBit(d.skipProb) - } - // Prepare the workspace. - for i := range d.coeff { - d.coeff[i] = 0 - } - d.prepareYBR(mbx, mby) - // Parse the predictor modes. - d.usePredY16 = d.fp.readBit(145) - if d.usePredY16 { - d.parsePredModeY16(mbx) - } else { - d.parsePredModeY4(mbx) - } - d.parsePredModeC8() - // Parse the residuals. - if !skip { - skip = d.parseResiduals(mbx, mby) - } else { - if d.usePredY16 { - d.leftMB.nzY16 = 0 - d.upMB[mbx].nzY16 = 0 - } - d.leftMB.nzMask = 0 - d.upMB[mbx].nzMask = 0 - d.nzDCMask = 0 - d.nzACMask = 0 - } - // Reconstruct the YCbCr data and copy it to the image. - d.reconstructMacroblock(mbx, mby) - for i, y := (mby*d.img.YStride+mbx)*16, 0; y < 16; i, y = i+d.img.YStride, y+1 { - copy(d.img.Y[i:i+16], d.ybr[ybrYY+y][ybrYX:ybrYX+16]) - } - for i, y := (mby*d.img.CStride+mbx)*8, 0; y < 8; i, y = i+d.img.CStride, y+1 { - copy(d.img.Cb[i:i+8], d.ybr[ybrBY+y][ybrBX:ybrBX+8]) - copy(d.img.Cr[i:i+8], d.ybr[ybrRY+y][ybrRX:ybrRX+8]) - } - return skip -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8/token.go b/Godeps/_workspace/src/golang.org/x/image/vp8/token.go deleted file mode 100644 index da99cf0f..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8/token.go +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8 - -// This file contains token probabilities for decoding DCT/WHT coefficients, as -// specified in chapter 13. - -func (d *Decoder) parseTokenProb() { - for i := range d.tokenProb { - for j := range d.tokenProb[i] { - for k := range d.tokenProb[i][j] { - for l := range d.tokenProb[i][j][k] { - if d.fp.readBit(tokenProbUpdateProb[i][j][k][l]) { - d.tokenProb[i][j][k][l] = uint8(d.fp.readUint(uniformProb, 8)) - } - } - } - } - } -} - -// The plane enumeration is specified in section 13.3. -const ( - planeY1WithY2 = iota - planeY2 - planeUV - planeY1SansY2 - nPlane -) - -const ( - nBand = 8 - nContext = 3 - nProb = 11 -) - -// Token probability update probabilities are specified in section 13.4. -var tokenProbUpdateProb = [nPlane][nBand][nContext][nProb]uint8{ - { - { - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255}, - {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255}, - {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255}, - {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255}, - {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - }, - { - { - {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255}, - {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255}, - }, - { - {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255}, - {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - }, - { - { - {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255}, - {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255}, - {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255}, - }, - { - {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - }, - { - { - {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255}, - {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255}, - {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255}, - {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255}, - {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255}, - {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255}, - {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255}, - {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - { - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - }, -} - -// Default token probabilities are specified in section 13.5. -var defaultTokenProb = [nPlane][nBand][nContext][nProb]uint8{ - { - { - {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, - {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, - {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, - }, - { - {253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128}, - {189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128}, - {106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128}, - }, - { - {1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128}, - {181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128}, - {78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128}, - }, - { - {1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128}, - {184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128}, - {77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128}, - }, - { - {1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128}, - {170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128}, - {37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128}, - }, - { - {1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128}, - {207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128}, - {102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128}, - }, - { - {1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128}, - {177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128}, - {80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128}, - }, - { - {1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - {246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - {255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, - }, - }, - { - { - {198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62}, - {131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1}, - {68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128}, - }, - { - {1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128}, - {184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128}, - {81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128}, - }, - { - {1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128}, - {99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128}, - {23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128}, - }, - { - {1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128}, - {109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128}, - {44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128}, - }, - { - {1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128}, - {94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128}, - {22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128}, - }, - { - {1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128}, - {124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128}, - {35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128}, - }, - { - {1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128}, - {121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128}, - {45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128}, - }, - { - {1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128}, - {203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128}, - {137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128}, - }, - }, - { - { - {253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128}, - {175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128}, - {73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128}, - }, - { - {1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128}, - {239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128}, - {155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128}, - }, - { - {1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128}, - {201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128}, - {69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128}, - }, - { - {1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128}, - {223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128}, - {141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128}, - }, - { - {1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128}, - {190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128}, - {149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - }, - { - {1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - {247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - {240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - }, - { - {1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128}, - {213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128}, - {55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - }, - { - {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, - {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, - {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, - }, - }, - { - { - {202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255}, - {126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128}, - {61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128}, - }, - { - {1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128}, - {166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128}, - {39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128}, - }, - { - {1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128}, - {124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128}, - {24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128}, - }, - { - {1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128}, - {149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128}, - {28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128}, - }, - { - {1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128}, - {123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128}, - {20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128}, - }, - { - {1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128}, - {168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128}, - {47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128}, - }, - { - {1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128}, - {141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128}, - {42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128}, - }, - { - {1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - {244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - {238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, - }, - }, -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8l/decode.go b/Godeps/_workspace/src/golang.org/x/image/vp8l/decode.go deleted file mode 100644 index 43194870..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8l/decode.go +++ /dev/null @@ -1,603 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package vp8l implements a decoder for the VP8L lossless image format. -// -// The VP8L specification is at: -// https://developers.google.com/speed/webp/docs/riff_container -package vp8l // import "golang.org/x/image/vp8l" - -import ( - "bufio" - "errors" - "image" - "image/color" - "io" -) - -var ( - errInvalidCodeLengths = errors.New("vp8l: invalid code lengths") - errInvalidHuffmanTree = errors.New("vp8l: invalid Huffman tree") -) - -// colorCacheMultiplier is the multiplier used for the color cache hash -// function, specified in section 4.2.3. -const colorCacheMultiplier = 0x1e35a7bd - -// distanceMapTable is the look-up table for distanceMap. -var distanceMapTable = [120]uint8{ - 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, - 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, - 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, - 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, - 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, - 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, - 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, - 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, - 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, - 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, - 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, - 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70, -} - -// distanceMap maps a LZ77 backwards reference distance to a two-dimensional -// pixel offset, specified in section 4.2.2. -func distanceMap(w int32, code uint32) int32 { - if int32(code) > int32(len(distanceMapTable)) { - return int32(code) - int32(len(distanceMapTable)) - } - distCode := int32(distanceMapTable[code-1]) - yOffset := distCode >> 4 - xOffset := 8 - distCode&0xf - if d := yOffset*w + xOffset; d >= 1 { - return d - } - return 1 -} - -// decoder holds the bit-stream for a VP8L image. -type decoder struct { - r io.ByteReader - bits uint32 - nBits uint32 -} - -// read reads the next n bits from the decoder's bit-stream. -func (d *decoder) read(n uint32) (uint32, error) { - for d.nBits < n { - c, err := d.r.ReadByte() - if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return 0, err - } - d.bits |= uint32(c) << d.nBits - d.nBits += 8 - } - u := d.bits & (1<>= n - d.nBits -= n - return u, nil -} - -// decodeTransform decodes the next transform and the width of the image after -// transformation (or equivalently, before inverse transformation), specified -// in section 3. -func (d *decoder) decodeTransform(w int32, h int32) (t transform, newWidth int32, err error) { - t.oldWidth = w - t.transformType, err = d.read(2) - if err != nil { - return transform{}, 0, err - } - switch t.transformType { - case transformTypePredictor, transformTypeCrossColor: - t.bits, err = d.read(3) - if err != nil { - return transform{}, 0, err - } - t.bits += 2 - t.pix, err = d.decodePix(nTiles(w, t.bits), nTiles(h, t.bits), 0, false) - if err != nil { - return transform{}, 0, err - } - case transformTypeSubtractGreen: - // No-op. - case transformTypeColorIndexing: - nColors, err := d.read(8) - if err != nil { - return transform{}, 0, err - } - nColors++ - t.bits = 0 - switch { - case nColors <= 2: - t.bits = 3 - case nColors <= 4: - t.bits = 2 - case nColors <= 16: - t.bits = 1 - } - w = nTiles(w, t.bits) - pix, err := d.decodePix(int32(nColors), 1, 4*256, false) - if err != nil { - return transform{}, 0, err - } - for p := 4; p < len(pix); p += 4 { - pix[p+0] += pix[p-4] - pix[p+1] += pix[p-3] - pix[p+2] += pix[p-2] - pix[p+3] += pix[p-1] - } - // The spec says that "if the index is equal or larger than color_table_size, - // the argb color value should be set to 0x00000000 (transparent black)." - // We re-slice up to 256 4-byte pixels. - t.pix = pix[:4*256] - } - return t, w, nil -} - -// repeatsCodeLength is the minimum code length for repeated codes. -const repeatsCodeLength = 16 - -// These magic numbers are specified at the end of section 5.2.2. -// The 3-length arrays apply to code lengths >= repeatsCodeLength. -var ( - codeLengthCodeOrder = [19]uint8{ - 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - } - repeatBits = [3]uint8{2, 3, 7} - repeatOffsets = [3]uint8{3, 3, 11} -) - -// decodeCodeLengths decodes a Huffman tree's code lengths which are themselves -// encoded via a Huffman tree, specified in section 5.2.2. -func (d *decoder) decodeCodeLengths(dst []uint32, codeLengthCodeLengths []uint32) error { - h := hTree{} - if err := h.build(codeLengthCodeLengths); err != nil { - return err - } - - maxSymbol := len(dst) - useLength, err := d.read(1) - if err != nil { - return err - } - if useLength != 0 { - n, err := d.read(3) - if err != nil { - return err - } - n = 2 + 2*n - ms, err := d.read(n) - if err != nil { - return err - } - maxSymbol = int(ms) + 2 - if maxSymbol > len(dst) { - return errInvalidCodeLengths - } - } - - // The spec says that "if code 16 [meaning repeat] is used before - // a non-zero value has been emitted, a value of 8 is repeated." - prevCodeLength := uint32(8) - - for symbol := 0; symbol < len(dst); { - if maxSymbol == 0 { - break - } - maxSymbol-- - codeLength, err := h.next(d) - if err != nil { - return err - } - if codeLength < repeatsCodeLength { - dst[symbol] = codeLength - symbol++ - if codeLength != 0 { - prevCodeLength = codeLength - } - continue - } - - repeat, err := d.read(uint32(repeatBits[codeLength-repeatsCodeLength])) - if err != nil { - return err - } - repeat += uint32(repeatOffsets[codeLength-repeatsCodeLength]) - if symbol+int(repeat) > len(dst) { - return errInvalidCodeLengths - } - // A code length of 16 repeats the previous non-zero code. - // A code length of 17 or 18 repeats zeroes. - cl := uint32(0) - if codeLength == 16 { - cl = prevCodeLength - } - for ; repeat > 0; repeat-- { - dst[symbol] = cl - symbol++ - } - } - return nil -} - -// decodeHuffmanTree decodes a Huffman tree into h. -func (d *decoder) decodeHuffmanTree(h *hTree, alphabetSize uint32) error { - useSimple, err := d.read(1) - if err != nil { - return err - } - if useSimple != 0 { - nSymbols, err := d.read(1) - if err != nil { - return err - } - nSymbols++ - firstSymbolLengthCode, err := d.read(1) - if err != nil { - return err - } - firstSymbolLengthCode = 7*firstSymbolLengthCode + 1 - var symbols [2]uint32 - symbols[0], err = d.read(firstSymbolLengthCode) - if err != nil { - return err - } - if nSymbols == 2 { - symbols[1], err = d.read(8) - if err != nil { - return err - } - } - return h.buildSimple(nSymbols, symbols, alphabetSize) - } - - nCodes, err := d.read(4) - if err != nil { - return err - } - nCodes += 4 - if int(nCodes) > len(codeLengthCodeOrder) { - return errInvalidHuffmanTree - } - codeLengthCodeLengths := [len(codeLengthCodeOrder)]uint32{} - for i := uint32(0); i < nCodes; i++ { - codeLengthCodeLengths[codeLengthCodeOrder[i]], err = d.read(3) - if err != nil { - return err - } - } - codeLengths := make([]uint32, alphabetSize) - if err = d.decodeCodeLengths(codeLengths, codeLengthCodeLengths[:]); err != nil { - return err - } - return h.build(codeLengths) -} - -const ( - huffGreen = 0 - huffRed = 1 - huffBlue = 2 - huffAlpha = 3 - huffDistance = 4 - nHuff = 5 -) - -// hGroup is an array of 5 Huffman trees. -type hGroup [nHuff]hTree - -// decodeHuffmanGroups decodes the one or more hGroups used to decode the pixel -// data. If one hGroup is used for the entire image, then hPix and hBits will -// be zero. If more than one hGroup is used, then hPix contains the meta-image -// that maps tiles to hGroup index, and hBits contains the log-2 tile size. -func (d *decoder) decodeHuffmanGroups(w int32, h int32, topLevel bool, ccBits uint32) ( - hGroups []hGroup, hPix []byte, hBits uint32, err error) { - - maxHGroupIndex := 0 - if topLevel { - useMeta, err := d.read(1) - if err != nil { - return nil, nil, 0, err - } - if useMeta != 0 { - hBits, err = d.read(3) - if err != nil { - return nil, nil, 0, err - } - hBits += 2 - hPix, err = d.decodePix(nTiles(w, hBits), nTiles(h, hBits), 0, false) - if err != nil { - return nil, nil, 0, err - } - for p := 0; p < len(hPix); p += 4 { - i := int(hPix[p])<<8 | int(hPix[p+1]) - if maxHGroupIndex < i { - maxHGroupIndex = i - } - } - } - } - hGroups = make([]hGroup, maxHGroupIndex+1) - for i := range hGroups { - for j, alphabetSize := range alphabetSizes { - if j == 0 && ccBits > 0 { - alphabetSize += 1 << ccBits - } - if err := d.decodeHuffmanTree(&hGroups[i][j], alphabetSize); err != nil { - return nil, nil, 0, err - } - } - } - return hGroups, hPix, hBits, nil -} - -const ( - nLiteralCodes = 256 - nLengthCodes = 24 - nDistanceCodes = 40 -) - -var alphabetSizes = [nHuff]uint32{ - nLiteralCodes + nLengthCodes, - nLiteralCodes, - nLiteralCodes, - nLiteralCodes, - nDistanceCodes, -} - -// decodePix decodes pixel data, specified in section 5.2.2. -func (d *decoder) decodePix(w int32, h int32, minCap int32, topLevel bool) ([]byte, error) { - // Decode the color cache parameters. - ccBits, ccShift, ccEntries := uint32(0), uint32(0), ([]uint32)(nil) - useColorCache, err := d.read(1) - if err != nil { - return nil, err - } - if useColorCache != 0 { - ccBits, err = d.read(4) - if err != nil { - return nil, err - } - if ccBits < 1 || 11 < ccBits { - return nil, errors.New("vp8l: invalid color cache parameters") - } - ccShift = 32 - ccBits - ccEntries = make([]uint32, 1<>hBits) + (x >> hBits)) - hg = &hGroups[uint32(hPix[i])<<8|uint32(hPix[i+1])] - } - - green, err := hg[huffGreen].next(d) - if err != nil { - return nil, err - } - switch { - case green < nLiteralCodes: - // We have a literal pixel. - red, err := hg[huffRed].next(d) - if err != nil { - return nil, err - } - blue, err := hg[huffBlue].next(d) - if err != nil { - return nil, err - } - alpha, err := hg[huffAlpha].next(d) - if err != nil { - return nil, err - } - pix[p+0] = uint8(red) - pix[p+1] = uint8(green) - pix[p+2] = uint8(blue) - pix[p+3] = uint8(alpha) - p += 4 - - x++ - if x == w { - x, y = 0, y+1 - } - lookupHG = hMask != 0 && x&hMask == 0 - - case green < nLiteralCodes+nLengthCodes: - // We have a LZ77 backwards reference. - length, err := d.lz77Param(green - nLiteralCodes) - if err != nil { - return nil, err - } - distSym, err := hg[huffDistance].next(d) - if err != nil { - return nil, err - } - distCode, err := d.lz77Param(distSym) - if err != nil { - return nil, err - } - dist := distanceMap(w, distCode) - pEnd := p + 4*int(length) - q := p - 4*int(dist) - qEnd := pEnd - 4*int(dist) - if p < 0 || len(pix) < pEnd || q < 0 || len(pix) < qEnd { - return nil, errors.New("vp8l: invalid LZ77 parameters") - } - for ; p < pEnd; p, q = p+1, q+1 { - pix[p] = pix[q] - } - - x += int32(length) - for x >= w { - x, y = x-w, y+1 - } - lookupHG = hMask != 0 - - default: - // We have a color cache lookup. First, insert previous pixels - // into the cache. Note that VP8L assumes ARGB order, but the - // Go image.RGBA type is in RGBA order. - for ; cachedP < p; cachedP += 4 { - argb := uint32(pix[cachedP+0])<<16 | - uint32(pix[cachedP+1])<<8 | - uint32(pix[cachedP+2])<<0 | - uint32(pix[cachedP+3])<<24 - ccEntries[(argb*colorCacheMultiplier)>>ccShift] = argb - } - green -= nLiteralCodes + nLengthCodes - if int(green) >= len(ccEntries) { - return nil, errors.New("vp8l: invalid color cache index") - } - argb := ccEntries[green] - pix[p+0] = uint8(argb >> 16) - pix[p+1] = uint8(argb >> 8) - pix[p+2] = uint8(argb >> 0) - pix[p+3] = uint8(argb >> 24) - p += 4 - - x++ - if x == w { - x, y = 0, y+1 - } - lookupHG = hMask != 0 && x&hMask == 0 - } - } - return pix, nil -} - -// lz77Param returns the next LZ77 parameter: a length or a distance, specified -// in section 4.2.2. -func (d *decoder) lz77Param(symbol uint32) (uint32, error) { - if symbol < 4 { - return symbol + 1, nil - } - extraBits := (symbol - 2) >> 1 - offset := (2 + symbol&1) << extraBits - n, err := d.read(extraBits) - if err != nil { - return 0, err - } - return offset + n + 1, nil -} - -// decodeHeader decodes the VP8L header from r. -func decodeHeader(r io.Reader) (d *decoder, w int32, h int32, err error) { - rr, ok := r.(io.ByteReader) - if !ok { - rr = bufio.NewReader(r) - } - d = &decoder{r: rr} - magic, err := d.read(8) - if err != nil { - return nil, 0, 0, err - } - if magic != 0x2f { - return nil, 0, 0, errors.New("vp8l: invalid header") - } - width, err := d.read(14) - if err != nil { - return nil, 0, 0, err - } - width++ - height, err := d.read(14) - if err != nil { - return nil, 0, 0, err - } - height++ - _, err = d.read(1) // Read and ignore the hasAlpha hint. - if err != nil { - return nil, 0, 0, err - } - version, err := d.read(3) - if err != nil { - return nil, 0, 0, err - } - if version != 0 { - return nil, 0, 0, errors.New("vp8l: invalid version") - } - return d, int32(width), int32(height), nil -} - -// DecodeConfig decodes the color model and dimensions of a VP8L image from r. -func DecodeConfig(r io.Reader) (image.Config, error) { - _, w, h, err := decodeHeader(r) - if err != nil { - return image.Config{}, err - } - return image.Config{ - ColorModel: color.NRGBAModel, - Width: int(w), - Height: int(h), - }, nil -} - -// Decode decodes a VP8L image from r. -func Decode(r io.Reader) (image.Image, error) { - d, w, h, err := decodeHeader(r) - if err != nil { - return nil, err - } - // Decode the transforms. - var ( - nTransforms int - transforms [nTransformTypes]transform - transformsSeen [nTransformTypes]bool - originalW = w - ) - for { - more, err := d.read(1) - if err != nil { - return nil, err - } - if more == 0 { - break - } - var t transform - t, w, err = d.decodeTransform(w, h) - if err != nil { - return nil, err - } - if transformsSeen[t.transformType] { - return nil, errors.New("vp8l: repeated transform") - } - transformsSeen[t.transformType] = true - transforms[nTransforms] = t - nTransforms++ - } - // Decode the transformed pixels. - pix, err := d.decodePix(w, h, 0, true) - if err != nil { - return nil, err - } - // Apply the inverse transformations. - for i := nTransforms - 1; i >= 0; i-- { - t := &transforms[i] - pix = inverseTransforms[t.transformType](t, pix, h) - } - return &image.NRGBA{ - Pix: pix, - Stride: 4 * int(originalW), - Rect: image.Rect(0, 0, int(originalW), int(h)), - }, nil -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8l/huffman.go b/Godeps/_workspace/src/golang.org/x/image/vp8l/huffman.go deleted file mode 100644 index 36368a87..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8l/huffman.go +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8l - -import ( - "io" -) - -// reverseBits reverses the bits in a byte. -var reverseBits = [256]uint8{ - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -} - -// hNode is a node in a Huffman tree. -type hNode struct { - // symbol is the symbol held by this node. - symbol uint32 - // children, if positive, is the hTree.nodes index of the first of - // this node's two children. Zero means an uninitialized node, - // and -1 means a leaf node. - children int32 -} - -const leafNode = -1 - -// lutSize is the log-2 size of an hTree's look-up table. -const lutSize, lutMask = 7, 1<<7 - 1 - -// hTree is a Huffman tree. -type hTree struct { - // nodes are the nodes of the Huffman tree. During construction, - // len(nodes) grows from 1 up to cap(nodes) by steps of two. - // After construction, len(nodes) == cap(nodes), and both equal - // 2*theNumberOfSymbols - 1. - nodes []hNode - // lut is a look-up table for walking the nodes. The x in lut[x] is - // the next lutSize bits in the bit-stream. The low 8 bits of lut[x] - // equals 1 plus the number of bits in the next code, or 0 if the - // next code requires more than lutSize bits. The high 24 bits are: - // - the symbol, if the code requires lutSize or fewer bits, or - // - the hTree.nodes index to start the tree traversal from, if - // the next code requires more than lutSize bits. - lut [1 << lutSize]uint32 -} - -// insert inserts into the hTree a symbol whose encoding is the least -// significant codeLength bits of code. -func (h *hTree) insert(symbol uint32, code uint32, codeLength uint32) error { - if symbol > 0xffff || codeLength > 0xfe { - return errInvalidHuffmanTree - } - baseCode := uint32(0) - if codeLength > lutSize { - baseCode = uint32(reverseBits[(code>>(codeLength-lutSize))&0xff]) >> (8 - lutSize) - } else { - baseCode = uint32(reverseBits[code&0xff]) >> (8 - codeLength) - for i := 0; i < 1<<(lutSize-codeLength); i++ { - h.lut[baseCode|uint32(i)< 0; { - codeLength-- - if int(n) > len(h.nodes) { - return errInvalidHuffmanTree - } - switch h.nodes[n].children { - case leafNode: - return errInvalidHuffmanTree - case 0: - if len(h.nodes) == cap(h.nodes) { - return errInvalidHuffmanTree - } - // Create two empty child nodes. - h.nodes[n].children = int32(len(h.nodes)) - h.nodes = h.nodes[:len(h.nodes)+2] - } - n = uint32(h.nodes[n].children) + 1&(code>>codeLength) - jump-- - if jump == 0 && h.lut[baseCode] == 0 { - h.lut[baseCode] = n << 8 - } - } - - switch h.nodes[n].children { - case leafNode: - // No-op. - case 0: - // Turn the uninitialized node into a leaf. - h.nodes[n].children = leafNode - default: - return errInvalidHuffmanTree - } - h.nodes[n].symbol = symbol - return nil -} - -// codeLengthsToCodes returns the canonical Huffman codes implied by the -// sequence of code lengths. -func codeLengthsToCodes(codeLengths []uint32) ([]uint32, error) { - maxCodeLength := uint32(0) - for _, cl := range codeLengths { - if maxCodeLength < cl { - maxCodeLength = cl - } - } - const maxAllowedCodeLength = 15 - if len(codeLengths) == 0 || maxCodeLength > maxAllowedCodeLength { - return nil, errInvalidHuffmanTree - } - histogram := [maxAllowedCodeLength + 1]uint32{} - for _, cl := range codeLengths { - histogram[cl]++ - } - currCode, nextCodes := uint32(0), [maxAllowedCodeLength + 1]uint32{} - for cl := 1; cl < len(nextCodes); cl++ { - currCode = (currCode + histogram[cl-1]) << 1 - nextCodes[cl] = currCode - } - codes := make([]uint32, len(codeLengths)) - for symbol, cl := range codeLengths { - if cl > 0 { - codes[symbol] = nextCodes[cl] - nextCodes[cl]++ - } - } - return codes, nil -} - -// build builds a canonical Huffman tree from the given code lengths. -func (h *hTree) build(codeLengths []uint32) error { - // Calculate the number of symbols. - var nSymbols, lastSymbol uint32 - for symbol, cl := range codeLengths { - if cl != 0 { - nSymbols++ - lastSymbol = uint32(symbol) - } - } - if nSymbols == 0 { - return errInvalidHuffmanTree - } - h.nodes = make([]hNode, 1, 2*nSymbols-1) - // Handle the trivial case. - if nSymbols == 1 { - if len(codeLengths) <= int(lastSymbol) { - return errInvalidHuffmanTree - } - return h.insert(lastSymbol, 0, 0) - } - // Handle the non-trivial case. - codes, err := codeLengthsToCodes(codeLengths) - if err != nil { - return err - } - for symbol, cl := range codeLengths { - if cl > 0 { - if err := h.insert(uint32(symbol), codes[symbol], cl); err != nil { - return err - } - } - } - return nil -} - -// buildSimple builds a Huffman tree with 1 or 2 symbols. -func (h *hTree) buildSimple(nSymbols uint32, symbols [2]uint32, alphabetSize uint32) error { - h.nodes = make([]hNode, 1, 2*nSymbols-1) - for i := uint32(0); i < nSymbols; i++ { - if symbols[i] >= alphabetSize { - return errInvalidHuffmanTree - } - if err := h.insert(symbols[i], i, nSymbols-1); err != nil { - return err - } - } - return nil -} - -// next returns the next Huffman-encoded symbol from the bit-stream d. -func (h *hTree) next(d *decoder) (uint32, error) { - var n uint32 - // Read enough bits so that we can use the look-up table. - if d.nBits < lutSize { - c, err := d.r.ReadByte() - if err != nil { - if err == io.EOF { - // There are no more bytes of data, but we may still be able - // to read the next symbol out of the previously read bits. - goto slowPath - } - return 0, err - } - d.bits |= uint32(c) << d.nBits - d.nBits += 8 - } - // Use the look-up table. - n = h.lut[d.bits&lutMask] - if b := n & 0xff; b != 0 { - b-- - d.bits >>= b - d.nBits -= b - return n >> 8, nil - } - n >>= 8 - d.bits >>= lutSize - d.nBits -= lutSize - -slowPath: - for h.nodes[n].children != leafNode { - if d.nBits == 0 { - c, err := d.r.ReadByte() - if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return 0, err - } - d.bits = uint32(c) - d.nBits = 8 - } - n = uint32(h.nodes[n].children) + 1&d.bits - d.bits >>= 1 - d.nBits-- - } - return h.nodes[n].symbol, nil -} diff --git a/Godeps/_workspace/src/golang.org/x/image/vp8l/transform.go b/Godeps/_workspace/src/golang.org/x/image/vp8l/transform.go deleted file mode 100644 index 06543dac..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/vp8l/transform.go +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package vp8l - -// This file deals with image transforms, specified in section 3. - -// nTiles returns the number of tiles needed to cover size pixels, where each -// tile's side is 1<> bits -} - -const ( - transformTypePredictor = 0 - transformTypeCrossColor = 1 - transformTypeSubtractGreen = 2 - transformTypeColorIndexing = 3 - nTransformTypes = 4 -) - -// transform holds the parameters for an invertible transform. -type transform struct { - // transformType is the type of the transform. - transformType uint32 - // oldWidth is the width of the image before transformation (or - // equivalently, after inverse transformation). The color-indexing - // transform can reduce the width. For example, a 50-pixel-wide - // image that only needs 4 bits (half a byte) per color index can - // be transformed into a 25-pixel-wide image. - oldWidth int32 - // bits is the log-2 size of the transform's tiles, for the predictor - // and cross-color transforms. 8>>bits is the number of bits per - // color index, for the color-index transform. - bits uint32 - // pix is the tile values, for the predictor and cross-color - // transforms, and the color palette, for the color-index transform. - pix []byte -} - -var inverseTransforms = [nTransformTypes]func(*transform, []byte, int32) []byte{ - transformTypePredictor: inversePredictor, - transformTypeCrossColor: inverseCrossColor, - transformTypeSubtractGreen: inverseSubtractGreen, - transformTypeColorIndexing: inverseColorIndexing, -} - -func inversePredictor(t *transform, pix []byte, h int32) []byte { - if t.oldWidth == 0 || h == 0 { - return pix - } - // The first pixel's predictor is mode 0 (opaque black). - pix[3] += 0xff - p, mask := int32(4), int32(1)<> t.bits) * tilesPerRow - predictorMode := t.pix[q+1] & 0x0f - q += 4 - for x := int32(1); x < t.oldWidth; x++ { - if x&mask == 0 { - predictorMode = t.pix[q+1] & 0x0f - q += 4 - } - switch predictorMode { - case 0: // Opaque black. - pix[p+3] += 0xff - - case 1: // L. - pix[p+0] += pix[p-4] - pix[p+1] += pix[p-3] - pix[p+2] += pix[p-2] - pix[p+3] += pix[p-1] - - case 2: // T. - pix[p+0] += pix[top+0] - pix[p+1] += pix[top+1] - pix[p+2] += pix[top+2] - pix[p+3] += pix[top+3] - - case 3: // TR. - pix[p+0] += pix[top+4] - pix[p+1] += pix[top+5] - pix[p+2] += pix[top+6] - pix[p+3] += pix[top+7] - - case 4: // TL. - pix[p+0] += pix[top-4] - pix[p+1] += pix[top-3] - pix[p+2] += pix[top-2] - pix[p+3] += pix[top-1] - - case 5: // Average2(Average2(L, TR), T). - pix[p+0] += avg2(avg2(pix[p-4], pix[top+4]), pix[top+0]) - pix[p+1] += avg2(avg2(pix[p-3], pix[top+5]), pix[top+1]) - pix[p+2] += avg2(avg2(pix[p-2], pix[top+6]), pix[top+2]) - pix[p+3] += avg2(avg2(pix[p-1], pix[top+7]), pix[top+3]) - - case 6: // Average2(L, TL). - pix[p+0] += avg2(pix[p-4], pix[top-4]) - pix[p+1] += avg2(pix[p-3], pix[top-3]) - pix[p+2] += avg2(pix[p-2], pix[top-2]) - pix[p+3] += avg2(pix[p-1], pix[top-1]) - - case 7: // Average2(L, T). - pix[p+0] += avg2(pix[p-4], pix[top+0]) - pix[p+1] += avg2(pix[p-3], pix[top+1]) - pix[p+2] += avg2(pix[p-2], pix[top+2]) - pix[p+3] += avg2(pix[p-1], pix[top+3]) - - case 8: // Average2(TL, T). - pix[p+0] += avg2(pix[top-4], pix[top+0]) - pix[p+1] += avg2(pix[top-3], pix[top+1]) - pix[p+2] += avg2(pix[top-2], pix[top+2]) - pix[p+3] += avg2(pix[top-1], pix[top+3]) - - case 9: // Average2(T, TR). - pix[p+0] += avg2(pix[top+0], pix[top+4]) - pix[p+1] += avg2(pix[top+1], pix[top+5]) - pix[p+2] += avg2(pix[top+2], pix[top+6]) - pix[p+3] += avg2(pix[top+3], pix[top+7]) - - case 10: // Average2(Average2(L, TL), Average2(T, TR)). - pix[p+0] += avg2(avg2(pix[p-4], pix[top-4]), avg2(pix[top+0], pix[top+4])) - pix[p+1] += avg2(avg2(pix[p-3], pix[top-3]), avg2(pix[top+1], pix[top+5])) - pix[p+2] += avg2(avg2(pix[p-2], pix[top-2]), avg2(pix[top+2], pix[top+6])) - pix[p+3] += avg2(avg2(pix[p-1], pix[top-1]), avg2(pix[top+3], pix[top+7])) - - case 11: // Select(L, T, TL). - l0 := int32(pix[p-4]) - l1 := int32(pix[p-3]) - l2 := int32(pix[p-2]) - l3 := int32(pix[p-1]) - c0 := int32(pix[top-4]) - c1 := int32(pix[top-3]) - c2 := int32(pix[top-2]) - c3 := int32(pix[top-1]) - t0 := int32(pix[top+0]) - t1 := int32(pix[top+1]) - t2 := int32(pix[top+2]) - t3 := int32(pix[top+3]) - l := abs(c0-t0) + abs(c1-t1) + abs(c2-t2) + abs(c3-t3) - t := abs(c0-l0) + abs(c1-l1) + abs(c2-l2) + abs(c3-l3) - if l < t { - pix[p+0] += uint8(l0) - pix[p+1] += uint8(l1) - pix[p+2] += uint8(l2) - pix[p+3] += uint8(l3) - } else { - pix[p+0] += uint8(t0) - pix[p+1] += uint8(t1) - pix[p+2] += uint8(t2) - pix[p+3] += uint8(t3) - } - - case 12: // ClampAddSubtractFull(L, T, TL). - pix[p+0] += clampAddSubtractFull(pix[p-4], pix[top+0], pix[top-4]) - pix[p+1] += clampAddSubtractFull(pix[p-3], pix[top+1], pix[top-3]) - pix[p+2] += clampAddSubtractFull(pix[p-2], pix[top+2], pix[top-2]) - pix[p+3] += clampAddSubtractFull(pix[p-1], pix[top+3], pix[top-1]) - - case 13: // ClampAddSubtractHalf(Average2(L, T), TL). - pix[p+0] += clampAddSubtractHalf(avg2(pix[p-4], pix[top+0]), pix[top-4]) - pix[p+1] += clampAddSubtractHalf(avg2(pix[p-3], pix[top+1]), pix[top-3]) - pix[p+2] += clampAddSubtractHalf(avg2(pix[p-2], pix[top+2]), pix[top-2]) - pix[p+3] += clampAddSubtractHalf(avg2(pix[p-1], pix[top+3]), pix[top-1]) - } - p, top = p+4, top+4 - } - } - return pix -} - -func inverseCrossColor(t *transform, pix []byte, h int32) []byte { - var greenToRed, greenToBlue, redToBlue int32 - p, mask, tilesPerRow := int32(0), int32(1)<> t.bits) * tilesPerRow - for x := int32(0); x < t.oldWidth; x++ { - if x&mask == 0 { - redToBlue = int32(int8(t.pix[q+0])) - greenToBlue = int32(int8(t.pix[q+1])) - greenToRed = int32(int8(t.pix[q+2])) - q += 4 - } - red := pix[p+0] - green := pix[p+1] - blue := pix[p+2] - red += uint8(uint32(greenToRed*int32(int8(green))) >> 5) - blue += uint8(uint32(greenToBlue*int32(int8(green))) >> 5) - blue += uint8(uint32(redToBlue*int32(int8(red))) >> 5) - pix[p+0] = red - pix[p+2] = blue - p += 4 - } - } - return pix -} - -func inverseSubtractGreen(t *transform, pix []byte, h int32) []byte { - for p := 0; p < len(pix); p += 4 { - green := pix[p+1] - pix[p+0] += green - pix[p+2] += green - } - return pix -} - -func inverseColorIndexing(t *transform, pix []byte, h int32) []byte { - if t.bits == 0 { - for p := 0; p < len(pix); p += 4 { - i := 4 * uint32(pix[p+1]) - pix[p+0] = t.pix[i+0] - pix[p+1] = t.pix[i+1] - pix[p+2] = t.pix[i+2] - pix[p+3] = t.pix[i+3] - } - return pix - } - - vMask, xMask, bitsPerPixel := uint32(0), int32(0), uint32(8>>t.bits) - switch t.bits { - case 1: - vMask, xMask = 0x0f, 0x01 - case 2: - vMask, xMask = 0x03, 0x03 - case 3: - vMask, xMask = 0x01, 0x07 - } - - d, p, v, dst := 0, 0, uint32(0), make([]byte, 4*t.oldWidth*h) - for y := int32(0); y < h; y++ { - for x := int32(0); x < t.oldWidth; x++ { - if x&xMask == 0 { - v = uint32(pix[p+1]) - p += 4 - } - - i := 4 * (v & vMask) - dst[d+0] = t.pix[i+0] - dst[d+1] = t.pix[i+1] - dst[d+2] = t.pix[i+2] - dst[d+3] = t.pix[i+3] - d += 4 - - v >>= bitsPerPixel - } - } - return dst -} - -func abs(x int32) int32 { - if x < 0 { - return -x - } - return x -} - -func avg2(a, b uint8) uint8 { - return uint8((int32(a) + int32(b)) / 2) -} - -func clampAddSubtractFull(a, b, c uint8) uint8 { - x := int32(a) + int32(b) - int32(c) - if x < 0 { - return 0 - } - if x > 255 { - return 255 - } - return uint8(x) -} - -func clampAddSubtractHalf(a, b uint8) uint8 { - x := int32(a) + (int32(a)-int32(b))/2 - if x < 0 { - return 0 - } - if x > 255 { - return 255 - } - return uint8(x) -} diff --git a/Godeps/_workspace/src/golang.org/x/image/webp/decode.go b/Godeps/_workspace/src/golang.org/x/image/webp/decode.go deleted file mode 100644 index 60fb5560..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/webp/decode.go +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package webp implements a decoder for WEBP images. -// -// WEBP is defined at: -// https://developers.google.com/speed/webp/docs/riff_container -package webp // import "golang.org/x/image/webp" - -import ( - "bytes" - "errors" - "image" - "image/color" - "io" - - "golang.org/x/image/riff" - "golang.org/x/image/vp8" - "golang.org/x/image/vp8l" - "golang.org/x/image/webp/nycbcra" -) - -var errInvalidFormat = errors.New("webp: invalid format") - -var ( - fccALPH = riff.FourCC{'A', 'L', 'P', 'H'} - fccVP8 = riff.FourCC{'V', 'P', '8', ' '} - fccVP8L = riff.FourCC{'V', 'P', '8', 'L'} - fccVP8X = riff.FourCC{'V', 'P', '8', 'X'} - fccWEBP = riff.FourCC{'W', 'E', 'B', 'P'} -) - -func decode(r io.Reader, configOnly bool) (image.Image, image.Config, error) { - formType, riffReader, err := riff.NewReader(r) - if err != nil { - return nil, image.Config{}, err - } - if formType != fccWEBP { - return nil, image.Config{}, errInvalidFormat - } - - var ( - alpha []byte - alphaStride int - wantAlpha bool - widthMinusOne uint32 - heightMinusOne uint32 - buf [10]byte - ) - for { - chunkID, chunkLen, chunkData, err := riffReader.Next() - if err == io.EOF { - err = errInvalidFormat - } - if err != nil { - return nil, image.Config{}, err - } - - switch chunkID { - case fccALPH: - if !wantAlpha { - return nil, image.Config{}, errInvalidFormat - } - wantAlpha = false - // Read the Pre-processing | Filter | Compression byte. - if _, err := io.ReadFull(chunkData, buf[:1]); err != nil { - if err == io.EOF { - err = errInvalidFormat - } - return nil, image.Config{}, err - } - alpha, alphaStride, err = readAlpha(chunkData, widthMinusOne, heightMinusOne, buf[0]&0x03) - if err != nil { - return nil, image.Config{}, err - } - unfilterAlpha(alpha, alphaStride, (buf[0]>>2)&0x03) - - case fccVP8: - if wantAlpha || int32(chunkLen) < 0 { - return nil, image.Config{}, errInvalidFormat - } - d := vp8.NewDecoder() - d.Init(chunkData, int(chunkLen)) - fh, err := d.DecodeFrameHeader() - if err != nil { - return nil, image.Config{}, err - } - if configOnly { - return nil, image.Config{ - ColorModel: color.YCbCrModel, - Width: fh.Width, - Height: fh.Height, - }, nil - } - m, err := d.DecodeFrame() - if err != nil { - return nil, image.Config{}, err - } - if alpha != nil { - return &nycbcra.Image{ - YCbCr: *m, - A: alpha, - AStride: alphaStride, - }, image.Config{}, nil - } - return m, image.Config{}, nil - - case fccVP8L: - if wantAlpha || alpha != nil { - return nil, image.Config{}, errInvalidFormat - } - if configOnly { - c, err := vp8l.DecodeConfig(chunkData) - return nil, c, err - } - m, err := vp8l.Decode(chunkData) - return m, image.Config{}, err - - case fccVP8X: - if chunkLen != 10 { - return nil, image.Config{}, errInvalidFormat - } - if _, err := io.ReadFull(chunkData, buf[:10]); err != nil { - return nil, image.Config{}, err - } - const ( - animationBit = 1 << 1 - xmpMetadataBit = 1 << 2 - exifMetadataBit = 1 << 3 - alphaBit = 1 << 4 - iccProfileBit = 1 << 5 - ) - if buf[0] != alphaBit { - return nil, image.Config{}, errors.New("webp: non-Alpha VP8X is not implemented") - } - widthMinusOne = uint32(buf[4]) | uint32(buf[5])<<8 | uint32(buf[6])<<16 - heightMinusOne = uint32(buf[7]) | uint32(buf[8])<<8 | uint32(buf[9])<<16 - if configOnly { - return nil, image.Config{ - ColorModel: nycbcra.ColorModel, - Width: int(widthMinusOne) + 1, - Height: int(heightMinusOne) + 1, - }, nil - } - wantAlpha = true - - default: - return nil, image.Config{}, errInvalidFormat - } - } -} - -func readAlpha(chunkData io.Reader, widthMinusOne, heightMinusOne uint32, compression byte) ( - alpha []byte, alphaStride int, err error) { - - switch compression { - case 0: - w := int(widthMinusOne) + 1 - h := int(heightMinusOne) + 1 - alpha = make([]byte, w*h) - if _, err := io.ReadFull(chunkData, alpha); err != nil { - return nil, 0, err - } - return alpha, w, nil - - case 1: - // Read the VP8L-compressed alpha values. First, synthesize a 5-byte VP8L header: - // a 1-byte magic number, a 14-bit widthMinusOne, a 14-bit heightMinusOne, - // a 1-bit (ignored, zero) alphaIsUsed and a 3-bit (zero) version. - // TODO(nigeltao): be more efficient than decoding an *image.NRGBA just to - // extract the green values to a separately allocated []byte. Fixing this - // will require changes to the vp8l package's API. - if widthMinusOne > 0x3fff || heightMinusOne > 0x3fff { - return nil, 0, errors.New("webp: invalid format") - } - alphaImage, err := vp8l.Decode(io.MultiReader( - bytes.NewReader([]byte{ - 0x2f, // VP8L magic number. - uint8(widthMinusOne), - uint8(widthMinusOne>>8) | uint8(heightMinusOne<<6), - uint8(heightMinusOne >> 2), - uint8(heightMinusOne >> 10), - }), - chunkData, - )) - if err != nil { - return nil, 0, err - } - // The green values of the inner NRGBA image are the alpha values of the - // outer NYCbCrA image. - pix := alphaImage.(*image.NRGBA).Pix - alpha = make([]byte, len(pix)/4) - for i := range alpha { - alpha[i] = pix[4*i+1] - } - return alpha, int(widthMinusOne) + 1, nil - } - return nil, 0, errInvalidFormat -} - -func unfilterAlpha(alpha []byte, alphaStride int, filter byte) { - if len(alpha) == 0 || alphaStride == 0 { - return - } - switch filter { - case 1: // Horizontal filter. - for i := 1; i < alphaStride; i++ { - alpha[i] += alpha[i-1] - } - for i := alphaStride; i < len(alpha); i += alphaStride { - // The first column is equivalent to the vertical filter. - alpha[i] += alpha[i-alphaStride] - - for j := 1; j < alphaStride; j++ { - alpha[i+j] += alpha[i+j-1] - } - } - - case 2: // Vertical filter. - // The first row is equivalent to the horizontal filter. - for i := 1; i < alphaStride; i++ { - alpha[i] += alpha[i-1] - } - - for i := alphaStride; i < len(alpha); i++ { - alpha[i] += alpha[i-alphaStride] - } - - case 3: // Gradient filter. - // The first row is equivalent to the horizontal filter. - for i := 1; i < alphaStride; i++ { - alpha[i] += alpha[i-1] - } - - for i := alphaStride; i < len(alpha); i += alphaStride { - // The first column is equivalent to the vertical filter. - alpha[i] += alpha[i-alphaStride] - - // The interior is predicted on the three top/left pixels. - for j := 1; j < alphaStride; j++ { - c := int(alpha[i+j-alphaStride-1]) - b := int(alpha[i+j-alphaStride]) - a := int(alpha[i+j-1]) - x := a + b - c - if x < 0 { - x = 0 - } else if x > 255 { - x = 255 - } - alpha[i+j] += uint8(x) - } - } - } -} - -// Decode reads a WEBP image from r and returns it as an image.Image. -func Decode(r io.Reader) (image.Image, error) { - m, _, err := decode(r, false) - if err != nil { - return nil, err - } - return m, err -} - -// DecodeConfig returns the color model and dimensions of a WEBP image without -// decoding the entire image. -func DecodeConfig(r io.Reader) (image.Config, error) { - _, c, err := decode(r, true) - return c, err -} - -func init() { - image.RegisterFormat("webp", "RIFF????WEBPVP8", Decode, DecodeConfig) -} diff --git a/Godeps/_workspace/src/golang.org/x/image/webp/decode_test.go b/Godeps/_workspace/src/golang.org/x/image/webp/decode_test.go deleted file mode 100644 index 4b69f90d..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/webp/decode_test.go +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package webp - -import ( - "bytes" - "fmt" - "image" - "image/png" - "io/ioutil" - "os" - "strings" - "testing" - - "golang.org/x/image/webp/nycbcra" -) - -// hex is like fmt.Sprintf("% x", x) but also inserts dots every 16 bytes, to -// delineate VP8 macroblock boundaries. -func hex(x []byte) string { - buf := new(bytes.Buffer) - for len(x) > 0 { - n := len(x) - if n > 16 { - n = 16 - } - fmt.Fprintf(buf, " . % x", x[:n]) - x = x[n:] - } - return buf.String() -} - -func testDecodeLossy(t *testing.T, tc string, withAlpha bool) { - webpFilename := "../testdata/" + tc + ".lossy.webp" - pngFilename := webpFilename + ".ycbcr.png" - if withAlpha { - webpFilename = "../testdata/" + tc + ".lossy-with-alpha.webp" - pngFilename = webpFilename + ".nycbcra.png" - } - - f0, err := os.Open(webpFilename) - if err != nil { - t.Errorf("%s: Open WEBP: %v", tc, err) - return - } - defer f0.Close() - img0, err := Decode(f0) - if err != nil { - t.Errorf("%s: Decode WEBP: %v", tc, err) - return - } - - var ( - m0 *image.YCbCr - a0 *nycbcra.Image - ok bool - ) - if withAlpha { - a0, ok = img0.(*nycbcra.Image) - if ok { - m0 = &a0.YCbCr - } - } else { - m0, ok = img0.(*image.YCbCr) - } - if !ok || m0.SubsampleRatio != image.YCbCrSubsampleRatio420 { - t.Errorf("%s: decoded WEBP image is not a 4:2:0 YCbCr or 4:2:0 NYCbCrA", tc) - return - } - // w2 and h2 are the half-width and half-height, rounded up. - w, h := m0.Bounds().Dx(), m0.Bounds().Dy() - w2, h2 := int((w+1)/2), int((h+1)/2) - - f1, err := os.Open(pngFilename) - if err != nil { - t.Errorf("%s: Open PNG: %v", tc, err) - return - } - defer f1.Close() - img1, err := png.Decode(f1) - if err != nil { - t.Errorf("%s: Open PNG: %v", tc, err) - return - } - - // The split-into-YCbCr-planes golden image is a 2*w2 wide and h+h2 high - // (or 2*h+h2 high, if with Alpha) gray image arranged in IMC4 format: - // YYYY - // YYYY - // BBRR - // AAAA - // See http://www.fourcc.org/yuv.php#IMC4 - pngW, pngH := 2*w2, h+h2 - if withAlpha { - pngH += h - } - if got, want := img1.Bounds(), image.Rect(0, 0, pngW, pngH); got != want { - t.Errorf("%s: bounds0: got %v, want %v", tc, got, want) - return - } - m1, ok := img1.(*image.Gray) - if !ok { - t.Errorf("%s: decoded PNG image is not a Gray", tc) - return - } - - type plane struct { - name string - m0Pix []uint8 - m0Stride int - m1Rect image.Rectangle - } - planes := []plane{ - {"Y", m0.Y, m0.YStride, image.Rect(0, 0, w, h)}, - {"Cb", m0.Cb, m0.CStride, image.Rect(0*w2, h, 1*w2, h+h2)}, - {"Cr", m0.Cr, m0.CStride, image.Rect(1*w2, h, 2*w2, h+h2)}, - } - if withAlpha { - planes = append(planes, plane{ - "A", a0.A, a0.AStride, image.Rect(0, h+h2, w, 2*h+h2), - }) - } - - for _, plane := range planes { - dx := plane.m1Rect.Dx() - nDiff, diff := 0, make([]byte, dx) - for j, y := 0, plane.m1Rect.Min.Y; y < plane.m1Rect.Max.Y; j, y = j+1, y+1 { - got := plane.m0Pix[j*plane.m0Stride:][:dx] - want := m1.Pix[y*m1.Stride+plane.m1Rect.Min.X:][:dx] - if bytes.Equal(got, want) { - continue - } - nDiff++ - if nDiff > 10 { - t.Errorf("%s: %s plane: more rows differ", tc, plane.name) - break - } - for i := range got { - diff[i] = got[i] - want[i] - } - t.Errorf("%s: %s plane: m0 row %d, m1 row %d\ngot %s\nwant%s\ndiff%s", - tc, plane.name, j, y, hex(got), hex(want), hex(diff)) - } - } -} - -func TestDecodeVP8(t *testing.T) { - testCases := []string{ - "blue-purple-pink", - "blue-purple-pink-large.no-filter", - "blue-purple-pink-large.simple-filter", - "blue-purple-pink-large.normal-filter", - "video-001", - "yellow_rose", - } - - for _, tc := range testCases { - testDecodeLossy(t, tc, false) - } -} - -func TestDecodeVP8XAlpha(t *testing.T) { - testCases := []string{ - "yellow_rose", - } - - for _, tc := range testCases { - testDecodeLossy(t, tc, true) - } -} - -func TestDecodeVP8L(t *testing.T) { - testCases := []string{ - "blue-purple-pink", - "blue-purple-pink-large", - "gopher-doc.1bpp", - "gopher-doc.2bpp", - "gopher-doc.4bpp", - "gopher-doc.8bpp", - "tux", - "yellow_rose", - } - -loop: - for _, tc := range testCases { - f0, err := os.Open("../testdata/" + tc + ".lossless.webp") - if err != nil { - t.Errorf("%s: Open WEBP: %v", tc, err) - continue - } - defer f0.Close() - img0, err := Decode(f0) - if err != nil { - t.Errorf("%s: Decode WEBP: %v", tc, err) - continue - } - m0, ok := img0.(*image.NRGBA) - if !ok { - t.Errorf("%s: WEBP image is %T, want *image.NRGBA", tc, img0) - continue - } - - f1, err := os.Open("../testdata/" + tc + ".png") - if err != nil { - t.Errorf("%s: Open PNG: %v", tc, err) - continue - } - defer f1.Close() - img1, err := png.Decode(f1) - if err != nil { - t.Errorf("%s: Decode PNG: %v", tc, err) - continue - } - m1, ok := img1.(*image.NRGBA) - if !ok { - rgba1, ok := img1.(*image.RGBA) - if !ok { - t.Fatalf("%s: PNG image is %T, want *image.NRGBA", tc, img1) - continue - } - if !rgba1.Opaque() { - t.Fatalf("%s: PNG image is non-opaque *image.RGBA, want *image.NRGBA", tc) - continue - } - // The image is fully opaque, so we can re-interpret the RGBA pixels - // as NRGBA pixels. - m1 = &image.NRGBA{ - Pix: rgba1.Pix, - Stride: rgba1.Stride, - Rect: rgba1.Rect, - } - } - - b0, b1 := m0.Bounds(), m1.Bounds() - if b0 != b1 { - t.Errorf("%s: bounds: got %v, want %v", tc, b0, b1) - continue - } - for i := range m0.Pix { - if m0.Pix[i] != m1.Pix[i] { - y := i / m0.Stride - x := (i - y*m0.Stride) / 4 - i = 4 * (y*m0.Stride + x) - t.Errorf("%s: at (%d, %d):\ngot %02x %02x %02x %02x\nwant %02x %02x %02x %02x", - tc, x, y, - m0.Pix[i+0], m0.Pix[i+1], m0.Pix[i+2], m0.Pix[i+3], - m1.Pix[i+0], m1.Pix[i+1], m1.Pix[i+2], m1.Pix[i+3], - ) - continue loop - } - } - } -} - -// TestDecodePartitionTooLarge tests that decoding a malformed WEBP image -// doesn't try to allocate an unreasonable amount of memory. This WEBP image -// claims a RIFF chunk length of 0x12345678 bytes (291 MiB) compressed, -// independent of the actual image size (0 pixels wide * 0 pixels high). -// -// This is based on golang.org/issue/10790. -func TestDecodePartitionTooLarge(t *testing.T) { - data := "RIFF\xff\xff\xff\x7fWEBPVP8 " + - "\x78\x56\x34\x12" + // RIFF chunk length. - "\xbd\x01\x00\x14\x00\x00\xb2\x34\x0a\x9d\x01\x2a\x96\x00\x67\x00" - _, err := Decode(strings.NewReader(data)) - if err == nil { - t.Fatal("got nil error, want non-nil") - } - if got, want := err.Error(), "too much data"; !strings.Contains(got, want) { - t.Fatalf("got error %q, want something containing %q", got, want) - } -} - -func benchmarkDecode(b *testing.B, filename string) { - data, err := ioutil.ReadFile("../testdata/blue-purple-pink-large." + filename + ".webp") - if err != nil { - b.Fatal(err) - } - s := string(data) - cfg, err := DecodeConfig(strings.NewReader(s)) - if err != nil { - b.Fatal(err) - } - b.SetBytes(int64(cfg.Width * cfg.Height * 4)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Decode(strings.NewReader(s)) - } -} - -func BenchmarkDecodeVP8NoFilter(b *testing.B) { benchmarkDecode(b, "no-filter.lossy") } -func BenchmarkDecodeVP8SimpleFilter(b *testing.B) { benchmarkDecode(b, "simple-filter.lossy") } -func BenchmarkDecodeVP8NormalFilter(b *testing.B) { benchmarkDecode(b, "normal-filter.lossy") } -func BenchmarkDecodeVP8L(b *testing.B) { benchmarkDecode(b, "lossless") } diff --git a/Godeps/_workspace/src/golang.org/x/image/webp/nycbcra/nycbcra.go b/Godeps/_workspace/src/golang.org/x/image/webp/nycbcra/nycbcra.go deleted file mode 100644 index 2e1fe05f..00000000 --- a/Godeps/_workspace/src/golang.org/x/image/webp/nycbcra/nycbcra.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package nycbcra provides non-alpha-premultiplied Y'CbCr-with-alpha image and -// color types. -package nycbcra // import "golang.org/x/image/webp/nycbcra" - -import ( - "image" - "image/color" -) - -// TODO: move this to the standard image and image/color packages, so that the -// image/draw package can have fast-path code. Moving would rename: -// nycbcra.Color to color.NYCbCrA -// nycbcra.ColorModel to color.NYCbCrAModel -// nycbcra.Image to image.NYCbCrA - -// Color represents a non-alpha-premultiplied Y'CbCr-with-alpha color, having -// 8 bits each for one luma, two chroma and one alpha component. -type Color struct { - color.YCbCr - A uint8 -} - -func (c Color) RGBA() (r, g, b, a uint32) { - r8, g8, b8 := color.YCbCrToRGB(c.Y, c.Cb, c.Cr) - a = uint32(c.A) * 0x101 - r = uint32(r8) * 0x101 * a / 0xffff - g = uint32(g8) * 0x101 * a / 0xffff - b = uint32(b8) * 0x101 * a / 0xffff - return -} - -// ColorModel is the Model for non-alpha-premultiplied Y'CbCr-with-alpha colors. -var ColorModel color.Model = color.ModelFunc(nYCbCrAModel) - -func nYCbCrAModel(c color.Color) color.Color { - switch c := c.(type) { - case Color: - return c - case color.YCbCr: - return Color{c, 0xff} - } - r, g, b, a := c.RGBA() - - // Convert from alpha-premultiplied to non-alpha-premultiplied. - if a != 0 { - r = (r * 0xffff) / a - g = (g * 0xffff) / a - b = (b * 0xffff) / a - } - - y, u, v := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8)) - return Color{color.YCbCr{Y: y, Cb: u, Cr: v}, uint8(a >> 8)} -} - -// Image is an in-memory image of non-alpha-premultiplied Y'CbCr-with-alpha -// colors. A and AStride are analogous to the Y and YStride fields of the -// embedded YCbCr. -type Image struct { - image.YCbCr - A []uint8 - AStride int -} - -func (p *Image) ColorModel() color.Model { - return ColorModel -} - -func (p *Image) At(x, y int) color.Color { - return p.NYCbCrAAt(x, y) -} - -func (p *Image) NYCbCrAAt(x, y int) Color { - if !(image.Point{X: x, Y: y}.In(p.Rect)) { - return Color{} - } - yi := p.YOffset(x, y) - ci := p.COffset(x, y) - ai := p.AOffset(x, y) - return Color{ - color.YCbCr{ - Y: p.Y[yi], - Cb: p.Cb[ci], - Cr: p.Cr[ci], - }, - p.A[ai], - } -} - -// AOffset returns the index of the first element of A that corresponds to -// the pixel at (x, y). -func (p *Image) AOffset(x, y int) int { - return (y-p.Rect.Min.Y)*p.AStride + (x - p.Rect.Min.X) -} - -// SubImage returns an image representing the portion of the image p visible -// through r. The returned value shares pixels with the original image. -func (p *Image) SubImage(r image.Rectangle) image.Image { - // TODO: share code with image.NewYCbCr when this type moves into the - // standard image package. - r = r.Intersect(p.Rect) - // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside - // either r1 or r2 if the intersection is empty. Without explicitly checking for - // this, the Pix[i:] expression below can panic. - if r.Empty() { - return &Image{ - YCbCr: image.YCbCr{ - SubsampleRatio: p.SubsampleRatio, - }, - } - } - yi := p.YOffset(r.Min.X, r.Min.Y) - ci := p.COffset(r.Min.X, r.Min.Y) - ai := p.AOffset(r.Min.X, r.Min.Y) - return &Image{ - YCbCr: image.YCbCr{ - Y: p.Y[yi:], - Cb: p.Cb[ci:], - Cr: p.Cr[ci:], - SubsampleRatio: p.SubsampleRatio, - YStride: p.YStride, - CStride: p.CStride, - Rect: r, - }, - A: p.A[ai:], - AStride: p.AStride, - } -} - -// Opaque scans the entire image and reports whether it is fully opaque. -func (p *Image) Opaque() bool { - if p.Rect.Empty() { - return true - } - i0, i1 := 0, p.Rect.Dx() - for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { - for _, a := range p.A[i0:i1] { - if a != 0xff { - return false - } - } - i0 += p.AStride - i1 += p.AStride - } - return true -} - -// New returns a new Image with the given bounds and subsample ratio. -func New(r image.Rectangle, subsampleRatio image.YCbCrSubsampleRatio) *Image { - // TODO: share code with image.NewYCbCr when this type moves into the - // standard image package. - w, h, cw, ch := r.Dx(), r.Dy(), 0, 0 - switch subsampleRatio { - case image.YCbCrSubsampleRatio422: - cw = (r.Max.X+1)/2 - r.Min.X/2 - ch = h - case image.YCbCrSubsampleRatio420: - cw = (r.Max.X+1)/2 - r.Min.X/2 - ch = (r.Max.Y+1)/2 - r.Min.Y/2 - case image.YCbCrSubsampleRatio440: - cw = w - ch = (r.Max.Y+1)/2 - r.Min.Y/2 - default: - // Default to 4:4:4 subsampling. - cw = w - ch = h - } - b := make([]byte, 2*w*h+2*cw*ch) - // TODO: use s[i:j:k] notation to set the cap. - return &Image{ - YCbCr: image.YCbCr{ - Y: b[:w*h], - Cb: b[w*h+0*cw*ch : w*h+1*cw*ch], - Cr: b[w*h+1*cw*ch : w*h+2*cw*ch], - SubsampleRatio: subsampleRatio, - YStride: w, - CStride: cw, - Rect: r, - }, - A: b[w*h+2*cw*ch:], - AStride: w, - } -} diff --git a/Makefile b/Makefile index 1696fdbd..6c5eeb4d 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,23 @@ -test_all: test +test_all: test test_bench go test -v github.com/mat/besticon/besticon/iconserver go get ./... test: go test -v github.com/mat/besticon/ico go test -v github.com/mat/besticon/besticon + go test -v github.com/mat/besticon/lettericon + go test -v github.com/mat/besticon/colorfinder test_race: go test -v -race github.com/mat/besticon/ico go test -v -race github.com/mat/besticon/besticon go test -v -race github.com/mat/besticon/besticon/iconserver +test_bench: + go test github.com/mat/besticon/lettericon -bench . + go test github.com/mat/besticon/colorfinder -bench . + update_godeps: godep save ./... diff --git a/Readme.markdown b/Readme.markdown index 4e2e7d44..77e729f9 100644 --- a/Readme.markdown +++ b/Readme.markdown @@ -3,26 +3,64 @@ Source code powering The Favicon Finder at . [![Build Status](https://travis-ci.org/mat/besticon.svg?branch=master)](https://travis-ci.org/mat/besticon) -[![GoDoc](https://godoc.org/github.com/mat/besticon/besticon?status.svg)](http://godoc.org/github.com/mat/besticon/besticon) [![Screenshot of The Favicon Finder](the-icon-finder.png)](http://icons.better-idea.org) +## API + +### GET /icon + +This endpoint always returns an icon image for the given site — it redirects to an official icon if possible or creates and returns a fallback image if needed. + +Parameter | Example | Description | Default +-------- | -------- | -------- | ---- +url | http://yelp.com | | required +size | 120 | Desired **minimum** icon size | required +formats | png,ico | Comma-separated list of accepted image formats: png, ico, gif | `png,ico,gif` + +#### Examples + +|Input URL | Icon | +|----------|------| +||![Icon for yelp.com](http://icons.better-idea.org/icon?url=yelp.com&size=32)| +||![Icon for yelp.com](http://icons.better-idea.org/icon?url=yelp.com&size=64)| +||size missing| + + + +### GET /allicons.json + +This endpoint returns all icons for a given site. + +Parameter | Example | Description | Default +-------- | -------- | --------- | ---- +url | http://yelp.com | | required +formats | png,ico | Comma-separated list of accepted image formats: png, ico, gif | `png,ico,gif` +pretty | true | Whether to return a pretty-printed JSON response, for debugging | `false` + +#### Examples + +* +* +* + + ## Server Executable ### Download binaries -Binaries for some operating systems are available under +Binaries for some operating systems can be downloaded from -Find even more binaries on the excellent GoBuilder community site +Even more binaries are available from the excellent GoBuilder community site ### Build your own -If you have Go installed on your system you can use `go get` to fetch the source code and build the server: +If you have Go 1.5 installed on your system you can use `go get` to fetch the source code and build the server: $ go get -u github.com/mat/besticon/... -If you want to build exectuables for a different target operating system you can add the `GOOS` and `GOARCH` environment variables: +If you want to build executables for a different target operating system you can add the `GOOS` and `GOARCH` environment variables: $ GOOS=linux GOARCH=amd64 go get -u github.com/mat/besticon/... @@ -33,36 +71,41 @@ To start the server on port 8080 use $ iconserver --port=8080 +## Libraries etc. -## Command Line Tool - -### Dependencies - - - +Package | Description | License +------ | ---------- | ------ + | net/http gzip compression | [Apache License, Version 2.0](https://github.com/NYTimes/gziphandler/blob/master/LICENSE.md) | + | |[BSD style](https://github.com/PuerkitoBio/goquery/blob/master/LICENSE) | + | CSS selectors| [License](https://github.com/andybalholm/cascadia/blob/master/LICENSE) | + | | [FreeType License](https://github.com/golang/freetype/blob/master/LICENSE)| + | supplementary image libraries | [BSD style](https://github.com/golang/image/blob/master/LICENSE) | + | | [BSD style](https://github.com/golang/net/blob/master/LICENSE)| + | | [BSD style](https://github.com/golang/text/blob/master/LICENSE)| +| [Open Sans font](https://www.google.com/fonts/specimen/Open+Sans) used for the generated icons | | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html) | +| [The icon](http://sixrevisions.com/freebies/icons/free-icons-1000/) used on [icons.better-idea.org](http://icons.better-idea.org) | | [License](http://sixrevisions.com/freebies/icons/free-icons-1000/) | -### Setup - $ go get -u github.com/mat/besticon/... - -### Usage - -Finding the biggest icon: - - $ besticon http://github.com - http://github.com: https://github.com/apple-touch-icon-144.png +## License -Finding all icons, sorted by biggest icon first: +MIT License (MIT) - $ besticon --all http://github.com - http://github.com: https://github.com/apple-touch-icon-144.png - http://github.com: https://github.com/apple-touch-icon.png - http://github.com: https://github.com/apple-touch-icon-114.png - http://github.com: https://github.com/apple-touch-icon-precomposed.png - http://github.com: https://assets-cdn.github.com/favicon.ico - http://github.com: https://github.com/favicon.ico +Copyright (c) 2015 Matthias Lüdtke, Hamburg - -## License +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 *source code* of besticon is released under the [MIT License](http://www.opensource.org/licenses/MIT). +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -The *icon* used for the website/server is licensed under [these terms](http://sixrevisions.com/freebies/icons/free-icons-1000/). +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/besticon/besticon.go b/besticon/besticon.go index fc9869ff..db7121e6 100644 --- a/besticon/besticon.go +++ b/besticon/besticon.go @@ -19,10 +19,14 @@ import ( "strings" "time" - // Load support image formats. + "image/color" + + // Load supported image formats. _ "image/gif" _ "image/png" + "github.com/mat/besticon/colorfinder" + // ...even more image formats. _ "github.com/mat/besticon/ico" @@ -31,21 +35,92 @@ import ( "golang.org/x/net/publicsuffix" ) +var defaultFormats []string + // Icon holds icon information. type Icon struct { - URL string `json:"url"` - Width int `json:"width"` - Height int `json:"height"` - Format string `json:"format"` - Bytes int `json:"bytes"` - Error error `json:"error"` - Sha1sum string `json:"sha1sum"` + URL string `json:"url"` + Width int `json:"width"` + Height int `json:"height"` + Format string `json:"format"` + Bytes int `json:"bytes"` + Error error `json:"error"` + Sha1sum string `json:"sha1sum"` + imageData []byte +} + +type IconFinder struct { + FormatsAllowed []string + KeepImageBytes bool + icons []Icon +} + +func (f *IconFinder) FetchIcons(url string) (error, []Icon) { + var err error + f.icons, err = FetchIcons(url) + return err, f.Icons() +} + +func (f *IconFinder) IconWithMinSize(minSize int) *Icon { + SortIcons(f.icons, false) + + for _, ico := range f.icons { + if ico.Width >= minSize && ico.Height >= minSize { + return &ico + } + } + return nil +} + +func (f *IconFinder) MainColorForIcons() *color.RGBA { + return MainColorForIcons(f.icons) +} + +func (f *IconFinder) Icons() []Icon { + return discardUnwantedFormats(f.icons, f.FormatsAllowed) +} + +func (ico *Icon) Image() *image.Image { + img, _, _ := image.Decode(bytes.NewReader(ico.imageData)) + return &img +} + +func discardUnwantedFormats(icons []Icon, wantedFormats []string) []Icon { + formats := defaultFormats + if len(wantedFormats) > 0 { + formats = wantedFormats + } + + return filterIcons(icons, func(ico Icon) bool { + return includesString(formats, ico.Format) + }) +} + +type iconPredicate func(Icon) bool + +func filterIcons(icons []Icon, pred iconPredicate) []Icon { + result := []Icon{} + for _, ico := range icons { + if pred(ico) { + result = append(result, ico) + } + } + return result +} + +func includesString(arr []string, str string) bool { + for _, e := range arr { + if e == str { + return true + } + } + return false } // FetchBestIcon takes a siteURL and returns the icon with // the largest dimensions for this site or an error. -func FetchBestIcon(siteURL string, useCache bool) (*Icon, error) { - icons, e := FetchIcons(siteURL, useCache) +func FetchBestIcon(siteURL string) (*Icon, error) { + icons, e := FetchIcons(siteURL) if e != nil { return nil, e } @@ -58,18 +133,36 @@ func FetchBestIcon(siteURL string, useCache bool) (*Icon, error) { return &best, nil } +func FetchOrGenerateIcon(siteURL string, size int) (*Icon, error) { + icons, err := FetchIcons(siteURL) + if err != nil { + return nil, err + } + if len(icons) < 1 { + return nil, errors.New("besticon: no icons found for site") + } + + best := icons[0] + if best.Width >= size && best.Height > size { + return &best, nil + } + + return &Icon{ + Width: size, + Height: size, + Format: "png", + URL: fmt.Sprintf("/siteicon?url=%s&size=%d", siteURL, size), + }, nil +} + // FetchIcons takes a siteURL and returns all icons for this site // or an error. -func FetchIcons(siteURL string, useCache bool) ([]Icon, error) { +func FetchIcons(siteURL string) ([]Icon, error) { siteURL = strings.TrimSpace(siteURL) if !strings.HasPrefix(siteURL, "http") { siteURL = "http://" + siteURL } - if useCache && cacheEnabled() { - return resultFromCache(siteURL) - } - html, url, e := fetchHTML(siteURL) if e != nil { return nil, e @@ -82,7 +175,7 @@ func FetchIcons(siteURL string, useCache bool) ([]Icon, error) { icons := fetchAllIcons(links) icons = rejectBrokenIcons(icons) - sortIcons(icons) + SortIcons(icons, true) return icons, nil } @@ -210,6 +303,36 @@ func extractIconTags(doc *goquery.Document) []string { return hits } +func MainColorForIcons(icons []Icon) *color.RGBA { + if len(icons) == 0 { + return nil + } + + var icon *Icon + for _, ico := range icons { + if ico.Format == "png" { + icon = &ico + break + } + } + if icon == nil { + return nil + } + + img := icon.Image() + if img == nil { + return nil + } + + cf := colorfinder.ColorFinder{} + color, err := cf.FindMainColor(*img) + if err != nil { + return nil + } + + return &color +} + func fetchAllIcons(urls []string) []Icon { ch := make(chan Icon) @@ -252,6 +375,9 @@ func fetchIconDetails(url string) Icon { i.Format = format i.Bytes = len(b) i.Sha1sum = sha1Sum(b) + if keepImageBytes { + i.imageData = b + } return i } @@ -360,9 +486,13 @@ func sha1Sum(b []byte) string { } var client *http.Client +var keepImageBytes bool func init() { setHTTPClient(&http.Client{Timeout: 60 * time.Second}) + + // Needs to be kept in sync with those image/... imports + defaultFormats = []string{"png", "gif", "ico"} } func setHTTPClient(c *http.Client) { @@ -380,4 +510,5 @@ func SetLogOutput(w io.Writer) { func init() { SetLogOutput(os.Stdout) + keepImageBytes = true } diff --git a/besticon/besticon/cmd.go b/besticon/besticon/cmd.go index 98f17165..21c931f9 100644 --- a/besticon/besticon/cmd.go +++ b/besticon/besticon/cmd.go @@ -22,7 +22,7 @@ func main() { url := os.Args[len(os.Args)-1] - icons, err := besticon.FetchIcons(url, false) + icons, err := besticon.FetchIcons(url) if err != nil { fmt.Fprintf(os.Stderr, "%s: failed to fetch icons: %s\n", url, err) os.Exit(1) diff --git a/besticon/besticon_test.go b/besticon/besticon_test.go index 91db8925..9da3c654 100644 --- a/besticon/besticon_test.go +++ b/besticon/besticon_test.go @@ -192,7 +192,7 @@ func fetchIconsWithVCR(vcrFile string, url string) ([]Icon, error) { defer f.Close() setHTTPClient(c) - return FetchIcons(url, true) + return FetchIcons(url) } func fetchBestIconWithVCR(vcrFile string, url string) (*Icon, error) { @@ -204,7 +204,7 @@ func fetchBestIconWithVCR(vcrFile string, url string) (*Icon, error) { defer f.Close() setHTTPClient(c) - i, err := FetchBestIcon(url, true) + i, err := FetchBestIcon(url) return i, err } @@ -242,3 +242,7 @@ func fail(t *testing.T, failureMessage string) { "\r\t", failureMessage) } + +func init() { + keepImageBytes = false +} diff --git a/besticon/caching.go b/besticon/caching.go deleted file mode 100644 index 00fc83f5..00000000 --- a/besticon/caching.go +++ /dev/null @@ -1,83 +0,0 @@ -package besticon - -import ( - "encoding/json" - "errors" - "fmt" - "time" - - "github.com/golang/groupcache" -) - -var iconCache *groupcache.Group - -type result struct { - Icons []Icon - Error string -} - -func resultFromCache(siteURL string) ([]Icon, error) { - if iconCache == nil { - return FetchIcons(siteURL, false) - } - - // Let results expire after a day - now := time.Now() - key := fmt.Sprintf("%d-%02d-%02d-%s", now.Year(), now.Month(), now.Day(), siteURL) - var data []byte - err := iconCache.Get(siteURL, key, groupcache.AllocatingByteSliceSink(&data)) - if err != nil { - logger.Println("ERR:", err) - return FetchIcons(siteURL, false) - } - - res := &result{} - err = json.Unmarshal(data, res) - if err != nil { - panic(err) - } - - if res.Error != "" { - return res.Icons, errors.New(res.Error) - } - return res.Icons, nil -} - -func generatorFunc(ctx groupcache.Context, key string, sink groupcache.Sink) error { - siteURL := ctx.(string) - icons, err := FetchIcons(siteURL, false) - if err != nil { - // Don't cache errors - return err - } - - res := result{Icons: icons} - if err != nil { - res.Error = err.Error() - } - bytes, err := json.Marshal(res) - if err != nil { - panic(err) - } - sink.SetBytes(bytes) - - return nil -} - -func cacheEnabled() bool { - return iconCache != nil -} - -// SetCacheMaxSize enables icon caching if sizeInMB > 0. -func SetCacheMaxSize(sizeInMB int64) { - if sizeInMB > 0 { - iconCache = groupcache.NewGroup("icons", sizeInMB<<20, groupcache.GetterFunc(generatorFunc)) - } else { - iconCache = nil - } -} - -// GetCacheStats returns cache statistics. -func GetCacheStats() groupcache.CacheStats { - return iconCache.CacheStats(groupcache.MainCache) -} diff --git a/besticon/example_test.go b/besticon/example_test.go index ccef2fc4..fa4ef4cc 100644 --- a/besticon/example_test.go +++ b/besticon/example_test.go @@ -3,7 +3,7 @@ package besticon import "fmt" func ExampleFetchBestIcon() { - i, err := FetchBestIcon("github.com", false) + i, err := FetchBestIcon("github.com") if err != nil { fmt.Println("could not fetch icon: ", err) } else { diff --git a/besticon/iconserver/assets/assets.go b/besticon/iconserver/assets/assets.go index 9b6436b3..205f6030 100644 --- a/besticon/iconserver/assets/assets.go +++ b/besticon/iconserver/assets/assets.go @@ -10,8 +10,10 @@ // besticon/iconserver/assets/main-min.css // besticon/iconserver/assets/main.css // besticon/iconserver/assets/not_found.html +// besticon/iconserver/assets/popular.html // besticon/iconserver/assets/pure-0.5.0-min.css // besticon/iconserver/assets/robots.txt +// besticon/iconserver/assets/test-lettericons.html // DO NOT EDIT! package assets @@ -79,7 +81,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _besticonIconserverAssets152x152_iconPng = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x00\x52\x05\xad\xfa\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x98\x00\x00\x00\x98\x08\x04\x00\x00\x00\xb2\xcb\xe8\xaa\x00\x00\x05\x19\x49\x44\x41\x54\x78\x01\xec\xd6\xc1\x0d\x80\x40\x08\x45\xc1\xaf\xa1\x5a\xfa\xbf\x63\x03\x5e\x76\x0f\x1a\xe3\xbc\x0e\x98\x40\x42\xf4\x85\x24\x49\x92\x74\x64\xab\x9e\xbf\xce\x5e\x1d\xad\x74\xe6\x3e\x01\x03\x06\x0c\x18\x30\xd5\x63\x1f\xcd\xfb\x8d\x0d\x73\x92\xc0\x80\x01\x13\x30\x60\xc0\x80\x01\x13\x30\x60\xc0\x80\x01\x03\x86\x00\x18\x30\x60\xc0\x80\x09\x18\x30\x60\xc0\x80\x09\x18\x30\x60\xc0\x80\x01\x13\x30\x60\xc0\x80\x01\x13\x30\x60\x57\xbb\xf6\x1b\x5b\x67\x55\x07\x70\xfc\x73\x69\xeb\x05\xff\x74\xd5\xba\xc1\x58\xd0\x68\x15\xc6\x70\x9a\x2d\x75\x24\xa2\x0c\x82\x8a\x6e\xa2\x6c\x66\x59\x08\x6e\x2c\xc3\x3f\x11\xb3\x10\x8d\x12\x2d\x2f\xd4\xc0\x8b\xf9\x02\x48\xf4\x05\x51\x19\x2e\x61\x83\x44\xdd\x32\xaa\x34\x21\xd5\x65\x28\x11\x1b\x34\x52\xba\x14\x21\x5b\x98\xae\x56\xb7\xd2\x64\x65\xb3\x69\xef\x6c\xaf\x2f\x39\x27\xed\xf5\x39\x35\x59\xd2\xe7\xe6\x7c\xde\xde\xbe\x68\xbe\xf9\x9d\xe7\x9c\xe4\x9c\x0b\xac\xd5\xe2\xb0\xc6\x47\xad\xd1\xe5\x72\x55\x75\xff\xf6\xba\x13\x5e\x31\xe0\x19\xe7\xcc\xef\x72\x9f\xb1\xde\x2a\xef\xb2\xc4\x8c\xd7\xfd\xcd\xb0\xdf\xe9\x75\xda\x05\x55\xb9\xcb\xff\xa5\x2e\x54\x59\xd0\x5f\xc4\x56\xf8\xaa\xed\xae\x30\xbf\x69\x3f\x74\x0f\x31\xeb\xdc\x6b\xa3\x16\x73\x9d\x77\xc8\x7d\x86\x12\xfe\x67\x2a\xe5\x5b\x92\xed\x1e\x72\xdc\xbd\x0d\x73\x51\xf5\x76\xb1\x0e\x8f\xfa\xa3\xcf\xce\x9b\x8b\x36\x5b\xbc\xe0\x01\x17\x37\xe3\x92\xbc\xde\x3e\x57\x28\xf2\x5b\xa1\x95\x9e\x74\x65\xe1\x10\x7c\xc3\x75\x3e\xe7\x54\x73\x7d\xf4\x77\xf8\x4d\x42\xae\xd9\x28\xd8\x2a\x47\x5c\x29\xc5\xb5\xfa\x2d\x6d\xa6\x60\xb7\xdb\xa3\x4d\xb1\x17\x8d\x01\x58\xea\xd7\x2e\x15\xe3\x94\x3f\x3b\xaa\x26\xc6\x6a\xfb\xb4\x34\x4b\xb0\x6e\x7b\x5c\x24\x56\x73\xc0\x5d\xd6\xba\x4c\xa7\x2e\xd7\xf9\x92\x3d\xc6\xf4\x7b\xc3\x8f\xbd\x47\xec\x71\xeb\x5c\xa6\xdb\x6a\x1d\xb6\xf9\xbb\xd8\x27\xdd\xdd\x1c\xbb\x64\xd5\xa0\xab\x84\xea\x1e\x71\x9f\x93\x62\xb4\x69\x37\x0e\xd8\xe4\x60\x1c\xd8\x36\x3f\x17\xea\xf4\x0b\x37\x0a\x9d\xd5\x65\xac\xfc\xbb\xe4\xdd\x71\x2e\x35\x5b\x7c\x79\x9e\x5c\x9c\x37\x0e\xa8\xb8\x5f\xec\x2b\x71\x2e\x8c\xdb\xe4\x25\xa1\xb7\xf9\x7a\xf9\x97\xe4\x25\xbe\x29\xb6\xcb\x01\x45\x3e\x6e\x95\x50\x9f\xbd\xe6\x9a\x70\xa7\xd8\x9d\xda\xca\x1e\x6c\x93\xa5\x42\x8f\xfb\x89\x62\x77\x88\xf5\x98\xdf\x73\xfa\x84\x96\xb9\xb1\xec\xc1\xb6\x0a\xcd\xfa\xae\x62\xad\x36\x0a\x0d\x1a\xd4\xc8\xcf\xc4\x6e\x2e\x77\xb0\x16\xeb\x85\x8e\x38\xa6\xd8\x35\x3a\x84\x0e\x69\xac\xcf\x79\xa1\x0f\x97\x3b\xd8\x4a\x4b\x84\x9e\x96\x62\xad\xd8\x73\x1a\x9b\x34\x2c\xb4\xaa\xdc\xc1\xba\xc4\x06\xa5\x78\xaf\xd8\x2b\x1a\xe3\x25\xa1\x4e\x97\x94\x39\xd8\x0a\xb1\x51\x29\x3a\xc5\xfe\xa9\x31\xc6\xc5\x3a\xca\x1c\xac\x5d\x6c\x42\x8a\x25\x62\x53\x1a\xe3\xac\x58\x5b\x99\x83\x55\xc4\xaa\x52\xcc\x88\xb5\x88\x14\xfc\x3a\x59\xe6\x60\x93\x62\xcb\xa4\x98\x28\x58\xa2\xb1\x77\x0a\xd5\x9d\x2d\x73\xb0\xd3\x62\x2b\xa5\x18\x15\x7b\x77\xfa\x16\xe1\x94\xe9\x32\x07\x3b\x2e\x76\x83\x14\xc7\xc4\xd6\x68\xac\x62\xb5\xd0\xcb\x94\x39\xd8\x90\x9a\xd0\xad\x3a\x14\xfb\x93\xd8\x4d\x1a\xfb\x88\x77\x08\x3d\x5f\xee\x60\x53\xfe\x20\xf4\x56\x5f\x53\xec\x55\xc7\x85\x36\x6a\xd7\xc8\x56\xb1\xfe\x72\x07\xe3\xa0\xd8\xb7\xbd\x5f\xb1\x43\x42\x6f\xb1\xcb\xfc\x3a\xdd\x21\x74\xc6\x33\x65\x0f\xf6\x98\x73\xe2\x19\xeb\xb3\x42\x91\x47\xd4\x85\xbe\xd3\x20\xf3\x43\xda\x85\xf6\x9a\x2e\x7b\xb0\x33\x7e\x24\xf6\x3e\x03\x36\xf8\xdf\xfe\x3a\x67\xc6\x7e\x65\x39\x62\xf7\xd8\x26\x34\xe5\x41\xca\x1e\x8c\xdd\x4e\x8a\xad\xf0\x94\x23\xbe\x18\x1d\x17\x96\xb8\xc9\xfd\x6e\x0f\x66\x6a\x5a\xe8\x2a\xcf\xdb\xac\x02\xe0\x52\x7b\xfd\x40\xec\x41\x27\x9b\xe3\xe6\xfb\x7a\xfd\xde\x64\x3e\xa7\xfd\xc3\xac\x37\x5b\xa6\x13\x3c\x66\x7b\x30\x3f\x71\x10\x38\xe1\xb0\x7f\xa9\xfa\x80\x1b\x54\xc5\x06\x5d\x6b\x3a\xe1\xe6\xbb\x04\xc1\xd8\xe9\xa7\x49\xd3\xfd\xa2\x0f\x01\xa8\x78\xc2\x56\xa9\x4e\xe9\x36\xd2\x3c\x4f\x05\x1e\xf5\x05\x53\x8a\x5d\xad\x0d\x40\xdd\x76\xbf\x94\xe6\x84\xf5\x46\x9a\xeb\xe6\xfb\x09\xeb\xfc\x45\x91\x36\xd7\x78\x43\xcd\x56\xdf\xf3\x1f\x45\x9e\xd4\xed\x65\x9a\x2b\x18\x43\xba\xed\x70\xb4\x70\xc6\x42\xb3\xbe\xaf\xdb\xd3\x1a\x7b\xc1\x66\xb7\x1a\x6f\xde\xe7\x4e\x15\xdd\x3e\xef\x63\xd6\xba\x58\xe8\x8c\x61\xcf\x7a\xca\xef\xd5\xcd\xb5\xda\x36\x9f\xf0\x41\x17\x05\x29\x8f\x3a\xec\x80\x67\x45\xca\xf2\xd1\x5f\xb8\x8a\xe5\x96\xeb\x50\x71\xce\xa4\x51\xaf\x29\x56\xd5\xa5\x53\xd5\x94\xd7\xbc\x6a\x1a\xb8\xb0\xc1\x5a\x2d\x16\x75\xa3\x46\x2d\xcc\xb4\xe1\xfc\xc6\x75\xe1\x72\xb0\x1c\x2c\x07\xcb\xc1\xb2\x1c\x2c\x07\xcb\xc1\x72\xb0\x1c\x2c\xcb\xc1\x72\xb0\x1c\xac\x99\x82\x65\xad\xca\xab\x9e\x27\x2c\x2f\xc9\xe6\x0f\x96\xe5\x60\x39\x58\x0e\x96\x83\xe5\x60\x59\x0e\xf6\x40\x0e\xb6\x10\xfb\x7d\x2b\x07\x4b\x77\xd8\x4e\xf5\x1c\x2c\xd5\x90\xcd\x6a\x12\xe5\x60\x23\x36\x98\x90\x28\x07\x3b\x63\x83\x11\x89\x72\xb0\x49\x9f\x32\x24\x51\x0e\x36\xe3\x36\x03\x92\xe5\x60\xbb\xf4\x4a\x96\x83\xed\xf6\xb0\x64\x39\xd8\x7e\x3d\x92\xe5\x60\x7d\x0b\x39\xa8\xe6\x60\x03\xb6\xa8\x49\x94\x83\x1d\x73\x8b\x49\x89\x72\xb0\x31\x9f\x36\x26\x51\x0e\x36\xe9\x16\xc7\xc8\xc1\x2e\xc0\x41\x35\x07\xab\xdb\xa1\x57\xb2\x1c\xac\xc7\x3e\xc9\x72\xb0\x87\xed\x5e\xcc\x8f\x51\xea\x16\x97\x5e\xbb\x24\xcb\x13\x36\xe0\x36\x33\x39\x58\xaa\xe1\x85\x1c\x54\x73\xb0\x11\x37\x1b\x93\x28\x07\x9b\xb0\xc1\x88\x44\x39\x58\xcd\x66\x43\x12\xe5\x60\x75\x3b\x1d\x96\x2c\x07\xeb\xb1\x7f\x31\x3f\x0a\xae\x28\xb9\x3c\x61\x39\x58\x0e\x96\x83\xe5\x60\x59\x0e\x96\x83\xe5\x60\xe5\xf2\x5f\xc7\x04\x25\xeb\xa3\xa0\x17\x25\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\x01\x00\x00\xff\xff\xd9\x38\x3c\x38\x52\x05\x00\x00") +var _besticonIconserverAssets152x152_iconPng = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x9c\x94\x7d\x3c\x13\x88\x1f\xc7\x17\x5e\x61\x11\x32\x11\x93\xfc\xfc\x1a\xae\xc5\xa2\x14\xd1\x6e\xa2\xa5\xcd\x2a\x4f\xa9\x3c\xcc\xc3\x92\xb1\x28\xd7\xf2\xd8\x92\xa3\x9b\x44\xb8\x1c\xd9\xdc\xcb\x55\x73\xe8\x32\x4f\x75\x32\x63\x1e\x4e\xcd\x4c\x0a\xed\x21\x7a\x51\x6c\xad\xd9\x6c\xcb\x32\xb3\xeb\xdc\xeb\x5e\xaf\x7b\xdd\x1f\xf7\xd7\xfd\xf1\x7d\xfc\xe3\xf3\xdf\xfb\x4d\x3e\x81\x41\x9a\x02\x6d\x81\x00\x00\xc0\x34\xe8\x68\x40\xc8\xfa\xac\xfe\xb3\x8c\x0c\xd6\x7b\xdb\x88\xb8\x09\x00\x30\xf8\x14\x14\x80\x08\xcb\x14\x2c\x4e\xc7\x9e\x9f\xc4\x81\x87\x15\x49\x6e\xd3\x90\x3d\x48\x14\x52\xe0\x50\xd2\x1f\x07\xad\x3c\xf3\xa5\x23\xfa\xbe\x15\xc8\x48\x6d\x16\xec\xd8\xec\x28\x35\x25\x8e\x17\xee\x7e\xea\xc2\x86\x77\x42\x0a\x80\xee\xab\x9e\xf1\xde\x6d\xf0\x80\x6e\x73\x69\xff\x99\x7c\xfa\xcd\x59\xda\x1c\x6c\x2b\x19\xd2\x51\xe5\x91\x52\x74\x61\xf1\xb8\xf5\x53\xaa\x8e\x29\x7a\xf2\x36\x8b\xf8\xce\x7b\x4c\xa1\xca\xbb\x00\xee\x95\x5f\x19\x53\x31\x0e\x68\xa9\x22\xdf\xde\xb7\x9a\x0f\x14\xff\xfa\x13\x2e\x20\x60\xa1\x7f\x79\x2f\x2b\x73\x25\x18\xab\x67\x59\xdd\x67\x00\x81\xe5\x1b\x43\x73\xe9\xb0\xd7\xa5\x7f\x9f\x68\xec\x7f\x59\xe7\x77\xd9\x8c\xf0\xfd\x3d\xe1\xe3\x23\xae\x98\x97\x87\x0d\x73\xb2\x6e\x3a\xff\x4a\x14\x14\x17\xa6\xd2\xee\xb8\x71\x3d\xfa\xcd\x49\xe3\x41\x9b\x3a\xa1\x46\x5b\x39\x57\xd2\xa1\xf1\x76\x0d\x34\x1d\xf3\xb7\x40\xdb\x78\xbc\xec\xc1\xad\x72\xde\x5a\x1c\xf3\xa7\xaf\xd2\x58\x2e\x0f\xc8\x37\xb7\x31\xe7\x94\xad\x8d\xae\xf7\x6a\x5a\x07\x8b\x4f\x12\x4f\x52\x6e\x60\x27\xfe\xcf\x68\x0b\x21\x44\xdf\xa7\x55\xc4\x32\x98\x41\x13\x88\xc0\xba\xfc\x56\x72\x5c\x19\xb9\xcc\x83\x74\x6c\x34\x64\x95\xd1\x9b\x7b\x39\x11\x8f\x5b\xc2\xa6\x62\x27\x52\x04\xd1\xa1\xf8\x05\xd5\x59\xf4\x11\x07\x2a\x18\xe7\xb2\xf0\xec\x33\x68\xc1\xd8\xe6\xf3\x20\xa5\xab\x68\xa5\xc8\xa7\x2a\x94\x75\xf9\x0d\xbb\x60\x42\x69\xac\x0b\x3d\xae\xc9\xad\x8d\x78\x75\x6c\x79\x3e\x61\x67\xea\xfb\x44\x81\xe2\x94\x52\xaf\xe4\x7f\xa5\xb5\xac\x32\x85\xc5\xfe\xa1\xb5\x52\xfe\xf7\xc7\x7f\xcf\x21\xd8\x2e\xb5\x43\xba\x29\x0e\x68\x2e\xbc\x1c\x2e\xc6\xb2\x1e\xd3\x82\x75\x8d\x25\x3a\xab\x74\x4e\x18\xa1\xf8\xf9\x5d\x64\xd9\x73\x81\x85\xaf\xcd\xce\x4f\xb5\xf5\x69\x6a\xb1\xdc\x22\xb4\x3d\xed\x2e\xc3\x10\x3d\xf3\x23\x67\xb3\xbd\xd4\x3b\x67\xbb\x52\x92\x56\xd6\x78\xc6\x8b\xb0\x70\xa8\x52\x73\x5e\x8c\x25\x9c\xe3\xa7\xd7\x22\xd3\x5e\xc3\xcc\x1b\x25\x98\x67\x79\x82\x3e\x29\xd0\xb6\xc4\x9f\x1b\x58\x0a\x5e\x92\x10\x6a\x6a\xa4\xb5\xc6\x5d\x19\xa3\xab\x32\x11\x9d\x25\x83\x0d\xcc\x48\x26\x85\x9b\x68\x92\xd6\x41\xa9\xec\xa8\xac\x86\xce\x9a\xe2\x24\x4a\x2a\xc3\xd3\x6a\x9b\x86\xc8\xfc\xd8\x6a\x69\xc5\x6d\x96\x84\x43\x6f\x66\x64\x0b\x09\x4d\xc5\x96\xed\xf0\xbd\xfc\xfd\xdf\x9a\xa8\x9b\xb6\xa9\x47\x63\x7a\x3a\xb9\x89\x4d\xd2\x12\xb9\x13\x9a\x9e\xed\x29\x15\xf6\x64\xa7\xec\x09\x2f\x24\xf3\x4d\x21\xda\xd5\xdb\xac\x18\xaf\x81\x98\xd9\x49\xa1\x21\x0d\x8f\x88\x27\xb6\x6b\x78\xe1\x20\x0f\x9e\x8f\xa7\xf4\x07\x46\x76\xce\x68\x58\xb8\xf3\xb9\x27\xc8\x4b\x5f\x8c\xb4\xd1\x6d\x02\x13\x6d\x46\xcb\x4c\x9d\xe2\x0b\x2c\x70\x43\x92\x53\xd7\x62\x5c\x81\x55\x2d\xb5\x19\xc1\xf6\xcd\x3e\x9b\x0a\xd1\xe2\xfc\x65\xc0\x4a\x6d\x8c\xd8\xe1\xd6\xd5\xbd\xfa\xa4\xe9\xe6\xde\x58\xa7\x7d\x22\x57\xaa\x97\x4a\x97\xab\x85\x76\x0d\x99\xe4\xbe\x10\x51\x2b\x8e\xc0\xcf\xb1\x35\x07\x2b\xf6\xc3\x2e\xb2\xcd\xac\x1f\x96\x20\x3c\x3f\xc5\x6c\xc5\x49\x5b\x5e\x46\xb9\xfa\x38\x8c\x51\x1e\x03\x92\xd9\x37\x4c\x07\xed\x93\xcf\x3e\x6f\xc8\xf2\x4d\x28\x23\x16\xac\xae\x0c\x02\x0f\xc5\xa5\x28\xfb\x27\xf2\xde\xa4\xb3\x8e\x25\xb8\xb7\x74\x86\x8e\xec\x2e\x9f\x7e\x15\x9e\x9a\x30\xf0\x7e\x0c\xf5\xf2\x91\x3e\x65\x21\x08\x08\x29\x3b\xb5\x74\x5a\x20\x7f\x53\xe7\x6e\x8d\xc0\xc7\xb7\x28\xa3\x04\x8e\x7e\x01\xce\x7e\x94\xae\xb5\x0c\x54\xff\xc7\x24\xca\x45\xcc\x92\xab\x30\x39\x91\xc4\xc1\xdd\x91\x4d\x68\x76\xa5\xc3\x44\x99\xe3\x2a\x0f\xe1\xec\x33\x60\x8a\xdc\x64\x3b\x90\x3f\x7c\x2b\xc8\x09\x28\xf7\x97\x65\xbb\x65\xa2\x73\x0e\x74\x3a\xcb\xc1\x19\x2b\x82\xca\x8f\x06\xa8\x0a\x24\x68\xee\x17\xbd\x70\xb0\xb2\x7a\x35\xba\xfc\xee\x69\x06\x8b\xb4\x2d\x85\x89\x8a\xae\x1b\x71\x82\x89\xaa\x87\x54\xe0\x51\x98\x66\x79\x8f\xdd\x94\xb6\xf2\xd1\x9d\xf6\xa9\x24\xce\xec\x8c\x2c\xec\xeb\x7d\xf2\x74\xd8\xa2\xd9\x37\xd7\x0a\x18\xa8\x60\x49\xde\x0b\x86\x8f\x9d\xb8\x98\x62\x88\xf4\x46\x5b\xee\xca\x1b\x06\xaf\xd9\x7f\x07\xa2\xdf\xee\x3e\x3d\x84\x97\x89\xb8\x64\xbf\x87\x26\xfb\x02\xa1\xf3\x8e\x11\xed\x15\x6c\xf1\xc1\xb9\x70\x00\xf1\xc1\x30\xf4\xdf\x59\xa2\x43\x0b\x3e\x90\xb8\x5b\xfe\xf1\xe5\x4d\x02\xa6\x5c\xe8\x35\x1d\x7e\x8a\x27\x3b\x8c\xa0\x4c\x7b\x2c\x26\xc2\xd0\xce\x86\x67\xb1\x80\xcb\xa2\x23\xf2\x75\x17\xe4\x68\x50\x64\x88\xdd\x92\xb6\x88\xd6\xe7\xd6\x49\xea\x72\x77\xf6\x7a\xa7\xb7\xc1\x2e\x2e\xb8\x54\x1a\xb3\x51\x2f\x42\x44\xe9\x5b\x13\x62\x44\x06\x55\xdd\x9b\x26\xfb\x58\xea\x68\x45\x21\xfe\x05\xd6\x9e\x73\x19\x83\x65\x62\x7b\xd4\xe3\x57\xf5\x50\x78\xdd\x21\xb3\xc3\x5b\x22\xd5\xd6\x4d\x88\xeb\xb8\x8c\x7a\xdb\x1d\x3c\x1b\x3b\xaa\x65\x35\x3c\xb2\x27\x43\x4f\x65\x28\x5c\x8c\xda\x5c\x30\x1f\x95\x82\xba\x4a\x29\xef\xbb\x94\x56\x6f\x6b\xce\x6b\xa5\x44\xfe\xbc\x51\xbf\x8a\x6a\xba\x8e\x05\x17\x97\xac\xef\x73\x82\xee\xb8\x9d\xb8\x1e\x48\x80\x2e\x83\xac\xf2\x35\x1d\xd9\x0d\x7f\xa9\x66\xdd\x38\x90\x39\xd2\xc0\x3d\xc3\xa3\x57\xae\x2d\x37\xac\x6b\x10\x10\x14\x88\x09\x78\xe4\x8f\xbd\xfe\x47\x00\x00\x00\xff\xff\x06\xb8\x3b\x31\x2d\x05\x00\x00") func besticonIconserverAssets152x152_iconPngBytes() ([]byte, error) { return bindataRead( @@ -94,7 +96,7 @@ func besticonIconserverAssets152x152_iconPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/152x152_icon.png", size: 1362, mode: os.FileMode(420), modTime: time.Unix(1421870483, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/152x152_icon.png", size: 1325, mode: os.FileMode(420), modTime: time.Unix(1445273224, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -114,7 +116,7 @@ func besticonIconserverAssetsAppleTouchIconPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/apple-touch-icon.png", size: 952, mode: os.FileMode(420), modTime: time.Unix(1430949422, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/apple-touch-icon.png", size: 952, mode: os.FileMode(420), modTime: time.Unix(1444911021, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -134,7 +136,7 @@ func besticonIconserverAssetsFaviconIco() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/favicon.ico", size: 99678, mode: os.FileMode(420), modTime: time.Unix(1445967136, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/favicon.ico", size: 99678, mode: os.FileMode(420), modTime: time.Unix(1448297876, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -154,7 +156,7 @@ func besticonIconserverAssetsGridsResponsive050MinCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/grids-responsive-0.5.0-min.css", size: 9796, mode: os.FileMode(420), modTime: time.Unix(1429165516, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/grids-responsive-0.5.0-min.css", size: 9796, mode: os.FileMode(420), modTime: time.Unix(1429175968, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -174,12 +176,12 @@ func besticonIconserverAssetsIconSvg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/icon.svg", size: 1192, mode: os.FileMode(420), modTime: time.Unix(1421914288, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/icon.svg", size: 1192, mode: os.FileMode(420), modTime: time.Unix(1428934523, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _besticonIconserverAssetsIconsHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x9c\x57\x51\x8f\x9c\xb6\x13\x7f\xff\x7f\x8a\xf9\x53\x29\x9b\x48\x01\x6e\x53\x45\xaa\x12\xa0\x6a\xab\x24\x97\x28\x6d\xa5\xdc\x55\xf7\x6c\x60\x16\xac\x33\x18\xd9\x66\xf7\x36\xab\xfd\x66\x7d\xeb\x17\xeb\xd8\xc0\x2e\xb0\xdc\xa9\xba\x3c\x6c\x8c\xc7\xf3\x9b\x99\x9f\x67\xc6\x73\xd1\xff\x73\x99\x99\x7d\x83\x50\x9a\x4a\x24\xff\x8b\xba\xff\x00\xa2\x12\x59\x6e\x17\xb4\xac\xd0\x30\xc8\x4a\xa6\x34\x9a\xd8\x6b\xcd\xc6\xff\xc9\x1b\x8b\x6a\x56\x61\xec\x6d\x39\xee\x1a\xa9\x8c\x07\x99\xac\x0d\xd6\x74\x74\xc7\x73\x53\xc6\x39\x6e\x79\x86\xbe\xfb\x78\x0d\xbc\xe6\x86\x33\xe1\xeb\x8c\x09\x8c\xd7\xc1\xd5\x02\x54\x8e\x3a\x53\xbc\x31\x5c\xd6\x23\xb4\xcf\xb4\xd2\x20\x6b\x38\x1c\x20\xb8\x96\xda\xc0\xf1\x48\xca\x9d\xb6\xe1\x46\x60\xb2\x74\x24\x0a\x3b\x59\x7f\x50\xf0\xfa\x1e\x14\x8a\xd8\xd3\x66\x2f\x50\x97\x88\xe4\x72\xa9\x70\x13\x7b\x41\xd8\xb4\x0a\xfd\xab\xe0\x6d\x70\xe5\x57\xbc\x0e\x32\xad\x07\xf7\x9e\xd6\x2b\x14\xcf\xb5\xaf\x50\x37\xe4\x00\xdf\x3e\x0b\xa3\x62\xbc\x1e\x69\x8c\x58\x69\x94\x6c\x50\x99\x7d\xec\xc9\xe2\x9d\x8b\xc6\x83\xee\xdf\x89\x9c\xdb\x12\xe1\x23\x23\xa2\x29\xf8\x8f\xbc\xce\x51\x79\x10\x26\x8f\x61\x2c\x13\xdc\xeb\x5f\x70\xfc\x04\x10\xaf\x58\x71\xe9\x8c\x55\xfe\x15\xcf\xca\xf3\xe8\xad\x95\x21\xee\x70\xd3\x59\x0d\xe8\xe7\x92\x27\xd6\x34\x02\x7d\x23\xdb\xac\xf4\x27\x5a\x73\x41\xd0\xd4\x85\x53\x8f\xc2\x2e\x73\xed\x32\x95\xf9\xbe\x87\xcc\xf9\x16\x78\x1e\x7b\x82\xed\x65\x6b\x06\x7a\x47\x02\xcb\x7e\x6f\xff\xb4\x9f\x09\xa6\x75\xec\x59\x40\xe2\xf3\x2c\x9c\x8a\xbb\x0b\x19\x4b\x6d\xf9\xac\x93\x88\x0d\xce\x7a\x27\x24\x59\xa1\x0d\xce\x4b\x2e\xef\x6b\xa2\xef\x30\x78\x55\x0c\x8a\x42\x16\xd2\x03\xad\x32\x9b\x28\x2e\x5e\xbd\x2d\x3c\x60\xc2\xc4\xab\x1b\x6e\x10\xec\x81\x55\x12\x85\x6c\xe6\x47\x48\x8e\x8c\xfd\x0e\xc9\xf1\xc9\x46\xf9\x26\xf9\x05\x34\x2a\x5b\xa3\xb0\x21\x4f\x78\x5d\xc0\x29\x0d\x76\x98\x82\x26\x7c\x4d\x40\x6f\x46\xec\x74\x30\x8b\x6c\xf5\x59\xe0\xcd\xac\x38\x92\xa9\x40\x5a\x61\xbc\xd9\x51\x5f\xb7\xa9\xe5\xd8\x4b\x2c\x13\xe0\x8a\xb8\xb3\x37\x86\xd8\x48\x55\x01\xcb\x6c\xce\x12\xa5\xce\xc3\x1f\x06\x3c\x4a\xcc\x52\x12\xfe\xa7\x0f\xb7\x27\x70\x57\xca\x4e\xc9\xad\x8a\xf9\x0d\x8d\x5c\x76\x07\x5a\x7f\x0d\xfd\x42\x57\xfe\x8f\xfe\xdb\xe1\x4b\x14\xe3\xaf\x07\x61\xbf\x66\x60\x53\x38\xa1\x1a\x1b\xcc\xc2\x85\xd6\x4d\x6b\xfa\x1e\xd7\x2a\x31\x75\xd5\x09\xfd\xb5\x07\xb6\x1d\x53\x56\xe1\x03\x05\xd6\x08\x96\x61\x29\x05\xe5\x47\xec\xdd\xd1\x65\xd8\xcb\xa6\x7b\x6f\x8d\xcc\x64\x45\x25\x60\xe8\xa8\xdc\x6c\x86\x2d\xa5\x30\x33\xdd\xce\x85\x79\x77\x82\x35\xdc\x30\xc1\xbf\x0f\x6a\xba\x41\x21\xb2\x12\xb3\xfb\xd8\xdb\x30\xa1\x09\x7c\xcb\x44\x8b\xb6\x88\x83\xbf\xbe\x7d\x75\x2d\x76\x16\xc6\x3c\x87\x96\xb7\x9e\xe6\x77\x3d\xe1\x77\x3d\xe1\x77\xfd\x5c\x7e\xd3\xd6\x18\x4a\xda\x8e\x40\x4a\xaa\x8a\x9b\x29\xc7\xfd\x81\xd1\xda\x6f\x14\xf5\x30\xb5\x87\xc9\x1d\x24\x9f\x64\x14\x76\x07\x9e\x13\x7d\x14\xda\xbc\x9b\xa4\x2f\xb5\xc4\x1d\x37\x25\x04\x1f\x94\x92\x8a\x1a\xe3\xb9\xf3\xa0\xdd\xf1\x12\xd7\x72\xed\xbe\x43\xb3\x5f\x48\xc5\x70\x3c\xce\x50\xf8\x06\x5e\xbe\x14\x58\x43\xe0\xea\xe4\x15\xd4\x08\x57\xaf\xec\xb9\x91\x7d\x2a\xb7\xc7\x4a\x6c\xf9\x89\x9c\x17\x9b\x61\xa9\xc0\x09\x75\xdd\xce\x79\xe9\x97\x52\xf1\xef\x84\xce\xc4\xbc\xb2\xcc\x79\x76\x18\xef\xaa\x85\x1b\x33\x25\xf5\x2c\xfa\x59\x94\xdc\x50\x9a\x3e\x2a\xed\x9d\x5b\x51\x1d\xad\x12\x4a\xd4\xc7\x61\x6e\x29\x1d\x96\xa4\xb4\xa7\xe6\x17\xb9\xe0\xfa\xe1\xa0\x58\x5d\x60\xcf\xf7\x84\x67\x17\xd5\xe0\x88\xed\x48\xab\xcb\xa8\xf3\xd3\x3b\xb0\x1a\x2a\x8a\xfa\xb4\x6d\xed\xb6\x9b\x9f\xf7\xa0\x1b\x96\x68\x03\x3e\x57\xc5\x9d\xfd\x80\x00\xac\xc0\x35\xf9\xae\xb7\x93\x83\x0b\xc4\xe6\x83\x0b\x39\xaf\x90\xc6\x0f\x72\x73\x95\x10\xb0\x03\x39\x1e\x1f\x68\x79\x8d\xbc\x28\x8d\x1b\x86\x9e\x02\x70\x64\x2e\xf8\x3b\xac\xfe\x83\x0f\xb6\xf8\x9c\xc2\x47\x2a\x01\xb6\x68\xf2\x92\xf8\xc3\x81\x72\x7d\x9a\xc2\xa1\xcb\xb2\x64\x9a\xfc\x97\x15\xf1\x54\xaa\x7f\xb9\xf9\xf3\x0f\xf8\xe6\x9e\x88\xe9\xf3\x05\x70\x5b\x72\x0d\xdd\xeb\x01\xb4\x62\x5b\xc6\x85\x4b\x70\xa6\xc1\xa9\x31\x33\x36\xc2\xce\x63\x07\xef\x9e\x9e\x9f\x1b\x85\x86\x86\xa0\x3d\xea\x17\xac\x6a\xde\x13\x73\xb1\xad\x28\xa2\xc9\x8d\xa5\xa5\x31\xcd\xbb\x30\x8c\x76\xa9\x4a\x9c\x42\x90\xd2\x79\x54\x3e\xcf\x91\x05\x52\x15\x9d\xe8\x8c\xe7\x3e\xa7\x28\x96\xed\x60\xfe\xe6\x5e\x7c\x8c\xdf\xe2\x71\x97\xdc\x48\x49\xf6\x40\xf8\xa9\x7c\x38\x55\x68\xd4\x9c\x56\xc3\x2d\xf7\x9e\x2e\x3a\xb9\x5a\x98\x53\xac\x57\xf0\x22\x67\xba\x7c\x4f\xc3\x3c\x8d\x0e\x4c\x65\x25\x50\xc3\xeb\xa7\x06\xcd\x6b\x9a\x24\xbe\xb0\xba\xb5\x6d\xf5\xcd\xd5\xfa\xed\x10\xc3\x9d\xe2\x84\x5e\x5b\xad\xb9\xf5\x42\x0a\x2a\xb2\xce\xa4\xed\xbd\x2c\x79\xdd\x2b\x69\xd9\x2a\xc2\x93\x67\x1d\xcf\xea\x68\xab\x44\x0d\xb5\x4d\x03\x7a\x08\x69\x76\x36\x61\x4a\x13\xa7\x9b\x11\x93\x4f\xdc\x5c\xb7\xe9\x98\xbe\xdf\x14\x32\x83\x39\xa4\xfb\x0b\xd3\xbb\xdd\xee\x32\xec\xdf\x99\x31\x25\xa7\x64\xf8\xfa\xcf\xdf\xb9\xb9\xc7\x31\x56\x14\x36\x73\xe6\xe9\xb1\x70\xa3\x26\xa5\x99\xfb\xfb\xe9\xdf\x00\x00\x00\xff\xff\xca\xfa\x73\x72\x57\x0d\x00\x00") +var _besticonIconserverAssetsIconsHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x9c\x57\xdb\x8e\xdb\x36\x13\xbe\xcf\x53\x30\xfc\x81\x38\x01\x22\xc9\xde\x1f\x29\x8a\x8d\xa5\xa2\x2d\x92\x4d\x82\xa4\x05\x9a\x14\xb9\xa6\xa4\xb1\xc4\x2e\x25\x0a\x24\x65\xaf\x63\xf8\xcd\x7a\xd7\x17\xeb\x90\x3a\x58\xa7\xdd\x06\xbb\x17\x5e\x9e\xe6\x9b\xe1\xc7\x39\x69\xfb\x34\x95\x89\x39\x56\x40\x72\x53\x88\xe8\xc9\xb6\xf9\x47\xc8\x36\x07\x96\xda\x01\x0e\x0b\x30\x8c\x24\x39\x53\x1a\x4c\x48\x6b\xb3\xf3\x7e\xa4\xc3\xad\x92\x15\x10\xd2\x3d\x87\x43\x25\x95\xa1\x24\x91\xa5\x81\x12\x8f\x1e\x78\x6a\xf2\x30\x85\x3d\x4f\xc0\x73\x93\x97\x84\x97\xdc\x70\x26\x3c\x9d\x30\x01\xe1\xc6\x5f\x2f\x40\xa5\xa0\x13\xc5\x2b\xc3\x65\x39\x40\x7b\x8f\x23\x4d\x64\x49\x4e\x27\xe2\xbf\x93\xda\x90\xf3\x19\x85\x1b\x69\xc3\x8d\x80\xe8\x2d\x43\x55\x78\x62\x27\xd5\xf0\xd4\x36\x68\xb6\xdb\xb3\x82\x97\xb7\x44\x81\x08\xa9\x36\x47\x01\x3a\x07\x40\xab\x73\x05\xbb\x90\xfa\x41\x55\x2b\xf0\xd6\xfe\x2b\x7f\xed\x15\xbc\xf4\x13\xad\x3b\x0b\x1f\x96\xcb\x14\x4f\xb5\xa7\x40\x57\x68\x26\xdf\x3f\x0a\xa3\x60\xbc\x1c\x48\x0c\x88\xa9\x94\xac\x40\x99\x63\x48\x65\x76\xed\x6e\x43\x49\xf3\xd7\xf3\xf3\x25\x07\xd2\x11\xf0\x96\x97\x29\x28\x4a\x82\xe8\x3e\x8c\x65\x8e\x5b\xf9\x19\xcd\x0f\x00\xf1\x82\x65\x73\x63\xac\xf0\x2f\x70\x11\x9e\xde\xde\x6a\xe9\xee\x1d\xec\x1a\xad\x3e\xfe\xcc\x79\x62\x55\x25\xc0\x33\xb2\x4e\x72\x6f\x24\x35\xdd\xf0\xab\x32\x73\xe2\xdb\xa0\x71\x5e\x3b\x8c\x65\x7a\x6c\x21\x53\xbe\x27\x3c\x0d\xa9\x60\x47\x59\x9b\x8e\xde\xc1\x86\x65\xbf\xd5\xdf\xaf\x27\x82\x69\x1d\x52\x0b\x88\x7c\x5e\x36\xc7\xdb\xcd\x83\x0c\x77\x6d\x04\x6d\xa2\x2d\xeb\x8c\xa5\x3d\x92\x2c\xc0\x5e\x8e\x46\xf3\xf7\x1a\xc9\x3b\x0c\x5e\x64\x9d\xa0\x90\x99\xa4\x44\xab\xc4\x3a\x8a\xbb\xaf\xde\x67\x94\x30\x61\xc2\xd5\x67\x6e\x80\xd8\x03\xab\x68\x1b\xb0\x89\x1d\x01\x1a\x32\xb4\x3b\x40\xc3\x47\x0b\xf9\x55\xf4\x33\xd1\xa0\x6c\x98\x92\x1d\x5a\xc2\xcb\x8c\xf4\x6e\x70\x80\x98\x68\xc4\xd7\x08\x74\x35\x60\xa7\x81\x59\x64\xab\xf5\x02\x3a\xd1\xe2\x48\xc6\x00\xa9\x85\xa1\x93\xa3\x9e\xae\x63\xcb\x31\x8d\x6e\xc0\x74\xac\x34\x0a\x87\x18\x18\xd7\x05\x61\x89\x75\x5a\xe4\xd4\x99\xf8\xbf\x0e\x10\x3d\x33\x97\xa8\xe0\xe6\xcd\x97\x1e\xdd\xc5\xb2\x13\x72\xa3\x6c\xfa\x44\x03\x9b\xdd\x81\xda\xdb\x90\x76\xa0\x0b\xef\xff\xde\xab\x6e\x26\xb2\xe1\xec\x4e\xd8\xd9\x04\x6c\x0c\x27\x54\x65\x6f\xb3\xf0\xa2\x65\x55\x9b\x36\xcf\xd5\x4a\x8c\x4d\x75\x9b\xde\x86\x12\x9b\x92\xd1\xad\xe0\x0e\x2f\x56\x09\x96\x40\x2e\x05\x3a\x48\x48\xbf\xe2\x6b\xd8\xd7\xc6\x87\xaf\x8d\x4c\x64\x81\x31\x60\xf0\xa8\xdc\xed\xba\x25\xa5\x20\x31\xcd\xca\x4c\xbd\x3b\xc1\x2a\x6e\x98\xe0\xdf\x3a\x31\x5d\x81\x10\x49\x0e\xc9\x6d\x48\x77\x4c\x68\x04\xdf\x33\x51\x83\x8d\x62\xff\xcf\x3f\x3e\xba\x34\x3b\xb9\xc6\xd4\x89\x96\x97\x1e\xe6\x77\x33\xe2\x77\x33\xe2\x77\xf3\x58\x7e\xe3\xda\x18\xf4\xda\x86\x40\xf4\xaa\x82\x9b\x31\xc7\xed\x81\xc1\xd8\xab\x14\x26\x31\x75\x24\xa3\x37\x88\x6e\xe4\x36\x68\x0e\x3c\xe6\xf6\xdb\xc0\xfa\xdd\xc8\x7d\x31\x27\x1e\xb8\xc9\x89\xff\x46\x29\x2c\x50\xe7\xf3\x25\xf5\x80\x5d\xa1\x91\xcb\xb9\x76\xdd\xa1\xd9\x19\x94\x29\x1e\x7c\x32\x09\xa4\xfb\x82\xe7\xde\xfa\x37\x8c\xdc\x36\xad\xb8\x4c\xe2\x62\xe8\x27\xf4\xc3\xd0\x1e\xc7\xb7\xc6\xd3\xcf\x58\x51\xbd\xd6\xd6\x3d\x36\x57\x6b\x4a\x9a\x22\xfe\xc3\xba\xc9\x34\xab\x11\x4e\x35\x9c\xd9\xfa\x4c\x6c\x6a\xbb\x1e\x1e\xe9\x33\xa0\xd3\xd4\xc1\x3a\x1d\x63\xb5\x34\xca\x8d\xa9\xae\x83\x60\x7b\x88\x55\xe4\x62\xdb\x8f\xc1\x18\x50\x1e\x4f\x81\xf9\x52\x65\x6e\xa7\x01\x72\xc3\x31\x80\x5b\x1a\x19\x3f\xc9\x85\xdb\xa0\x9a\xbe\x07\xdf\x91\xe7\xcf\x05\x94\xc4\x77\xdd\xc5\x0b\x52\x02\x59\xbf\xb0\x8c\x7f\x1f\xe1\x9f\xa4\x02\xb2\xd4\x98\xcc\x73\x97\x61\xb1\x80\x91\x27\x36\x2b\x97\xa1\x97\x4b\xc5\xbf\xa1\x0a\x26\xa6\x89\xca\x5c\xda\xb1\xe1\xaa\x5a\x08\x00\x93\x63\x0d\xc0\x9f\xc5\x9d\xcf\xc8\xcc\xbd\xbb\xad\x71\x2b\xa4\x75\x15\x21\xa7\xf7\xc3\x7c\xc1\xe8\x5a\xda\xc5\x35\x35\x8d\x8b\x05\xd3\x4f\x27\xc5\xca\x0c\x5a\xd2\x47\x64\xbb\x5b\x75\x86\xd8\x97\x5e\xcd\x6f\x9d\xf6\x75\x75\xd5\x25\x28\xac\x7b\x9d\x4f\x5f\xd6\x5a\xd7\xc5\x05\xf2\xbe\xc8\xbe\xda\x09\xf1\x89\xdd\x68\x5d\xd9\xfa\x07\x1a\xb8\x40\x6c\xda\x99\x90\xf2\x02\xb0\x9d\x43\x33\x57\x11\x02\x3b\x90\xf3\xf9\x0e\x87\xef\x80\x67\xb9\x71\xcd\xe5\x43\x00\x8e\xcc\x05\x7b\xbb\xd1\x77\xd8\x60\x73\x99\x13\x78\x8b\x19\x85\x2d\xaa\x9c\x13\x7f\x3a\x61\xea\x18\xfb\x71\xe0\xbc\x6c\xe4\x95\xd3\x18\xb6\x7f\x1f\x3e\xff\xfe\x1b\xb6\x5e\x15\x16\x56\xf4\x75\x66\x8b\xed\xf5\xd4\x0b\x2e\x61\xcd\x84\x68\x62\xf5\x2f\x8d\x61\x89\x42\x06\xfb\x42\xa3\x6a\x78\x5c\x88\x37\x5b\x63\xd0\xa5\x58\x47\xd6\xfc\x09\x03\xa3\x8b\x2c\xa7\xce\xa7\x9e\xf7\x1f\xf9\x53\x88\x98\x25\xb7\x2e\xa4\x1f\xc8\x9a\xb6\x1f\x1a\x64\xce\xe6\x25\x2f\xa9\xe7\x6a\xdd\xe7\xcd\xcd\xba\x4f\x9c\xc4\xf3\x66\xed\xd3\x6c\x32\x6c\xab\x86\xf5\x6e\x27\x25\xd2\x44\x84\x17\xcb\xbb\x3e\x39\x5c\xde\xae\x77\xb0\x96\xe0\x45\x6e\x57\x0b\x2d\xa7\x25\x92\x3c\x4b\x99\xce\x5f\xe3\xa7\x19\x76\x81\x4c\x25\xb9\xab\x1f\x4d\x03\xa8\x79\x89\x4d\xe1\x07\x56\xd6\xb6\x40\x5e\xad\x37\xaf\x3a\xda\xbf\x2a\x8e\xe8\xa5\x95\x9a\x6a\xcf\xa4\xc0\xf8\x6e\x54\xda\x2a\xca\xa2\x97\xad\x90\x96\xb5\x42\x3c\x79\x91\xa1\x56\x46\x5b\x21\x2c\x8d\x75\xec\x63\x4b\x83\x9f\x41\x26\x88\xf1\xe3\xc1\xb5\xfb\xd1\x0d\x37\xef\xea\x78\xf8\xe2\xbf\x2a\x60\x06\x52\x12\x1f\x67\xaa\x0f\x87\xc3\xfc\xda\x9f\x98\x31\x39\x67\x9a\x7c\xfc\xe7\xef\xd4\xdc\xc2\x10\xab\xf7\x9b\x0b\xf3\x58\xf6\xdd\x57\x03\x3a\x80\xfb\x1a\xfe\x37\x00\x00\xff\xff\x45\xa4\x57\x09\x25\x0f\x00\x00") func besticonIconserverAssetsIconsHtmlBytes() ([]byte, error) { return bindataRead( @@ -194,12 +196,12 @@ func besticonIconserverAssetsIconsHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/icons.html", size: 3415, mode: os.FileMode(420), modTime: time.Unix(1444631066, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/icons.html", size: 3877, mode: os.FileMode(420), modTime: time.Unix(1448303138, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _besticonIconserverAssetsIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xec\x5a\xef\x6e\xdb\x38\x12\xff\xde\xa7\xe0\x6a\x71\xcd\x97\xca\xb2\xe3\x38\x69\x5c\xdb\x45\xd0\xdb\xfe\x39\xec\x02\xc5\x36\x40\x3f\x1c\x0e\x05\x25\x8d\x24\xc2\x94\xa8\x25\xa9\x38\xbe\xc5\x02\x7d\x8d\x03\xee\xde\xe4\xbe\xdd\x9b\xf4\x49\x6e\x86\x92\x12\x49\x76\xd2\xa4\xcd\xee\x1e\x0e\xdb\x0f\xb1\x44\x91\xc3\xf9\xfb\x1b\xce\xb0\x8b\x6f\x62\x15\xd9\x6d\x09\x2c\xb3\xb9\x5c\x3d\x5a\xd4\x3f\x8c\x2d\x32\xe0\x31\x3d\xe0\x63\x0e\x96\xb3\x28\xe3\xda\x80\x5d\x7a\x95\x4d\xfc\xa7\x5e\xf7\x53\xc1\x73\x58\x7a\x17\x02\x36\xa5\xd2\xd6\x63\x91\x2a\x2c\x14\x38\x75\x23\x62\x9b\x2d\x63\xb8\x10\x11\xf8\xee\xe5\x09\x13\x85\xb0\x82\x4b\xdf\x44\x5c\xc2\x72\x32\x1a\xef\x21\x15\x83\x89\xb4\x28\xad\x50\x45\x87\xda\x19\x33\xa0\x89\x14\x4b\x44\x11\x8b\x22\x65\x02\xbf\x19\xa6\x0a\xb6\x81\x90\x19\x61\xc1\x20\xb1\x9a\x9a\x15\x56\xc2\xea\x3c\x03\xf6\x92\x5f\xd0\x3c\xf6\x12\x17\x81\x5e\x04\xf5\x97\x66\x9a\x14\xc5\x9a\x69\x90\x4b\xcf\xd8\xad\x04\x93\x01\xa0\x00\x99\x86\x64\xe9\x8d\x82\xb2\xd2\xe0\x8f\x47\xb3\xd1\xd8\xcf\x45\x31\x8a\x8c\x69\x99\xbd\x7d\x5d\xaa\x45\x6c\x7c\x0d\xa6\x44\xfe\xc4\xc5\x17\xd1\xc8\xb9\x28\x3a\x2b\x3a\x3a\x2a\xb5\x2a\x41\xdb\xed\xd2\x53\xe9\xdc\x49\xe3\xb1\xfa\xdf\x95\xaa\x76\xe5\xf6\x58\xb0\xba\x89\xc6\x57\xa8\xfb\x16\xaa\x22\xe7\xe9\x2e\x67\x99\xb5\xe5\x3c\x08\x1c\xa9\x51\x08\xd6\x82\xf6\x45\x0c\x7c\xa4\x74\x1a\xf0\xb2\x94\xe0\x5b\x55\x45\x99\x4f\x33\x46\x65\x91\xba\x2d\x86\x0a\xa3\x8f\xad\xaa\x82\xa4\x16\x74\x84\x7f\x76\x55\x3b\x24\x79\xb5\x6a\xef\x5e\xce\xf3\x83\xda\xf5\xe9\x31\x54\xf1\xb6\x21\x19\x8b\x0b\x26\xe2\xa5\x27\xf9\x56\x55\xb6\xb5\x48\xe7\x03\x19\xac\xd9\xff\x6a\x3c\x92\xdc\x18\x14\x1a\x09\xa2\x09\xae\x3f\xf6\x3f\xd7\x36\xec\x7e\xa5\xf8\x9b\xac\x16\xbc\x65\xd6\xbb\xa2\xa4\x72\x20\xe1\xbc\x3d\xae\xdd\x5b\xef\x68\x88\x3c\x6d\x17\x4a\x95\x2a\x8f\x19\x1d\x91\x6f\x39\x79\xcd\x05\xea\x96\x4b\xbb\x3c\x78\x87\xa6\x64\x34\xe1\x60\xb5\x08\xf8\x80\x8f\x00\x19\xe9\xf2\x1d\x20\xe3\xbd\x81\xec\x70\x75\x17\x57\x41\x42\x87\x1d\xed\xd4\x64\xf6\x6a\xab\xf1\x15\x6f\xb0\xcb\xe0\xb3\x6f\xaa\x90\xf4\xea\xad\xde\x67\xdc\xb2\x37\x86\x9d\x67\xc2\xb0\xb3\x10\xad\xf3\xbc\xbf\x19\x2e\x2f\xbb\x6f\xef\x5b\x9e\x58\x65\x20\x66\x56\xb1\x8c\x5f\x00\xe3\x6c\x11\xa9\x18\xae\xd5\xde\xf8\x2a\x14\xa3\x8d\x58\x8b\x12\x62\x51\xbb\x29\xbd\x05\x8d\xee\xbd\x55\xc7\xfd\x48\x7b\x8b\xc0\x11\x61\x8f\x63\x6e\xb2\x67\x4c\x69\x56\x28\x3b\xea\xee\x2e\x6c\xc6\x2c\x5a\x4f\x14\x56\xab\xb8\x8a\x28\xee\x98\x4a\xdc\xd8\x1e\x0e\x0c\xb2\x80\x10\x0a\x92\x62\x6b\xe4\xdc\x76\x14\xa9\x3c\x90\x22\xd4\x5c\x6f\x03\xa1\x4c\x80\x20\x5e\xe5\xa8\x14\x4e\xb4\x82\x33\x9a\x43\x7f\x44\xe4\x06\x4c\xf0\x23\x24\xa0\xa1\x88\x20\x78\xc7\x13\xae\x05\x6a\xe0\x45\xad\xc6\x00\x7f\x13\x91\x56\x1a\xad\x86\xa3\xbd\x55\x37\x7f\x1a\x51\x9a\xf0\x56\xfb\x62\xa8\xab\x83\xd6\x1b\x3e\x7d\xfc\x27\x0a\xf7\xe9\xe3\xbf\x9c\x5f\xb0\x04\x95\xc2\x9d\x05\x58\x08\x11\x22\x3e\xcb\x95\x06\xc4\x88\xbc\xde\x01\xe2\xae\xbe\x9c\x59\xbb\xfe\x65\xd0\x6b\x25\x6a\x4b\x19\x7c\xaf\x95\x8f\x43\x45\xcc\x0c\x66\x1f\x43\x6a\xcc\x59\xb8\x45\xfa\x7f\x87\x51\xcf\x73\xcb\x8e\xc3\xdd\xee\x52\x14\x50\xec\x0d\x11\xae\x3d\xa9\xbb\x0c\xb9\xcf\x19\x77\x56\xc3\xc8\x74\xbb\x7f\x8b\x50\x5f\x49\x04\x6f\x44\xc1\x4c\x21\x16\xbc\xfa\xee\xfc\x2a\x64\x5d\x12\x71\x8b\xdc\x53\x3a\x0c\xf4\x8e\xe7\xbb\x09\x95\x3f\x61\xcd\x83\xc9\xfd\xa9\x3f\x6b\xdf\x64\xda\x7d\xbb\x94\xf4\x36\x20\xd6\x27\x27\x75\x49\xc2\xec\xc1\x85\xa2\xac\x6c\x93\x6b\x2b\x2d\xfb\xac\xba\x8f\xfe\xc4\x63\x74\x2c\x40\x70\x82\x4b\x14\xac\x94\x3c\x82\x4c\x49\x84\x99\xa5\x47\xf1\x43\x98\x81\xf0\x51\x59\xe5\xcc\x06\x16\xa7\xaa\x24\x69\x87\xb4\x86\xc8\xd6\x23\x3b\xdb\xbb\x19\xbc\x14\x96\x4b\x34\x51\xb3\xcc\x94\x20\x65\x94\x41\xb4\x5e\x7a\x09\x97\x66\x88\x87\x7b\x90\x67\xff\xd0\xed\xea\x9c\xf4\xd4\x39\xe9\xa9\x73\xf2\xa5\xea\x0c\x2b\x6b\xd1\xad\x6b\x7d\xa1\x0f\xe5\xc2\xf6\x55\xda\x4c\xe8\x3c\xfb\xa5\xc6\xfc\xa8\xb7\xac\xa7\xf2\xd5\x2b\x84\x90\x7a\xc2\x97\x48\xbf\x08\xc8\xcd\x6e\xca\x32\x70\xc9\xc9\x50\x03\x01\xbe\xab\x47\xcd\xbc\x4f\xfa\x2a\xf3\x38\xff\x7e\x8e\x4e\xb2\x4c\x11\xb7\xaa\x90\xa0\xa7\x75\xf7\xd5\xf5\x10\x45\xfd\x93\xcf\x92\x10\x85\xb1\x3c\xd5\x3c\xef\x51\xe9\x8d\x0e\x12\xd0\x30\x4f\xdc\x1e\xb6\xaf\xcf\xcf\xdf\xb2\xb3\xb7\x6f\x6e\x87\x7f\xca\x9c\x38\x89\x45\x04\x23\xdc\x76\xe7\xf5\xd1\x17\xcf\x08\xa2\xe1\xbe\xd4\x78\x54\xd9\x2e\xb7\x60\x1e\xa3\xbe\x9e\x91\x30\xc8\x74\xb4\x56\x17\xa0\x13\xa9\x36\xc4\xba\xb7\xba\xf5\x70\xb3\xd8\x84\x7a\x75\x45\xb1\x03\x93\x1d\x06\x4c\x55\x96\x0e\xc4\x42\x85\x49\x42\x0a\x63\x09\x3e\x89\xcf\x6b\x94\xd3\x98\x87\x28\xba\x28\x6b\x60\xea\xa2\xac\x21\xb9\x4e\xc1\x58\x37\xe9\x76\xc8\x9b\xae\x1a\x83\xcf\xd9\x19\x52\x6d\x21\x6e\x7a\xb3\xb6\x16\x43\x1e\x19\x43\x74\x63\xbf\x89\x92\x9e\xbb\xd7\xbd\x74\x76\xfc\x64\xc8\xe6\x8e\xec\xdf\xf8\x3e\x7b\x7d\xfe\xc3\xf7\x2c\x85\x02\x34\x65\x19\x4c\xff\xa4\xde\x4c\x48\x04\xb3\x11\xa6\x21\xdf\x5f\xb9\x88\x71\xe7\xf1\xa5\x17\xe2\x9e\xa9\x56\x55\x11\xcf\xd9\xb7\x89\xfb\x87\x09\xbd\x61\x62\x4e\x30\xf6\xcc\x15\x35\xf5\x63\xa8\x34\xa2\xe3\xdc\x28\x29\x62\x86\xee\xbc\x6d\x46\xea\xc2\x67\x3e\x9a\x60\x5a\xea\xfc\x99\x42\xfe\x0c\xf1\x84\xf2\xe3\x7c\x74\x48\x23\xc7\x38\xe2\xad\x16\xa8\xc5\x96\x01\x44\x88\x54\x14\x73\x36\x7e\x86\xbe\x50\x80\x9f\x81\x48\x33\x3b\x67\x93\xc9\xf8\x4f\x14\xc7\x3f\x93\x7c\x0b\x53\xf2\xa2\x5d\x91\x60\x48\xf8\x9b\x66\x5a\x88\x78\xed\xad\x1e\xff\x54\x29\x4b\xc6\xa8\x1f\x16\x01\xcd\x5f\xcd\xf7\xac\x73\xcf\x73\xe6\x80\x39\x6a\x17\xee\x68\xbe\x47\xe6\xc9\xdd\x39\x70\x16\x1d\xf0\xf0\xd7\xda\x40\x3f\xb7\x76\xfa\x95\x65\x69\x5c\x6f\x47\xa4\xbd\xc5\xc0\xae\x9c\x77\xe7\xd0\x99\x7c\xc0\xe3\x64\xf6\xf4\x9e\x54\x6a\x73\x7f\x35\x19\x4a\x0a\x7c\x48\xe6\x8e\x1a\xfb\x4a\x3d\x84\x5b\x3c\x65\x0f\x76\x9e\x9e\x4c\xa7\xf7\x24\x03\x5a\x2b\xfd\x59\x01\xfa\x2b\x8b\x4a\xca\x2f\x63\xda\x64\x7c\x62\xaa\xfc\xcb\x14\x76\x34\x49\x8e\x61\x32\xc5\x7a\xef\xf8\xf4\xf0\x64\x3a\x9b\x9d\x4e\x42\x0e\x27\x70\x72\x72\x74\x9c\x24\x11\x9c\x8e\x23\x38\x99\x1d\x26\x3d\xea\x35\x7f\xbf\x3c\xf9\x5d\xa2\x21\x8a\xb1\x16\x34\x54\x3a\x44\xa3\x02\x6c\x3f\x3a\x02\x2c\x21\xbb\x05\xf6\xf3\x8b\xe5\x78\xfa\xf4\xf8\xf0\xf0\x78\x32\x7e\x3a\x1d\x3f\x74\x8c\x4c\x0f\x1f\x22\x44\xee\x4d\xe5\x6b\x22\x04\x95\xf2\xd0\x11\x32\x3b\x9a\x8e\xff\x7f\x23\xa4\xeb\x3f\xa7\x13\xac\xff\xc2\x93\x69\x34\x1b\xc3\x2c\x3e\x0d\x4f\xa3\xf1\xf1\xf8\xf0\x68\x96\xc4\xd3\xd9\xff\x4e\x84\xec\xe6\x8b\x4e\x44\xfc\x11\x02\x7f\x84\xc0\x6f\x19\x02\xf4\xf3\xb7\x47\xf5\x6f\xcb\x71\x80\x67\xc6\xd5\xbe\x52\xa9\x73\xdc\xff\xb1\x29\x1b\x86\xa7\xfd\x97\xd4\x8c\xc1\xf3\x6b\x4e\x09\xe0\x73\xc5\x05\xc3\x83\x12\x60\x0d\x72\xdd\xaa\x12\x1f\x78\xfe\x21\x01\x6a\x4a\xa6\x1f\x64\x15\xad\xdd\xf9\xbf\x6d\x00\x95\x1c\xcb\x3a\xc0\x13\xfe\xe8\x21\xea\x8b\xbd\x85\x80\x2b\x35\xf6\x73\xb1\x53\xab\x3f\x50\xe9\x41\x5f\x6e\xd9\xf6\xfe\xa5\x09\xd9\x89\xbc\x77\xa7\x14\xab\x47\x19\xc7\x92\x00\x6b\xab\x4a\x17\x58\xb4\x6c\xa8\x7f\x48\xf9\xba\x32\x8d\xf2\x8e\xc6\x47\xad\xc2\xa9\x40\x44\x0f\xac\xc7\x5d\x44\x5c\xf7\xe2\x40\xc6\x4c\x14\xce\x76\xcd\xd5\x04\x3c\x88\x59\xf6\x94\x7d\xa1\x56\x6b\x28\xfc\xa6\xe5\x50\xd7\x7d\x0f\x61\x8b\x5d\xba\xbf\x56\x1d\xf8\xe8\x77\x2f\x04\x1f\xdd\xa9\x12\x1c\xbb\x4a\xf0\x1e\x85\xe0\xdd\x60\x72\x2f\x6c\xbd\x02\xdb\x9a\x6d\xd7\x10\x73\x16\x0b\x2e\x99\x8d\xca\x39\x93\x4a\xad\xab\x92\xed\x9b\x54\x28\x66\xb0\xca\x62\x99\x32\xfd\x6c\xf3\xe8\x97\x9b\x61\xec\xe6\x8e\xcf\x9f\x85\xc1\x4f\x22\x07\xcd\x9c\xf3\xb1\x77\x20\x13\x9f\x88\x0b\x6a\x45\xdf\xd6\x06\xa2\x06\x50\xf1\xe9\xe3\x3f\x2c\x4b\x2b\x84\x29\x24\x0c\x18\x1b\x9d\x5e\xf3\x46\x48\x89\x4a\xa1\xbf\x21\x86\x4c\x55\x14\xee\x66\xa3\x40\xa5\xb3\x2d\x70\x8c\xcb\x44\xab\x1c\x25\xda\x30\x9f\x19\x85\x38\x87\x7c\x18\xb6\x55\xd5\xc1\x05\xb0\x54\x59\x42\xd0\x1c\xdd\x84\x7d\xa6\x2b\x33\xe8\x4e\x71\xcb\x0c\x17\xf1\x13\x26\x12\x22\xc6\x36\xc8\x1b\x91\x42\x0e\x6a\x06\x11\x87\x71\x5c\x33\xb5\x29\x58\xce\xa3\x0c\x1d\xc2\x6d\x4b\x02\x31\xd2\x8b\xf3\x4d\x5c\xd2\xdd\x64\x78\xa5\x70\xdd\xbb\x0b\x10\xfa\x83\x10\x21\xbe\xbe\xcf\x68\x9f\x68\x9b\x57\xc2\xbe\xae\x42\x8a\x31\xb6\xc9\x00\xdd\xb1\xdd\x85\xfa\xf0\xdd\xbe\x15\xb2\x13\x51\x07\x3f\x06\x07\x41\xd4\xd2\xd3\xf5\xcd\x86\x63\x37\x43\x1d\xa1\x04\xae\xd3\x47\x4d\x37\x6a\x63\x55\x35\x14\x91\xb6\x41\xa3\xb0\xf6\xc0\xb0\x9f\x2a\xba\x14\x00\x6e\xb6\x77\x57\xd8\x5b\x89\xf3\x81\x11\x0c\xa3\x41\xc8\x88\xea\xce\xd2\x06\xc2\x98\x0a\x4c\x50\xc0\xc6\x5b\x29\x4c\x6d\x04\x9e\x6e\x6c\x80\x2b\x4e\xa1\x68\x98\x5a\x21\xad\x65\x32\x97\x0e\x69\x43\x63\xab\x3c\x94\xc0\xaa\x52\x39\x1a\x2e\xca\xd8\xf5\x3d\x87\x25\xab\xc6\x0a\xed\x54\xa0\x5f\x6c\x94\x5e\x33\x6e\x18\x5c\x96\x98\x6b\xfb\xd7\x1d\xf7\xb9\xa6\x38\x8b\xd6\xe8\x7d\x12\xe2\x94\x2e\x7f\xcc\xd0\xdf\x31\xb5\xdb\xaa\x40\x84\x93\xdb\xc6\xb3\x89\x15\xfc\xe5\xc4\x2a\x79\x14\x7d\x41\x86\x0d\xa0\x78\x18\xbc\x68\x55\x60\xa5\x80\x08\xf9\x54\x49\xcd\xa6\xf3\x71\x85\x96\xd2\x66\xc4\xde\x1c\xc4\x88\x3f\x6b\xa8\xcf\x06\xbc\x58\x77\x19\xad\xe4\xa0\x3f\x2d\x85\xbb\xa5\x8c\x34\x70\x4b\x69\xac\xb9\xe3\x8a\x31\x5f\x22\x2c\x25\x78\xf6\xda\xb2\xe1\x65\x1b\xf5\xc3\x23\x63\x46\x42\x05\xde\xca\xcd\xab\x41\x8c\xbd\xc5\x0f\xec\xc5\xbb\x77\xc8\x10\x1e\x29\x88\xb5\xba\x85\x8a\x9b\xec\xec\xfa\x12\xdd\xa0\x14\x6b\x77\xd1\xa4\x92\x04\xe8\x06\xab\xd6\xc0\x70\x3b\x23\x2e\x35\x5c\x08\xe3\x2e\xb5\xdc\xc9\x1e\x97\x86\x02\x5d\xc2\x65\x1e\xf7\xea\x3a\x42\xc6\x47\xa8\x1d\x07\x14\x1e\x08\xf2\x02\x99\xaf\x0f\x44\x06\xec\xcd\x7c\x9c\x49\xe1\x78\xc8\x40\x96\xc4\x42\x0e\x75\xf6\x76\xb7\x7f\xb8\x7a\xb8\x6a\x11\x74\x75\xd8\xeb\xef\x77\x5e\xba\x08\xd9\x6d\xf0\x27\x4a\x61\x12\x65\xd2\x0f\xd5\xe5\x55\xba\xbd\x8e\x95\x56\xf4\x83\xdb\x32\xef\xc1\xde\xff\x32\xc1\xaf\xae\x33\x05\x49\xcc\x35\x02\x38\xc9\x55\x37\xa5\x31\x79\x62\xec\xff\x85\x17\x15\x5d\x68\x1c\x8e\x27\xb3\xd6\x9f\xdf\x6b\x81\xd4\x0b\x5a\x35\xdc\x3d\x55\x92\x17\x69\xbd\xe5\x2b\xd5\xbd\x3e\x68\xb0\x44\x15\xf7\xc0\xac\x6b\x9c\x6a\xb7\x7e\x41\x4e\x87\xa9\x3d\xdc\xee\x6c\xbd\xd9\x6c\x76\xc5\xfe\x81\x5b\x74\x10\x8c\xc9\xef\xff\xf3\xef\xd8\xae\xa1\x4b\xcb\x85\x64\x5f\xf3\x8b\xa0\xfe\xaf\x01\x18\x72\xee\x3f\xcc\xfc\x37\x00\x00\xff\xff\x29\x7c\xdb\xd8\x48\x23\x00\x00") +var _besticonIconserverAssetsIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xa4\x58\xcd\x8e\xdb\xc8\x11\xbe\xfb\x29\x3a\x0c\xe0\xb9\x98\xe4\xc8\x81\x81\xc0\x2b\x69\x31\x70\xd6\xce\x04\x1b\xc0\xd8\x71\x60\xe4\xd8\x24\x4b\x64\x47\x4d\x36\xd3\xdd\x94\x46\x39\xf9\x35\x02\x24\x6f\x92\x5b\xde\xc4\x4f\x92\xaf\x9a\xa2\x86\xa4\x64\xad\xed\xf8\x20\x93\xfd\x53\xbf\x5f\x55\x7d\x9c\xe5\x6f\x0a\x93\xfb\x43\x4b\xa2\xf2\xb5\x5e\x3f\x5b\xf6\xff\x09\xb1\xac\x48\x16\xfc\x80\xc7\x9a\xbc\x14\x79\x25\xad\x23\xbf\x8a\x3a\xbf\x89\x7f\x1f\x8d\xb7\x1a\x59\xd3\x2a\xda\x29\xda\xb7\xc6\xfa\x48\xe4\xa6\xf1\xd4\xe0\xe8\x5e\x15\xbe\x5a\x15\xb4\x53\x39\xc5\xe1\xe5\x85\x50\x8d\xf2\x4a\xea\xd8\xe5\x52\xd3\x6a\x91\xdc\x5e\x10\x55\x90\xcb\xad\x6a\xbd\x32\xcd\x48\xda\x9d\x70\x64\x59\x94\xd8\xa8\xa6\x50\x4d\x29\x14\xf6\x9c\x30\x8d\xd8\x53\x26\x9c\xf2\xe4\x20\xac\x97\xe6\x95\xd7\xb4\xfe\x50\x91\x78\x2b\x77\x7c\x4e\xbc\xc5\x25\xb2\xcb\xb4\xdf\x39\x1e\xd3\xaa\xd9\x0a\x4b\x7a\x15\x39\x7f\xd0\xe4\x2a\x22\x38\x50\x59\xda\xac\xa2\x24\x6d\x3b\x4b\xf1\x6d\xf2\x2a\xb9\x8d\x6b\xd5\x24\xb9\x73\x83\xb1\xd7\xef\x95\x56\x15\x2e\xb6\xe4\x5a\xd8\xa7\x76\xdf\x25\xa3\x96\xaa\x19\xdd\x18\xc5\xa8\xb5\xa6\x25\xeb\x0f\xab\xc8\x94\xaf\x83\x37\x91\xe8\xff\x9d\x42\x75\xee\x77\x24\xd2\xf5\x97\x64\xfc\x1f\xe1\xbe\x22\x55\xd5\xb2\x3c\xb7\xac\xf2\xbe\x7d\x9d\xa6\x41\x54\x92\x91\xf7\x64\x63\x55\x90\x4c\x8c\x2d\x53\xd9\xb6\x9a\x62\x6f\xba\xbc\x8a\xf9\x44\xd2\x36\x65\x50\x31\x0f\x18\x6f\x0e\xa1\x4a\x37\xbd\xa3\x09\x7e\xce\x43\x3b\x17\x79\xba\x75\x51\x57\x40\x7e\xda\x43\x9f\x1f\x33\x53\x1c\x8e\x22\x0b\xb5\x13\xaa\x58\x45\x5a\x1e\x4c\xe7\x87\x8c\x8c\x36\x38\x61\x47\xfd\xa7\xf5\x5c\x4b\xe7\xe0\x34\x04\x22\x05\x4f\x9b\xd3\xed\x3e\x87\xe3\x5d\xae\xbf\xc5\x7a\x29\x07\x63\xa3\x93\x24\x53\x13\x3b\x17\x5d\x80\xf6\xe4\x7e\x90\xa1\xea\x72\xb8\xa8\x4d\x69\x22\xe1\x6c\xce\xd8\x0a\xfe\xba\x1d\x62\x2b\xb5\x5f\xdd\x3c\x20\x95\x82\x0f\xdc\xac\x97\xa9\x9c\xd9\x91\xc2\x90\xb1\xdd\x29\x0c\x9f\x2c\x54\x2f\xd7\x5f\x03\x15\x08\x7a\x39\x8a\x4e\x2f\xe6\x62\xb4\x8e\x58\x89\x66\x5a\x66\xdb\xb1\xeb\x32\x8e\x6b\xb4\xfe\x58\x49\x2f\xee\x9d\xf8\x50\x29\x27\xee\x32\x64\xe7\xc7\xa9\x32\x5c\x6f\xc7\x6f\x1f\x07\x9b\x44\xe7\xa8\x10\xde\x88\x4a\xee\x48\x48\xb1\xcc\x4d\x41\x4f\x61\x3f\x62\x95\x9a\x64\xaf\xb6\xaa\xa5\x42\xf5\x30\xe5\xb7\xf4\x18\xfb\x68\x3d\x82\x1f\x47\x6f\x99\x06\x21\x2f\x84\xb1\xa2\x31\x3e\x19\xeb\x55\xbe\x12\x1e\x79\x53\x8d\xb7\xa6\xe8\x72\xae\x38\x61\x36\x61\xed\x82\x6e\x07\xe5\x68\x9e\xa4\xb9\xaa\x92\x00\xd8\x24\x37\x75\xaa\x55\x66\xa5\x3d\xa4\xca\xb8\x14\xed\xbb\xab\x11\x0e\xc9\xb2\xd2\x3b\x3e\xc3\x3f\x2a\x0f\x0b\x2e\xfd\x85\x36\x64\xa9\xc9\x29\x7d\x90\x1b\x69\x15\x7c\x7f\xd3\x07\x30\xc5\xff\x1b\x55\x76\x16\xf9\xc2\xea\xe4\xd6\x97\xb7\x12\x1e\x10\xd1\xfa\x52\xf5\x8c\xbc\x3f\xe1\xe0\xf3\xa7\x7f\xc1\xb9\xcf\x9f\xfe\x1d\x10\x21\x36\x08\x8a\x0c\xb1\x17\x19\xe5\xe8\xf5\xa2\x36\x96\xd0\x1d\xea\x5e\x03\x15\xe3\x78\x85\x84\x8e\x91\xe5\x84\x6c\x0a\xf1\xbc\x2e\xa4\xab\x7e\x10\x6a\x23\x1a\xca\xc9\x39\xc4\xe2\xb4\x58\x52\x43\x56\x72\x6e\x7b\x08\xb2\xc6\x13\x06\x93\x09\x90\xdb\x11\xfe\xae\x23\x8c\xeb\x4b\xdc\x63\xb9\xc7\xd5\xf8\x16\xe4\xd7\x42\x86\x4c\xa2\x4e\x83\xce\xdf\xa2\xf1\x77\x1a\xad\x1c\x3d\xb1\x32\xe8\x0c\xef\x7e\xfa\x70\x2a\xe0\x30\x52\xc2\xa5\xf0\x54\xce\xcb\x7e\x54\x07\xe1\x40\x17\x2f\xc4\xf1\xc1\xd5\xf1\xef\xe2\x57\xc3\x9b\x2e\xc7\x6f\x8f\x9a\xdf\x66\xc2\xa6\xe2\xb4\x6d\xd9\x97\x0b\x5d\xa2\x69\x3b\x7f\x9c\xbc\x9d\xd5\x53\x53\xc3\x66\xbc\x88\x04\x93\x04\xb4\x2a\x7a\x84\x63\xad\x96\x39\x55\x46\xa3\xe9\xac\x22\xae\x26\xee\x20\x68\x26\x9d\x37\x21\x95\xe4\x71\xd4\x6c\x36\xc3\x92\xb5\x94\xfb\x7e\xe5\x4c\x7d\x38\x21\x5b\xe5\xa5\x56\xff\x18\xae\xb9\x96\xb4\xce\x2b\xca\xb7\xab\x68\x23\xb5\x9b\x77\xc7\x0b\x7d\xe8\xf2\xd2\xf5\x70\x2e\x26\xe1\x5c\x4c\xc2\xb9\xf8\xde\x70\x66\x9d\xf7\x80\x7a\x1f\x2f\x40\xa8\x56\x7e\x1a\xd2\xe3\x81\xd1\x73\xdc\x5a\x4c\x4b\xa0\x78\x12\xf2\xf5\x3b\x34\x94\xfe\xc0\xf7\x78\xbf\x4c\x19\x66\x5f\x9a\x39\xf4\x28\x39\x51\x33\x07\x7e\xea\x57\xdd\xeb\xa9\xe8\xd3\x1c\x0a\xf8\xfe\x11\x20\x59\x95\xe8\x65\x5d\xc6\xed\x68\x80\xfb\xfa\x69\x89\x3b\xc1\x8b\x5f\x15\x71\x20\xdd\x4e\x04\x0c\x0b\xd7\xae\xb7\xa6\xed\xb4\xc4\x2c\x7d\xdf\x3f\x04\xe8\xb9\xd9\xd8\x9a\x4f\x97\xeb\xd5\xfd\x97\x5f\x7e\x16\x77\xef\xef\xcf\x6a\xfb\xaf\xa6\x13\xb9\x6c\xc4\xdf\x3a\xe7\x45\x60\x14\x98\x14\x78\x0f\x9d\xac\x73\xdc\xde\xb8\x71\x5b\xfa\x7b\xa7\x2c\xe6\x48\xdf\xc1\xe1\xd9\xd0\x04\xb9\x59\xf5\x8b\x0e\xd0\x1e\x56\x5b\x69\x51\x6a\xe0\x3d\x93\x28\x4f\x27\x54\x7f\xeb\x72\x08\x58\xfd\x2c\x05\xcf\x91\xb5\x1f\x58\xc7\x6a\xf1\xf2\xf6\x0c\x93\x57\x29\xd7\x72\x9f\xd9\x75\x10\x19\x9e\xa6\x72\xc3\xd2\x44\xf8\x59\xa0\xe7\x86\x86\xb6\xfa\xf4\x1a\x3a\x67\xe8\xf1\x05\x08\xa2\xd2\x08\x93\x6a\x18\x97\x61\x9a\xe0\xb9\x9f\x7d\xf3\xa9\xf7\x64\x02\x78\xb0\x4f\x33\x72\x9e\x6d\x4c\x33\x6d\x32\xac\x38\xb8\x80\xc9\x26\x8b\x9a\x12\xd4\xcd\xb6\x30\x7b\x0c\xe2\x7e\x81\x49\xc7\x3b\xe5\xff\xd8\x65\x6c\x6b\xf2\xec\x6b\x51\xf0\x07\xe5\xb0\xa5\x6a\xb2\x22\x78\x2c\x1e\x48\x6f\xe2\xca\x40\x33\x8f\xb6\x6b\x7c\xe2\x9e\x61\xf2\xf9\xd3\x3f\xbd\x28\x3b\x24\x17\x82\x09\x6e\x8d\x66\xd7\x5e\x69\x2d\x20\x08\xbf\x19\x00\xd3\x35\x4d\xe0\x48\x8d\x58\xdc\x8a\x03\xe1\xbb\x4a\x6c\xac\xa9\x41\x17\xf6\x22\x16\x0e\x14\xcf\xc3\x0e\x27\x40\x34\x6f\xc0\x4b\x4a\xe3\x19\x79\xb5\xd9\xb1\x73\x57\x67\xd8\xc4\xac\x0f\xcc\x8b\x9c\x54\xc5\x0b\x1e\x95\x10\x26\xf6\xb0\x8d\x45\xc1\x82\xde\x40\xc4\x0a\xeb\x56\x20\x7e\xa2\x96\x79\xa5\x9a\x5e\x6d\xc0\x3d\xc7\x45\x40\xa9\xc5\x95\x67\x17\x80\xf8\x2b\xc9\x8a\xd6\xc3\xd3\x34\x25\x62\x5f\x81\x91\x9c\xb4\xf0\x5c\x1f\x49\x77\x30\x27\x67\x46\x50\x50\xa8\x1f\xd5\x38\x6f\x7b\xa6\x14\xcc\xad\x10\x23\x78\xc0\xcb\x12\xe1\xe4\x23\xbd\x37\x14\xa2\x4d\x16\xce\xfa\x1b\x27\x50\x93\x20\x19\x24\xdd\xe1\xeb\x03\xf6\x5e\xe3\x3c\x98\x06\x91\x46\x42\x38\x89\xe6\xeb\xa1\xa9\x9c\xeb\xc8\xa5\x0d\xed\xa3\x35\xf8\x5a\x13\x3a\x05\xaf\xcd\x4a\x26\x04\x14\x89\xe9\x03\x32\x64\xa6\x02\xa1\xc2\x1d\x28\x74\xbe\xab\x33\x4d\xa2\xc3\xb7\x23\xcb\x20\x6b\x41\x61\x9e\x78\x93\xe7\xac\x16\x06\x79\x02\xbb\x14\x7b\x63\xb7\x42\x3a\x41\x8f\x2d\x46\xec\x94\x3e\x7d\x0b\xc3\xb9\xcb\xb7\x40\x1f\xca\xb3\x64\x32\xe9\xe6\x78\x7f\x8b\xef\xfa\xae\x01\xad\xd2\x87\x23\xb2\xd9\x14\xfc\x2f\xd9\x54\x46\x14\xef\xc0\x60\x07\xba\x6a\xa5\xe6\xac\x92\x68\x15\xd3\x33\x26\xb8\xc1\xcc\x80\x71\x83\x4c\x59\x97\x88\xfb\x9b\x02\x3d\x75\x1b\x2e\xc3\xa5\x66\x3b\x36\xb4\xd3\xb3\xde\xa7\x55\xf8\xde\xc9\x2d\x49\x6f\xac\x1b\x38\x73\x81\x6f\xa1\xb2\xf2\x9b\x4e\x43\xfb\x9c\xb6\xf3\x2c\xc5\xb7\x73\xa2\x4c\x1a\xad\xc3\xb9\x3d\xf1\xaf\x78\x8f\x0d\xf1\xe6\xe1\x01\x06\xa1\x11\xb3\x69\x3d\x73\x85\x92\x33\xad\x6f\x01\x83\x56\x6d\x03\x8d\x04\x33\x21\xdb\x77\x7d\x78\x3e\x57\xe7\xd4\xa3\xa5\x9d\x72\x81\x24\x33\x3a\x18\x41\x99\x02\x24\x42\xe3\x0d\xaf\x81\x2a\xbb\x78\x71\x7b\x7b\x9b\x72\x79\x80\xfb\x28\x18\xdf\x4f\x14\x47\xfe\xcb\x76\xdc\x69\x15\x6c\xa8\x30\x22\xd9\x84\x9a\x9b\xca\xf0\x35\x11\x88\xe9\xf4\xd6\x32\x1d\xc7\x70\xc2\x0d\x46\x2f\xe3\x39\x39\x26\x07\x1b\x63\xd0\x61\x85\x8e\x33\xf3\x78\x1a\x27\x4f\xb5\x32\xb8\x7e\x73\x6d\xb2\xdc\x5c\xfc\xe3\x0b\xca\xff\xf9\x91\xbd\xb3\xc7\xd2\xe6\x55\xf0\xab\x27\xeb\x98\xa9\xa8\xfd\x3f\xc9\xa6\x63\x32\xf4\xf2\x76\xf1\x6a\xc0\xf3\x47\xab\x20\x3d\x0c\x8c\xb9\xf6\xd2\x68\xd9\x94\xbd\xca\x77\x66\xcc\x1d\x8e\xbd\xc4\x34\xdf\xd0\xb3\xc6\xa3\xa3\x97\xf2\x86\x41\x87\xb9\x95\x1d\xce\x54\xef\xf7\xfb\x73\xb7\xff\x2c\x3d\x00\x82\x9a\xfc\xf9\xbf\xff\x29\xfc\x96\xc6\xb2\x4e\xd3\xf1\x29\xf2\xa0\x78\xe1\x8f\x0c\x28\xb9\xf0\xa7\xb7\xff\x05\x00\x00\xff\xff\x42\x2a\xa3\x29\x92\x13\x00\x00") func besticonIconserverAssetsIndexHtmlBytes() ([]byte, error) { return bindataRead( @@ -214,7 +216,7 @@ func besticonIconserverAssetsIndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/index.html", size: 9032, mode: os.FileMode(420), modTime: time.Unix(1444632938, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/index.html", size: 5010, mode: os.FileMode(420), modTime: time.Unix(1448303138, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -234,7 +236,7 @@ func besticonIconserverAssetsMainMinCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/main-min.css", size: 1103, mode: os.FileMode(420), modTime: time.Unix(1429383769, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/main-min.css", size: 1103, mode: os.FileMode(420), modTime: time.Unix(1437407693, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -254,7 +256,7 @@ func besticonIconserverAssetsMainCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/main.css", size: 1931, mode: os.FileMode(493), modTime: time.Unix(1423571759, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/main.css", size: 1931, mode: os.FileMode(493), modTime: time.Unix(1438789027, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -274,7 +276,27 @@ func besticonIconserverAssetsNot_foundHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/not_found.html", size: 1942, mode: os.FileMode(420), modTime: time.Unix(1444631088, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/not_found.html", size: 1942, mode: os.FileMode(420), modTime: time.Unix(1445273224, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _besticonIconserverAssetsPopularHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xac\x56\xdf\x6e\xdb\x36\x17\xbf\xcf\x53\xf0\x23\x8a\xf8\x26\x92\x9c\x7c\x69\x30\x24\x92\x86\x61\x6d\xd3\x0d\xdd\xcd\xd2\x61\xd7\x94\x74\x2c\x11\xa1\x48\x82\xa4\xec\xb8\x46\xde\x6c\x77\x7b\xb1\x1d\x52\xb2\x2d\xc9\x49\x30\x0c\xed\x45\x23\xf3\xfc\xff\x9d\xc3\xdf\x61\xfa\xbf\x4a\x95\x6e\xab\x81\x34\xae\x15\xf9\x59\xba\xff\x03\xac\xca\xcf\x08\x49\x5b\x70\x8c\x94\x0d\x33\x16\x5c\x46\x3b\xb7\x8a\x7e\xa0\x47\x81\x64\x2d\x64\x74\xcd\x61\xa3\x95\x71\x94\x94\x4a\x3a\x90\xa8\xb8\xe1\x95\x6b\xb2\x0a\xd6\xbc\x84\x28\xfc\xb8\x20\x5c\x72\xc7\x99\x88\x6c\xc9\x04\x64\x97\xf1\xf2\xc4\x51\x05\xb6\x34\x5c\x3b\xae\xe4\xc8\xd7\x27\x86\x5e\x94\x24\x1f\x9f\x58\xab\x05\x58\x34\xf3\x76\x8e\x3b\x01\xf9\x5c\x98\x26\xfd\x79\x50\x11\x5c\x3e\x12\x03\x22\xa3\xd6\x6d\x51\xd8\x00\x60\x92\x8d\x81\x55\x46\xe3\x44\x77\x06\xa2\x65\xfc\x3e\x5e\x46\x2d\x97\x71\x69\x6d\x9f\xd0\xdb\x56\xb5\xe1\x95\x8d\x0c\x58\xad\xa4\xe5\xeb\xff\xe0\xa1\x65\x5c\x8e\xf4\x0f\x18\x68\xa3\x34\x18\xb7\xcd\xa8\xaa\x6f\x43\x15\x94\xf4\xff\x0e\x50\x7c\x6d\x80\xec\x2b\xfe\xc4\x65\x05\x86\x92\x24\x7f\xd9\xc3\xbf\x04\xd3\xdb\x4f\x73\xf6\xf2\x7d\xb6\xc9\xaa\xd7\x8f\xf1\xbf\x79\x6d\x4c\xa3\x83\xc8\xa9\xae\x6c\xa2\x89\xcd\x5c\x10\x6b\x59\xa3\x71\x9a\xf4\x53\x75\x96\x16\xaa\xda\x06\x67\x15\x5f\x13\x5e\x65\x54\xb0\xad\xea\x5c\x0f\xc6\xe8\xd8\x23\x15\xa2\x1e\x4e\x4b\xc1\xac\xcd\xa8\x77\x84\xb5\xef\x45\x53\x61\x0f\xdd\x51\x86\xd2\xe6\x32\x4f\xd9\x3e\x3d\x7a\xf0\xa2\x5a\xf0\xe5\xd0\xfc\x14\xd7\x91\x35\xda\xf3\xb6\xde\x1b\x09\x55\x2b\x4a\xac\x29\x7d\x2b\x43\x75\x76\x5d\x53\xc2\x84\xcb\x16\x0f\xdc\x01\xf1\x0a\x8b\x3c\x4d\xd8\x24\x83\x04\x53\x38\x66\x9b\x60\xba\xa3\x9f\xcd\x55\xfe\x13\xb1\x60\xfc\x6d\x21\x2b\x8c\xcf\x65\x4d\xbc\x6f\x4b\x30\xa1\x0d\x14\xc4\xa2\x67\x9c\x6d\x54\x3c\x9b\xb8\x78\x01\x9b\xa1\xd5\xf4\x20\x0c\x01\x66\xd2\xc8\x76\x85\x07\x91\xe6\xbf\x4c\x6f\x8f\x8f\x70\xb4\x5b\x29\xd3\x12\x56\xfa\x19\x42\xe0\xb4\xd2\x9d\x60\x38\x72\x38\x6c\x8d\xc2\xfe\xdc\x7f\xfc\x7a\x00\x33\xdc\x26\xaf\x3f\x45\x7e\xc5\x41\x54\xc8\x1d\xf9\x14\x50\xc1\x0a\x10\x04\xd5\xfb\x71\xb3\xfc\xdb\xb4\x63\x3d\xea\x52\x77\x6e\xa0\x86\x83\x16\xf1\x6c\x95\x51\xd9\xb5\x85\x9f\x7e\x2d\x58\x09\x8d\x12\xd8\xb2\x8c\x86\x5a\x1e\x82\x16\xeb\x9c\x2a\x95\x2f\xca\xa1\xb6\x5a\xad\xf6\x47\xc6\x40\xe9\xfa\x93\x59\xbc\x20\x67\x9a\x3b\x26\xd0\xc5\x60\x64\x35\x08\x51\x36\x50\x3e\x66\x74\xc5\x84\x85\xb9\x55\x98\xb6\x6c\xf1\x59\x49\xb0\x4e\x6c\x2f\x86\xbe\x31\x03\x1e\xb8\x8e\x09\xb1\xc5\xeb\xe2\x47\x0a\x2a\xc2\x1c\xa1\x06\x1c\x97\x8c\xe2\xa1\x55\xa2\xf3\xd0\x12\xc4\x42\x6d\x10\x55\x26\x7d\xe3\x5d\xc3\x2d\xf1\xb5\x92\x84\x5c\xc5\x8b\x59\x3c\x24\x8e\x8c\x2e\xb1\x07\xec\x29\xa3\x97\xcb\x25\x7e\x5a\x07\x3a\xa3\xd7\xf3\xcc\xd6\x4c\x74\x58\xc6\x6e\x17\x7b\x5c\x3c\x2c\xcf\xcf\x33\x90\xd3\x24\x34\x62\xd4\xf2\x70\x5a\x74\xce\x61\x5a\x3d\xd2\x38\x29\x2d\x77\xd3\x3e\x0f\x0a\xa3\xef\x48\x1b\xde\x32\xb3\xa5\xf9\x03\xb8\x80\x41\x28\x21\x4d\x7a\xf1\xf4\x2e\x9c\x0e\x05\x9e\xe1\xe8\x8c\x47\xcf\xb1\x42\xc0\x24\x68\x7f\x72\xfc\x8c\x1a\x65\xf8\x37\x9c\x67\x26\xa6\x33\xe7\xf6\xdb\x6b\x7c\x66\x4e\xc6\xcb\x35\xb9\xbf\xb0\xb8\x31\x9a\x97\x64\x37\xd7\xaf\x49\x2e\xaf\x96\xaf\x89\x76\xbb\x77\x23\xb4\x5f\xd3\x3a\x97\x85\xd5\x77\xa7\x52\x3c\x31\x53\xa4\x4e\x4a\xd9\xed\x0c\x93\x35\x90\x77\x9d\x11\xe4\x36\x23\xf1\x1f\xbf\x7f\xb1\xcf\xcf\x93\xf2\xcd\x00\xdb\xc2\xb7\x61\x31\x07\xa2\xf2\x49\xa2\x75\x48\xef\x04\x26\x9c\x51\xc1\x6b\x99\x2d\x4a\x64\x09\x30\x48\x64\x9e\xfb\x02\xdd\x05\xb6\xfb\x11\x2d\xb3\xbd\x83\x73\x64\x8d\x3b\xdf\xe6\xec\xe6\x7a\xa0\xc0\x05\x09\x2b\x2f\x5b\xe0\x7c\xf6\x8b\xff\x96\xfc\xff\x4a\x3f\x79\x46\xfc\x6e\xd1\xb0\x01\x6f\x84\xbb\x59\x7e\xe7\x70\xd3\xa6\xbe\x11\xd9\x2b\x7e\xe0\x16\x39\x69\xdb\xeb\xbe\x9a\xc8\x68\x1d\x05\xbe\x98\x44\xa6\xf9\x07\xdc\xe6\x5c\x58\xbf\x44\xe6\xe6\xf3\x19\xd9\xed\x90\x5c\x46\x03\x80\x72\x7f\x39\x66\x7b\x62\xf2\x79\xdc\x1d\xe3\xbd\xb1\x52\x0a\x31\x21\x22\x2a\xd4\xd3\x70\x9f\x52\x7d\x70\x33\xa4\xbb\x68\x9c\xd3\xb7\x49\x9f\x74\x5c\x80\x43\x93\x88\x57\xc0\x62\x65\xea\xc5\x0b\x7b\xd4\x97\x40\xce\x2b\x66\x9b\x3b\x7c\x00\xe2\x92\x63\xa6\x6c\x3c\xf1\x0f\x3c\x69\xb9\xc4\x9d\xf7\x2b\x93\x1d\x92\x07\xb9\x5a\x5e\xbe\x8f\x87\x90\x7f\x1a\x8e\xde\xa5\xb7\x9a\x47\xaf\x95\xc0\x4b\xd0\x87\xbc\x57\x3e\xc4\xc5\x60\x64\x55\x67\xd0\x9f\x3a\xda\x50\x6f\x63\xbd\x11\x77\x4d\x57\xc4\xb8\x14\xf0\x05\xe6\x92\x02\xe9\x3a\xbc\x5a\xf2\x7b\xee\x3e\x77\x85\xf7\xb2\x0f\xfd\xb3\x01\xe6\x90\xae\x8b\xed\x49\xe8\xcd\x66\x73\x5a\xf6\x6f\xcc\x21\x69\x33\x4b\xbe\xfc\xfd\x57\xe5\x1e\xe1\xe8\x2b\x4d\xf4\x18\x71\xa4\xc3\xf0\xf4\xc1\x3d\x1b\xde\xd9\xff\x04\x00\x00\xff\xff\x55\x23\xab\xfc\x7f\x0b\x00\x00") + +func besticonIconserverAssetsPopularHtmlBytes() ([]byte, error) { + return bindataRead( + _besticonIconserverAssetsPopularHtml, + "besticon/iconserver/assets/popular.html", + ) +} + +func besticonIconserverAssetsPopularHtml() (*asset, error) { + bytes, err := besticonIconserverAssetsPopularHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "besticon/iconserver/assets/popular.html", size: 2943, mode: os.FileMode(420), modTime: time.Unix(1448303138, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -294,7 +316,7 @@ func besticonIconserverAssetsPure050MinCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/pure-0.5.0-min.css", size: 18943, mode: os.FileMode(420), modTime: time.Unix(1429165516, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/pure-0.5.0-min.css", size: 18943, mode: os.FileMode(420), modTime: time.Unix(1429175968, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -314,7 +336,27 @@ func besticonIconserverAssetsRobotsTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "besticon/iconserver/assets/robots.txt", size: 59, mode: os.FileMode(420), modTime: time.Unix(1430246639, 0)} + info := bindataFileInfo{name: "besticon/iconserver/assets/robots.txt", size: 59, mode: os.FileMode(420), modTime: time.Unix(1430320706, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _besticonIconserverAssetsTestLettericonsHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x9c\xd8\xc9\x8a\xea\x40\x14\x80\xe1\x7d\x9e\x22\x64\xaf\x99\xa3\x42\x14\xae\x19\x9c\xe7\xd9\x9d\xd7\x29\x82\x43\xa3\x81\xa6\xdf\xbe\x5b\xdc\x99\x26\xd5\xf5\xaf\xb2\xfa\xb0\xea\xfc\x72\x16\xe5\x27\xe9\xe5\x5c\x53\xfc\x64\xbf\xd9\xfd\x7c\xf4\xd7\x57\xf1\xff\xdf\x76\x5f\x35\x45\x55\x55\xff\x74\x39\xaa\x8f\xfb\xb6\xaa\x15\xf5\xf3\x3e\x4d\xf7\xf7\xd3\xf6\x76\x7d\xe8\xff\x0a\x25\xaf\x70\x38\x6c\xca\x86\xa1\xa9\x9f\xa7\x5d\x9a\x54\x35\xbb\xac\x09\x8c\x69\x3a\xef\xc8\x2d\x09\x91\x65\xbc\x23\xcf\x10\x22\x27\xf3\x4b\x25\x4b\x88\x5c\x2b\x83\x3c\x21\x2a\x67\x8e\x57\x11\x1f\xaf\x92\x99\x5e\x45\x38\x3d\x3b\x3b\x08\x53\x3c\x09\xd7\xcc\x5c\xca\x72\x9f\xb7\x12\xe5\x95\xeb\x2a\x17\x54\xae\xa4\x5c\x42\xb9\x76\x72\xd1\xe4\x6a\x49\x66\xfa\xad\x4f\x72\xd7\x45\xa5\x9e\x7f\x75\xd3\xb2\x1d\xd7\x2b\x7e\x5c\x8f\x7f\x9e\x55\x9d\xc2\x80\xc2\x90\xc2\x88\xc2\x98\xc2\x06\x85\x4d\x0a\x5b\x14\xb6\x29\xec\x50\xd8\xa5\xb0\x47\x61\x9f\xc2\x01\x85\x43\x0a\x47\x14\x8e\x29\x9c\x50\x38\xa5\x70\x46\xe1\x9c\xc2\x05\x85\x4b\x0a\x57\x14\xae\x73\xa1\x78\x95\x3b\xb6\x57\xf7\x0c\xb0\xca\x01\x0c\x28\x0c\x29\x8c\x28\x8c\x29\x6c\x50\xd8\xa4\xb0\x45\x61\x9b\xc2\x0e\x85\x5d\x0a\x7b\x14\xf6\x29\x1c\x50\x38\xa4\x70\x44\xe1\x98\xc2\x09\x85\x53\x0a\x67\x14\xce\x29\x5c\x50\xb8\xa4\x70\x45\xe1\x3a\x17\x8a\x57\x79\x14\x07\x96\x1b\x82\x55\x0e\x60\x40\x61\x48\x61\x44\x61\x4c\x61\x83\xc2\x26\x85\x2d\x0a\xdb\x14\x76\x28\xec\x52\xd8\xa3\xb0\x4f\xe1\x80\xc2\x21\x85\x23\x0a\xc7\x14\x4e\x28\x9c\x52\x38\xa3\x70\x4e\xe1\x82\xc2\x25\x85\x2b\x0a\xd7\xb9\x50\xf1\xf5\xd7\x8b\xa7\xaf\xbf\x1e\x44\xbf\x03\x00\x00\xff\xff\x57\x28\xfc\xd3\x18\x15\x00\x00") + +func besticonIconserverAssetsTestLettericonsHtmlBytes() ([]byte, error) { + return bindataRead( + _besticonIconserverAssetsTestLettericonsHtml, + "besticon/iconserver/assets/test-lettericons.html", + ) +} + +func besticonIconserverAssetsTestLettericonsHtml() (*asset, error) { + bytes, err := besticonIconserverAssetsTestLettericonsHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "besticon/iconserver/assets/test-lettericons.html", size: 5400, mode: os.FileMode(420), modTime: time.Unix(1448303138, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -381,8 +423,10 @@ var _bindata = map[string]func() (*asset, error){ "besticon/iconserver/assets/main-min.css": besticonIconserverAssetsMainMinCss, "besticon/iconserver/assets/main.css": besticonIconserverAssetsMainCss, "besticon/iconserver/assets/not_found.html": besticonIconserverAssetsNot_foundHtml, + "besticon/iconserver/assets/popular.html": besticonIconserverAssetsPopularHtml, "besticon/iconserver/assets/pure-0.5.0-min.css": besticonIconserverAssetsPure050MinCss, "besticon/iconserver/assets/robots.txt": besticonIconserverAssetsRobotsTxt, + "besticon/iconserver/assets/test-lettericons.html": besticonIconserverAssetsTestLettericonsHtml, } // AssetDir returns the file names below a certain @@ -448,10 +492,14 @@ var _bintree = &bintree{nil, map[string]*bintree{ }}, "not_found.html": &bintree{besticonIconserverAssetsNot_foundHtml, map[string]*bintree{ }}, + "popular.html": &bintree{besticonIconserverAssetsPopularHtml, map[string]*bintree{ + }}, "pure-0.5.0-min.css": &bintree{besticonIconserverAssetsPure050MinCss, map[string]*bintree{ }}, "robots.txt": &bintree{besticonIconserverAssetsRobotsTxt, map[string]*bintree{ }}, + "test-lettericons.html": &bintree{besticonIconserverAssetsTestLettericonsHtml, map[string]*bintree{ + }}, }}, }}, }}, diff --git a/besticon/iconserver/assets/icons.html b/besticon/iconserver/assets/icons.html index 46b27247..709606cc 100644 --- a/besticon/iconserver/assets/icons.html +++ b/besticon/iconserver/assets/icons.html @@ -5,7 +5,7 @@ - Icons on {{ .Host }} + Favicon for {{ .Host }} @@ -33,7 +33,7 @@

A service finding icons on web sites

-

Find Icons

+

Get Favicon

@@ -51,8 +51,15 @@

Find Icons

{{ with .Error }}
{{ .}}
{{ end }} +

Favicon for {{ .Host }}

+ +

+ Icon link: + http://icons.better-idea.org/icon?url={{ .URL }}&size=120 +

+ {{ if ((len .Icons) ne 0) }} -

Icons on {{ .Host }}

+

More Icons on {{ .Host }}

@@ -72,11 +79,15 @@

Icons on {{ .Host }}

{{end}}
+ +

+ JSON representation: + http://icons.better-idea.org/allicons.json?url={{ .URL }}. +

{{ end }} -

JSON Result

- This result is available as JSON at - http://icons.better-idea.org/api/icons?url={{ .URL }}. +
diff --git a/besticon/iconserver/assets/index.html b/besticon/iconserver/assets/index.html index ba9b7c51..0b309fa2 100644 --- a/besticon/iconserver/assets/index.html +++ b/besticon/iconserver/assets/index.html @@ -35,12 +35,12 @@

A service finding icons on web sites

What Is This About?

- Web sites used to have a favicon.ico ‐ or not. + Web sites used to have a favicon.ico, or not. With the introduction of the apple-touch-icon.png finding “the” icon for a site became more complicated. - This service finds all those favicons and sorts them by size. + This service finds and — if necessary — generates icons for web sites.

-

Find Icons

+

Find Icon

@@ -58,82 +58,21 @@

Find Icons

-

HTTP API

-

- The API call at - http://icons.better-idea.org/api/icons - supports both listing all icons and redirection to the largest icon. -

- -

Example: All Icons

-

- - GET http://icons.better-idea.org/api/icons?url=stackoverflow.com - -

- -
- {
-   "url": "stackoverflow.com",
-   "icons": [
-     {
-       "url": "http://stackoverflow.com/apple-touch-icon.png",
-       "width": 158,
-       "height": 158,
-       "format": "png",
-       "bytes": 3733,
-       "error": null,
-       "sha1sum": "41f6e13ade692735591bae7e7746ffce90ce752f"
-     },
-     {
-       "url": "http://cdn.sstatic.net/stackoverflow/img/favicon.ico?v=038622610830",
-       "width": 32,
-       "height": 32,
-       "format": "ico",
-       "bytes": 5430,
-       "error": null,
-       "sha1sum": "03862261083091ecab73c50e5d9b9c060245fd35"
-     },
-     {
-       "url": "http://stackoverflow.com/favicon.ico",
-       "width": 32,
-       "height": 32,
-       "format": "ico",
-       "bytes": 5430,
-       "error": null,
-       "sha1sum": "03862261083091ecab73c50e5d9b9c060245fd35"
-     }
-   ]
- }
-          
- -

Example: Redirect

- For automatic redirection to the largest icon append the i_am_feeling_lucky=yes parameter. -

- - GET - http://icons.better-idea.org/api/icons?url=stackoverflow.com&i_am_feeling_lucky=yes - -

+

URL API

-

Errors

- Errors are returned with status 404 and an error field in the response. + You can just link to an icon using the required url and size parameters:

- GET - http://icons.better-idea.org/api/icons?url=broken-example.com + + http://icons.better-idea.org/icon?url=github.com&size=120

+ Find more detailed information in the Readme on GitHub. - -
-
-{
-   "error": "Get http://broken-example.com: dial tcp: lookup broken-example.com: no such host"
-}

Disclaimer & Self-hosting

diff --git a/besticon/iconserver/assets/popular.html b/besticon/iconserver/assets/popular.html new file mode 100644 index 00000000..f84d5ed1 --- /dev/null +++ b/besticon/iconserver/assets/popular.html @@ -0,0 +1,86 @@ + + + + + + + + Favicon Examples + + + + + + + + + + + + + +

+ +
+
+ +

A service finding icons on web sites

+
+ +
+ +

Icon Examples

+ + +
+ + + +
+ + + + + + + + + + + + + {{range $url := .URLs}} + + + + + + + + {{end}} +
Site64120{{$.IconSize}} 
{{$url}}Details
+
+
+
+ + + + + diff --git a/besticon/iconserver/assets/test-lettericons.html b/besticon/iconserver/assets/test-lettericons.html new file mode 100644 index 00000000..eade9186 --- /dev/null +++ b/besticon/iconserver/assets/test-lettericons.html @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/besticon/iconserver/server.go b/besticon/iconserver/server.go index c2936fc6..19d3c300 100644 --- a/besticon/iconserver/server.go +++ b/besticon/iconserver/server.go @@ -4,18 +4,19 @@ import ( "bytes" "encoding/json" "errors" - "expvar" "flag" "fmt" "html/template" "net/http" "net/url" "strconv" + "strings" "time" "github.com/NYTimes/gziphandler" "github.com/mat/besticon/besticon" "github.com/mat/besticon/besticon/iconserver/assets" + "github.com/mat/besticon/lettericon" ) func indexHandler(w http.ResponseWriter, r *http.Request) { @@ -33,11 +34,18 @@ func iconsHandler(w http.ResponseWriter, r *http.Request) { return } - icons, e := fetchIcons(url) + finder := besticon.IconFinder{} + + formats := r.FormValue("formats") + if formats != "" { + finder.FormatsAllowed = strings.Split(r.FormValue("formats"), ",") + } + + e, icons := finder.FetchIcons(url) switch { case e != nil: renderHTMLTemplate(w, 404, iconsHTML, pageInfo{URL: url, Error: e}) - case len(icons) <= 0: + case len(icons) == 0: errNoIcons := errors.New("this poor site has no icons at all :-(") renderHTMLTemplate(w, 404, iconsHTML, pageInfo{URL: url, Error: errNoIcons}) default: @@ -45,64 +53,113 @@ func iconsHandler(w http.ResponseWriter, r *http.Request) { } } +func iconHandler(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if len(url) == 0 { + writeAPIError(w, 400, errors.New("need url parameter"), true) + return + } + + size := r.FormValue("size") + if size == "" { + writeAPIError(w, 400, errors.New("need size parameter"), true) + return + } + minSize, err := strconv.Atoi(size) + if err != nil || minSize < 0 || minSize > 1000 { + writeAPIError(w, 400, errors.New("bad size parameter"), true) + return + } + + finder := besticon.IconFinder{} + formats := r.FormValue("formats") + if formats != "" { + finder.FormatsAllowed = strings.Split(r.FormValue("formats"), ",") + } + + err, _ = finder.FetchIcons(url) + if err != nil { + writeAPIError(w, 404, err, true) + return + } + + icon := finder.IconWithMinSize(minSize) + if icon != nil { + http.Redirect(w, r, icon.URL, 302) + return + } + + iconColor := finder.MainColorForIcons() + letter := lettericon.MainLetterFromURL(url) + redirectPath := lettericon.IconPath(letter, size, iconColor) + http.Redirect(w, r, redirectPath, 302) +} + +func popularHandler(w http.ResponseWriter, r *http.Request) { + iconSize, err := strconv.Atoi(r.FormValue("iconsize")) + if iconSize > 1000 || iconSize < 10 || err != nil { + iconSize = 180 + } + + pageInfo := struct { + URLs []string + IconSize int + DisplaySize int + }{ + besticon.PopularSites, + iconSize, + iconSize / 2, + } + renderHTMLTemplate(w, 200, popularHTML, pageInfo) +} + const ( - urlParam = "url" - feelingLuckyParam = "i_am_feeling_lucky" - prettyParam = "pretty" - maxAge = "max_age" + urlParam = "url" + prettyParam = "pretty" + maxAge = "max_age" ) const defaultMaxAge = time.Duration(604800) * time.Second // 7 days -func apiHandler(w http.ResponseWriter, r *http.Request) { - pretty := r.FormValue(prettyParam) == "yes" +func alliconsHandler(w http.ResponseWriter, r *http.Request) { url := r.FormValue(urlParam) if len(url) == 0 { errMissingURL := errors.New("need url query parameter") - writeAPIError(w, 400, errMissingURL, pretty) + writeAPIError(w, 400, errMissingURL, true) return } - bestOnly := r.FormValue(feelingLuckyParam) == "yes" - if bestOnly { - icon, e := fetchBestIcon(url) - if e != nil { - writeAPIError(w, 404, e, pretty) - return - } - - http.Redirect(w, r, icon.URL, 302) - } else { - icons, e := fetchIcons(url) - if e != nil { - writeAPIError(w, 404, e, pretty) - return - } + finder := besticon.IconFinder{} + formats := r.FormValue("formats") + if formats != "" { + finder.FormatsAllowed = strings.Split(r.FormValue("formats"), ",") + } - maxAge, err := time.ParseDuration(r.FormValue(maxAge)) - if err != nil || maxAge.Seconds() < 1 { - maxAge = defaultMaxAge - } - writeAPIIcons(w, url, icons, maxAge, pretty) + e, icons := finder.FetchIcons(url) + if e != nil { + writeAPIError(w, 404, e, true) + return } + + pretty, err := strconv.ParseBool(r.FormValue(prettyParam)) + prettyPrint := (err == nil) && pretty + + writeAPIIcons(w, url, icons, prettyPrint) } -func fetchIcons(url string) ([]besticon.Icon, error) { - fetchCount.Add(1) - icons, err := besticon.FetchIcons(url, true) - if err != nil { - fetchErrors.Add(1) - } - return icons, err +func lettericonHandler(w http.ResponseWriter, r *http.Request) { + charParam, col, size := lettericon.ParseIconPath(r.URL.Path) + + w.Header().Add("Content-Type", "image/png") + lettericon.Render(charParam, col, size, w) } -func fetchBestIcon(url string) (*besticon.Icon, error) { - fetchCount.Add(1) - icon, err := besticon.FetchBestIcon(url, true) - if err != nil { - fetchErrors.Add(1) +func obsoleteAPIHandler(w http.ResponseWriter, r *http.Request) { + if r.FormValue("i_am_feeling_lucky") == "yes" { + http.Redirect(w, r, fmt.Sprintf("/icon?size=120&%s", r.URL.RawQuery), 302) + } else { + http.Redirect(w, r, fmt.Sprintf("/allicons.json?%s", r.URL.RawQuery), 302) } - return icon, err } func writeAPIError(w http.ResponseWriter, httpStatus int, e error, pretty bool) { @@ -119,7 +176,7 @@ func writeAPIError(w http.ResponseWriter, httpStatus int, e error, pretty bool) } } -func writeAPIIcons(w http.ResponseWriter, url string, icons []besticon.Icon, maxAge time.Duration, pretty bool) { +func writeAPIIcons(w http.ResponseWriter, url string, icons []besticon.Icon, pretty bool) { data := struct { URL string `json:"url"` Icons []besticon.Icon `json:"icons"` @@ -128,7 +185,6 @@ func writeAPIIcons(w http.ResponseWriter, url string, icons []besticon.Icon, max icons, } - w.Header().Add(cacheControl, fmt.Sprintf("max-age=%d", int64(maxAge.Seconds()))) if pretty { renderJSONResponsePretty(w, 200, data) } else { @@ -192,9 +248,13 @@ func renderHTMLTemplate(w http.ResponseWriter, httpStatus int, templ *template.T } func startServer(port int) { - httpHandle("/", indexHandler) - httpHandle("/icons", iconsHandler) - httpHandle("/api/icons", apiHandler) + httpHandleGzip("/", indexHandler) + httpHandleGzip("/icons", iconsHandler) + http.HandleFunc("/icon", iconHandler) + httpHandleGzip("/popular", popularHandler) + httpHandleGzip("/allicons.json", alliconsHandler) + http.HandleFunc("/lettericons/", lettericonHandler) + http.HandleFunc("/api/icons", obsoleteAPIHandler) serveAsset("/pure-0.5.0-min.css", "besticon/iconserver/assets/pure-0.5.0-min.css", oneYear) serveAsset("/grids-responsive-0.5.0-min.css", "besticon/iconserver/assets/grids-responsive-0.5.0-min.css", oneYear) @@ -204,6 +264,7 @@ func startServer(port int) { serveAsset("/favicon.ico", "besticon/iconserver/assets/favicon.ico", oneYear) serveAsset("/apple-touch-icon.png", "besticon/iconserver/assets/apple-touch-icon.png", oneYear) serveAsset("/robots.txt", "besticon/iconserver/assets/robots.txt", nocache) + serveAsset("/test-lettericons", "besticon/iconserver/assets/test-lettericons.html", nocache) logger.Print("Starting server on port ", port, "...") e := http.ListenAndServe(":"+strconv.Itoa(port), newLoggingMux()) @@ -218,7 +279,7 @@ const ( ) func serveAsset(path string, assetPath string, maxAgeSeconds int) { - httpHandle(path, func(w http.ResponseWriter, r *http.Request) { + httpHandleGzip(path, func(w http.ResponseWriter, r *http.Request) { assetInfo, err := assets.AssetInfo(assetPath) if err != nil { panic(err) @@ -233,7 +294,7 @@ func serveAsset(path string, assetPath string, maxAgeSeconds int) { }) } -func httpHandle(path string, f http.HandlerFunc) { +func httpHandleGzip(path string, f http.HandlerFunc) { http.Handle(path, gziphandler.GzipHandler(http.HandlerFunc(f))) } @@ -251,6 +312,7 @@ func main() { func init() { indexHTML = templateFromAsset("besticon/iconserver/assets/index.html", "index.html") iconsHTML = templateFromAsset("besticon/iconserver/assets/icons.html", "icons.html") + popularHTML = templateFromAsset("besticon/iconserver/assets/popular.html", "popular.html") notFoundHTML = templateFromAsset("besticon/iconserver/assets/not_found.html", "not_found.html") } @@ -261,6 +323,7 @@ func templateFromAsset(assetPath, templateName string) *template.Template { var indexHTML *template.Template var iconsHTML *template.Template +var popularHTML *template.Template var notFoundHTML *template.Template var funcMap = template.FuncMap{ @@ -270,20 +333,3 @@ var funcMap = template.FuncMap{ func imgWidth(i *besticon.Icon) int { return i.Width / 2.0 } - -func init() { - besticon.SetCacheMaxSize(64) - - expvar.Publish("cacheBytes", expvar.Func(func() interface{} { return besticon.GetCacheStats().Bytes })) - expvar.Publish("cacheItems", expvar.Func(func() interface{} { return besticon.GetCacheStats().Items })) - expvar.Publish("cacheGets", expvar.Func(func() interface{} { return besticon.GetCacheStats().Gets })) - expvar.Publish("cacheHits", expvar.Func(func() interface{} { return besticon.GetCacheStats().Hits })) - expvar.Publish("cacheEvictions", expvar.Func(func() interface{} { return besticon.GetCacheStats().Evictions })) - - ticker := time.NewTicker(time.Minute * 1) - go func() { - for range ticker.C { - logger.Printf("Cache: %+v", besticon.GetCacheStats()) - } - }() -} diff --git a/besticon/iconserver/server_test.go b/besticon/iconserver/server_test.go index ee4edbf2..1a7da4e3 100644 --- a/besticon/iconserver/server_test.go +++ b/besticon/iconserver/server_test.go @@ -46,18 +46,17 @@ func TestGetIcons(t *testing.T) { assertStringContains(t, w.Body.String(), "32x32") } -func TestGetApiIcons(t *testing.T) { - req, err := http.NewRequest("GET", "/api/icons?url=apple.com", nil) +func TestGetAllIcons(t *testing.T) { + req, err := http.NewRequest("GET", "/allicons.json?url=apple.com", nil) if err != nil { log.Fatal(err) } w := httptest.NewRecorder() - apiHandler(w, req) + alliconsHandler(w, req) assertStringEquals(t, "200", fmt.Sprintf("%d", w.Code)) assertStringEquals(t, "application/json", w.Header().Get("Content-Type")) - assertStringEquals(t, "max-age=604800", w.Header().Get("Cache-Control")) assertStringContains(t, w.Body.String(), `"url":"http://www.apple.com/favicon.ico"`) assertStringContains(t, w.Body.String(), `"width":32`) @@ -65,34 +64,33 @@ func TestGetApiIcons(t *testing.T) { } func TestGetApiIconsWithMaxAge(t *testing.T) { - req, err := http.NewRequest("GET", "/api/icons?url=apple.com&max_age=2h", nil) + req, err := http.NewRequest("GET", "/allicons.json?url=apple.com&max_age=2h", nil) if err != nil { log.Fatal(err) } w := httptest.NewRecorder() - apiHandler(w, req) + alliconsHandler(w, req) assertStringEquals(t, "200", fmt.Sprintf("%d", w.Code)) assertStringEquals(t, "application/json", w.Header().Get("Content-Type")) - assertStringEquals(t, "max-age=7200", w.Header().Get("Cache-Control")) assertStringContains(t, w.Body.String(), `"url":"http://www.apple.com/favicon.ico"`) assertStringContains(t, w.Body.String(), `"width":32`) assertStringContains(t, w.Body.String(), `"height":32`) } -func TestGetApiIconsRedirect(t *testing.T) { - req, err := http.NewRequest("GET", "/api/icons?url=apple.com&i_am_feeling_lucky=yes", nil) +func TestGetObsoleteApiRedirect(t *testing.T) { + req, err := http.NewRequest("GET", "/api/icons?url=http%3A%2F%2Fapple.com&i_am_feeling_lucky=yes", nil) if err != nil { log.Fatal(err) } w := httptest.NewRecorder() - apiHandler(w, req) + obsoleteAPIHandler(w, req) assertStringEquals(t, "302", fmt.Sprintf("%d", w.Code)) - assertStringEquals(t, "http://www.apple.com/apple-touch-icon.png", w.Header().Get("Location")) + assertStringEquals(t, "/icon?size=120&url=http%3A%2F%2Fapple.com&i_am_feeling_lucky=yes", w.Header().Get("Location")) } func TestGet404(t *testing.T) { diff --git a/besticon/popular_sites.go b/besticon/popular_sites.go new file mode 100644 index 00000000..6aabe293 --- /dev/null +++ b/besticon/popular_sites.go @@ -0,0 +1,117 @@ +package besticon + +// PopularSites we might use for examples and testing. +var PopularSites []string + +func init() { + PopularSites = []string{ + "163.com", + "360.cn", + "about.com", + "adcash.com", + "adobe.com", + "alibaba.com", + "aliexpress.com", + "alipay.com", + "amazon.com", + "amazonaws.com", + "ameblo.jp", + "aol.com", + "apple.com", + "ask.com", + "baidu.com", + "bankofamerica.com", + "bbc.co.uk", + "bestbuy.com", + "bing.com", + "blogger.com", + "blogspot.com", + "bongacams.com", + "booking.com", + "bp.blogspot.com", + "buzzfeed.com", + "chase.com", + "china.com", + "cnet.com", + "cnn.com", + "cntv.cn", + "coccoc.com", + "craigslist.org", + "dailymail.co.uk", + "dailymotion.com", + "directrev.com", + "dropbox.com", + "ebay.com", + "espn.go.com", + "etsy.com", + "ettoday.net", + "facebook.com", + "fc2.com", + "flickr.com", + "flipkart.com", + "github.com", + "globo.com", + "gmail.com", + "gmw.cn", + "go.com", + "google.com", + "googleadservices.com", + "googleusercontent.com", + "hao123.com", + "huffingtonpost.com", + "imdb.com", + "imgur.com", + "indiatimes.com", + "instagram.com", + "jd.com", + "life.com.tw", + "linkedin.com", + "live.com", + "mail.ru", + "microsoft.com", + "msn.com", + "naver.com", + "netflix.com", + "nytimes.com", + "odnoklassniki.ru", + "onclickads.net", + "outbrain.com", + "paypal.com", + "pconline.com.cn", + "people.com.cn", + "pinterest.com", + "pixnet.net", + "qq.com", + "rakuten.co.jp", + "reddit.com", + "sina.com.cn", + "slideshare.net", + "sogou.com", + "sohu.com", + "soso.com", + "stackoverflow.com", + "t.co", + "taobao.com", + "target.com", + "thepiratebay.se", + "tmall.com", + "tudou.com", + "tumblr.com", + "twitter.com", + "uol.com.br", + "vimeo.com", + "vk.com", + "walmart.com", + "weather.com", + "weibo.com", + "wikia.com", + "wikipedia.org", + "wordpress.com", + "xinhuanet.com", + "yahoo.com", + "yandex.ru", + "yelp.com", + "youku.com", + "youtube.com", + } +} diff --git a/besticon/sorting.go b/besticon/sorting.go index 4a376054..9c4c1f1a 100644 --- a/besticon/sorting.go +++ b/besticon/sorting.go @@ -2,11 +2,16 @@ package besticon import "sort" -func sortIcons(icons []Icon) { +func SortIcons(icons []Icon, sizeDescending bool) { // Order after sorting: (width/height, bytes, url) sort.Stable(byURL(icons)) sort.Stable(byBytes(icons)) - sort.Stable(sort.Reverse(byWidthHeight(icons))) + + if sizeDescending { + sort.Stable(sort.Reverse(byWidthHeight(icons))) + } else { + sort.Stable(byWidthHeight(icons)) + } } type byWidthHeight []Icon diff --git a/colorfinder/colorfinder.go b/colorfinder/colorfinder.go new file mode 100644 index 00000000..8025f44a --- /dev/null +++ b/colorfinder/colorfinder.go @@ -0,0 +1,198 @@ +package colorfinder + +// colorfinder takes an image and tries to find its main color. +// It is a liberal port of +// http://pieroxy.net/blog/pages/color-finder/demo.html + +import ( + "fmt" + "image" + "io" + "log" + "math" + "net/http" + "os" + "strings" + + "image/color" + + // Load supported image formats + _ "image/gif" + _ "image/png" +) + +func main() { + arg := os.Args[1] + + var imageReader io.ReadCloser + if strings.HasPrefix(arg, "http") { + var err error + response, err := http.Get(arg) + if err != nil { + log.Fatal(err) + } + imageReader = response.Body + } else { + var err error + fmt.Fprintln(os.Stderr, "Reading "+arg+"...") + imageReader, err = os.Open(arg) + if err != nil { + log.Fatal(err) + } + } + defer imageReader.Close() + + img, _, err := image.Decode(imageReader) + if err != nil { + log.Fatal(err) + } + + cf := ColorFinder{} + c, err := cf.FindMainColor(img) + if err != nil { + log.Fatal(err) + } + fmt.Println("#" + ColorToHex(c)) +} + +type ColorFinder struct { + img image.Image +} + +// FindMainColor tries to identify the most important color in the given logo. +func (cf *ColorFinder) FindMainColor(img image.Image) (color.RGBA, error) { + cf.img = img + + colorMap := cf.buildColorMap() + + sRGB := cf.findMainColor(colorMap, 6, nil) + sRGB = cf.findMainColor(colorMap, 4, &sRGB) + sRGB = cf.findMainColor(colorMap, 2, &sRGB) + sRGB = cf.findMainColor(colorMap, 0, &sRGB) + + return sRGB.rgb, nil +} + +const sampleThreshold = 160 * 160 + +func (cf *ColorFinder) buildColorMap() *map[color.RGBA]colorStats { + colorMap := make(map[color.RGBA]colorStats) + bounds := cf.img.Bounds() + + for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + for x := bounds.Min.X; x < bounds.Max.X; x++ { + r, g, b, a := cf.img.At(x, y).RGBA() + rgb := color.RGBA{} + rgb.R = uint8(r >> shiftRGB) + rgb.G = uint8(g >> shiftRGB) + rgb.B = uint8(b >> shiftRGB) + rgb.A = uint8(a >> shiftRGB) + + colrStats, exist := colorMap[rgb] + if exist { + colrStats.count++ + } else { + colrStats := colorStats{count: 1, weight: weight(&rgb)} + if colrStats.weight <= 0 { + colrStats.weight = 1e-10 + } + colorMap[rgb] = colrStats + } + } + } + return &colorMap +} + +// Turns out using this is faster than using +// RGBAModel.Convert(img.At(x, y))).(color.RGBA) +const shiftRGB = uint8(8) + +func (cf *ColorFinder) findMainColor(colorMap *map[color.RGBA]colorStats, shift uint, targetColor *shiftedRGBA) shiftedRGBA { + colorWeights := make(map[shiftedRGBA]float64) + + bounds := cf.img.Bounds() + stepLength := stepLength(bounds) + + for y := bounds.Min.Y; y < bounds.Max.Y; y += stepLength { + for x := bounds.Min.X; x < bounds.Max.X; x += stepLength { + r, g, b, a := cf.img.At(x, y).RGBA() + color := color.RGBA{} + color.R = uint8(r >> shiftRGB) + color.G = uint8(g >> shiftRGB) + color.B = uint8(b >> shiftRGB) + color.A = uint8(a >> shiftRGB) + + if rgbMatchesTargetColor(targetColor, &color) { + increaseColorWeight(&colorWeights, colorMap, &color, shift) + } + } + } + + maxColor := shiftedRGBA{} + maxWeight := 0.0 + for sRGB, weight := range colorWeights { + if weight > maxWeight { + maxColor = sRGB + maxWeight = weight + } + } + + return maxColor +} + +func increaseColorWeight(weightedColors *map[shiftedRGBA]float64, colorMap *map[color.RGBA]colorStats, rgb *color.RGBA, shift uint) { + shiftedColor := color.RGBA{R: rgb.R >> shift, G: rgb.G >> shift, B: rgb.B >> shift} + pixelGroup := shiftedRGBA{rgb: shiftedColor, shift: shift} + colorStats := (*colorMap)[*rgb] + (*weightedColors)[pixelGroup] += colorStats.weight * float64(colorStats.count) +} + +type shiftedRGBA struct { + rgb color.RGBA + shift uint +} + +func rgbMatchesTargetColor(targetCol *shiftedRGBA, rgb *color.RGBA) bool { + if targetCol == nil { + return true + } + + return targetCol.rgb.R == (rgb.R>>targetCol.shift) && + targetCol.rgb.G == (rgb.G>>targetCol.shift) && + targetCol.rgb.B == (rgb.B>>targetCol.shift) +} + +type colorStats struct { + weight float64 + count int64 +} + +func stepLength(bounds image.Rectangle) int { + width := bounds.Dx() + height := bounds.Dy() + pixelCount := width * height + + var stepLength int + if pixelCount > sampleThreshold { + stepLength = 2 + } else { + stepLength = 1 + } + + return stepLength +} + +func weight(rgb *color.RGBA) float64 { + rr := float64(rgb.R) + gg := float64(rgb.G) + bb := float64(rgb.B) + return (abs(rr-gg)*abs(rr-gg)+abs(rr-bb)*abs(rr-bb)+abs(gg-bb)*abs(gg-bb))/65535.0*1000.0 + 1 +} + +func abs(n float64) float64 { + return math.Abs(float64(n)) +} + +func ColorToHex(c color.RGBA) string { + return fmt.Sprintf("%02x%02x%02x", c.R, c.G, c.B) +} diff --git a/colorfinder/colorfinder_test.go b/colorfinder/colorfinder_test.go new file mode 100644 index 00000000..880077ed --- /dev/null +++ b/colorfinder/colorfinder_test.go @@ -0,0 +1,151 @@ +package colorfinder + +import ( + "bytes" + "compress/gzip" + "fmt" + "image" + "io" + "io/ioutil" + "log" + "os" + "reflect" + "strings" + "testing" +) + +func TestSimplePixel(t *testing.T) { + assertFindsRightColor(t, "white1x1.png", "ffffff") + assertFindsRightColor(t, "black1x1.png", "000000") +} + +func TestImageFormats(t *testing.T) { + assertFindsRightColor(t, "white1x1.png", "ffffff") + assertFindsRightColor(t, "white1x1.gif", "ffffff") +} + +func TestFindColors01(t *testing.T) { + assertFindsRightColor(t, "icon01.png.gz", "113671") +} + +func TestFindColors02(t *testing.T) { + assertFindsRightColor(t, "icon02.png.gz", "cb1c1f") +} + +func TestFindColors03(t *testing.T) { + assertFindsRightColor(t, "icon03.png.gz", "f48024") +} + +func TestFindColors04(t *testing.T) { + assertFindsRightColor(t, "icon04.png.gz", "cfdc00") +} + +func TestFindColors05(t *testing.T) { + assertFindsRightColor(t, "icon05.png.gz", "ffa700") +} + +func TestFindColors06(t *testing.T) { + assertFindsRightColor(t, "icon06.png.gz", "ff6600") +} + +func TestFindColors07(t *testing.T) { + assertFindsRightColor(t, "icon07.png.gz", "e61a30") +} + +func BenchmarkFindMainColor152x152(b *testing.B) { + file, _ := os.Open(testdataDir + "icon02.png.gz") + gzReader, _ := gzip.NewReader(file) + byts, _ := ioutil.ReadAll(gzReader) + imgReader := bytes.NewReader(byts) + img, _, err := image.Decode(imgReader) + if err != nil { + log.Fatal(err) + } + + b.ResetTimer() + + cf := ColorFinder{} + for i := 0; i < b.N; i++ { + col, err := cf.FindMainColor(img) + if err != nil { + b.Errorf("Unexpected error: %#v", err) + } + if ColorToHex(col) != "cb1c1f" { + b.Errorf("Wrong color: %s", ColorToHex(col)) + } + + imgReader.Seek(0, 0) + } +} + +func BenchmarkFindMainColor57x57(b *testing.B) { + file, _ := os.Open(testdataDir + "icon07.png.gz") + gzReader, _ := gzip.NewReader(file) + byts, _ := ioutil.ReadAll(gzReader) + imgReader := bytes.NewReader(byts) + img, _, err := image.Decode(imgReader) + if err != nil { + log.Fatal(err) + } + + b.ResetTimer() + + cf := ColorFinder{} + for i := 0; i < b.N; i++ { + col, err := cf.FindMainColor(img) + if err != nil { + b.Errorf("Unexpected error: %#v", err) + } + if ColorToHex(col) != "e61a30" { + b.Errorf("Wrong color: %s", ColorToHex(col)) + } + + imgReader.Seek(0, 0) + } +} + +const testdataDir = "testdata/" + +func assertFindsRightColor(t *testing.T, fileName string, expectedHexColor string) { + var imgReader io.ReadCloser + + path := testdataDir + fileName + imgReader, err := os.Open(path) + check(t, err) + + if strings.HasSuffix(path, ".gz") { + imgReader, err = gzip.NewReader(imgReader) + check(t, err) + } + + defer imgReader.Close() + img, _, err := image.Decode(imgReader) + if err != nil { + log.Fatal(err) + } + + cf := ColorFinder{} + actualColor, err := cf.FindMainColor(img) + check(t, err) + + assertEquals(t, expectedHexColor, ColorToHex(actualColor)) +} + +func check(t *testing.T, err error) { + if err != nil { + fail(t, fmt.Sprintf("Unexpected error: %#v", err)) + } +} + +func assertEquals(t *testing.T, expected, actual interface{}) { + if !reflect.DeepEqual(expected, actual) { + fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+ + " != %#v (actual)", expected, actual)) + } +} + +func fail(t *testing.T, failureMessage string) { + t.Errorf("\t%s\n"+ + "\r\t", + failureMessage) +} diff --git a/colorfinder/testdata/black1x1.png b/colorfinder/testdata/black1x1.png new file mode 100644 index 0000000000000000000000000000000000000000..cb424a3885b788c5862b3dec38edf4e31625a0e3 GIT binary patch literal 1049 zcmZ{j!EVzq7{^`UFv51?f)GeiI44fBR-;xLi8XAiL`T&Yl-`=P?yyMWDE5@>%8eUm zv@^#&1P`!B;Lb}R>?B=7XcHyz_xJy2`}-V!9i5*ZD9;rDz`@|m8;fsCK6?+u`&%~o zB?C4-JqEXTFMf;QadI|e06cjrpBDIj^9+E8KgiVQ{_q`I(8vgu^a2}sln6HfPL4z~ z!aPv(D2y4(ds^W@qAg{psfC4q?rHvTr1oiw)sE3NOwCnPRdv$k3XQ#!3KvmN`^0&I zAk4DN$PNvfUP7ze?LyOrwyg_?&aPt~y|b zt6FE2+)os`-hS}J29M-9hmGXv7#8|8XZwlG^9(iy7mH& zUE8!ex@GESduqK#mWkR&4s3Wf85VRu#Q~@3l+w^0ksODS4AnzJ+$CFg)L@whdY=+3 z3M|X$S`PeAYx?^%N>a?2^mi(MU2FQsn9=Y`4*wx0+_fvDAvdYnrr$kUGj*{E_}hTG zSOernprTT~MP@asLz+&KV1Z@13Zy1A-Nh`k9kbN*igTd+lWTu=d29+* woEujW`?)@YuJSQAeu`tcKk(j6_g*gM^SOu~f!5NV{1GiMczf>M9?!r01u@n)Qvd(} literal 0 HcmV?d00001 diff --git a/colorfinder/testdata/icon01.png.gz b/colorfinder/testdata/icon01.png.gz new file mode 100644 index 0000000000000000000000000000000000000000..57fefebbd72194cf642c26f5db8be396ff276b7d GIT binary patch literal 29267 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 B?&|;m literal 0 HcmV?d00001 diff --git a/colorfinder/testdata/icon03.png.gz b/colorfinder/testdata/icon03.png.gz new file mode 100644 index 0000000000000000000000000000000000000000..ece8e2a6d91e6fe278aab234dc23a6fb2d47f43c GIT binary patch literal 3096 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 literal 0 HcmV?d00001 diff --git a/colorfinder/testdata/icon05.png.gz b/colorfinder/testdata/icon05.png.gz new file mode 100644 index 0000000000000000000000000000000000000000..d73a7800c5eadce988b04b9dd90189ab3cbad356 GIT binary patch literal 1036 zcmV+n1oQhJiwFp_whC4N18HM#ZZI`2aBgP+0qO%4{E1LbM-2)Z3IG5A4M|8uQUCw| zAOHXWAP5Ek0047(dh`GQ1F=a&K~z|UwU$q499100KhNw2#H6M|)TP-_L~5;G zdJ)WO4k}h@z>5ci$-zTuz(p{K2rc5lKQwnsz=Jh3Tkzl|6w`u9v$4`dHX9FBLN+8p zi91OSY2oW(ccwF$$<8!szwnrOZ+`FnzVG|{{oWg>K~j^Xk0s6P;o+8~K}nC|hNKQj ze?COVK}6aCjHD*uCh#l~VObUn3ky!)7(*hFAdyH!T>@YhIF6)GqtYJB=hdCfDi)7B zt-^;#~Mi%OtC6syy{z205NVxeRrDzOzxAfL|% zI!I+QI^Emr3yIxc$!4PvP$+>9`ujsA&gF7}B%y12XN)0}$@pyIjg6kZfVdO-p-NEPG0Nj@u?Ce2SOD{rPIEhb!W3$T3Yhh?Nx!g1WKh+;KGGM!DCl0mwh2= zco646aem&B(=DyLA^?iTqVsNC&*kOi&|LZ@!8m6NM|ytR4R2tP?vx^wmVBNl}@WIncTGu?ePo4!+R$n`LE*L zS}K$AjkP6{DwRt6BVhlG_;y&6yrC8n%d(tX(N-wTc_achi3`KS4v~gfOsPyp{R0EO zl00|*y!rI14}+ILO9#Ah8@B(2@#m{V{<;iz zHugqfbqeOr!B2-^vkV(WXnoORVkF%K8a$(SEV%g@-2MtwyMU7KL(4IE@}(-#cr(5^ z>m^v9gVk%Was{^ksh(UXE<^kP%zX~8{^FkXpOJJ6crI`UYXz8m4>pVUj>DaIr*Vz# z{2h4eEl7U>k9WY@bd^L)huh-1k@OMpWgr0?e~-cZ*RXz#pnF+z`8L2agK+p=Xgywc zSzy3OY6PZ$RG2keWmubn%|%$bT61V1ey|#zgGZtD1%G&gaUFQMwgWva=}MF{;Q`@$ zNl(~-riT>+rPx# U07*qoM6N<$f^$7EnN$G)0D8KXw*UYD literal 0 HcmV?d00001 diff --git a/colorfinder/testdata/icon07.png.gz b/colorfinder/testdata/icon07.png.gz new file mode 100644 index 0000000000000000000000000000000000000000..d93d1d7814997d46803abfb099da458b0cc39411 GIT binary patch literal 3173 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 LVaYj8Lks`_u$A=| literal 0 HcmV?d00001 diff --git a/colorfinder/testdata/white1x1.gif b/colorfinder/testdata/white1x1.gif new file mode 100644 index 0000000000000000000000000000000000000000..18a642d9282f0c7b0e19d4a0006154941ee7b4cc GIT binary patch literal 3221 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 literal 0 HcmV?d00001 diff --git a/colorfinder/testdata/white1x1.png b/colorfinder/testdata/white1x1.png new file mode 100644 index 0000000000000000000000000000000000000000..148c4e6077539d2eb8c953ac98b12bf69578c93e GIT binary patch literal 1049 zcmZ{jL2uJA7>2zeq!HMO3ql}8*_Fgex(aHgL0bb`B|56MNa>BNb-^NuL+mNpl^ZwC z2#Es{$Ndlv`~>d&15O)ulCB}NiJaK4-^cd%CEv&4$Fv~I{YZ)|s1FcS{15F#+wk{kxJCAvg>oMCa7g?_3VKz%i!U>I4xo&Vu&v;kU z%hb*NiS-0oCTh1F*zl|(Ea+Z}15VQkrJ*|{ISwN^R9l9)OSbN)!7>i? zG9_3fSfbT>G=j zvME$iH?AVS=duP}<^A~4H&K>%`rg50=i%(n)zwpQ^K$$0>knO&Gywf)C*H;3>koec Dc*;8Z literal 0 HcmV?d00001 diff --git a/ico/ico.go b/ico/ico.go index 29428fd1..c78b0ffe 100644 --- a/ico/ico.go +++ b/ico/ico.go @@ -3,10 +3,18 @@ package ico import ( + "bytes" "encoding/binary" "errors" + "fmt" "image" "io" + "io/ioutil" + "os" + + //asdf + _ "image/gif" + _ "image/png" ) type icondir struct { @@ -17,14 +25,14 @@ type icondir struct { } type icondirEntry struct { - Width byte - Height byte - Colors byte - Reserved byte - Planes uint16 - Bits uint16 - Bytes uint32 - Offset uint32 + Width byte + Height byte + PaletteCount byte + Reserved byte + ColorPlanes uint16 + BitsPerPixel uint16 + Size uint32 + Offset uint32 } func (dir *icondir) FindBestIcon() *icondirEntry { @@ -82,11 +90,17 @@ func parseIcondirEntry(r io.Reader, e *icondirEntry) error { return nil } +type dibHeader struct { + dibHeaderSize uint32 + width uint32 + height uint32 +} + func (e *icondirEntry) ColorCount() int { - if e.Colors == 0 { + if e.PaletteCount == 0 { return 256 } - return int(e.Colors) + return int(e.PaletteCount) } func (e *icondirEntry) width() int { @@ -118,8 +132,84 @@ func DecodeConfig(r io.Reader) (image.Config, error) { return image.Config{Width: best.width(), Height: best.height()}, nil } +type header struct { + sigBM [2]byte + fileSize uint32 + resverved [2]uint16 + pixOffset uint32 + // dibHeaderSize uint32 + // width uint32 + // height uint32 + // colorPlane uint16 + // bpp uint16 + // compression uint32 + // imageSize uint32 + // xPixelsPerMeter uint32 + // yPixelsPerMeter uint32 + // colorUse uint32 + // colorImportant uint32 +} + +func decodeImage(r io.Reader) (image.Image, error) { + dir, err := ParseIco(r) + if err != nil { + return nil, err + } + + best := dir.FindBestIcon() + if best == nil { + return nil, errors.New("ico file does not contain any icons") + } + + startOffset := best.Offset + endOffset := startOffset + best.Size + fullIcoBytes, err := ioutil.ReadAll(r) + singleIcoBytes := fullIcoBytes[startOffset:(endOffset)] + + h := &header{ + sigBM: [2]byte{'B', 'M'}, + fileSize: 14 + best.Size, + pixOffset: 14, + // dibHeaderSize: 40, + // width: uint32(best.Width), + // height: uint32(best.Height), + // colorPlane: 1, + } + + buf := new(bytes.Buffer) + if err = binary.Write(buf, binary.LittleEndian, h); err != nil { + return nil, err + } + buf.Write(singleIcoBytes) + + // step = (3*d.X + 3) &^ 3 + // h.imageSize = uint32(d.Y * step) + // h.fileSize += h.imageSize + + fmt.Println("len(bytes)", buf.Len()) + + f, err := os.Create("/tmp/pic.bmp") + if err != nil { + return nil, err + } + f.Write(buf.Bytes()) + f.Sync() + defer f.Close() + + // err = ioutil.WriteFile("/tmp/pic.bmp", buf.Bytes(), 0644) + // if err != nil { + // return nil, err + // } + + img, format, err := image.Decode(bytes.NewReader(buf.Bytes())) + fmt.Println("err:", err) + fmt.Println("format:", format) + + return img, err +} + const icoHeader = "\x00\x00\x01\x00" func init() { - image.RegisterFormat("ico", icoHeader, nil, DecodeConfig) + image.RegisterFormat("ico", icoHeader, decodeImage, DecodeConfig) } diff --git a/ico/ico_test.go b/ico/ico_test.go index c5674e39..dfa2624e 100644 --- a/ico/ico_test.go +++ b/ico/ico_test.go @@ -15,9 +15,9 @@ func TestParseICO(t *testing.T) { func TestParseICODetails(t *testing.T) { entries := []icondirEntry{ - icondirEntry{Width: 0x30, Height: 0x30, Colors: 0x10, Reserved: 0x0, Planes: 0x1, Bits: 0x4, Bytes: 0x668, Offset: 0x36}, - icondirEntry{Width: 0x20, Height: 0x20, Colors: 0x10, Reserved: 0x0, Planes: 0x1, Bits: 0x4, Bytes: 0x2e8, Offset: 0x69e}, - icondirEntry{Width: 0x10, Height: 0x10, Colors: 0x10, Reserved: 0x0, Planes: 0x1, Bits: 0x4, Bytes: 0x128, Offset: 0x986}, + icondirEntry{Width: 0x30, Height: 0x30, PaletteCount: 0x10, Reserved: 0x0, ColorPlanes: 0x1, BitsPerPixel: 0x4, Size: 0x668, Offset: 0x36}, + icondirEntry{Width: 0x20, Height: 0x20, PaletteCount: 0x10, Reserved: 0x0, ColorPlanes: 0x1, BitsPerPixel: 0x4, Size: 0x2e8, Offset: 0x69e}, + icondirEntry{Width: 0x10, Height: 0x10, PaletteCount: 0x10, Reserved: 0x0, ColorPlanes: 0x1, BitsPerPixel: 0x4, Size: 0x128, Offset: 0x986}, } assertEquals(t, icondir{Reserved: 0, Type: 1, Count: 3, Entries: entries}, mustParseIcoFile(t, "favicon.ico")) } @@ -27,7 +27,7 @@ func TestFindBestIcon(t *testing.T) { best := dir.FindBestIcon() assertEquals(t, - &icondirEntry{Width: 0x30, Height: 0x30, Colors: 0x10, Reserved: 0x0, Planes: 0x1, Bits: 0x4, Bytes: 0x668, Offset: 0x36}, + &icondirEntry{Width: 0x30, Height: 0x30, PaletteCount: 0x10, Reserved: 0x0, ColorPlanes: 0x1, BitsPerPixel: 0x4, Size: 0x668, Offset: 0x36}, best) } diff --git a/ico/icoparser/icoparser.go b/ico/icoparser/icoparser.go index 3b8f4415..41030566 100644 --- a/ico/icoparser/icoparser.go +++ b/ico/icoparser/icoparser.go @@ -2,8 +2,9 @@ package main import ( "fmt" - "github.com/mat/besticon/ico" "os" + + "github.com/mat/besticon/ico" ) func main() { @@ -27,7 +28,6 @@ func main() { best.Width, best.Height, best.ColorCount()) - // fmt.Printf("%+v\n", dir) } } } diff --git a/lettericon/fonts/LICENSE.txt b/lettericon/fonts/LICENSE.txt new file mode 100644 index 00000000..75b52484 --- /dev/null +++ b/lettericon/fonts/LICENSE.txt @@ -0,0 +1,202 @@ + + 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/lettericon/fonts/open_sans.ttf b/lettericon/fonts/open_sans.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c122ce468be9a36bd2e4970bbfd8efc7b6078ba6 GIT binary patch literal 24140 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 literal 0 HcmV?d00001 diff --git a/lettericon/fonts/open_sans_light.go b/lettericon/fonts/open_sans_light.go new file mode 100644 index 00000000..6c913e24 --- /dev/null +++ b/lettericon/fonts/open_sans_light.go @@ -0,0 +1,22 @@ +package fonts + +import "encoding/base64" + +// The Open Sans font encoded here is subject to the Apache License 2.0 +// https://www.apache.org/licenses/LICENSE-2.0.html + +const openSansLightTTFBase64 = "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AEf/hQAFAEn/wwAFAE//wwAFAFD/wwAFAFH/hQAFAFL/wwAFAFP/hQAFAFT/wwAFAFX/wwAFAFf/wwAFAIH/cQAFAIL/cQAFAIP/cQAFAIT/cQAFAIX/cQAFAIb/cQAFAJoAFAAFAJ3/hQAFAJ7/rgAFAJ//rgAFAKD/rgAFAKH/rgAFAKL/rgAFAKP/rgAFAKT/hQAFAKX/hQAFAKb/hQAFAKf/hQAFAKj/hQAFAK//hQAFALD/hQAFALH/hQAFALL/hQAFALP/hQAFALX/hQAFALb/wwAFALf/wwAFALj/wwAFALn/wwAFAL//hQAKACT/cQAKADYAKQAKADgAKQAKADkAKQAKADsAFAAKAEP/rgAKAEX/hQAKAEb/hQAKAEf/hQAKAEn/wwAKAE//wwAKAFD/wwAKAFH/hQAKAFL/wwAKAFP/hQAKAFT/wwAKAFX/wwAKAFf/wwAKAIH/cQAKAIL/cQAKAIP/cQAKAIT/cQAKAIX/cQAKAIb/cQAKAJoAFAAKAJ3/hQAKAJ7/rgAKAJ//rgAKAKD/rgAKAKH/rgAKAKL/rgAKAKP/rgAKAKT/hQAKAKX/hQAKAKb/hQAKAKf/hQAKAKj/hQAKAK//hQAKALD/hQAKALH/hQAKALL/hQAKALP/hQAKALX/hQAKALb/wwAKALf/wwAKALj/wwAKALn/wwAKAL//hQALACwAuAAPACb/mgAPACr/mgAPADH/mgAPADP/mgAPADb/cQAPADf/1wAPADj/hQAPADn/hQAPADv/hQAPAIj/mgAPAI//mgAPAJD/mgAPAJH/mgAPAJL/mgAPAJP/mgAPAJX/mgAPAJb/1wAPAJf/1wAPAJj/1wAPAJn/1wAPAJr/hQAPAL7/mgAQADb/rgARACb/mgARACr/mgARADH/mgARADP/mgARADb/cQARADf/1wARADj/hQARADn/hQARADv/hQARAIj/mgARAI//mgARAJD/mgARAJH/mgARAJL/mgARAJP/mgARAJX/mgARAJb/1wARAJf/1wARAJj/1wARAJn/1wARAJr/hQARAL7/mgAkAAX/cQAkAAr/cQAkACb/1wAkACr/1wAkACwBCgAkADH/1wAkADP/1wAkADb/cQAkADj/rgAkADn/rgAkADv/hQAkAIj/1wAkAI//1wAkAJD/1wAkAJH/1wAkAJL/1wAkAJP/1wAkAJX/1wAkAJr/hQAkAL7/1wAkAMb/cQAkAMn/cQAlAA//rgAlABH/rgAlACT/1wAlADb/wwAlADj/7AAlADn/7AAlADr/1wAlADv/7AAlADz/7AAlAIH/1wAlAIL/1wAlAIP/1wAlAIT/1wAlAIX/1wAlAIb/1wAlAJr/7AAlAMf/rgAlAMr/rgAmACb/1wAmACr/1wAmADH/1wAmADP/1wAmAIj/1wAmAI//1wAmAJD/1wAmAJH/1wAmAJL/1wAmAJP/1wAmAJX/1wAmAL7/1wAnAA//rgAnABH/rgAnACT/1wAnADb/wwAnADj/7AAnADn/7AAnADr/1wAnADv/7AAnADz/7AAnAIH/1wAnAIL/1wAnAIP/1wAnAIT/1wAnAIX/1wAnAIb/1wAnAJr/7AAnAMf/rgAnAMr/rgAoACwAewApAA//hQApABH/hQApACIAKQApACT/1wApAIH/1wApAIL/1wApAIP/1wApAIT/1wApAIX/1wApAIb/1wApAMf/hQApAMr/hQAtACb/1wAtACr/1wAtADH/1wAtADP/1wAtAIj/1wAtAI//1wAtAJD/1wAtAJH/1wAtAJL/1wAtAJP/1wAtAJX/1wAtAL7/1wAuAAX/XAAuAAr/XAAuACb/1wAuACr/1wAuADH/1wAuADP/1wAuADb/1wAuADf/7AAuADj/1wAuADn/1wAuADv/wwAuAIj/1wAuAI//1wAuAJD/1wAuAJH/1wAuAJL/1wAuAJP/1wAuAJX/1wAuAJb/7AAuAJf/7AAuAJj/7AAuAJn/7AAuAJr/wwAuAL7/1wAuAMb/XAAuAMn/XAAxAA//rgAxABH/rgAxACT/1wAxADb/wwAxADj/7AAxADn/7AAxADr/1wAxADv/7AAxADz/7AAxAIH/1wAxAIL/1wAxAIP/1wAxAIT/1wAxAIX/1wAxAIb/1wAxAJr/7AAxAMf/rgAxAMr/rgAyAA/+9gAyABH+9gAyACT/mgAyADr/1wAyADz/7AAyAIH/mgAyAIL/mgAyAIP/mgAyAIT/mgAyAIX/mgAyAIb/mgAyAMf+9gAyAMr+9gAzAA//rgAzABH/rgAzACT/1wAzADb/wwAzADj/7AAzADn/7AAzADr/1wAzADv/7AAzADz/7AAzAIH/1wAzAIL/1wAzAIP/1wAzAIT/1wAzAIX/1wAzAIb/1wAzAJr/7AAzAMf/rgAzAMr/rgA2AA//hQA2ABD/rgA2ABH/hQA2ACIAKQA2ACT/cQA2ACb/1wA2ACr/1wA2ADH/1wA2ADP/1wA2ADYAKQA2AEP/XAA2AEX/cQA2AEb/cQA2AEf/cQA2AEn/cQA2AE//mgA2AFD/mgA2AFH/cQA2AFL/mgA2AFP/cQA2AFT/mgA2AFX/hQA2AFf/mgA2AFj/1wA2AFn/1wA2AFr/1wA2AFv/1wA2AFz/rgA2AIH/cQA2AIL/cQA2AIP/cQA2AIT/cQA2AIX/cQA2AIb/cQA2AIj/1wA2AI//1wA2AJD/1wA2AJH/1wA2AJL/1wA2AJP/1wA2AJX/1wA2AJ3/cQA2AJ7/XAA2AJ//XAA2AKD/XAA2AKH/XAA2AKL/XAA2AKP/XAA2AKT/cQA2AKX/cQA2AKb/cQA2AKf/cQA2AKj/cQA2AK//cQA2ALD/cQA2ALH/cQA2ALL/cQA2ALP/cQA2ALX/cQA2ALb/mgA2ALf/mgA2ALj/mgA2ALn/mgA2ALr/1wA2AL7/1wA2AL//cQA2AMP/rgA2AMT/rgA2AMf/hQA2AMr/hQA3AA//1wA3ABH/1wA3ACT/7AA3AIH/7AA3AIL/7AA3AIP/7AA3AIT/7AA3AIX/7AA3AIb/7AA3AMf/1wA3AMr/1wA4AA//mgA4ABH/mgA4ACIAKQA4ACT/rgA4ACb/7AA4ACr/7AA4ADH/7AA4ADP/7AA4AEP/1wA4AEX/1wA4AEb/1wA4AEf/1wA4AEn/7AA4AE//7AA4AFD/7AA4AFH/1wA4AFL/7AA4AFP/1wA4AFT/7AA4AFX/7AA4AFf/7AA4AIH/rgA4AIL/rgA4AIP/rgA4AIT/rgA4AIX/rgA4AIb/rgA4AIj/7AA4AI//7AA4AJD/7AA4AJH/7AA4AJL/7AA4AJP/7AA4AJX/7AA4AJ3/1wA4AJ7/1wA4AJ//1wA4AKD/1wA4AKH/1wA4AKL/1wA4AKP/1wA4AKT/1wA4AKX/1wA4AKb/1wA4AKf/1wA4AKj/1wA4AK//1wA4ALD/1wA4ALH/1wA4ALL/1wA4ALP/1wA4ALX/1wA4ALb/7AA4ALf/7AA4ALj/7AA4ALn/7AA4AL7/7AA4AL//1wA4AMf/mgA4AMr/mgA5AA//mgA5ABH/mgA5ACIAKQA5ACT/rgA5ACb/7AA5ACr/7AA5ADH/7AA5ADP/7AA5AEP/1wA5AEX/1wA5AEb/1wA5AEf/1wA5AEn/7AA5AE//7AA5AFD/7AA5AFH/1wA5AFL/7AA5AFP/1wA5AFT/7AA5AFX/7AA5AFf/7AA5AIH/rgA5AIL/rgA5AIP/rgA5AIT/rgA5AIX/rgA5AIb/rgA5AIj/7AA5AI//7AA5AJD/7AA5AJH/7AA5AJL/7AA5AJP/7AA5AJX/7AA5AJ3/1wA5AJ7/1wA5AJ//1wA5AKD/1wA5AKH/1wA5AKL/1wA5AKP/1wA5AKT/1wA5AKX/1wA5AKb/1wA5AKf/1wA5AKj/1wA5AK//1wA5ALD/1wA5ALH/1wA5ALL/1wA5ALP/1wA5ALX/1wA5ALb/7AA5ALf/7AA5ALj/7AA5ALn/7AA5AL7/7AA5AL//1wA5AMf/mgA5AMr/mgA6ACb/1wA6ACr/1wA6ADH/1wA6ADP/1wA6AIj/1wA6AI//1wA6AJD/1wA6AJH/1wA6AJL/1wA6AJP/1wA6AJX/1wA6AL7/1wA7AA//hQA7ABH/hQA7ACIAKQA7ACT/hQA7ACb/1wA7ACr/1wA7ADH/1wA7ADP/1wA7AEP/mgA7AEX/mgA7AEb/mgA7AEf/mgA7AEn/1wA7AE//wwA7AFD/wwA7AFH/mgA7AFL/wwA7AFP/mgA7AFT/wwA7AFX/rgA7AFf/wwA7AFz/1wA7AIH/hQA7AIL/hQA7AIP/hQA7AIT/hQA7AIX/hQA7AIb/hQA7AIj/1wA7AI//1wA7AJD/1wA7AJH/1wA7AJL/1wA7AJP/1wA7AJX/1wA7AJ3/mgA7AJ7/mgA7AJ//mgA7AKD/mgA7AKH/mgA7AKL/mgA7AKP/mgA7AKT/mgA7AKX/mgA7AKb/mgA7AKf/mgA7AKj/mgA7AK//mgA7ALD/mgA7ALH/mgA7ALL/mgA7ALP/mgA7ALX/mgA7ALb/wwA7ALf/wwA7ALj/wwA7ALn/wwA7AL7/1wA7AL//mgA7AMf/hQA7AMr/hQA8ACb/7AA8ACr/7AA8ADH/7AA8ADP/7AA8AIj/7AA8AI//7AA8AJD/7AA8AJH/7AA8AJL/7AA8AJP/7AA8AJX/7AA8AL7/7AA9ACwAuABDAAX/7ABDAAr/7ABDAMb/7ABDAMn/7ABEAAX/7ABEAAr/7ABEAFj/1wBEAFn/1wBEAFr/1wBEAFv/1wBEAFz/7ABEALr/1wBEAMb/7ABEAMn/7ABFAAUAKQBFAAoAKQBFAMYAKQBFAMkAKQBHAAX/7ABHAAr/7ABHAFj/1wBHAFn/1wBHAFr/1wBHAFv/1wBHAFz/7ABHALr/1wBHAMb/7ABHAMn/7ABIAAUAewBIAAoAewBIAMYAewBIAMkAewBKAAX/7ABKAAr/7ABKAMb/7ABKAMn/7ABNAEX/1wBNAEb/1wBNAEf/1wBNAFH/1wBNAFP/1wBNAJ3/1wBNAKT/1wBNAKX/1wBNAKb/1wBNAKf/1wBNAKj/1wBNAK//1wBNALD/1wBNALH/1wBNALL/1wBNALP/1wBNALX/1wBNAL//1wBPAAX/7ABPAAr/7ABPAMb/7ABPAMn/7ABQAAX/7ABQAAr/7ABQAMb/7ABQAMn/7ABRAAX/7ABRAAr/7ABRAFj/1wBRAFn/1wBRAFr/1wBRAFv/1wBRAFz/7ABRALr/1wBRAMb/7ABRAMn/7ABSAAX/7ABSAAr/7ABSAFj/1wBSAFn/1wBSAFr/1wBSAFv/1wBSAFz/7ABSALr/1wBSAMb/7ABSAMn/7ABUAAUAUgBUAAoAUgBUAEP/1wBUAEX/1wBUAEb/1wBUAEf/1wBUAEn/7ABUAFH/1wBUAFP/1wBUAJ3/1wBUAJ7/1wBUAJ//1wBUAKD/1wBUAKH/1wBUAKL/1wBUAKP/1wBUAKT/1wBUAKX/1wBUAKb/1wBUAKf/1wBUAKj/1wBUAK//1wBUALD/1wBUALH/1wBUALL/1wBUALP/1wBUALX/1wBUAL//1wBUAMYAUgBUAMkAUgBWAAUAKQBWAAoAKQBWAMYAKQBWAMkAKQBYAAUAUgBYAAoAUgBYAA//rgBYABH/rgBYACIAKQBYAMYAUgBYAMf/rgBYAMkAUgBYAMr/rgBZAAUAUgBZAAoAUgBZAA//rgBZABH/rgBZACIAKQBZAMYAUgBZAMf/rgBZAMkAUgBZAMr/rgBaAEX/1wBaAEb/1wBaAEf/1wBaAFH/1wBaAFP/1wBaAJ3/1wBaAKT/1wBaAKX/1wBaAKb/1wBaAKf/1wBaAKj/1wBaAK//1wBaALD/1wBaALH/1wBaALL/1wBaALP/1wBaALX/1wBaAL//1wBbAAUAUgBbAAoAUgBbAA//rgBbABH/rgBbACIAKQBbAMYAUgBbAMf/rgBbAMkAUgBbAMr/rgBdACwAuACBAAX/cQCBAAr/cQCBACb/1wCBACr/1wCBACwBCgCBADH/1wCBADP/1wCBADb/cQCBADj/rgCBADn/rgCBADv/hQCBAIj/1wCBAI//1wCBAJD/1wCBAJH/1wCBAJL/1wCBAJP/1wCBAJX/1wCBAJr/hQCBAL7/1wCBAMb/cQCBAMn/cQCCAAX/cQCCAAr/cQCCACb/1wCCACr/1wCCACwBCgCCADH/1wCCADP/1wCCADb/cQCCADj/rgCCADn/rgCCADv/hQCCAIj/1wCCAI//1wCCAJD/1wCCAJH/1wCCAJL/1wCCAJP/1wCCAJX/1wCCAJr/hQCCAL7/1wCCAMb/cQCCAMn/cQCDAAX/cQCDAAr/cQCDACb/1wCDACr/1wCDACwBCgCDADH/1wCDADP/1wCDADb/cQCDADj/rgCDADn/rgCDADv/hQCDAIj/1wCDAI//1wCDAJD/1wCDAJH/1wCDAJL/1wCDAJP/1wCDAJX/1wCDAJr/hQCDAL7/1wCDAMb/cQCDAMn/cQCEAAX/cQCEAAr/cQCEACb/1wCEACr/1wCEACwBCgCEADH/1wCEADP/1wCEADb/cQCEADj/rgCEADn/rgCEADv/hQCEAIj/1wCEAI//1wCEAJD/1wCEAJH/1wCEAJL/1wCEAJP/1wCEAJX/1wCEAJr/hQCEAL7/1wCEAMb/cQCEAMn/cQCFAAX/cQCFAAr/cQCFACb/1wCFACr/1wCFACwBCgCFADH/1wCFADP/1wCFADb/cQCFADj/rgCFADn/rgCFADv/hQCFAIj/1wCFAI//1wCFAJD/1wCFAJH/1wCFAJL/1wCFAJP/1wCFAJX/1wCFAJr/hQCFAL7/1wCFAMb/cQCFAMn/cQCGAAX/cQCGAAr/cQCGACb/1wCGACr/1wCGACwBCgCGADH/1wCGADP/1wCGADb/cQCGADj/rgCGADn/rgCGADv/hQCGAIj/1wCGAI//1wCGAJD/1wCGAJH/1wCGAJL/1wCGAJP/1wCGAJX/1wCGAJr/hQCGAL7/1wCGAMb/cQCGAMn/cQCHACwAewCIACb/1wCIACr/1wCIADH/1wCIADP/1wCIAIj/1wCIAI//1wCIAJD/1wCIAJH/1wCIAJL/1wCIAJP/1wCIAJX/1wCIAL7/1wCJACwAewCKACwAewCLACwAewCMACwAewCNAA//rgCNABH/rgCNACT/1wCNADb/wwCNADj/7ACNADn/7ACNADr/1wCNADv/7ACNADz/7ACNAIH/1wCNAIL/1wCNAIP/1wCNAIT/1wCNAIX/1wCNAIb/1wCNAJr/7ACNAMf/rgCNAMr/rgCPAA//rgCPABH/rgCPACT/1wCPADb/wwCPADj/7ACPADn/7ACPADr/1wCPADv/7ACPADz/7ACPAIH/1wCPAIL/1wCPAIP/1wCPAIT/1wCPAIX/1wCPAIb/1wCPAJr/7ACPAMf/rgCPAMr/rgCQAA//rgCQABH/rgCQACT/1wCQADb/wwCQADj/7ACQADn/7ACQADr/1wCQADv/7ACQADz/7ACQAIH/1wCQAIL/1wCQAIP/1wCQAIT/1wCQAIX/1wCQAIb/1wCQAJr/7ACQAMf/rgCQAMr/rgCRAA//rgCRABH/rgCRACT/1wCRADb/wwCRADj/7ACRADn/7ACRADr/1wCRADv/7ACRADz/7ACRAIH/1wCRAIL/1wCRAIP/1wCRAIT/1wCRAIX/1wCRAIb/1wCRAJr/7ACRAMf/rgCRAMr/rgCSAA//rgCSABH/rgCSACT/1wCSADb/wwCSADj/7ACSADn/7ACSADr/1wCSADv/7ACSADz/7ACSAIH/1wCSAIL/1wCSAIP/1wCSAIT/1wCSAIX/1wCSAIb/1wCSAJr/7ACSAMf/rgCSAMr/rgCTAA//rgCTABH/rgCTACT/1wCTADb/wwCTADj/7ACTADn/7ACTADr/1wCTADv/7ACTADz/7ACTAIH/1wCTAIL/1wCTAIP/1wCTAIT/1wCTAIX/1wCTAIb/1wCTAJr/7ACTAMf/rgCTAMr/rgCVAA//rgCVABH/rgCVACT/1wCVADb/wwCVADj/7ACVADn/7ACVADr/1wCVADv/7ACVADz/7ACVAIH/1wCVAIL/1wCVAIP/1wCVAIT/1wCVAIX/1wCVAIb/1wCVAJr/7ACVAMf/rgCVAMr/rgCWAA//1wCWABH/1wCWACT/7ACWAIH/7ACWAIL/7ACWAIP/7ACWAIT/7ACWAIX/7ACWAIb/7ACWAMf/1wCWAMr/1wCXAA//1wCXABH/1wCXACT/7ACXAIH/7ACXAIL/7ACXAIP/7ACXAIT/7ACXAIX/7ACXAIb/7ACXAMf/1wCXAMr/1wCYAA//1wCYABH/1wCYACT/7ACYAIH/7ACYAIL/7ACYAIP/7ACYAIT/7ACYAIX/7ACYAIb/7ACYAMf/1wCYAMr/1wCZAA//1wCZABH/1wCZACT/7ACZAIH/7ACZAIL/7ACZAIP/7ACZAIT/7ACZAIX/7ACZAIb/7ACZAMf/1wCZAMr/1wCaAA//hQCaABH/hQCaACIAKQCaACT/hQCaACb/1wCaACr/1wCaADH/1wCaADP/1wCaAEP/mgCaAEX/mgCaAEb/mgCaAEf/mgCaAEn/1wCaAE//wwCaAFD/wwCaAFH/mgCaAFL/wwCaAFP/mgCaAFT/wwCaAFX/rgCaAFf/wwCaAFz/1wCaAIH/hQCaAIL/hQCaAIP/hQCaAIT/hQCaAIX/hQCaAIb/hQCaAIj/1wCaAI//1wCaAJD/1wCaAJH/1wCaAJL/1wCaAJP/1wCaAJX/1wCaAJ3/mgCaAJ7/mgCaAJ//mgCaAKD/mgCaAKH/mgCaAKL/mgCaAKP/mgCaAKT/mgCaAKX/mgCaAKb/mgCaAKf/mgCaAKj/mgCaAK//mgCaALD/mgCaALH/mgCaALL/mgCaALP/mgCaALX/mgCaALb/wwCaALf/wwCaALj/wwCaALn/wwCaAL7/1wCaAL//mgCaAMf/hQCaAMr/hQCbAA/+9gCbABH+9gCbACT/mgCbADr/1wCbADz/7ACbAIH/mgCbAIL/mgCbAIP/mgCbAIT/mgCbAIX/mgCbAIb/mgCbAMf+9gCbAMr+9gCdAAX/7ACdAAr/7ACdAMb/7ACdAMn/7ACeAAX/7ACeAAr/7ACeAMb/7ACeAMn/7ACfAAX/7ACfAAr/7ACfAMb/7ACfAMn/7ACgAAX/7ACgAAr/7ACgAMb/7ACgAMn/7AChAAX/7AChAAr/7AChAMb/7AChAMn/7ACiAAX/7ACiAAr/7ACiAMb/7ACiAMn/7AClAAX/7AClAAr/7AClAFj/1wClAFn/1wClAFr/1wClAFv/1wClAFz/7AClALr/1wClAMb/7AClAMn/7ACmAAX/7ACmAAr/7ACmAFj/1wCmAFn/1wCmAFr/1wCmAFv/1wCmAFz/7ACmALr/1wCmAMb/7ACmAMn/7ACnAAX/7ACnAAr/7ACnAFj/1wCnAFn/1wCnAFr/1wCnAFv/1wCnAFz/7ACnALr/1wCnAMb/7ACnAMn/7ACo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" + +var openSansLight []byte + +func OpenSansLightBytes() []byte { + if len(openSansLight) == 0 { + var err error + openSansLight, err = base64.StdEncoding.DecodeString(openSansLightTTFBase64) + if err != nil { + panic(err) + } + } + + return openSansLight +} diff --git a/lettericon/fonts/open_sans_light.ttf b/lettericon/fonts/open_sans_light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0012a525f71ca92cc8072f40e650248f3defc242 GIT binary patch literal 24120 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 literal 0 HcmV?d00001 diff --git a/lettericon/lettericon.go b/lettericon/lettericon.go new file mode 100644 index 00000000..59e33a9d --- /dev/null +++ b/lettericon/lettericon.go @@ -0,0 +1,277 @@ +package lettericon + +import ( + "bufio" + "errors" + "fmt" + "image" + "image/color" + "image/draw" + "image/png" + "io" + "log" + "math" + "net/url" + "path" + "strconv" + "strings" + + "golang.org/x/image/font" + "golang.org/x/image/math/fixed" + "golang.org/x/net/publicsuffix" + + "github.com/golang/freetype/truetype" + "github.com/mat/besticon/colorfinder" + "github.com/mat/besticon/lettericon/fonts" +) + +const dpi = 72 + +const fontSizeFactor = 0.6180340 // (by taste) +const yOffsetFactor = 102.0 / 1024.0 // (by trial and error) :-) + +func Render(letter string, bgColor color.Color, width int, out io.Writer) error { + fg := pickForegroundColor(bgColor) + + rgba := image.NewRGBA(image.Rect(0, 0, width, width)) + draw.Draw(rgba, rgba.Bounds(), &image.Uniform{bgColor}, image.ZP, draw.Src) + + fontSize := fontSizeFactor * float64(width) + d := &font.Drawer{ + Dst: rgba, + Src: &image.Uniform{fg}, + Face: truetype.NewFace(fnt, &truetype.Options{ + Size: fontSize, + DPI: dpi, + Hinting: font.HintingNone, + }), + } + + y := int(yOffsetFactor*float64(width)) + int(math.Ceil(fontSize*dpi/72)) + d.Dot = fixed.Point26_6{ + X: (fixed.I(width) - d.MeasureString(letter)) / 2, + Y: fixed.I(y), + } + d.DrawString(letter) + + b := bufio.NewWriter(out) + encoder := png.Encoder{CompressionLevel: png.DefaultCompression} + err := encoder.Encode(b, rgba) + if err != nil { + return err + } + err = b.Flush() + if err != nil { + return err + } + return nil +} + +func pickForegroundColor(bgColor color.Color) color.Color { + cWhite := contrastRatio(pickLighterColor(color.White, bgColor)) + + // We prefer white text, this ratio was deemed good enough + if cWhite > 1.5 { + return color.White + } + return lightDark +} + +func pickLighterColor(c1, c2 color.Color) (color.Color, color.Color) { + _, _, v1 := RGBToHSV(c1) + _, _, v2 := RGBToHSV(c2) + + if v1 >= v2 { + return c1, c2 + } + return c2, c1 +} + +// https://code.google.com/p/gorilla/source/browse/color/hsv.go?r=ef489f63418265a7249b1d53bdc358b09a4a2ea0 +func RGBToHSV(c color.Color) (h, s, v float64) { + r, g, b, _ := c.RGBA() + fR := float64(r) / 255 + fG := float64(g) / 255 + fB := float64(b) / 255 + max := math.Max(math.Max(fR, fG), fB) + min := math.Min(math.Min(fR, fG), fB) + d := max - min + s, v = 0, max + if max > 0 { + s = d / max + } + if max == min { + // Achromatic. + h = 0 + } else { + // Chromatic. + switch max { + case fR: + h = (fG - fB) / d + if fG < fB { + h += 6 + } + case fG: + h = (fB-fR)/d + 2 + case fB: + h = (fR-fG)/d + 4 + } + h /= 6 + } + return +} + +func contrastRatio(c1 color.Color, c2 color.Color) float64 { + // http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef + + l1 := relativeLuminance(c1) + l2 := relativeLuminance(c2) + + return (l1 + 0.05) / (l2 + 0.05) +} + +func relativeLuminance(c color.Color) float64 { + r, g, b, _ := c.RGBA() + r64 := foo(r) + g64 := foo(g) + b64 := foo(b) + + return 0.2126*r64 + 0.7152*g64 + 0.0722*b64 +} + +const shiftRGB = uint8(8) + +func foo(col uint32) float64 { + c := float64(uint8(col >> shiftRGB)) + c /= 255.0 + + if c < 0.03928 { + return c / 12.92 + } + + return math.Pow(((c + 0.055) / 1.055), 2.4) +} + +var ( + errMalformedColorString = errors.New("Malformed hex color string") +) + +func ColorFromHex(hex string) (*color.RGBA, error) { + if len(hex) != 6 && len(hex) != 7 { + return nil, errMalformedColorString + } + hex = strings.TrimPrefix(hex, "#") + + r, err := strconv.ParseInt(hex[0:2], 16, 16) + if err != nil { + return nil, errMalformedColorString + } + g, err := strconv.ParseInt(hex[2:4], 16, 16) + if err != nil { + return nil, errMalformedColorString + } + b, err := strconv.ParseInt(hex[4:6], 16, 16) + if err != nil { + return nil, errMalformedColorString + } + + col := color.RGBA{uint8(r), uint8(g), uint8(b), 0xff} + return &col, nil +} + +func IconPath(letter string, size string, colr *color.RGBA) string { + if letter == "" { + letter = " " + } else { + letter = strings.ToUpper(letter) + } + + if colr != nil { + return fmt.Sprintf("/lettericons/%s-%s-%s.png", letter, size, colorfinder.ColorToHex(*colr)) + } + return fmt.Sprintf("/lettericons/%s-%s.png", letter, size) +} + +const defaultIconSize = 144 +const maxIconSize = 1024 + +// path is like: lettericons/M-144-EFC25D.png +func ParseIconPath(fullpath string) (string, *color.RGBA, int) { + _, filename := path.Split(fullpath) + filename = strings.TrimSuffix(filename, ".png") + params := strings.SplitN(filename, "-", 3) + + charParam := "" + if len(params) >= 1 { + charParam = string(params[0][0]) + } + sizeParam := "" + if len(params) >= 2 { + sizeParam = params[1] + } + colorParam := "" + if len(params) >= 3 { + colorParam = params[2] + } + + size, err := strconv.Atoi(sizeParam) + if err != nil || size < 0 { + size = defaultIconSize + } + if size > maxIconSize { + size = maxIconSize + } + + col, _ := ColorFromHex(colorParam) + if col == nil { + col = DefaultBackgroundColor + } + + return charParam, col, size +} + +func MainLetterFromURL(URL string) string { + URL = strings.TrimSpace(URL) + if !strings.HasPrefix(URL, "http") { + URL = "http://" + URL + } + + url, err := url.Parse(URL) + if err != nil { + return "" + } + + host := url.Host + hostSuffix, _ := publicsuffix.PublicSuffix(host) + if hostSuffix != "" { + host = strings.TrimSuffix(host, hostSuffix) + host = strings.TrimSuffix(host, ".") + } + + hostParts := strings.Split(host, ".") + domain := hostParts[len(hostParts)-1] + if len(domain) > 0 { + return string(domain[0]) + } else if len(hostSuffix) > 0 { + return string(hostSuffix[0]) + } + + return "" +} + +var fnt *truetype.Font + +var DefaultBackgroundColor *color.RGBA +var lightDark *color.RGBA + +func init() { + var err error + fnt, err = truetype.Parse(fonts.OpenSansLightBytes()) + if err != nil { + log.Println(err) + return + } + + DefaultBackgroundColor, _ = ColorFromHex("#909090") + lightDark, _ = ColorFromHex("#505050") +} diff --git a/lettericon/lettericon/cmd.go b/lettericon/lettericon/cmd.go new file mode 100644 index 00000000..b8cb53e6 --- /dev/null +++ b/lettericon/lettericon/cmd.go @@ -0,0 +1,39 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + + "github.com/mat/besticon/lettericon" +) + +var ( + letter = flag.String("letter", "X", "letter to draw") + width = flag.Int("width", 144, "width/height of the icon") + iconColor = flag.String("color", "#909090", "icon color, as hex string") +) + +func main() { + flag.Parse() + + f, err := os.Create("out.png") + if err != nil { + log.Println(err) + os.Exit(1) + } + defer f.Close() + + col, err := lettericon.ColorFromHex(*iconColor) + if err != nil { + log.Println(err) + os.Exit(1) + } + + err = lettericon.Render(*letter, col, *width, f) + if err != nil { + os.Exit(1) + } + fmt.Println("Wrote out.png OK.") +} diff --git a/lettericon/lettericon_test.go b/lettericon/lettericon_test.go new file mode 100644 index 00000000..015198b6 --- /dev/null +++ b/lettericon/lettericon_test.go @@ -0,0 +1,153 @@ +package lettericon + +import ( + "bytes" + "fmt" + "image/color" + "io/ioutil" + "reflect" + "testing" +) + +func TestColorFromHex(t *testing.T) { + assertColor(t, "#000000", &color.RGBA{0, 0, 0, 0xff}) + assertColor(t, "#ffffff", &color.RGBA{255, 255, 255, 0xff}) + assertColor(t, "#dfdfdf", &color.RGBA{223, 223, 223, 0xff}) +} + +func TestRender(t *testing.T) { + assertCorrectImageData(t, "A", 16, "123456") + assertCorrectImageData(t, "X", 32, "dfdfdf") +} + +func TestPickForegroundColor(t *testing.T) { + orange := color.RGBA{255, 152, 0, 255} + assertEquals(t, color.White, pickForegroundColor(orange)) + + white := color.RGBA{254, 255, 252, 255} + assertEquals(t, lightDark, pickForegroundColor(white)) +} + +func TestContrastRatio(t *testing.T) { + white := &color.RGBA{255, 255, 255, 0} + blue := &color.RGBA{0, 0, 255, 0} + + assertFloatEquals(t, 1.0, contrastRatio(white, white)) + assertFloatEquals(t, 1.0, contrastRatio(blue, blue)) + assertFloatEquals(t, 8.6, contrastRatio(white, blue)) +} + +func TestRelativeLuminance(t *testing.T) { + white := &color.RGBA{255, 255, 255, 0} + blue := &color.RGBA{0, 0, 255, 0} + + assertFloatEquals(t, 1.0, relativeLuminance(white)) + assertFloatEquals(t, 0.07, relativeLuminance(blue)) +} + +const testdataDir = "testdata/" + +func assertCorrectImageData(t *testing.T, letter string, width int, hexColor string) { + imageData, err := renderBytes(letter, mustColorFromHex(hexColor), width) + if err != nil { + fail(t, fmt.Sprintf("could not generate icon: %s", err)) + return + } + + // "A-144-123456.png" + file := fmt.Sprintf(testdataDir+"%s-%d-%s.png", letter, width, hexColor) + fileData, err := bytesFromFile(file) + if err != nil { + fail(t, fmt.Sprintf("could not load icon file: %s", err)) + return + } + + assertEquals(t, len(fileData), len(imageData)) + assertEquals(t, fileData, imageData) +} + +func mustColorFromHex(hexColor string) color.Color { + col, err := ColorFromHex(hexColor) + if err != nil { + panic(err) + } + return col +} + +func BenchmarkColorFromHex(b *testing.B) { + for i := 0; i < b.N; i++ { + ColorFromHex("#dfdfdf") + } +} + +func bytesFromFile(file string) ([]byte, error) { + dat, err := ioutil.ReadFile(file) + if err != nil { + return nil, err + } + return dat, nil +} + +func renderBytes(letter string, bgColor color.Color, width int) ([]byte, error) { + var b bytes.Buffer + + err := Render(letter, bgColor, width, &b) + if err != nil { + return nil, err + } + return b.Bytes(), nil +} + +func BenchmarkRender(b *testing.B) { + Render("X", DefaultBackgroundColor, 144, ioutil.Discard) // warmup + b.ResetTimer() + + for i := 0; i < b.N; i++ { + Render("X", DefaultBackgroundColor, 144, ioutil.Discard) + } +} + +func TestMainLetterFromURL(t *testing.T) { + assertEquals(t, "b", MainLetterFromURL("http://better-idea.org")) + assertEquals(t, "b", MainLetterFromURL("http://www.better-idea.org")) + assertEquals(t, "b", MainLetterFromURL("better-idea.org")) + assertEquals(t, "b", MainLetterFromURL("www.better-idea.org")) + + assertEquals(t, "s", MainLetterFromURL("some-user.blogspot.com")) + assertEquals(t, "b", MainLetterFromURL("blogspot.com")) +} + +func TestIconPath(t *testing.T) { + assertEquals(t, "/lettericons/A-120-000000.png", IconPath("a", "120", &color.RGBA{0, 0, 0, 0})) + assertEquals(t, "/lettericons/Z-100-640ac8.png", IconPath("z", "100", &color.RGBA{100, 10, 200, 0})) +} + +func assertColor(t *testing.T, hexColor string, expectedColor color.Color) { + actualColor, err := ColorFromHex(hexColor) + if err != nil { + fail(t, fmt.Sprintf("'%s' does not into a color", hexColor)) + return + } + + assertEquals(t, expectedColor, actualColor) +} +func assertEquals(t *testing.T, expected, actual interface{}) { + if !reflect.DeepEqual(expected, actual) { + fail(t, fmt.Sprintf("Not equal: %v (expected)\n"+ + " != %v (actual)", expected, actual)) + } +} + +func assertFloatEquals(t *testing.T, expected, actual float64) { + delta := expected - actual + if delta > 0.01 { + fail(t, fmt.Sprintf("Not equal: %v (expected)\n"+ + " != %v (actual)", expected, actual)) + } +} + +func fail(t *testing.T, failureMessage string) { + t.Errorf("\t%s\n"+ + "\r\t", + failureMessage) +} diff --git a/lettericon/testdata/A-16-123456.png b/lettericon/testdata/A-16-123456.png new file mode 100644 index 0000000000000000000000000000000000000000..ed905c05c80a1eda62da6e777e91ca30c1ba0852 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|OFdm2Ln`JZ2^w)GE3g_&Tr#Ul zYR1f&4IM1Jg7>~HoVP7vX~c%EQ{J6_|9`uqO=|M%*C zxZLoRD^s)Pn|pWD|0(;sSrgSi78I_~@i=u2C>jca+|)j1L+w+y@`MkV-pXYs36y+t)c+ItY0Vn{!1aKTD48vzVNfO((F#vd;-)^_h zIz>^p+YJL?I2^jJD+t1)2xq5hda+nw01yPR*=)||v+w&K;^A0mHuwOVjjBuU}~ zfO9UF%X+;|Q1~{EgqtU2VtEFkVT%OP8yWI{CKomvGvc}`_qX<)0tyUR^ z`6(a>0ysYWSXdaJKCM=(`~CjqLd`H}-;00n;1qxY@aKT{00030|94f9XHKFNGXMYp M07*qoM6N<$f-AYhg8%>k literal 0 HcmV?d00001